Skip to content

Feature/polymarket plugin#346

Open
Craxe2 wants to merge 3 commits intoEmberAGI:mainfrom
Craxe2:feature/polymarket-mcp
Open

Feature/polymarket plugin#346
Craxe2 wants to merge 3 commits intoEmberAGI:mainfrom
Craxe2:feature/polymarket-mcp

Conversation

@Craxe2
Copy link

@Craxe2 Craxe2 commented Nov 28, 2025

Summary

Related Issue(s):

Provide a brief description of what this PR accomplishes:

Adds a Polymarket perpetuals plugin for the Ember Plugin System, enabling Vibekit agents to trade on Polymarket prediction markets. The plugin maps Polymarket's YES/NO token model to perpetuals long/short positions, with market discovery, position tracking, order placement, and cancellation.

Type of Change:

  • 🔌 Protocol integration (adds support for new DeFi protocol)

🧪 Testing

Tests Performed:

  • TypeScript compilation verified (pnpm build)
  • Linting passed (pnpm lint)
  • Code structure reviewed against AAVE plugin patterns
  • API integration points validated (Gamma, CLOB, Data APIs)

Test Results:

  • ✅ TypeScript compilation successful
  • ✅ No linting errors

Steps to Run Tests:

# Build and lint
cd typescript/onchain-actions-plugins/registry
pnpm build
pnpm lint

# Integration testing requires:
# 1. Valid Polymarket API credentials
# 2. Test wallet with USDC on Polygon
# 3. Environment variables configured

Checklists

Code Quality

  • Code follows project conventions and style guidelines
  • TypeScript compilation passes (pnpm build)
  • Linting passes (pnpm lint)
  • All tests pass (pnpm test) - Integration tests pending API credentials
  • No any types introduced (uses unknown with proper type guards)
  • Error handling implemented appropriately (try/catch blocks, fallbacks)
  • Security best practices followed (no exposed secrets/keys, credentials via env)

Documentation

  • Code is self-documenting or includes necessary comments
  • README updated
  • API/interface changes documented
  • Breaking changes noted in description - No breaking changes

Agent/MCP Specific (if applicable)

  • MCP protocol compliance verified - N/A (plugin, not MCP)
  • Agent skills and tools properly defined - Actions and queries defined
  • Error handling for external API failures - Implemented with fallbacks
  • Rate limiting and retry logic implemented - Market caching reduces API calls
  • Configuration options documented - All params documented in README

Deployment Notes

Deployment Considerations:

  • Plugin requires Polygon (chain ID 137) configuration
  • Credentials (private key, funder address) must be provided via registerPolymarket() parameters
  • Plugin uses deferred registration pattern (async initialization)
  • Market data caching reduces API load
  • Position fetching has fallback mechanism (Data API → CLOB)

New or Changed Environment Variables:

  • None (credentials passed via function parameters, not env vars)
  • Optional: POLYMARKET_HOST, POLYMARKET_GAMMA_API_URL, POLYMARKET_DATA_API_URL can be configured via adapter params

Breaking Changes or Migration Steps:

  • None. This is a new plugin addition.

New Dependencies Added:

  • @polymarket/clob-client (^4.22.8) - Official Polymarket CLOB client
  • @ethersproject/wallet (^5.7.2) - Already in dependencies, used for signing

Additional Context

Screenshots or Demo Videos (if applicable):

  • N/A (backend plugin, no UI)

Implementation Details:

  • Plugin Type: perpetuals (maps prediction markets to derivatives model)
  • Actions Implemented:
    • perpetuals-long → BUY YES tokens
    • perpetuals-short → BUY NO tokens
    • perpetuals-close → Cancel orders
  • Queries Implemented:
    • getMarkets - Fetches active markets from Gamma API
    • getPositions - Fetches user positions from Data API (with CLOB fallback)
    • getOrders - Fetches pending orders from CLOB ledger
  • APIs Integrated:
    • Gamma API (https://gamma-api.polymarket.com) - Market data
    • CLOB API (https://clob.polymarket.com) - Order execution
    • Data API (https://data-api.polymarket.com) - User positions
  • Risk Controls: Configurable maxOrderSize and maxOrderNotional limits
  • Architecture: Follows AAVE plugin pattern for consistency

Craxe2 and others added 3 commits November 27, 2025 12:08
…trading

- Implement PolymarketAdapter with full CLOB, Gamma, and Data API integration
- Add market discovery, position tracking, and order management
- Map Polymarket YES/NO tokens to perpetuals long/short positions
- Support order placement, cancellation, and position queries
- Include risk limits (maxOrderSize, maxOrderNotional)
- Remove MCP server implementation in favor of plugin architecture
@Jay-Sojitra
Copy link

Jay-Sojitra commented Jan 9, 2026

PR #346 Review - Polymarket Plugin

Summary

Recommendation: Request Changes - The plugin has critical bugs that prevent it from working.


Critical Issues Found

1. 🔴 API Response Parsing Bug (CRITICAL)

File: adapter.ts

The plugin expects the Gamma API to return { markets: [...] } but it actually returns a direct array [...].

Current code (line 400):

const data = (await response.json()) as PolymarketMarketResponse;
const markets = data.markets.filter(...) // ❌ data.markets is undefined!

Should be:

const data = (await response.json()) as PolymarketMarket[];
const markets = data.filter(...) // ✅ data IS the array

Result: Plugin returns { markets: [] } while direct API call returns 100+ markets.


2. 🔴 Wrong clobTokenIds Type (CRITICAL)

File: adapter.ts (lines 54-57)

The plugin expects clobTokenIds to be an object:

clobTokenIds: {
  yes: string;  // ❌ WRONG
  no: string;
}

Actual API returns a JSON string:

clobTokenIds: '["tokenId1", "tokenId2"]'  // YES = index 0, NO = index 1

Fix: Parse the JSON string with JSON.parse() and access by index.


3. 🟡 No Tests

No unit or integration tests exist for this plugin. Adding tests against the real API would catch these parsing issues.


4. 🟡 Lint Errors (6 errors)

Running pnpm lint shows 6 errors - mostly unused variables that need to be fixed.


5. 🟡 ethers vs viem

Team recommends using viem instead of @ethersproject/wallet.

Note: @polymarket/clob-client has ethers as a direct dependency. Options:

  • Option A: Keep ethers for clob-client interaction (simplest, works now)
  • Option B: Create an adapter that wraps viem account to look like ethers Wallet (more work, cleaner long-term)

Affected Methods

All these methods have the same parsing bugs:

  • fetchMarketData()
  • getAvailableTokens()
  • getMarkets()

Recommendation

  1. Fix the API response parsing (array vs object)
  2. Fix the clobTokenIds parsing (JSON string vs object)
  3. Add integration tests against real Polymarket API
  4. Fix lint errors
  5. Decide on ethers vs viem approach

Once fixed, the plugin should be re-tested against mainnet before merging.

0xTomDaniel

This comment was marked as duplicate.

Copy link
Contributor

@0xTomDaniel 0xTomDaniel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes - prediction markets must not be modeled as perpetuals. We need a dedicated prediction-markets plugin type, schemas, actions, and queries.

Blocking issues

  1. Wrong abstraction: prediction markets are not perpetuals.

    • Mapping YES/NO outcomes into Perpetuals* actions/schemas breaks core semantics (no leverage, funding/borrowing fees, or perpetual position mechanics). This should be a first-class predictionMarkets plugin type with purpose-built actions/queries/schemas, then port Polymarket to that interface.
    • Integration points (core registry):
      • registry/src/core/pluginType.ts -> add predictionMarkets and extend AvailableActions/AvailableQueries.
      • registry/src/core/actions/predictionMarkets.ts -> new action types + callbacks; export in actions/index.ts; add to Action union and CallbacksRecord in actions/types.ts.
      • registry/src/core/queries/predictionMarkets.ts -> new query types; export in queries/index.ts.
      • registry/src/core/schemas/predictionMarkets.ts -> Zod schemas; export in schemas/index.ts.
      • registry/README.md + registry/DEVELOPMENT.md -> document new type, action names, queries, and MCP tools (if exposed).
    • Integration points (downstream consumers):
      • Search for PluginType or perpetuals enumerations in clients/agents to add the new category where relevant (tool groupings, prompt mappings, UI categories).
  2. Lockfile not updated for new deps.

    • registry/package.json adds deps, but typescript/pnpm-lock.yaml is not updated. Run pnpm install from typescript/ and commit the lockfile.
  3. registerPolymarket drops config options documented in README.

    • gammaApiUrl/dataApiUrl are documented but never passed. Either plumb them through or remove from docs/type.
    • registry/src/polymarket-perpetuals-plugin/index.ts:115
  4. Inconsistent identifiers for market vs outcome tokens.

    • Actions treat marketAddress as a YES token id, while queries return market.id or tokenId. This breaks round-trip flows.
    • New prediction-markets schemas must separate marketId from outcomeTokenId explicitly.

Suggested prediction-markets abstraction (dense, domain-accurate)
Actions (type names are illustrative):

  • predictionMarkets-placeOrder
    • Request: marketId, outcomeId (or outcomeTokenId), side (buy/sell), size (shares), optional price (limit), optional quoteTokenAddress, optional timeInForce/expiration.
    • Response: orderId (if available) + transactions (can be empty for off-chain matching).
  • predictionMarkets-cancelOrder
    • Request: orderId + walletAddress.
    • Response: transactions or success.
  • predictionMarkets-redeem / predictionMarkets-claimWinnings
    • Request: marketId, outcomeId, walletAddress, optional amount.
    • Response: transactions.

Queries:

  • getMarkets
    • Request: chainIds, optional filters: status (active|resolved|voided|paused), category, endTimeBefore/After, minLiquidity, limit/offset.
  • getMarketDetails (optional but strongly useful)
    • Request: marketId; Response includes outcomes, prices, status, resolution metadata.
  • getPositions
    • Request: walletAddress, optional marketIds, optional includeResolved.
  • getOrders
    • Request: walletAddress, optional marketIds, status (open|filled|canceled|expired).

Schemas (key fields to keep consistent across protocols):

  • PredictionMarket
    • marketId, chainId, title/question, status, endTime, resolutionOutcome (nullable), oracle/source, outcomes[].
  • PredictionOutcome
    • outcomeId, name, optional tokenId, price (as decimal string), probability (optional if price already normalized), liquidity (optional).
  • PredictionPosition
    • marketId, outcomeId, optional tokenId, size, avgPrice, cost, pnl (optional), quoteTokenAddress.
  • PredictionOrder
    • orderId, marketId, outcomeId, side, price, size, status, createdAt, updatedAt.

Modeling rules (to avoid future mismatches):

  • marketId != outcomeTokenId; never overload.
  • Do not include leverage/funding/borrowing fields in prediction-market positions; keep it share-based.
  • Normalize prices consistently (0-1 probability or quote-token price) and document with an enum if needed.
  • Represent resolution explicitly (resolvedOutcomeId or voided) to support redeem/claim flows.

Next steps

  • Implement the new prediction-markets plugin type + schemas/actions/queries, migrate Polymarket adapter to it.
  • Fix remaining blockers and re-run pnpm lint + pnpm build from typescript/.

0xTomDaniel

This comment was marked as duplicate.

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.

3 participants