tokens_send_ft
Send fungible tokens (e.g., USDC, USDT, WNEAR) from one account to another using the specified token contract, amount, and network.
Instructions
Send Fungible Tokens (FT) like USDC native, USDT, WNEAR, etc. based on the NEP-141 and NEP-148 standards to an account. The signer account is the sender of the tokens, and the receiver account is the recipient of the tokens. Ensure the contract account id exists and is in the same network as the signer and receiver accounts.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| signerAccountId | Yes | The account that will send the tokens. | |
| receiverAccountId | Yes | The account that will receive the tokens. | |
| networkId | No | mainnet | |
| fungibleTokenContractAccountId | Yes | The account id of the fungible token contract. Ensure the contract account id exists and is in the same network as the signer and receiver accounts. | |
| amount | Yes | The amount of tokens to send in the fungible token contract. e.g. 1 USDC, 0.33 USDT, 1.5 WNEAR, etc. |
Implementation Reference
- src/services.ts:1683-1793 (registration)The tool 'tokens_send_ft' is registered using mcp.tool() on line 1683. This is the MCP tool registration call.
mcp.tool( 'tokens_send_ft', noLeadingWhitespace` Send Fungible Tokens (FT) like USDC native, USDT, WNEAR, etc. based on the NEP-141 and NEP-148 standards to an account. The signer account is the sender of the tokens, and the receiver account is the recipient of the tokens. Ensure the contract account id exists and is in the same network as the signer and receiver accounts.`, { signerAccountId: z .string() .describe('The account that will send the tokens.'), receiverAccountId: z .string() .describe('The account that will receive the tokens.'), networkId: z.enum(['mainnet']).default('mainnet'), fungibleTokenContractAccountId: z .string() .describe( 'The account id of the fungible token contract. Ensure the contract account id exists and is in the same network as the signer and receiver accounts.', ), amount: z .number() .describe( 'The amount of tokens to send in the fungible token contract. e.g. 1 USDC, 0.33 USDT, 1.5 WNEAR, etc.', ), }, async (args, _) => { const connection = await connect({ networkId: args.networkId, keyStore: keystore, nodeUrl: getEndpointsByNetwork(args.networkId)[0]!, }); // check that the fungible token contract exists by getting // the metadata of the contract const fungibleTokenContractMetadataResult: Result< FungibleTokenMetadata, Error > = await getFungibleTokenContractMetadataResult( args.fungibleTokenContractAccountId, connection, ); if (!fungibleTokenContractMetadataResult.ok) { return { content: [ { type: 'text', text: `Error: ${fungibleTokenContractMetadataResult.error}`, }, ], }; } // convert the amount into the decimals of the fungible token const amountInDecimals = BigInt( args.amount * 10 ** fungibleTokenContractMetadataResult.value.decimals, ); // call the transfer function of the fungible token contract const transferResult: Result<FinalExecutionOutcome, Error> = await (async () => { try { const fungibleTokenContractResult = await getAccount( args.fungibleTokenContractAccountId, connection, ); if (!fungibleTokenContractResult.ok) { return fungibleTokenContractResult; } const fungibleTokenContract = fungibleTokenContractResult.value; const senderAccount = await connection.account( args.signerAccountId, ); const receiverAccount = await connection.account( args.receiverAccountId, ); return { ok: true, value: await senderAccount.functionCall({ contractId: fungibleTokenContract.accountId, methodName: 'ft_transfer', args: { receiver_id: receiverAccount.accountId, amount: amountInDecimals.toString(), }, gas: DEFAULT_GAS, attachedDeposit: NearToken.parse_yocto_near('1').as_yocto_near(), }), }; } catch (e) { return { ok: false, error: new Error(e as string) }; } })(); if (!transferResult.ok) { return { content: [{ type: 'text', text: `Error: ${transferResult.error}` }], }; } return { content: [ { type: 'text', text: `Transaction sent: ${stringify_bigint(transferResult.value)}`, }, ], }; }, ); - src/services.ts:1689-1707 (schema)The input schema for 'tokens_send_ft' defines required parameters: signerAccountId, receiverAccountId, networkId (default 'mainnet'), fungibleTokenContractAccountId, and amount.
{ signerAccountId: z .string() .describe('The account that will send the tokens.'), receiverAccountId: z .string() .describe('The account that will receive the tokens.'), networkId: z.enum(['mainnet']).default('mainnet'), fungibleTokenContractAccountId: z .string() .describe( 'The account id of the fungible token contract. Ensure the contract account id exists and is in the same network as the signer and receiver accounts.', ), amount: z .number() .describe( 'The amount of tokens to send in the fungible token contract. e.g. 1 USDC, 0.33 USDT, 1.5 WNEAR, etc.', ), }, - src/services.ts:1708-1793 (handler)The handler function for 'tokens_send_ft'. It connects to the NEAR network, validates the fungible token contract by fetching its metadata, converts the amount to the correct decimal precision, and calls ft_transfer on the token contract.
async (args, _) => { const connection = await connect({ networkId: args.networkId, keyStore: keystore, nodeUrl: getEndpointsByNetwork(args.networkId)[0]!, }); // check that the fungible token contract exists by getting // the metadata of the contract const fungibleTokenContractMetadataResult: Result< FungibleTokenMetadata, Error > = await getFungibleTokenContractMetadataResult( args.fungibleTokenContractAccountId, connection, ); if (!fungibleTokenContractMetadataResult.ok) { return { content: [ { type: 'text', text: `Error: ${fungibleTokenContractMetadataResult.error}`, }, ], }; } // convert the amount into the decimals of the fungible token const amountInDecimals = BigInt( args.amount * 10 ** fungibleTokenContractMetadataResult.value.decimals, ); // call the transfer function of the fungible token contract const transferResult: Result<FinalExecutionOutcome, Error> = await (async () => { try { const fungibleTokenContractResult = await getAccount( args.fungibleTokenContractAccountId, connection, ); if (!fungibleTokenContractResult.ok) { return fungibleTokenContractResult; } const fungibleTokenContract = fungibleTokenContractResult.value; const senderAccount = await connection.account( args.signerAccountId, ); const receiverAccount = await connection.account( args.receiverAccountId, ); return { ok: true, value: await senderAccount.functionCall({ contractId: fungibleTokenContract.accountId, methodName: 'ft_transfer', args: { receiver_id: receiverAccount.accountId, amount: amountInDecimals.toString(), }, gas: DEFAULT_GAS, attachedDeposit: NearToken.parse_yocto_near('1').as_yocto_near(), }), }; } catch (e) { return { ok: false, error: new Error(e as string) }; } })(); if (!transferResult.ok) { return { content: [{ type: 'text', text: `Error: ${transferResult.error}` }], }; } return { content: [ { type: 'text', text: `Transaction sent: ${stringify_bigint(transferResult.value)}`, }, ], }; }, );