Skip to main content
Glama
transfer.ts11.7 kB
import { type Address, type Hash, getContract, parseEther, parseUnits } from 'viem'; import { DEFAULT_NETWORK } from '../config.js'; import { getPublicClient, getWalletClientFromProvider } from './clients.js'; import * as services from './index.js'; // Standard ERC20 ABI for transfers const erc20TransferAbi = [ { inputs: [ { type: 'address', name: 'to' }, { type: 'uint256', name: 'amount' } ], name: 'transfer', outputs: [{ type: 'bool' }], stateMutability: 'nonpayable', type: 'function' }, { inputs: [ { type: 'address', name: 'spender' }, { type: 'uint256', name: 'amount' } ], name: 'approve', outputs: [{ type: 'bool' }], stateMutability: 'nonpayable', type: 'function' }, { inputs: [], name: 'decimals', outputs: [{ type: 'uint8' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'symbol', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' } ] as const; // Standard ERC721 ABI for transfers const erc721TransferAbi = [ { inputs: [ { type: 'address', name: 'from' }, { type: 'address', name: 'to' }, { type: 'uint256', name: 'tokenId' } ], name: 'transferFrom', outputs: [], stateMutability: 'nonpayable', type: 'function' }, { inputs: [], name: 'name', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'symbol', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [{ type: 'uint256', name: 'tokenId' }], name: 'ownerOf', outputs: [{ type: 'address' }], stateMutability: 'view', type: 'function' } ] as const; // ERC1155 ABI for transfers const erc1155TransferAbi = [ { inputs: [ { type: 'address', name: 'from' }, { type: 'address', name: 'to' }, { type: 'uint256', name: 'id' }, { type: 'uint256', name: 'amount' }, { type: 'bytes', name: 'data' } ], name: 'safeTransferFrom', outputs: [], stateMutability: 'nonpayable', type: 'function' }, { inputs: [ { type: 'address', name: 'account' }, { type: 'uint256', name: 'id' } ], name: 'balanceOf', outputs: [{ type: 'uint256' }], stateMutability: 'view', type: 'function' } ] as const; /** * Transfer OM to an address * @param toAddress Recipient address * @param amount Amount to send in OM * @param network Network name or chain ID * @param gasParams Optional gas fee parameters * @returns Transaction hash * @throws Error if no private key is available */ export async function transferOM( toAddress: string, amount: string, // in ether network = DEFAULT_NETWORK, gasParams?: { maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint } ): Promise<Hash> { const validatedToAddress = services.helpers.validateAddress(toAddress); // Get wallet client from provider const client = await getWalletClientFromProvider(network); const amountWei = parseEther(amount); // Ensure account exists before using it if (!client.account) { throw new Error('Wallet account not initialized properly'); } const txParams: any = { to: validatedToAddress, value: amountWei, account: client.account, chain: client.chain }; // Add gas parameters if provided if (gasParams?.maxFeePerGas) txParams.maxFeePerGas = gasParams.maxFeePerGas; if (gasParams?.maxPriorityFeePerGas) txParams.maxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; return client.sendTransaction(txParams); } /** * Transfer ERC20 tokens to an address * @param tokenAddress Token contract address * @param toAddress Recipient address * @param amount Amount to send (in token units) * @param network Network name or chain ID * @param gasParams Optional gas fee parameters * @returns Transaction details * @throws Error if no private key is available */ export async function transferERC20( tokenAddress: string, toAddress: string, amount: string, network = DEFAULT_NETWORK, gasParams?: { maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint } ): Promise<{ txHash: Hash; amount: { raw: bigint; formatted: string; }; token: { symbol: string; decimals: number; }; }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); // Get wallet client from provider const walletClient = await getWalletClientFromProvider(network); const publicClient = getPublicClient(network); // Get token details const contract = getContract({ address: tokenAddress as Address, abi: erc20TransferAbi, client: publicClient }); // Get token decimals and symbol const decimals = await contract.read.decimals(); const symbol = await contract.read.symbol(); // Parse the amount with the correct number of decimals const rawAmount = parseUnits(amount, decimals); // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); } const txParams: any = { address: validatedTokenAddress, abi: erc20TransferAbi, functionName: 'transfer', args: [validatedToAddress, rawAmount], account: walletClient.account, chain: walletClient.chain }; // Add gas parameters if provided if (gasParams?.maxFeePerGas) txParams.maxFeePerGas = gasParams.maxFeePerGas; if (gasParams?.maxPriorityFeePerGas) txParams.maxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; // Send the transaction const hash = await walletClient.writeContract(txParams); return { txHash: hash, amount: { raw: rawAmount, formatted: amount }, token: { symbol, decimals } }; } /** * Approve ERC20 token spending * @param tokenAddress Token contract address * @param spenderAddress Spender address * @param amount Amount to approve (in token units) * @param network Network name or chain ID * @param gasParams Optional gas fee parameters * @returns Transaction details * @throws Error if no private key is available */ export async function approveERC20( tokenAddress: string, spenderAddress: string, amount: string, network = DEFAULT_NETWORK, gasParams?: { maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint } ): Promise<{ txHash: Hash; amount: { raw: bigint; formatted: string; }; token: { symbol: string; decimals: number; }; }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedSpenderAddress = services.helpers.validateAddress(spenderAddress); // Get wallet client from provider const walletClient = await getWalletClientFromProvider(network); const publicClient = getPublicClient(network); const contract = getContract({ address: validatedTokenAddress, abi: erc20TransferAbi, client: publicClient }); // Get token decimals and symbol const decimals = await contract.read.decimals(); const symbol = await contract.read.symbol(); // Parse the amount with the correct number of decimals const rawAmount = parseUnits(amount, decimals); // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); } const txParams: any = { address: validatedTokenAddress, abi: erc20TransferAbi, functionName: 'approve', args: [validatedSpenderAddress, rawAmount], account: walletClient.account, chain: walletClient.chain }; // Add gas parameters if provided if (gasParams?.maxFeePerGas) txParams.maxFeePerGas = gasParams.maxFeePerGas; if (gasParams?.maxPriorityFeePerGas) txParams.maxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; // Send the transaction const hash = await walletClient.writeContract(txParams); return { txHash: hash, amount: { raw: rawAmount, formatted: amount }, token: { symbol, decimals } }; } /** * Transfer an NFT (ERC721) to an address * @param tokenAddress NFT contract address * @param toAddress Recipient address * @param tokenId Token ID to transfer * @param network Network name or chain ID * @param gasParams Optional gas fee parameters * @returns Transaction details * @throws Error if no private key is available */ export async function transferERC721( tokenAddress: string, toAddress: string, tokenId: bigint, network = DEFAULT_NETWORK, gasParams?: { maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint } ): Promise<{ txHash: Hash; tokenId: string; token: { name: string; symbol: string; }; }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); // Get wallet client from provider const walletClient = await getWalletClientFromProvider(network); // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); } const fromAddress = walletClient.account.address; const txParams: any = { address: validatedTokenAddress, abi: erc721TransferAbi, functionName: 'transferFrom', args: [fromAddress, validatedToAddress, tokenId], account: walletClient.account, chain: walletClient.chain }; // Add gas parameters if provided if (gasParams?.maxFeePerGas) txParams.maxFeePerGas = gasParams.maxFeePerGas; if (gasParams?.maxPriorityFeePerGas) txParams.maxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; // Send the transaction const hash = await walletClient.writeContract(txParams); // Get token metadata const publicClient = getPublicClient(network); const contract = getContract({ address: validatedTokenAddress, abi: erc721TransferAbi, client: publicClient }); // Get token name and symbol let name = 'Unknown'; let symbol = 'NFT'; try { [name, symbol] = await Promise.all([contract.read.name(), contract.read.symbol()]); } catch (error) { console.error('Error fetching NFT metadata:', error); } return { txHash: hash, tokenId: tokenId.toString(), token: { name, symbol } }; } /** * Transfer ERC1155 tokens to an address * @param tokenAddress Token contract * @param toAddress Recipient address * @param tokenId Token ID to transfer * @param amount Amount to transfer * @param network Network name or chain ID * @param gasParams Optional gas fee parameters * @returns Transaction details * @throws Error if no private key is available */ export async function transferERC1155( tokenAddress: string, toAddress: string, tokenId: bigint, amount: string, network = DEFAULT_NETWORK, gasParams?: { maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint } ): Promise<{ txHash: Hash; tokenId: string; amount: string; }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); // Get wallet client from provider const walletClient = await getWalletClientFromProvider(network); // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); } const fromAddress = walletClient.account.address; // Parse amount to bigint const amountBigInt = BigInt(amount); const txParams: any = { address: validatedTokenAddress, abi: erc1155TransferAbi, functionName: 'safeTransferFrom', args: [fromAddress, validatedToAddress, tokenId, amountBigInt, '0x'], account: walletClient.account, chain: walletClient.chain }; // Add gas parameters if provided if (gasParams?.maxFeePerGas) txParams.maxFeePerGas = gasParams.maxFeePerGas; if (gasParams?.maxPriorityFeePerGas) txParams.maxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; // Send the transaction const hash = await walletClient.writeContract(txParams); return { txHash: hash, tokenId: tokenId.toString(), amount }; }

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/allthatjazzleo/mantrachain-mcp'

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