Skip to content

feat: add polymarket trading#118

Open
0xbbjoker wants to merge 17 commits intomasterfrom
feature/polymarket-phase2
Open

feat: add polymarket trading#118
0xbbjoker wants to merge 17 commits intomasterfrom
feature/polymarket-phase2

Conversation

@0xbbjoker
Copy link
Contributor

@0xbbjoker 0xbbjoker commented Jan 4, 2026

Note

Adds full Polymarket trading and upgrades market discovery for accuracy and usability.

  • New @elizaos/plugin-polymarket-trading with CDP wallet integration and actions: POLYMARKET_SETUP_TRADING, POLYMARKET_BUY_SHARES, POLYMARKET_SELL_SHARES, POLYMARKET_PLACE_LIMIT_ORDER, POLYMARKET_GET_OPEN_ORDERS, POLYMARKET_CANCEL_ORDER, POLYMARKET_GET_MY_POSITIONS, POLYMARKET_REDEEM, POLYMARKET_APPROVE_USDC; integrated into src/index.ts
  • Add deps: @polymarket/clob-client, ethers@5 for CLOB signing
  • Discovery improvements:
    • Use /events/pagination and filter non-expired/active markets; exclude markets with failed price fetches
    • Real-time prices via CLOB /price; support non-Yes/No outcomes with outcome names/token IDs
    • GET_POLYMARKET_DETAIL accepts market_slug/market_id/condition_id; includes outcome tokens/prices
    • GET_POLYMARKET_EVENTS adds query and slug; GET_POLYMARKET_EVENT_DETAIL surfaces yes_token_id/no_token_id
    • GET_POLYMARKET_LIVE_VOLUME paginates and reports top markets and totals
  • Minor: switch SQL plugin import to @elizaos/plugin-sql/node

Written by Cursor Bugbot for commit d7229fd. This will update automatically on new commits. Configure here.

Greptile Summary

This PR introduces comprehensive end-to-end Polymarket trading capabilities through a new @elizaos/plugin-polymarket-trading plugin with CDP wallet integration.

Key Additions:

Trading Plugin (plugin-polymarket-trading):

  • Complete trading infrastructure using @polymarket/clob-client for order execution
  • CDP wallet integration via custom CdpSignerAdapter bridging ethers v5 Signer interface
  • 9 trading actions: setup, buy/sell shares, limit orders, order management, positions, redemption, USDC approval
  • Dual approval system: USDC (ERC20) for buying + CTF tokens (ERC1155) for selling
  • Comprehensive validation, balance checks, and error handling with detailed user feedback
  • Dynamic context matching for intelligent action activation

Discovery Plugin Enhancements:

  • Switched to /events/pagination endpoint with non-expired market filtering (prevents showing expired markets)
  • Added support for market lookup by slug/ID/condition_id (not just condition_id)
  • Integrated CLOB /price endpoint for real-time pricing (replaces orderbook asks)
  • Enhanced token data with outcome names and token IDs for all market types
  • Added query and slug filters for events
  • Improved volume calculations with pagination support

Architecture Highlights:

  • Clean separation: discovery plugin for browsing, trading plugin for execution
  • Service-based design with user state caching and LRU eviction
  • Type-safe interfaces throughout with comprehensive TypeScript definitions
  • Proper error propagation and user-friendly error messages

Dependencies:

  • Added @polymarket/clob-client (^5.1.3) for CLOB API integration
  • Added ethers@5.7.2 for compatibility with clob-client

The implementation demonstrates solid software engineering practices with extensive documentation, proper abstraction layers, and thorough validation.

Confidence Score: 4/5

  • This PR is safe to merge with minor considerations around trading safety mechanisms and error handling edge cases
  • Score reflects well-architected trading functionality with comprehensive validation and safety checks, but includes financial operations requiring careful testing. The code quality is high with proper error handling, but real-money trading introduces inherent risk that warrants thorough QA.
  • Pay close attention to src/plugins/plugin-polymarket-trading/src/services/trading.service.ts for approval logic and order execution paths

Important Files Changed

Filename Overview
src/plugins/plugin-polymarket-trading/src/services/trading.service.ts Core trading service with CDP wallet integration, order execution via CLOB client, approval management, and position tracking - comprehensive implementation
src/plugins/plugin-polymarket-trading/src/adapters/cdp-signer-adapter.ts Clean adapter bridging CDP accounts to ethers v5 Signer interface for CLOB client compatibility - well-documented EIP-712 signature translation
src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts Buy shares action with comprehensive parameter validation, balance checks, and market order execution - extensive error handling and user guidance
src/plugins/plugin-polymarket-trading/src/actions/sellShares.action.ts Sell shares action fetching positions from data API and executing sales - clean implementation with proper error handling
src/plugins/plugin-polymarket-trading/src/utils/approvalHelpers.ts Approval utilities for USDC (ERC20) and CTF tokens (ERC1155) covering all Polymarket exchange contracts - complete approval flow for buying and selling
src/plugins/plugin-polymarket-discovery/src/services/polymarket.service.ts Enhanced discovery service with improved market filtering (non-expired markets), slug/ID/condition_id support, CLOB price endpoint integration, and richer token data

Sequence Diagram

sequenceDiagram
    participant User
    participant Agent
    participant TradingService
    participant CDPClient
    participant CdpSignerAdapter
    participant ClobClient
    participant PolymarketCLOB
    participant PolygonRPC
    participant DiscoveryService

    Note over User,DiscoveryService: Setup Trading (One-time)
    User->>Agent: POLYMARKET_SETUP_TRADING
    Agent->>TradingService: setupTrading(userId)
    TradingService->>CDPClient: getOrCreateAccount(userId)
    CDPClient-->>TradingService: cdpAccount
    TradingService->>CdpSignerAdapter: new CdpSignerAdapter(cdpAccount)
    TradingService->>ClobClient: createOrDeriveApiKey()
    ClobClient->>CdpSignerAdapter: signTypedData for EIP-712
    CdpSignerAdapter->>CDPClient: signTypedData()
    CDPClient-->>CdpSignerAdapter: signature
    CdpSignerAdapter-->>ClobClient: signature
    ClobClient->>PolymarketCLOB: POST auth endpoint
    PolymarketCLOB-->>ClobClient: API credentials
    ClobClient-->>TradingService: credentials
    TradingService->>PolygonRPC: checkAllAllowances()
    PolygonRPC-->>TradingService: allowances
    TradingService->>PolygonRPC: checkAllCtfApprovals()
    PolygonRPC-->>TradingService: ctfApprovals
    alt Approvals Needed
        TradingService->>CDPClient: approveAllPolymarketContracts()
        CDPClient->>PolygonRPC: approve USDC (ERC20)
        CDPClient->>PolygonRPC: setApprovalForAll CTF tokens
        PolygonRPC-->>CDPClient: transaction receipts
    end
    TradingService-->>Agent: setup result with status
    Agent-->>User: Setup complete!

    Note over User,DiscoveryService: Discover Markets
    User->>Agent: search for Bitcoin market
    Agent->>DiscoveryService: searchMarkets(query)
    DiscoveryService->>PolymarketCLOB: GET events endpoint
    PolymarketCLOB-->>DiscoveryService: markets with token IDs
    DiscoveryService->>PolymarketCLOB: GET price endpoint
    PolymarketCLOB-->>DiscoveryService: current prices
    DiscoveryService-->>Agent: markets with tokens and prices
    Agent-->>User: Found market with token IDs

    Note over User,DiscoveryService: Execute Trade
    User->>Agent: buy YES shares
    Agent->>TradingService: getUsdcBalance(userId)
    TradingService->>PolygonRPC: balanceOf(USDC)
    PolygonRPC-->>TradingService: balance
    TradingService-->>Agent: available balance
    Agent->>TradingService: placeOrder(userId, params)
    TradingService->>ClobClient: createAndPostMarketOrder()
    ClobClient->>CdpSignerAdapter: sign order
    CdpSignerAdapter->>CDPClient: signTypedData()
    CDPClient-->>CdpSignerAdapter: signature
    ClobClient->>PolymarketCLOB: POST order endpoint
    PolymarketCLOB->>PolygonRPC: execute on-chain trade
    PolygonRPC-->>PolymarketCLOB: transaction hash
    PolymarketCLOB-->>ClobClient: order result matched
    ClobClient-->>TradingService: order result
    TradingService-->>Agent: FILLED with tx hash
    Agent-->>User: Trade executed successfully

    Note over User,DiscoveryService: View Positions
    User->>Agent: show my positions
    Agent->>TradingService: getWalletAddress(userId)
    TradingService-->>Agent: walletAddress
    Agent->>DiscoveryService: getUserPositions(walletAddress)
    DiscoveryService->>PolymarketCLOB: GET positions endpoint
    PolymarketCLOB-->>DiscoveryService: positions with PnL
    DiscoveryService-->>Agent: position data
    Agent-->>User: Your positions with PnL

    Note over User,DiscoveryService: Sell Position
    User->>Agent: sell my position
    Agent->>DiscoveryService: getUserPositions(walletAddress)
    DiscoveryService-->>Agent: position data with token ID
    Agent->>TradingService: placeOrder SELL
    TradingService->>ClobClient: createAndPostMarketOrder SELL
    ClobClient->>PolymarketCLOB: POST sell order
    PolymarketCLOB->>PolygonRPC: execute on-chain trade
    PolygonRPC-->>PolymarketCLOB: transaction hash
    PolymarketCLOB-->>ClobClient: order matched
    TradingService-->>Agent: FILLED status
    Agent-->>User: Sold successfully
Loading

- Fix: Exclude markets with failed price fetches instead of showing
  misleading 50% fallback prices (getActiveMarkets, searchMarkets)
- Enhance action descriptions to guide users to correct actions
  (e.g., use GET_POLYMARKET_EVENTS for sports/category markets)
- Add query and slug parameters to getEvents for text search and
  direct event lookup by slug
- Improve getLiveVolume: show top 10 markets, format volume in millions,
  include total market count in footer
- Add trading instructions to searchMarkets response
- Pin @elizaos/core dependency to 1.6.4
@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/polymarket-phase2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@railway-app
Copy link

railway-app bot commented Jan 4, 2026

🚅 Deployed to the otaku-pr-118 environment in otaku

Service Status Web Updated (UTC)
otaku-fe ◻️ Removed (View Logs) Web Jan 5, 2026 at 1:37 pm

@railway-app railway-app bot temporarily deployed to otaku / otaku-pr-118 January 4, 2026 16:45 Destroyed
@claude

This comment was marked as outdated.

@claude

This comment was marked as outdated.

…ions

- Create matcher.ts with trading-specific keyword patterns
- Update all 9 trading actions to use shouldPolymarketTradingPluginBeInContext
- Actions now only visible when conversation context is trading-related
- Export matcher function from plugin index for external use
@railway-app railway-app bot temporarily deployed to otaku / otaku-pr-118 January 4, 2026 16:51 Destroyed
@claude

This comment was marked as outdated.

- Remove all debug telemetry calls from buyShares.action.ts
- Remove all debug telemetry calls from trading.service.ts
- Addresses CI blocking issue: hardcoded telemetry must be removed
@railway-app railway-app bot temporarily deployed to otaku / otaku-pr-118 January 4, 2026 17:23 Destroyed
@wtfsayo wtfsayo marked this pull request as ready for review January 4, 2026 17:24
@claude

This comment was marked as outdated.

greptile-apps[bot]

This comment was marked as outdated.

- trading.service.ts: Use clearer variable names (usdcToSpend, sharesToSell) for order amount calculation
- trading.service.ts: Add safe division check for executedPrice to prevent NaN when takingAmount is 0
- trading.service.ts: isSetupComplete now validates all 3 USDC allowances + all 3 CTF token approvals
- sellShares.action.ts: Return explicit errors for invalid share amounts instead of silently selling all shares
  - Error for NaN values
  - Error for zero/negative values
  - Error when requested shares exceed position size
@railway-app railway-app bot temporarily deployed to otaku / otaku-pr-118 January 4, 2026 17:39 Destroyed
@claude

This comment was marked as outdated.

Fixed broken string interpolation in getOrCreateUserState() where
'$  {userId' had an extra space, causing the literal string to be
logged instead of the actual user ID value.
@railway-app railway-app bot temporarily deployed to otaku / otaku-pr-118 January 4, 2026 17:54 Destroyed
@claude

This comment was marked as outdated.

wtfsayo and others added 2 commits January 5, 2026 06:20
- Add CONDITIONAL_TOKENS_ABI to constants.ts for CTF contract interaction
- Add redeemPosition() and redeemAllPositions() methods to trading service
- Rewrite redeemWinnings.action.ts to call CTF contract directly via viem
- Redemption burns winning outcome tokens and returns USDC to wallet
- Supports both single condition redemption and batch redemption of all redeemable positions
- Uses Polymarket Data API to detect redeemable positions (redeemable: true)

Amp-Thread-ID: https://ampcode.com/threads/T-019b8bea-8da1-7318-873c-432ff5658ea0
Co-authored-by: Amp <amp@ampcode.com>
feat(polymarket): implement redemption for resolved market positions
@claude

This comment was marked as outdated.

// Markets can be active=true/closed=false but still expired if endDate has passed
const activeMarkets = event.markets.filter((m: any) => {
if (m.active !== true || m.closed === true || m.archived === true) {
return false;

This comment was marked as outdated.

// For Yes/No markets, use yes_price/no_price for backwards compatibility
// For alternative markets, first outcome goes to yes_price, second to no_price
yes_price: price1,
no_price: price2,

This comment was marked as outdated.

@claude

This comment was marked as outdated.

…kups

When getMarketDetail is called with a condition_id, now:
1. First tries /markets?condition_id=xxx direct lookup (consistent with slug/id)
2. Falls back to events pagination WITHOUT active/closed filters

This fixes 'Market not found' errors when getMarketPrices called
getMarketDetail for closed or low-volume markets that were previously
retrieved via slug or numeric ID.
@claude

This comment was marked as outdated.

@claude

This comment was marked as outdated.

…tion

- Fix wallet account resolution priority across all trading actions:
  - Changed from walletEntityId || accountName to accountName || walletEntityId
  - accountName contains cdp_user_id from user_registry (original entity_id)
  - Server wallets are keyed by cdp_user_id, not current entity_id
- Fix executedSize type in buyShares - parse string to number (API returns string)
- Fix events cache to allow client-side query filtering on cached results
- Fix error serialization in entity.ts logging

Affected files:
- All polymarket trading actions (approveUsdc, buyShares, cancelOrder,
  getOpenOrders, placeLimitOrder, sellShares, setupTrading)
- polymarket.service.ts (events caching)
- entity.ts (error logging)
@claude
Copy link

claude bot commented Jan 5, 2026

🤖 Claude Code Review

Summary

This PR adds comprehensive Polymarket trading capabilities via a new plugin-polymarket-trading plugin with CDP wallet integration, alongside significant improvements to the discovery plugin for better market browsing and data quality.


🔒 Security

CRITICAL FINDINGS - MUST ADDRESS:

  1. Private Key Exposure Risk (src/plugins/plugin-polymarket-trading/src/adapters/cdp-signer-adapter.ts:76-81)

    • getPrivateKey() method exposes raw private key string
    • Private key logged/returned could leak to state, logs, or error messages
    • Fix: Remove this method entirely. The adapter should only use the key internally for signing, never expose it.
  2. Insufficient Transaction Amount Validation (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts)

    • Missing maximum transaction size limits
    • No percentage-of-balance safety caps
    • Could allow draining wallet on compromised/manipulated params
    • Fix: Add configurable max transaction limits (e.g., 25% of USDC balance per trade, 0k absolute max)
  3. USDC Balance Check Race Condition (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:172-181)

    • Balance checked before order placement, but no guarantee balance remains sufficient during async execution
    • Risk: Insufficient funds error after validation passes
    • Fix: Add balance re-check immediately before order submission or use atomic balance-check-and-execute
  4. Approval Amount Unbounded (src/plugins/plugin-polymarket-trading/src/utils/approvalHelpers.ts:88-95, 196-203)

    • Uses MaxUint256 for unlimited approvals (USDC ERC20 + CTF ERC1155)
    • Standard DeFi practice but increases attack surface if Polymarket contracts compromised
    • Recommendation: Consider time-limited or amount-capped approvals, or document this risk in character config
  5. No Slippage Protection on Market Orders (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:656-672)

    • Market buy/sell orders execute at any price
    • Vulnerable to front-running and sandwich attacks
    • Fix: Add max slippage parameter (default 2-5%) and validate execution price against expected price
  6. Error Messages May Leak Sensitive Data (multiple files)

    • Error handling returns full error messages to user
    • Could expose API keys, private data, or internal state
    • Fix: Sanitize error messages before returning to user (see src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:411-413)

🐛 Issues Found

Must Fix:

  1. Type Safety Violation (src/plugins/plugin-polymarket-trading/src/adapters/cdp-signer-adapter.ts:14-15)

    • any types for CDP account: private account: any
    • Should use proper types from @coinbase/coinbase-sdk
    • Also affects src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:60
  2. Unhandled Promise Rejection (src/plugins/plugin-polymarket-trading/src/actions/setupTrading.action.ts:190-205)

    • Approval transactions in parallel with Promise.all() but individual failures not isolated
    • If one approval fails, all fail - should catch individually and report which failed
  3. Memory Leak in User Cache (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:70-88)

    • LRU cache size 100 users, but no TTL on entries
    • Stale CLOB clients may accumulate if users don't trade for long periods
    • Fix: Add TTL (e.g., 24h) to cache entries or periodic cleanup
  4. Race Condition in Setup (src/plugins/plugin-polymarket-trading/src/actions/setupTrading.action.ts:170-189)

    • Concurrent calls to setupTrading could create duplicate API keys
    • Fix: Add mutex/lock around setup or check cache first
  5. Missing Input Sanitization (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:156-169)

    • Token IDs not validated (should be valid hex/numeric format)
    • Outcome strings not validated against expected values
    • Market slugs not sanitized
    • Fix: Add Zod schema validation for all string inputs
  6. Incorrect Network Assumptions (src/plugins/plugin-polymarket-trading/src/constants.ts:31-42)

    • Hardcoded Polygon chain ID 137
    • No validation that CDP wallet is on Polygon
    • Could submit transactions to wrong network
    • Fix: Validate CDP account network matches Polygon before any operation
  7. SQL Plugin Import Path Changed Without Dependency Update (src/index.ts:3)

    • Changed from @elizaos/plugin-sql to @elizaos/plugin-sql/node
    • Could break if package doesn't export /node subpath
    • Fix: Verify package.json exports or document this requirement

📋 Test Coverage

BLOCKING - Tests Required:

This PR adds 9 new trading actions handling real cryptocurrency transactions but includes ZERO tests. This is unacceptable for financial operations.

Required tests (must be added to src/packages/server/ or src/plugins/plugin-polymarket-trading/):

  1. Unit tests for trading.service.ts:

    • Setup trading with mock CDP client
    • Approval flows (USDC + CTF)
    • Order placement validation
    • Balance checks
    • Error handling
  2. Integration tests for actions:

    • setupTrading - API key creation, approval flow
    • buyShares - parameter validation, balance checks, order execution
    • sellShares - position fetching, selling flow
    • placeLimitOrder - limit order validation
    • cancelOrder - order cancellation
    • redeemWinnings - redemption flow
  3. Approval helper tests:

    • USDC approval for all exchange contracts
    • CTF approval for all exchange contracts
    • Approval status checks
    • Error handling
  4. CDP Signer Adapter tests:

    • EIP-712 signature generation
    • Message signing
    • Error handling

Minimum acceptable coverage: 70% for financial code


💡 Suggestions (Non-blocking)

  1. DRY Violation - Repeated Price Fetching (src/plugins/plugin-polymarket-discovery/src/actions/)

    • Multiple actions fetch prices with service.getMarketPrices() using same error handling pattern
    • Consider extracting to shared utility in src/plugins/plugin-polymarket-discovery/src/utils/priceHelpers.ts
  2. Inconsistent Error Response Format

    • Some actions return { success: false, error: string }, others throw exceptions
    • Standardize error handling across all trading actions
  3. Magic Numbers (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:82)

    • LRU cache size hardcoded as 100
    • Move to constants file
  4. Missing Character Config Updates

    • New trading actions not documented in docs/character-config.md
    • Should add Polymarket trading safety rules to character (similar to Morpho high-risk protocol)
  5. Outdated Comments (src/plugins/plugin-polymarket-discovery/src/services/polymarket.service.ts:12-15)

    • Comments reference old /markets endpoint but code now uses /events/pagination
  6. Verbose Logging

    • Every action logs extensively (good for debugging but noisy in production)
    • Consider log levels: DEBUG for param details, INFO for execution, ERROR only for failures
  7. Frontend Integration Missing

    • Trading plugin has no frontend UI
    • Users must interact via chat only
    • Consider adding trading panel to frontend (similar to wallet panel)

📋 Checklist

  • CRITICAL: Tests added for all trading actions (required before merge)
  • CRITICAL: Remove getPrivateKey() method from CdpSignerAdapter
  • CRITICAL: Add transaction amount limits (max % of balance, absolute max)
  • CRITICAL: Add slippage protection to market orders
  • HIGH: Fix any types - use proper CDP SDK types
  • HIGH: Add input sanitization (Zod schemas) for token IDs, outcomes, slugs
  • HIGH: Validate CDP wallet network is Polygon before operations
  • MEDIUM: Fix race conditions (balance check, setup trading)
  • MEDIUM: Add TTL to user cache or periodic cleanup
  • MEDIUM: Sanitize error messages before returning to user
  • LOW: Update character config docs with Polymarket trading rules
  • LOW: Consider approval amount limits or document unlimited approval risk

✅ What's Good

  • Clean separation of concerns: discovery vs trading plugins
  • Comprehensive validation in action validate() methods
  • Well-documented code with extensive inline comments
  • CDP signer adapter properly bridges ethers v5 for CLOB client compatibility
  • Discovery plugin improvements (pagination, non-expired filtering, CLOB pricing) are solid
  • Service-based architecture with proper state management

Overall Assessment: This is high-quality code with proper architecture, but it MUST NOT be merged without:

  1. Comprehensive test coverage (financial code requires tests)
  2. Security fixes (private key exposure, transaction limits, slippage protection)
  3. Type safety improvements (remove any types)

Estimated effort to address: 2-3 days for tests + security fixes.

@0xbbjoker 0xbbjoker force-pushed the feature/polymarket-phase2 branch from 6677ef5 to d7229fd Compare January 5, 2026 17:57
@claude
Copy link

claude bot commented Jan 5, 2026

🤖 Claude Code Review

Summary

This PR adds comprehensive Polymarket trading capabilities through a new @elizaos/plugin-polymarket-trading plugin with CDP wallet integration, plus significant enhancements to the discovery plugin for better market lookup and pricing accuracy.

🔒 Security

✅ No Critical Security Issues Found

The implementation demonstrates solid security practices:

  1. Transaction Safety:

    • ✅ Maximum trade amount configurable (POLYMARKET_MAX_TRADE_AMOUNT) with default $1000 limit (src/plugins/plugin-polymarket-trading/src/constants.ts:13)
    • ✅ Minimum order validation ($1 USDC minimum) prevents dust orders (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:480-487)
    • ✅ Balance checks before trades (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:344-364)
    • ✅ Price validation (0.01-0.99 range) prevents invalid orders (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:314-322)
    • ✅ Token ID format validation to prevent using wrong identifiers (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:272-296)
  2. Credential Handling:

    • ✅ CDP credentials loaded from environment variables, not hardcoded (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:106-108)
    • ✅ API credentials cached with TTL to avoid repeated derivation (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:384-390)
    • ✅ No secrets logged in error messages
  3. Input Validation:

    • ✅ Comprehensive parameter validation with helpful error messages (src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:214-267)
    • ✅ Wallet address sanitization via Viem's Hex type
    • ✅ Multi-stage validation: service availability → setup complete → parameter validation → balance check
  4. Network Handling:

    • ✅ Hardcoded Polygon chain ID (137) prevents cross-chain mistakes (src/plugins/plugin-polymarket-trading/src/constants.ts:7)
    • ✅ Proper contract addresses for USDC, CTF tokens, and exchanges (src/plugins/plugin-polymarket-trading/src/constants.ts:9-21)
    • ✅ Dual approval system: USDC (ERC20) for buying + CTF tokens (ERC1155) for selling (src/plugins/plugin-polymarket-trading/src/utils/approvalHelpers.ts:241-344)

⚠️ Minor Considerations:

  1. Approval Amount: Uses unlimited approval (2^256-1) for USDC by default (src/plugins/plugin-polymarket-trading/src/constants.ts:34). This is standard practice but creates unlimited trust in exchange contracts. Consider documenting this in setup action.

  2. Gas Estimation: No explicit gas estimation before transactions. Low MATIC warning at 0.01 threshold (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:265-269) is good, but transactions could still fail if gas spikes.

  3. Race Conditions: User state caching (src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:79) uses a simple Map without locks. Unlikely to cause issues with single-user agents, but could be problematic if multiple requests happen simultaneously for the same user.

🐛 Issues Found

✅ No blocking issues

Code quality is high with proper error handling, comprehensive validation, and well-structured architecture.

💡 Suggestions

  1. Discovery Plugin - Failed Price Fetches:

    • File: src/plugins/plugin-polymarket-discovery/src/actions/getActiveMarkets.action.ts:141-166
    • Good: Now correctly excludes markets where price fetch fails instead of returning fake "50%" prices
    • Suggestion: Consider adding a warning in the response text when markets are excluded due to failed price fetches (currently only logged)
  2. Trading Service - TODO Comments:

    • File: src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:998, 1173
    • Two TODO comments for calculating locked USDC from open orders and parsing redemption amounts from logs
    • Impact: Low priority - these are nice-to-haves, not critical functionality
  3. Type Safety - Loose Any Types:

    • File: src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:397, 443, 516-523
    • Using any casts for clob-client responses due to upstream type limitations
    • Mitigation: Code properly handles all response variations with null coalescing and type guards
    • Suggestion: Consider defining local interfaces for expected CLOB response shapes
  4. Documentation - Approval Requirements:

    • The dual approval system (USDC for buying, CTF tokens for selling) is well-implemented but could be better documented in user-facing actions
    • Consider adding a note in POLYMARKET_SETUP_TRADING response explaining both approval types
  5. Error Handling - Redemption Amounts:

    • File: src/plugins/plugin-polymarket-trading/src/services/trading.service.ts:1173
    • Redemption returns hardcoded "0" amount instead of parsing from logs
    • Impact: Low - transaction still succeeds, just missing display value

📋 Checklist

  • Tests added/updated - Trading functionality is complex; integration tests would be valuable but not strictly required for initial release
  • ⚠️ Types are strict (no any) - Some any types present but justified by upstream library limitations; mitigated with runtime checks
  • Follows plugin patterns from CLAUDE.md - Excellent adherence to ElizaOS patterns:
    • Actions properly exported from plugin index
    • Service-based architecture with proper lifecycle
    • Multi-stage validation (service → required fields → types → business logic)
    • Parameters flow through state.data.actionParams
    • Clean separation: discovery for browsing, trading for execution

🎯 Architecture Highlights

Excellent Software Engineering:

  1. Clean Separation of Concerns:

    • Discovery plugin: Read-only market data
    • Trading plugin: Execution with CDP wallet integration
    • Clear service boundaries with typed interfaces
  2. CDP Signer Adapter:

    • Brilliant bridge between CDP SDK and ethers v5 (required by clob-client)
    • Well-documented EIP-712 signature handling
    • Clean implementation at src/plugins/plugin-polymarket-trading/src/adapters/cdp-signer-adapter.ts
  3. Comprehensive Error Messages:

    • User-friendly error messages with actionable guidance
    • Examples: src/plugins/plugin-polymarket-trading/src/actions/buyShares.action.ts:243-259, 272-289
    • Includes troubleshooting steps and expected values
  4. Discovery Improvements:

    • Switched to /events/pagination with non-expired market filtering (prevents showing stale markets)
    • Real-time CLOB pricing replaces orderbook asks (more accurate)
    • Flexible market lookup: slug → ID → condition_id fallback chain

✅ Recommendation

This PR is safe to merge. The implementation demonstrates exceptional attention to:

  • Transaction safety with multiple validation layers
  • Secure credential handling
  • Comprehensive error handling with user-friendly messages
  • Clean architecture following ElizaOS patterns
  • Proper separation between discovery (read) and trading (write) operations

The minor suggestions above are enhancements, not blockers. The code is production-ready for real-money cryptocurrency trading.


Reviewed with: Claude Sonnet 4.5
Security Focus Areas: DeFi transaction safety, wallet security, input validation, network handling

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants