UNPKG

@iqai/mcp-bamm

Version:

MCP server for bamm (borrow automated market maker)

91 lines (90 loc) 3.63 kB
import dedent from "dedent"; import { BAMM_ADDRESSES } from "../constants.js"; import { BAMM_FACTORY_ABI } from "../lib/bamm-factory.abi.js"; import { BAMM_ABI } from "../lib/bamm.abi.js"; import formatNumber from "../lib/format-number.js"; export class BammPoolsStatsService { walletService; // Frax API endpoint for all Fraxswap pools endpoint = "https://api.frax.finance/v2/fraxswap/pools"; constructor(walletService) { this.walletService = walletService; } async getPoolsStats() { const publicClient = this.walletService.getPublicClient(); const zeroAddress = "0x0000000000000000000000000000000000000000"; // 1. Get the list of all BAMM addresses from the factory. const bammsOnChain = await publicClient.readContract({ address: BAMM_ADDRESSES.FACTORY, abi: BAMM_FACTORY_ABI, functionName: "bammsArray", args: [], }); // 2. Build a mapping: underlying Fraxswap pair address -> BAMM address. const pairToBammMap = new Map(); for (const bammAddress of bammsOnChain) { if (bammAddress === zeroAddress) continue; // Get the Fraxswap pair address from this BAMM contract. const pairAddress = await publicClient.readContract({ address: bammAddress, abi: BAMM_ABI, functionName: "pair", args: [], }); if (pairAddress && pairAddress !== zeroAddress) { pairToBammMap.set(pairAddress.toLowerCase(), bammAddress); } } // 3. Fetch the full list of pools from the Frax API endpoint. const response = await fetch(this.endpoint); if (!response.ok) { throw new Error(`Failed to fetch pools: ${response.statusText}`); } const data = await response.json(); // Map the API response to our PoolStats type and add placeholder fields. // biome-ignore lint/suspicious/noExplicitAny: <explanation> const allPools = data.pools.map((pool) => ({ ...pool, bammAddress: "", bammApr: 0, fraxswapApr: 0, })); // 4. Filter the API pools to only include those with a matching pair address. const filteredPools = []; for (const pool of allPools) { const poolPair = pool.poolAddress.toLowerCase(); if (pairToBammMap.has(poolPair)) { // Set the BAMM address from our mapping. pool.bammAddress = pairToBammMap.get(poolPair) ?? ""; filteredPools.push(pool); } } filteredPools.sort((a, b) => b.tvl - a.tvl); return filteredPools; } formatPoolsStats(pools) { if (pools.length === 0) { return "📊 No BAMM Pools Found"; } const formattedStats = pools .map((pool) => { const poolName = `${pool.token0Symbol}/${pool.token1Symbol}`; return dedent ` 📊 Pool: ${poolName} - Pool Address: ${pool.poolAddress} - BAMM Address: ${pool.bammAddress} - TVL: $${formatNumber(pool.tvl || 0)} - ${pool.token0Symbol} Locked: ${formatNumber(pool.token0AmountLocked || 0)} - ${pool.token1Symbol} Locked: ${formatNumber(pool.token1AmountLocked || 0)} `; }) .join("\n\n"); return dedent ` 📊 *BAMM Pool Stats:* Total: ${pools.length} ${formattedStats} `; } } //# sourceMappingURL=pool-stats.js.map