sodax_get_user_transactions
Retrieve transaction history for a wallet address, supporting pagination and multiple output formats to analyze user activity.
Instructions
Get intent/transaction history for a specific wallet address
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| userAddress | Yes | The wallet address to look up (e.g., '0x...') | |
| limit | No | Maximum number of transactions to return (1-100) | |
| offset | No | Number of transactions to skip for pagination | |
| format | No | Response format: 'json' for raw data or 'markdown' for formatted text | markdown |
Implementation Reference
- src/tools/sodaxApi.ts:184-217 (registration)MCP tool registration for sodax_get_user_transactions with input schema (zod validation for userAddress, limit, offset, format) and the async handler that calls getUserTransactions service and formats the response// Tool 4: Get User Transactions server.tool( "sodax_get_user_transactions", "Get intent/transaction history for a specific wallet address", { userAddress: z.string() .describe("The wallet address to look up (e.g., '0x...')"), limit: z.number().min(1).max(100).optional().default(20) .describe("Maximum number of transactions to return (1-100)"), offset: z.number().min(0).optional().default(0) .describe("Number of transactions to skip for pagination"), format: z.nativeEnum(ResponseFormat).optional().default(ResponseFormat.MARKDOWN) .describe("Response format: 'json' for raw data or 'markdown' for formatted text") }, READ_ONLY, async ({ userAddress, limit, offset, format }) => { try { const transactions = await getUserTransactions(userAddress, { limit, offset }); const header = `## Transactions for ${userAddress.slice(0, 10)}...${userAddress.slice(-8)}\n\n`; const summary = `${transactions.length} transactions found\n\n`; return { content: [{ type: "text", text: header + summary + formatResponse(transactions, format) }] }; } catch (error) { return { content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : "Unknown error"}` }], isError: true }; } } );
- src/services/sodaxApi.ts:128-146 (handler)Service function getUserTransactions that executes the actual API call to SODAX endpoint `/intent/user/${userAddress}` with optional pagination parameters (limit, offset) and returns Transaction[]export async function getUserTransactions( userAddress: string, options?: { chainId?: string; limit?: number; offset?: number } ): Promise<Transaction[]> { try { const params = new URLSearchParams(); if (options?.limit) params.append("limit", options.limit.toString()); if (options?.offset) params.append("offset", options.offset.toString()); const queryString = params.toString(); const url = `/intent/user/${userAddress}${queryString ? `?${queryString}` : ""}`; const response = await apiClient.get(url); // API returns { items, total, offset, limit } return response.data?.items || response.data?.data || []; } catch (error) { console.error("Error fetching user transactions:", error); throw new Error("Failed to fetch user transactions from SODAX API"); } }
- src/services/analytics.ts:31-31 (registration)Analytics tool group mapping that categorizes sodax_get_user_transactions under the 'api' group for PostHog trackingsodax_get_user_transactions: "api",
- src/tools/sodaxApi.ts:30-77 (helper)Helper functions formatResponse and formatAsMarkdown used by the tool handler to format transaction data as JSON or markdown tablesfunction formatResponse(data: unknown, format: ResponseFormat): string { if (format === ResponseFormat.MARKDOWN) { return formatAsMarkdown(data); } return JSON.stringify(data, null, 2); } /** * Format data as Markdown for better readability */ function formatAsMarkdown(data: unknown): string { if (Array.isArray(data)) { if (data.length === 0) return "_No data available_"; // Try to create a table for arrays of objects if (typeof data[0] === "object" && data[0] !== null) { const keys = Object.keys(data[0]).slice(0, 6); // Limit columns let md = `| ${keys.join(" | ")} |\n`; md += `| ${keys.map(() => "---").join(" | ")} |\n`; for (const item of data.slice(0, 20)) { // Limit rows const values = keys.map(k => { const val = (item as Record<string, unknown>)[k]; if (val === null || val === undefined) return "-"; if (typeof val === "object") return JSON.stringify(val).slice(0, 30); return String(val).slice(0, 40); }); md += `| ${values.join(" | ")} |\n`; } if (data.length > 20) { md += `\n_... and ${data.length - 20} more items_`; } return md; } return data.map(item => `- ${String(item)}`).join("\n"); } if (typeof data === "object" && data !== null) { const entries = Object.entries(data); return entries.map(([key, value]) => { if (typeof value === "object" && value !== null) { return `**${key}:**\n\`\`\`json\n${JSON.stringify(value, null, 2)}\n\`\`\``; } return `**${key}:** ${value}`; }).join("\n\n"); } return String(data); }