Skip to main content
Glama
covalenthq

GoldRush MCP Server

by covalenthq

historical_token_balances

Retrieve historical token balances for any wallet address at a specific block height or date, supporting native tokens, ERC20 tokens, and optional NFTs across multiple blockchain networks.

Instructions

Commonly used to fetch the historical native and fungible (ERC20) tokens held by an address at a given block height or dateRequired: chainName (blockchain network), address (wallet address). Optional: quoteCurrency for value conversion, blockHeight or date to specify point in time, nft (include NFTs, default false), noNftFetch, noSpam, and noNftAssetMetadata (all default true). Returns token balances as they existed at the specified historical point.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chainNameYesThe blockchain network to query (e.g., 'eth-mainnet', 'matic-mainnet', 'bsc-mainnet').
addressYesThe wallet address to get historical token balances for. Must be a valid blockchain address.
quoteCurrencyNoCurrency to quote token values in (e.g., 'USD', 'EUR'). If not specified, uses default quote currency.
nftNoInclude NFT token balances in the response. Default is false.
noNftFetchNoSkip fetching NFT metadata. Default is true for better performance.
noSpamNoFilter out spam/scam tokens from results. Default is true.
noNftAssetMetadataNoSkip fetching NFT asset metadata. Default is true for better performance.
blockHeightNoSpecific block height to get historical balances from. Cannot be used with date parameter.
dateNoSpecific date to get historical balances from (YYYY-MM-DD format). Cannot be used with blockHeight parameter.

Implementation Reference

  • The 'historical_token_balances' tool handler definition and implementation using the GoldRush SDK.
    server.tool(
        "historical_token_balances",
        "Commonly used to fetch the historical native and fungible (ERC20) tokens held by an address at a given block height or date" +
            "Required: chainName (blockchain network), address (wallet address). " +
            "Optional: quoteCurrency for value conversion, blockHeight or date to specify point in time, " +
            "nft (include NFTs, default false), noNftFetch, noSpam, and noNftAssetMetadata (all default true). " +
            "Returns token balances as they existed at the specified historical point.",
        {
            chainName: z
                .enum(Object.values(ChainName) as [string, ...string[]])
                .describe(
                    "The blockchain network to query (e.g., 'eth-mainnet', 'matic-mainnet', 'bsc-mainnet')."
                ),
            address: z
                .string()
                .describe(
                    "The wallet address to get historical token balances for. Must be a valid blockchain address."
                ),
            quoteCurrency: z
                .enum(Object.values(validQuoteValues) as [string, ...string[]])
                .optional()
                .describe(
                    "Currency to quote token values in (e.g., 'USD', 'EUR'). If not specified, uses default quote currency."
                ),
            nft: z
                .boolean()
                .optional()
                .default(false)
                .describe(
                    "Include NFT token balances in the response. Default is false."
                ),
            noNftFetch: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Skip fetching NFT metadata. Default is true for better performance."
                ),
            noSpam: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Filter out spam/scam tokens from results. Default is true."
                ),
            noNftAssetMetadata: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Skip fetching NFT asset metadata. Default is true for better performance."
                ),
            blockHeight: z
                .number()
                .optional()
                .describe(
                    "Specific block height to get historical balances from. Cannot be used with date parameter."
                ),
            date: z
                .string()
                .optional()
                .describe(
                    "Specific date to get historical balances from (YYYY-MM-DD format). Cannot be used with blockHeight parameter."
                ),
        },
        async (params) => {
            try {
                const response =
                    await goldRushClient.BalanceService.getHistoricalTokenBalancesForWalletAddress(
                        params.chainName as Chain,
                        params.address,
                        {
                            quoteCurrency: params.quoteCurrency as Quote,
                            nft: params.nft,
                            noNftFetch: params.noNftFetch,
                            noSpam: params.noSpam,
                            noNftAssetMetadata: params.noNftAssetMetadata,
                            blockHeight: params.blockHeight,
                            date: params.date,
                        }
                    );
                return {
                    content: [
                        {
                            type: "text",
                            text: stringifyWithBigInt(response.data),
                        },
                    ],
                };
            } catch (error) {
                return {
                    content: [{ type: "text", text: `Error: ${error}` }],
                    isError: true,
                };
            }
        }
    );
  • Zod schema definition for the 'historical_token_balances' tool inputs.
    {
        chainName: z
            .enum(Object.values(ChainName) as [string, ...string[]])
            .describe(
                "The blockchain network to query (e.g., 'eth-mainnet', 'matic-mainnet', 'bsc-mainnet')."
            ),
        address: z
            .string()
            .describe(
                "The wallet address to get historical token balances for. Must be a valid blockchain address."
            ),
        quoteCurrency: z
            .enum(Object.values(validQuoteValues) as [string, ...string[]])
            .optional()
            .describe(
                "Currency to quote token values in (e.g., 'USD', 'EUR'). If not specified, uses default quote currency."
            ),
        nft: z
            .boolean()
            .optional()
            .default(false)
            .describe(
                "Include NFT token balances in the response. Default is false."
            ),
        noNftFetch: z
            .boolean()
            .optional()
            .default(true)
            .describe(
                "Skip fetching NFT metadata. Default is true for better performance."
            ),
        noSpam: z
            .boolean()
            .optional()
            .default(true)
            .describe(
                "Filter out spam/scam tokens from results. Default is true."
            ),
        noNftAssetMetadata: z
            .boolean()
            .optional()
            .default(true)
            .describe(
                "Skip fetching NFT asset metadata. Default is true for better performance."
            ),
        blockHeight: z
            .number()
            .optional()
            .describe(
                "Specific block height to get historical balances from. Cannot be used with date parameter."
            ),
        date: z
            .string()
            .optional()
            .describe(
                "Specific date to get historical balances from (YYYY-MM-DD format). Cannot be used with blockHeight parameter."
            ),
    },
  • Registration of the 'historical_token_balances' tool within the MCP server.
    server.tool(
        "historical_token_balances",
        "Commonly used to fetch the historical native and fungible (ERC20) tokens held by an address at a given block height or date" +
            "Required: chainName (blockchain network), address (wallet address). " +
            "Optional: quoteCurrency for value conversion, blockHeight or date to specify point in time, " +
            "nft (include NFTs, default false), noNftFetch, noSpam, and noNftAssetMetadata (all default true). " +
            "Returns token balances as they existed at the specified historical point.",
        {
            chainName: z
                .enum(Object.values(ChainName) as [string, ...string[]])
                .describe(
                    "The blockchain network to query (e.g., 'eth-mainnet', 'matic-mainnet', 'bsc-mainnet')."
                ),
            address: z
                .string()
                .describe(
                    "The wallet address to get historical token balances for. Must be a valid blockchain address."
                ),
            quoteCurrency: z
                .enum(Object.values(validQuoteValues) as [string, ...string[]])
                .optional()
                .describe(
                    "Currency to quote token values in (e.g., 'USD', 'EUR'). If not specified, uses default quote currency."
                ),
            nft: z
                .boolean()
                .optional()
                .default(false)
                .describe(
                    "Include NFT token balances in the response. Default is false."
                ),
            noNftFetch: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Skip fetching NFT metadata. Default is true for better performance."
                ),
            noSpam: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Filter out spam/scam tokens from results. Default is true."
                ),
            noNftAssetMetadata: z
                .boolean()
                .optional()
                .default(true)
                .describe(
                    "Skip fetching NFT asset metadata. Default is true for better performance."
                ),
            blockHeight: z
                .number()
                .optional()
                .describe(
                    "Specific block height to get historical balances from. Cannot be used with date parameter."
                ),
            date: z
                .string()
                .optional()
                .describe(
                    "Specific date to get historical balances from (YYYY-MM-DD format). Cannot be used with blockHeight parameter."
                ),
        },
        async (params) => {
            try {
                const response =
                    await goldRushClient.BalanceService.getHistoricalTokenBalancesForWalletAddress(
                        params.chainName as Chain,
                        params.address,
                        {
                            quoteCurrency: params.quoteCurrency as Quote,
                            nft: params.nft,
                            noNftFetch: params.noNftFetch,
                            noSpam: params.noSpam,
                            noNftAssetMetadata: params.noNftAssetMetadata,
                            blockHeight: params.blockHeight,
                            date: params.date,
                        }
                    );
                return {
                    content: [
                        {
                            type: "text",
                            text: stringifyWithBigInt(response.data),
                        },
                    ],
                };
            } catch (error) {
                return {
                    content: [{ type: "text", text: `Error: ${error}` }],
                    isError: true,
                };
            }
        }
    );
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses return behavior ('Returns token balances as they existed at the specified historical point') and default values for boolean flags (nft=false, others=true). However, it lacks critical behavioral details such as safety profile (read-only vs destructive), rate limits, or data availability constraints for historical blocks.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description suffers from poor formatting: it is a single run-on sentence with a critical missing space ('dateRequired' instead of 'date. Required:'), significantly hindering readability. While the information density is appropriate, the structural execution is flawed, forcing the reader to parse a dense block of text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter tool with no output schema, the description provides the minimum necessary context: what is returned (historical balances) and key parameters. However, given the complexity (multichain, historical state, NFT toggles), it could enhance completeness by describing the output format or error conditions (e.g., invalid block height).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, establishing a baseline of 3. The description adds value by grouping parameters into 'Required' and 'Optional' categories and reiterating default values, but largely repeats information already present in the schema property descriptions rather than adding semantic meaning beyond the structured data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'fetch[es] the historical native and fungible (ERC20) tokens held by an address at a given block height or date.' The specific verb (fetch), resource (historical token balances), and temporal scoping (block height/date) effectively distinguish it from sibling tools like 'token_balances' (current) and 'historical_portfolio_value' (value vs holdings).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description uses 'Commonly used to' which implies the primary use case (historical lookup), but it fails to explicitly state when NOT to use this tool (e.g., for current balances) or explicitly name alternatives like 'token_balances'. It provides implicit context but lacks explicit when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/covalenthq/goldrush-mcp-server'

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