{"version":3,"sources":["../src/queries/portfolio.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport { PublicKey } from '@solana/web3.js';\nimport {\n  EthCallQueryRequest,\n  EthCallQueryResponse,\n  PerChainQueryRequest,\n  QueryRequest,\n  QueryResponse,\n  SolanaAccountQueryRequest,\n  SolanaAccountQueryResponse,\n  hexToUint8Array,\n  isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WalletManager } from '../core/WalletManager.js';\nimport { getAllTokens, isNativeToken } from '../constants/tokens.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryPortfolioNetwork = 'testnet' | 'mainnet';\n\nexport type QueryPortfolioOptions = {\n  /** Max response age in seconds (default: 60). */\n  maxAge?: number;\n  network?: QueryPortfolioNetwork;\n  /** Maximum attempts including the first try (default: 4). */\n  maxAttempts?: number;\n  /** Cache TTL in ms (default: 30_000). */\n  cacheTtlMs?: number;\n  /** Request timeout in ms (default: 15_000 for testnet, 10_000 for mainnet). */\n  timeout?: number;\n  /** Override Query Proxy endpoint. */\n  endpoint?: string;\n  /** Override per-chain RPC URLs used for block tag lookups. */\n  rpcUrls?: Record<number, string>;\n  /** Override derived vault addresses for specific Wormhole chain IDs. */\n  vaultAddresses?: Record<number, string>;\n  /** Override token lists (ERC20 only) for specific Wormhole chain IDs. */\n  evmTokenAddresses?: Record<number, string[]>;\n  /** Additional Solana accounts to include in the Solana account query (base58). */\n  solanaAccounts?: string[];\n  /** Optional USD prices by symbol/address for aggregation (e.g. { USDC: 1 }). */\n  pricesUsd?: Record<string, number>;\n};\n\nexport type PortfolioBalance = {\n  assetId: string;\n  amount: bigint;\n  decimals?: number;\n  symbol?: string;\n  usdValue?: number;\n};\n\nexport type PortfolioChainErrorCode =\n  | 'UNSUPPORTED_CHAIN'\n  | 'MISSING_VAULT'\n  | 'MISSING_TOKENS'\n  | 'ATTESTATION_STALE'\n  | 'DECODE_ERROR';\n\nexport type PortfolioChainResult = {\n  wormholeChainId: number;\n  chainName?: string;\n  vaultAddress?: string;\n  blockTime?: number;\n  balances: PortfolioBalance[];\n  error?: {\n    code: PortfolioChainErrorCode;\n    message: string;\n  };\n};\n\nexport type PortfolioResult = {\n  proof: Uint8Array;\n  totalUsd?: number;\n  chains: PortfolioChainResult[];\n};\n\nexport type QueryPortfolioErrorCode =\n  | 'INVALID_ARGUMENT'\n  | 'NETWORK_ERROR'\n  | 'PROXY_HTTP_ERROR'\n  | 'PROXY_RESPONSE_INVALID'\n  | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryPortfolioError extends Error {\n  code: QueryPortfolioErrorCode;\n  cause?: unknown;\n\n  constructor(code: QueryPortfolioErrorCode, message: string, cause?: unknown) {\n    super(message);\n    this.name = 'QueryPortfolioError';\n    this.code = code;\n    this.cause = cause;\n  }\n}\n\ntype CacheEntry = { expiresAt: number; value: PortfolioResult };\nconst PORTFOLIO_CACHE = new Map<string, CacheEntry>();\n\nfunction resolveNetwork(options?: QueryPortfolioOptions): QueryPortfolioNetwork {\n  if (options?.network) return options.network;\n\n  const envCandidates = [\n    (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n    (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n    (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n    (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n  ].filter(Boolean);\n\n  const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n  if (env === 'mainnet' || env === 'testnet') return env;\n\n  return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n  const total = parts.reduce((sum, p) => sum + p.length, 0);\n  const out = new Uint8Array(total);\n  let offset = 0;\n  for (const p of parts) {\n    out.set(p, offset);\n    offset += p.length;\n  }\n  return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n  const chunks: Uint8Array[] = [];\n\n  for (const sig of signatures) {\n    if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n      throw new QueryPortfolioError(\n        'PROXY_RESPONSE_INVALID',\n        `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n      );\n    }\n    // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n    chunks.push(hexToUint8Array(`0x${sig}`));\n  }\n\n  return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n  if (typeof bytes !== 'string' || bytes.length === 0) {\n    throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n  }\n\n  if (isValidHexString(bytes)) {\n    return hexToUint8Array(bytes);\n  }\n\n  try {\n    if (typeof atob === 'function') {\n      const raw = atob(bytes);\n      const arr = new Uint8Array(raw.length);\n      for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n      return arr;\n    }\n  } catch {\n    // ignore\n  }\n\n  try {\n    return new Uint8Array(Buffer.from(bytes, 'base64'));\n  } catch (cause) {\n    throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n  }\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Simple rate limiter for Wormhole Query Proxy (6 requests/second limit).\n * Queues requests and releases them at the allowed rate.\n */\nconst rateLimiter = {\n  queue: [] as Array<() => void>,\n  lastRequest: 0,\n  minInterval: 170, // ~6 req/s with buffer\n  \n  async acquire(): Promise<void> {\n    return new Promise((resolve) => {\n      const tryAcquire = () => {\n        const now = Date.now();\n        const elapsed = now - rateLimiter.lastRequest;\n        if (elapsed >= rateLimiter.minInterval) {\n          rateLimiter.lastRequest = now;\n          resolve();\n        } else {\n          setTimeout(tryAcquire, rateLimiter.minInterval - elapsed);\n        }\n      };\n      tryAcquire();\n    });\n  }\n};\n\nasync function withExponentialBackoff<T>(fn: () => Promise<T>, maxAttempts: number): Promise<T> {\n  let attempt = 0;\n  let lastError: unknown;\n\n  while (attempt < maxAttempts) {\n    try {\n      return await fn();\n    } catch (err) {\n      lastError = err;\n      attempt += 1;\n      if (attempt >= maxAttempts) break;\n\n      const baseMs = 250;\n      const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n      const jitterMs = Math.floor(Math.random() * 100);\n      await sleep(backoffMs + jitterMs);\n    }\n  }\n\n  throw lastError;\n}\n\nfunction getChainConfigs(network: QueryPortfolioNetwork) {\n  return network === 'testnet' ? TESTNET_CHAINS : MAINNET_CHAINS;\n}\n\nfunction getProxyEndpoint(network: QueryPortfolioNetwork, options?: QueryPortfolioOptions): string {\n  if (options?.endpoint) return options.endpoint;\n  return network === 'testnet' ? WORMHOLE_QUERY_PROXY_URLS.testnet : WORMHOLE_QUERY_PROXY_URLS.mainnet;\n}\n\nfunction getDefaultPortfolioChains(network: QueryPortfolioNetwork): number[] {\n  // Include hub (Base Sepolia 10004) and spoke chains\n  return network === 'testnet' ? [10004, 10005, 10003, 1] : [30, 24, 23, 1];\n}\n\nfunction normalizeHex32(hex: string): Uint8Array {\n  if (typeof hex !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(hex)) {\n    throw new QueryPortfolioError('INVALID_ARGUMENT', `Invalid userKeyHash (expected 0x + 32 bytes hex): ${hex}`);\n  }\n  return new Uint8Array(Buffer.from(hex.slice(2), 'hex'));\n}\n\nfunction deriveSolanaVaultAddress(programIdBase58: string, userKeyHash: string): string {\n  const programId = new PublicKey(programIdBase58);\n  const keyHashBytes = normalizeHex32(userKeyHash);\n  const [vaultPda] = PublicKey.findProgramAddressSync([Buffer.from('vault'), Buffer.from(keyHashBytes)], programId);\n  return vaultPda.toBase58();\n}\n\nfunction makeCacheKey(userKeyHash: string, apiKey: string, options: QueryPortfolioOptions | undefined, chainIds: number[]) {\n  // Do not include apiKey in the cache key; it should not affect the data.\n  const payload = {\n    userKeyHash,\n    network: resolveNetwork(options),\n    chainIds: [...chainIds].sort((a, b) => a - b),\n    vaultAddresses: options?.vaultAddresses ?? null,\n    evmTokenAddresses: options?.evmTokenAddresses ?? null,\n    solanaAccounts: options?.solanaAccounts ?? null,\n    endpoint: options?.endpoint ?? null,\n  };\n\n  void apiKey;\n  return JSON.stringify(payload);\n}\n\nfunction safeNumberFromBigint(b: bigint): number {\n  const n = Number(b);\n  return Number.isFinite(n) ? n : 0;\n}\n\nfunction priceLookup(pricesUsd: Record<string, number> | undefined, symbol?: string, assetId?: string): number | undefined {\n  if (!pricesUsd) return undefined;\n  if (symbol && pricesUsd[symbol] != null) return pricesUsd[symbol];\n  if (assetId && pricesUsd[assetId] != null) return pricesUsd[assetId];\n  return undefined;\n}\n\nfunction sumUsd(balances: PortfolioBalance[], pricesUsd?: Record<string, number>): number | undefined {\n  let total = 0;\n  let any = false;\n\n  for (const b of balances) {\n    const p = priceLookup(pricesUsd, b.symbol, b.assetId);\n    if (p == null) continue;\n    if (b.decimals == null) continue;\n\n    const denom = 10 ** b.decimals;\n    const amount = Number(b.amount) / denom;\n    if (!Number.isFinite(amount)) continue;\n    total += amount * p;\n    any = true;\n  }\n\n  return any ? total : undefined;\n}\n\nasync function getRecentBlockTag(rpcUrl: string): Promise<number> {\n  const provider = new ethers.JsonRpcProvider(rpcUrl);\n  const latest = await provider.getBlockNumber();\n  return Math.max(0, latest - 2);\n}\n\nfunction encodeErc20BalanceCalls(vaultAddress: string, tokenAddresses: string[]): { to: string; data: string }[] {\n  const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n  return tokenAddresses.map((token) => ({\n    to: token,\n    data: iface.encodeFunctionData('balanceOf', [vaultAddress]),\n  }));\n}\n\nfunction decodeErc20Balances(results: string[], tokenAddresses: string[]): bigint[] {\n  const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n  const out: bigint[] = [];\n  for (let i = 0; i < tokenAddresses.length; i++) {\n    const data = results[i];\n    if (!data || data === '0x') {\n      out.push(0n);\n      continue;\n    }\n    const decoded = iface.decodeFunctionResult('balanceOf', data);\n    out.push(decoded[0] as bigint);\n  }\n  return out;\n}\n\n/**\n * Fetch Guardian-attested vault balances across multiple chains in one Query Proxy request.\n *\n * Notes:\n * - EVM balances are ERC20-only via `eth_call` (native ETH is not queryable via this query type).\n * - Solana balance uses lamports of the Veridex vault PDA (plus optional extra accounts).\n * - Aptos is included only if/when Wormhole Queries adds Aptos query types (currently returned as unsupported).\n */\nexport async function queryPortfolio(\n  userKeyHash: string,\n  apiKey: string,\n  options?: QueryPortfolioOptions\n): Promise<PortfolioResult> {\n  const network = resolveNetwork(options);\n  const maxAgeSeconds = options?.maxAge ?? 60;\n  const maxAttempts = options?.maxAttempts ?? 4;\n  const cacheTtlMs = options?.cacheTtlMs ?? 30_000;\n  const endpoint = getProxyEndpoint(network, options);\n\n  const chainIds = options?.rpcUrls ? Object.keys(options.rpcUrls).map(Number) : undefined;\n  void chainIds;\n\n  const requestedChains = options?.vaultAddresses\n    ? Object.keys(options.vaultAddresses).map(Number)\n    : undefined;\n\n  const defaultChains = getDefaultPortfolioChains(network);\n  const wormholeChainIds = options?.evmTokenAddresses\n    ? Array.from(new Set([...defaultChains, ...Object.keys(options.evmTokenAddresses).map(Number)]))\n    : defaultChains;\n\n  // If the caller provided explicit vault overrides, include those chain IDs even if not in defaults.\n  const finalChainIds = requestedChains\n    ? Array.from(new Set([...wormholeChainIds, ...requestedChains]))\n    : wormholeChainIds;\n\n  if (!apiKey || typeof apiKey !== 'string') {\n    throw new QueryPortfolioError('INVALID_ARGUMENT', 'Missing Query Proxy apiKey');\n  }\n\n  const cacheKey = makeCacheKey(userKeyHash, apiKey, options, finalChainIds);\n  const cached = PORTFOLIO_CACHE.get(cacheKey);\n  if (cached && cached.expiresAt > Date.now()) {\n    return cached.value;\n  }\n\n  const chains = getChainConfigs(network);\n  const walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n\n  const pricesUsd: Record<string, number> | undefined = {\n    USDC: 1,\n    ...(options?.pricesUsd ?? {}),\n  };\n\n  const doFetch = async (): Promise<PortfolioResult> => {\n    try {\n      const perChainRequests: PerChainQueryRequest[] = [];\n      const chainMeta: Record<number, { vaultAddress?: string; chainName?: string; kind: 'evm' | 'solana' | 'unsupported' }> = {};\n\n      // Precompute any EVM block tags in parallel to keep total latency down.\n      const evmChainIds = finalChainIds.filter((id) => {\n        const cfg = Object.values(chains).find((c) => c.wormholeChainId === id);\n        return cfg?.isEvm;\n      });\n\n      const blockTagsByChainId = new Map<number, number>();\n      await Promise.all(\n        evmChainIds.map(async (wormholeChainId) => {\n          const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n          if (!cfg) return;\n          const rpcUrl = options?.rpcUrls?.[wormholeChainId] ?? cfg.rpcUrl;\n          const blockTag = await getRecentBlockTag(rpcUrl);\n          blockTagsByChainId.set(wormholeChainId, blockTag);\n        })\n      );\n\n      for (const wormholeChainId of finalChainIds) {\n        const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n\n        if (wormholeChainId === 22) {\n          chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg?.name };\n          continue;\n        }\n\n        if (!cfg) {\n          chainMeta[wormholeChainId] = { kind: 'unsupported' };\n          continue;\n        }\n\n        if (cfg.isEvm) {\n          const vaultAddress = options?.vaultAddresses?.[wormholeChainId]\n            ?? (cfg.contracts.vaultFactory && cfg.contracts.vaultImplementation\n              ? walletManager.computeVaultAddress(userKeyHash, cfg.contracts.vaultFactory, cfg.contracts.vaultImplementation)\n              : undefined);\n\n          chainMeta[wormholeChainId] = { kind: 'evm', vaultAddress, chainName: cfg.name };\n\n          if (!vaultAddress) {\n            continue;\n          }\n\n          const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n            ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n          if (!tokenAddresses.length) {\n            continue;\n          }\n\n          const blockTag = blockTagsByChainId.get(wormholeChainId);\n          if (blockTag == null) {\n            continue;\n          }\n\n          const calls = encodeErc20BalanceCalls(vaultAddress, tokenAddresses);\n          perChainRequests.push(new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, calls)));\n          continue;\n        }\n\n        // Solana\n        if (wormholeChainId === 1) {\n          const programId = options?.vaultAddresses?.[wormholeChainId] ?? cfg.contracts.hub;\n          chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name };\n\n          if (!programId) {\n            continue;\n          }\n\n          const vaultAddress = deriveSolanaVaultAddress(programId, userKeyHash);\n          chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name, vaultAddress };\n\n          const accounts = [vaultAddress, ...(options?.solanaAccounts ?? [])];\n          perChainRequests.push(\n            new PerChainQueryRequest(\n              wormholeChainId,\n              new SolanaAccountQueryRequest('finalized', accounts, undefined, 0n, 0n)\n            )\n          );\n          continue;\n        }\n\n        chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg.name };\n      }\n\n      if (perChainRequests.length > 255) {\n        throw new QueryPortfolioError(\n          'INVALID_ARGUMENT',\n          `Too many per-chain requests (${perChainRequests.length}); max is 255 per Query Proxy request`\n        );\n      }\n\n      // If no per-chain requests were built (e.g., missing vaults or tokens), return early with empty results\n      if (perChainRequests.length === 0) {\n        const chainsOut: PortfolioChainResult[] = finalChainIds.map((wormholeChainId) => {\n          const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n          return {\n            wormholeChainId,\n            chainName: meta.chainName,\n            vaultAddress: meta.vaultAddress,\n            balances: [],\n            error: { \n              code: 'MISSING_VAULT' as const, \n              message: 'Unable to build query: missing vault address or no tokens configured' \n            },\n          };\n        });\n        return { proof: new Uint8Array(), totalUsd: 0, chains: chainsOut };\n      }\n\n      const request = new QueryRequest(Date.now() & 0xffffffff, perChainRequests);\n      // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n      const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n      // Respect rate limit before making request\n      await rateLimiter.acquire();\n\n      let response;\n      try {\n        console.log('[queryPortfolio] Sending request to:', endpoint);\n        console.log('[queryPortfolio] Request bytes length:', requestHex.length);\n        \n        // Use provided timeout, or default to 15s for testnet (slower), 10s for mainnet\n        const defaultTimeout = network === 'testnet' ? 15_000 : 10_000;\n        const requestTimeout = options?.timeout ?? defaultTimeout;\n        \n        response = await axios.post(\n          endpoint,\n          { bytes: requestHex },\n          {\n            headers: {\n              'X-API-Key': apiKey,\n              'Content-Type': 'application/json',\n            },\n            timeout: requestTimeout,\n          }\n        );\n      } catch (axiosErr) {\n        const err = axiosErr as AxiosError;\n        // Network errors (CORS, timeout, no connection) have no response\n        if (!err.response) {\n          console.error('[queryPortfolio] Network error:', {\n            message: err.message,\n            code: err.code,\n            name: err.name,\n          });\n          throw new QueryPortfolioError(\n            'NETWORK_ERROR',\n            `Network error: ${err.message} (code: ${err.code})`\n          );\n        }\n        const status = err.response.status;\n        const errData = err.response.data;\n        console.error('[queryPortfolio] Wormhole Query Proxy error:', { status, data: errData });\n        throw new QueryPortfolioError(\n          'PROXY_RESPONSE_INVALID',\n          `Query Proxy returned ${status}: ${JSON.stringify(errData)}`\n        );\n      }\n\n      const data = response.data as any;\n      const signatures = data?.signatures as string[] | undefined;\n      const bytes = data?.bytes as string | undefined;\n\n      if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n        throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n      }\n\n      const proof = signaturesToProofBytes(signatures);\n      const queryBytes = decodeQueryBytes(bytes);\n      const parsed = QueryResponse.from(queryBytes);\n\n      const nowSeconds = Math.floor(Date.now() / 1000);\n      const chainsOut: PortfolioChainResult[] = [];\n\n      for (const wormholeChainId of finalChainIds) {\n        const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n\n        if (meta.kind === 'unsupported') {\n          const msg = wormholeChainId === 22\n            ? 'Aptos Queries are not supported by the Wormhole Query SDK yet'\n            : 'Chain is not supported by this portfolio query implementation';\n          chainsOut.push({\n            wormholeChainId,\n            chainName: meta.chainName,\n            balances: [],\n            error: { code: 'UNSUPPORTED_CHAIN', message: msg },\n          });\n          continue;\n        }\n\n        if (!meta.vaultAddress) {\n          chainsOut.push({\n            wormholeChainId,\n            chainName: meta.chainName,\n            balances: [],\n            error: { code: 'MISSING_VAULT', message: 'Unable to derive vault address for chain' },\n          });\n          continue;\n        }\n\n        const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n        if (!perChain) {\n          chainsOut.push({\n            wormholeChainId,\n            chainName: meta.chainName,\n            vaultAddress: meta.vaultAddress,\n            balances: [],\n            error: { code: 'DECODE_ERROR', message: 'Missing per-chain response from Query Proxy' },\n          });\n          continue;\n        }\n\n        try {\n          if (meta.kind === 'evm') {\n            const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n            const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n              ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n            if (!tokenAddresses.length) {\n              chainsOut.push({\n                wormholeChainId,\n                chainName: meta.chainName,\n                vaultAddress: meta.vaultAddress,\n                balances: [],\n                error: { code: 'MISSING_TOKENS', message: 'No ERC20 tokens configured for EVM portfolio query' },\n              });\n              continue;\n            }\n\n            const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n            const blockTime = Number(chainResp.blockTime);\n            const age = nowSeconds - blockTime;\n            if (age > maxAgeSeconds) {\n              chainsOut.push({\n                wormholeChainId,\n                chainName: meta.chainName,\n                vaultAddress: meta.vaultAddress,\n                blockTime,\n                balances: [],\n                error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n              });\n              continue;\n            }\n\n            const amounts = decodeErc20Balances(chainResp.results, tokenAddresses);\n            const tokenInfos = getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address));\n\n            const balances: PortfolioBalance[] = tokenAddresses.map((addr, i) => {\n              const info = tokenInfos.find((t) => t.address.toLowerCase() === addr.toLowerCase());\n              const symbol = info?.symbol;\n              const decimals = info?.decimals;\n              const usdPrice = priceLookup(pricesUsd, symbol, addr);\n              const usdValue = usdPrice != null && decimals != null\n                ? (Number(amounts[i]) / 10 ** decimals) * usdPrice\n                : undefined;\n\n              return {\n                assetId: addr,\n                amount: amounts[i],\n                symbol,\n                decimals,\n                usdValue: Number.isFinite(usdValue ?? NaN) ? usdValue : undefined,\n              };\n            });\n\n            void cfg;\n            chainsOut.push({\n              wormholeChainId,\n              chainName: meta.chainName,\n              vaultAddress: meta.vaultAddress,\n              blockTime,\n              balances,\n            });\n            continue;\n          }\n\n          // Solana\n          const chainResp = SolanaAccountQueryResponse.from(perChain.response.serialize());\n          const blockTime = safeNumberFromBigint(chainResp.blockTime);\n          const age = nowSeconds - blockTime;\n          if (age > maxAgeSeconds) {\n            chainsOut.push({\n              wormholeChainId,\n              chainName: meta.chainName,\n              vaultAddress: meta.vaultAddress,\n              blockTime,\n              balances: [],\n              error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n            });\n            continue;\n          }\n\n          const vaultResult = chainResp.results[0];\n          const lamports = vaultResult?.lamports ?? 0n;\n\n          const balances: PortfolioBalance[] = [\n            {\n              assetId: 'SOL',\n              amount: lamports,\n              decimals: 9,\n              symbol: 'SOL',\n              usdValue: priceLookup(pricesUsd, 'SOL', 'SOL') != null\n                ? (Number(lamports) / 1e9) * (priceLookup(pricesUsd, 'SOL', 'SOL') as number)\n                : undefined,\n            },\n          ];\n\n          chainsOut.push({\n            wormholeChainId,\n            chainName: meta.chainName,\n            vaultAddress: meta.vaultAddress,\n            blockTime,\n            balances,\n          });\n        } catch (cause) {\n          chainsOut.push({\n            wormholeChainId,\n            chainName: meta.chainName,\n            vaultAddress: meta.vaultAddress,\n            balances: [],\n            error: { code: 'DECODE_ERROR', message: `Failed to decode chain response: ${String((cause as any)?.message ?? cause)}` },\n          });\n        }\n      }\n\n      const allBalances = chainsOut.flatMap((c) => c.balances);\n      const totalUsd = sumUsd(allBalances, pricesUsd);\n\n      const result: PortfolioResult = { proof, totalUsd, chains: chainsOut };\n\n      PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n      return result;\n    } catch (err) {\n      if (err instanceof QueryPortfolioError) throw err;\n      if (axios.isAxiosError(err)) {\n        const ax = err as AxiosError;\n        const status = ax.response?.status;\n        const statusText = ax.response?.statusText;\n        const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n        throw new QueryPortfolioError(\n          'PROXY_HTTP_ERROR',\n          `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n          err\n        );\n      }\n\n      throw new QueryPortfolioError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n    }\n  };\n\n  const result = await withExponentialBackoff(doFetch, maxAttempts);\n  PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n  return result;\n}\n"],"mappings":"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","names":["chainsOut","chainResp","blockTime","age","balances","result"]}