UNPKG

uniderp-mcp

Version:

> A plug-and-play MCP tool server to **send ETH**, **transfer ERC-20 tokens**, **deploy tokens**, and **interact with smart contracts** on the **UNICHAIN** — built for **Claude Desktop**, **AI agents**, and **developers.**

112 lines (111 loc) 4.51 kB
import { getContract, parseUnits, isAddress, } from "viem"; import { erc20Abi, maxUint256 } from "viem"; import { CurrencyAmount, Token, TradeType, Percent, } from "@uniswap/sdk-core"; import { JsonRpcProvider } from "@ethersproject/providers"; import { publicClient, walletClient } from "../config.js"; import { erc20abi } from "../lib/abi/erc20Abi.js"; import { AlphaRouter, getApplicableV4FeesTickspacingsHooks, SwapType, } from "@uniswap/smart-order-router"; import { ChainNativeCurrency, supportedChain } from "../chains/index.js"; import { AddressConfig } from "../addressConfig.js"; import { UniversalRouterVersion } from "@uniswap/universal-router-sdk"; import { Protocol } from "@uniswap/router-sdk"; export const getToken = async (token) => { if (token.toUpperCase() === "ETH") { return new ChainNativeCurrency(); } let address = token.toLowerCase(); let decimal; const url = "https://raw.githubusercontent.com/Uniswap/default-token-list/refs/heads/add-unichain-tokens/src/tokens/unichain.json"; const resp = await fetch(url); const tokens = await resp.json(); let symbol; if (!isAddress(address)) { const tokenInfo = tokens.find((item) => item.symbol.toLowerCase() === address); if (!tokenInfo) { throw new Error("Token not found"); } address = tokenInfo.address; decimal = tokenInfo.decimals; symbol = tokenInfo.symbol; } else { const tokenInfo = tokens.find((item) => item.address.toLowerCase() === address); if (!tokenInfo) { const contract = getContract({ address: address, abi: erc20abi, client: publicClient, }); decimal = await contract.read.decimals(); symbol = await contract.read.symbol(); } else { decimal = tokenInfo.decimals; symbol = tokenInfo.symbol; } } return new Token(supportedChain.id, address, decimal, symbol); }; export const uniswapTrade = async ({ account, inputToken, outputToken, amount, }) => { let currencyA = await getToken(inputToken); let currencyB = await getToken(outputToken); let amountDecimal = currencyA.decimals; const parseAmountIn = parseUnits(amount, amountDecimal); const amountValue = CurrencyAmount.fromRawAmount(currencyA, parseAmountIn.toString()); const universalRouterAddress = AddressConfig.UniversalRouterContract; // Routing const swapParams = { type: SwapType.UNIVERSAL_ROUTER, version: UniversalRouterVersion.V2_0, recipient: account.address, slippageTolerance: new Percent(5000, 10_000), }; const router = new AlphaRouter({ chainId: supportedChain.id, provider: new JsonRpcProvider(supportedChain.rpcUrls.default.http[0]), v4PoolParams: getApplicableV4FeesTickspacingsHooks(supportedChain.id).concat([[3000, 60, AddressConfig.UniderpHookContract]]), }); const route = await router.route(amountValue, currencyB, TradeType.EXACT_INPUT, swapParams, { protocols: [Protocol.V4], }); if (!route || !route.methodParameters) { // Handle failed request throw new Error("No trading route found"); } // Approve if token in is not native if (!currencyA.isNative) { const TokenContract = getContract({ address: currencyA.address, abi: erc20Abi, client: { wallet: walletClient(account), public: publicClient, }, }); if (!TokenContract.write || !TokenContract.write.approve || !TokenContract.read.allowance) { throw new Error("Unable to Swap Tokens"); } const allowance = (await TokenContract.read.allowance([ account.address, universalRouterAddress, ])); if (allowance < parseAmountIn) { const approveResult = await TokenContract.write.approve([ universalRouterAddress, maxUint256, ]); await publicClient.waitForTransactionReceipt({ hash: approveResult, }); } } const txHash = await walletClient(account).sendTransaction({ data: route.methodParameters.calldata, to: universalRouterAddress, value: BigInt(route.methodParameters.value), from: account.address, }); return txHash; };