diff --git a/callput/SKILL.md b/callput/SKILL.md new file mode 100644 index 00000000..711b7239 --- /dev/null +++ b/callput/SKILL.md @@ -0,0 +1,47 @@ +--- +name: callput-lite-trader +description: Spread-only on-chain options trading skill for Base. MCP builds unsigned transactions; agent signs via Bankr /agent/sign and broadcasts via /agent/submit. +version: 1.0.0 +homepage: https://callput.app +license: MIT +mcp: + required: + - name: callput-lite-agent-mcp + setup: See references/SETUP.md +--- + +# Callput Lite Trader + +Trade Callput spreads on Base. MCP builds unsigned_tx; Bankr signs and broadcasts. + +## Integration Pattern (Bankr) + +1. callput_execute_spread -> unsigned_tx + usdc_approval +2. If usdc_approval.sufficient == false -> sign + broadcast approve_tx first +3. POST /agent/sign(unsigned_tx) -> signed_tx +4. POST /agent/submit(signed_tx) -> tx_hash +5. callput_get_request_key_from_tx(tx_hash) -> request_key +6. Persist request_key -> poll callput_check_request_status + +## Hard Rules + +1. Spread-only. No single-leg execution. +2. Always callput_portfolio_summary before new position. +3. MCP never holds CALLPUT_PRIVATE_KEY. +4. Save every request_key from get_request_key_from_tx. +5. High IV (>80% ETH, >70% BTC) favors sell spreads. + +## Tool Reference + +| Tool | Purpose | +|---|---| +| callput_scan_spreads | Market scan — ranked candidates + ATM IV | +| callput_execute_spread | Build unsigned open tx + USDC check | +| callput_get_request_key_from_tx | Parse request_key from receipt | +| callput_check_request_status | Poll keeper | +| callput_portfolio_summary | Balance + positions + P&L | +| callput_close_position | Build unsigned close tx | +| callput_settle_position | Build unsigned settle tx | +| callput_list_positions_by_wallet | Recover request_keys | +| callput_get_settled_pnl | Realized payout history | +| callput_get_option_chains | Raw chain data + IV | diff --git a/callput/references/SETUP.md b/callput/references/SETUP.md new file mode 100644 index 00000000..fd464bf1 --- /dev/null +++ b/callput/references/SETUP.md @@ -0,0 +1,414 @@ +# Callput MCP Server Setup Guide + +## 1. Overview + +This guide covers the complete setup of the Callput MCP (Model Context Protocol) server, which enables AI agents to scan, validate, and execute options spreads on the Base network. + +The Callput MCP server supports two target environments: + +- **Local Development & OpenClaw** — Direct configuration with a private key for testing, development, and standalone agent deployments +- **Bankr Integration** — Delegated signing where Bankr agent handles signing and broadcasting (no private key needed in MCP) + +This guide walks you through prerequisites, installation, configuration, and verification for both environments. + +--- + +## 2. Prerequisites + +### System Requirements + +You must have the following tools installed on your system: + +**Node.js 18 or higher** + +Check your version: +```bash +node --version +``` + +Expected output: `v18.0.0` or higher (e.g., `v20.11.0`, `v22.3.0`) + +**npm 8 or higher** + +Check your version: +```bash +npm --version +``` + +Expected output: `8.0.0` or higher (e.g., `9.6.0`, `10.2.0`) + +### Network Requirements + +**Base Mainnet RPC Endpoint** + +The MCP server requires a Base Mainnet RPC endpoint to query options chains and simulate spreads. You have two options: + +1. **Free Public RPC** (suitable for development and dry-runs) + ``` + https://mainnet.base.org + ``` + +2. **Paid RPC Providers** (recommended for production) + - **Alchemy**: https://base-mainnet.g.alchemy.com/v2/{YOUR_API_KEY} + - **Infura**: https://base-mainnet.infura.io/v3/{YOUR_PROJECT_ID} + +### API Keys & Credentials + +**Private Key (Optional for Standalone, NOT needed for Bankr)** + +If you plan to run the server in **standalone mode with live trading**, you need an Ethereum private key for the Base network. + +- A private key for a Base Mainnet wallet (must have ETH for gas and collateral for spreads) +- The key must start with `0x` and be 66 characters (32 bytes in hex) +- **Never commit private keys to version control** +- If using **Bankr**, you do NOT need a private key—signing is delegated to Bankr's API + +**Example private key format:** +``` +0xabcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 +``` + +--- + +## 3. Step 1: Clone & Install + +Clone the Callput MCP repository and install dependencies: + +```bash +git clone https://github.com/ayggdrasil/callput-option-agent.git +cd callput-option-agent +npm install +``` + +**Expected output:** + +``` +npm notice created a lockfile as package-lock.json +added 87 packages from 26 contributors in 8.234s + +up to date, audited 87 packages in 1.234s +0 vulnerabilities found +``` + +After installation completes, verify that `node_modules` was created: + +```bash +ls -la node_modules/@modelcontextprotocol/sdk +``` + +--- + +## 4. Step 2: Build + +Compile TypeScript into JavaScript: + +```bash +npm run build +``` + +**Expected output:** + +``` +tsc +``` + +The build script runs the TypeScript compiler with no visible output (which is good—it means no errors). To verify the build succeeded, check for the compiled output: + +```bash +ls build/index.js +``` + +**Expected output:** + +``` +build/index.js +``` + +If the file exists, the build was successful. You can also verify all MCP tools were compiled: + +```bash +ls -la build/ +``` + +This should show compiled `.js` files for the main entry point and any smoke test utilities. + +--- + +## 5. Step 3: MCP Configuration — Two Paths + +The Callput MCP server can be configured in two ways depending on your deployment environment. + +### Path A: Standalone or OpenClaw (with Private Key) + +Use this configuration if you are running the MCP server directly with a private key for signing transactions. The MCP server receives tool calls from the agent and returns unsigned transactions. The agent (or agent runtime) is responsible for signing and broadcasting. + +#### Configuration Block + +Add this to your MCP config file: + +```json +{ + "mcpServers": { + "callput": { + "command": "node", + "args": ["/absolute/path/to/callput-option-agent/build/index.js"], + "env": { + "CALLPUT_RPC_URL": "https://mainnet.base.org", + "CALLPUT_PRIVATE_KEY": "0x..." + } + } + } +} +``` + +#### Config File Locations + +Choose the appropriate location for your environment: + +**Claude Desktop (macOS):** +``` +~/Library/Application Support/Claude/claude_desktop_config.json +``` + +**Claude Desktop (Windows):** +``` +%APPDATA%\Claude\claude_desktop_config.json +``` + +**OpenClaw:** +``` +~/.openclaw/mcp_config.json +``` + +**Generic/Custom:** +Any JSON file that your MCP client reads at startup. + +#### Configuration Notes + +- Replace `/absolute/path/to/callput-option-agent/build/index.js` with the actual absolute path to your cloned repository +- Use absolute paths (not relative paths like `./build/index.js`) to ensure the MCP server can be found regardless of the current working directory +- `CALLPUT_PRIVATE_KEY` is **optional** for dry-run mode (scanning spreads without executing), but **required** for live trading (executing spreads) +- `CALLPUT_RPC_URL` defaults to `https://mainnet.base.org` if not specified, but you can override it with a paid RPC provider for better reliability + +#### Example with Alchemy (Production) + +```json +{ + "mcpServers": { + "callput": { + "command": "node", + "args": ["/Users/alice/projects/callput-option-agent/build/index.js"], + "env": { + "CALLPUT_RPC_URL": "https://base-mainnet.g.alchemy.com/v2/your-alchemy-api-key", + "CALLPUT_PRIVATE_KEY": "0xabcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" + } + } + } +} +``` + +--- + +### Path B: Bankr Integration (NO Private Key) + +Use this configuration if your agent is running under Bankr. The MCP server operates in read-only mode (scan, query, build unsigned transactions). Bankr's agent runtime receives unsigned transactions from the MCP server and handles signing via its secure internal API, then broadcasts. + +#### Configuration Block + +Add this to your MCP config file: + +```json +{ + "mcpServers": { + "callput": { + "command": "node", + "args": ["/absolute/path/to/callput-option-agent/build/index.js"], + "env": { + "CALLPUT_RPC_URL": "https://mainnet.base.org" + } + } + } +} +``` + +#### Key Differences + +- **No `CALLPUT_PRIVATE_KEY`** — Bankr agent retains the private key securely; MCP server never sees it +- **Passive MCP server** — Returns unsigned transactions; Bankr agent calls its own `/agent/sign` API to sign and `/agent/submit` to broadcast +- MCP server role: scan spreads, validate strikes, build unsigned transactions, query portfolio state, poll execution status +- Full live trading supported without exposing a private key to the MCP process + +#### Security Architecture + +The correct flow is: +1. Bankr agent calls MCP tools (e.g., `callput_execute_spread`) +2. MCP returns `unsigned_tx` with fields `{to, data, value, chain_id}` +3. Bankr agent internally calls `/agent/sign` with the unsigned transaction +4. Bankr agent calls `/agent/submit` with the signed transaction +5. Bankr agent calls `callput_get_request_key_from_tx(tx_hash)` to retrieve the request key for P&L tracking + +In this model, the MCP server never calls Bankr—it is purely a passive tool that responds to requests. + +--- + +## 6. Step 4: Verify Installation + +After configuration, test that the MCP server is working correctly by making two sample MCP tool calls. + +### Test 1: Scan Spreads (Dry-Run) + +Scan for profitable ETH bullish call spreads without executing: + +```json +{ + "name": "callput_scan_spreads", + "arguments": { + "underlying": "ETH", + "position_type": "bullish", + "max_results": 5, + "dry_run": true + } +} +``` + +**Expected response:** + +```json +{ + "status": "success", + "spreads": [ + { + "name": "ETH Bullish Call Spread", + "short_strike": 3000, + "long_strike": 3100, + "expiry": 1712102400, + "credit": 250, + "max_profit": 750, + "max_loss": 250 + } + ], + "chain_available": true, + "rpc_status": "connected" +} +``` + +### Test 2: Portfolio Summary + +Query the portfolio summary for a test address (does not require signing): + +```json +{ + "name": "callput_portfolio_summary", + "arguments": { + "wallet_address": "0x1234567890123456789012345678901234567890" + } +} +``` + +**Expected response:** + +```json +{ + "status": "success", + "total_spreads": 2, + "total_collateral_locked": "2.5", + "total_premium_collected": "0.8", + "open_positions": [ + { + "id": "spread_001", + "underlying": "ETH", + "position_type": "bullish", + "status": "open" + } + ] +} +``` + +If both calls succeed, your installation is correct. + +--- + +## 7. Environment Variables + +The MCP server reads the following environment variables: + +| Variable | Required | Default | Purpose | +|----------|----------|---------|---------| +| `CALLPUT_RPC_URL` | No | `https://mainnet.base.org` | Base Mainnet RPC endpoint for queries and simulations | +| `CALLPUT_PRIVATE_KEY` | For Path A (standalone) live mode only | (none) | 32-byte Ethereum private key (0x prefix); omit for Path B (Bankr) | + +--- + +## 8. Verification Checklist + +Before using the MCP server in production, verify all of the following: + +- [ ] Node.js version is 18 or higher (`node --version`) +- [ ] npm version is 8 or higher (`npm --version`) +- [ ] Repository cloned to disk and `npm install` completed without errors +- [ ] `npm run build` succeeded and `build/index.js` exists +- [ ] MCP configuration file is in place with correct absolute path to `build/index.js` +- [ ] (Path A: Standalone/OpenClaw) `CALLPUT_PRIVATE_KEY` is set and valid, OR (Path B: Bankr) config omits `CALLPUT_PRIVATE_KEY` entirely +- [ ] `callput_scan_spreads` MCP call returns results (query mode works) +- [ ] `callput_portfolio_summary` MCP call returns results (RPC connectivity verified) + +--- + +## 9. Troubleshooting + +| Issue | Cause | Fix | +|-------|-------|-----| +| `command not found: node` | Node.js not installed or not in PATH | Install Node.js 18+ from https://nodejs.org; verify with `node --version` | +| `build/index.js` does not exist | Build failed or TypeScript compilation error | Run `npm run build` and check for error messages; verify TypeScript config exists | +| `ENOENT: no such file or directory` in MCP logs | Absolute path in config is incorrect | Verify the path to `build/index.js` exists; use `pwd` in repo root and copy full path into config | +| RPC call times out | RPC endpoint is unreachable or rate-limited | Try the free public RPC `https://mainnet.base.org`; or use a paid provider (Alchemy, Infura) with higher rate limits | +| `CALLPUT_PRIVATE_KEY invalid` (Path A only) | Private key format is incorrect or missing `0x` prefix | Ensure key is 66 characters and starts with `0x`; never use partial keys | +| `execute_spread` returns unsigned_tx, but Bankr agent cannot sign | MCP worked correctly; check Bankr `/agent/sign` endpoint | Verify Bankr agent runtime is operational and `/agent/sign` API is reachable; MCP is passive and cannot call Bankr | + +--- + +## 10. Next Steps + +### For OpenClaw Deployments + +Refer to the OpenClaw integration guide for agent-specific setup and testing: + +``` +../OPENCLAW_GUIDE.md +``` + +### For Bankr Integrations + +Refer to the Bankr integration guide for secure signing and execution: + +``` +../BANKR_GUIDE.md +``` + +### For Local Testing + +Start with dry-run mode to test MCP connectivity without risking funds: + +```bash +npm run verify:mcp +``` + +This runs a smoke test that verifies RPC connectivity and all MCP tools. + +### For Live Trading + +Once verified, you can execute spreads by: + +1. Setting a valid `CALLPUT_PRIVATE_KEY` and removing `dry_run: true` +2. Or setting `BANKR_MODE=true` and letting Bankr handle signing +3. Calling `callput_execute_spread` with your selected spread parameters + +--- + +## Support + +For issues, questions, or feature requests, open an issue on GitHub: + +https://github.com/ayggdrasil/callput-option-agent/issues + +For security concerns or private key handling questions, see the [Security](#security) section of the main README. diff --git a/callput/references/TOOL_REFERENCE.md b/callput/references/TOOL_REFERENCE.md new file mode 100644 index 00000000..25f8678f --- /dev/null +++ b/callput/references/TOOL_REFERENCE.md @@ -0,0 +1,534 @@ +# Callput Lite MCP Tool Reference + +Complete reference for all 10 Callput trading tools. Each tool serves a specific role in the spread trading workflow: scanning markets, executing trades, tracking P&L, and managing positions. + +--- + +## 1. callput_scan_spreads + +**Purpose** — Scan the options market and return pre-ranked spread candidates ready for execution, filtered by underlying asset and directional bias. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| underlying_asset | string | Yes | `"ETH"` | Asset symbol (ETH, BTC, etc.) | +| bias | enum | Yes | `"bullish"` | Options: bullish, bearish, neutral-bearish, neutral-bullish | +| max_results | number | No | `3` | Return top N results (1–5, default auto) | + +**Strategy Mapping** +- `bullish` → BuyCallSpread (pay debit, profit if spot rises) +- `bearish` → BuyPutSpread (pay debit, profit if spot falls) +- `neutral-bearish` → SellCallSpread (collect premium) +- `neutral-bullish` → SellPutSpread (collect premium) + +**Example Input** +```json +{ + "underlying_asset": "ETH", + "bias": "bullish", + "max_results": 3 +} +``` + +**Example Output** +```json +{ + "underlying_asset": "ETH", + "atm_iv": 0.65, + "spreads": [ + { + "rank": 1, + "spread_id": "spread_0x123abc", + "strategy": "BuyCallSpread", + "long_leg_id": "opt_long_0x456def", + "short_leg_id": "opt_short_0x789ghi", + "long_strike": 2100, + "short_strike": 2200, + "expiry_date": "2026-04-30", + "days_to_expiry": 38, + "width": 100, + "entry_debit_usd": 45.50, + "max_profit_usd": 54.50, + "win_probability": 0.62, + "long_iv": 0.64, + "short_iv": 0.62 + } + ] +} +``` + +**Key Output Fields** +- `atm_iv` — At-the-money implied volatility; high IV favors sell spreads (more premium) +- `long_leg_id`, `short_leg_id` — Pass directly to `execute_spread` +- `entry_debit_usd` — Net cost (buy spreads); negative = credit received (sell spreads) +- `max_profit_usd` — Maximum risk/reward for the spread +- `days_to_expiry` — Time to expiration; <1 day signals close opportunity +- `rank` — Quality ranking by Callput engine + +**When to Use** — Call this first to discover available spread opportunities. Use ATM IV to decide: high IV (>0.6) favors selling spreads for premium collection; low IV favors buying cheap spreads. Pass the returned `long_leg_id` and `short_leg_id` directly to `callput_execute_spread`. + +--- + +## 2. callput_execute_spread + +**Purpose** — Build an unsigned transaction to open a new spread position on-chain. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| strategy | enum | Yes | `"BuyCallSpread"` | BuyCallSpread, SellCallSpread, BuyPutSpread, SellPutSpread | +| from_address | string | Yes | `"0x742d..."` | Your wallet address (checksummed) | +| long_leg_id | string | Yes | `"opt_long_0x456def"` | From scan_spreads result | +| short_leg_id | string | Yes | `"opt_short_0x789ghi"` | From scan_spreads result | +| size | number | Yes | `10` | Position size (contracts or units) | +| min_fill_ratio | number | No | `0.95` | Acceptable slippage (0.01–1.0, default 0.9) | + +**Example Input** +```json +{ + "strategy": "BuyCallSpread", + "from_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "long_leg_id": "opt_long_0x456def", + "short_leg_id": "opt_short_0x789ghi", + "size": 10, + "min_fill_ratio": 0.95 +} +``` + +**Example Output** +```json +{ + "unsigned_tx": { + "to": "0xCallputRouterAddress", + "data": "0xa1b2c3d4...", + "value": "0", + "chain_id": 8453 + }, + "usdc_approval": { + "sufficient": false, + "approve_tx": { + "to": "0xUSDCTokenAddress", + "data": "0xapprovedata...", + "value": "0", + "chain_id": 8453 + }, + "needed_amount_usd": 455.50 + }, + "request_key_preview": "req_0x999..." +} +``` + +**Key Output Fields** +- `unsigned_tx` — Sign and broadcast this to open the position; contains encoded spread parameters +- `usdc_approval.sufficient` — If false, must sign and broadcast `approve_tx` first (ERC-20 approve) +- `approve_tx` — USDC approval transaction; send before `unsigned_tx` if `sufficient=false` +- `needed_amount_usd` — Total USDC required (entry debit or initial credit margin) + +**When to Use** — After selecting a spread from `scan_spreads`. The function returns an unsigned transaction; you must sign it and broadcast to Base. If `usdc_approval.sufficient=false`, first send the USDC approval, then send the main spread transaction. After broadcasting the spread tx, extract the `request_key` using `callput_get_request_key_from_tx`. + +--- + +## 3. callput_get_request_key_from_tx + +**Purpose** — Extract and return the request_key from a spread or close transaction receipt; critical for P&L tracking. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| tx_hash | string | Yes | `"0x123abc..."` | Transaction hash from broadcasted tx | + +**Example Input** +```json +{ + "tx_hash": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f" +} +``` + +**Example Output** +```json +{ + "request_key": "req_0x999aaabbbcccdddeeefff", + "is_open": true +} +``` + +**Key Output Fields** +- `request_key` — Unique identifier for this position; **save immediately** for P&L tracking +- `is_open` — true for open requests, false for close/settle requests; required for `check_request_status` + +**When to Use** — Call immediately after broadcasting `execute_spread` or `close_position` transactions. **Critical**: Losing the request_key means losing P&L tracking for that position. Store it in your session state or database right away. Pass both `request_key` and `is_open` to `callput_check_request_status` to poll execution status. + +--- + +## 4. callput_check_request_status + +**Purpose** — Poll the keeper's execution status for a pending spread or close request. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| request_key | string | Yes | `"req_0x999..."` | From `get_request_key_from_tx` | +| is_open | boolean | Yes | `true` | true for open requests, false for close/settle | + +**Example Input** +```json +{ + "request_key": "req_0x999aaabbbcccdddeeefff", + "is_open": true +} +``` + +**Example Output** +```json +{ + "request_key": "req_0x999aaabbbcccdddeeefff", + "status": "executed", + "is_open": true, + "execution_details": { + "filled_size": 10, + "filled_price_usd": 45.50, + "timestamp": 1711270800 + } +} +``` + +**Key Output Fields** +- `status` — One of: `pending`, `executed`, `cancelled` +- `filled_size` — Actual size filled at execution +- `filled_price_usd` — Actual entry price (execution_details present only when status=executed) + +**Polling Guide** — Poll every 30 seconds, max 6 attempts (3 minutes). After 3 minutes with no update, assume the request failed or was cancelled. When status changes to `executed` or `cancelled`, stop polling and proceed with portfolio updates or error handling. + +**When to Use** — After extracting a request_key, poll this endpoint to wait for the keeper to execute the on-chain transaction. Once status reaches `executed`, the position is live; you can then call `portfolio_summary` with the request_key to see current mark value and P&L. + +--- + +## 5. callput_portfolio_summary + +**Purpose** — Get current USDC balance, active positions with mark-to-market values, and optional P&L when request_keys are provided. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| address | string | Yes | `"0x742d..."` | Your wallet address | +| request_keys | array[string] | No | `["req_0x999...", "req_0xaaa..."]` | Saved request_keys for cost-basis & P&L; optional | + +**Example Input** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "request_keys": ["req_0x999aaabbbcccdddeeefff"] +} +``` + +**Example Output** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "usdc_balance": 5000.00, + "positions": [ + { + "option_token_id": "opt_0xabc123", + "underlying_asset": "ETH", + "side": "long", + "option_type": "Call", + "strike": 2100, + "expiry_date": "2026-04-30", + "size": 10, + "days_to_expiry": 38, + "current_mark_usd": 52.00, + "entry_cost_usd": 45.50, + "unrealized_pnl_usd": 65.00, + "unrealized_pnl_pct": 14.3, + "close_pnl_est_pct": 14.3 + } + ], + "urgent_count": 0 +} +``` + +**Key Output Fields** +- `usdc_balance` — Available USDC in your wallet +- `current_mark_usd` — Current mid-price for the option (Greeks-based or market mid) +- `unrealized_pnl_usd`, `unrealized_pnl_pct` — Only present if request_keys provided (enables cost-basis lookup) +- `close_pnl_est_pct` — Estimated P&L if closed now; >50% signals strong close opportunity +- `urgent_count` — Number of positions expiring within 24h; >0 = manage expiries first +- `days_to_expiry` — Time remaining; <1 day means close/settle soon + +**When to Use** — Call frequently (every 5–10 min) to monitor positions. Without `request_keys`, you get balance + positions only. Pass saved `request_keys` to unlock cost-basis and P&L fields. If `urgent_count > 0`, prioritize closing or settling expiring positions with `callput_close_position` or `callput_settle_position`. + +--- + +## 6. callput_close_position + +**Purpose** — Build an unsigned transaction to close an open position before expiration. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| underlying_asset | string | Yes | `"ETH"` | Asset of the position | +| from_address | string | Yes | `"0x742d..."` | Your wallet address | +| option_token_id | string | Yes | `"opt_0xabc123"` | Token ID from portfolio_summary | +| size | number | Yes | `10` | Size to close (≤ current position size) | + +**Example Input** +```json +{ + "underlying_asset": "ETH", + "from_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "option_token_id": "opt_0xabc123", + "size": 10 +} +``` + +**Example Output** +```json +{ + "unsigned_tx": { + "to": "0xCallputRouterAddress", + "data": "0xe5f3d2c1...", + "value": "0", + "chain_id": 8453 + }, + "realized_pnl_estimate_usd": 65.00, + "request_key_preview": "req_close_0x555..." +} +``` + +**Key Output Fields** +- `unsigned_tx` — Sign and broadcast to close the position +- `realized_pnl_estimate_usd` — Estimated profit/loss at current mark + +**When to Use** — Close a position when: (1) `days_to_expiry < 1` (avoid expiration risk), or (2) `close_pnl_est_pct > 50%` (take profit). Sign and broadcast the tx, then call `get_request_key_from_tx` with the close tx hash to get the close request_key (pass `is_open=false` to `check_request_status`). + +--- + +## 7. callput_settle_position + +**Purpose** — Build an unsigned transaction to settle an expired position and collect the payout. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| underlying_asset | string | Yes | `"ETH"` | Asset of the position | +| option_token_id | string | Yes | `"opt_0xabc123"` | Token ID from portfolio_summary | + +**Example Input** +```json +{ + "underlying_asset": "ETH", + "option_token_id": "opt_0xabc123" +} +``` + +**Example Output** +```json +{ + "unsigned_tx": { + "to": "0xCallputSettlerAddress", + "data": "0xf2e1d3c4...", + "value": "0", + "chain_id": 8453 + }, + "payout_estimate_usd": 100.00, + "request_key_preview": "req_settle_0x666..." +} +``` + +**Key Output Fields** +- `unsigned_tx` — Sign and broadcast to settle the position +- `payout_estimate_usd` — Estimated USDC received at settlement (intrinsic value) + +**When to Use** — Only for expired positions (`days_to_expiry ≤ 0`). Once expiry is reached, the position must be settled to collect the final payout. Sign and broadcast the tx, then track with `get_request_key_from_tx` (is_open=false). + +--- + +## 8. callput_list_positions_by_wallet + +**Purpose** — Recover all request_keys from on-chain GenerateRequestKey events; essential for session recovery and P&L restoration. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| address | string | Yes | `"0x742d..."` | Your wallet address | +| from_block | number | No | `100000` | Start block for event lookup; default ~50k blocks back (~1 day on Base) | + +**Example Input** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "from_block": 15000000 +} +``` + +**Example Output** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "open_request_keys": [ + "req_0x999aaabbbcccdddeeefff", + "req_0xaaa111bbb222ccc333ddd" + ], + "close_request_keys": [ + "req_close_0x555eeeffggg666" + ], + "total_open": 2, + "total_closed": 1 +} +``` + +**Key Output Fields** +- `open_request_keys` — Request keys for open positions; pass to `portfolio_summary` for P&L +- `close_request_keys` — Request keys for closed positions; can verify with `check_request_status(is_open=false)` +- `total_open`, `total_closed` — Counts of open and closed positions + +**When to Use** — Use after session loss or restart to restore all request_keys. Lower `from_block` to search further back in history (useful for older positions). Pass the returned `open_request_keys` to `portfolio_summary` to restore full P&L tracking. + +--- + +## 9. callput_get_settled_pnl + +**Purpose** — Query SettlePosition events to retrieve realized P&L from settled positions. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| address | string | Yes | `"0x742d..."` | Your wallet address | +| from_block | number | No | `100000` | Start block for event lookup; default ~50k blocks back (~1 day on Base) | + +**Example Input** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "from_block": 15000000 +} +``` + +**Example Output** +```json +{ + "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f9bEb", + "settled_positions": [ + { + "option_token_id": "opt_0xabc123", + "underlying_asset": "ETH", + "option_type": "Call", + "strike": 2100, + "expiry_date": "2026-03-28", + "amount_out_usd": 100.00, + "settlement_timestamp": 1711270800 + } + ] +} +``` + +**Key Output Fields** +- `amount_out_usd` — Gross USDC received at settlement (intrinsic value) +- `option_token_id`, `underlying_asset`, `option_type`, `strike` — Position details +- `settlement_timestamp` — When the position settled + +**Realized P&L Calculation** — Realized P&L = `amount_out_usd` - `entry_cost_usd` (from portfolio_summary). For a sold spread, subtract the credit received. Track over time to monitor total realized gains/losses. + +**When to Use** — Call after settling positions to verify payouts and compute realized P&L. Combine with `portfolio_summary` entry_cost to calculate net profit/loss per settled position. Lower `from_block` to look further back in settlement history. + +--- + +## 10. callput_get_option_chains + +**Purpose** — Fetch raw tradable options from the Callput market feed; use only when you need detailed chain data or IV inspection. + +**Input Parameters** + +| Param | Type | Required | Example | Notes | +|-------|------|----------|---------|-------| +| underlying_asset | string | Yes | `"ETH"` | Asset symbol | +| option_type | enum | No | `"Call"` | Call or Put; if omitted, returns both | +| expiry_date | string | No | `"2026-04-30"` | Specific expiry (YYYY-MM-DD); if omitted, returns all | +| max_expiries | number | No | `3` | Limit expiries returned (1–5) | +| max_strikes | number | No | `10` | Limit strikes per expiry (2–30) | + +**Example Input** +```json +{ + "underlying_asset": "ETH", + "option_type": "Call", + "expiry_date": "2026-04-30", + "max_strikes": 10 +} +``` + +**Example Output** +```json +{ + "underlying_asset": "ETH", + "spot_price_usd": 2050.00, + "chains": [ + { + "expiry_date": "2026-04-30", + "days_to_expiry": 38, + "options": [ + { + "option_id": "opt_0x123abc", + "option_type": "Call", + "strike": 2000, + "bid_usd": 68.50, + "ask_usd": 70.00, + "mark_usd": 69.25, + "iv": 0.62, + "delta": 0.68, + "gamma": 0.0015, + "vega": 0.45, + "theta": -0.12 + } + ] + } + ] +} +``` + +**Key Output Fields** +- `spot_price_usd` — Current underlying asset price +- `iv` — Implied volatility; high IV (>0.6) favors selling, low IV favors buying +- `delta`, `gamma`, `vega`, `theta` — Greeks for Greeks-based analysis +- `bid_usd`, `ask_usd`, `mark_usd` — Pricing; bid-ask spread indicates liquidity + +**When to Use** — Prefer `callput_scan_spreads` for normal trading (it returns pre-ranked spreads). Use `get_option_chains` only when you need raw IV data, delta, gamma analysis, or want to manually construct spreads outside the scan recommendations. + +--- + +## Workflow Summary + +1. **Discover** → `callput_scan_spreads` (by bias and asset) +2. **Execute** → `callput_execute_spread` (sign + broadcast tx) +3. **Track** → `callput_get_request_key_from_tx` (extract request_key) +4. **Poll** → `callput_check_request_status` (wait for execution) +5. **Monitor** → `callput_portfolio_summary` (view P&L, mark values) +6. **Close** → `callput_close_position` (before expiry or at +50% P&L) +7. **Settle** → `callput_settle_position` (after expiry) +8. **Recover** → `callput_list_positions_by_wallet` (after session loss) +9. **Verify** → `callput_get_settled_pnl` (confirm realized P&L) +10. **Debug** → `callput_get_option_chains` (raw chain data) + +--- + +## Error Handling & Recovery + +- **Lost request_key?** → Call `callput_list_positions_by_wallet` to recover all keys, then pass them to `portfolio_summary`. +- **Approval failed?** → If `usdc_approval.sufficient=false`, send the `approve_tx` first, then retry `execute_spread`. +- **Position not closed after 3 min?** → Stop polling; check transaction status on-chain (may have failed), retry manually. +- **Expired position stranded?** → Call `settle_position` to collect final payout. + +--- + +**Version**: 0.2.0 +**Network**: Base (Chain ID 8453) +**Last Updated**: March 2026