UNPKG

run402-mcp

Version:

MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.

72 lines • 3.29 kB
/** * The wallet's on-chain token balances, one per network a rail pays on, under * the snake_case keys `run402 wallets balance`, `run402 status`, and * `run402 init` share (spec `status-account-balances`). Test money and real * money are separate keys: a sum alone would hide which one the wallet holds. * * Every read is best-effort: a network whose read fails is `null`, never 0. */ import { PATH_USD, TEMPO_MAINNET, TEMPO_MODERATO } from "./tempo.js"; const BALANCE_OF_ABI = [{ name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }] }]; const USDC_MAINNET = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; const USDC_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; export const ALL_ON_CHAIN_BALANCE_KEYS = [ "base_mainnet_usd_micros", "base_sepolia_usd_micros", "tempo_mainnet_pathusd_micros", "tempo_moderato_pathusd_micros", ]; /** * The networks a rail pays on: Tempo for `mpp`; Base for `x402` and for * `lightning`, whose fallback is x402. */ export function railBalanceKeys(rail) { return rail === "mpp" ? ["tempo_mainnet_pathusd_micros", "tempo_moderato_pathusd_micros"] : ["base_mainnet_usd_micros", "base_sepolia_usd_micros"]; } async function defaultReader() { const { createPublicClient, defineChain, http } = await import("viem"); const { base, baseSepolia } = await import("viem/chains"); const tempo = (chain) => defineChain({ id: chain.id, name: chain.name, nativeCurrency: { name: "pathUSD", symbol: "pathUSD", decimals: 6 }, rpcUrls: { default: { http: [chain.rpcUrl] } }, }); const targets = { base_mainnet_usd_micros: { chain: base, token: USDC_MAINNET }, base_sepolia_usd_micros: { chain: baseSepolia, token: USDC_SEPOLIA }, tempo_mainnet_pathusd_micros: { chain: tempo(TEMPO_MAINNET), token: PATH_USD }, tempo_moderato_pathusd_micros: { chain: tempo(TEMPO_MODERATO), token: PATH_USD }, }; return async (key, address) => { const { chain, token } = targets[key]; const client = createPublicClient({ chain: chain, transport: http() }); const raw = await client.readContract({ address: token, abi: BALANCE_OF_ABI, functionName: "balanceOf", args: [address], }); return Number(raw); }; } /** Read the given networks in parallel; a failed read is `null`. */ export async function readOnChainBalances(address, keys = ALL_ON_CHAIN_BALANCE_KEYS, reader) { let read; try { read = reader ?? await defaultReader(); } catch { return Object.fromEntries(keys.map((key) => [key, null])); } const values = await Promise.all(keys.map((key) => read(key, address).catch(() => null))); return Object.fromEntries(keys.map((key, i) => [key, values[i]])); } /** The sum over `keys`, or null when every one of them is unknown. */ export function sumOnChainBalances(balances, keys) { const known = keys.map((key) => balances[key]).filter((value) => typeof value === "number"); return known.length === 0 ? null : known.reduce((total, value) => total + value, 0); } //# sourceMappingURL=onchain-balances.js.map