dex-swap
Swap tokens on the MantraChain DEX by specifying input and output token denominations, amounts, and slippage tolerance using the Model Context Protocol.
Instructions
Execute a token swap on the DEX - must first check two tokens are available in the DEX pools by using dex-get-pools
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| memo | No | Optional memo for the transaction | |
| networkName | Yes | Name of the network to use | |
| slippage | No | Maximum acceptable slippage percentage (e.g., '1' for 1%) | |
| tokenInAmount | Yes | Amount of tokens to swap | |
| tokenInDenom | Yes | Denomination of the token to swap from | |
| tokenOutDenom | Yes | Denomination of the token to swap to |
Implementation Reference
- src/tools/dex.ts:87-102 (handler)The MCP tool handler function for 'dex-swap'. Initializes the MantraClient and calls its swap method with the provided parameters.async ({ networkName, tokenInDenom, tokenInAmount, tokenOutDenom, slippage, memo }) => { await mantraClient.initialize(networkName); const result = await mantraClient.swap({ tokenIn: { denom: tokenInDenom, amount: tokenInAmount }, tokenOutDenom, slippage, memo }); return { content: [{type: "text", text: JSON.stringify(result)}], }; }
- src/tools/dex.ts:77-86 (schema)Zod schema defining the input parameters for the dex-swap tool.{ networkName: z.string().refine(val => Object.keys(networks).includes(val), { message: "Must be a valid network name" }).describe("Name of the network to use"), tokenInDenom: z.string().describe("Denomination of the token to swap from"), tokenInAmount: z.string().describe("Amount of tokens to swap"), tokenOutDenom: z.string().describe("Denomination of the token to swap to"), slippage: z.string().optional().describe("Maximum acceptable slippage percentage (e.g., '1' for 1%)"), memo: z.string().optional().describe("Optional memo for the transaction"), },
- src/tools/dex.ts:75-103 (registration)Registration of the 'dex-swap' tool using server.tool(), including description, input schema, and handler function."dex-swap", "Execute a token swap on the DEX - must first check two tokens are available in the DEX pools by using `dex-get-pools`", { networkName: z.string().refine(val => Object.keys(networks).includes(val), { message: "Must be a valid network name" }).describe("Name of the network to use"), tokenInDenom: z.string().describe("Denomination of the token to swap from"), tokenInAmount: z.string().describe("Amount of tokens to swap"), tokenOutDenom: z.string().describe("Denomination of the token to swap to"), slippage: z.string().optional().describe("Maximum acceptable slippage percentage (e.g., '1' for 1%)"), memo: z.string().optional().describe("Optional memo for the transaction"), }, async ({ networkName, tokenInDenom, tokenInAmount, tokenOutDenom, slippage, memo }) => { await mantraClient.initialize(networkName); const result = await mantraClient.swap({ tokenIn: { denom: tokenInDenom, amount: tokenInAmount }, tokenOutDenom, slippage, memo }); return { content: [{type: "text", text: JSON.stringify(result)}], }; } );
- src/services/dex-service.ts:189-245 (helper)Core helper function in DexService that implements the swap: simulates routes, applies slippage tolerance, constructs execute message for single or multi-hop swaps, and broadcasts the transaction via wasmClient.execute.async swap(params: SwapParams): Promise<TransactionResponse> { try { // First simulate to get the expected return const { expectedReturn, routes } = await this.simulateSwap(params); // Calculate minimum to receive based on slippage const slippagePercent = params.slippage ? parseFloat(params.slippage) : 1.0; const slippageMultiplier = (100 - slippagePercent) / 100; const minToReceive = (BigInt(Math.floor(Number(expectedReturn) * slippageMultiplier))).toString(); // Execute the swap const contractAddress = this.getDexContractAddress(); let executeMsg; if (routes.length === 1) { // Single swap executeMsg = { swap: { ask_asset_denom: params.tokenOutDenom, belief_price: null, max_spread: `${slippagePercent/100}`, pool_identifier: routes[0].mantra_swap.pool_identifier, receiver: null } }; } else { // Multi-hop swap executeMsg = { execute_swap_operations: { max_spread: `${slippagePercent/100}`, minimum_receive: minToReceive, operations: routes, receiver: null } }; } const result = await this.wasmClient.execute( this.address, contractAddress, executeMsg, 'auto', params.memo, [params.tokenIn] ); return { transactionHash: result.transactionHash, explorerUrl: `${this.network.explorerUrl}/tx/${result.transactionHash}`, success: true, gasUsed: result.gasUsed.toString(), gasWanted: result.gasWanted.toString(), }; } catch (error) { throw new Error(`Failed to execute swap: ${error instanceof Error ? error.message : String(error)}`); } }
- src/mantra-client.ts:304-309 (helper)MantraClient.swap() method that delegates to the underlying DexService.swap() after ensuring initialization.async swap(params: SwapParams): Promise<TransactionResponse> { if (!this.dexService) { throw new Error('Client not initialized. Call initialize() first.'); } return this.dexService.swap(params); }