Skill: romovow/poseidon-otc (version 1.0.0)

--- name: poseidon-otc description: Execute trustless P2P token swaps on Solana via the Poseidon OTC protocol. Create trade rooms, negotiate offers, lock tokens with time-based escrow, and execute atomic on-chain swaps. Supports agent-to-agent trading with real-time WebSocket updates. metadata: { "openclaw": { "emoji": "🔱", "requires": { "env": ["POSEIDON_BURNER_KEY"] }, "primaryEnv": "POSEIDON_BURNER_KEY", "homepage": "https://poseidon.cash" } } --- # Poseidon OTC Skill **TL;DR for Agents:** This skill lets you trade tokens with humans or other agents on Solana. You create a room, both parties deposit tokens to escrow, confirm, and execute an atomic swap. No trust required - it's all on-chain. ## When to Use This Skill - **Trading tokens P2P** - Swap any SPL token directly with another party - **Agent-to-agent commerce** - Two AI agents can negotiate and execute trades autonomously - **Large OTC deals** - Avoid slippage from DEX trades by going direct - **Protected trades** - Use lockups to prevent counterparty from dumping immediately - **Multi-token swaps** - Trade up to 4 tokens per side in one atomic transaction ## Quick Start for Agents ### 1. Initialize (requires wallet) ```typescript import { PoseidonOTC } from 'poseidon-otc-skill'; const client = new PoseidonOTC({ burnerKey: process.env.POSEIDON_BURNER_KEY // base58 private key }); ``` ### 2. Create a Trade Room ```typescript const { roomId, link } = await client.createRoom(); // Share `link` with counterparty or another agent ``` ### 3. Wait for Counterparty & Set Offer ```typescript // Check room status const room = await client.getRoom(roomId); // Set what you're offering (100 USDC example) await client.updateOffer(roomId, [{ mint: [REDACTED_SECRET], // USDC mint amount: 100000000, // 100 USDC (6 decimals) decimals: 6 }]); ``` ### 4. Confirm & Execute ```typescript // First confirmation = "I agree to these terms" await client.confirmTrade(roomId, 'first'); // After deposits, second confirmation await client.confirmTrade(roomId, 'second'); // Execute the atomic swap const { txSignature } = await client.executeSwap(roomId); ``` ## Complete Trade Flow ``` ┌─────────────────────────────────────────────────────────────────┐ │ TRADE LIFECYCLE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. CREATE ROOM │ │ └─> Party A calls createRoom() │ │ Returns: roomId, shareable link │ │ │ │ 2. JOIN ROOM │ │ └─> Party B calls joinRoom(roomId) │ │ Room now has both participants │ │ │ │ 3. SET OFFERS │ │ └─> Both parties call updateOffer(roomId, tokens) │ │ Each specifies what they're putting up │ │ │ │ 4. FIRST CONFIRM (agree on terms) │ │ └─> Both call confirmTrade(roomId, 'first') │ │ "I agree to swap my X for your Y" │ │ │ │ 5. DEPOSIT TO ESCROW │ │ └─> Tokens move to on-chain escrow │ │ (Handled by frontend or depositToEscrow) │ │ │ │ 6. SECOND CONFIRM (verify deposits) │ │ └─> Both call confirmTrade(roomId, 'second') │ │ "I see the deposits, ready to swap" │ │ │ │ 7. EXECUTE SWAP │ │ └─> Either party calls executeSwap(roomId) │ │ Atomic on-chain swap via relayer │ │ Returns: txSignature │ │ │ │ [OPTIONAL] LOCKUP FLOW │ │ └─> Before step 4, Party A can proposeLockup(roomId, secs) │ │ └─> Party B must acceptLockup(roomId) to continue │ │ └─> After execute, locked tokens claimed via claimLockedTokens │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ## API Reference ### Room Management | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `createRoom(options?)` | `{ inviteCode?: string }` | `{ roomId, link }` | Create new room | | `getRoom(roomId)` | `roomId: string` | `TradeRoom` | Get full room state | | `getUserRooms(wallet?)` | `wallet?: string` | `TradeRoom[]` | List your rooms | | `joinRoom(roomId, inviteCode?)` | `roomId, inviteCode?` | `{ success }` | Join as Party B | | `cancelRoom(roomId)` | `roomId: string` | `{ success }` | Cancel & refund | | `getRoomLink(roomId)` | `roomId: string` | `string` | Get share URL | ### Trading | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `updateOffer(roomId, tokens)` | `roomId, [{mint, amount, decimals}]` | `{ success }` | Set your offer | | `withdrawFromOffer(roomId, tokens)` | `roomId, tokens[]` | `{ success }` | Pull back tokens | | `confirmTrade(roomId, stage)` | `roomId, 'first'│'second'` | `{ success }` | Confirm stage | | `executeSwap(roomId)` | `roomId: string` | `{ txSignature }` | Execute swap | | `declineOffer(roomId)` | `roomId: string` | `{ success }` | Reject terms | ### Lockups (Anti-Dump) | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `proposeLockup(roomId, seconds)` | `roomId, seconds` | `{ success }` | Propose lock | | `acceptLockup(roomId)` | `roomId: string` | `{ success }` | Accept lock | | `getLockupStatus(roomId)` | `roomId: string` | `{ canClaim, timeRemaining }` | Check timer | | `claimLockedTokens(roomId)` | `roomId: string` | `{ txSignature }` | Claim after expiry | ### Utility | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `getBalance()` | none | `{ sol: number }` | Check SOL balance | | `isAutonomous()` | none | `boolean` | Has signing wallet? | | `getWebSocketUrl()` | none | `string` | Get WS endpoint | ## WebSocket Real-Time Updates **Don't poll. Subscribe.** Instead of repeatedly calling `getRoom()`, connect to WebSocket for instant updates: **Endpoint:** `wss://poseidon.cash/ws/trade-room` ### Subscribe to Room Events ```typescript const { unsubscribe } = await client.subscribeToRoom(roomId, (event) => { switch (event.type) { case 'join': console.log('Counterparty joined!'); break; case 'offer': console.log('Offer updated:', event.data.tokens); break; case 'confirm': console.log('Confirmation received'); break; case 'execute': console.log('Swap complete! TX:', event.data.txSignature); break; case 'cancel': console.log('Trade cancelled'); break; } }); ``` ### Event Types | Event | When It Fires | |-------|--------------| | `full-state` | Immediately on subscribe - complete room state | | `join` | Counterparty joined the room | | `offer` | Someone updated their offer | | `confirm` | Someone confirmed (first or second) | | `lockup` | Lockup proposed or accepted | | `execute` | Swap executed successfully | | `cancel` | Room was cancelled | | `terminated` | Room expired or terminated | | `error` | Something went wrong | ### WebSocket Actions (Faster than HTTP) ```typescript await client.sendOfferViaWs(roomId, tokens); // Update offer await client.sendConfirmViaWs(roomId, 'first'); // Confirm await client.sendLockupProposalViaWs(roomId, 3600); // Propose 1hr lock await client.sendAcceptLockupViaWs(roomId); // Accept lock await client.sendExecuteViaWs(roomId); // Execute swap ``` ## Agent-to-Agent Trading Example **Scenario:** Agent A wants to sell 1000 USDC for 5 SOL to Agent B ### Agent A (Seller): ```typescript // 1. Create room const { roomId } = await client.createRoom(); // 2. Set offer (1000 USDC) await client.updateOffer(roomId, [{ mint: [REDACTED_SECRET], amount: 1000000000, // 1000 USDC decimals: 6 }]); // 3. Share roomId with Agent B via your inter-agent protocol // 4. Subscribe to updates await client.subscribeToRoom(roomId, async (event) => { if (event.type === 'offer') { // Check if Agent B's offer is acceptable (5 SOL) const room = await client.getRoom(roomId); if (room.partyBTokenSlots?.[0]?.amount >= 5 * 1e9) { await client.confirmTrade(roomId, 'first'); } } if (event.type === 'confirm' && room.partyBFirstConfirm) { await client.confirmTrade(roomId, 'second'); } }); ``` ### Agent B (Buyer): ```typescript // 1. Join the room await client.joinRoom(roomId); // 2. Set offer (5 SOL) await client.updateOffer(roomId, [{ mint: [REDACTED_SECRET], // wSOL amount: 5000000000, // 5 SOL decimals: 9 }]); // 3. Subscribe and react await client.subscribeToRoom(roomId, async (event) => { if (event.type === 'confirm') { const room = await client.getRoom(roomId); if (room.partyAFirstConfirm && !room.partyBFirstConfirm) { await client.confirmTrade(roomId, 'first'); } if (room.partyASecondConfirm && room.partyBSecondConfirm) { // Both confirmed, execute! await client.executeSwap(roomId); } } }); ``` ## Common Token Mints | Token | Mint Address | Decimals | |-------|--------------|----------| | USDC | [REDACTED_SECRET] | 6 | | USDT | [REDACTED_SECRET] | 6 | | wSOL | [REDACTED_SECRET] | 9 | | BONK | [REDACTED_SECRET] | 5 | ## Environment Variables ```bash POSEIDON_BURNER_KEY=<base58-private-key> # Required for autonomous mode POSEIDON_API_URL=https://poseidon.cash # API endpoint (default: mainnet) POSEIDON_RPC_URL=https://api.mainnet-beta.solana.com # Solana RPC ``` ## Security Notes - **Escrow is on-chain** - Funds are held by the Solana program, not the API - **Atomic swaps** - Either both sides complete or neither does - **Signatures expire** - Auth signatures valid for 24 hours - **Lockups are enforced on-chain** - Can't bypass the timer - **Hot wallet warning** - Only fund your burner wallet with amounts you're comfortable risking ## Program ID **Mainnet:** [REDACTED_SECRET] ## Links - Website: https://poseidon.cash - Docs: https://docs.poseidon.cash


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector:  ()