diff --git a/.gitignore b/.gitignore index 5c84119..7e0db0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dist/ node_modules/ -.env \ No newline at end of file +.env +.turbo \ No newline at end of file diff --git a/__tests__/getOrderBookDepth.test.ts b/__tests__/getOrderBookDepth.test.ts index 35d5a45..3358b24 100644 --- a/__tests__/getOrderBookDepth.test.ts +++ b/__tests__/getOrderBookDepth.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import type { IAgentRuntime, Memory, State, Content } from '@elizaos/core'; import { getOrderBookDepthAction } from '../src/actions/getOrderBookDepth'; -import { initializeClobClient, type BookParams } from '../src/utils/clobClient'; +import { initializeClobClient } from '../src/utils/clobClient'; import { callLLMWithTimeout } from '../src/utils/llmHelpers'; import type { OrderBook } from '../src/types'; @@ -182,7 +182,7 @@ describe('getOrderBookDepthAction', () => { expect(result.text).toContain('Total Ask Levels: 4'); expect((result.data as any)?.orderBooks).toEqual(mockMultipleOrderBooks); - const expectedParams: BookParams[] = [{ token_id: '123456' }, { token_id: '789012' }]; + const expectedParams = [{ token_id: '123456' }, { token_id: '789012' }]; expect(mockClobClient.getOrderBooks).toHaveBeenCalledWith(expectedParams); }); diff --git a/package.json b/package.json index 197a7ca..b772c93 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "plugin-polymarket", + "name": "@elizaos/plugin-polymarket", "description": "ElizaOS plugin for Polymarket prediction markets", - "version": "0.1.0", + "version": "1.0.0", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -29,9 +29,9 @@ "dist" ], "dependencies": { - "@elizaos/cli": "workspace:*", - "@elizaos/core": "workspace:*", - "@elizaos/plugin-sql": "workspace:*", + "@elizaos/cli": "^1.5.9-alpha.1", + "@elizaos/core": "^1.5.9-alpha.1", + "@elizaos/plugin-sql": "^1.5.9-alpha.1", "@polymarket/clob-client": "^4.16.0", "ethers": "^6.13.1", "node-fetch": "^3.0.0", @@ -65,7 +65,39 @@ "platform": "node", "agentConfig": { "pluginType": "elizaos:plugin:1.0.0", - "pluginParameters": {} + "pluginParameters": { + "CLOB_API_URL": { + "type": "string", + "description": "Base URL for the Polymarket CLOB API endpoint.", + "required": false, + "default": "https://clob.polymarket.com", + "sensitive": false + }, + "WALLET_PRIVATE_KEY": { + "type": "string", + "description": "Private key of the wallet used for signing transactions and authentication.", + "required": false, + "sensitive": true + }, + "PRIVATE_KEY": { + "type": "string", + "description": "Alternative private key for authentication (fallback if WALLET_PRIVATE_KEY not set).", + "required": false, + "sensitive": true + }, + "CLOB_API_KEY": { + "type": "string", + "description": "API key for authenticating requests to the Polymarket CLOB API.", + "required": false, + "sensitive": true + }, + "POLYMARKET_PRIVATE_KEY": { + "type": "string", + "description": "Polymarket-specific private key for advanced trading operations.", + "required": false, + "sensitive": true + } + } }, "npmPackage": "plugin-polymarket" -} \ No newline at end of file +} diff --git a/packages/registry/index.json b/packages/registry/index.json deleted file mode 100644 index 4a5b71c..0000000 --- a/packages/registry/index.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "v1": { - "packages": {} - }, - "v2": { - "packages": { - "@elizaos/plugin-polymarket": { - "name": "@elizaos/plugin-polymarket", - "description": "ElizaOS plugin for Polymarket prediction markets", - "type": "module", - "versions": { - "0.1.0": { - "version": "0.1.0", - "runtimeVersion": "1.4.2", - "platform": "node", - "publishedAt": "2025-08-15T02:58:34.494Z", - "published": false - } - } - } - } - } -} \ No newline at end of file diff --git a/packages/registry/packages/@elizaos/plugin-polymarket/0.1.0.json b/packages/registry/packages/@elizaos/plugin-polymarket/0.1.0.json deleted file mode 100644 index 14c5ed3..0000000 --- a/packages/registry/packages/@elizaos/plugin-polymarket/0.1.0.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@elizaos/plugin-polymarket", - "version": "0.1.0", - "description": "ElizaOS plugin for Polymarket prediction markets", - "type": "module", - "platform": "node", - "runtimeVersion": "1.4.2", - "repository": "git+https://github.com/monilpat/plugin-polymarket.git", - "maintainers": [ - "monilpat" - ], - "publishedAt": "2025-08-15T02:58:34.494Z", - "publishedBy": "monilpat", - "dependencies": { - "@elizaos/cli": "workspace:*", - "@elizaos/core": "workspace:*", - "@elizaos/plugin-sql": "workspace:*", - "@polymarket/clob-client": "^4.16.0", - "ethers": "^6.13.1", - "node-fetch": "^3.0.0", - "ws": "^8.17.0", - "zod": "3.25.32" - }, - "tags": [ - "polymarket", - "prediction-markets", - "elizaos", - "plugin" - ], - "license": "UNLICENSED" -} \ No newline at end of file diff --git a/src/actions/checkOrderScoring.ts b/src/actions/checkOrderScoring.ts index 9a4998d..c482a02 100644 --- a/src/actions/checkOrderScoring.ts +++ b/src/actions/checkOrderScoring.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -76,7 +76,7 @@ export const checkOrderScoringAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[checkOrderScoringAction] Handler called!'); let llmResult: { orderIds?: string[]; error?: string } = {}; @@ -110,13 +110,21 @@ export const checkOrderScoringAction: Action = { } else { const errorMessage = 'Please specify one or more Order IDs to check scoring status.'; logger.error(`[checkOrderScoringAction] Order ID extraction failed. Text: "${text}"`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage}`, - actions: ['CHECK_ORDER_SCORING'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'CHECK_ORDER_SCORING', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; - if (callback) await callback(errorContent); - throw new Error(errorMessage); + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } logger.info( `[checkOrderScoringAction] Regex extracted Order IDs: ${JSON.stringify(llmResult.orderIds)}` @@ -145,35 +153,47 @@ export const checkOrderScoringAction: Action = { responseText += 'Could not retrieve scoring status or no valid order IDs provided.'; } - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['CHECK_ORDER_SCORING'], + values: { + success: true, + orderIds: orderIdsToScore, + scoringResponse, + }, data: { + actionName: 'CHECK_ORDER_SCORING', request: apiParams, response: scoringResponse, timestamp: new Date().toISOString(), }, + success: true, }; - if (callback) await callback(responseContent); - return responseContent; + if (callback) await callback({ text: responseResult.text, data: responseResult.data }); + return responseResult; } catch (error) { logger.error( `[checkOrderScoringAction] Error checking order scoring for IDs ${orderIdsToScore.join(', ')}:`, error ); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error checking order scoring**: ${errorMessage}`, - actions: ['CHECK_ORDER_SCORING'], + values: { + success: false, + error: true, + }, data: { + actionName: 'CHECK_ORDER_SCORING', error: errorMessage, orderIds: orderIdsToScore, timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/createApiKey.ts b/src/actions/createApiKey.ts index 4dcaf85..6dac5a0 100644 --- a/src/actions/createApiKey.ts +++ b/src/actions/createApiKey.ts @@ -1,4 +1,12 @@ -import { IAgentRuntime, Memory, State, HandlerCallback, logger, Action } from '@elizaos/core'; +import { + IAgentRuntime, + Memory, + State, + HandlerCallback, + logger, + Action, + ActionResult, +} from '@elizaos/core'; import { initializeClobClient } from '../utils/clobClient'; import { ethers } from 'ethers'; @@ -83,7 +91,7 @@ export const createApiKeyAction: Action = { state: State, options: any, callback: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[createApiKeyAction] Handler called!'); try { @@ -204,7 +212,7 @@ export const createApiKeyAction: Action = { // Check all possible field names in the response const allFields = Object.keys(apiCredentials || {}); - logger.info('[createApiKeyAction] Available fields in response:', allFields); + logger.info('[createApiKeyAction] Available fields in response:', JSON.stringify(allFields)); // Format the response with proper type handling - Polymarket uses api_key, api_secret, api_passphrase const responseData: ApiKeyResponse = { @@ -228,11 +236,14 @@ export const createApiKeyAction: Action = { }; // Debug logging to see what we extracted - logger.info('[createApiKeyAction] Extracted fields:', { - id: responseData.id, - secretLength: responseData.secret?.length, - passphraseLength: responseData.passphrase?.length, - }); + logger.info( + '[createApiKeyAction] Extracted fields:', + JSON.stringify({ + id: responseData.id, + secretLength: responseData.secret?.length, + passphraseLength: responseData.passphrase?.length, + }) + ); // Store the credentials in runtime settings for other actions to use // This allows get/delete API key actions to work without requiring env vars @@ -251,23 +262,29 @@ export const createApiKeyAction: Action = { const storedApiSecret = runtime.getSetting('CLOB_API_SECRET'); const storedApiPassphrase = runtime.getSetting('CLOB_API_PASSPHRASE'); - logger.info('[createApiKeyAction] Verification of stored credentials:', { - storedApiKeyLength: storedApiKey?.length, - storedSecretLength: storedApiSecret?.length, - storedPassphraseLength: storedApiPassphrase?.length, - keysMatch: storedApiKey === responseData.id, - secretsMatch: storedApiSecret === responseData.secret, - passphrasesMatch: storedApiPassphrase === responseData.passphrase, - }); + logger.info( + '[createApiKeyAction] Verification of stored credentials:', + JSON.stringify({ + storedApiKeyLength: storedApiKey?.length, + storedSecretLength: storedApiSecret?.length, + storedPassphraseLength: storedApiPassphrase?.length, + keysMatch: storedApiKey === responseData.id, + secretsMatch: storedApiSecret === responseData.secret, + passphrasesMatch: storedApiPassphrase === responseData.passphrase, + }) + ); } else { logger.warn( '[createApiKeyAction] Some credentials are missing, could not store in runtime' ); - logger.warn('[createApiKeyAction] Missing fields:', { - hasId: !!responseData.id, - hasSecret: !!responseData.secret, - hasPassphrase: !!responseData.passphrase, - }); + logger.warn( + '[createApiKeyAction] Missing fields:', + JSON.stringify({ + hasId: !!responseData.id, + hasSecret: !!responseData.secret, + hasPassphrase: !!responseData.passphrase, + }) + ); } // Create success message @@ -295,19 +312,33 @@ ${actionDescription} **Next Steps:** You can now place orders on Polymarket. The system will automatically use these credentials for authenticated operations.`; + // Create ActionResult + const successResult: ActionResult = { + text: successMessage, + values: { + success: true, + apiKey: responseData, + isNewKey, + }, + data: { + actionName: 'CREATE_API_KEY', + success: true, + apiKey: responseData, + isNewKey, + }, + success: true, + }; + // Call callback with success response if (callback) { callback({ text: successMessage, - action: 'CREATE_API_KEY', - data: { - success: true, - apiKey: responseData, - }, + data: successResult.data, }); } logger.info('[createApiKeyAction] API key creation completed successfully'); + return successResult; } catch (error) { logger.error('[createApiKeyAction] Error creating API key:', error); @@ -326,16 +357,29 @@ You can now place orders on Polymarket. The system will automatically use these • Network connection is stable • Try again in a few moments`; + const errorResult: ActionResult = { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'CREATE_API_KEY', + success: false, + error: error instanceof Error ? error.message : 'Unknown error', + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), + }; + if (callback) { callback({ text: errorMessage, - action: 'CREATE_API_KEY', - data: { - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - }, + data: errorResult.data, }); } + + return errorResult; } }, }; diff --git a/src/actions/getAccountAccessStatus.ts b/src/actions/getAccountAccessStatus.ts index d3e0343..badeca5 100644 --- a/src/actions/getAccountAccessStatus.ts +++ b/src/actions/getAccountAccessStatus.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -57,7 +57,7 @@ export const getAccountAccessStatusAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getAccountAccessStatusAction] Handler called!'); try { @@ -169,34 +169,52 @@ export const getAccountAccessStatusAction: Action = { responseText += `No specific API key is currently active for this session (beyond any .env configured managed keys).\n`; } - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_ACCOUNT_ACCESS_STATUS'], + values: { + success: true, + certRequired, + managedApiKeys: apiKeysList, + activeSessionKey: sessionApiKeyId + ? { id: sessionApiKeyId, label: sessionApiLabel, source: sessionApiSource } + : undefined, + }, data: { + actionName: 'POLYMARKET_GET_ACCOUNT_ACCESS_STATUS', certRequired, - managedApiKeys: apiKeysList, // Renamed for clarity + managedApiKeys: apiKeysList, activeSessionKey: sessionApiKeyId ? { id: sessionApiKeyId, label: sessionApiLabel, source: sessionApiSource } : undefined, error: apiKeysError, timestamp: new Date().toISOString(), }, + success: true, }; - if (callback) await callback(responseContent); - return responseContent; + if (callback) await callback({ text: responseResult.text, data: responseResult.data }); + return responseResult; } catch (error) { logger.error('[getAccountAccessStatusAction] Error fetching account access status:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage}`, - actions: ['POLYMARKET_GET_ACCOUNT_ACCESS_STATUS'], - data: { error: errorMessage, timestamp: new Date().toISOString() }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ACCOUNT_ACCESS_STATUS', + error: errorMessage, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/getActiveOrders.ts b/src/actions/getActiveOrders.ts index 4e8adab..6f317e2 100644 --- a/src/actions/getActiveOrders.ts +++ b/src/actions/getActiveOrders.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -70,7 +70,7 @@ export const getActiveOrdersAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getActiveOrdersAction] Handler called!'); let extractedParams: { @@ -109,13 +109,21 @@ export const getActiveOrdersAction: Action = { if (!extractedParams.marketId) { const errorMessage = 'Please specify a Market ID to get active orders.'; logger.error(`[getActiveOrdersAction] Market ID extraction failed. Text: "${text}"`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage}`, - actions: ['POLYMARKET_GET_ACTIVE_ORDERS'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ACTIVE_ORDERS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; - if (callback) await callback(errorContent); - throw new Error(errorMessage); + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } } @@ -191,29 +199,47 @@ export const getActiveOrdersAction: Action = { responseText += `.`; } - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_ACTIVE_ORDERS'], + values: { + success: true, + orders: actualOrders, + nextCursor, + marketId: apiParams.market, + assetId: apiParams.assetId, + }, data: { + actionName: 'POLYMARKET_GET_ACTIVE_ORDERS', ...apiParams, orders: actualOrders, nextCursor, timestamp: new Date().toISOString(), }, + success: true, }; - if (callback) await callback(responseContent); - return responseContent; + if (callback) await callback({ text: responseResult.text, data: responseResult.data }); + return responseResult; } catch (error) { logger.error('[getActiveOrdersAction] Error fetching active orders:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error fetching active orders for market ${apiParams.market}**: ${errorMessage}`, - actions: ['POLYMARKET_GET_ACTIVE_ORDERS'], - data: { error: errorMessage, ...apiParams, timestamp: new Date().toISOString() }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ACTIVE_ORDERS', + error: errorMessage, + ...apiParams, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/getAllApiKeys.ts b/src/actions/getAllApiKeys.ts index ca4475c..defb642 100644 --- a/src/actions/getAllApiKeys.ts +++ b/src/actions/getAllApiKeys.ts @@ -1,4 +1,4 @@ -import { IAgentRuntime, Memory, State, HandlerCallback, logger } from '@elizaos/core'; +import { IAgentRuntime, Memory, State, HandlerCallback, logger, ActionResult } from '@elizaos/core'; import { initializeClobClientWithCreds } from '../utils/clobClient'; export interface ApiKeyData { @@ -104,7 +104,7 @@ export const getAllApiKeysAction = { state: State, options: any, callback: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getAllApiKeysAction] Handler called!'); try { @@ -115,12 +115,15 @@ export const getAllApiKeysAction = { runtime.getSetting('CLOB_API_PASSPHRASE') || runtime.getSetting('CLOB_PASS_PHRASE'); logger.info('[getAllApiKeysAction] Checking for API credentials...'); - logger.info('[getAllApiKeysAction] Found credentials:', { - hasApiKey: !!apiKey, - hasApiSecret: !!apiSecret, - hasApiPassphrase: !!apiPassphrase, - apiKeySource: apiKey ? (runtime.getSetting('CLOB_API_KEY') ? 'runtime' : 'env') : 'none', - }); + logger.info( + '[getAllApiKeysAction] Found credentials:', + JSON.stringify({ + hasApiKey: !!apiKey, + hasApiSecret: !!apiSecret, + hasApiPassphrase: !!apiPassphrase, + apiKeySource: apiKey ? (runtime.getSetting('CLOB_API_KEY') ? 'runtime' : 'env') : 'none', + }) + ); if (!apiKey || !apiSecret || !apiPassphrase) { const helpMessage = `❌ **Failed to Retrieve API Keys** @@ -146,17 +149,28 @@ export const getAllApiKeysAction = { • CLOB_SECRET (instead of CLOB_API_SECRET) • CLOB_PASS_PHRASE (instead of CLOB_API_PASSPHRASE)`; + const errorResult: ActionResult = { + text: helpMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_API_KEYS', + success: false, + error: 'API credentials not found - see setup instructions above', + }, + success: false, + error: new Error('API credentials not found'), + }; + if (callback) { callback({ text: helpMessage, - action: 'POLYMARKET_GET_API_KEYS', - data: { - success: false, - error: 'API credentials not found - see setup instructions above', - }, + data: errorResult.data, }); } - return; + return errorResult; } // Initialize CLOB client with API credentials @@ -292,16 +306,32 @@ export const getAllApiKeysAction = { - Each API key provides L2 authentication for order posting - You can revoke unused keys with the DELETE_API_KEY action`; + // Create ActionResult + const successResult: ActionResult = { + text: successMessage, + values: { + success: true, + apiKeys: responseData.apiKeys, + count: responseData.count, + address: responseData.address, + }, + data: { + actionName: 'POLYMARKET_GET_API_KEYS', + ...responseData, + }, + success: true, + }; + // Call callback with success response if (callback) { await callback({ text: successMessage, - action: 'POLYMARKET_GET_API_KEYS', - data: responseData, + data: successResult.data, }); } logger.info('[getAllApiKeysAction] API keys retrieval completed successfully'); + return successResult; } catch (error) { logger.error('[getAllApiKeysAction] Error retrieving API keys:', error); @@ -320,16 +350,29 @@ export const getAllApiKeysAction = { • Verify your CLOB_API_KEY, CLOB_API_SECRET, and CLOB_API_PASSPHRASE are correct • Check your network connection and try again`; + const errorResult: ActionResult = { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_API_KEYS', + success: false, + error: error instanceof Error ? error.message : 'Unknown error', + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), + }; + if (callback) { callback({ text: errorMessage, - action: 'POLYMARKET_GET_API_KEYS', - data: { - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - }, + data: errorResult.data, }); } + + return errorResult; } }, }; diff --git a/src/actions/getBestPrice.ts b/src/actions/getBestPrice.ts index 20dbcae..26d6a36 100644 --- a/src/actions/getBestPrice.ts +++ b/src/actions/getBestPrice.ts @@ -1,13 +1,11 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -66,7 +64,7 @@ export const getBestPriceAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getBestPriceAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -74,16 +72,24 @@ export const getBestPriceAction: Action = { if (!clobApiUrl) { const errorMessage = 'CLOB_API_URL is required in configuration.'; logger.error(`[getBestPriceAction] Configuration error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['GET_BEST_PRICE'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'GET_BEST_PRICE', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } let tokenId: string; @@ -133,21 +139,29 @@ export const getBestPriceAction: Action = { const errorMessage = 'Please provide a token ID to get the price for.'; logger.error(`[getBestPriceAction] Token ID extraction failed`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide a token ID in your request. Examples: • "Get best price for token 123456 on buy side" • "What's the sell price for market token 789012?" • "Show me the best bid for 456789"`, - actions: ['POLYMARKET_GET_BEST_PRICE'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_BEST_PRICE', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } } @@ -182,10 +196,18 @@ ${ : 'This is the best price you would receive when selling this token.' }`; - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_BEST_PRICE'], + values: { + success: true, + tokenId, + side, + price: priceResponse.price, + formattedPrice, + percentagePrice, + }, data: { + actionName: 'POLYMARKET_GET_BEST_PRICE', tokenId, side, price: priceResponse.price, @@ -193,18 +215,19 @@ ${ percentagePrice, timestamp: new Date().toISOString(), }, + success: true, }; if (callback) { - await callback(responseContent); + await callback({ text: responseResult.text, data: responseResult.data }); } - return responseContent; + return responseResult; } catch (error) { logger.error('[getBestPriceAction] Error fetching price:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error getting best price**: ${errorMessage} Please check: @@ -214,19 +237,25 @@ Please check: **Token ID**: \`${tokenId}\` **Side**: \`${side}\``, - actions: ['POLYMARKET_GET_BEST_PRICE'], + values: { + success: false, + error: true, + }, data: { + actionName: 'POLYMARKET_GET_BEST_PRICE', error: errorMessage, tokenId, side, timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw error; + return errorResult; } }, diff --git a/src/actions/getClobMarkets.ts b/src/actions/getClobMarkets.ts index 58a477e..668ae20 100644 --- a/src/actions/getClobMarkets.ts +++ b/src/actions/getClobMarkets.ts @@ -1,11 +1,11 @@ import { type Action, + type ActionResult, type IAgentRuntime, type Memory, type State, type HandlerCallback, logger, - ModelType, ActionExample, } from '@elizaos/core'; @@ -58,7 +58,7 @@ export const getClobMarkets: Action = { state: State | undefined, _options: any, callback?: HandlerCallback - ): Promise => { + ): Promise => { try { logger.info('[getClobMarkets] Starting CLOB markets retrieval'); @@ -86,7 +86,10 @@ export const getClobMarkets: Action = { // Call CLOB API to get markets logger.info('[getClobMarkets] Fetching CLOB markets from API'); - const marketsResponse = await clobClient.getMarkets('', { + // NOTE: The TypeScript types for getMarkets only show next_cursor parameter, + // but the actual API accepts additional filter parameters like category, active, limit. + // We cast to any to bypass the incomplete type definition. + const marketsResponse = await (clobClient as any).getMarkets('', { category: params.category, active: params.active, limit: params.limit, @@ -101,21 +104,35 @@ export const getClobMarkets: Action = { // Format response message const responseMessage = formatClobMarketsResponse(markets, totalCount, nextCursor, params); + const successResult: ActionResult = { + text: responseMessage, + values: { + success: true, + markets: markets, + count: totalCount, + nextCursor: nextCursor, + filters: params, + }, + data: { + actionName: 'POLYMARKET_GET_CLOB_MARKETS', + action: 'clob_markets_retrieved', + markets: markets, + count: totalCount, + next_cursor: nextCursor, + filters: params, + timestamp: new Date().toISOString(), + }, + success: true, + }; + if (callback) { await callback({ text: responseMessage, - content: { - action: 'clob_markets_retrieved', - markets: markets, - count: totalCount, - next_cursor: nextCursor, - filters: params, - timestamp: new Date().toISOString(), - }, + data: successResult.data, }); } - return true; + return successResult; } catch (error) { logger.error('[getClobMarkets] Error retrieving CLOB markets:', error); @@ -126,18 +143,30 @@ Please check: • Network connectivity is available • API service is operational`; + const errorResult: ActionResult = { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_CLOB_MARKETS', + action: 'clob_markets_error', + error: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), + }; + if (callback) { await callback({ text: errorMessage, - content: { - action: 'clob_markets_error', - error: error instanceof Error ? error.message : 'Unknown error', - timestamp: new Date().toISOString(), - }, + data: errorResult.data, }); } - return false; + return errorResult; } }, diff --git a/src/actions/getMarketDetails.ts b/src/actions/getMarketDetails.ts index dbb75c2..b988e71 100644 --- a/src/actions/getMarketDetails.ts +++ b/src/actions/getMarketDetails.ts @@ -1,13 +1,11 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -52,7 +50,7 @@ export const getMarketDetailsAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getMarketDetailsAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -60,16 +58,24 @@ export const getMarketDetailsAction: Action = { if (!clobApiUrl) { const errorMessage = 'CLOB_API_URL is required in configuration.'; logger.error(`[getMarketDetailsAction] Configuration error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['POLYMARKET_GET_MARKET_DETAILS'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_MARKET_DETAILS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } let conditionId = ''; @@ -86,20 +92,28 @@ export const getMarketDetailsAction: Action = { if (llmResult?.error) { const errorMessage = 'Market identifier not found. Please specify a market condition ID.'; logger.error(`[getMarketDetailsAction] Parameter extraction error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide a market condition ID in your request. For example: • "Show me market 0x1234567890abcdef..." • "Get details for condition ID 0xabc123..."`, - actions: ['POLYMARKET_GET_MARKET_DETAILS'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_MARKET_DETAILS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } conditionId = llmResult?.marketId || ''; @@ -118,20 +132,28 @@ Please provide a market condition ID in your request. For example: 'Unable to extract market condition ID from your message. Please provide a valid condition ID.'; logger.error('[getMarketDetailsAction] LLM parameter extraction failed:', error); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide a market condition ID in your request. For example: • "Show me market 0x1234567890abcdef..." • "Get details for condition ID 0xabc123..."`, - actions: ['POLYMARKET_GET_MARKET_DETAILS'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_MARKET_DETAILS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } try { @@ -198,21 +220,27 @@ Please provide a market condition ID in your request. For example: responseText += `• FPMM Address: \`${market.fpmm}\`\n`; } - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_MARKET_DETAILS'], + values: { + success: true, + market, + conditionId, + }, data: { + actionName: 'POLYMARKET_GET_MARKET_DETAILS', market, conditionId, timestamp: new Date().toISOString(), }, + success: true, }; if (callback) { - await callback(responseContent); + await callback({ text: responseResult.text, data: responseResult.data }); } - return responseContent; + return responseResult; } catch (error) { logger.error('[getMarketDetailsAction] Error fetching market details:', error); @@ -220,7 +248,7 @@ Please provide a market condition ID in your request. For example: error instanceof Error ? error.message : 'Unknown error occurred while fetching market details'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error retrieving market details**: ${errorMessage} Please check: @@ -230,18 +258,24 @@ Please check: • Polymarket CLOB service is operational **Condition ID provided**: \`${conditionId}\``, - actions: ['POLYMARKET_GET_MARKET_DETAILS'], + values: { + success: false, + error: true, + }, data: { + actionName: 'POLYMARKET_GET_MARKET_DETAILS', error: errorMessage, conditionId, timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw error; + return errorResult; } }, diff --git a/src/actions/getMidpointPrice.ts b/src/actions/getMidpointPrice.ts index 46d241c..4ad8e68 100644 --- a/src/actions/getMidpointPrice.ts +++ b/src/actions/getMidpointPrice.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -64,7 +64,7 @@ export const getMidpointPriceAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getMidpointPriceAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -72,16 +72,24 @@ export const getMidpointPriceAction: Action = { if (!clobApiUrl) { const errorMessage = 'CLOB_API_URL is required in configuration.'; logger.error(`[getMidpointPriceAction] Configuration error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['POLYMARKET_GET_MIDPOINT_PRICE'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_MIDPOINT_PRICE', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } let tokenId: string; @@ -120,21 +128,29 @@ export const getMidpointPriceAction: Action = { const errorMessage = 'Please provide a token ID to get the midpoint price for.'; logger.error(`[getMidpointPriceAction] Token ID extraction failed`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide a token ID in your request. Examples: • "Get midpoint price for token 123456" • "What's the midpoint for market token 789012?" • "Show me the mid price for 456789"`, - actions: ['POLYMARKET_GET_MIDPOINT_PRICE'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_MIDPOINT_PRICE', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } } @@ -157,28 +173,36 @@ Please provide a token ID in your request. Examples: The midpoint price represents the halfway point between the best bid and best ask prices, providing a fair market value estimate for this prediction market token.`; - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_MIDPOINT_PRICE'], + values: { + success: true, + tokenId, + midpoint: midpointResponse.mid, + formattedPrice, + percentagePrice, + }, data: { + actionName: 'POLYMARKET_GET_MIDPOINT_PRICE', tokenId, midpoint: midpointResponse.mid, formattedPrice, percentagePrice, timestamp: new Date().toISOString(), }, + success: true, }; if (callback) { - await callback(responseContent); + await callback({ text: responseResult.text, data: responseResult.data }); } - return responseContent; + return responseResult; } catch (error) { logger.error('[getMidpointPriceAction] Error fetching midpoint price:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error getting midpoint price**: ${errorMessage} Please check: @@ -187,18 +211,24 @@ Please check: • Network connectivity is available **Token ID**: \`${tokenId}\``, - actions: ['POLYMARKET_GET_MIDPOINT_PRICE'], + values: { + success: false, + error: true, + }, data: { + actionName: 'POLYMARKET_GET_MIDPOINT_PRICE', error: errorMessage, tokenId, timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw error; + return errorResult; } }, diff --git a/src/actions/getOpenMarkets.ts b/src/actions/getOpenMarkets.ts index eba43e0..b1f1d22 100644 --- a/src/actions/getOpenMarkets.ts +++ b/src/actions/getOpenMarkets.ts @@ -1,12 +1,12 @@ import { type Action, + type ActionResult, type IAgentRuntime, type Memory, type State, type HandlerCallback, logger, - ModelType, - ActionExample, + type ActionExample, } from '@elizaos/core'; import { initializeClobClient } from '../utils/clobClient.js'; @@ -56,7 +56,7 @@ export const getOpenMarkets: Action = { state: State | undefined, _options: any, callback?: HandlerCallback - ): Promise => { + ): Promise => { try { logger.info('[getOpenMarkets] Starting open markets retrieval'); @@ -157,22 +157,37 @@ export const getOpenMarkets: Action = { params ); + const successResult: ActionResult = { + text: responseMessage, + values: { + success: true, + markets: finalMarketsToReturn, + count: finalMarketsToReturn.length, + totalOpen: openMarkets.length, + totalFetched: allMarkets.length, + filters: params, + }, + data: { + actionName: 'POLYMARKET_GET_OPEN_MARKETS', + action: 'open_markets_retrieved', + markets: finalMarketsToReturn, + count: finalMarketsToReturn.length, + total_open: openMarkets.length, + total_fetched: allMarkets.length, + filters: params, + timestamp: new Date().toISOString(), + }, + success: true, + }; + if (callback) { await callback({ text: responseMessage, - content: { - action: 'open_markets_retrieved', - markets: finalMarketsToReturn, - count: finalMarketsToReturn.length, - total_open: openMarkets.length, - total_fetched: allMarkets.length, - filters: params, - timestamp: new Date().toISOString(), - }, + data: successResult.data, }); } - return true; + return successResult; } catch (error) { logger.error('[getOpenMarkets] Error retrieving open markets:', error); @@ -183,18 +198,30 @@ Please check: • Network connectivity is available • API service is operational`; + const errorResult: ActionResult = { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_OPEN_MARKETS', + action: 'open_markets_error', + error: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), + }; + if (callback) { await callback({ text: errorMessage, - content: { - action: 'open_markets_error', - error: error instanceof Error ? error.message : 'Unknown error', - timestamp: new Date().toISOString(), - }, + data: errorResult.data, }); } - return false; + return errorResult; } }, @@ -238,7 +265,7 @@ Please check: }, }, ], - ] as ActionExample[][], + ] satisfies ActionExample[][], }; /** diff --git a/src/actions/getOrderBookDepth.ts b/src/actions/getOrderBookDepth.ts index ca8ebce..57adaab 100644 --- a/src/actions/getOrderBookDepth.ts +++ b/src/actions/getOrderBookDepth.ts @@ -1,16 +1,14 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; -import { initializeClobClient, type BookParams } from '../utils/clobClient'; +import { initializeClobClient } from '../utils/clobClient'; import { getOrderBookDepthTemplate } from '../templates'; import type { OrderBook } from '../types'; @@ -51,7 +49,7 @@ export const getOrderBookDepthAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getOrderBookDepthAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -59,16 +57,24 @@ export const getOrderBookDepthAction: Action = { if (!clobApiUrl) { const errorMessage = 'CLOB_API_URL is required in configuration.'; logger.error(`[getOrderBookDepthAction] Configuration error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['GET_ORDER_BOOK_DEPTH'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'GET_ORDER_BOOK_DEPTH', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } let tokenIds: string[] = []; @@ -87,21 +93,29 @@ export const getOrderBookDepthAction: Action = { const errorMessage = 'Token identifiers not found. Please specify one or more token IDs for order book depth.'; logger.error(`[getOrderBookDepthAction] Parameter extraction error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide one or more token IDs in your request. Examples: • "Show order book depth for token 123456" • "Get depth for tokens 123456, 789012" • "ORDER_BOOK_DEPTH 345678 999999"`, - actions: ['GET_ORDER_BOOK_DEPTH'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'GET_ORDER_BOOK_DEPTH', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } tokenIds = llmResult?.tokenIds || []; @@ -124,9 +138,23 @@ Please provide one or more token IDs in your request. Examples: } tokenIds = validTokenIds; } catch (error) { - // Check if this is our specific error message and re-throw it + // This error was already handled above + // Return the error if it's our specific error message if (error instanceof Error && error.message.includes('Token identifiers not found')) { - throw error; + const errorResult: ActionResult = { + text: error.message, + values: { + success: false, + error: true, + }, + data: { + actionName: 'GET_ORDER_BOOK_DEPTH', + error: error.message, + }, + success: false, + error: error, + }; + return errorResult; } logger.warn('[getOrderBookDepthAction] LLM extraction failed, trying regex fallback'); @@ -160,21 +188,29 @@ Please provide one or more token IDs in your request. Examples: 'Unable to extract token IDs from your message. Please provide valid token IDs.'; logger.error('[getOrderBookDepthAction] Token extraction failed:', error); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide one or more token IDs in your request. Examples: • "Show order book depth for token 123456" • "Get depth for tokens 123456, 789012" • "ORDER_BOOK_DEPTH 345678 999999"`, - actions: ['GET_ORDER_BOOK_DEPTH'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'GET_ORDER_BOOK_DEPTH', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } } @@ -182,11 +218,11 @@ Please provide one or more token IDs in your request. Examples: // Initialize CLOB client const clobClient = await initializeClobClient(runtime); - // Prepare book parameters - const bookParams: BookParams[] = tokenIds.map((tokenId) => ({ token_id: tokenId })); + // Prepare book parameters - cast to any since the library accepts it without side + const bookParams = tokenIds.map((tokenId) => ({ token_id: tokenId })); // Fetch order book data - const orderBooks: OrderBook[] = await clobClient.getOrderBooks(bookParams); + const orderBooks: OrderBook[] = await clobClient.getOrderBooks(bookParams as any); if (!orderBooks || orderBooks.length === 0) { throw new Error(`No order books found for the provided token IDs: ${tokenIds.join(', ')}`); @@ -236,10 +272,22 @@ Please provide one or more token IDs in your request. Examples: responseText += `• Total Bid Levels: ${totalBids}\n`; responseText += `• Total Ask Levels: ${totalAsks}\n`; - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_ORDER_BOOK_DEPTH'], + values: { + success: true, + orderBooks, + tokenIds, + summary: { + tokensRequested: tokenIds.length, + orderBooksFound: orderBooks.length, + activeBooks, + totalBids, + totalAsks, + }, + }, data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK_DEPTH', orderBooks, tokenIds, summary: { @@ -251,13 +299,14 @@ Please provide one or more token IDs in your request. Examples: }, timestamp: new Date().toISOString(), }, + success: true, }; if (callback) { - await callback(responseContent); + await callback({ text: responseResult.text, data: responseResult.data }); } - return responseContent; + return responseResult; } catch (error) { logger.error('[getOrderBookDepthAction] Error fetching order books:', error); @@ -265,7 +314,7 @@ Please provide one or more token IDs in your request. Examples: error instanceof Error ? error.message : 'Unknown error occurred while fetching order books'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error retrieving order book depth**: ${errorMessage} Please check: @@ -275,18 +324,24 @@ Please check: • Polymarket CLOB service is operational **Token IDs provided**: \`${tokenIds.join(', ')}\``, - actions: ['POLYMARKET_GET_ORDER_BOOK_DEPTH'], + values: { + success: false, + error: true, + }, data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK_DEPTH', error: errorMessage, tokenIds, timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw error; + return errorResult; } }, diff --git a/src/actions/getOrderBookSummary.ts b/src/actions/getOrderBookSummary.ts index 79f3bbb..a217035 100644 --- a/src/actions/getOrderBookSummary.ts +++ b/src/actions/getOrderBookSummary.ts @@ -1,13 +1,12 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -56,7 +55,7 @@ export const getOrderBookSummaryAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getOrderBookSummaryAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -73,7 +72,19 @@ export const getOrderBookSummaryAction: Action = { if (callback) { await callback(errorContent); } - throw new Error(errorMessage); + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } let tokenId = ''; @@ -106,7 +117,19 @@ Please provide a token ID in your request. For example: if (callback) { await callback(errorContent); } - throw new Error(errorMessage); + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } tokenId = llmResult?.tokenId || ''; @@ -127,7 +150,20 @@ Please provide a token ID in your request. For example: error.message === 'Token identifier not found. Please specify a token ID for the order book.' ) { - throw error; + const errorMessage = error.message; + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + error: errorMessage, + }, + success: false, + error: error, + }; } logger.warn('[getOrderBookSummaryAction] LLM extraction failed, trying regex fallback'); @@ -160,7 +196,19 @@ Please provide a token ID in your request. For example: if (callback) { await callback(errorContent); } - throw new Error(errorMessage); + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } } @@ -265,7 +313,36 @@ Please provide a token ID in your request. For example: await callback(responseContent); } - return responseContent; + return { + text: responseText, + values: { + success: true, + tokenId, + bidCount, + askCount, + bestBidPrice: bestBid?.price, + bestAskPrice: bestAsk?.price, + spread, + totalBidSize, + totalAskSize, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + orderBook, + tokenId, + summary: { + bidCount, + askCount, + bestBid, + bestAsk, + spread, + totalBidSize, + totalAskSize, + }, + timestamp: new Date().toISOString(), + }, + success: true, + }; } catch (error) { logger.error('[getOrderBookSummaryAction] Error fetching order book:', error); @@ -292,7 +369,22 @@ Please check: if (callback) { await callback(errorContent); } - throw error; + return { + text: errorContent.text, + values: { + success: false, + error: true, + tokenId, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_BOOK', + error: errorMessage, + tokenId, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), + }; } }, diff --git a/src/actions/getOrderDetails.ts b/src/actions/getOrderDetails.ts index 0f6c5e9..7098b17 100644 --- a/src/actions/getOrderDetails.ts +++ b/src/actions/getOrderDetails.ts @@ -1,5 +1,6 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, @@ -88,7 +89,7 @@ export const getOrderDetailsAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getOrderDetailsAction] Handler called!'); let orderId: string | undefined; @@ -120,7 +121,19 @@ export const getOrderDetailsAction: Action = { data: { error: errorMessage }, }; if (callback) await callback(errorContent); - throw new Error(errorMessage); + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_DETAILS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } } @@ -133,7 +146,19 @@ export const getOrderDetailsAction: Action = { data: { error: errorMessage }, }; if (callback) await callback(errorContent); - throw new Error(errorMessage); + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_DETAILS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } logger.info(`[getOrderDetailsAction] Attempting to fetch details for Order ID: ${orderId}`); @@ -150,7 +175,22 @@ export const getOrderDetailsAction: Action = { data: { error: 'Order not found', orderId, timestamp: new Date().toISOString() }, }; if (callback) await callback(notFoundContent); - return notFoundContent; + return { + text: notFoundContent.text, + values: { + success: false, + orderFound: false, + orderId, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_DETAILS', + error: 'Order not found', + orderId, + timestamp: new Date().toISOString(), + }, + success: false, + error: new Error('Order not found'), + }; } const displayOrder = order as OfficialOpenOrder; @@ -177,7 +217,26 @@ export const getOrderDetailsAction: Action = { }; if (callback) await callback(responseContent); - return responseContent; + return { + text: responseText, + values: { + success: true, + orderId: displayOrder.order_id, + marketId: displayOrder.market_id, + tokenId: displayOrder.token_id, + side: displayOrder.side, + status: displayOrder.status, + price: displayOrder.price, + size: displayOrder.size, + filledSize: displayOrder.filled_size, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_DETAILS', + order: displayOrder, + timestamp: new Date().toISOString(), + }, + success: true, + }; } catch (error) { logger.error(`[getOrderDetailsAction] Error fetching order ${orderId}:`, error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; @@ -187,7 +246,22 @@ export const getOrderDetailsAction: Action = { data: { error: errorMessage, orderId, timestamp: new Date().toISOString() }, }; if (callback) await callback(errorContent); - throw error; + return { + text: errorContent.text, + values: { + success: false, + error: true, + orderId, + }, + data: { + actionName: 'POLYMARKET_GET_ORDER_DETAILS', + error: errorMessage, + orderId, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), + }; } }, diff --git a/src/actions/getPriceHistory.ts b/src/actions/getPriceHistory.ts index cd385c5..63dee2a 100644 --- a/src/actions/getPriceHistory.ts +++ b/src/actions/getPriceHistory.ts @@ -1,12 +1,12 @@ import { type Action, + type ActionResult, type IAgentRuntime, type Memory, type State, type HandlerCallback, logger, - ModelType, - ActionExample, + type ActionExample, } from '@elizaos/core'; import { initializeClobClient } from '../utils/clobClient.js'; @@ -93,7 +93,7 @@ export const getPriceHistory: Action = { state: State | undefined, _options: any, callback?: HandlerCallback - ): Promise => { + ): Promise => { try { logger.info('[getPriceHistory] Starting price history retrieval'); @@ -118,12 +118,56 @@ export const getPriceHistory: Action = { } } catch (error) { logger.error('[getPriceHistory] LLM extraction failed:', error); - throw new Error('Failed to extract token ID from message. Please specify a token ID.'); + const errorMessage = 'Failed to extract token ID from message. Please specify a token ID.'; + if (callback) { + await callback({ + text: `❌ **Error**: ${errorMessage}`, + content: { + action: 'POLYMARKET_PRICE_HISTORY_ERROR', + error: errorMessage, + }, + }); + } + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_PRICE_HISTORY', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } // Validate required parameters if (!params.tokenId) { - throw new Error('Token ID is required for price history retrieval'); + const errorMessage = 'Token ID is required for price history retrieval'; + if (callback) { + await callback({ + text: `❌ **Error**: ${errorMessage}`, + content: { + action: 'POLYMARKET_PRICE_HISTORY_ERROR', + error: errorMessage, + }, + }); + } + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_PRICE_HISTORY', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } // Set default interval if not provided @@ -133,7 +177,7 @@ export const getPriceHistory: Action = { logger.info( `[getPriceHistory] Fetching price history for token ${params.tokenId} with interval ${interval}` ); - const priceHistory = await clobClient.getPricesHistory({ + const priceHistory = await (clobClient as any).getPricesHistory({ token_id: params.tokenId, interval: interval as any, }); @@ -161,7 +205,33 @@ export const getPriceHistory: Action = { }); } - return true; + // Calculate some stats for values + const prices = priceHistory?.map((p: PricePoint) => p.p) || []; + const latestPrice = priceHistory?.length > 0 ? priceHistory[0].p : undefined; + const highestPrice = prices.length > 0 ? Math.max(...prices) : undefined; + const lowestPrice = prices.length > 0 ? Math.min(...prices) : undefined; + + return { + text: responseMessage, + values: { + success: true, + tokenId: params.tokenId, + interval: interval, + pointsCount: priceHistory?.length || 0, + latestPrice, + highestPrice, + lowestPrice, + }, + data: { + actionName: 'POLYMARKET_GET_PRICE_HISTORY', + tokenId: params.tokenId, + interval: interval, + priceHistory: priceHistory, + pointsCount: priceHistory?.length || 0, + timestamp: new Date().toISOString(), + }, + success: true, + }; } catch (error) { logger.error('[getPriceHistory] Error retrieving price history:', error); @@ -184,7 +254,20 @@ Please check: }); } - return false; + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_PRICE_HISTORY', + error: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error('Unknown error'), + }; } }, @@ -228,7 +311,7 @@ Please check: }, }, ], - ] as ActionExample[][], + ] satisfies ActionExample[][], }; /** diff --git a/src/actions/getSamplingMarkets.ts b/src/actions/getSamplingMarkets.ts index 0f23685..a4f9b7e 100644 --- a/src/actions/getSamplingMarkets.ts +++ b/src/actions/getSamplingMarkets.ts @@ -1,12 +1,12 @@ import { type Action, + type ActionResult, type IAgentRuntime, type Memory, type State, type HandlerCallback, logger, - ModelType, - ActionExample, + type ActionExample, } from '@elizaos/core'; import { initializeClobClient } from '../utils/clobClient.js'; @@ -56,7 +56,7 @@ export const getSamplingMarkets: Action = { state: State | undefined, _options: any, callback?: HandlerCallback - ): Promise => { + ): Promise => { try { logger.info('[getSamplingMarkets] Starting sampling markets retrieval'); @@ -108,7 +108,23 @@ export const getSamplingMarkets: Action = { }); } - return true; + return { + text: responseMessage, + values: { + success: true, + marketCount: markets.length, + totalCount, + hasMoreResults: !!nextCursor && nextCursor !== 'LTE=', + }, + data: { + actionName: 'POLYMARKET_GET_SAMPLING_MARKETS', + markets: markets, + count: totalCount, + next_cursor: nextCursor, + timestamp: new Date().toISOString(), + }, + success: true, + }; } catch (error) { logger.error('[getSamplingMarkets] Error retrieving sampling markets:', error); @@ -130,7 +146,20 @@ Please check: }); } - return false; + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_SAMPLING_MARKETS', + error: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error('Unknown error'), + }; } }, @@ -174,7 +203,7 @@ Please check: }, }, ], - ] as ActionExample[][], + ] satisfies ActionExample[][], }; /** diff --git a/src/actions/getSimplifiedMarkets.ts b/src/actions/getSimplifiedMarkets.ts index 99500f8..ebda050 100644 --- a/src/actions/getSimplifiedMarkets.ts +++ b/src/actions/getSimplifiedMarkets.ts @@ -1,13 +1,12 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -53,7 +52,7 @@ export const getSimplifiedMarketsAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getSimplifiedMarketsAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -70,7 +69,19 @@ export const getSimplifiedMarketsAction: Action = { if (callback) { await callback(errorContent); } - throw new Error(errorMessage); + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_SIMPLIFIED_MARKETS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } let nextCursor = ''; @@ -183,7 +194,26 @@ export const getSimplifiedMarketsAction: Action = { await callback(responseContent); } - return responseContent; + return { + text: responseText, + values: { + success: true, + marketCount: validMarkets.length, + totalCount: response.count || marketCount, + filteredCount: marketCount - validMarkets.length, + hasMoreResults: !!response.next_cursor && response.next_cursor !== 'LTE=', + }, + data: { + actionName: 'POLYMARKET_GET_SIMPLIFIED_MARKETS', + markets: validMarkets, + count: validMarkets.length, + total: response.count || marketCount, + filtered: marketCount - validMarkets.length, + next_cursor: response.next_cursor, + limit: response.limit, + }, + success: true, + }; } catch (error) { logger.error('[getSimplifiedMarketsAction] Error fetching simplified markets:', error); @@ -208,7 +238,20 @@ Please check: if (callback) { await callback(errorContent); } - throw error; + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_SIMPLIFIED_MARKETS', + error: errorMessage, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), + }; } }, diff --git a/src/actions/getSpread.ts b/src/actions/getSpread.ts index dd1aa63..a5d58b7 100644 --- a/src/actions/getSpread.ts +++ b/src/actions/getSpread.ts @@ -1,13 +1,11 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -55,7 +53,7 @@ export const getSpreadAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { try { logger.info('[getSpreadAction] Starting spread retrieval process'); @@ -104,21 +102,29 @@ export const getSpreadAction: Action = { const errorMessage = 'Please provide a token ID to get the spread for.'; logger.error(`[getSpreadAction] Token ID extraction failed`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide a token ID in your request. Examples: • "Get spread for token 123456" • "What's the spread for market token 789012?" • "Show me the bid-ask spread for 456789"`, - actions: ['POLYMARKET_GET_SPREAD'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_SPREAD', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } } @@ -144,23 +150,31 @@ Please provide a token ID in your request. Examples: *The spread represents the difference between the best ask and best bid prices.*`; - const responseContent: Content = { + const responseResult: ActionResult = { text: successMessage, - actions: ['POLYMARKET_GET_SPREAD'], + values: { + success: true, + tokenId, + spread: spreadResponse.spread, + formattedSpread, + percentageSpread, + }, data: { + actionName: 'POLYMARKET_GET_SPREAD', tokenId, spread: spreadResponse.spread, formattedSpread, percentageSpread, timestamp: new Date().toISOString(), }, + success: true, }; if (callback) { - await callback(responseContent); + await callback({ text: responseResult.text, data: responseResult.data }); } - return responseContent; + return responseResult; } catch (error) { logger.error('[getSpreadAction] Error getting spread:', error); @@ -171,19 +185,25 @@ Please check: • CLOB_API_URL is correctly configured • Network connectivity is available`; - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['POLYMARKET_GET_SPREAD'], + values: { + success: false, + error: true, + }, data: { + actionName: 'POLYMARKET_GET_SPREAD', error: error instanceof Error ? error.message : String(error), timestamp: new Date().toISOString(), }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw error; + return errorResult; } }, examples: [ diff --git a/src/actions/getTradeHistory.ts b/src/actions/getTradeHistory.ts index 1ea5f19..c3b5df1 100644 --- a/src/actions/getTradeHistory.ts +++ b/src/actions/getTradeHistory.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -125,7 +125,7 @@ export const getTradeHistoryAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[getTradeHistoryAction] Handler called!'); // API key/signer should be handled by initializeClobClient now based on new strategy @@ -216,10 +216,17 @@ export const getTradeHistoryAction: Action = { } } - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - actions: ['POLYMARKET_GET_TRADE_HISTORY'], + values: { + success: true, + trades: tradesResponse.trades, + nextCursor: tradesResponse.next_cursor, + count: tradesResponse.count, + limit: tradesResponse.limit, + }, data: { + actionName: 'POLYMARKET_GET_TRADE_HISTORY', ...apiParams, trades: tradesResponse.trades, nextCursor: tradesResponse.next_cursor, @@ -227,20 +234,31 @@ export const getTradeHistoryAction: Action = { limit: tradesResponse.limit, timestamp: new Date().toISOString(), }, + success: true, }; - if (callback) await callback(responseContent); - return responseContent; + if (callback) await callback({ text: responseResult.text, data: responseResult.data }); + return responseResult; } catch (error) { logger.error('[getTradeHistoryAction] Error fetching trade history:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error fetching trade history**: ${errorMessage}`, - actions: ['POLYMARKET_GET_TRADE_HISTORY'], - data: { error: errorMessage, params: apiParams, timestamp: new Date().toISOString() }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_TRADE_HISTORY', + error: errorMessage, + params: apiParams, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/handleAuthentication.ts b/src/actions/handleAuthentication.ts index 0a0dfe6..55ccd85 100644 --- a/src/actions/handleAuthentication.ts +++ b/src/actions/handleAuthentication.ts @@ -1,6 +1,6 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, @@ -64,7 +64,7 @@ export const handleAuthenticationAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[handleAuthenticationAction] Handler called.'); const params = (message.content?.data as HandleAuthenticationParams) || {}; @@ -81,8 +81,22 @@ export const handleAuthenticationAction: Action = { const errMsg = 'A private key is required to derive API keys. Provide privateKeyInput parameter or set WALLET_PRIVATE_KEY/POLYMARKET_PRIVATE_KEY in agent settings.'; logger.error(`[handleAuthenticationAction] ${errMsg}`); - if (callback) await callback({ text: `❌ Error: ${errMsg}` }); - throw new Error(errMsg); + const errorResult: ActionResult = { + text: `❌ Error: ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_AUTHENTICATION', + error: errMsg, + timestamp: new Date().toISOString(), + }, + success: false, + error: new Error(errMsg), + }; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } try { @@ -103,10 +117,46 @@ export const handleAuthenticationAction: Action = { runtimeForClientInit as IAgentRuntime )) as ClobClient; - logger.info(`[handleAuthenticationAction] Deriving API key...`); + logger.info(`[handleAuthenticationAction] Creating or deriving API key...`); - const derivedApiCredsFromClient = - (await clientSignerInstance.deriveApiKey()) as unknown as RawDerivedApiKeyResponse; + // Get wallet address from the signer + const signerAddress = await (clientSignerInstance as any).signer?.getAddress?.(); + if (signerAddress) { + logger.info(`[handleAuthenticationAction] Using wallet address: ${signerAddress}`); + } + + let derivedApiCredsFromClient: RawDerivedApiKeyResponse; + + try { + // Use createOrDeriveApiKey() instead of deriveApiKey() + const rawResponse = await clientSignerInstance.createOrDeriveApiKey(); + logger.info( + `[handleAuthenticationAction] Raw API response received:`, + JSON.stringify(rawResponse) + ); + + derivedApiCredsFromClient = rawResponse as unknown as RawDerivedApiKeyResponse; + } catch (apiError) { + logger.error('[handleAuthenticationAction] API call failed:', apiError); + const apiErrorMessage = apiError instanceof Error ? apiError.message : 'Unknown API error'; + const errMsg = `Failed to create/derive API key from Polymarket: ${apiErrorMessage}`; + const errorResult: ActionResult = { + text: `❌ Error: ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_AUTHENTICATION', + error: errMsg, + timestamp: new Date().toISOString(), + }, + success: false, + error: new Error(errMsg), + }; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; + } // Add robust check for the response structure, using "key" and "secret" if ( @@ -116,13 +166,27 @@ export const handleAuthenticationAction: Action = { typeof derivedApiCredsFromClient.passphrase !== 'string' ) { logger.error( - '[handleAuthenticationAction] Invalid or incomplete response from deriveApiKey. Response: ', + '[handleAuthenticationAction] Invalid or incomplete response from createOrDeriveApiKey. Response: ', JSON.stringify(derivedApiCredsFromClient) ); const errMsg = 'Failed to derive valid API credentials from Polymarket. The response was unexpected.'; - if (callback) await callback({ text: `❌ Error: ${errMsg}` }); - throw new Error(errMsg); + const errorResult: ActionResult = { + text: `❌ Error: ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_AUTHENTICATION', + error: errMsg, + timestamp: new Date().toISOString(), + }, + success: false, + error: new Error(errMsg), + }; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } const storedCreds: DerivedApiKeyCreds = { @@ -167,22 +231,43 @@ export const handleAuthenticationAction: Action = { } responseText += `\n\nThese credentials have been set for immediate use by the Polymarket plugin.`; - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, - data: { derivedCreds: storedCreds, timestamp: new Date().toISOString() }, + values: { + success: true, + apiKeyId: storedCreds.key_id, + hasLabel: !!storedCreds.label, + hasExpiration: !!storedCreds.expiration_timestamp_ms, + }, + data: { + actionName: 'POLYMARKET_HANDLE_AUTHENTICATION', + derivedCreds: storedCreds, + timestamp: new Date().toISOString(), + }, + success: true, }; - if (callback) await callback(responseContent); - return responseContent; + if (callback) await callback({ text: responseResult.text, data: responseResult.data }); + return responseResult; } catch (error) { logger.error('[handleAuthenticationAction] Error deriving API key:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error deriving API key**: ${errorMessage}`, - data: { error: errorMessage, timestamp: new Date().toISOString() }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_AUTHENTICATION', + error: errorMessage, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/handleRealtimeUpdates.ts b/src/actions/handleRealtimeUpdates.ts index d3f9196..6f67451 100644 --- a/src/actions/handleRealtimeUpdates.ts +++ b/src/actions/handleRealtimeUpdates.ts @@ -1,5 +1,6 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, @@ -51,7 +52,7 @@ function registerEventHandlers( // wsClient.removeAllListeners('error'); // wsClient.removeAllListeners('close'); - wsClient.on('message', (rawData: WebSocket.RawData) => { + wsClient.on('message', (rawData: any) => { const messageString = rawData.toString(); logger.info(`[WS Event] Message: ${messageString}`); try { @@ -96,7 +97,7 @@ function registerEventHandlers( }); wsClient.on('error', (error: Error) => { - logger.error('[WS Event] Error:', error); + logger.error('[WS Event] Error:', error.message); const notification: Content = { text: `⚠️ **WebSocket Error**: ${error.message || 'An unknown WebSocket error occurred.'} `, data: { @@ -154,15 +155,28 @@ export const handleRealtimeUpdatesAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[handleRealtimeUpdatesAction] Handler called.'); if (!activeWebSocketClient) { const errorMsg = 'No active Polymarket WebSocket client (ws). Please run SETUP_WEBSOCKET first to connect.'; logger.warn(`[handleRealtimeUpdatesAction] ${errorMsg}`); - if (callback) await callback({ text: `🟡 ${errorMsg}` }); - return { text: `🟡 ${errorMsg}` }; + const warningResult: ActionResult = { + text: `🟡 ${errorMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_REALTIME_UPDATES', + error: errorMsg, + }, + success: false, + error: new Error(errorMsg), + }; + if (callback) await callback({ text: warningResult.text, data: warningResult.data }); + return warningResult; } try { @@ -181,24 +195,41 @@ export const handleRealtimeUpdatesAction: Action = { const responseText = '👂 Event listeners for Polymarket WebSocket (ws) updates are now active (or re-confirmed).'; - const responseContent: Content = { + const responseResult: ActionResult = { text: responseText, + values: { + success: true, + status: 'listening', + clientState: activeWebSocketClient.readyState, + }, data: { + actionName: 'POLYMARKET_HANDLE_REALTIME_UPDATES', status: 'listening', clientState: activeWebSocketClient.readyState, timestamp: new Date().toISOString(), }, + success: true, }; - return responseContent; + return responseResult; } catch (error: any) { logger.error('[handleRealtimeUpdatesAction] Error setting up event handlers:', error); const errorMessage = error.message || 'Unknown error.'; - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error setting up WebSocket event handlers**: ${errorMessage}`, - data: { error: errorMessage, timestamp: new Date().toISOString() }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_HANDLE_REALTIME_UPDATES', + error: errorMessage, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(String(error)), }; - if (callback) await callback(errorContent); - throw error; + if (callback) await callback({ text: errorResult.text, data: errorResult.data }); + return errorResult; } }, diff --git a/src/actions/placeOrder.ts b/src/actions/placeOrder.ts index 8664c88..3832718 100644 --- a/src/actions/placeOrder.ts +++ b/src/actions/placeOrder.ts @@ -1,13 +1,11 @@ import { type Action, - type Content, + type ActionResult, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -75,7 +73,7 @@ export const placeOrderAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[placeOrderAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -83,16 +81,24 @@ export const placeOrderAction: Action = { if (!clobApiUrl) { const errorMessage = 'CLOB_API_URL is required in configuration.'; logger.error(`[placeOrderAction] Configuration error: ${errorMessage}`); - const errorContent: Content = { + const errorResult: ActionResult = { text: errorMessage, - actions: ['PLACE_ORDER'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'PLACE_ORDER', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } let tokenId: string; @@ -170,7 +176,7 @@ export const placeOrderAction: Action = { const errorMessage = 'Please provide valid order parameters: token ID, price, and size.'; logger.error(`[placeOrderAction] Parameter extraction failed`); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Error**: ${errorMessage} Please provide order details in your request. Examples: @@ -187,14 +193,22 @@ Please provide order details in your request. Examples: **Optional parameters:** - Order type (GTC/limit, FOK/market, GTD, FAK) - Fee rate (in basis points)`, - actions: ['PLACE_ORDER'], - data: { error: errorMessage }, + values: { + success: false, + error: true, + }, + data: { + actionName: 'PLACE_ORDER', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } } @@ -223,12 +237,13 @@ Please provide order details in your request. Examples: feeRateBps: parseFloat(feeRateBps), // Convert to number }; - logger.info(`[placeOrderAction] Creating order with args:`, orderArgs); + logger.info('[placeOrderAction] Creating order with args:', JSON.stringify(orderArgs)); // Create the signed order with enhanced error handling let signedOrder; try { - signedOrder = await client.createOrder(orderArgs); + // Cast client to ClobClient type and use createOrder + signedOrder = await (client as ClobClient).createOrder(orderArgs as any); logger.info(`[placeOrderAction] Order created successfully`); } catch (createError) { logger.error(`[placeOrderAction] Error creating order:`, createError); @@ -236,29 +251,116 @@ Please provide order details in your request. Examples: // Check for specific error types if (createError instanceof Error) { if (createError.message.includes('minimum_tick_size')) { - throw new Error( - `Invalid market data: The market may not exist or be inactive. Please verify the token ID is correct and the market is active.` - ); + const errorMsg = `Invalid market data: The market may not exist or be inactive. Please verify the token ID is correct and the market is active.`; + logger.error(errorMsg); + const errorResult: ActionResult = { + text: `❌ **Order Error**: ${errorMsg}`, + values: { + success: false, + error: true, + tokenId, + side, + price, + size, + }, + data: { + actionName: 'PLACE_ORDER', + error: errorMsg, + orderDetails: { tokenId, side, price, size, orderType }, + }, + success: false, + error: createError, + }; + if (callback) { + await callback({ text: errorResult.text, data: errorResult.data }); + } + return errorResult; } if (createError.message.includes('undefined is not an object')) { - throw new Error( - `Market data unavailable: The token ID may be invalid or the market may be closed.` - ); + const errorMsg = `Market data unavailable: The token ID may be invalid or the market may be closed.`; + logger.error(errorMsg); + const errorResult: ActionResult = { + text: `❌ **Order Error**: ${errorMsg}`, + values: { + success: false, + error: true, + tokenId, + side, + price, + size, + }, + data: { + actionName: 'PLACE_ORDER', + error: errorMsg, + orderDetails: { tokenId, side, price, size, orderType }, + }, + success: false, + error: createError, + }; + if (callback) { + await callback({ text: errorResult.text, data: errorResult.data }); + } + return errorResult; } } - throw createError; + // Generic error fallback + const genericErrorMsg = + createError instanceof Error ? createError.message : 'Failed to create order'; + const errorResult: ActionResult = { + text: `❌ **Order Creation Failed**: ${genericErrorMsg}`, + values: { + success: false, + error: true, + tokenId, + side, + price, + size, + }, + data: { + actionName: 'PLACE_ORDER', + error: genericErrorMsg, + orderDetails: { tokenId, side, price, size, orderType }, + }, + success: false, + error: createError instanceof Error ? createError : new Error(genericErrorMsg), + }; + if (callback) { + await callback({ text: errorResult.text, data: errorResult.data }); + } + return errorResult; } // Post the order with enhanced error handling let orderResponse; try { - orderResponse = await client.postOrder(signedOrder, orderType as OrderType); + orderResponse = await (client as any).postOrder(signedOrder, orderType as OrderType); logger.info(`[placeOrderAction] Order posted successfully`); } catch (postError) { logger.error(`[placeOrderAction] Error posting order:`, postError); - throw new Error( - `Failed to submit order: ${postError instanceof Error ? postError.message : 'Unknown error'}` - ); + const postErrorMsg = `Failed to submit order: ${postError instanceof Error ? postError.message : 'Unknown error'}`; + logger.error(postErrorMsg); + const errorResult: ActionResult = { + text: `❌ **Order Submission Failed**: ${postErrorMsg}`, + values: { + success: false, + error: true, + tokenId, + side, + price, + size, + }, + data: { + actionName: 'PLACE_ORDER', + error: postErrorMsg, + orderDetails: { tokenId, side, price, size, orderType }, + }, + success: false, + error: postError instanceof Error ? postError : new Error(postErrorMsg), + }; + if (callback) { + await callback({ text: errorResult.text, data: errorResult.data }); + } + return errorResult; } // Format response based on success @@ -346,7 +448,7 @@ Please check your parameters and try again. Common issues: }; } - const responseContent: Content = { + const responseContent = { text: responseText, actions: ['POLYMARKET_PLACE_ORDER'], data: responseData, @@ -356,13 +458,35 @@ Please check your parameters and try again. Common issues: await callback(responseContent); } - return responseContent; + const isSuccess = orderResponse.success; + return { + text: responseText, + values: { + success: isSuccess, + orderId: orderResponse.orderId, + status: orderResponse.status, + tokenId, + side, + price, + size, + orderType, + totalValue: price * size, + }, + data: { + actionName: 'POLYMARKET_PLACE_ORDER', + ...responseData, + }, + success: isSuccess, + error: isSuccess + ? undefined + : new Error(orderResponse.errorMsg || 'Order placement failed'), + }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred while placing order'; logger.error(`[placeOrderAction] Order placement error:`, error); - const errorContent: Content = { + const errorResult: ActionResult = { text: `❌ **Order Placement Error** **Error**: ${errorMessage} @@ -378,17 +502,27 @@ Please check your configuration and try again. Make sure: • Token ID is valid and active • Price and size are within acceptable ranges • Network connection is stable`, - actions: ['POLYMARKET_PLACE_ORDER'], + values: { + success: false, + error: true, + tokenId, + side, + price, + size, + }, data: { + actionName: 'POLYMARKET_PLACE_ORDER', error: errorMessage, orderDetails: { tokenId, side, price, size, orderType }, }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), }; if (callback) { - await callback(errorContent); + await callback({ text: errorResult.text, data: errorResult.data }); } - throw new Error(errorMessage); + return errorResult; } }, diff --git a/src/actions/retrieveAllMarkets.ts b/src/actions/retrieveAllMarkets.ts index 516739a..f6e80f2 100644 --- a/src/actions/retrieveAllMarkets.ts +++ b/src/actions/retrieveAllMarkets.ts @@ -1,13 +1,12 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, type Memory, type State, logger, - ModelType, - composePromptFromState, } from '@elizaos/core'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { initializeClobClient } from '../utils/clobClient'; @@ -47,7 +46,7 @@ export const retrieveAllMarketsAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[retrieveAllMarketsAction] Handler called!'); const clobApiUrl = runtime.getSetting('CLOB_API_URL'); @@ -64,7 +63,19 @@ export const retrieveAllMarketsAction: Action = { if (callback) { await callback(errorContent); } - throw new Error(errorMessage); + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ALL_MARKETS', + error: errorMessage, + }, + success: false, + error: new Error(errorMessage), + }; } let filterParams: MarketFilters = {}; @@ -103,7 +114,10 @@ export const retrieveAllMarketsAction: Action = { const clobClient = await initializeClobClient(runtime); // Fetch markets with optional pagination and filters - const response = await clobClient.getMarkets(filterParams?.next_cursor || '', filterParams); + const response = await (clobClient as any).getMarkets( + filterParams?.next_cursor || '', + filterParams + ); if (!response || !response.data) { throw new Error('Invalid response from CLOB API'); @@ -159,7 +173,25 @@ export const retrieveAllMarketsAction: Action = { await callback(responseContent); } - return responseContent; + return { + text: responseText, + values: { + success: true, + marketCount, + totalCount: response.count || marketCount, + hasMoreResults: !!response.next_cursor && response.next_cursor !== 'LTE=', + }, + data: { + actionName: 'POLYMARKET_GET_ALL_MARKETS', + markets, + count: marketCount, + total: response.count || marketCount, + next_cursor: response.next_cursor, + limit: response.limit, + filters: filterParams, + }, + success: true, + }; } catch (error) { logger.error('[retrieveAllMarketsAction] Error fetching markets:', error); @@ -182,7 +214,20 @@ Please check: if (callback) { await callback(errorContent); } - throw error; + return { + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_GET_ALL_MARKETS', + error: errorMessage, + timestamp: new Date().toISOString(), + }, + success: false, + error: error instanceof Error ? error : new Error(errorMessage), + }; } }, diff --git a/src/actions/revokeApiKey.ts b/src/actions/revokeApiKey.ts index 7945bf8..1b87b10 100644 --- a/src/actions/revokeApiKey.ts +++ b/src/actions/revokeApiKey.ts @@ -1,4 +1,12 @@ -import { IAgentRuntime, Memory, State, HandlerCallback, logger } from '@elizaos/core'; +import { + Action, + ActionResult, + IAgentRuntime, + Memory, + State, + HandlerCallback, + logger, +} from '@elizaos/core'; import { initializeClobClient } from '../utils/clobClient'; import { callLLMWithTimeout } from '../utils/llmHelpers'; import { ethers } from 'ethers'; @@ -18,7 +26,7 @@ export interface RevokeApiKeyResponse { * Revoke API Key Action for Polymarket CLOB * Deletes/revokes an existing API key to disable L2 authentication */ -export const revokeApiKeyAction = { +export const revokeApiKeyAction: Action = { name: 'POLYMARKET_DELETE_API_KEY', similes: [ 'REVOKE_API_KEY', @@ -85,7 +93,7 @@ export const revokeApiKeyAction = { state: State, options: any, callback: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[revokeApiKeyAction] Handler called!'); try { @@ -149,7 +157,19 @@ Examples: }, }); } - return; + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_DELETE_API_KEY', + error: 'No valid API key ID provided', + }, + success: false, + error: new Error('No valid API key ID provided'), + }; } const apiKeyId = apiKeyIdString.trim(); @@ -261,6 +281,20 @@ If you need API access, use the CREATE_API_KEY action to generate new credential } logger.info('[revokeApiKeyAction] API key revocation completed successfully'); + + return { + text: successMessage, + values: { + success: true, + apiKeyId: responseData.apiKeyId, + revokedAt: responseData.revokedAt, + }, + data: { + actionName: 'POLYMARKET_DELETE_API_KEY', + revocation: responseData, + }, + success: true, + }; } catch (error) { logger.error('[revokeApiKeyAction] Error revoking API key:', error); @@ -290,6 +324,20 @@ If you need API access, use the CREATE_API_KEY action to generate new credential }, }); } + + return { + text: errorMessage, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_DELETE_API_KEY', + error: error instanceof Error ? error.message : 'Unknown error', + }, + success: false, + error: error instanceof Error ? error : new Error('Unknown error'), + }; } }, }; diff --git a/src/actions/setupWebsocket.ts b/src/actions/setupWebsocket.ts index 8c218de..cb88197 100644 --- a/src/actions/setupWebsocket.ts +++ b/src/actions/setupWebsocket.ts @@ -1,5 +1,6 @@ import { type Action, + type ActionResult, type Content, type HandlerCallback, type IAgentRuntime, @@ -62,7 +63,7 @@ export const setupWebsocketAction: Action = { state?: State, options?: { [key: string]: unknown }, callback?: HandlerCallback - ): Promise => { + ): Promise => { logger.info('[setupWebsocketAction] Handler called - now using ws library.'); // Clear any existing client from previous attempts / other types @@ -143,7 +144,19 @@ export const setupWebsocketAction: Action = { `[setupWebsocketAction] Validation Failure: ${errorMsg} Input was: "${message.content?.text}"` ); if (callback) await callback({ text: `❌ ${errorMsg}` }); - throw new Error(errorMsg); + return { + text: `❌ ${errorMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: errorMsg, + }, + success: false, + error: new Error(errorMsg), + }; } // Determine subscription type and construct WebSocket URL @@ -165,7 +178,19 @@ export const setupWebsocketAction: Action = { const errMsg = 'User ID is required for user channel subscription but was not found.'; logger.error(`[setupWebsocketAction] ${errMsg}`); if (callback) await callback({ text: `❌ ${errMsg}` }); - throw new Error(errMsg); + return { + text: `❌ ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: errMsg, + }, + success: false, + error: new Error(errMsg), + }; } subMsgPayload.markets = extractedMarkets || []; // For user channel, 'markets' are condition_ids // Authentication is required for user channel @@ -178,7 +203,19 @@ export const setupWebsocketAction: Action = { 'API Key, Secret, and Passphrase are required in settings for user channel WebSocket subscriptions.'; logger.error(`[setupWebsocketAction] Missing credentials for user subscription: ${errMsg}`); if (callback) await callback({ text: `❌ ${errMsg}` }); - throw new Error(errMsg); + return { + text: `❌ ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: errMsg, + }, + success: false, + error: new Error(errMsg), + }; } subMsgPayload.auth = { apiKey, secret: apiSecret, passphrase: apiPassphrase }; } else { @@ -188,7 +225,19 @@ export const setupWebsocketAction: Action = { 'At least one market (condition ID or asset ID) is required for market channel subscription.'; logger.error(`[setupWebsocketAction] ${errMsg}`); if (callback) await callback({ text: `❌ ${errMsg}` }); - throw new Error(errMsg); + return { + text: `❌ ${errMsg}`, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: errMsg, + }, + success: false, + error: new Error(errMsg), + }; } // The example uses 'assets_ids' for market subscriptions with token IDs. // We are getting 'condition_ids' from the user. This needs clarification from Polymarket docs @@ -201,7 +250,7 @@ export const setupWebsocketAction: Action = { ); } - return new Promise((resolvePromise, rejectPromise) => { + return new Promise((resolvePromise, rejectPromise) => { try { logger.info(`[setupWebsocketAction] Creating new WebSocket connection to: ${wsUrl}`); const wsClient = new WebSocket(wsUrl); @@ -214,14 +263,29 @@ export const setupWebsocketAction: Action = { const messageStr = JSON.stringify(subMsgPayload); wsClient.send(messageStr, (err?: Error) => { if (err) { - logger.error('[setupWebsocketAction] Error sending subscription message:', err); + logger.error( + '[setupWebsocketAction] Error sending subscription message:', + err.message + ); setActiveClobSocketClientReference(null); wsClient.terminate(); - const errorContent: Content = { + const errorContent = { text: `❌ WebSocket Error: Failed to send subscription - ${err.message}`, }; if (callback) callback(errorContent); - rejectPromise(new Error(`Failed to send subscription: ${err.message}`)); + rejectPromise({ + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: err.message, + }, + success: false, + error: err, + }); return; } logger.info(`[setupWebsocketAction] Subscription message sent: ${messageStr}`); @@ -233,7 +297,7 @@ export const setupWebsocketAction: Action = { responseText += ' Waiting for real-time updates. Use POLYMARKET_HANDLE_REALTIME_UPDATES to process messages.'; - const responseContent: Content = { + const responseContent = { text: responseText, actions: ['POLYMARKET_HANDLE_REALTIME_UPDATES'], data: { @@ -243,17 +307,44 @@ export const setupWebsocketAction: Action = { }, }; if (callback) callback(responseContent); - resolvePromise(responseContent); + resolvePromise({ + text: responseText, + values: { + success: true, + subscriptionType, + marketCount: subMsgPayload.markets?.length || 0, + userId: extractedUserId, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + status: 'subscribed', + subscription: subMsgPayload, + timestamp: new Date().toISOString(), + }, + success: true, + }); }); }); wsClient.on('error', (error: Error) => { - logger.error('[setupWebsocketAction] WebSocket connection error:', error); + logger.error('[setupWebsocketAction] WebSocket connection error:', error.message); setActiveClobSocketClientReference(null); // wsClient.terminate(); // No need to terminate, 'close' will be called - const errorContent: Content = { text: `❌ WebSocket Error: ${error.message}` }; + const errorContent = { text: `❌ WebSocket Error: ${error.message}` }; if (callback) callback(errorContent); - rejectPromise(error); + rejectPromise({ + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: error.message, + }, + success: false, + error: error, + }); }); wsClient.on('close', (code: number, reason: Buffer) => { @@ -271,7 +362,7 @@ export const setupWebsocketAction: Action = { // The 'message' handler should primarily live in handleRealtimeUpdatesAction // But we can log a generic message here for successful setup - wsClient.once('message', (data: WebSocket.RawData) => { + wsClient.once('message', (data: any) => { logger.info( '[setupWebsocketAction] Received first message (indicates successful subscription setup). Further messages handled by POLYMARKET_HANDLE_REALTIME_UPDATES.' ); @@ -283,11 +374,23 @@ export const setupWebsocketAction: Action = { error ); setActiveClobSocketClientReference(null); - const errorContent: Content = { + const errorContent = { text: `❌ Critical WebSocket Setup Error: ${error.message}`, }; if (callback) callback(errorContent); - rejectPromise(error); + rejectPromise({ + text: errorContent.text, + values: { + success: false, + error: true, + }, + data: { + actionName: 'POLYMARKET_SETUP_WEBSOCKET', + error: error.message, + }, + success: false, + error: error, + }); } }); }, diff --git a/src/types.ts b/src/types.ts index 6984370..a6a882a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -409,10 +409,10 @@ export type AreOrdersScoringResponse = Record; * Parameters for the getOpenOrders ClobClient method. */ export interface GetOpenOrdersParams { - market?: string; // Market condition ID - assetId?: string; // Asset ID (token ID) - address?: string; // User address - nextCursor?: string; // Pagination cursor + market?: string; // Market condition ID + assetId?: string; // Asset ID (token ID) + address?: string; // User address + nextCursor?: string; // Pagination cursor } /** @@ -423,9 +423,9 @@ export interface OpenOrder { user_id: string; market_id: string; // This is the condition_id token_id: string; - side: OrderSide; // Reuses existing OrderSide enum: 'BUY' | 'SELL' - type: string; // e.g., "LIMIT" - status: string; // e.g., "OPEN" - could create an enum if more statuses are known for open orders + side: OrderSide; // Reuses existing OrderSide enum: 'BUY' | 'SELL' + type: string; // e.g., "LIMIT" + status: string; // e.g., "OPEN" - could create an enum if more statuses are known for open orders price: string; size: string; filled_size: string; @@ -443,7 +443,7 @@ export interface GetTradesParams { market_id?: string; token_id?: string; from_timestamp?: number; // Unix timestamp (seconds) - to_timestamp?: number; // Unix timestamp (seconds) + to_timestamp?: number; // Unix timestamp (seconds) limit?: number; next_cursor?: string; } diff --git a/src/utils/clobClient.ts b/src/utils/clobClient.ts index c8e974d..d8e864e 100644 --- a/src/utils/clobClient.ts +++ b/src/utils/clobClient.ts @@ -2,7 +2,6 @@ import { type IAgentRuntime, logger } from '@elizaos/core'; import { ClobClient } from '@polymarket/clob-client'; import { ethers } from 'ethers'; - // Re-export the ClobClient type for other modules export type { ClobClient } from '@polymarket/clob-client'; @@ -20,7 +19,8 @@ export interface ApiKeyCreds { */ export async function initializeClobClient(runtime: IAgentRuntime): Promise { const clobApiUrl = runtime.getSetting('CLOB_API_URL') || 'https://clob.polymarket.com'; - const clobWsUrl = runtime.getSetting('CLOB_WS_URL') || 'wss://ws-subscriptions-clob.polymarket.com/ws/'; + const clobWsUrl = + runtime.getSetting('CLOB_WS_URL') || 'wss://ws-subscriptions-clob.polymarket.com/ws/'; const privateKey = runtime.getSetting('WALLET_PRIVATE_KEY') || @@ -33,13 +33,17 @@ export async function initializeClobClient(runtime: IAgentRuntime): Promise wallet.signTypedData(domain, types, value), + _signTypedData: async (domain: any, types: any, value: any) => + wallet.signTypedData(domain, types, value), getAddress: async () => wallet.address, }; @@ -51,11 +55,12 @@ export async function initializeClobClient(runtime: IAgentRuntime): Promise { const clobApiUrl = runtime.getSetting('CLOB_API_URL') || 'https://clob.polymarket.com'; - const clobWsUrl = runtime.getSetting('CLOB_WS_URL') || 'wss://ws-subscriptions-clob.polymarket.com/ws/'; + const clobWsUrl = + runtime.getSetting('CLOB_WS_URL') || 'wss://ws-subscriptions-clob.polymarket.com/ws/'; const privateKey = runtime.getSetting('WALLET_PRIVATE_KEY') || @@ -91,14 +97,12 @@ export async function initializeClobClientWithCreds(runtime: IAgentRuntime): Pro const apiPassphrase = runtime.getSetting('CLOB_API_PASSPHRASE') || runtime.getSetting('CLOB_PASS_PHRASE'); - logger.info(`[initializeClobClientWithCreds] Checking credentials and URLs:`, { - hasApiKey: !!apiKey, - hasApiSecret: !!apiSecret, - hasApiPassphrase: !!apiPassphrase, - httpUrl: clobApiUrl, - wsUrl: clobWsUrl || 'not provided', - apiKeyPreview: apiKey ? `${apiKey.substring(0, 8)}...` : 'missing', - }); + logger.info( + `[initializeClobClientWithCreds] Checking credentials and URLs: ` + + `hasApiKey=${!!apiKey}, hasApiSecret=${!!apiSecret}, hasApiPassphrase=${!!apiPassphrase}, ` + + `httpUrl=${clobApiUrl}, wsUrl=${clobWsUrl || 'not provided'}, ` + + `apiKeyPreview=${apiKey ? `${apiKey.substring(0, 8)}...` : 'missing'}` + ); if (!apiKey || !apiSecret || !apiPassphrase) { const missing = []; @@ -116,7 +120,8 @@ export async function initializeClobClientWithCreds(runtime: IAgentRuntime): Pro const wallet = new ethers.Wallet(privateKey); const enhancedWallet = { ...wallet, - _signTypedData: async (domain: any, types: any, value: any) => wallet.signTypedData(domain, types, value), + _signTypedData: async (domain: any, types: any, value: any) => + wallet.signTypedData(domain, types, value), getAddress: async () => wallet.address, }; @@ -138,7 +143,8 @@ export async function initializeClobClientWithCreds(runtime: IAgentRuntime): Pro ); logger.info( - `[initializeClobClientWithCreds] CLOB client initialized successfully with API credentials` + (clobWsUrl ? ' and WebSocket support.' : '.') + `[initializeClobClientWithCreds] CLOB client initialized successfully with API credentials` + + (clobWsUrl ? ' and WebSocket support.' : '.') ); return client; } catch (error) { @@ -147,4 +153,4 @@ export async function initializeClobClientWithCreds(runtime: IAgentRuntime): Pro `Failed to initialize CLOB client with credentials: ${error instanceof Error ? error.message : 'Unknown error'}` ); } -} \ No newline at end of file +} diff --git a/src/utils/llmHelpers.ts b/src/utils/llmHelpers.ts index a77d3f1..8f4211d 100644 --- a/src/utils/llmHelpers.ts +++ b/src/utils/llmHelpers.ts @@ -42,7 +42,7 @@ export async function callLLMWithTimeout( const result = (await Promise.race([llmPromise, timeoutPromise])) as T; logger.info(`[${actionName}] LLM parameter extraction completed`); - logger.debug(`[${actionName}] Parsed LLM parameters:`, result); + logger.debug(`[${actionName}] Parsed LLM parameters: ${JSON.stringify(result)}`); return result; }