ref_finance_get_pools
Search for liquidity pools on Ref Finance by token pair, returning pools prioritized by higher liquidity and better rates.
Instructions
Search for liquidity pools on the Ref Finance exchange contract based on two tokens. Prioritize pools with higher liquidity and better rates for the user.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tokenA | Yes | ||
| tokenB | Yes | ||
| networkId | No | mainnet |
Implementation Reference
- src/services.ts:2151-2233 (registration)Registration of the 'ref_finance_get_pools' MCP tool. Uses mcp.tool() with name 'ref_finance_get_pools', defines input schema (tokenA, tokenB, networkId), and the handler callback.
mcp.tool( 'ref_finance_get_pools', noLeadingWhitespace` Search for liquidity pools on the Ref Finance exchange contract based on two tokens. Prioritize pools with higher liquidity and better rates for the user.`, { tokenA: z.object({ contractId: z.string().describe('The first token contract id'), symbol: z.string().describe('The first token symbol'), }), tokenB: z.object({ contractId: z.string().describe('The second token contract id'), symbol: z.string().describe('The second token symbol'), }), networkId: z.enum(['testnet', 'mainnet']).default('mainnet'), }, async (args, _) => { const connection = await connect({ networkId: args.networkId, keyStore: keystore, nodeUrl: getEndpointsByNetwork(args.networkId)[0]!, }); const tokenAContractAccountResult = await getAccount( args.tokenA.contractId, connection, ); if (!tokenAContractAccountResult.ok) { return { content: [ { type: 'text', text: `Error: ${tokenAContractAccountResult.error}`, }, ], }; } const tokenA = tokenAContractAccountResult.value; const tokenBContractAccountResult = await getAccount( args.tokenB.contractId, connection, ); if (!tokenBContractAccountResult.ok) { return { content: [ { type: 'text', text: `Error: ${tokenBContractAccountResult.error}`, }, ], }; } const tokenB = tokenBContractAccountResult.value; const poolsInfoResult = await refFinanceGetPoolsInfo(connection); if (!poolsInfoResult.ok) { return { content: [{ type: 'text', text: `Error: ${poolsInfoResult.error}` }], }; } const filteredPools = poolsInfoResult.value.filter( (pool) => pool.tokenIds.includes(tokenA.accountId) && pool.tokenIds.includes(tokenB.accountId), ); if (filteredPools.length === 0) { return { content: [ { type: 'text', text: `No pool found for ${args.tokenA.contractId} and ${args.tokenB.contractId}`, }, ], }; } return { content: [{ type: 'text', text: stringify_bigint(filteredPools) }], }; }, ); - src/services.ts:2167-2233 (handler)Handler for 'ref_finance_get_pools' tool. Connects to NEAR, validates token contracts, calls refFinanceGetPoolsInfo(), filters pools matching both token IDs, and returns the result.
async (args, _) => { const connection = await connect({ networkId: args.networkId, keyStore: keystore, nodeUrl: getEndpointsByNetwork(args.networkId)[0]!, }); const tokenAContractAccountResult = await getAccount( args.tokenA.contractId, connection, ); if (!tokenAContractAccountResult.ok) { return { content: [ { type: 'text', text: `Error: ${tokenAContractAccountResult.error}`, }, ], }; } const tokenA = tokenAContractAccountResult.value; const tokenBContractAccountResult = await getAccount( args.tokenB.contractId, connection, ); if (!tokenBContractAccountResult.ok) { return { content: [ { type: 'text', text: `Error: ${tokenBContractAccountResult.error}`, }, ], }; } const tokenB = tokenBContractAccountResult.value; const poolsInfoResult = await refFinanceGetPoolsInfo(connection); if (!poolsInfoResult.ok) { return { content: [{ type: 'text', text: `Error: ${poolsInfoResult.error}` }], }; } const filteredPools = poolsInfoResult.value.filter( (pool) => pool.tokenIds.includes(tokenA.accountId) && pool.tokenIds.includes(tokenB.accountId), ); if (filteredPools.length === 0) { return { content: [ { type: 'text', text: `No pool found for ${args.tokenA.contractId} and ${args.tokenB.contractId}`, }, ], }; } return { content: [{ type: 'text', text: stringify_bigint(filteredPools) }], }; }, ); - src/services.ts:309-352 (helper)Helper function refFinanceGetPoolsInfo() that fetches all pools from the Ref Finance contract using paginated view calls to 'get_pools' and 'get_number_of_pools' methods.
export const refFinanceGetPoolsInfo = async ( connection: Near, ): Promise<Result<Pool[], Error>> => { try { const refConfig = refGetConfig(connection.connection.networkId); const refAccount = await connection.account(refConfig.REF_FI_CONTRACT_ID); // get the total number of pools const numberOfPools = (await refAccount.viewFunction({ contractId: refConfig.REF_FI_CONTRACT_ID, methodName: 'get_number_of_pools', args: {}, })) as unknown as number; // Concurrently get all pools const perPage = 1024; const allResults = ( await mapSemaphore( Array.from( { length: Math.ceil(numberOfPools / perPage) }, (_, i) => i * perPage, ), 4, async (index) => { const contractResult = (await refAccount.viewFunction({ contractId: refConfig.REF_FI_CONTRACT_ID, methodName: 'get_pools', args: { from_index: index, limit: perPage }, })) as unknown as PoolRPCView[]; return contractResult.map((rawPool, i) => parsePool(rawPool, i + index), ); }, ) ).flat(); return { ok: true, value: allResults, }; } catch (e) { return { ok: false, error: new Error(e as string) }; } }; - src/services.ts:2156-2166 (schema)Input schema for the 'ref_finance_get_pools' tool: tokenA (contractId, symbol), tokenB (contractId, symbol), and optional networkId.
{ tokenA: z.object({ contractId: z.string().describe('The first token contract id'), symbol: z.string().describe('The first token symbol'), }), tokenB: z.object({ contractId: z.string().describe('The second token contract id'), symbol: z.string().describe('The second token symbol'), }), networkId: z.enum(['testnet', 'mainnet']).default('mainnet'), }, - src/utils.ts:155-172 (helper)Helper parsePool() function that converts raw pool RPC view data into the Pool interface used by the tool.
export const parsePool = (pool: PoolRPCView, id?: number): Pool => ({ id: Number(typeof id === 'number' ? id : pool.id), tokenIds: pool.token_account_ids, supplies: pool.amounts.reduce( (acc: Record<string, string>, amount: string, i: number) => { if (pool.token_account_ids[i] !== undefined) { acc[pool.token_account_ids[i]] = amount; } return acc; }, {}, ), fee: pool.total_fee, shareSupply: pool.shares_total_supply, tvl: pool.tvl, token0_ref_price: pool.token0_ref_price, pool_kind: pool.pool_kind, });