get_nep11_transfers
Retrieve NEP-11 non-fungible token transfer records for a given Neo N3 address, with optional time range filters and network selection.
Instructions
Get NEP-11 transfer history for an address.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Neo N3 address | |
| fromTimestampMs | No | Optional start timestamp in Unix epoch milliseconds | |
| toTimestampMs | No | Optional end timestamp in Unix epoch milliseconds | |
| network | No | Network to use: "mainnet" or "testnet" |
Implementation Reference
- src/index.ts:388-406 (registration)Registration of the 'get_nep11_transfers' tool using the MCP server's registerTool method. Defines the tool name, description, Zod input schema (address required, optional fromTimestampMs, toTimestampMs, network), and a handler lambda that calls callTool().
registerTool( 'get_nep11_transfers', 'Get NEP-11 transfer history for an address.', { address: z.string().describe('Neo N3 address'), fromTimestampMs: z.number().int().nonnegative().optional().describe('Optional start timestamp in Unix epoch milliseconds'), toTimestampMs: z.number().int().nonnegative().optional().describe('Optional end timestamp in Unix epoch milliseconds'), network: z.string().optional().describe('Network to use: "mainnet" or "testnet"'), }, async (args) => { try { await this.ensureServicesInitialized(); const result = await callTool('get_nep11_transfers', args, this.neoServices, this.contractServices); return this.formatDelegatedToolResponse(result); } catch (error: unknown) { return this.createErrorResponse(error); } } ); - src/handlers/tool-handler.ts:205-223 (handler)Handler function handleGetNep11Transfers - validates address, parses optional timestamp filters, calls neoService.getNep11Transfers(), and returns success response.
async function handleGetNep11Transfers(input: Record<string, unknown>, neoService: NeoService): Promise<unknown> { try { validateAddress(input.address as string); const fromTimestampMs = input.fromTimestampMs !== undefined ? validateInteger(input.fromTimestampMs as string | number) : undefined; const toTimestampMs = input.toTimestampMs !== undefined ? validateInteger(input.toTimestampMs as string | number) : undefined; if (fromTimestampMs !== undefined && toTimestampMs !== undefined && fromTimestampMs > toTimestampMs) { throw new McpError(ErrorCode.InvalidParams, 'fromTimestampMs must be less than or equal to toTimestampMs.'); } const result = await neoService.getNep11Transfers(input.address as string, { ...(fromTimestampMs !== undefined ? { fromTimestampMs } : {}), ...(toTimestampMs !== undefined ? { toTimestampMs } : {}), }); return createSuccessResponse(result); } catch (error) { return handleError(error); } } - JSON Schema definition for 'get_nep11_transfers' in the tool setup: describes address (string, required), fromTimestampMs, toTimestampMs, and network fields.
{ name: 'get_nep11_transfers', description: 'Get NEP-11 transfer history for an address with additive asset and party enrichment when available', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Neo N3 address', }, fromTimestampMs: { type: 'integer', description: 'Optional start of the transfer history window, in Unix epoch milliseconds.', }, toTimestampMs: { type: 'integer', description: 'Optional end of the transfer history window, in Unix epoch milliseconds.', }, network: { type: 'string', description: 'Optional: Network to use ("mainnet" or "testnet"). Defaults based on config.', enum: [NeoNetwork.MAINNET, NeoNetwork.TESTNET], }, }, required: ['address'], }, - src/services/neo-service.ts:533-578 (handler)Service-layer implementation of getNep11Transfers - validates inputs, builds RPC params (with optional timestamp filters), executes the 'getnep11transfers' RPC call, then enriches the response via enrichNep11Transfers().
async getNep11Transfers( address: string, options: { fromTimestampMs?: number, toTimestampMs?: number, } = {} ) { try { if (!address || typeof address !== 'string') { throw new Error('Invalid address format'); } if (options.fromTimestampMs !== undefined && (!Number.isInteger(options.fromTimestampMs) || options.fromTimestampMs < 0)) { throw new Error(`Invalid fromTimestampMs: ${options.fromTimestampMs}`); } if (options.toTimestampMs !== undefined && (!Number.isInteger(options.toTimestampMs) || options.toTimestampMs < 0)) { throw new Error(`Invalid toTimestampMs: ${options.toTimestampMs}`); } if (options.fromTimestampMs !== undefined && options.toTimestampMs !== undefined && options.fromTimestampMs > options.toTimestampMs) { throw new Error('fromTimestampMs must be less than or equal to toTimestampMs'); } const params: Array<string | number> = [address]; if (options.fromTimestampMs !== undefined) { params.push(options.fromTimestampMs); } if (options.toTimestampMs !== undefined) { if (options.fromTimestampMs === undefined) { params.push(0); } params.push(options.toTimestampMs); } const transfers = await this.rpcClient.execute(new neonJs.rpc.Query({ method: 'getnep11transfers', params, })); return this.enrichNep11Transfers(transfers as Nep11TransfersResponse, address); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to get NEP-11 transfers for address ${address}: ${errorMessage}`); } } - src/services/neo-service.ts:322-336 (helper)Helper enrichNep11Transfers() - enriches sent/received transfer arrays by mapping each entry through buildTransferHistoryEntry(), adding direction, timestampIso, asset, from/to parties and counterparty info.
private enrichNep11Transfers(transfers: Nep11TransfersResponse, accountAddress: string) { if (!transfers || typeof transfers !== 'object') { return transfers; } return { ...transfers, sent: Array.isArray(transfers.sent) ? transfers.sent.map((entry: Nep17TransferEntry) => this.buildTransferHistoryEntry(entry, accountAddress, 'sent')) : transfers.sent, received: Array.isArray(transfers.received) ? transfers.received.map((entry: Nep17TransferEntry) => this.buildTransferHistoryEntry(entry, accountAddress, 'received')) : transfers.received, }; }