Skip to main content
Glama
getErc20Allowance.ts5.55 kB
import { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js"; import { getDefaultProvider, Wallet, Contract, ethers } from '@coti-io/coti-ethers'; import { getNetwork } from "../shared/account.js"; import { ERC20_ABI } from "../constants/abis.js"; import { decryptUint } from "@coti-io/coti-sdk-typescript"; import { z } from "zod"; /** * Tool definition for checking ERC20 token allowance on the COTI blockchain */ export const GET_ERC20_ALLOWANCE: ToolAnnotations = { title: "Get ERC20 Allowance", name: "get_erc20_allowance", description: "Check how many tokens a spender is allowed to use. " + "This is used for checking the current allowance a spender has for an owner's tokens. " + "Requires token contract address, owner address, and spender address as input. " + "Returns the allowance amount.", inputSchema: { private_key: z.string().describe("Private key of the account (tracked by AI from previous operations)"), aes_key: z.string().optional().describe("AES key for private transactions (tracked by AI). Required for private operations."), network: z.enum(['testnet', 'mainnet']).describe("Network to use: 'testnet' or 'mainnet' (required)."), token_address: z.string().describe("ERC20 token contract address on COTI blockchain"), owner_address: z.string().describe("Address of the token owner"), spender_address: z.string().describe("Address of the spender to check allowance for"), }, }; /** * Type guard for validating get ERC20 allowance arguments * @param args - Arguments to validate * @returns True if arguments are valid for get ERC20 allowance operation */ export function isGetERC20AllowanceArgs(args: unknown): args is { token_address: string, owner_address: string, spender_address: string , private_key?: string, aes_key?: string, network: 'testnet' | 'mainnet' } { return ( typeof args === "object" && args !== null && "token_address" in args && typeof (args as { token_address: string }).token_address === "string" && "owner_address" in args && typeof (args as { owner_address: string }).owner_address === "string" && "spender_address" in args && typeof (args as { spender_address: string }).spender_address === "string" ); } /** * Handler for the getERC20Allowance tool * @param args The arguments for the tool * @returns The tool response */ export async function getERC20AllowanceHandler(args: any): Promise<any> { if (!isGetERC20AllowanceArgs(args)) { throw new Error("Invalid arguments for get_erc20_allowance"); } const { token_address, owner_address, spender_address, network, private_key, aes_key } = args; if (!private_key || !aes_key) { throw new Error("private_key and aes_key are required"); } const results = await performGetERC20Allowance(private_key, aes_key, token_address, owner_address, spender_address, network); return { structuredContent: { tokenSymbol: results.tokenSymbol, decimals: results.decimals, ownerAddress: results.ownerAddress, spenderAddress: results.spenderAddress, allowance: results.allowance, tokenAddress: results.tokenAddress }, content: [{ type: "text", text: results.formattedText }], isError: false, }; } /** * Retrieves the allowance for an ERC20 token spender on the COTI blockchain * @param token_address - Address of the ERC20 token contract * @param owner_address - Address of the token owner * @param spender_address - Address of the spender to check allowance for * @returns An object with allowance details and formatted text */ export async function performGetERC20Allowance(private_key: string, aes_key: string, token_address: string, owner_address: string, spender_address: string, network: 'testnet' | 'mainnet'): Promise<{ tokenSymbol: string, decimals: number, ownerAddress: string, spenderAddress: string, allowance: string, tokenAddress: string, formattedText: string }> { try { const provider = getDefaultProvider(getNetwork(network)); const wallet = new Wallet(private_key, provider); wallet.setAesKey(aes_key); const tokenContract = new Contract(token_address, ERC20_ABI, wallet); const symbolResult = await tokenContract.symbol(); const decimalsResult = await tokenContract.decimals(); const allowanceResult = await tokenContract.allowance(owner_address, spender_address); const decryptedAllowance = decryptUint(allowanceResult, aes_key); const formattedAllowance = decryptedAllowance ? ethers.formatUnits(decryptedAllowance, decimalsResult) : "Unable to decrypt"; const formattedText = `ERC20 Token Allowance:\nToken: ${symbolResult}\nOwner: ${owner_address}\nSpender: ${spender_address}\nAllowance: ${formattedAllowance}`; return { tokenSymbol: symbolResult, decimals: Number(decimalsResult), ownerAddress: owner_address, spenderAddress: spender_address, allowance: formattedAllowance, tokenAddress: token_address, formattedText }; } catch (error) { console.error('Error getting ERC20 allowance:', error); throw new Error(`Failed to get ERC20 allowance: ${error instanceof Error ? error.message : String(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/davibauer/coti-mcp'

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