Skip to main content
Glama

getApprovalStatus

Check ERC-20 token approval status for wallet addresses to identify spending risks across multiple EVM chains.

Instructions

ERC-20 토큰 승인(allowance) 상태를 조회합니다. 주요 프로토콜 자동 체크, 리스크 레벨 판정

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ownerYes지갑 주소
tokenYes토큰 심볼 (USDC, USDT) 또는 contract address
spenderNo특정 spender 주소 (미지정 시 주요 프로토콜 자동 조회)
chainNoEVM 체인ethereum

Implementation Reference

  • The core handler logic that fetches allowance data from the blockchain for a given owner, token, and spender(s), calculates risk, and caches the result.
    async function handler(args: z.infer<typeof inputSchema>): Promise<ToolResult<ApprovalStatusData>> {
      const { owner, token, spender, chain } = args;
    
      // 토큰 주소 확인
      let tokenAddress = token;
      if (!isValidAddress(token)) {
        const meta = resolveTokenMeta(token, chain);
        if (!meta) return makeError(`Token '${token}' not found on ${chain}`, "TOKEN_NOT_FOUND");
        const addresses = meta.addresses;
        const addr = addresses[chain];
        if (!addr) return makeError(`Token '${token}' not available on ${chain}`, "TOKEN_NOT_FOUND");
        tokenAddress = addr;
      }
    
      const cacheKey = `approval:${chain}:${owner}:${tokenAddress.toLowerCase()}:${spender ?? "auto"}`;
      const cached = cache.get<ApprovalStatusData>(cacheKey);
      if (cached.hit) return makeSuccess(chain, cached.data, true);
    
      try {
        const client = getClient(chain);
        const spendersToCheck = spender
          ? [{ name: "custom", address: spender }]
          : getProtocolSpenders(chain);
    
        if (spendersToCheck.length === 0) {
          return makeError(`No known protocol spenders for ${chain}`, "INVALID_INPUT");
        }
    
        const results = await Promise.allSettled(
          spendersToCheck.map(async (s) => {
            const allowance = await client.readContract({
              address: tokenAddress as `0x${string}`,
              abi: ERC20_ALLOWANCE_ABI,
              functionName: "allowance",
              args: [owner as `0x${string}`, s.address as `0x${string}`],
            });
            return { ...s, allowance: allowance as bigint };
          }),
        );
    
        const approvals: ApprovalEntry[] = [];
        for (const result of results) {
          if (result.status === "fulfilled") {
            const { name, address, allowance: raw } = result.value;
            if (raw > 0n) {
              approvals.push({
                protocol: name,
                spender: address,
                allowance: raw >= UNLIMITED_THRESHOLD ? "unlimited" : raw.toString(),
                isUnlimited: raw >= UNLIMITED_THRESHOLD,
              });
            }
          }
        }
    
        // 리스크 레벨 결정
        const unlimitedCount = approvals.filter((a) => a.isUnlimited).length;
        let riskLevel: "safe" | "moderate" | "high" = "safe";
        if (unlimitedCount >= 3) riskLevel = "high";
        else if (unlimitedCount >= 1 || approvals.length >= 3) riskLevel = "moderate";
    
        const tokenMeta = resolveTokenMeta(token);
        const data: ApprovalStatusData = {
          owner,
          token: tokenMeta?.symbol ?? token,
          tokenAddress,
          approvals,
          riskLevel,
        };
    
        cache.set(cacheKey, data, CACHE_TTL);
        return makeSuccess(chain, data, false);
      } catch (err) {
        const message = sanitizeError(err);
        return makeError(`Failed to check approvals: ${message}`, "RPC_ERROR");
      }
    }
  • Input validation schema for the getApprovalStatus tool using zod.
    const inputSchema = z.object({
      owner: z.string().describe("지갑 주소"),
      token: z.string().describe("토큰 심볼 (USDC, USDT) 또는 contract address"),
      spender: z.string().optional().describe("특정 spender 주소 (미지정 시 주요 프로토콜 자동 조회)"),
      chain: z.enum(SUPPORTED_CHAINS).default("ethereum").describe("EVM 체인"),
    });
  • Registration of the getApprovalStatus tool with the McpServer.
    export function register(server: McpServer) {
      server.tool(
        "getApprovalStatus",
        "ERC-20 토큰 승인(allowance) 상태를 조회합니다. 주요 프로토콜 자동 체크, 리스크 레벨 판정",
        inputSchema.shape,
        async (args) => {
          const result = await handler(args as z.infer<typeof inputSchema>);
          return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
        },
      );
    }

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/calintzy/evmscope'

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