Skip to main content
Glama
lordbasilaiassistant-sudo

base-price-oracle-mcp

get_price_history

Retrieve historical price data for tokens on Base by querying DEX pool swap events. Specify token address, time intervals, and data points to analyze price trends.

Instructions

Get recent price data points by querying swap events from DEX pools

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
token_addressYesToken contract address on Base
periodsNoNumber of data points to return
intervalNoTime interval between points (e.g. 1h, 15m, 1d)1h

Implementation Reference

  • The tool `get_price_history` is defined and implemented here as an MCP tool, which queries DEX pools for recent swap events to generate price history.
    server.tool(
      "get_price_history",
      "Get recent price data points by querying swap events from DEX pools",
      {
        token_address: z.string().describe("Token contract address on Base"),
        periods: z.number().default(24).describe("Number of data points to return"),
        interval: z.string().default("1h").describe("Time interval between points (e.g. 1h, 15m, 1d)"),
      },
      async ({ token_address, periods, interval }) => {
        try {
          const quoteAddress = WETH;
          const [tokenDecimals, quoteDecimals, tokenSymbol] = await Promise.all([
            getTokenDecimals(token_address),
            getTokenDecimals(quoteAddress),
            getTokenSymbol(token_address),
          ]);
    
          const pools = await findAllPools(token_address, quoteAddress);
          if (pools.length === 0) {
            return { content: [{ type: "text" as const, text: `No DEX pools found for ${token_address} on Base.` }] };
          }
    
          // Use the pool with most liquidity (V2: highest reserves, V3: highest liquidity)
          const bestPool = pools[0];
          const blocksPerInterval = intervalToBlocks(interval);
          const totalBlocks = blocksPerInterval * periods;
    
          // Cap at ~50000 blocks to avoid RPC limits
          const lookback = Math.min(totalBlocks, 50000);
          const swaps = await getSwapHistory(bestPool, tokenDecimals, quoteDecimals, lookback);
    
          if (swaps.length === 0) {
            // Fall back to current price only
            const currentPrice = calculatePrice(bestPool, tokenDecimals, quoteDecimals);
            return {
              content: [{
                type: "text" as const,
                text: JSON.stringify({
                  token: token_address,
                  symbol: tokenSymbol,
                  message: "No recent swap events found. Current spot price from reserves:",
                  currentPrice: formatEth(currentPrice),
                  dex: bestPool.dex,
                }, null, 2),
              }],
            };
          }
    
          // Bucket swaps into intervals
          const now = swaps[swaps.length - 1].timestamp;
          const intervalSeconds = blocksPerInterval * 2; // 2s per block
          const buckets: PricePoint[][] = [];
    
          for (let i = 0; i < periods; i++) {
            const bucketEnd = now - i * intervalSeconds;
            const bucketStart = bucketEnd - intervalSeconds;
            const bucketSwaps = swaps.filter(
              (s) => s.timestamp > bucketStart && s.timestamp <= bucketEnd
            );
            buckets.unshift(bucketSwaps);
          }
    
          const dataPoints = buckets.map((bucket, i) => {
            const time = now - (periods - 1 - i) * intervalSeconds;
            if (bucket.length === 0) {
              return { timestamp: time, price: null, swapCount: 0 };
            }
            const avgPrice = bucket.reduce((s, p) => s + p.price, 0) / bucket.length;
            return {
              timestamp: time,
              price: formatEth(avgPrice),
              swapCount: bucket.length,
            };
          });
    
          return {
            content: [{
              type: "text" as const,
              text: JSON.stringify({
                token: token_address,
                symbol: tokenSymbol,
                dex: bestPool.dex,
                interval,
                periods: dataPoints.length,
                totalSwaps: swaps.length,
                data: dataPoints,
              }, null, 2),
            }],
          };
        } catch (err: unknown) {
          const msg = err instanceof Error ? err.message : String(err);
          return { content: [{ type: "text" as const, text: `Error: ${msg}` }] };
        }
      }
    );

Latest Blog Posts

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/lordbasilaiassistant-sudo/base-price-oracle-mcp'

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