Skip to main content
Glama

generate_sip010_transfer

Create SIP-010 token transfer transactions with required post-conditions for secure blockchain transfers. Generates transaction parameters ready for wallet signing on Stacks networks.

Instructions

Generate a SIP-010 fungible token transfer transaction with proper post-conditions. Returns the transaction parameters for wallet signing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
amountYesThe amount to transfer (in base units, considering decimals)
contractAddressYesThe contract address (e.g., SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9)
contractNameYesThe contract name of the SIP-010 token
memoNoOptional memo (max 34 bytes)
networkYesThe Stacks network
recipientYesThe recipient's Stacks address
senderYesThe sender's Stacks address

Implementation Reference

  • Zod schema defining the input parameters for the generate_sip010_transfer tool, including contract details, amount, addresses, optional memo, and network.
    const SIP010TransferScheme = z.object({ contractAddress: z.string().describe("The contract address (e.g., SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9)"), contractName: z.string().describe("The contract name of the SIP-010 token"), amount: z.number().describe("The amount to transfer (in base units, considering decimals)"), sender: z.string().describe("The sender's Stacks address"), recipient: z.string().describe("The recipient's Stacks address"), memo: z.string().optional().describe("Optional memo (max 34 bytes)"), network: NetworkScheme.describe("The Stacks network"), });
  • The main execute function of the tool that validates inputs, generates transaction parameters for SIP-010 transfer including function args and post-conditions, and returns formatted JSON and integration code.
    execute: async (args, context) => { try { await recordTelemetry({ action: "generate_sip010_transfer" }, context); // Validate inputs if (args.amount <= 0) { return "❌ Amount must be positive"; } if (args.sender === args.recipient) { return "❌ Sender and recipient cannot be the same"; } if (args.memo && Buffer.from(args.memo, 'utf8').length > 34) { return "❌ Memo cannot exceed 34 bytes"; } // Generate the transaction parameters const transactionParams = { contractAddress: args.contractAddress, contractName: args.contractName, functionName: "transfer", functionArgs: [ { type: "uint", value: args.amount }, { type: "principal", value: args.sender }, { type: "principal", value: args.recipient }, args.memo ? { type: "some", value: { type: "buffer", value: args.memo } } : { type: "none" } ], postConditions: [ { type: "fungible", condition: "equal", amount: args.amount, asset: { contractAddress: args.contractAddress, contractName: args.contractName, assetName: args.contractName }, principal: args.sender } ], network: args.network }; return `# SIP-010 Transfer Transaction ## Transaction Parameters \`\`\`json ${JSON.stringify(transactionParams, null, 2)} \`\`\` ## Frontend Integration Example (TypeScript) \`\`\`typescript import { openContractCall, PostConditionMode, FungibleConditionCode, createAssetInfo, makeStandardFungiblePostCondition, uintCV, principalCV, ${args.memo ? 'someCV, bufferCV' : 'noneCV'} } from '@stacks/connect'; const functionArgs = [ uintCV(${args.amount}), principalCV('${args.sender}'), principalCV('${args.recipient}'), ${args.memo ? `someCV(bufferCV(Buffer.from('${args.memo}', 'utf8')))` : 'noneCV()'} ]; const postConditions = [ makeStandardFungiblePostCondition( '${args.sender}', FungibleConditionCode.Equal, ${args.amount}, createAssetInfo('${args.contractAddress}', '${args.contractName}', '${args.contractName}') ), ]; await openContractCall({ contractAddress: '${args.contractAddress}', contractName: '${args.contractName}', functionName: 'transfer', functionArgs, postConditions, postConditionMode: PostConditionMode.Deny, // REQUIRED onFinish: (data) => { console.log('Transaction ID:', data.txId); }, }); \`\`\` ## Security Notes - ✅ Post-condition included (MANDATORY for SIP-010) - ✅ Input validation performed - ✅ Using deny mode for maximum security - ⚠️ Always verify recipient address before signing`; } catch (error) { return `❌ Failed to generate SIP-010 transfer: ${error}`; } },
  • Registration of the generateSIP010TransferTool with the FastMCP server.
    server.addTool(generateSIP010TransferTool);
  • Full tool definition including name, description, parameters schema reference, and execute handler.
    export const generateSIP010TransferTool: Tool<undefined, typeof SIP010TransferScheme> = { name: "generate_sip010_transfer", description: "Generate a SIP-010 fungible token transfer transaction with proper post-conditions. Returns the transaction parameters for wallet signing.", parameters: SIP010TransferScheme, execute: async (args, context) => { try { await recordTelemetry({ action: "generate_sip010_transfer" }, context); // Validate inputs if (args.amount <= 0) { return "❌ Amount must be positive"; } if (args.sender === args.recipient) { return "❌ Sender and recipient cannot be the same"; } if (args.memo && Buffer.from(args.memo, 'utf8').length > 34) { return "❌ Memo cannot exceed 34 bytes"; } // Generate the transaction parameters const transactionParams = { contractAddress: args.contractAddress, contractName: args.contractName, functionName: "transfer", functionArgs: [ { type: "uint", value: args.amount }, { type: "principal", value: args.sender }, { type: "principal", value: args.recipient }, args.memo ? { type: "some", value: { type: "buffer", value: args.memo } } : { type: "none" } ], postConditions: [ { type: "fungible", condition: "equal", amount: args.amount, asset: { contractAddress: args.contractAddress, contractName: args.contractName, assetName: args.contractName }, principal: args.sender } ], network: args.network }; return `# SIP-010 Transfer Transaction ## Transaction Parameters \`\`\`json ${JSON.stringify(transactionParams, null, 2)} \`\`\` ## Frontend Integration Example (TypeScript) \`\`\`typescript import { openContractCall, PostConditionMode, FungibleConditionCode, createAssetInfo, makeStandardFungiblePostCondition, uintCV, principalCV, ${args.memo ? 'someCV, bufferCV' : 'noneCV'} } from '@stacks/connect'; const functionArgs = [ uintCV(${args.amount}), principalCV('${args.sender}'), principalCV('${args.recipient}'), ${args.memo ? `someCV(bufferCV(Buffer.from('${args.memo}', 'utf8')))` : 'noneCV()'} ]; const postConditions = [ makeStandardFungiblePostCondition( '${args.sender}', FungibleConditionCode.Equal, ${args.amount}, createAssetInfo('${args.contractAddress}', '${args.contractName}', '${args.contractName}') ), ]; await openContractCall({ contractAddress: '${args.contractAddress}', contractName: '${args.contractName}', functionName: 'transfer', functionArgs, postConditions, postConditionMode: PostConditionMode.Deny, // REQUIRED onFinish: (data) => { console.log('Transaction ID:', data.txId); }, }); \`\`\` ## Security Notes - ✅ Post-condition included (MANDATORY for SIP-010) - ✅ Input validation performed - ✅ Using deny mode for maximum security - ⚠️ Always verify recipient address before signing`; } catch (error) { return `❌ Failed to generate SIP-010 transfer: ${error}`; } }, };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/exponentlabshq/stacks-clarity-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server