tx-indexer 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/{client-DdzTiKZ4.d.ts → client-xmDVjOy4.d.ts} +13 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +499 -49
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +109 -5
- package/dist/index.js +521 -52
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/package.json +1 -1
- package/dist/{classification.types-Cn9IGtEC.d.ts → classification.types-h046WjuF.d.ts} +7 -7
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../solana/src/rpc/client.ts","../../domain/src/money/token-registry.ts","../../solana/src/constants/program-ids.ts","../../solana/src/fetcher/balances.ts","../../solana/src/mappers/transaction-mapper.ts","../../../node_modules/.bun/base-x@5.0.1/node_modules/base-x/src/esm/index.js","../../../node_modules/.bun/bs58@6.0.0/node_modules/bs58/src/esm/index.js","../../solana/src/mappers/memo-parser.ts","../../solana/src/rpc/retry.ts","../../../node_modules/.bun/yocto-queue@1.2.2/node_modules/yocto-queue/index.js","../../../node_modules/.bun/p-limit@6.2.0/node_modules/p-limit/index.js","../../solana/src/fetcher/transactions.ts","../../domain/src/tx/account-id.ts","../../solana/src/mappers/balance-parser.ts","../../solana/src/constants/protocol-constants.ts","../../solana/src/mappers/transaction-to-legs.ts","../../classification/src/classifiers/transfer-classifier.ts","../../classification/src/protocols/detector.ts","../../classification/src/classifiers/swap-classifier.ts","../../classification/src/classifiers/airdrop-classifier.ts","../../classification/src/classifiers/fee-only-classifier.ts","../../classification/src/classifiers/solana-pay-classifier.ts","../../classification/src/classifiers/nft-mint-classifier.ts","../../classification/src/classifiers/stake-deposit-classifier.ts","../../classification/src/classifiers/stake-withdraw-classifier.ts","../../classification/src/classifiers/bridge-classifier.ts","../../classification/src/engine/classification-service.ts","../../domain/src/tx/spam-filter.ts","../src/nft.ts","../src/client.ts"],"names":["address","ALPHABET","esm_default","signature","DEX_PROTOCOL_IDS","DEFAULT_CONFIG","options","walletAddressStr"],"mappings":"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","file":"client.js","sourcesContent":["import {\n createSolanaRpc,\n createSolanaRpcSubscriptions,\n type Rpc,\n type RpcSubscriptions,\n type GetBalanceApi,\n type GetTokenAccountsByOwnerApi,\n type GetSignaturesForAddressApi,\n type GetTransactionApi,\n address,\n type Address,\n signature,\n type Signature,\n} from \"@solana/kit\";\n\n/**\n * Union type of all RPC APIs used by the transaction indexer.\n * \n * This ensures type safety when calling RPC methods while maintaining\n * flexibility for the complete indexer API surface.\n */\nexport type IndexerRpcApi = GetBalanceApi \n & GetTokenAccountsByOwnerApi \n & GetSignaturesForAddressApi \n & GetTransactionApi;\n\nexport interface SolanaClient {\n rpc: Rpc<IndexerRpcApi>;\n rpcSubscriptions: RpcSubscriptions<any>;\n}\n\n/**\n * Creates a Solana RPC client with both regular RPC and WebSocket subscriptions.\n * \n * @param rpcUrl - HTTP RPC endpoint URL\n * @param wsUrl - Optional WebSocket URL (defaults to rpcUrl with wss:// protocol)\n */\nexport function createSolanaClient(\n rpcUrl: string,\n wsUrl?: string\n): SolanaClient {\n const rpc = createSolanaRpc(rpcUrl);\n const rpcSubscriptions = wsUrl\n ? createSolanaRpcSubscriptions(wsUrl)\n : createSolanaRpcSubscriptions(rpcUrl.replace(\"https://\", \"wss://\"));\n\n return { rpc, rpcSubscriptions };\n}\n\n/**\n * Parses and validates a Solana address string.\n * \n * @param addr - Base58-encoded Solana address\n */\nexport function parseAddress(addr: string): Address {\n return address(addr);\n}\n\n/**\n * Parses and validates a Solana transaction signature string.\n * \n * @param sig - Base58-encoded transaction signature\n */\nexport function parseSignature(sig: string): Signature {\n return signature(sig);\n}\n\n","import type { TokenInfo } from \"./money.types\";\n\nexport const KNOWN_TOKENS = {\n SOL: \"So11111111111111111111111111111111111111112\",\n USDC: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n USDC_BRIDGED: \"A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM\",\n USDG: \"2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH\",\n} as const;\n\nexport const TOKEN_INFO: Record<string, TokenInfo> = {\n [KNOWN_TOKENS.SOL]: {\n mint: KNOWN_TOKENS.SOL,\n symbol: \"SOL\",\n name: \"Solana\",\n decimals: 9,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png\",\n },\n [KNOWN_TOKENS.USDC]: {\n mint: KNOWN_TOKENS.USDC,\n symbol: \"USDC\",\n name: \"USD Coin\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png\",\n },\n [KNOWN_TOKENS.USDC_BRIDGED]: {\n mint: KNOWN_TOKENS.USDC_BRIDGED,\n symbol: \"USDCet\",\n name: \"USDC (Bridged)\",\n decimals: 6,\n },\n [KNOWN_TOKENS.USDG]: {\n mint: KNOWN_TOKENS.USDG,\n symbol: \"USDG\",\n name: \"USD Glitter\",\n decimals: 6,\n },\n};\n\nexport function getTokenInfo(mint: string): TokenInfo | undefined {\n return TOKEN_INFO[mint];\n}\n\nexport function isSupportedToken(mint: string): boolean {\n return mint in TOKEN_INFO;\n}\n\nexport const SUPPORTED_STABLECOINS = [\n KNOWN_TOKENS.USDC,\n KNOWN_TOKENS.USDC_BRIDGED,\n KNOWN_TOKENS.USDG,\n] as const;\n\nexport const TRACKED_TOKENS = [\n KNOWN_TOKENS.SOL,\n KNOWN_TOKENS.USDC,\n] as const;\n\n","/**\n * Solana Program IDs\n *\n * Centralized registry of known Solana program addresses.\n * These are public keys that identify on-chain programs.\n */\n\n// ============================================\n// Core Solana Programs\n// ============================================\n\nexport const SYSTEM_PROGRAM_ID = \"11111111111111111111111111111111\";\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\nexport const STAKE_PROGRAM_ID = \"Stake11111111111111111111111111111111111111\";\nexport const STAKE_POOL_PROGRAM_ID =\n \"SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy\";\n\n// ============================================\n// Token Programs\n// ============================================\n\nexport const TOKEN_PROGRAM_ID = \"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\";\nexport const TOKEN_2022_PROGRAM_ID =\n \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\";\nexport const ASSOCIATED_TOKEN_PROGRAM_ID =\n \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\";\n\n// ============================================\n// Memo Programs\n// ============================================\n\nexport const SPL_MEMO_PROGRAM_ID =\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\";\nexport const MEMO_V1_PROGRAM_ID = \"Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo\";\n\n// ============================================\n// DeFi Programs\n// ============================================\n\n// Jupiter\nexport const JUPITER_V6_PROGRAM_ID =\n \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nexport const JUPITER_V4_PROGRAM_ID =\n \"JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB\";\nexport const JUPITER_ORDER_ENGINE_PROGRAM_ID =\n \"61DFfeTKM7trxYcPQCM78bJ794ddZprZpAwAnLiwTpYH\";\n\n// Raydium\nexport const RAYDIUM_PROGRAM_ID =\n \"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8\";\nexport const RAYDIUM_CLMM_PROGRAM_ID =\n \"CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK\";\nexport const RAYDIUM_CPMM_PROGRAM_ID =\n \"CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C\";\nexport const RAYDIUM_STABLE_PROGRAM_ID =\n \"5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h\";\n\n// Orca\nexport const ORCA_WHIRLPOOL_PROGRAM_ID =\n \"whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc\";\nexport const ORCA_TOKEN_SWAP_V1_PROGRAM_ID =\n \"9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP\";\n\n// CLOBs (Central Limit Order Books)\nexport const OPENBOOK_V2_PROGRAM_ID =\n \"opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb\";\nexport const PHOENIX_PROGRAM_ID = \"PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY\";\n\n// Stableswap\nexport const SABER_STABLE_SWAP_PROGRAM_ID =\n \"SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ\";\nexport const MERCURIAL_STABLE_SWAP_PROGRAM_ID =\n \"MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky\";\n\n// Meteora\nexport const METEORA_DLMM_PROGRAM_ID =\n \"LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo\";\nexport const METEORA_POOLS_PROGRAM_ID =\n \"Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB\";\n\n// Pump.fun\nexport const PUMPFUN_AMM_PROGRAM_ID =\n \"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA\";\nexport const PUMPFUN_BONDING_CURVE_PROGRAM_ID =\n \"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P\";\n\n// Lifinity\nexport const LIFINITY_V2_PROGRAM_ID =\n \"2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c\";\n\n// ============================================\n// NFT Programs\n// ============================================\n\nexport const METAPLEX_PROGRAM_ID =\n \"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s\";\nexport const CANDY_MACHINE_V3_PROGRAM_ID =\n \"CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR\";\nexport const CANDY_GUARD_PROGRAM_ID =\n \"Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g\";\nexport const BUBBLEGUM_PROGRAM_ID =\n \"BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY\";\nexport const MAGIC_EDEN_CANDY_MACHINE_ID =\n \"CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb\";\n\n// ============================================\n// Bridge Programs\n// ============================================\n\nexport const WORMHOLE_PROGRAM_ID =\n \"worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth\";\nexport const WORMHOLE_TOKEN_BRIDGE_ID =\n \"wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb\";\nexport const DEGODS_BRIDGE_PROGRAM_ID =\n \"35iLrpYNNR9ygHLcvE1xKFHbHq6paHthrF6wSovdWgGu\";\nexport const DEBRIDGE_PROGRAM_ID =\n \"DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh\";\nexport const ALLBRIDGE_PROGRAM_ID =\n \"BrdgN2RPzEMWF96ZbnnJaUtQDQx7VRXYaHHbYCBvceWB\";\n\n// ============================================\n// Payment Facilitators\n// ============================================\n\nexport const PAYAI_FACILITATOR = \"2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4\";\n\n// ============================================\n// Helper Collections\n// ============================================\n\nexport const MEMO_PROGRAM_IDS = [\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n] as const;\n\nexport const TOKEN_PROGRAM_IDS = [\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n] as const;\n\nexport const DEX_PROGRAM_IDS = [\n JUPITER_V6_PROGRAM_ID,\n JUPITER_V4_PROGRAM_ID,\n JUPITER_ORDER_ENGINE_PROGRAM_ID,\n RAYDIUM_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n RAYDIUM_CPMM_PROGRAM_ID,\n RAYDIUM_STABLE_PROGRAM_ID,\n ORCA_WHIRLPOOL_PROGRAM_ID,\n ORCA_TOKEN_SWAP_V1_PROGRAM_ID,\n OPENBOOK_V2_PROGRAM_ID,\n PHOENIX_PROGRAM_ID,\n SABER_STABLE_SWAP_PROGRAM_ID,\n MERCURIAL_STABLE_SWAP_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n METEORA_POOLS_PROGRAM_ID,\n PUMPFUN_AMM_PROGRAM_ID,\n PUMPFUN_BONDING_CURVE_PROGRAM_ID,\n LIFINITY_V2_PROGRAM_ID,\n] as const;\n\nexport const NFT_PROGRAM_IDS = [\n METAPLEX_PROGRAM_ID,\n CANDY_MACHINE_V3_PROGRAM_ID,\n CANDY_GUARD_PROGRAM_ID,\n BUBBLEGUM_PROGRAM_ID,\n MAGIC_EDEN_CANDY_MACHINE_ID,\n] as const;\n\nexport const BRIDGE_PROGRAM_IDS = [\n WORMHOLE_PROGRAM_ID,\n WORMHOLE_TOKEN_BRIDGE_ID,\n DEGODS_BRIDGE_PROGRAM_ID,\n DEBRIDGE_PROGRAM_ID,\n ALLBRIDGE_PROGRAM_ID,\n] as const;\n\nexport const KNOWN_FACILITATORS = [PAYAI_FACILITATOR] as const;\n\nexport function detectFacilitator(accountKeys: string[]): string | null {\n for (const facilitator of KNOWN_FACILITATORS) {\n if (accountKeys.includes(facilitator)) {\n if (facilitator === PAYAI_FACILITATOR) {\n return \"payai\";\n }\n }\n }\n return null;\n}\n","import {\n type Address,\n type Rpc,\n type GetBalanceApi,\n type GetTokenAccountsByOwnerApi,\n address,\n} from \"@solana/kit\";\n\nimport {\n getTokenInfo,\n KNOWN_TOKENS,\n} from \"@tx-indexer/core/money/token-registry\";\nimport {\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from \"../constants/program-ids\";\n\nexport interface WalletBalance {\n address: string;\n sol: {\n lamports: bigint;\n ui: number;\n };\n tokens: TokenAccountBalance[];\n}\n\nexport interface TokenAccountBalance {\n mint: string;\n tokenAccount?: string;\n amount: {\n raw: string;\n ui: number;\n };\n decimals: number;\n symbol: string;\n}\n\n/**\n * Fetches wallet balance including SOL and SPL tokens\n *\n * @param rpc - Solana RPC client\n * @param walletAddress - Wallet address to query\n * @param tokenMints - Optional array of token mint addresses to track. If omitted, returns all tokens in wallet\n * @returns Wallet balance data with SOL and token balances\n *\n * @example\n * // Fetch all tokens\n * const allBalances = await fetchWalletBalance(rpc, address);\n *\n * @example\n * // Fetch specific tokens only\n * const usdcOnly = await fetchWalletBalance(rpc, address, [\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"]);\n */\nexport async function fetchWalletBalance(\n rpc: Rpc<GetBalanceApi & GetTokenAccountsByOwnerApi>,\n walletAddress: Address,\n tokenMints?: readonly string[],\n): Promise<WalletBalance> {\n const balanceResponse = await rpc.getBalance(walletAddress).send();\n const lamports = balanceResponse.value;\n\n const tokenAccounts = await fetchTokenAccounts(rpc, walletAddress);\n\n const tokens = tokenMints\n ? filterToTrackedTokens(tokenAccounts, tokenMints)\n : Array.from(tokenAccounts.values());\n\n return {\n address: walletAddress,\n sol: {\n lamports,\n ui: Number(lamports) / 1e9,\n },\n tokens,\n };\n}\n\nasync function fetchTokenAccounts(\n rpc: Rpc<GetBalanceApi & GetTokenAccountsByOwnerApi>,\n walletAddress: Address,\n): Promise<Map<string, TokenAccountBalance>> {\n const accountsMap = new Map<string, TokenAccountBalance>();\n\n const tokenPrograms = [TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID];\n\n const responses = await Promise.all(\n tokenPrograms.map((programId) =>\n rpc\n .getTokenAccountsByOwner(\n walletAddress,\n { programId: address(programId) },\n { encoding: \"jsonParsed\" },\n )\n .send()\n .catch(() => ({ value: [] })),\n ),\n );\n\n for (const response of responses) {\n for (const account of response.value) {\n const parsedInfo = account.account.data.parsed.info;\n const mint = parsedInfo.mint;\n\n const tokenInfo = getTokenInfo(mint);\n const symbol = tokenInfo?.symbol || mint.substring(0, 8);\n\n accountsMap.set(mint, {\n mint,\n tokenAccount: account.pubkey.toString(),\n amount: {\n raw: parsedInfo.tokenAmount.amount,\n ui: parsedInfo.tokenAmount.uiAmountString\n ? parseFloat(parsedInfo.tokenAmount.uiAmountString)\n : 0,\n },\n decimals: parsedInfo.tokenAmount.decimals,\n symbol,\n });\n }\n }\n\n return accountsMap;\n}\n\n/**\n * Filters token accounts to only include specified mints, adding zero balances for missing tokens\n *\n * @param fetchedAccounts - Map of mint addresses to token balances from RPC\n * @param tokenMints - Array of token mint addresses to include in results\n */\nfunction filterToTrackedTokens(\n fetchedAccounts: Map<string, TokenAccountBalance>,\n tokenMints: readonly string[],\n): TokenAccountBalance[] {\n const result: TokenAccountBalance[] = [];\n\n for (const mint of tokenMints) {\n if (mint === KNOWN_TOKENS.SOL) continue;\n\n const existing = fetchedAccounts.get(mint);\n if (existing) {\n result.push(existing);\n } else {\n const tokenInfo = getTokenInfo(mint);\n if (tokenInfo) {\n result.push({\n mint,\n amount: {\n raw: \"0\",\n ui: 0,\n },\n decimals: tokenInfo.decimals,\n symbol: tokenInfo.symbol,\n });\n }\n }\n }\n\n return result;\n}\n\nexport function formatBalance(balance: WalletBalance): string[] {\n const lines: string[] = [];\n\n lines.push(`Wallet: ${balance.address}`);\n lines.push(`SOL: ${balance.sol.ui.toFixed(9)}`);\n\n for (const token of balance.tokens) {\n lines.push(`${token.symbol}: ${token.amount.ui.toFixed(token.decimals)}`);\n }\n\n return lines;\n}\n","import type {\n SolanaTransaction,\n InnerInstruction,\n} from \"@tx-indexer/solana/types/transaction.types\";\n\n/**\n * Extracts all unique program IDs from a transaction's top-level instructions.\n */\nexport function extractProgramIds(transaction: SolanaTransaction): string[] {\n const programIds = new Set<string>();\n\n const { message } = transaction;\n const { accountKeys, instructions } = message;\n\n for (const ix of instructions) {\n const { programIdIndex } = ix;\n if (programIdIndex !== undefined && accountKeys[programIdIndex]) {\n const key = accountKeys[programIdIndex];\n programIds.add(key.toString());\n }\n }\n\n return Array.from(programIds);\n}\n\n/**\n * Extracts program IDs from inner instructions (CPI calls).\n */\nexport function extractInnerProgramIds(\n innerInstructions: InnerInstruction[] | undefined,\n allAccountKeys: string[]\n): string[] {\n if (!innerInstructions) return [];\n\n const programIds = new Set<string>();\n\n for (const block of innerInstructions) {\n for (const ix of block.instructions) {\n const key = allAccountKeys[ix.programIdIndex];\n if (key) programIds.add(key);\n }\n }\n\n return Array.from(programIds);\n}\n","// base-x encoding / decoding\n// Copyright (c) 2018 base-x contributors\n// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)\n// Distributed under the MIT software license, see the accompanying\n// file LICENSE or http://www.opensource.org/licenses/mit-license.php.\nfunction base (ALPHABET) {\n if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }\n const BASE_MAP = new Uint8Array(256)\n for (let j = 0; j < BASE_MAP.length; j++) {\n BASE_MAP[j] = 255\n }\n for (let i = 0; i < ALPHABET.length; i++) {\n const x = ALPHABET.charAt(i)\n const xc = x.charCodeAt(0)\n if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }\n BASE_MAP[xc] = i\n }\n const BASE = ALPHABET.length\n const LEADER = ALPHABET.charAt(0)\n const FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up\n const iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up\n function encode (source) {\n // eslint-disable-next-line no-empty\n if (source instanceof Uint8Array) { } else if (ArrayBuffer.isView(source)) {\n source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)\n } else if (Array.isArray(source)) {\n source = Uint8Array.from(source)\n }\n if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }\n if (source.length === 0) { return '' }\n // Skip & count leading zeroes.\n let zeroes = 0\n let length = 0\n let pbegin = 0\n const pend = source.length\n while (pbegin !== pend && source[pbegin] === 0) {\n pbegin++\n zeroes++\n }\n // Allocate enough space in big-endian base58 representation.\n const size = ((pend - pbegin) * iFACTOR + 1) >>> 0\n const b58 = new Uint8Array(size)\n // Process the bytes.\n while (pbegin !== pend) {\n let carry = source[pbegin]\n // Apply \"b58 = b58 * 256 + ch\".\n let i = 0\n for (let it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {\n carry += (256 * b58[it1]) >>> 0\n b58[it1] = (carry % BASE) >>> 0\n carry = (carry / BASE) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n pbegin++\n }\n // Skip leading zeroes in base58 result.\n let it2 = size - length\n while (it2 !== size && b58[it2] === 0) {\n it2++\n }\n // Translate the result into a string.\n let str = LEADER.repeat(zeroes)\n for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }\n return str\n }\n function decodeUnsafe (source) {\n if (typeof source !== 'string') { throw new TypeError('Expected String') }\n if (source.length === 0) { return new Uint8Array() }\n let psz = 0\n // Skip and count leading '1's.\n let zeroes = 0\n let length = 0\n while (source[psz] === LEADER) {\n zeroes++\n psz++\n }\n // Allocate enough space in big-endian base256 representation.\n const size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.\n const b256 = new Uint8Array(size)\n // Process the characters.\n while (psz < source.length) {\n // Find code of next character\n const charCode = source.charCodeAt(psz)\n // Base map can not be indexed using char code\n if (charCode > 255) { return }\n // Decode character\n let carry = BASE_MAP[charCode]\n // Invalid character\n if (carry === 255) { return }\n let i = 0\n for (let it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {\n carry += (BASE * b256[it3]) >>> 0\n b256[it3] = (carry % 256) >>> 0\n carry = (carry / 256) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n psz++\n }\n // Skip leading zeroes in b256.\n let it4 = size - length\n while (it4 !== size && b256[it4] === 0) {\n it4++\n }\n const vch = new Uint8Array(zeroes + (size - it4))\n let j = zeroes\n while (it4 !== size) {\n vch[j++] = b256[it4++]\n }\n return vch\n }\n function decode (string) {\n const buffer = decodeUnsafe(string)\n if (buffer) { return buffer }\n throw new Error('Non-base' + BASE + ' character')\n }\n return {\n encode,\n decodeUnsafe,\n decode\n }\n}\nexport default base\n","import basex from 'base-x';\nvar ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\nexport default basex(ALPHABET);\n","import type { SolanaTransaction } from \"@tx-indexer/solana/types/transaction.types\";\nimport {\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n} from \"@tx-indexer/solana/constants/program-ids\";\nimport bs58 from \"bs58\";\n\ninterface TransactionWithLogs extends SolanaTransaction {\n meta?: {\n logMessages?: readonly string[] | null;\n };\n}\n\nfunction decodeMemoData(base64Data: string): string {\n const buffer = Buffer.from(base64Data, \"base64\");\n\n const text = buffer.toString(\"utf-8\");\n if (!text.includes(\"\\ufffd\") && /^[\\x20-\\x7E\\s]*$/.test(text)) {\n return text;\n }\n\n if (buffer.length === 32) {\n return bs58.encode(buffer);\n }\n\n if (buffer.length % 32 === 0 && buffer.length > 0) {\n const addresses: string[] = [];\n for (let i = 0; i < buffer.length; i += 32) {\n const chunk = buffer.subarray(i, i + 32);\n addresses.push(bs58.encode(chunk));\n }\n return addresses.join(\", \");\n }\n\n if (buffer.length >= 16) {\n const uuidBytes = buffer.subarray(0, 16);\n const uuid = [\n uuidBytes.subarray(0, 4).toString(\"hex\"),\n uuidBytes.subarray(4, 6).toString(\"hex\"),\n uuidBytes.subarray(6, 8).toString(\"hex\"),\n uuidBytes.subarray(8, 10).toString(\"hex\"),\n uuidBytes.subarray(10, 16).toString(\"hex\"),\n ].join(\"-\");\n\n if (buffer.length === 16) {\n return `Product: ${uuid}`;\n }\n\n const extraData = buffer.subarray(16);\n const extraHex = extraData.toString(\"hex\");\n return `Product: ${uuid} | Meta: ${extraHex}`;\n }\n\n return bs58.encode(buffer);\n}\n\n/**\n * Extracts memo data from a Solana transaction.\n * \n * First attempts to extract human-readable memos from program logs, which contain\n * the decoded text. Falls back to parsing memo program instructions for binary data.\n * Handles various memo formats including UTF-8 text, public keys, and Solana Pay metadata.\n * \n * @param transaction - Solana transaction with message and optional logs\n * @returns Extracted memo string, or null if no memo is found\n */\nexport function extractMemo(transaction: TransactionWithLogs): string | null {\n if (transaction.meta?.logMessages) {\n const memoLogPattern = /Program log: Memo \\(len \\d+\\): \"(.+)\"/;\n for (const log of transaction.meta.logMessages) {\n const match = log.match(memoLogPattern);\n if (match?.[1]) {\n return match[1];\n }\n }\n }\n\n const { message } = transaction;\n const { accountKeys, instructions } = message;\n\n for (const ix of instructions) {\n const programId = accountKeys[ix.programIdIndex]?.toString();\n\n if (programId === SPL_MEMO_PROGRAM_ID || programId === MEMO_V1_PROGRAM_ID) {\n if (ix.data) {\n try {\n return decodeMemoData(ix.data);\n } catch (e) {\n console.warn(\"Failed to decode memo:\", e);\n }\n }\n }\n }\n\n return null;\n}\n\nexport interface SolanaPayMemo {\n merchant?: string;\n item?: string;\n reference?: string;\n label?: string;\n message?: string;\n raw: string;\n}\n\n/**\n * Parses a Solana Pay memo string into structured fields.\n * \n * Attempts to parse the memo as JSON to extract merchant, item, reference,\n * label, and message fields. Falls back to returning just the raw memo if parsing fails.\n * \n * @param memo - Memo string to parse\n * @returns Parsed Solana Pay memo object with raw memo included\n */\nexport function parseSolanaPayMemo(memo: string): SolanaPayMemo {\n try {\n const parsed = JSON.parse(memo);\n return { ...parsed, raw: memo };\n } catch {\n return { raw: memo };\n }\n}\n\n/**\n * Determines if a transaction is a Solana Pay transaction.\n * \n * A transaction is considered Solana Pay if it includes the SPL Memo program\n * and has a non-null memo. Solana Pay uses memos to attach payment metadata.\n * \n * @param programIds - Program IDs involved in the transaction\n * @param memo - Extracted memo from the transaction\n * @returns True if this is a Solana Pay transaction\n */\nexport function isSolanaPayTransaction(\n programIds: string[],\n memo: string | null | undefined\n): boolean {\n const hasMemoProgram =\n programIds.includes(SPL_MEMO_PROGRAM_ID) ||\n programIds.includes(MEMO_V1_PROGRAM_ID);\n\n return hasMemoProgram && memo !== null && memo !== undefined;\n}\n","export interface RetryConfig {\n maxAttempts?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n}\n\nconst DEFAULT_CONFIG: Required<RetryConfig> = {\n maxAttempts: 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n};\n\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return (\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\") ||\n message.includes(\"network\") ||\n message.includes(\"429\") ||\n message.includes(\"rate limit\") ||\n message.includes(\"too many requests\") ||\n message.includes(\"503\") ||\n message.includes(\"502\") ||\n message.includes(\"504\")\n );\n }\n return false;\n}\n\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n const jitter = Math.random() * 0.3 * exponentialDelay;\n return Math.min(exponentialDelay + jitter, maxDelayMs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Executes an async function with retry logic and exponential backoff.\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration\n * @returns Result of the function\n * @throws Last error if all retries fail\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config: RetryConfig = {},\n): Promise<T> {\n const { maxAttempts, baseDelayMs, maxDelayMs } = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n const isLastAttempt = attempt === maxAttempts;\n const shouldRetry = !isLastAttempt && isRetryableError(error);\n\n if (!shouldRetry) {\n throw error;\n }\n\n const delay = calculateDelay(attempt, baseDelayMs, maxDelayMs);\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\n\t\t// Clean up tail reference when queue becomes empty\n\t\tif (!this.#head) {\n\t\t\tthis.#tail = undefined;\n\t\t}\n\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\t* drain() {\n\t\twhile (this.#head) {\n\t\t\tyield this.dequeue();\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","import type {\n Address,\n Rpc,\n Signature,\n GetSignaturesForAddressApi,\n GetTransactionApi,\n} from \"@solana/kit\";\nimport type { RawTransaction } from \"@tx-indexer/core/tx/tx.types\";\nimport { extractProgramIds } from \"@tx-indexer/solana/mappers/transaction-mapper\";\nimport { extractMemo } from \"@tx-indexer/solana/mappers/memo-parser\";\nimport { withRetry, type RetryConfig } from \"@tx-indexer/solana/rpc/retry\";\nimport pLimit from \"p-limit\";\n\nexport interface FetchTransactionsConfig {\n limit?: number;\n before?: Signature;\n until?: Signature;\n}\n\nexport interface FetchTransactionOptions {\n commitment?: \"confirmed\" | \"finalized\";\n retry?: RetryConfig;\n}\n\nexport interface FetchBatchOptions {\n commitment?: \"confirmed\" | \"finalized\";\n concurrency?: number;\n retry?: RetryConfig;\n onFetchError?: (signature: Signature, error: Error) => void;\n}\n\n/**\n * Fetches transaction signatures for a wallet address.\n *\n * @param rpc - Solana RPC client\n * @param walletAddress - Wallet address to fetch signatures for\n * @param config - Optional pagination and limit configuration\n * @returns Array of raw transactions with basic metadata only\n */\nexport async function fetchWalletSignatures(\n rpc: Rpc<GetSignaturesForAddressApi>,\n walletAddress: Address,\n config: FetchTransactionsConfig = {},\n): Promise<RawTransaction[]> {\n const { limit = 100, before, until } = config;\n\n const response = await rpc\n .getSignaturesForAddress(walletAddress, {\n limit,\n before,\n until,\n })\n .send();\n\n return response.map((sig) => ({\n signature: sig.signature,\n slot: sig.slot,\n blockTime: sig.blockTime,\n err: sig.err,\n programIds: [],\n protocol: null,\n memo: sig.memo || null,\n }));\n}\n\n/**\n * Fetches a single transaction with full details including program IDs.\n *\n * @param rpc - Solana RPC client\n * @param signature - Transaction signature\n * @param options - Fetch options including commitment level and retry config\n * @returns Full raw transaction with program IDs, or null if not found\n */\nexport async function fetchTransaction(\n rpc: Rpc<GetTransactionApi>,\n signature: Signature,\n options: FetchTransactionOptions = {},\n): Promise<RawTransaction | null> {\n const { commitment = \"confirmed\", retry } = options;\n\n const response = await withRetry(\n () =>\n rpc\n .getTransaction(signature, {\n commitment,\n maxSupportedTransactionVersion: 0,\n encoding: \"json\",\n })\n .send(),\n retry,\n );\n\n if (!response) {\n return null;\n }\n\n // Try to get memo from response metadata first (already decoded by RPC)\n // Fall back to manual extraction if not available\n const transactionWithLogs = {\n ...response.transaction,\n meta: { logMessages: response.meta?.logMessages },\n };\n const memo = extractMemo(transactionWithLogs);\n\n return {\n signature,\n slot: response.slot,\n blockTime: response.blockTime,\n fee: Number(response.meta?.fee ?? 0),\n err: response.meta?.err ?? null,\n programIds: extractProgramIds(response.transaction),\n protocol: null,\n preTokenBalances: (response.meta?.preTokenBalances ?? []).map((bal) => ({\n accountIndex: bal.accountIndex,\n mint: bal.mint.toString(),\n owner: bal.owner?.toString(),\n programId: bal.programId?.toString(),\n uiTokenAmount: {\n amount: bal.uiTokenAmount.amount.toString(),\n decimals: bal.uiTokenAmount.decimals,\n uiAmountString: bal.uiTokenAmount.uiAmountString.toString(),\n },\n })),\n postTokenBalances: (response.meta?.postTokenBalances ?? []).map((bal) => ({\n accountIndex: bal.accountIndex,\n mint: bal.mint.toString(),\n owner: bal.owner?.toString(),\n programId: bal.programId?.toString(),\n uiTokenAmount: {\n amount: bal.uiTokenAmount.amount.toString(),\n decimals: bal.uiTokenAmount.decimals,\n uiAmountString: bal.uiTokenAmount.uiAmountString.toString(),\n },\n })),\n preBalances: (response.meta?.preBalances ?? []).map((bal) => Number(bal)),\n postBalances: (response.meta?.postBalances ?? []).map((bal) => Number(bal)),\n accountKeys: response.transaction.message.accountKeys.map((key) =>\n key.toString(),\n ),\n memo,\n };\n}\n\n/**\n * Fetches multiple transactions with controlled concurrency.\n *\n * @param rpc - Solana RPC client\n * @param signatures - Array of transaction signatures to fetch\n * @param options - Fetch options including commitment level, concurrency limit, and retry config\n * @returns Array of successfully fetched transactions (nulls and errors filtered out)\n */\nexport async function fetchTransactionsBatch(\n rpc: Rpc<GetTransactionApi>,\n signatures: Signature[],\n options: FetchBatchOptions = {},\n): Promise<RawTransaction[]> {\n const {\n commitment = \"confirmed\",\n concurrency = 10,\n retry,\n onFetchError,\n } = options;\n\n if (signatures.length === 0) {\n return [];\n }\n\n const limit = pLimit(concurrency);\n\n const safeFetch = async (sig: Signature): Promise<RawTransaction | null> => {\n try {\n return await fetchTransaction(rpc, sig, { commitment, retry });\n } catch (error) {\n onFetchError?.(\n sig,\n error instanceof Error ? error : new Error(String(error)),\n );\n return null;\n }\n };\n\n const promises = signatures.map((sig) => limit(() => safeFetch(sig)));\n\n const results = await Promise.all(promises);\n return results.filter((tx): tx is RawTransaction => tx !== null);\n}\n","export type AccountIdType = \"wallet\" | \"protocol\" | \"external\" | \"fee\";\n\nexport interface BuildAccountIdParams {\n type: AccountIdType;\n address: string;\n protocol?: string;\n token?: string;\n}\n\n/**\n * Builds a standardized account identifier string for transaction legs.\n * \n * Account IDs follow these formats:\n * - Wallet: `wallet:{address}`\n * - Protocol: `protocol:{protocol}:{token}:{address}` or `protocol:{protocol}:{address}`\n * - External: `external:{address}`\n * - Fee: `fee:network`\n * \n * @param params - Account identifier parameters\n * @returns Formatted account ID string\n * @throws Error if parameters are invalid for the account type\n */\nexport function buildAccountId(params: BuildAccountIdParams): string {\n const { type, address, protocol, token } = params;\n\n if (type === \"wallet\") {\n return `wallet:${address}`;\n }\n\n if (type === \"protocol\" && protocol) {\n if (token) {\n return `protocol:${protocol}:${token}:${address}`;\n }\n return `protocol:${protocol}:${address}`;\n }\n\n if (type === \"external\") {\n return `external:${address}`;\n }\n\n if (type === \"fee\") {\n return \"fee:network\";\n }\n \n throw new Error(\n `Invalid accountId parameters: type=${type}, address=${address}, protocol=${protocol}`\n );\n}\n\nexport interface ParsedAccountId {\n type: AccountIdType | \"unknown\";\n address?: string;\n protocol?: string;\n token?: string;\n}\n\n/**\n * Parses an account identifier string into its components.\n * \n * Extracts the account type, address, protocol, and token information from\n * a formatted account ID string. Returns `unknown` type for unrecognized formats.\n * \n * @param accountId - Account ID string to parse\n * @returns Parsed account identifier with type and optional metadata\n */\nexport function parseAccountId(accountId: string): ParsedAccountId {\n const parts = accountId.split(\":\");\n\n if (parts[0] === \"wallet\" && parts.length === 2) {\n return { type: \"wallet\", address: parts[1] };\n }\n\n if (parts[0] === \"protocol\") {\n if (parts.length === 4) {\n return {\n type: \"protocol\",\n protocol: parts[1],\n token: parts[2],\n address: parts[3],\n };\n }\n if (parts.length === 3) {\n return {\n type: \"protocol\",\n protocol: parts[1],\n address: parts[2],\n };\n }\n }\n\n if (parts[0] === \"external\" && parts.length === 2) {\n return { type: \"external\", address: parts[1] };\n }\n\n if (parts[0] === \"fee\" && parts[1] === \"network\") {\n return { type: \"fee\" };\n }\n\n return { type: \"unknown\", address: accountId };\n}\n","import type { Address } from \"@solana/kit\";\nimport type { RawTransaction, TokenBalance } from \"@tx-indexer/core/tx/tx.types\";\nimport type { MoneyAmount, TokenInfo } from \"@tx-indexer/core/money/money.types\";\nimport {\n getTokenInfo,\n KNOWN_TOKENS,\n TOKEN_INFO,\n} from \"@tx-indexer/core/money/token-registry\";\n\nexport interface TokenBalanceChange {\n mint: string;\n tokenInfo: TokenInfo;\n accountIndex: number;\n owner?: string;\n preBalance: {\n raw: string;\n ui: number;\n };\n postBalance: {\n raw: string;\n ui: number;\n };\n change: {\n raw: string;\n ui: number;\n };\n}\n\nexport interface SolBalanceChange {\n accountIndex: number;\n address: string;\n preBalance: bigint;\n postBalance: bigint;\n change: bigint;\n changeUi: number;\n}\n\n/**\n * Extracts all SPL token balance changes from a transaction.\n * \n * Compares pre and post token balances to calculate the change for each token account.\n * Unknown tokens are automatically included with a generated symbol from their mint address.\n * \n * @param tx - Raw transaction with token balance data\n * @param filterMints - Optional array of mint addresses to filter to specific tokens\n * @returns Array of token balance changes with mint, owner, and amount information\n */\nexport function extractTokenBalanceChanges(\n tx: RawTransaction,\n filterMints?: string[]\n): TokenBalanceChange[] {\n const { preTokenBalances = [], postTokenBalances = [] } = tx;\n\n const changes: TokenBalanceChange[] = [];\n\n const preBalanceMap = new Map<number, TokenBalance>();\n for (const bal of preTokenBalances) {\n preBalanceMap.set(bal.accountIndex, bal);\n }\n\n for (const postBal of postTokenBalances) {\n const { accountIndex, mint } = postBal;\n\n if (filterMints && !filterMints.includes(mint)) {\n continue;\n }\n\n let tokenInfo = getTokenInfo(mint);\n if (!tokenInfo) {\n tokenInfo = {\n mint,\n symbol: mint.slice(0, 8),\n decimals: postBal.uiTokenAmount.decimals,\n name: `Unknown Token (${mint.slice(0, 8)}...)`,\n };\n }\n\n const preBal = preBalanceMap.get(accountIndex);\n\n const preAmount = preBal?.uiTokenAmount.amount ?? \"0\";\n const postAmount = postBal.uiTokenAmount.amount;\n const preUi = preBal?.uiTokenAmount.uiAmountString\n ? parseFloat(preBal.uiTokenAmount.uiAmountString)\n : 0;\n const postUi = postBal.uiTokenAmount.uiAmountString\n ? parseFloat(postBal.uiTokenAmount.uiAmountString)\n : 0;\n\n const changeRaw = (BigInt(postAmount) - BigInt(preAmount)).toString();\n const changeUi = postUi - preUi;\n\n if (changeRaw !== \"0\") {\n changes.push({\n mint,\n tokenInfo,\n accountIndex,\n owner: postBal.owner,\n preBalance: {\n raw: preAmount,\n ui: preUi,\n },\n postBalance: {\n raw: postAmount,\n ui: postUi,\n },\n change: {\n raw: changeRaw,\n ui: changeUi,\n },\n });\n }\n }\n\n return changes;\n}\n\n/**\n * Extracts SOL balance changes for all accounts in a transaction.\n * \n * Compares pre and post lamport balances for each account key to calculate\n * the SOL change. Only includes accounts with non-zero changes.\n * \n * @param tx - Raw transaction with SOL balance data\n * @returns Array of SOL balance changes with account address and amounts\n */\nexport function extractSolBalanceChanges(\n tx: RawTransaction\n): SolBalanceChange[] {\n const {\n preBalances = [],\n postBalances = [],\n accountKeys = [],\n } = tx;\n\n const changes: SolBalanceChange[] = [];\n\n for (let i = 0; i < accountKeys.length; i++) {\n const address = accountKeys[i];\n if (!address) continue;\n\n const preBal = BigInt(preBalances[i] ?? 0);\n const postBal = BigInt(postBalances[i] ?? 0);\n const change = postBal - preBal;\n\n if (change !== 0n) {\n changes.push({\n accountIndex: i,\n address,\n preBalance: preBal,\n postBalance: postBal,\n change,\n changeUi: Number(change) / 1e9,\n });\n }\n }\n\n return changes;\n}\n\nexport function getWalletTokenChanges(\n tx: RawTransaction,\n walletAddress: Address,\n filterMints?: string[]\n): TokenBalanceChange[] {\n const allChanges = extractTokenBalanceChanges(tx, filterMints);\n\n return allChanges.filter(\n (change) =>\n change.owner?.toLowerCase() === walletAddress.toLowerCase()\n );\n}\n\nexport function getWalletSolChange(\n tx: RawTransaction,\n walletAddress: Address\n): SolBalanceChange | null {\n if (!tx.accountKeys || tx.accountKeys.length === 0) {\n return null;\n }\n\n const allChanges = extractSolBalanceChanges(tx);\n\n return (\n allChanges.find(\n (change) => change.address.toLowerCase() === walletAddress.toLowerCase()\n ) ?? null\n );\n}\n\nexport function toMoneyAmount(change: TokenBalanceChange): MoneyAmount {\n return {\n token: change.tokenInfo,\n amountRaw: change.change.raw,\n amountUi: change.change.ui,\n };\n}\n\nexport function solChangeToMoneyAmount(change: SolBalanceChange): MoneyAmount {\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (!solInfo) {\n throw new Error(\"SOL token info not found in registry\");\n }\n return {\n token: solInfo,\n amountRaw: change.change.toString(),\n amountUi: change.changeUi,\n };\n}\n\n","/**\n * Constants for DEX protocol detection\n */\n\nexport const DEX_PROTOCOL_IDS = new Set([\n \"jupiter\",\n \"jupiter-v4\",\n \"raydium\",\n \"orca-whirlpool\",\n]);\n\n","import type {\n RawTransaction,\n TxLeg,\n TxLegRole,\n} from \"@tx-indexer/core/tx/tx.types\";\nimport type { ProtocolInfo } from \"@tx-indexer/core/actors/counterparty.types\";\nimport { buildAccountId } from \"@tx-indexer/core/tx/account-id\";\nimport {\n extractSolBalanceChanges,\n extractTokenBalanceChanges,\n type SolBalanceChange,\n type TokenBalanceChange,\n} from \"./balance-parser\";\nimport {\n KNOWN_TOKENS,\n TOKEN_INFO,\n} from \"@tx-indexer/core/money/token-registry\";\nimport { DEX_PROTOCOL_IDS } from \"../constants/protocol-constants\";\n\nfunction isDexProtocol(protocol: ProtocolInfo | null | undefined): boolean {\n return (\n protocol !== null &&\n protocol !== undefined &&\n DEX_PROTOCOL_IDS.has(protocol.id)\n );\n}\n\n/**\n * Converts a raw Solana transaction into a double-entry accounting ledger.\n *\n * Creates TxLeg entries for all SOL and token balance changes, automatically\n * detecting and accounting for network fees. Each leg represents a debit or credit\n * for a specific account and token, enabling transaction classification and validation.\n *\n * All accounts are tagged as \"external:\" - the classification layer determines\n * the transaction type and direction from the initiator's (fee payer's) perspective.\n *\n * @param tx - Raw transaction data with balance changes\n * @returns Array of transaction legs representing all balance movements\n */\nexport function transactionToLegs(tx: RawTransaction): TxLeg[] {\n const legs: TxLeg[] = [];\n const feePayer = tx.accountKeys?.[0]?.toLowerCase();\n\n const solChanges = extractSolBalanceChanges(tx);\n let totalSolDebits = 0n;\n let totalSolCredits = 0n;\n\n for (const change of solChanges) {\n if (change.change === 0n) continue;\n\n const accountId = buildAccountId({\n type: \"external\",\n address: change.address,\n });\n\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (!solInfo) {\n throw new Error(\"SOL token info not found in registry\");\n }\n\n if (change.change > 0n) {\n totalSolCredits += change.change;\n } else {\n totalSolDebits += -change.change;\n }\n\n legs.push({\n accountId,\n side: change.change > 0n ? \"credit\" : \"debit\",\n amount: {\n token: solInfo,\n amountRaw: change.change.toString().replace(\"-\", \"\"),\n amountUi: Math.abs(change.changeUi),\n },\n role: determineSolRole(change, tx, feePayer),\n });\n }\n\n const networkFee = totalSolDebits - totalSolCredits;\n if (networkFee > 0n) {\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (solInfo) {\n legs.push({\n accountId: buildAccountId({ type: \"fee\", address: \"\" }),\n side: \"credit\",\n amount: {\n token: solInfo,\n amountRaw: networkFee.toString(),\n amountUi: Number(networkFee) / 1e9,\n },\n role: \"fee\",\n });\n }\n }\n\n const tokenChanges = extractTokenBalanceChanges(tx);\n for (const change of tokenChanges) {\n if (change.change.raw === \"0\") continue;\n\n let accountId: string;\n if (isDexProtocol(tx.protocol)) {\n const isFeePayer = feePayer && change.owner?.toLowerCase() === feePayer;\n if (isFeePayer) {\n accountId = buildAccountId({\n type: \"external\",\n address: change.owner || feePayer,\n });\n } else {\n accountId = buildAccountId({\n type: \"protocol\",\n address: change.owner || change.tokenInfo.mint,\n protocol: tx.protocol!.id,\n token: change.tokenInfo.symbol,\n });\n }\n } else {\n accountId = buildAccountId({\n type: \"external\",\n address: change.owner || change.tokenInfo.mint,\n });\n }\n\n legs.push({\n accountId,\n side: change.change.ui > 0 ? \"credit\" : \"debit\",\n amount: {\n token: change.tokenInfo,\n amountRaw: change.change.raw.replace(\"-\", \"\"),\n amountUi: Math.abs(change.change.ui),\n },\n role: determineTokenRole(change, tx, feePayer),\n });\n }\n\n return legs;\n}\n\n/**\n * Determines the role of a SOL balance change in the transaction context.\n *\n * Network fees are handled separately via the fee:network leg (calculated from\n * the imbalance between total debits and credits). This function only categorizes\n * external account balance changes as sent/received.\n *\n * @param change - SOL balance change for an account\n * @param tx - Raw transaction for additional context\n * @param _feePayer - Fee payer address (unused, kept for API compatibility)\n * @returns The role of this SOL balance change\n */\nfunction determineSolRole(\n change: SolBalanceChange,\n tx: RawTransaction,\n _feePayer?: string,\n): TxLegRole {\n const isPositive = change.change > 0n;\n\n if (isPositive) {\n if (tx.protocol?.id === \"stake\") {\n return \"reward\";\n }\n return \"received\";\n }\n\n return \"sent\";\n}\n\n/**\n * Determines the role of a token balance change in the transaction context.\n *\n * @param change - Token balance change for an account\n * @param tx - Raw transaction for protocol context\n * @param feePayer - Fee payer address\n * @returns The role of this token balance change\n */\nfunction determineTokenRole(\n change: TokenBalanceChange,\n tx: RawTransaction,\n feePayer?: string,\n): TxLegRole {\n const isFeePayer = feePayer\n ? change.owner?.toLowerCase() === feePayer\n : false;\n const isPositive = change.change.ui > 0;\n\n if (isFeePayer) {\n return isPositive ? \"received\" : \"sent\";\n }\n\n if (isDexProtocol(tx.protocol)) {\n return isPositive ? \"protocol_withdraw\" : \"protocol_deposit\";\n }\n\n return isPositive ? \"received\" : \"sent\";\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { detectFacilitator } from \"@tx-indexer/solana/constants/program-ids\";\n\nexport class TransferClassifier implements Classifier {\n name = \"transfer\";\n priority = 20;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const facilitator = tx.accountKeys\n ? detectFacilitator(tx.accountKeys)\n : null;\n\n const senderLeg = legs.find(\n (l) =>\n l.accountId.startsWith(\"external:\") &&\n l.side === \"debit\" &&\n l.role === \"sent\"\n );\n\n if (!senderLeg) return null;\n\n const sender = senderLeg.accountId.replace(\"external:\", \"\");\n\n const receiverLeg = legs.find(\n (l) =>\n l.accountId.startsWith(\"external:\") &&\n l.side === \"credit\" &&\n l.role === \"received\" &&\n l.amount.token.mint === senderLeg.amount.token.mint\n );\n\n if (!receiverLeg) return null;\n\n const receiver = receiverLeg.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"transfer\",\n primaryAmount: senderLeg.amount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: {\n type: \"unknown\",\n address: receiver,\n name: `${receiver.slice(0, 8)}...`,\n },\n confidence: 0.95,\n isRelevant: true,\n metadata: {\n ...(facilitator && { facilitator, payment_type: \"facilitated\" }),\n },\n };\n }\n}\n","import type { ProtocolInfo } from \"@tx-indexer/core/actors/counterparty.types\";\nimport {\n // Core programs\n JUPITER_V6_PROGRAM_ID,\n JUPITER_V4_PROGRAM_ID,\n JUPITER_ORDER_ENGINE_PROGRAM_ID,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n SYSTEM_PROGRAM_ID,\n COMPUTE_BUDGET_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n // DEX programs\n RAYDIUM_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n RAYDIUM_CPMM_PROGRAM_ID,\n RAYDIUM_STABLE_PROGRAM_ID,\n ORCA_WHIRLPOOL_PROGRAM_ID,\n ORCA_TOKEN_SWAP_V1_PROGRAM_ID,\n OPENBOOK_V2_PROGRAM_ID,\n PHOENIX_PROGRAM_ID,\n SABER_STABLE_SWAP_PROGRAM_ID,\n MERCURIAL_STABLE_SWAP_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n METEORA_POOLS_PROGRAM_ID,\n PUMPFUN_AMM_PROGRAM_ID,\n PUMPFUN_BONDING_CURVE_PROGRAM_ID,\n LIFINITY_V2_PROGRAM_ID,\n // NFT programs\n METAPLEX_PROGRAM_ID,\n CANDY_GUARD_PROGRAM_ID,\n CANDY_MACHINE_V3_PROGRAM_ID,\n BUBBLEGUM_PROGRAM_ID,\n MAGIC_EDEN_CANDY_MACHINE_ID,\n // Staking programs\n STAKE_POOL_PROGRAM_ID,\n STAKE_PROGRAM_ID,\n // Bridge programs\n WORMHOLE_PROGRAM_ID,\n WORMHOLE_TOKEN_BRIDGE_ID,\n DEGODS_BRIDGE_PROGRAM_ID,\n DEBRIDGE_PROGRAM_ID,\n ALLBRIDGE_PROGRAM_ID,\n} from \"@tx-indexer/solana/constants/program-ids\";\n\nconst KNOWN_PROGRAMS: Record<string, ProtocolInfo> = {\n // Jupiter aggregator\n [JUPITER_V6_PROGRAM_ID]: {\n id: \"jupiter\",\n name: \"Jupiter\",\n },\n [JUPITER_V4_PROGRAM_ID]: {\n id: \"jupiter-v4\",\n name: \"Jupiter V4\",\n },\n [JUPITER_ORDER_ENGINE_PROGRAM_ID]: {\n id: \"jupiter-limit-order\",\n name: \"Jupiter Limit Order\",\n },\n\n // Core token programs\n [TOKEN_PROGRAM_ID]: {\n id: \"spl-token\",\n name: \"Token Program\",\n },\n [TOKEN_2022_PROGRAM_ID]: {\n id: \"token-2022\",\n name: \"Token-2022 Program\",\n },\n [SYSTEM_PROGRAM_ID]: {\n id: \"system\",\n name: \"System Program\",\n },\n [COMPUTE_BUDGET_PROGRAM_ID]: {\n id: \"compute-budget\",\n name: \"Compute Budget\",\n },\n [ASSOCIATED_TOKEN_PROGRAM_ID]: {\n id: \"associated-token\",\n name: \"Associated Token Program\",\n },\n\n // Memo programs\n [SPL_MEMO_PROGRAM_ID]: {\n id: \"memo\",\n name: \"Memo Program\",\n },\n [MEMO_V1_PROGRAM_ID]: {\n id: \"memo-v1\",\n name: \"Memo Program V1\",\n },\n\n // Raydium AMMs\n [RAYDIUM_PROGRAM_ID]: {\n id: \"raydium\",\n name: \"Raydium\",\n },\n [RAYDIUM_CLMM_PROGRAM_ID]: {\n id: \"raydium-clmm\",\n name: \"Raydium CLMM\",\n },\n [RAYDIUM_CPMM_PROGRAM_ID]: {\n id: \"raydium-cpmm\",\n name: \"Raydium CPMM\",\n },\n [RAYDIUM_STABLE_PROGRAM_ID]: {\n id: \"raydium-stable\",\n name: \"Raydium Stable\",\n },\n\n // Orca\n [ORCA_WHIRLPOOL_PROGRAM_ID]: {\n id: \"orca-whirlpool\",\n name: \"Orca Whirlpool\",\n },\n [ORCA_TOKEN_SWAP_V1_PROGRAM_ID]: {\n id: \"orca-v1\",\n name: \"Orca Token Swap V1\",\n },\n\n // CLOBs (Central Limit Order Books)\n [OPENBOOK_V2_PROGRAM_ID]: {\n id: \"openbook\",\n name: \"OpenBook\",\n },\n [PHOENIX_PROGRAM_ID]: {\n id: \"phoenix\",\n name: \"Phoenix\",\n },\n\n // Stableswap protocols\n [SABER_STABLE_SWAP_PROGRAM_ID]: {\n id: \"saber\",\n name: \"Saber\",\n },\n [MERCURIAL_STABLE_SWAP_PROGRAM_ID]: {\n id: \"mercurial\",\n name: \"Mercurial\",\n },\n\n // Meteora\n [METEORA_DLMM_PROGRAM_ID]: {\n id: \"meteora-dlmm\",\n name: \"Meteora DLMM\",\n },\n [METEORA_POOLS_PROGRAM_ID]: {\n id: \"meteora-pools\",\n name: \"Meteora Pools\",\n },\n\n // Pump.fun\n [PUMPFUN_AMM_PROGRAM_ID]: {\n id: \"pumpfun\",\n name: \"Pump.fun\",\n },\n [PUMPFUN_BONDING_CURVE_PROGRAM_ID]: {\n id: \"pumpfun-bonding\",\n name: \"Pump.fun Bonding Curve\",\n },\n\n // Lifinity\n [LIFINITY_V2_PROGRAM_ID]: {\n id: \"lifinity\",\n name: \"Lifinity\",\n },\n\n // NFT programs\n [METAPLEX_PROGRAM_ID]: {\n id: \"metaplex\",\n name: \"Metaplex\",\n },\n [CANDY_GUARD_PROGRAM_ID]: {\n id: \"candy-guard\",\n name: \"Metaplex Candy Guard Program\",\n },\n [CANDY_MACHINE_V3_PROGRAM_ID]: {\n id: \"candy-machine-v3\",\n name: \"Metaplex Candy Machine Core Program\",\n },\n [BUBBLEGUM_PROGRAM_ID]: {\n id: \"bubblegum\",\n name: \"Bubblegum Program\",\n },\n [MAGIC_EDEN_CANDY_MACHINE_ID]: {\n id: \"magic-eden-candy-machine\",\n name: \"Nft Candy Machine Program (Magic Eden)\",\n },\n\n // Staking programs\n [STAKE_PROGRAM_ID]: {\n id: \"stake\",\n name: \"Stake Program\",\n },\n [STAKE_POOL_PROGRAM_ID]: {\n id: \"stake-pool\",\n name: \"Stake Pool Program\",\n },\n\n // Bridge programs\n [WORMHOLE_PROGRAM_ID]: {\n id: \"wormhole\",\n name: \"Wormhole\",\n },\n [WORMHOLE_TOKEN_BRIDGE_ID]: {\n id: \"wormhole-token-bridge\",\n name: \"Wormhole Token Bridge\",\n },\n [DEGODS_BRIDGE_PROGRAM_ID]: {\n id: \"degods-bridge\",\n name: \"DeGods Bridge\",\n },\n [DEBRIDGE_PROGRAM_ID]: {\n id: \"debridge\",\n name: \"deBridge\",\n },\n [ALLBRIDGE_PROGRAM_ID]: {\n id: \"allbridge\",\n name: \"Allbridge\",\n },\n};\n\nconst PRIORITY_ORDER = [\n // Bridge protocols (highest priority - cross-chain operations)\n \"wormhole\",\n \"wormhole-token-bridge\",\n \"degods-bridge\",\n \"debridge\",\n \"allbridge\",\n // DEX aggregators (route through multiple DEXes)\n \"jupiter\",\n \"jupiter-v4\",\n \"jupiter-limit-order\",\n // AMMs and DEXes\n \"raydium\",\n \"raydium-clmm\",\n \"raydium-cpmm\",\n \"raydium-stable\",\n \"orca-whirlpool\",\n \"orca-v1\",\n \"meteora-dlmm\",\n \"meteora-pools\",\n \"lifinity\",\n \"pumpfun\",\n \"pumpfun-bonding\",\n // CLOBs\n \"openbook\",\n \"phoenix\",\n // Stableswap\n \"saber\",\n \"mercurial\",\n // NFT\n \"metaplex\",\n \"candy-guard\",\n \"candy-machine-v3\",\n \"bubblegum\",\n \"magic-eden-candy-machine\",\n // Staking\n \"stake\",\n \"stake-pool\",\n // Infrastructure (lowest priority)\n \"memo\",\n \"memo-v1\",\n \"associated-token\",\n \"spl-token\",\n \"token-2022\",\n \"compute-budget\",\n \"system\",\n];\n\n/**\n * Protocol IDs that are DEX (decentralized exchange) protocols.\n * These protocols perform swaps and should have their legs tagged as \"protocol:\"\n * with deposit/withdraw roles.\n */\nconst DEX_PROTOCOL_IDS = new Set([\n // Jupiter aggregator\n \"jupiter\",\n \"jupiter-v4\",\n \"jupiter-limit-order\",\n // Raydium AMMs\n \"raydium\",\n \"raydium-clmm\",\n \"raydium-cpmm\",\n \"raydium-stable\",\n // Orca\n \"orca-whirlpool\",\n \"orca-v1\",\n // CLOBs\n \"openbook\",\n \"phoenix\",\n // Stableswap\n \"saber\",\n \"mercurial\",\n // Meteora\n \"meteora-dlmm\",\n \"meteora-pools\",\n // Pump.fun\n \"pumpfun\",\n \"pumpfun-bonding\",\n // Lifinity\n \"lifinity\",\n]);\n\nconst NFT_MINT_PROTOCOL_IDS = new Set([\n \"metaplex\",\n \"candy-machine-v3\",\n \"candy-guard\",\n \"bubblegum\",\n \"magic-eden-candy-machine\",\n]);\n\nconst STAKE_PROTOCOL_IDS = new Set([\"stake\", \"stake-pool\"]);\n\nconst BRIDGE_PROTOCOL_IDS = new Set([\n \"wormhole\",\n \"wormhole-token-bridge\",\n \"degods-bridge\",\n \"debridge\",\n \"allbridge\",\n]);\n\n/**\n * Checks if a protocol is a DEX (decentralized exchange) that performs swaps.\n * DEX protocols should have their legs tagged as \"protocol:\" with deposit/withdraw roles.\n * Non-DEX protocols (like Associated Token Program) are infrastructure and should not\n * affect leg tagging.\n */\nexport function isDexProtocol(protocol: ProtocolInfo | null): boolean {\n return protocol !== null && DEX_PROTOCOL_IDS.has(protocol.id);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a DEX protocol.\n * Useful when you only have the protocol ID string, not the full ProtocolInfo object.\n */\nexport function isDexProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && DEX_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a NFT Mint\n */\nexport function isNftMintProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && NFT_MINT_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a stake\n */\n\nexport function isStakeProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && STAKE_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a bridge protocol\n */\nexport function isBridgeProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && BRIDGE_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Detects the primary protocol used in a transaction based on its program IDs.\n *\n * When multiple protocols are detected, returns the highest priority protocol\n * according to the PRIORITY_ORDER (e.g., Jupiter > Raydium > Token Program).\n *\n * @param programIds - Array of program IDs involved in the transaction\n * @returns The detected protocol information, or null if no known protocol is found\n */\nexport function detectProtocol(programIds: string[]): ProtocolInfo | null {\n const detectedProtocols: ProtocolInfo[] = [];\n\n for (const programId of programIds) {\n const protocol = KNOWN_PROGRAMS[programId];\n if (protocol) {\n detectedProtocols.push(protocol);\n }\n }\n\n if (detectedProtocols.length === 0) {\n return null;\n }\n\n detectedProtocols.sort((a, b) => {\n const aPriority = PRIORITY_ORDER.indexOf(a.id);\n const bPriority = PRIORITY_ORDER.indexOf(b.id);\n return aPriority - bPriority;\n });\n\n return detectedProtocols[0] ?? null;\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport type { TxLeg } from \"@tx-indexer/core/tx/tx.types\";\nimport { isDexProtocolById } from \"../protocols/detector\";\n\n/**\n * Finds the best swap pair from the lists of tokens going out and coming in.\n *\n * The best pair is determined by:\n * 1. Must have different token symbols (otherwise it's not a swap)\n * 2. Prefer the pair with the largest total value (to avoid picking up dust/fees)\n *\n * For now, we use amountUi as a proxy for value since we don't have USD prices.\n * This works well because:\n * - The main swap tokens typically have much larger amounts than dust\n * - A 2000 USDC swap will always beat a 0.0002 SOL fee\n */\nfunction findSwapPair(\n tokensOut: TxLeg[],\n tokensIn: TxLeg[],\n): { initiatorOut: TxLeg; initiatorIn: TxLeg } | null {\n let bestPair: { initiatorOut: TxLeg; initiatorIn: TxLeg } | null = null;\n let bestScore = 0;\n\n for (const out of tokensOut) {\n for (const inLeg of tokensIn) {\n if (out.amount.token.symbol !== inLeg.amount.token.symbol) {\n // Score by the larger of the two amounts (in UI units)\n // This helps identify the \"main\" swap vs dust movements\n const score = Math.max(out.amount.amountUi, inLeg.amount.amountUi);\n\n if (score > bestScore) {\n bestScore = score;\n bestPair = { initiatorOut: out, initiatorIn: inLeg };\n }\n }\n }\n }\n\n return bestPair;\n}\n\nexport class SwapClassifier implements Classifier {\n name = \"swap\";\n priority = 80;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx, walletAddress } = context;\n\n const initiator = tx.accountKeys?.[0] ?? null;\n\n if (!initiator) {\n return null;\n }\n\n const initiatorAccountId = `external:${initiator}`;\n\n const initiatorTokensOut = legs.filter(\n (leg) =>\n leg.accountId === initiatorAccountId &&\n leg.side === \"debit\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\"),\n );\n\n const initiatorTokensIn = legs.filter(\n (leg) =>\n leg.accountId === initiatorAccountId &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\"),\n );\n\n if (initiatorTokensOut.length === 0 || initiatorTokensIn.length === 0) {\n return null;\n }\n\n const swapPair = findSwapPair(initiatorTokensOut, initiatorTokensIn);\n if (!swapPair) {\n return null;\n }\n\n const { initiatorOut, initiatorIn } = swapPair;\n\n let tokenOut = initiatorOut;\n let tokenIn = initiatorIn;\n let perspectiveWallet = initiator;\n\n if (walletAddress) {\n const walletAccountId = `external:${walletAddress}`;\n\n const walletOut = legs.find(\n (leg) =>\n leg.accountId === walletAccountId &&\n leg.side === \"debit\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\"),\n );\n\n const walletIn = legs.find(\n (leg) =>\n leg.accountId === walletAccountId &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\"),\n );\n\n if (\n walletOut &&\n walletIn &&\n walletOut.amount.token.symbol !== walletIn.amount.token.symbol\n ) {\n tokenOut = walletOut;\n tokenIn = walletIn;\n perspectiveWallet = walletAddress;\n }\n }\n\n const hasDexProtocol = isDexProtocolById(tx.protocol?.id);\n const confidence = hasDexProtocol ? 0.95 : 0.75;\n\n return {\n primaryType: \"swap\",\n primaryAmount: tokenOut.amount,\n secondaryAmount: tokenIn.amount,\n sender: perspectiveWallet,\n receiver: perspectiveWallet,\n counterparty: null,\n confidence,\n isRelevant: true,\n metadata: {\n swap_type: \"token_to_token\",\n from_token: tokenOut.amount.token.symbol,\n to_token: tokenIn.amount.token.symbol,\n from_amount: tokenOut.amount.amountUi,\n to_amount: tokenIn.amount.amountUi,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { detectFacilitator } from \"@tx-indexer/solana/constants/program-ids\";\n\nexport class AirdropClassifier implements Classifier {\n name = \"airdrop\";\n priority = 70;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const facilitator = tx.accountKeys\n ? detectFacilitator(tx.accountKeys)\n : null;\n\n const protocolLegs = legs.filter((leg) =>\n leg.accountId.startsWith(\"protocol:\")\n );\n\n if (protocolLegs.length === 0) {\n return null;\n }\n\n const tokenReceived = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.role === \"received\" &&\n leg.amount.token.symbol !== \"SOL\"\n );\n\n if (tokenReceived.length === 0) {\n return null;\n }\n\n const tokenSent = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role === \"sent\" &&\n leg.amount.token.symbol !== \"SOL\"\n );\n\n if (tokenSent.length > 0) {\n return null;\n }\n\n const mainToken = tokenReceived[0]!;\n const receiver = mainToken.accountId.replace(\"external:\", \"\");\n\n const senderLeg = legs.find(\n (leg) =>\n leg.side === \"debit\" &&\n leg.amount.token.mint === mainToken.amount.token.mint\n );\n\n const sender = senderLeg\n ? senderLeg.accountId.replace(/^(external:|protocol:)/, \"\")\n : null;\n\n return {\n primaryType: \"airdrop\",\n primaryAmount: mainToken.amount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: sender\n ? {\n type: \"protocol\",\n address: sender,\n }\n : null,\n confidence: 0.85,\n isRelevant: true,\n metadata: {\n airdrop_type: \"token\",\n token: mainToken.amount.token.symbol,\n amount: mainToken.amount.amountUi,\n ...(facilitator && { facilitator }),\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\n\nexport class FeeOnlyClassifier implements Classifier {\n name = \"fee-only\";\n priority = 60;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs } = context;\n\n const externalLegs = legs.filter((leg) =>\n leg.accountId.startsWith(\"external:\")\n );\n const nonFeeLegs = externalLegs.filter((leg) => leg.role !== \"fee\");\n\n if (nonFeeLegs.length > 0) {\n return null;\n }\n\n const feeLegs = legs.filter((leg) => leg.role === \"fee\");\n\n if (feeLegs.length === 0) {\n return null;\n }\n\n const feePayerLeg = feeLegs.find(\n (leg) => leg.side === \"debit\" && leg.amount.token.symbol === \"SOL\"\n );\n\n const feePayer = feePayerLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const totalFee = feeLegs.find((leg) => leg.amount.token.symbol === \"SOL\");\n\n return {\n primaryType: \"fee_only\",\n primaryAmount: totalFee?.amount ?? null,\n secondaryAmount: null,\n sender: feePayer,\n receiver: null,\n counterparty: null,\n confidence: 0.95,\n isRelevant: false,\n metadata: {\n fee_type: \"network\",\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport {\n isSolanaPayTransaction,\n parseSolanaPayMemo,\n} from \"@tx-indexer/solana/mappers/memo-parser\";\n\nexport class SolanaPayClassifier implements Classifier {\n name = \"solana-pay\";\n priority = 95;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { tx, legs } = context;\n\n if (!isSolanaPayTransaction(tx.programIds, tx.memo)) {\n return null;\n }\n\n const memo = parseSolanaPayMemo(tx.memo!);\n\n const senderLeg = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role === \"sent\"\n );\n\n const receiverLeg = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.role === \"received\"\n );\n\n const sender = senderLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const receiver = receiverLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const primaryAmount = senderLeg?.amount ?? receiverLeg?.amount ?? null;\n\n return {\n primaryType: \"transfer\",\n primaryAmount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: receiver\n ? {\n address: receiver,\n name: memo.merchant ?? undefined,\n type: memo.merchant ? \"merchant\" : \"unknown\",\n }\n : null,\n confidence: 0.98,\n isRelevant: true,\n metadata: {\n payment_type: \"solana_pay\",\n memo: memo.raw,\n merchant: memo.merchant,\n item: memo.item,\n reference: memo.reference,\n label: memo.label,\n message: memo.message,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isNftMintProtocolById } from \"../protocols/detector\";\n\nexport class NftMintClassifier implements Classifier {\n name = \"nft-mint\";\n priority = 85;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasNftMintProtocol = isNftMintProtocolById(tx.protocol?.id);\n if (!hasNftMintProtocol) {\n return null;\n }\n\n const nftCredits = legs.filter(\n (leg) =>\n leg.side === \"credit\" &&\n leg.amount.token.decimals === 0 &&\n leg.amount.amountUi >= 1 &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n if (nftCredits.length === 0) {\n return null;\n }\n\n const primaryNft = nftCredits[0]!;\n const minter = primaryNft.accountId.replace(\"external:\", \"\");\n\n const paymentLeg = legs.find(\n (leg) =>\n leg.side === \"debit\" &&\n leg.role === \"sent\" &&\n leg.amount.token.symbol === \"SOL\"\n );\n\n const totalMinted = nftCredits.reduce(\n (sum, leg) => sum + leg.amount.amountUi,\n 0\n );\n\n return {\n primaryType: \"nft_mint\",\n primaryAmount: primaryNft.amount,\n secondaryAmount: paymentLeg?.amount ?? null,\n sender: null,\n receiver: minter,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n nft_mint: primaryNft.amount.token.mint,\n nft_name: primaryNft.amount.token.name,\n quantity: totalMinted,\n mint_price: paymentLeg?.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isStakeProtocolById } from \"../protocols/detector\";\n\nexport class StakeDepositClassifier implements Classifier {\n name = \"stake-deposit\";\n priority = 82;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);\n if (!hasStakeProtocol) {\n return null;\n }\n\n const solDebit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n if (!solDebit) {\n return null;\n }\n\n const staker = solDebit.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"stake_deposit\",\n primaryAmount: solDebit.amount,\n secondaryAmount: null,\n sender: staker,\n receiver: null,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n stake_amount: solDebit.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isStakeProtocolById } from \"../protocols/detector\";\n\nexport class StakeWithdrawClassifier implements Classifier {\n name = \"stake-withdraw\";\n priority = 81;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);\n if (!hasStakeProtocol) {\n return null;\n }\n\n const solCredit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n if (!solCredit) {\n return null;\n }\n\n const solDebit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n if (solDebit) {\n return null;\n }\n\n const withdrawer = solCredit.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"stake_withdraw\",\n primaryAmount: solCredit.amount,\n secondaryAmount: null,\n sender: null,\n receiver: withdrawer,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n withdraw_amount: solCredit.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isBridgeProtocolById } from \"../protocols/detector\";\n\nexport class BridgeClassifier implements Classifier {\n name = \"bridge\";\n priority = 88;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasBridgeProtocol = isBridgeProtocolById(tx.protocol?.id);\n if (!hasBridgeProtocol) {\n return null;\n }\n\n const tokensOut = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role !== \"fee\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n const tokensIn = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n let primaryType: \"bridge_in\" | \"bridge_out\";\n let primaryAmount = null;\n let participant: string | null = null;\n\n if (tokensIn.length > 0 && tokensOut.length === 0) {\n primaryType = \"bridge_in\";\n const creditLeg = tokensIn[0]!;\n primaryAmount = creditLeg.amount;\n participant = creditLeg.accountId.replace(\"external:\", \"\");\n } else if (tokensOut.length > 0 && tokensIn.length === 0) {\n primaryType = \"bridge_out\";\n const debitLeg = tokensOut[0]!;\n primaryAmount = debitLeg.amount;\n participant = debitLeg.accountId.replace(\"external:\", \"\");\n } else if (tokensIn.length > 0 && tokensOut.length > 0) {\n primaryType = \"bridge_in\";\n const creditLeg = tokensIn[0]!;\n primaryAmount = creditLeg.amount;\n participant = creditLeg.accountId.replace(\"external:\", \"\");\n } else {\n return null;\n }\n\n return {\n primaryType,\n primaryAmount,\n secondaryAmount: null,\n sender: primaryType === \"bridge_out\" ? participant : null,\n receiver: primaryType === \"bridge_in\" ? participant : null,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n bridge_protocol: tx.protocol?.id,\n bridge_name: tx.protocol?.name,\n },\n };\n }\n}\n","import type { TxLeg, RawTransaction } from \"@tx-indexer/core/tx/tx.types\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport type { Classifier, ClassifierContext } from \"./classifier.interface\";\nimport { TransferClassifier } from \"../classifiers/transfer-classifier\";\nimport { SwapClassifier } from \"../classifiers/swap-classifier\";\nimport { AirdropClassifier } from \"../classifiers/airdrop-classifier\";\nimport { FeeOnlyClassifier } from \"../classifiers/fee-only-classifier\";\nimport { SolanaPayClassifier } from \"../classifiers/solana-pay-classifier\";\nimport { NftMintClassifier } from \"../classifiers/nft-mint-classifier\";\nimport { StakeDepositClassifier } from \"../classifiers/stake-deposit-classifier\";\nimport { StakeWithdrawClassifier } from \"../classifiers/stake-withdraw-classifier\";\nimport { BridgeClassifier } from \"../classifiers/bridge-classifier\";\n\nexport class ClassificationService {\n private classifiers: Classifier[] = [];\n\n constructor() {\n this.registerClassifier(new SolanaPayClassifier());\n this.registerClassifier(new BridgeClassifier());\n this.registerClassifier(new NftMintClassifier());\n this.registerClassifier(new StakeDepositClassifier());\n this.registerClassifier(new StakeWithdrawClassifier());\n this.registerClassifier(new SwapClassifier());\n this.registerClassifier(new AirdropClassifier());\n this.registerClassifier(new TransferClassifier());\n this.registerClassifier(new FeeOnlyClassifier());\n }\n\n registerClassifier(classifier: Classifier): void {\n this.classifiers.push(classifier);\n this.classifiers.sort((a, b) => b.priority - a.priority);\n }\n\n classify(legs: TxLeg[], tx: RawTransaction, walletAddress?: string): TransactionClassification {\n const context: ClassifierContext = { legs, tx, walletAddress };\n\n for (const classifier of this.classifiers) {\n const result = classifier.classify(context);\n if (result && result.isRelevant) {\n return result;\n }\n }\n\n return {\n primaryType: \"other\",\n primaryAmount: null,\n secondaryAmount: null,\n sender: null,\n receiver: null,\n counterparty: null,\n confidence: 0.0,\n isRelevant: false,\n metadata: {},\n };\n }\n}\n\nexport const classificationService = new ClassificationService();\n\n/**\n * Classifies a transaction based on its accounting legs and context.\n *\n * Uses a priority-ordered chain of classifiers (Solana Pay > Bridge > NFT Mint > Stake Deposit > Stake Withdraw > Swap > Airdrop > Transfer > Fee-only)\n * to determine the transaction type, direction, amounts, sender, and receiver.\n *\n * @param legs - Transaction legs representing all balance movements\n * @param tx - Raw transaction data for additional context (protocol, memo, etc.)\n * @param walletAddress - Optional wallet address for perspective-aware classification (e.g., swap direction)\n * @returns Classification result with type, amounts, sender, receiver, and confidence\n */\nexport function classifyTransaction(\n legs: TxLeg[],\n tx: RawTransaction,\n walletAddress?: string\n): TransactionClassification {\n return classificationService.classify(legs, tx, walletAddress);\n}\n","import type { TransactionClassification } from \"./classification.types\";\nimport type { RawTransaction } from \"./tx.types\";\n\nexport interface SpamFilterConfig {\n minSolAmount?: number;\n minTokenAmountUsd?: number;\n minConfidence?: number;\n allowFailed?: boolean;\n}\n\nconst DEFAULT_CONFIG: Required<SpamFilterConfig> = {\n minSolAmount: 0.001,\n minTokenAmountUsd: 0.01,\n minConfidence: 0.5,\n allowFailed: false,\n};\n\n/**\n * Determines if a transaction should be filtered as spam or dust.\n * \n * A transaction is considered spam if it:\n * - Failed (and allowFailed is false)\n * - Has low classification confidence\n * - Is not relevant to the wallet\n * - Involves dust amounts below configured thresholds\n * \n * @param tx - Raw transaction data\n * @param classification - Transaction classification result\n * @param config - Optional spam filter configuration (uses defaults if omitted)\n * @returns True if the transaction should be filtered as spam\n */\nexport function isSpamTransaction(\n tx: RawTransaction,\n classification: TransactionClassification,\n config: SpamFilterConfig = {}\n): boolean {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.allowFailed && tx.err) {\n return true;\n }\n\n if (classification.confidence < cfg.minConfidence) {\n return true;\n }\n\n if (!classification.isRelevant) {\n return true;\n }\n\n if (isDustTransaction(classification, cfg)) {\n return true;\n }\n\n return false;\n}\n\nfunction isDustTransaction(\n classification: TransactionClassification,\n config: Required<SpamFilterConfig>\n): boolean {\n const { primaryAmount } = classification;\n \n if (!primaryAmount) {\n return false;\n }\n\n const { token, amountUi } = primaryAmount;\n\n if (token.symbol === \"SOL\") {\n return Math.abs(amountUi) < config.minSolAmount;\n }\n\n if (token.symbol === \"USDC\") {\n return Math.abs(amountUi) < config.minTokenAmountUsd;\n }\n\n return Math.abs(amountUi) < config.minTokenAmountUsd;\n}\n\n/**\n * Filters an array of transactions to remove spam and dust transactions.\n * \n * Applies spam detection criteria to each transaction while preserving\n * additional properties in the returned array items.\n * \n * @param transactions - Array of transaction objects with tx and classification\n * @param config - Optional spam filter configuration\n * @returns Filtered array with spam transactions removed\n */\nexport function filterSpamTransactions<T extends {\n tx: RawTransaction;\n classification: TransactionClassification;\n}>(\n transactions: T[],\n config?: SpamFilterConfig\n): T[] {\n return transactions.filter(\n ({ tx, classification }) => !isSpamTransaction(tx, classification, config)\n );\n}\n\n","export interface NftMetadata {\n mint: string;\n name: string;\n symbol: string;\n image: string;\n cdnImage?: string;\n description?: string;\n collection?: string;\n attributes?: Array<{ trait_type: string; value: string }>;\n}\n\ninterface DasAssetResponse {\n jsonrpc: string;\n result?: {\n id: string;\n content: {\n metadata: {\n name: string;\n symbol: string;\n description?: string;\n attributes?: Array<{ trait_type: string; value: string }>;\n };\n links: {\n image?: string;\n };\n files?: Array<{\n uri: string;\n cdn_uri?: string;\n mime: string;\n }>;\n };\n grouping?: Array<{\n group_key: string;\n group_value: string;\n }>;\n };\n error?: {\n code: number;\n message: string;\n };\n}\n\n/**\n * Fetches NFT metadata from Helius DAS API.\n *\n * @param rpcUrl - Helius RPC endpoint URL\n * @param mintAddress - NFT mint address\n * @returns NFT metadata including name, image, collection, and attributes, or null if not found\n */\nexport async function fetchNftMetadata(\n rpcUrl: string,\n mintAddress: string\n): Promise<NftMetadata | null> {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: \"get-asset\",\n method: \"getAsset\",\n params: { id: mintAddress },\n }),\n });\n\n const data = (await response.json()) as DasAssetResponse;\n\n if (data.error || !data.result?.content?.metadata) {\n return null;\n }\n\n const { result } = data;\n const { content, grouping } = result;\n\n return {\n mint: mintAddress,\n name: content.metadata.name,\n symbol: content.metadata.symbol,\n image: content.links.image ?? content.files?.[0]?.uri ?? \"\",\n cdnImage: content.files?.[0]?.cdn_uri,\n description: content.metadata.description,\n collection: grouping?.find((g) => g.group_key === \"collection\")?.group_value,\n attributes: content.metadata.attributes,\n };\n}\n\n/**\n * Fetches NFT metadata for multiple mints in parallel.\n *\n * @param rpcUrl - Helius RPC endpoint URL\n * @param mintAddresses - Array of NFT mint addresses\n * @returns Map of mint address to NFT metadata (only includes successful fetches)\n */\nexport async function fetchNftMetadataBatch(\n rpcUrl: string,\n mintAddresses: string[]\n): Promise<Map<string, NftMetadata>> {\n const results = await Promise.all(\n mintAddresses.map((mint) => fetchNftMetadata(rpcUrl, mint))\n );\n\n const map = new Map<string, NftMetadata>();\n results.forEach((metadata, index) => {\n if (metadata) {\n map.set(mintAddresses[index]!, metadata);\n }\n });\n\n return map;\n}\n","import type { Address, Signature } from \"@solana/kit\";\nimport {\n createSolanaClient,\n parseSignature,\n type SolanaClient,\n} from \"@tx-indexer/solana/rpc/client\";\nimport { fetchWalletBalance } from \"@tx-indexer/solana/fetcher/balances\";\nimport {\n fetchWalletSignatures,\n fetchTransaction,\n fetchTransactionsBatch,\n} from \"@tx-indexer/solana/fetcher/transactions\";\n\nexport type { FetchTransactionsConfig } from \"@tx-indexer/solana/fetcher/transactions\";\nimport { transactionToLegs } from \"@tx-indexer/solana/mappers/transaction-to-legs\";\nimport { classifyTransaction } from \"@tx-indexer/classification/engine/classification-service\";\nimport { detectProtocol } from \"@tx-indexer/classification/protocols/detector\";\nimport { filterSpamTransactions, type SpamFilterConfig } from \"@tx-indexer/core/tx/spam-filter\";\nimport type { WalletBalance } from \"@tx-indexer/solana/fetcher/balances\";\nimport type { RawTransaction } from \"@tx-indexer/core/tx/tx.types\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { fetchNftMetadata, fetchNftMetadataBatch, type NftMetadata } from \"./nft\";\n\nconst NFT_TRANSACTION_TYPES = [\"nft_mint\", \"nft_purchase\", \"nft_sale\"] as const;\n\nasync function enrichNftClassification(\n rpcUrl: string,\n classified: ClassifiedTransaction\n): Promise<ClassifiedTransaction> {\n const { classification } = classified;\n\n if (!NFT_TRANSACTION_TYPES.includes(classification.primaryType as any)) {\n return classified;\n }\n\n const nftMint = classification.metadata?.nft_mint as string | undefined;\n if (!nftMint) {\n return classified;\n }\n\n const nftData = await fetchNftMetadata(rpcUrl, nftMint);\n if (!nftData) {\n return classified;\n }\n\n return {\n ...classified,\n classification: {\n ...classification,\n metadata: {\n ...classification.metadata,\n nft_name: nftData.name,\n nft_image: nftData.image,\n nft_cdn_image: nftData.cdnImage,\n nft_collection: nftData.collection,\n nft_symbol: nftData.symbol,\n nft_attributes: nftData.attributes,\n },\n },\n };\n}\n\nexport type TxIndexerOptions =\n | { \n rpcUrl: string; \n wsUrl?: string;\n }\n | { \n client: SolanaClient;\n };\n\nexport interface GetTransactionsOptions {\n limit?: number;\n before?: Signature;\n until?: Signature;\n filterSpam?: boolean;\n spamConfig?: SpamFilterConfig;\n enrichNftMetadata?: boolean;\n}\n\nexport interface GetTransactionOptions {\n enrichNftMetadata?: boolean;\n}\n\nexport interface ClassifiedTransaction {\n tx: RawTransaction;\n classification: TransactionClassification;\n legs: ReturnType<typeof transactionToLegs>;\n}\n\nexport interface TxIndexer {\n rpc: ReturnType<typeof createSolanaClient>[\"rpc\"];\n \n getBalance(\n walletAddress: Address,\n tokenMints?: readonly string[]\n ): Promise<WalletBalance>;\n \n getTransactions(\n walletAddress: Address,\n options?: GetTransactionsOptions\n ): Promise<ClassifiedTransaction[]>;\n \n getTransaction(signature: Signature, options?: GetTransactionOptions): Promise<ClassifiedTransaction | null>;\n \n getRawTransaction(signature: Signature): Promise<RawTransaction | null>;\n\n getNftMetadata(mintAddress: string): Promise<NftMetadata | null>;\n\n getNftMetadataBatch(mintAddresses: string[]): Promise<Map<string, NftMetadata>>;\n}\n\nexport function createIndexer(options: TxIndexerOptions): TxIndexer {\n const rpcUrl = \"client\" in options ? \"\" : options.rpcUrl;\n const client = \"client\" in options\n ? options.client\n : createSolanaClient(options.rpcUrl, options.wsUrl);\n\n return {\n rpc: client.rpc,\n\n async getBalance(\n walletAddress: Address,\n tokenMints?: readonly string[]\n ): Promise<WalletBalance> {\n return fetchWalletBalance(client.rpc, walletAddress, tokenMints);\n },\n\n async getTransactions(\n walletAddress: Address,\n options: GetTransactionsOptions = {}\n ): Promise<ClassifiedTransaction[]> {\n const { limit = 10, before, until, filterSpam = true, spamConfig, enrichNftMetadata = true } = options;\n\n async function enrichBatch(transactions: ClassifiedTransaction[]): Promise<ClassifiedTransaction[]> {\n if (!enrichNftMetadata || !rpcUrl) {\n return transactions;\n }\n\n const nftMints = transactions\n .filter((t) => NFT_TRANSACTION_TYPES.includes(t.classification.primaryType as any))\n .map((t) => t.classification.metadata?.nft_mint as string)\n .filter(Boolean);\n\n if (nftMints.length === 0) {\n return transactions;\n }\n\n const nftMetadataMap = await fetchNftMetadataBatch(rpcUrl, nftMints);\n\n return transactions.map((t) => {\n const nftMint = t.classification.metadata?.nft_mint as string | undefined;\n if (!nftMint || !nftMetadataMap.has(nftMint)) {\n return t;\n }\n\n const nftData = nftMetadataMap.get(nftMint)!;\n return {\n ...t,\n classification: {\n ...t.classification,\n metadata: {\n ...t.classification.metadata,\n nft_name: nftData.name,\n nft_image: nftData.image,\n nft_cdn_image: nftData.cdnImage,\n nft_collection: nftData.collection,\n nft_symbol: nftData.symbol,\n nft_attributes: nftData.attributes,\n },\n },\n };\n });\n }\n\n if (!filterSpam) {\n const signatures = await fetchWalletSignatures(client.rpc, walletAddress, {\n limit,\n before,\n until,\n });\n\n if (signatures.length === 0) {\n return [];\n }\n\n const signatureObjects = signatures.map((sig) =>\n parseSignature(sig.signature)\n );\n const transactions = await fetchTransactionsBatch(\n client.rpc,\n signatureObjects\n );\n\n const walletAddressStr = walletAddress.toString();\n const classified = transactions.map((tx) => {\n tx.protocol = detectProtocol(tx.programIds);\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(legs, tx, walletAddressStr);\n return { tx, classification, legs };\n });\n\n return enrichBatch(classified);\n }\n\n const accumulated: ClassifiedTransaction[] = [];\n let currentBefore = before;\n const MAX_ITERATIONS = 10;\n let iteration = 0;\n const walletAddressStr = walletAddress.toString();\n\n while (accumulated.length < limit && iteration < MAX_ITERATIONS) {\n iteration++;\n\n const batchSize = iteration === 1 ? limit : limit * 2;\n\n const signatures = await fetchWalletSignatures(client.rpc, walletAddress, {\n limit: batchSize,\n before: currentBefore,\n until,\n });\n\n if (signatures.length === 0) {\n break;\n }\n\n const signatureObjects = signatures.map((sig) =>\n parseSignature(sig.signature)\n );\n const transactions = await fetchTransactionsBatch(\n client.rpc,\n signatureObjects\n );\n\n const classified = transactions.map((tx) => {\n tx.protocol = detectProtocol(tx.programIds);\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(legs, tx, walletAddressStr);\n return { tx, classification, legs };\n });\n\n const nonSpam = filterSpamTransactions(classified, spamConfig);\n accumulated.push(...nonSpam);\n\n const lastSignature = signatures[signatures.length - 1];\n if (lastSignature) {\n currentBefore = parseSignature(lastSignature.signature);\n } else {\n break;\n }\n }\n\n const result = accumulated.slice(0, limit);\n return enrichBatch(result);\n },\n\n async getTransaction(\n signature: Signature,\n options: GetTransactionOptions = {}\n ): Promise<ClassifiedTransaction | null> {\n const { enrichNftMetadata = true } = options;\n\n const tx = await fetchTransaction(client.rpc, signature);\n\n if (!tx) {\n return null;\n }\n\n tx.protocol = detectProtocol(tx.programIds);\n\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(legs, tx);\n\n let classified: ClassifiedTransaction = { tx, classification, legs };\n\n if (enrichNftMetadata && rpcUrl) {\n classified = await enrichNftClassification(rpcUrl, classified);\n }\n\n return classified;\n },\n\n async getRawTransaction(signature: Signature): Promise<RawTransaction | null> {\n return fetchTransaction(client.rpc, signature);\n },\n\n async getNftMetadata(mintAddress: string): Promise<NftMetadata | null> {\n if (!rpcUrl) {\n throw new Error(\"getNftMetadata requires rpcUrl to be set\");\n }\n return fetchNftMetadata(rpcUrl, mintAddress);\n },\n\n async getNftMetadataBatch(mintAddresses: string[]): Promise<Map<string, NftMetadata>> {\n if (!rpcUrl) {\n throw new Error(\"getNftMetadataBatch requires rpcUrl to be set\");\n }\n return fetchNftMetadataBatch(rpcUrl, mintAddresses);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../solana/src/rpc/client.ts","../../domain/src/money/token-registry.ts","../../solana/src/constants/program-ids.ts","../../solana/src/fetcher/balances.ts","../../solana/src/mappers/transaction-mapper.ts","../../../node_modules/.bun/base-x@5.0.1/node_modules/base-x/src/esm/index.js","../../../node_modules/.bun/bs58@6.0.0/node_modules/bs58/src/esm/index.js","../../solana/src/mappers/memo-parser.ts","../../solana/src/rpc/retry.ts","../../../node_modules/.bun/yocto-queue@1.2.2/node_modules/yocto-queue/index.js","../../../node_modules/.bun/p-limit@6.2.0/node_modules/p-limit/index.js","../../solana/src/fetcher/transactions.ts","../../domain/src/tx/account-id.ts","../../solana/src/mappers/balance-parser.ts","../../solana/src/constants/protocol-constants.ts","../../solana/src/mappers/transaction-to-legs.ts","../../classification/src/classifiers/transfer-classifier.ts","../../classification/src/protocols/detector.ts","../../classification/src/classifiers/swap-classifier.ts","../../classification/src/classifiers/airdrop-classifier.ts","../../classification/src/classifiers/fee-only-classifier.ts","../../classification/src/classifiers/solana-pay-classifier.ts","../../classification/src/classifiers/nft-mint-classifier.ts","../../classification/src/classifiers/stake-deposit-classifier.ts","../../classification/src/classifiers/stake-withdraw-classifier.ts","../../classification/src/classifiers/bridge-classifier.ts","../../classification/src/engine/classification-service.ts","../../domain/src/tx/spam-filter.ts","../../domain/src/money/token-fetcher.ts","../src/nft.ts","../src/client.ts"],"names":["address","ALPHABET","esm_default","signature","DEX_PROTOCOL_IDS","DEFAULT_CONFIG","options","result","walletAddressStr"],"mappings":"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","file":"client.js","sourcesContent":["import {\n createSolanaRpc,\n createSolanaRpcSubscriptions,\n type Rpc,\n type RpcSubscriptions,\n type GetBalanceApi,\n type GetTokenAccountsByOwnerApi,\n type GetSignaturesForAddressApi,\n type GetTransactionApi,\n address,\n type Address,\n signature,\n type Signature,\n} from \"@solana/kit\";\n\n/**\n * Union type of all RPC APIs used by the transaction indexer.\n * \n * This ensures type safety when calling RPC methods while maintaining\n * flexibility for the complete indexer API surface.\n */\nexport type IndexerRpcApi = GetBalanceApi \n & GetTokenAccountsByOwnerApi \n & GetSignaturesForAddressApi \n & GetTransactionApi;\n\nexport interface SolanaClient {\n rpc: Rpc<IndexerRpcApi>;\n rpcSubscriptions: RpcSubscriptions<any>;\n}\n\n/**\n * Creates a Solana RPC client with both regular RPC and WebSocket subscriptions.\n * \n * @param rpcUrl - HTTP RPC endpoint URL\n * @param wsUrl - Optional WebSocket URL (defaults to rpcUrl with wss:// protocol)\n */\nexport function createSolanaClient(\n rpcUrl: string,\n wsUrl?: string\n): SolanaClient {\n const rpc = createSolanaRpc(rpcUrl);\n const rpcSubscriptions = wsUrl\n ? createSolanaRpcSubscriptions(wsUrl)\n : createSolanaRpcSubscriptions(rpcUrl.replace(\"https://\", \"wss://\"));\n\n return { rpc, rpcSubscriptions };\n}\n\n/**\n * Parses and validates a Solana address string.\n * \n * @param addr - Base58-encoded Solana address\n */\nexport function parseAddress(addr: string): Address {\n return address(addr);\n}\n\n/**\n * Parses and validates a Solana transaction signature string.\n * \n * @param sig - Base58-encoded transaction signature\n */\nexport function parseSignature(sig: string): Signature {\n return signature(sig);\n}\n\n","import type { TokenInfo } from \"./money.types\";\n\n/**\n * Well-known token mint addresses on Solana mainnet.\n * These are used as constants throughout the codebase.\n */\nexport const KNOWN_TOKENS = {\n // Native\n SOL: \"So11111111111111111111111111111111111111112\",\n\n // Stablecoins\n USDC: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n USDT: \"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\",\n PYUSD: \"2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo\",\n USDG: \"2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH\",\n USDC_BRIDGED: \"A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM\",\n DAI: \"EjmyN6qEC1Tf1JxiG1ae7UTJhUxSwk1TCCi3Z4dPuFhh\",\n\n // Major tokens\n JUP: \"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN\",\n JTO: \"jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL\",\n PYTH: \"HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3\",\n BONK: \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n WIF: \"EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm\",\n RENDER: \"rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof\",\n HNT: \"hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux\",\n RAY: \"4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R\",\n ORCA: \"orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE\",\n MNGO: \"MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac\",\n MSOL: \"mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So\",\n JITOSOL: \"J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn\",\n BSOL: \"bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1\",\n\n // Memecoins\n POPCAT: \"7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr\",\n MEW: \"MEW1gQWJ3nEXg2qgERiKu7FAFj79PHvQVREQUzScPP5\",\n PNUT: \"2qEHjDLDLbuBgRYvsxhc5D6uDWAivNFZGan56P1tpump\",\n FARTCOIN: \"9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump\",\n AI16Z: \"HeLp6NuQkmYB4pYWo2zYs22mESHXPQYzXbB8n4V98jwC\",\n\n // Wrapped tokens\n WBTC: \"3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh\",\n WETH: \"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs\",\n WSOL: \"So11111111111111111111111111111111111111112\", // Same as SOL (wrapped)\n} as const;\n\n/**\n * Static token metadata registry.\n * This serves as a fallback when external APIs (like Jupiter) are unavailable.\n *\n * Logo URLs are from:\n * - Solana Labs token list (legacy but still hosted)\n * - Jupiter token list CDN\n */\nexport const TOKEN_INFO: Record<string, TokenInfo> = {\n // Native SOL\n [KNOWN_TOKENS.SOL]: {\n mint: KNOWN_TOKENS.SOL,\n symbol: \"SOL\",\n name: \"Solana\",\n decimals: 9,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png\",\n },\n\n // Stablecoins\n [KNOWN_TOKENS.USDC]: {\n mint: KNOWN_TOKENS.USDC,\n symbol: \"USDC\",\n name: \"USD Coin\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png\",\n },\n [KNOWN_TOKENS.USDT]: {\n mint: KNOWN_TOKENS.USDT,\n symbol: \"USDT\",\n name: \"Tether USD\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg\",\n },\n [KNOWN_TOKENS.PYUSD]: {\n mint: KNOWN_TOKENS.PYUSD,\n symbol: \"PYUSD\",\n name: \"PayPal USD\",\n decimals: 6,\n logoURI:\n \"https://img.fotofolio.xyz/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolana-labs%2Ftoken-list%2Fmain%2Fassets%2Fmainnet%2F2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo%2Flogo.png\",\n },\n [KNOWN_TOKENS.USDG]: {\n mint: KNOWN_TOKENS.USDG,\n symbol: \"USDG\",\n name: \"USD Glitter\",\n decimals: 6,\n },\n [KNOWN_TOKENS.USDC_BRIDGED]: {\n mint: KNOWN_TOKENS.USDC_BRIDGED,\n symbol: \"USDCet\",\n name: \"USDC (Wormhole)\",\n decimals: 6,\n },\n [KNOWN_TOKENS.DAI]: {\n mint: KNOWN_TOKENS.DAI,\n symbol: \"DAI\",\n name: \"DAI (Wormhole)\",\n decimals: 8,\n },\n\n // Major tokens\n [KNOWN_TOKENS.JUP]: {\n mint: KNOWN_TOKENS.JUP,\n symbol: \"JUP\",\n name: \"Jupiter\",\n decimals: 6,\n logoURI: \"https://static.jup.ag/jup/icon.png\",\n },\n [KNOWN_TOKENS.JTO]: {\n mint: KNOWN_TOKENS.JTO,\n symbol: \"JTO\",\n name: \"Jito\",\n decimals: 9,\n logoURI: \"https://metadata.jito.network/token/jto/image\",\n },\n [KNOWN_TOKENS.PYTH]: {\n mint: KNOWN_TOKENS.PYTH,\n symbol: \"PYTH\",\n name: \"Pyth Network\",\n decimals: 6,\n logoURI: \"https://pyth.network/token.svg\",\n },\n [KNOWN_TOKENS.BONK]: {\n mint: KNOWN_TOKENS.BONK,\n symbol: \"BONK\",\n name: \"Bonk\",\n decimals: 5,\n logoURI: \"https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I\",\n },\n [KNOWN_TOKENS.WIF]: {\n mint: KNOWN_TOKENS.WIF,\n symbol: \"WIF\",\n name: \"dogwifhat\",\n decimals: 6,\n logoURI:\n \"https://bafkreibk3covs5ltyqxa272uodhber6kcclnlgrbwjee4kyqhstwmjqpfa.ipfs.nftstorage.link/\",\n },\n [KNOWN_TOKENS.RENDER]: {\n mint: KNOWN_TOKENS.RENDER,\n symbol: \"RENDER\",\n name: \"Render Token\",\n decimals: 8,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof/logo.png\",\n },\n [KNOWN_TOKENS.HNT]: {\n mint: KNOWN_TOKENS.HNT,\n symbol: \"HNT\",\n name: \"Helium\",\n decimals: 8,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux/logo.png\",\n },\n [KNOWN_TOKENS.RAY]: {\n mint: KNOWN_TOKENS.RAY,\n symbol: \"RAY\",\n name: \"Raydium\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R/logo.png\",\n },\n [KNOWN_TOKENS.ORCA]: {\n mint: KNOWN_TOKENS.ORCA,\n symbol: \"ORCA\",\n name: \"Orca\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE/logo.png\",\n },\n [KNOWN_TOKENS.MNGO]: {\n mint: KNOWN_TOKENS.MNGO,\n symbol: \"MNGO\",\n name: \"Mango\",\n decimals: 6,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac/logo.png\",\n },\n\n // Liquid staking tokens\n [KNOWN_TOKENS.MSOL]: {\n mint: KNOWN_TOKENS.MSOL,\n symbol: \"mSOL\",\n name: \"Marinade Staked SOL\",\n decimals: 9,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So/logo.png\",\n },\n [KNOWN_TOKENS.JITOSOL]: {\n mint: KNOWN_TOKENS.JITOSOL,\n symbol: \"JitoSOL\",\n name: \"Jito Staked SOL\",\n decimals: 9,\n logoURI: \"https://storage.googleapis.com/token-metadata/JitoSOL-256.png\",\n },\n [KNOWN_TOKENS.BSOL]: {\n mint: KNOWN_TOKENS.BSOL,\n symbol: \"bSOL\",\n name: \"BlazeStake Staked SOL\",\n decimals: 9,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1/logo.png\",\n },\n\n // Memecoins\n [KNOWN_TOKENS.POPCAT]: {\n mint: KNOWN_TOKENS.POPCAT,\n symbol: \"POPCAT\",\n name: \"Popcat\",\n decimals: 9,\n logoURI:\n \"https://bafkreidvkvuzyslw5jh5z242lgzwzhbi2kxxnpkm73fkuqzasyr34jj2o4.ipfs.nftstorage.link/\",\n },\n [KNOWN_TOKENS.MEW]: {\n mint: KNOWN_TOKENS.MEW,\n symbol: \"MEW\",\n name: \"cat in a dogs world\",\n decimals: 5,\n logoURI:\n \"https://bafkreidlwyr565dxtao2ipsze6bmzpszqzybz7sqi2zaet5fs7k53henju.ipfs.nftstorage.link/\",\n },\n [KNOWN_TOKENS.PNUT]: {\n mint: KNOWN_TOKENS.PNUT,\n symbol: \"Peanut\",\n name: \"Peanut the Squirrel\",\n decimals: 6,\n logoURI:\n \"https://ipfs.io/ipfs/QmNS3Hdb6pMheFzRdwXr3PPCrXcBohzhLrKHqEUV1n3HnJ\",\n },\n [KNOWN_TOKENS.FARTCOIN]: {\n mint: KNOWN_TOKENS.FARTCOIN,\n symbol: \"FARTCOIN\",\n name: \"Fartcoin\",\n decimals: 6,\n logoURI:\n \"https://ipfs.io/ipfs/QmQHY6t8TxucH3F9LGPBBqqRLbyWx7NxWvrnoZKcq9ErrR\",\n },\n [KNOWN_TOKENS.AI16Z]: {\n mint: KNOWN_TOKENS.AI16Z,\n symbol: \"ai16z\",\n name: \"ai16z\",\n decimals: 9,\n logoURI:\n \"https://ipfs.io/ipfs/QmRbm1mprqHmJ7PvCTrSNydkquLi5r41wq8kWbHvoRm3FX\",\n },\n\n // Wrapped tokens\n [KNOWN_TOKENS.WBTC]: {\n mint: KNOWN_TOKENS.WBTC,\n symbol: \"WBTC\",\n name: \"Wrapped BTC (Wormhole)\",\n decimals: 8,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh/logo.png\",\n },\n [KNOWN_TOKENS.WETH]: {\n mint: KNOWN_TOKENS.WETH,\n symbol: \"WETH\",\n name: \"Wrapped ETH (Wormhole)\",\n decimals: 8,\n logoURI:\n \"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs/logo.png\",\n },\n};\n\nexport function getTokenInfo(mint: string): TokenInfo | undefined {\n return TOKEN_INFO[mint];\n}\n\nexport function isSupportedToken(mint: string): boolean {\n return mint in TOKEN_INFO;\n}\n\n/**\n * Creates an \"unknown token\" placeholder for tokens not in the registry.\n * Uses the first 8 characters of the mint address as a symbol.\n */\nexport function createUnknownToken(mint: string, decimals: number): TokenInfo {\n return {\n mint,\n symbol: mint.slice(0, 8),\n name: `Unknown Token (${mint.slice(0, 8)}...)`,\n decimals,\n };\n}\n\nexport const SUPPORTED_STABLECOINS = [\n KNOWN_TOKENS.USDC,\n KNOWN_TOKENS.USDT,\n KNOWN_TOKENS.PYUSD,\n KNOWN_TOKENS.USDG,\n KNOWN_TOKENS.USDC_BRIDGED,\n KNOWN_TOKENS.DAI,\n] as const;\n\nexport const TRACKED_TOKENS = [\n KNOWN_TOKENS.SOL,\n KNOWN_TOKENS.USDC,\n KNOWN_TOKENS.USDT,\n] as const;\n\n/**\n * Liquid staking tokens that represent staked SOL\n */\nexport const LIQUID_STAKING_TOKENS = [\n KNOWN_TOKENS.MSOL,\n KNOWN_TOKENS.JITOSOL,\n KNOWN_TOKENS.BSOL,\n] as const;\n","/**\n * Solana Program IDs\n *\n * Centralized registry of known Solana program addresses.\n * These are public keys that identify on-chain programs.\n */\n\n// ============================================\n// Core Solana Programs\n// ============================================\n\nexport const SYSTEM_PROGRAM_ID = \"11111111111111111111111111111111\";\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\nexport const STAKE_PROGRAM_ID = \"Stake11111111111111111111111111111111111111\";\nexport const STAKE_POOL_PROGRAM_ID =\n \"SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy\";\n\n// ============================================\n// Token Programs\n// ============================================\n\nexport const TOKEN_PROGRAM_ID = \"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\";\nexport const TOKEN_2022_PROGRAM_ID =\n \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\";\nexport const ASSOCIATED_TOKEN_PROGRAM_ID =\n \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\";\n\n// ============================================\n// Memo Programs\n// ============================================\n\nexport const SPL_MEMO_PROGRAM_ID =\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\";\nexport const MEMO_V1_PROGRAM_ID = \"Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo\";\n\n// ============================================\n// DeFi Programs\n// ============================================\n\n// Jupiter\nexport const JUPITER_V6_PROGRAM_ID =\n \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nexport const JUPITER_V4_PROGRAM_ID =\n \"JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB\";\nexport const JUPITER_ORDER_ENGINE_PROGRAM_ID =\n \"61DFfeTKM7trxYcPQCM78bJ794ddZprZpAwAnLiwTpYH\";\n\n// Raydium\nexport const RAYDIUM_PROGRAM_ID =\n \"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8\";\nexport const RAYDIUM_CLMM_PROGRAM_ID =\n \"CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK\";\nexport const RAYDIUM_CPMM_PROGRAM_ID =\n \"CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C\";\nexport const RAYDIUM_STABLE_PROGRAM_ID =\n \"5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h\";\n\n// Orca\nexport const ORCA_WHIRLPOOL_PROGRAM_ID =\n \"whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc\";\nexport const ORCA_TOKEN_SWAP_V1_PROGRAM_ID =\n \"9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP\";\n\n// CLOBs (Central Limit Order Books)\nexport const OPENBOOK_V2_PROGRAM_ID =\n \"opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb\";\nexport const PHOENIX_PROGRAM_ID = \"PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY\";\n\n// Stableswap\nexport const SABER_STABLE_SWAP_PROGRAM_ID =\n \"SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ\";\nexport const MERCURIAL_STABLE_SWAP_PROGRAM_ID =\n \"MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky\";\n\n// Meteora\nexport const METEORA_DLMM_PROGRAM_ID =\n \"LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo\";\nexport const METEORA_POOLS_PROGRAM_ID =\n \"Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB\";\n\n// Pump.fun\nexport const PUMPFUN_AMM_PROGRAM_ID =\n \"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA\";\nexport const PUMPFUN_BONDING_CURVE_PROGRAM_ID =\n \"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P\";\n\n// Lifinity\nexport const LIFINITY_V2_PROGRAM_ID =\n \"2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c\";\n\n// ============================================\n// NFT Programs\n// ============================================\n\nexport const METAPLEX_PROGRAM_ID =\n \"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s\";\nexport const CANDY_MACHINE_V3_PROGRAM_ID =\n \"CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR\";\nexport const CANDY_GUARD_PROGRAM_ID =\n \"Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g\";\nexport const BUBBLEGUM_PROGRAM_ID =\n \"BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY\";\nexport const MAGIC_EDEN_CANDY_MACHINE_ID =\n \"CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb\";\n\n// ============================================\n// Bridge Programs\n// ============================================\n\nexport const WORMHOLE_PROGRAM_ID =\n \"worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth\";\nexport const WORMHOLE_TOKEN_BRIDGE_ID =\n \"wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb\";\nexport const DEGODS_BRIDGE_PROGRAM_ID =\n \"35iLrpYNNR9ygHLcvE1xKFHbHq6paHthrF6wSovdWgGu\";\nexport const DEBRIDGE_PROGRAM_ID =\n \"DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh\";\nexport const ALLBRIDGE_PROGRAM_ID =\n \"BrdgN2RPzEMWF96ZbnnJaUtQDQx7VRXYaHHbYCBvceWB\";\n\n// ============================================\n// Payment Facilitators\n// ============================================\n\nexport const PAYAI_FACILITATOR = \"2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4\";\n\n// ============================================\n// Helper Collections\n// ============================================\n\nexport const MEMO_PROGRAM_IDS = [\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n] as const;\n\nexport const TOKEN_PROGRAM_IDS = [\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n] as const;\n\nexport const DEX_PROGRAM_IDS = [\n JUPITER_V6_PROGRAM_ID,\n JUPITER_V4_PROGRAM_ID,\n JUPITER_ORDER_ENGINE_PROGRAM_ID,\n RAYDIUM_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n RAYDIUM_CPMM_PROGRAM_ID,\n RAYDIUM_STABLE_PROGRAM_ID,\n ORCA_WHIRLPOOL_PROGRAM_ID,\n ORCA_TOKEN_SWAP_V1_PROGRAM_ID,\n OPENBOOK_V2_PROGRAM_ID,\n PHOENIX_PROGRAM_ID,\n SABER_STABLE_SWAP_PROGRAM_ID,\n MERCURIAL_STABLE_SWAP_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n METEORA_POOLS_PROGRAM_ID,\n PUMPFUN_AMM_PROGRAM_ID,\n PUMPFUN_BONDING_CURVE_PROGRAM_ID,\n LIFINITY_V2_PROGRAM_ID,\n] as const;\n\nexport const NFT_PROGRAM_IDS = [\n METAPLEX_PROGRAM_ID,\n CANDY_MACHINE_V3_PROGRAM_ID,\n CANDY_GUARD_PROGRAM_ID,\n BUBBLEGUM_PROGRAM_ID,\n MAGIC_EDEN_CANDY_MACHINE_ID,\n] as const;\n\nexport const BRIDGE_PROGRAM_IDS = [\n WORMHOLE_PROGRAM_ID,\n WORMHOLE_TOKEN_BRIDGE_ID,\n DEGODS_BRIDGE_PROGRAM_ID,\n DEBRIDGE_PROGRAM_ID,\n ALLBRIDGE_PROGRAM_ID,\n] as const;\n\nexport const KNOWN_FACILITATORS = [PAYAI_FACILITATOR] as const;\n\nexport function detectFacilitator(accountKeys: string[]): string | null {\n for (const facilitator of KNOWN_FACILITATORS) {\n if (accountKeys.includes(facilitator)) {\n if (facilitator === PAYAI_FACILITATOR) {\n return \"payai\";\n }\n }\n }\n return null;\n}\n","import {\n type Address,\n type Rpc,\n type GetBalanceApi,\n type GetTokenAccountsByOwnerApi,\n address,\n} from \"@solana/kit\";\n\nimport {\n getTokenInfo,\n KNOWN_TOKENS,\n} from \"@tx-indexer/core/money/token-registry\";\nimport {\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from \"../constants/program-ids\";\n\nexport interface WalletBalance {\n address: string;\n sol: {\n lamports: bigint;\n ui: number;\n };\n tokens: TokenAccountBalance[];\n}\n\nexport interface TokenAccountBalance {\n mint: string;\n tokenAccount?: string;\n amount: {\n raw: string;\n ui: number;\n };\n decimals: number;\n symbol: string;\n}\n\n/**\n * Fetches wallet balance including SOL and SPL tokens\n *\n * @param rpc - Solana RPC client\n * @param walletAddress - Wallet address to query\n * @param tokenMints - Optional array of token mint addresses to track. If omitted, returns all tokens in wallet\n * @returns Wallet balance data with SOL and token balances\n *\n * @example\n * // Fetch all tokens\n * const allBalances = await fetchWalletBalance(rpc, address);\n *\n * @example\n * // Fetch specific tokens only\n * const usdcOnly = await fetchWalletBalance(rpc, address, [\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"]);\n */\nexport async function fetchWalletBalance(\n rpc: Rpc<GetBalanceApi & GetTokenAccountsByOwnerApi>,\n walletAddress: Address,\n tokenMints?: readonly string[],\n): Promise<WalletBalance> {\n const balanceResponse = await rpc.getBalance(walletAddress).send();\n const lamports = balanceResponse.value;\n\n const tokenAccounts = await fetchTokenAccounts(rpc, walletAddress);\n\n const tokens = tokenMints\n ? filterToTrackedTokens(tokenAccounts, tokenMints)\n : Array.from(tokenAccounts.values());\n\n return {\n address: walletAddress,\n sol: {\n lamports,\n ui: Number(lamports) / 1e9,\n },\n tokens,\n };\n}\n\nasync function fetchTokenAccounts(\n rpc: Rpc<GetBalanceApi & GetTokenAccountsByOwnerApi>,\n walletAddress: Address,\n): Promise<Map<string, TokenAccountBalance>> {\n const accountsMap = new Map<string, TokenAccountBalance>();\n\n const tokenPrograms = [TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID];\n\n const responses = await Promise.all(\n tokenPrograms.map((programId) =>\n rpc\n .getTokenAccountsByOwner(\n walletAddress,\n { programId: address(programId) },\n { encoding: \"jsonParsed\" },\n )\n .send()\n .catch(() => ({ value: [] })),\n ),\n );\n\n for (const response of responses) {\n for (const account of response.value) {\n const parsedInfo = account.account.data.parsed.info;\n const mint = parsedInfo.mint;\n\n const tokenInfo = getTokenInfo(mint);\n const symbol = tokenInfo?.symbol || mint.substring(0, 8);\n\n accountsMap.set(mint, {\n mint,\n tokenAccount: account.pubkey.toString(),\n amount: {\n raw: parsedInfo.tokenAmount.amount,\n ui: parsedInfo.tokenAmount.uiAmountString\n ? parseFloat(parsedInfo.tokenAmount.uiAmountString)\n : 0,\n },\n decimals: parsedInfo.tokenAmount.decimals,\n symbol,\n });\n }\n }\n\n return accountsMap;\n}\n\n/**\n * Filters token accounts to only include specified mints, adding zero balances for missing tokens\n *\n * @param fetchedAccounts - Map of mint addresses to token balances from RPC\n * @param tokenMints - Array of token mint addresses to include in results\n */\nfunction filterToTrackedTokens(\n fetchedAccounts: Map<string, TokenAccountBalance>,\n tokenMints: readonly string[],\n): TokenAccountBalance[] {\n const result: TokenAccountBalance[] = [];\n\n for (const mint of tokenMints) {\n if (mint === KNOWN_TOKENS.SOL) continue;\n\n const existing = fetchedAccounts.get(mint);\n if (existing) {\n result.push(existing);\n } else {\n const tokenInfo = getTokenInfo(mint);\n if (tokenInfo) {\n result.push({\n mint,\n amount: {\n raw: \"0\",\n ui: 0,\n },\n decimals: tokenInfo.decimals,\n symbol: tokenInfo.symbol,\n });\n }\n }\n }\n\n return result;\n}\n\nexport function formatBalance(balance: WalletBalance): string[] {\n const lines: string[] = [];\n\n lines.push(`Wallet: ${balance.address}`);\n lines.push(`SOL: ${balance.sol.ui.toFixed(9)}`);\n\n for (const token of balance.tokens) {\n lines.push(`${token.symbol}: ${token.amount.ui.toFixed(token.decimals)}`);\n }\n\n return lines;\n}\n","import type {\n SolanaTransaction,\n InnerInstruction,\n} from \"@tx-indexer/solana/types/transaction.types\";\n\n/**\n * Extracts all unique program IDs from a transaction's top-level instructions.\n */\nexport function extractProgramIds(transaction: SolanaTransaction): string[] {\n const programIds = new Set<string>();\n\n const { message } = transaction;\n const { accountKeys, instructions } = message;\n\n for (const ix of instructions) {\n const { programIdIndex } = ix;\n if (programIdIndex !== undefined && accountKeys[programIdIndex]) {\n const key = accountKeys[programIdIndex];\n programIds.add(key.toString());\n }\n }\n\n return Array.from(programIds);\n}\n\n/**\n * Extracts program IDs from inner instructions (CPI calls).\n */\nexport function extractInnerProgramIds(\n innerInstructions: InnerInstruction[] | undefined,\n allAccountKeys: string[]\n): string[] {\n if (!innerInstructions) return [];\n\n const programIds = new Set<string>();\n\n for (const block of innerInstructions) {\n for (const ix of block.instructions) {\n const key = allAccountKeys[ix.programIdIndex];\n if (key) programIds.add(key);\n }\n }\n\n return Array.from(programIds);\n}\n","// base-x encoding / decoding\n// Copyright (c) 2018 base-x contributors\n// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)\n// Distributed under the MIT software license, see the accompanying\n// file LICENSE or http://www.opensource.org/licenses/mit-license.php.\nfunction base (ALPHABET) {\n if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }\n const BASE_MAP = new Uint8Array(256)\n for (let j = 0; j < BASE_MAP.length; j++) {\n BASE_MAP[j] = 255\n }\n for (let i = 0; i < ALPHABET.length; i++) {\n const x = ALPHABET.charAt(i)\n const xc = x.charCodeAt(0)\n if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }\n BASE_MAP[xc] = i\n }\n const BASE = ALPHABET.length\n const LEADER = ALPHABET.charAt(0)\n const FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up\n const iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up\n function encode (source) {\n // eslint-disable-next-line no-empty\n if (source instanceof Uint8Array) { } else if (ArrayBuffer.isView(source)) {\n source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)\n } else if (Array.isArray(source)) {\n source = Uint8Array.from(source)\n }\n if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }\n if (source.length === 0) { return '' }\n // Skip & count leading zeroes.\n let zeroes = 0\n let length = 0\n let pbegin = 0\n const pend = source.length\n while (pbegin !== pend && source[pbegin] === 0) {\n pbegin++\n zeroes++\n }\n // Allocate enough space in big-endian base58 representation.\n const size = ((pend - pbegin) * iFACTOR + 1) >>> 0\n const b58 = new Uint8Array(size)\n // Process the bytes.\n while (pbegin !== pend) {\n let carry = source[pbegin]\n // Apply \"b58 = b58 * 256 + ch\".\n let i = 0\n for (let it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {\n carry += (256 * b58[it1]) >>> 0\n b58[it1] = (carry % BASE) >>> 0\n carry = (carry / BASE) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n pbegin++\n }\n // Skip leading zeroes in base58 result.\n let it2 = size - length\n while (it2 !== size && b58[it2] === 0) {\n it2++\n }\n // Translate the result into a string.\n let str = LEADER.repeat(zeroes)\n for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }\n return str\n }\n function decodeUnsafe (source) {\n if (typeof source !== 'string') { throw new TypeError('Expected String') }\n if (source.length === 0) { return new Uint8Array() }\n let psz = 0\n // Skip and count leading '1's.\n let zeroes = 0\n let length = 0\n while (source[psz] === LEADER) {\n zeroes++\n psz++\n }\n // Allocate enough space in big-endian base256 representation.\n const size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.\n const b256 = new Uint8Array(size)\n // Process the characters.\n while (psz < source.length) {\n // Find code of next character\n const charCode = source.charCodeAt(psz)\n // Base map can not be indexed using char code\n if (charCode > 255) { return }\n // Decode character\n let carry = BASE_MAP[charCode]\n // Invalid character\n if (carry === 255) { return }\n let i = 0\n for (let it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {\n carry += (BASE * b256[it3]) >>> 0\n b256[it3] = (carry % 256) >>> 0\n carry = (carry / 256) >>> 0\n }\n if (carry !== 0) { throw new Error('Non-zero carry') }\n length = i\n psz++\n }\n // Skip leading zeroes in b256.\n let it4 = size - length\n while (it4 !== size && b256[it4] === 0) {\n it4++\n }\n const vch = new Uint8Array(zeroes + (size - it4))\n let j = zeroes\n while (it4 !== size) {\n vch[j++] = b256[it4++]\n }\n return vch\n }\n function decode (string) {\n const buffer = decodeUnsafe(string)\n if (buffer) { return buffer }\n throw new Error('Non-base' + BASE + ' character')\n }\n return {\n encode,\n decodeUnsafe,\n decode\n }\n}\nexport default base\n","import basex from 'base-x';\nvar ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\nexport default basex(ALPHABET);\n","import type { SolanaTransaction } from \"@tx-indexer/solana/types/transaction.types\";\nimport {\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n} from \"@tx-indexer/solana/constants/program-ids\";\nimport bs58 from \"bs58\";\n\ninterface TransactionWithLogs extends SolanaTransaction {\n meta?: {\n logMessages?: readonly string[] | null;\n };\n}\n\nfunction decodeMemoData(base64Data: string): string {\n const buffer = Buffer.from(base64Data, \"base64\");\n\n const text = buffer.toString(\"utf-8\");\n if (!text.includes(\"\\ufffd\") && /^[\\x20-\\x7E\\s]*$/.test(text)) {\n return text;\n }\n\n if (buffer.length === 32) {\n return bs58.encode(buffer);\n }\n\n if (buffer.length % 32 === 0 && buffer.length > 0) {\n const addresses: string[] = [];\n for (let i = 0; i < buffer.length; i += 32) {\n const chunk = buffer.subarray(i, i + 32);\n addresses.push(bs58.encode(chunk));\n }\n return addresses.join(\", \");\n }\n\n if (buffer.length >= 16) {\n const uuidBytes = buffer.subarray(0, 16);\n const uuid = [\n uuidBytes.subarray(0, 4).toString(\"hex\"),\n uuidBytes.subarray(4, 6).toString(\"hex\"),\n uuidBytes.subarray(6, 8).toString(\"hex\"),\n uuidBytes.subarray(8, 10).toString(\"hex\"),\n uuidBytes.subarray(10, 16).toString(\"hex\"),\n ].join(\"-\");\n\n if (buffer.length === 16) {\n return `Product: ${uuid}`;\n }\n\n const extraData = buffer.subarray(16);\n const extraHex = extraData.toString(\"hex\");\n return `Product: ${uuid} | Meta: ${extraHex}`;\n }\n\n return bs58.encode(buffer);\n}\n\n/**\n * Extracts memo data from a Solana transaction.\n * \n * First attempts to extract human-readable memos from program logs, which contain\n * the decoded text. Falls back to parsing memo program instructions for binary data.\n * Handles various memo formats including UTF-8 text, public keys, and Solana Pay metadata.\n * \n * @param transaction - Solana transaction with message and optional logs\n * @returns Extracted memo string, or null if no memo is found\n */\nexport function extractMemo(transaction: TransactionWithLogs): string | null {\n if (transaction.meta?.logMessages) {\n const memoLogPattern = /Program log: Memo \\(len \\d+\\): \"(.+)\"/;\n for (const log of transaction.meta.logMessages) {\n const match = log.match(memoLogPattern);\n if (match?.[1]) {\n return match[1];\n }\n }\n }\n\n const { message } = transaction;\n const { accountKeys, instructions } = message;\n\n for (const ix of instructions) {\n const programId = accountKeys[ix.programIdIndex]?.toString();\n\n if (programId === SPL_MEMO_PROGRAM_ID || programId === MEMO_V1_PROGRAM_ID) {\n if (ix.data) {\n try {\n return decodeMemoData(ix.data);\n } catch (e) {\n console.warn(\"Failed to decode memo:\", e);\n }\n }\n }\n }\n\n return null;\n}\n\nexport interface SolanaPayMemo {\n merchant?: string;\n item?: string;\n reference?: string;\n label?: string;\n message?: string;\n raw: string;\n}\n\n/**\n * Parses a Solana Pay memo string into structured fields.\n * \n * Attempts to parse the memo as JSON to extract merchant, item, reference,\n * label, and message fields. Falls back to returning just the raw memo if parsing fails.\n * \n * @param memo - Memo string to parse\n * @returns Parsed Solana Pay memo object with raw memo included\n */\nexport function parseSolanaPayMemo(memo: string): SolanaPayMemo {\n try {\n const parsed = JSON.parse(memo);\n return { ...parsed, raw: memo };\n } catch {\n return { raw: memo };\n }\n}\n\n/**\n * Determines if a transaction is a Solana Pay transaction.\n * \n * A transaction is considered Solana Pay if it includes the SPL Memo program\n * and has a non-null memo. Solana Pay uses memos to attach payment metadata.\n * \n * @param programIds - Program IDs involved in the transaction\n * @param memo - Extracted memo from the transaction\n * @returns True if this is a Solana Pay transaction\n */\nexport function isSolanaPayTransaction(\n programIds: string[],\n memo: string | null | undefined\n): boolean {\n const hasMemoProgram =\n programIds.includes(SPL_MEMO_PROGRAM_ID) ||\n programIds.includes(MEMO_V1_PROGRAM_ID);\n\n return hasMemoProgram && memo !== null && memo !== undefined;\n}\n","export interface RetryConfig {\n maxAttempts?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n}\n\nconst DEFAULT_CONFIG: Required<RetryConfig> = {\n maxAttempts: 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n};\n\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return (\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\") ||\n message.includes(\"network\") ||\n message.includes(\"429\") ||\n message.includes(\"rate limit\") ||\n message.includes(\"too many requests\") ||\n message.includes(\"503\") ||\n message.includes(\"502\") ||\n message.includes(\"504\")\n );\n }\n return false;\n}\n\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n const jitter = Math.random() * 0.3 * exponentialDelay;\n return Math.min(exponentialDelay + jitter, maxDelayMs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Executes an async function with retry logic and exponential backoff.\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration\n * @returns Result of the function\n * @throws Last error if all retries fail\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config: RetryConfig = {},\n): Promise<T> {\n const { maxAttempts, baseDelayMs, maxDelayMs } = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n const isLastAttempt = attempt === maxAttempts;\n const shouldRetry = !isLastAttempt && isRetryableError(error);\n\n if (!shouldRetry) {\n throw error;\n }\n\n const delay = calculateDelay(attempt, baseDelayMs, maxDelayMs);\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\n\t\t// Clean up tail reference when queue becomes empty\n\t\tif (!this.#head) {\n\t\t\tthis.#tail = undefined;\n\t\t}\n\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\t* drain() {\n\t\twhile (this.#head) {\n\t\t\tyield this.dequeue();\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","import type {\n Address,\n Rpc,\n Signature,\n GetSignaturesForAddressApi,\n GetTransactionApi,\n} from \"@solana/kit\";\nimport type { RawTransaction } from \"@tx-indexer/core/tx/tx.types\";\nimport { extractProgramIds } from \"@tx-indexer/solana/mappers/transaction-mapper\";\nimport { extractMemo } from \"@tx-indexer/solana/mappers/memo-parser\";\nimport { withRetry, type RetryConfig } from \"@tx-indexer/solana/rpc/retry\";\nimport pLimit from \"p-limit\";\n\nexport interface FetchTransactionsConfig {\n limit?: number;\n before?: Signature;\n until?: Signature;\n}\n\nexport interface FetchTransactionOptions {\n commitment?: \"confirmed\" | \"finalized\";\n retry?: RetryConfig;\n}\n\nexport interface FetchBatchOptions {\n commitment?: \"confirmed\" | \"finalized\";\n concurrency?: number;\n retry?: RetryConfig;\n onFetchError?: (signature: Signature, error: Error) => void;\n}\n\n/**\n * Fetches transaction signatures for a wallet address.\n *\n * @param rpc - Solana RPC client\n * @param walletAddress - Wallet address to fetch signatures for\n * @param config - Optional pagination and limit configuration\n * @returns Array of raw transactions with basic metadata only\n */\nexport async function fetchWalletSignatures(\n rpc: Rpc<GetSignaturesForAddressApi>,\n walletAddress: Address,\n config: FetchTransactionsConfig = {},\n): Promise<RawTransaction[]> {\n const { limit = 100, before, until } = config;\n\n const response = await rpc\n .getSignaturesForAddress(walletAddress, {\n limit,\n before,\n until,\n })\n .send();\n\n return response.map((sig) => ({\n signature: sig.signature,\n slot: sig.slot,\n blockTime: sig.blockTime,\n err: sig.err,\n programIds: [],\n protocol: null,\n memo: sig.memo || null,\n }));\n}\n\n/**\n * Fetches a single transaction with full details including program IDs.\n *\n * @param rpc - Solana RPC client\n * @param signature - Transaction signature\n * @param options - Fetch options including commitment level and retry config\n * @returns Full raw transaction with program IDs, or null if not found\n */\nexport async function fetchTransaction(\n rpc: Rpc<GetTransactionApi>,\n signature: Signature,\n options: FetchTransactionOptions = {},\n): Promise<RawTransaction | null> {\n const { commitment = \"confirmed\", retry } = options;\n\n const response = await withRetry(\n () =>\n rpc\n .getTransaction(signature, {\n commitment,\n maxSupportedTransactionVersion: 0,\n encoding: \"json\",\n })\n .send(),\n retry,\n );\n\n if (!response) {\n return null;\n }\n\n // Try to get memo from response metadata first (already decoded by RPC)\n // Fall back to manual extraction if not available\n const transactionWithLogs = {\n ...response.transaction,\n meta: { logMessages: response.meta?.logMessages },\n };\n const memo = extractMemo(transactionWithLogs);\n\n return {\n signature,\n slot: response.slot,\n blockTime: response.blockTime,\n fee: Number(response.meta?.fee ?? 0),\n err: response.meta?.err ?? null,\n programIds: extractProgramIds(response.transaction),\n protocol: null,\n preTokenBalances: (response.meta?.preTokenBalances ?? []).map((bal) => ({\n accountIndex: bal.accountIndex,\n mint: bal.mint.toString(),\n owner: bal.owner?.toString(),\n programId: bal.programId?.toString(),\n uiTokenAmount: {\n amount: bal.uiTokenAmount.amount.toString(),\n decimals: bal.uiTokenAmount.decimals,\n uiAmountString: bal.uiTokenAmount.uiAmountString.toString(),\n },\n })),\n postTokenBalances: (response.meta?.postTokenBalances ?? []).map((bal) => ({\n accountIndex: bal.accountIndex,\n mint: bal.mint.toString(),\n owner: bal.owner?.toString(),\n programId: bal.programId?.toString(),\n uiTokenAmount: {\n amount: bal.uiTokenAmount.amount.toString(),\n decimals: bal.uiTokenAmount.decimals,\n uiAmountString: bal.uiTokenAmount.uiAmountString.toString(),\n },\n })),\n preBalances: (response.meta?.preBalances ?? []).map((bal) => Number(bal)),\n postBalances: (response.meta?.postBalances ?? []).map((bal) => Number(bal)),\n accountKeys: response.transaction.message.accountKeys.map((key) =>\n key.toString(),\n ),\n memo,\n };\n}\n\n/**\n * Fetches multiple transactions with controlled concurrency.\n *\n * @param rpc - Solana RPC client\n * @param signatures - Array of transaction signatures to fetch\n * @param options - Fetch options including commitment level, concurrency limit, and retry config\n * @returns Array of successfully fetched transactions (nulls and errors filtered out)\n */\nexport async function fetchTransactionsBatch(\n rpc: Rpc<GetTransactionApi>,\n signatures: Signature[],\n options: FetchBatchOptions = {},\n): Promise<RawTransaction[]> {\n const {\n commitment = \"confirmed\",\n concurrency = 10,\n retry,\n onFetchError,\n } = options;\n\n if (signatures.length === 0) {\n return [];\n }\n\n const limit = pLimit(concurrency);\n\n const safeFetch = async (sig: Signature): Promise<RawTransaction | null> => {\n try {\n return await fetchTransaction(rpc, sig, { commitment, retry });\n } catch (error) {\n onFetchError?.(\n sig,\n error instanceof Error ? error : new Error(String(error)),\n );\n return null;\n }\n };\n\n const promises = signatures.map((sig) => limit(() => safeFetch(sig)));\n\n const results = await Promise.all(promises);\n return results.filter((tx): tx is RawTransaction => tx !== null);\n}\n","export type AccountIdType = \"wallet\" | \"protocol\" | \"external\" | \"fee\";\n\nexport interface BuildAccountIdParams {\n type: AccountIdType;\n address: string;\n protocol?: string;\n token?: string;\n}\n\n/**\n * Builds a standardized account identifier string for transaction legs.\n * \n * Account IDs follow these formats:\n * - Wallet: `wallet:{address}`\n * - Protocol: `protocol:{protocol}:{token}:{address}` or `protocol:{protocol}:{address}`\n * - External: `external:{address}`\n * - Fee: `fee:network`\n * \n * @param params - Account identifier parameters\n * @returns Formatted account ID string\n * @throws Error if parameters are invalid for the account type\n */\nexport function buildAccountId(params: BuildAccountIdParams): string {\n const { type, address, protocol, token } = params;\n\n if (type === \"wallet\") {\n return `wallet:${address}`;\n }\n\n if (type === \"protocol\" && protocol) {\n if (token) {\n return `protocol:${protocol}:${token}:${address}`;\n }\n return `protocol:${protocol}:${address}`;\n }\n\n if (type === \"external\") {\n return `external:${address}`;\n }\n\n if (type === \"fee\") {\n return \"fee:network\";\n }\n \n throw new Error(\n `Invalid accountId parameters: type=${type}, address=${address}, protocol=${protocol}`\n );\n}\n\nexport interface ParsedAccountId {\n type: AccountIdType | \"unknown\";\n address?: string;\n protocol?: string;\n token?: string;\n}\n\n/**\n * Parses an account identifier string into its components.\n * \n * Extracts the account type, address, protocol, and token information from\n * a formatted account ID string. Returns `unknown` type for unrecognized formats.\n * \n * @param accountId - Account ID string to parse\n * @returns Parsed account identifier with type and optional metadata\n */\nexport function parseAccountId(accountId: string): ParsedAccountId {\n const parts = accountId.split(\":\");\n\n if (parts[0] === \"wallet\" && parts.length === 2) {\n return { type: \"wallet\", address: parts[1] };\n }\n\n if (parts[0] === \"protocol\") {\n if (parts.length === 4) {\n return {\n type: \"protocol\",\n protocol: parts[1],\n token: parts[2],\n address: parts[3],\n };\n }\n if (parts.length === 3) {\n return {\n type: \"protocol\",\n protocol: parts[1],\n address: parts[2],\n };\n }\n }\n\n if (parts[0] === \"external\" && parts.length === 2) {\n return { type: \"external\", address: parts[1] };\n }\n\n if (parts[0] === \"fee\" && parts[1] === \"network\") {\n return { type: \"fee\" };\n }\n\n return { type: \"unknown\", address: accountId };\n}\n","import type { Address } from \"@solana/kit\";\nimport type { RawTransaction, TokenBalance } from \"@tx-indexer/core/tx/tx.types\";\nimport type { MoneyAmount, TokenInfo } from \"@tx-indexer/core/money/money.types\";\nimport {\n getTokenInfo,\n KNOWN_TOKENS,\n TOKEN_INFO,\n} from \"@tx-indexer/core/money/token-registry\";\n\nexport interface TokenBalanceChange {\n mint: string;\n tokenInfo: TokenInfo;\n accountIndex: number;\n owner?: string;\n preBalance: {\n raw: string;\n ui: number;\n };\n postBalance: {\n raw: string;\n ui: number;\n };\n change: {\n raw: string;\n ui: number;\n };\n}\n\nexport interface SolBalanceChange {\n accountIndex: number;\n address: string;\n preBalance: bigint;\n postBalance: bigint;\n change: bigint;\n changeUi: number;\n}\n\n/**\n * Extracts all SPL token balance changes from a transaction.\n * \n * Compares pre and post token balances to calculate the change for each token account.\n * Unknown tokens are automatically included with a generated symbol from their mint address.\n * \n * @param tx - Raw transaction with token balance data\n * @param filterMints - Optional array of mint addresses to filter to specific tokens\n * @returns Array of token balance changes with mint, owner, and amount information\n */\nexport function extractTokenBalanceChanges(\n tx: RawTransaction,\n filterMints?: string[]\n): TokenBalanceChange[] {\n const { preTokenBalances = [], postTokenBalances = [] } = tx;\n\n const changes: TokenBalanceChange[] = [];\n\n const preBalanceMap = new Map<number, TokenBalance>();\n for (const bal of preTokenBalances) {\n preBalanceMap.set(bal.accountIndex, bal);\n }\n\n for (const postBal of postTokenBalances) {\n const { accountIndex, mint } = postBal;\n\n if (filterMints && !filterMints.includes(mint)) {\n continue;\n }\n\n let tokenInfo = getTokenInfo(mint);\n if (!tokenInfo) {\n tokenInfo = {\n mint,\n symbol: mint.slice(0, 8),\n decimals: postBal.uiTokenAmount.decimals,\n name: `Unknown Token (${mint.slice(0, 8)}...)`,\n };\n }\n\n const preBal = preBalanceMap.get(accountIndex);\n\n const preAmount = preBal?.uiTokenAmount.amount ?? \"0\";\n const postAmount = postBal.uiTokenAmount.amount;\n const preUi = preBal?.uiTokenAmount.uiAmountString\n ? parseFloat(preBal.uiTokenAmount.uiAmountString)\n : 0;\n const postUi = postBal.uiTokenAmount.uiAmountString\n ? parseFloat(postBal.uiTokenAmount.uiAmountString)\n : 0;\n\n const changeRaw = (BigInt(postAmount) - BigInt(preAmount)).toString();\n const changeUi = postUi - preUi;\n\n if (changeRaw !== \"0\") {\n changes.push({\n mint,\n tokenInfo,\n accountIndex,\n owner: postBal.owner,\n preBalance: {\n raw: preAmount,\n ui: preUi,\n },\n postBalance: {\n raw: postAmount,\n ui: postUi,\n },\n change: {\n raw: changeRaw,\n ui: changeUi,\n },\n });\n }\n }\n\n return changes;\n}\n\n/**\n * Extracts SOL balance changes for all accounts in a transaction.\n * \n * Compares pre and post lamport balances for each account key to calculate\n * the SOL change. Only includes accounts with non-zero changes.\n * \n * @param tx - Raw transaction with SOL balance data\n * @returns Array of SOL balance changes with account address and amounts\n */\nexport function extractSolBalanceChanges(\n tx: RawTransaction\n): SolBalanceChange[] {\n const {\n preBalances = [],\n postBalances = [],\n accountKeys = [],\n } = tx;\n\n const changes: SolBalanceChange[] = [];\n\n for (let i = 0; i < accountKeys.length; i++) {\n const address = accountKeys[i];\n if (!address) continue;\n\n const preBal = BigInt(preBalances[i] ?? 0);\n const postBal = BigInt(postBalances[i] ?? 0);\n const change = postBal - preBal;\n\n if (change !== 0n) {\n changes.push({\n accountIndex: i,\n address,\n preBalance: preBal,\n postBalance: postBal,\n change,\n changeUi: Number(change) / 1e9,\n });\n }\n }\n\n return changes;\n}\n\nexport function getWalletTokenChanges(\n tx: RawTransaction,\n walletAddress: Address,\n filterMints?: string[]\n): TokenBalanceChange[] {\n const allChanges = extractTokenBalanceChanges(tx, filterMints);\n\n return allChanges.filter(\n (change) =>\n change.owner?.toLowerCase() === walletAddress.toLowerCase()\n );\n}\n\nexport function getWalletSolChange(\n tx: RawTransaction,\n walletAddress: Address\n): SolBalanceChange | null {\n if (!tx.accountKeys || tx.accountKeys.length === 0) {\n return null;\n }\n\n const allChanges = extractSolBalanceChanges(tx);\n\n return (\n allChanges.find(\n (change) => change.address.toLowerCase() === walletAddress.toLowerCase()\n ) ?? null\n );\n}\n\nexport function toMoneyAmount(change: TokenBalanceChange): MoneyAmount {\n return {\n token: change.tokenInfo,\n amountRaw: change.change.raw,\n amountUi: change.change.ui,\n };\n}\n\nexport function solChangeToMoneyAmount(change: SolBalanceChange): MoneyAmount {\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (!solInfo) {\n throw new Error(\"SOL token info not found in registry\");\n }\n return {\n token: solInfo,\n amountRaw: change.change.toString(),\n amountUi: change.changeUi,\n };\n}\n\n","/**\n * Constants for DEX protocol detection\n */\n\nexport const DEX_PROTOCOL_IDS = new Set([\n \"jupiter\",\n \"jupiter-v4\",\n \"raydium\",\n \"orca-whirlpool\",\n]);\n\n","import type {\n RawTransaction,\n TxLeg,\n TxLegRole,\n} from \"@tx-indexer/core/tx/tx.types\";\nimport type { ProtocolInfo } from \"@tx-indexer/core/actors/counterparty.types\";\nimport { buildAccountId } from \"@tx-indexer/core/tx/account-id\";\nimport {\n extractSolBalanceChanges,\n extractTokenBalanceChanges,\n type SolBalanceChange,\n type TokenBalanceChange,\n} from \"./balance-parser\";\nimport {\n KNOWN_TOKENS,\n TOKEN_INFO,\n} from \"@tx-indexer/core/money/token-registry\";\nimport { DEX_PROTOCOL_IDS } from \"../constants/protocol-constants\";\n\nfunction isDexProtocol(protocol: ProtocolInfo | null | undefined): boolean {\n return (\n protocol !== null &&\n protocol !== undefined &&\n DEX_PROTOCOL_IDS.has(protocol.id)\n );\n}\n\n/**\n * Converts a raw Solana transaction into a double-entry accounting ledger.\n *\n * Creates TxLeg entries for all SOL and token balance changes, automatically\n * detecting and accounting for network fees. Each leg represents a debit or credit\n * for a specific account and token, enabling transaction classification and validation.\n *\n * All accounts are tagged as \"external:\" - the classification layer determines\n * the transaction type and direction from the initiator's (fee payer's) perspective.\n *\n * @param tx - Raw transaction data with balance changes\n * @returns Array of transaction legs representing all balance movements\n */\nexport function transactionToLegs(tx: RawTransaction): TxLeg[] {\n const legs: TxLeg[] = [];\n const feePayer = tx.accountKeys?.[0]?.toLowerCase();\n\n const solChanges = extractSolBalanceChanges(tx);\n let totalSolDebits = 0n;\n let totalSolCredits = 0n;\n\n for (const change of solChanges) {\n if (change.change === 0n) continue;\n\n const accountId = buildAccountId({\n type: \"external\",\n address: change.address,\n });\n\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (!solInfo) {\n throw new Error(\"SOL token info not found in registry\");\n }\n\n if (change.change > 0n) {\n totalSolCredits += change.change;\n } else {\n totalSolDebits += -change.change;\n }\n\n legs.push({\n accountId,\n side: change.change > 0n ? \"credit\" : \"debit\",\n amount: {\n token: solInfo,\n amountRaw: change.change.toString().replace(\"-\", \"\"),\n amountUi: Math.abs(change.changeUi),\n },\n role: determineSolRole(change, tx, feePayer),\n });\n }\n\n const networkFee = totalSolDebits - totalSolCredits;\n if (networkFee > 0n) {\n const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];\n if (solInfo) {\n legs.push({\n accountId: buildAccountId({ type: \"fee\", address: \"\" }),\n side: \"credit\",\n amount: {\n token: solInfo,\n amountRaw: networkFee.toString(),\n amountUi: Number(networkFee) / 1e9,\n },\n role: \"fee\",\n });\n }\n }\n\n const tokenChanges = extractTokenBalanceChanges(tx);\n for (const change of tokenChanges) {\n if (change.change.raw === \"0\") continue;\n\n let accountId: string;\n if (isDexProtocol(tx.protocol)) {\n const isFeePayer = feePayer && change.owner?.toLowerCase() === feePayer;\n if (isFeePayer) {\n accountId = buildAccountId({\n type: \"external\",\n address: change.owner || feePayer,\n });\n } else {\n accountId = buildAccountId({\n type: \"protocol\",\n address: change.owner || change.tokenInfo.mint,\n protocol: tx.protocol!.id,\n token: change.tokenInfo.symbol,\n });\n }\n } else {\n accountId = buildAccountId({\n type: \"external\",\n address: change.owner || change.tokenInfo.mint,\n });\n }\n\n legs.push({\n accountId,\n side: change.change.ui > 0 ? \"credit\" : \"debit\",\n amount: {\n token: change.tokenInfo,\n amountRaw: change.change.raw.replace(\"-\", \"\"),\n amountUi: Math.abs(change.change.ui),\n },\n role: determineTokenRole(change, tx, feePayer),\n });\n }\n\n return legs;\n}\n\n/**\n * Determines the role of a SOL balance change in the transaction context.\n *\n * Network fees are handled separately via the fee:network leg (calculated from\n * the imbalance between total debits and credits). This function only categorizes\n * external account balance changes as sent/received.\n *\n * @param change - SOL balance change for an account\n * @param tx - Raw transaction for additional context\n * @param _feePayer - Fee payer address (unused, kept for API compatibility)\n * @returns The role of this SOL balance change\n */\nfunction determineSolRole(\n change: SolBalanceChange,\n tx: RawTransaction,\n _feePayer?: string,\n): TxLegRole {\n const isPositive = change.change > 0n;\n\n if (isPositive) {\n if (tx.protocol?.id === \"stake\") {\n return \"reward\";\n }\n return \"received\";\n }\n\n return \"sent\";\n}\n\n/**\n * Determines the role of a token balance change in the transaction context.\n *\n * @param change - Token balance change for an account\n * @param tx - Raw transaction for protocol context\n * @param feePayer - Fee payer address\n * @returns The role of this token balance change\n */\nfunction determineTokenRole(\n change: TokenBalanceChange,\n tx: RawTransaction,\n feePayer?: string,\n): TxLegRole {\n const isFeePayer = feePayer\n ? change.owner?.toLowerCase() === feePayer\n : false;\n const isPositive = change.change.ui > 0;\n\n if (isFeePayer) {\n return isPositive ? \"received\" : \"sent\";\n }\n\n if (isDexProtocol(tx.protocol)) {\n return isPositive ? \"protocol_withdraw\" : \"protocol_deposit\";\n }\n\n return isPositive ? \"received\" : \"sent\";\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { detectFacilitator } from \"@tx-indexer/solana/constants/program-ids\";\n\nexport class TransferClassifier implements Classifier {\n name = \"transfer\";\n priority = 20;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const facilitator = tx.accountKeys\n ? detectFacilitator(tx.accountKeys)\n : null;\n\n const senderLeg = legs.find(\n (l) =>\n l.accountId.startsWith(\"external:\") &&\n l.side === \"debit\" &&\n l.role === \"sent\"\n );\n\n if (!senderLeg) return null;\n\n const sender = senderLeg.accountId.replace(\"external:\", \"\");\n\n const receiverLeg = legs.find(\n (l) =>\n l.accountId.startsWith(\"external:\") &&\n l.side === \"credit\" &&\n l.role === \"received\" &&\n l.amount.token.mint === senderLeg.amount.token.mint\n );\n\n if (!receiverLeg) return null;\n\n const receiver = receiverLeg.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"transfer\",\n primaryAmount: senderLeg.amount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: {\n type: \"unknown\",\n address: receiver,\n name: `${receiver.slice(0, 8)}...`,\n },\n confidence: 0.95,\n isRelevant: true,\n metadata: {\n ...(facilitator && { facilitator, payment_type: \"facilitated\" }),\n },\n };\n }\n}\n","import type { ProtocolInfo } from \"@tx-indexer/core/actors/counterparty.types\";\nimport {\n // Core programs\n JUPITER_V6_PROGRAM_ID,\n JUPITER_V4_PROGRAM_ID,\n JUPITER_ORDER_ENGINE_PROGRAM_ID,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n SYSTEM_PROGRAM_ID,\n COMPUTE_BUDGET_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n SPL_MEMO_PROGRAM_ID,\n MEMO_V1_PROGRAM_ID,\n // DEX programs\n RAYDIUM_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n RAYDIUM_CPMM_PROGRAM_ID,\n RAYDIUM_STABLE_PROGRAM_ID,\n ORCA_WHIRLPOOL_PROGRAM_ID,\n ORCA_TOKEN_SWAP_V1_PROGRAM_ID,\n OPENBOOK_V2_PROGRAM_ID,\n PHOENIX_PROGRAM_ID,\n SABER_STABLE_SWAP_PROGRAM_ID,\n MERCURIAL_STABLE_SWAP_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n METEORA_POOLS_PROGRAM_ID,\n PUMPFUN_AMM_PROGRAM_ID,\n PUMPFUN_BONDING_CURVE_PROGRAM_ID,\n LIFINITY_V2_PROGRAM_ID,\n // NFT programs\n METAPLEX_PROGRAM_ID,\n CANDY_GUARD_PROGRAM_ID,\n CANDY_MACHINE_V3_PROGRAM_ID,\n BUBBLEGUM_PROGRAM_ID,\n MAGIC_EDEN_CANDY_MACHINE_ID,\n // Staking programs\n STAKE_POOL_PROGRAM_ID,\n STAKE_PROGRAM_ID,\n // Bridge programs\n WORMHOLE_PROGRAM_ID,\n WORMHOLE_TOKEN_BRIDGE_ID,\n DEGODS_BRIDGE_PROGRAM_ID,\n DEBRIDGE_PROGRAM_ID,\n ALLBRIDGE_PROGRAM_ID,\n} from \"@tx-indexer/solana/constants/program-ids\";\n\nconst KNOWN_PROGRAMS: Record<string, ProtocolInfo> = {\n // Jupiter aggregator\n [JUPITER_V6_PROGRAM_ID]: {\n id: \"jupiter\",\n name: \"Jupiter\",\n },\n [JUPITER_V4_PROGRAM_ID]: {\n id: \"jupiter-v4\",\n name: \"Jupiter V4\",\n },\n [JUPITER_ORDER_ENGINE_PROGRAM_ID]: {\n id: \"jupiter-limit-order\",\n name: \"Jupiter Limit Order\",\n },\n\n // Core token programs\n [TOKEN_PROGRAM_ID]: {\n id: \"spl-token\",\n name: \"Token Program\",\n },\n [TOKEN_2022_PROGRAM_ID]: {\n id: \"token-2022\",\n name: \"Token-2022 Program\",\n },\n [SYSTEM_PROGRAM_ID]: {\n id: \"system\",\n name: \"System Program\",\n },\n [COMPUTE_BUDGET_PROGRAM_ID]: {\n id: \"compute-budget\",\n name: \"Compute Budget\",\n },\n [ASSOCIATED_TOKEN_PROGRAM_ID]: {\n id: \"associated-token\",\n name: \"Associated Token Program\",\n },\n\n // Memo programs\n [SPL_MEMO_PROGRAM_ID]: {\n id: \"memo\",\n name: \"Memo Program\",\n },\n [MEMO_V1_PROGRAM_ID]: {\n id: \"memo-v1\",\n name: \"Memo Program V1\",\n },\n\n // Raydium AMMs\n [RAYDIUM_PROGRAM_ID]: {\n id: \"raydium\",\n name: \"Raydium\",\n },\n [RAYDIUM_CLMM_PROGRAM_ID]: {\n id: \"raydium-clmm\",\n name: \"Raydium CLMM\",\n },\n [RAYDIUM_CPMM_PROGRAM_ID]: {\n id: \"raydium-cpmm\",\n name: \"Raydium CPMM\",\n },\n [RAYDIUM_STABLE_PROGRAM_ID]: {\n id: \"raydium-stable\",\n name: \"Raydium Stable\",\n },\n\n // Orca\n [ORCA_WHIRLPOOL_PROGRAM_ID]: {\n id: \"orca-whirlpool\",\n name: \"Orca Whirlpool\",\n },\n [ORCA_TOKEN_SWAP_V1_PROGRAM_ID]: {\n id: \"orca-v1\",\n name: \"Orca Token Swap V1\",\n },\n\n // CLOBs (Central Limit Order Books)\n [OPENBOOK_V2_PROGRAM_ID]: {\n id: \"openbook\",\n name: \"OpenBook\",\n },\n [PHOENIX_PROGRAM_ID]: {\n id: \"phoenix\",\n name: \"Phoenix\",\n },\n\n // Stableswap protocols\n [SABER_STABLE_SWAP_PROGRAM_ID]: {\n id: \"saber\",\n name: \"Saber\",\n },\n [MERCURIAL_STABLE_SWAP_PROGRAM_ID]: {\n id: \"mercurial\",\n name: \"Mercurial\",\n },\n\n // Meteora\n [METEORA_DLMM_PROGRAM_ID]: {\n id: \"meteora-dlmm\",\n name: \"Meteora DLMM\",\n },\n [METEORA_POOLS_PROGRAM_ID]: {\n id: \"meteora-pools\",\n name: \"Meteora Pools\",\n },\n\n // Pump.fun\n [PUMPFUN_AMM_PROGRAM_ID]: {\n id: \"pumpfun\",\n name: \"Pump.fun\",\n },\n [PUMPFUN_BONDING_CURVE_PROGRAM_ID]: {\n id: \"pumpfun-bonding\",\n name: \"Pump.fun Bonding Curve\",\n },\n\n // Lifinity\n [LIFINITY_V2_PROGRAM_ID]: {\n id: \"lifinity\",\n name: \"Lifinity\",\n },\n\n // NFT programs\n [METAPLEX_PROGRAM_ID]: {\n id: \"metaplex\",\n name: \"Metaplex\",\n },\n [CANDY_GUARD_PROGRAM_ID]: {\n id: \"candy-guard\",\n name: \"Metaplex Candy Guard Program\",\n },\n [CANDY_MACHINE_V3_PROGRAM_ID]: {\n id: \"candy-machine-v3\",\n name: \"Metaplex Candy Machine Core Program\",\n },\n [BUBBLEGUM_PROGRAM_ID]: {\n id: \"bubblegum\",\n name: \"Bubblegum Program\",\n },\n [MAGIC_EDEN_CANDY_MACHINE_ID]: {\n id: \"magic-eden-candy-machine\",\n name: \"Nft Candy Machine Program (Magic Eden)\",\n },\n\n // Staking programs\n [STAKE_PROGRAM_ID]: {\n id: \"stake\",\n name: \"Stake Program\",\n },\n [STAKE_POOL_PROGRAM_ID]: {\n id: \"stake-pool\",\n name: \"Stake Pool Program\",\n },\n\n // Bridge programs\n [WORMHOLE_PROGRAM_ID]: {\n id: \"wormhole\",\n name: \"Wormhole\",\n },\n [WORMHOLE_TOKEN_BRIDGE_ID]: {\n id: \"wormhole-token-bridge\",\n name: \"Wormhole Token Bridge\",\n },\n [DEGODS_BRIDGE_PROGRAM_ID]: {\n id: \"degods-bridge\",\n name: \"DeGods Bridge\",\n },\n [DEBRIDGE_PROGRAM_ID]: {\n id: \"debridge\",\n name: \"deBridge\",\n },\n [ALLBRIDGE_PROGRAM_ID]: {\n id: \"allbridge\",\n name: \"Allbridge\",\n },\n};\n\nconst PRIORITY_ORDER = [\n // Bridge protocols (highest priority - cross-chain operations)\n \"wormhole\",\n \"wormhole-token-bridge\",\n \"degods-bridge\",\n \"debridge\",\n \"allbridge\",\n // DEX aggregators (route through multiple DEXes)\n \"jupiter\",\n \"jupiter-v4\",\n \"jupiter-limit-order\",\n // AMMs and DEXes\n \"raydium\",\n \"raydium-clmm\",\n \"raydium-cpmm\",\n \"raydium-stable\",\n \"orca-whirlpool\",\n \"orca-v1\",\n \"meteora-dlmm\",\n \"meteora-pools\",\n \"lifinity\",\n \"pumpfun\",\n \"pumpfun-bonding\",\n // CLOBs\n \"openbook\",\n \"phoenix\",\n // Stableswap\n \"saber\",\n \"mercurial\",\n // NFT\n \"metaplex\",\n \"candy-guard\",\n \"candy-machine-v3\",\n \"bubblegum\",\n \"magic-eden-candy-machine\",\n // Staking\n \"stake\",\n \"stake-pool\",\n // Infrastructure (lowest priority)\n \"memo\",\n \"memo-v1\",\n \"associated-token\",\n \"spl-token\",\n \"token-2022\",\n \"compute-budget\",\n \"system\",\n];\n\n/**\n * Protocol IDs that are DEX (decentralized exchange) protocols.\n * These protocols perform swaps and should have their legs tagged as \"protocol:\"\n * with deposit/withdraw roles.\n */\nconst DEX_PROTOCOL_IDS = new Set([\n // Jupiter aggregator\n \"jupiter\",\n \"jupiter-v4\",\n \"jupiter-limit-order\",\n // Raydium AMMs\n \"raydium\",\n \"raydium-clmm\",\n \"raydium-cpmm\",\n \"raydium-stable\",\n // Orca\n \"orca-whirlpool\",\n \"orca-v1\",\n // CLOBs\n \"openbook\",\n \"phoenix\",\n // Stableswap\n \"saber\",\n \"mercurial\",\n // Meteora\n \"meteora-dlmm\",\n \"meteora-pools\",\n // Pump.fun\n \"pumpfun\",\n \"pumpfun-bonding\",\n // Lifinity\n \"lifinity\",\n]);\n\nconst NFT_MINT_PROTOCOL_IDS = new Set([\n \"metaplex\",\n \"candy-machine-v3\",\n \"candy-guard\",\n \"bubblegum\",\n \"magic-eden-candy-machine\",\n]);\n\nconst STAKE_PROTOCOL_IDS = new Set([\"stake\", \"stake-pool\"]);\n\nconst BRIDGE_PROTOCOL_IDS = new Set([\n \"wormhole\",\n \"wormhole-token-bridge\",\n \"degods-bridge\",\n \"debridge\",\n \"allbridge\",\n]);\n\n/**\n * Checks if a protocol is a DEX (decentralized exchange) that performs swaps.\n * DEX protocols should have their legs tagged as \"protocol:\" with deposit/withdraw roles.\n * Non-DEX protocols (like Associated Token Program) are infrastructure and should not\n * affect leg tagging.\n */\nexport function isDexProtocol(protocol: ProtocolInfo | null): boolean {\n return protocol !== null && DEX_PROTOCOL_IDS.has(protocol.id);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a DEX protocol.\n * Useful when you only have the protocol ID string, not the full ProtocolInfo object.\n */\nexport function isDexProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && DEX_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a NFT Mint\n */\nexport function isNftMintProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && NFT_MINT_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a stake\n */\n\nexport function isStakeProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && STAKE_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Checks if a protocol ID string corresponds to a bridge protocol\n */\nexport function isBridgeProtocolById(protocolId: string | undefined): boolean {\n return protocolId !== undefined && BRIDGE_PROTOCOL_IDS.has(protocolId);\n}\n\n/**\n * Detects the primary protocol used in a transaction based on its program IDs.\n *\n * When multiple protocols are detected, returns the highest priority protocol\n * according to the PRIORITY_ORDER (e.g., Jupiter > Raydium > Token Program).\n *\n * @param programIds - Array of program IDs involved in the transaction\n * @returns The detected protocol information, or null if no known protocol is found\n */\nexport function detectProtocol(programIds: string[]): ProtocolInfo | null {\n const detectedProtocols: ProtocolInfo[] = [];\n\n for (const programId of programIds) {\n const protocol = KNOWN_PROGRAMS[programId];\n if (protocol) {\n detectedProtocols.push(protocol);\n }\n }\n\n if (detectedProtocols.length === 0) {\n return null;\n }\n\n detectedProtocols.sort((a, b) => {\n const aPriority = PRIORITY_ORDER.indexOf(a.id);\n const bPriority = PRIORITY_ORDER.indexOf(b.id);\n return aPriority - bPriority;\n });\n\n return detectedProtocols[0] ?? null;\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport type { TxLeg } from \"@tx-indexer/core/tx/tx.types\";\nimport { isDexProtocolById } from \"../protocols/detector\";\n\n/**\n * Finds the best swap pair from the lists of tokens going out and coming in.\n *\n * The best pair is determined by:\n * 1. Must have different token symbols (otherwise it's not a swap)\n * 2. Prefer the pair with the largest total value (to avoid picking up dust/fees)\n *\n * For now, we use amountUi as a proxy for value since we don't have USD prices.\n * This works well because:\n * - The main swap tokens typically have much larger amounts than dust\n * - A 2000 USDC swap will always beat a 0.0002 SOL fee\n */\nfunction findSwapPair(\n tokensOut: TxLeg[],\n tokensIn: TxLeg[],\n): { initiatorOut: TxLeg; initiatorIn: TxLeg } | null {\n let bestPair: { initiatorOut: TxLeg; initiatorIn: TxLeg } | null = null;\n let bestScore = 0;\n\n for (const out of tokensOut) {\n for (const inLeg of tokensIn) {\n if (out.amount.token.symbol !== inLeg.amount.token.symbol) {\n // Score by the larger of the two amounts (in UI units)\n // This helps identify the \"main\" swap vs dust movements\n const score = Math.max(out.amount.amountUi, inLeg.amount.amountUi);\n\n if (score > bestScore) {\n bestScore = score;\n bestPair = { initiatorOut: out, initiatorIn: inLeg };\n }\n }\n }\n }\n\n return bestPair;\n}\n\nexport class SwapClassifier implements Classifier {\n name = \"swap\";\n priority = 80;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx, walletAddress } = context;\n\n const initiator = tx.accountKeys?.[0] ?? null;\n\n if (!initiator) {\n return null;\n }\n\n const initiatorAccountId = `external:${initiator}`;\n\n const initiatorTokensOut = legs.filter(\n (leg) =>\n leg.accountId === initiatorAccountId &&\n leg.side === \"debit\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\"),\n );\n\n const initiatorTokensIn = legs.filter(\n (leg) =>\n leg.accountId === initiatorAccountId &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\"),\n );\n\n if (initiatorTokensOut.length === 0 || initiatorTokensIn.length === 0) {\n return null;\n }\n\n const swapPair = findSwapPair(initiatorTokensOut, initiatorTokensIn);\n if (!swapPair) {\n return null;\n }\n\n const { initiatorOut, initiatorIn } = swapPair;\n\n let tokenOut = initiatorOut;\n let tokenIn = initiatorIn;\n let perspectiveWallet = initiator;\n\n if (walletAddress) {\n const walletAccountId = `external:${walletAddress}`;\n\n const walletOut = legs.find(\n (leg) =>\n leg.accountId === walletAccountId &&\n leg.side === \"debit\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\"),\n );\n\n const walletIn = legs.find(\n (leg) =>\n leg.accountId === walletAccountId &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\"),\n );\n\n if (\n walletOut &&\n walletIn &&\n walletOut.amount.token.symbol !== walletIn.amount.token.symbol\n ) {\n tokenOut = walletOut;\n tokenIn = walletIn;\n perspectiveWallet = walletAddress;\n }\n }\n\n const hasDexProtocol = isDexProtocolById(tx.protocol?.id);\n const confidence = hasDexProtocol ? 0.95 : 0.75;\n\n return {\n primaryType: \"swap\",\n primaryAmount: tokenOut.amount,\n secondaryAmount: tokenIn.amount,\n sender: perspectiveWallet,\n receiver: perspectiveWallet,\n counterparty: null,\n confidence,\n isRelevant: true,\n metadata: {\n swap_type: \"token_to_token\",\n from_token: tokenOut.amount.token.symbol,\n to_token: tokenIn.amount.token.symbol,\n from_amount: tokenOut.amount.amountUi,\n to_amount: tokenIn.amount.amountUi,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { detectFacilitator } from \"@tx-indexer/solana/constants/program-ids\";\n\nexport class AirdropClassifier implements Classifier {\n name = \"airdrop\";\n priority = 70;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const facilitator = tx.accountKeys\n ? detectFacilitator(tx.accountKeys)\n : null;\n\n const protocolLegs = legs.filter((leg) =>\n leg.accountId.startsWith(\"protocol:\")\n );\n\n if (protocolLegs.length === 0) {\n return null;\n }\n\n const tokenReceived = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.role === \"received\" &&\n leg.amount.token.symbol !== \"SOL\"\n );\n\n if (tokenReceived.length === 0) {\n return null;\n }\n\n const tokenSent = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role === \"sent\" &&\n leg.amount.token.symbol !== \"SOL\"\n );\n\n if (tokenSent.length > 0) {\n return null;\n }\n\n const mainToken = tokenReceived[0]!;\n const receiver = mainToken.accountId.replace(\"external:\", \"\");\n\n const senderLeg = legs.find(\n (leg) =>\n leg.side === \"debit\" &&\n leg.amount.token.mint === mainToken.amount.token.mint\n );\n\n const sender = senderLeg\n ? senderLeg.accountId.replace(/^(external:|protocol:)/, \"\")\n : null;\n\n return {\n primaryType: \"airdrop\",\n primaryAmount: mainToken.amount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: sender\n ? {\n type: \"protocol\",\n address: sender,\n }\n : null,\n confidence: 0.85,\n isRelevant: true,\n metadata: {\n airdrop_type: \"token\",\n token: mainToken.amount.token.symbol,\n amount: mainToken.amount.amountUi,\n ...(facilitator && { facilitator }),\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\n\nexport class FeeOnlyClassifier implements Classifier {\n name = \"fee-only\";\n priority = 60;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs } = context;\n\n const externalLegs = legs.filter((leg) =>\n leg.accountId.startsWith(\"external:\")\n );\n const nonFeeLegs = externalLegs.filter((leg) => leg.role !== \"fee\");\n\n if (nonFeeLegs.length > 0) {\n return null;\n }\n\n const feeLegs = legs.filter((leg) => leg.role === \"fee\");\n\n if (feeLegs.length === 0) {\n return null;\n }\n\n const feePayerLeg = feeLegs.find(\n (leg) => leg.side === \"debit\" && leg.amount.token.symbol === \"SOL\"\n );\n\n const feePayer = feePayerLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const totalFee = feeLegs.find((leg) => leg.amount.token.symbol === \"SOL\");\n\n return {\n primaryType: \"fee_only\",\n primaryAmount: totalFee?.amount ?? null,\n secondaryAmount: null,\n sender: feePayer,\n receiver: null,\n counterparty: null,\n confidence: 0.95,\n isRelevant: false,\n metadata: {\n fee_type: \"network\",\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport {\n isSolanaPayTransaction,\n parseSolanaPayMemo,\n} from \"@tx-indexer/solana/mappers/memo-parser\";\n\nexport class SolanaPayClassifier implements Classifier {\n name = \"solana-pay\";\n priority = 95;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { tx, legs } = context;\n\n if (!isSolanaPayTransaction(tx.programIds, tx.memo)) {\n return null;\n }\n\n const memo = parseSolanaPayMemo(tx.memo!);\n\n const senderLeg = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role === \"sent\"\n );\n\n const receiverLeg = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.role === \"received\"\n );\n\n const sender = senderLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const receiver = receiverLeg?.accountId.replace(\"external:\", \"\") ?? null;\n const primaryAmount = senderLeg?.amount ?? receiverLeg?.amount ?? null;\n\n return {\n primaryType: \"transfer\",\n primaryAmount,\n secondaryAmount: null,\n sender,\n receiver,\n counterparty: receiver\n ? {\n address: receiver,\n name: memo.merchant ?? undefined,\n type: memo.merchant ? \"merchant\" : \"unknown\",\n }\n : null,\n confidence: 0.98,\n isRelevant: true,\n metadata: {\n payment_type: \"solana_pay\",\n memo: memo.raw,\n merchant: memo.merchant,\n item: memo.item,\n reference: memo.reference,\n label: memo.label,\n message: memo.message,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isNftMintProtocolById } from \"../protocols/detector\";\n\nexport class NftMintClassifier implements Classifier {\n name = \"nft-mint\";\n priority = 85;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasNftMintProtocol = isNftMintProtocolById(tx.protocol?.id);\n if (!hasNftMintProtocol) {\n return null;\n }\n\n const nftCredits = legs.filter(\n (leg) =>\n leg.side === \"credit\" &&\n leg.amount.token.decimals === 0 &&\n leg.amount.amountUi >= 1 &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n if (nftCredits.length === 0) {\n return null;\n }\n\n const primaryNft = nftCredits[0]!;\n const minter = primaryNft.accountId.replace(\"external:\", \"\");\n\n const paymentLeg = legs.find(\n (leg) =>\n leg.side === \"debit\" &&\n leg.role === \"sent\" &&\n leg.amount.token.symbol === \"SOL\"\n );\n\n const totalMinted = nftCredits.reduce(\n (sum, leg) => sum + leg.amount.amountUi,\n 0\n );\n\n return {\n primaryType: \"nft_mint\",\n primaryAmount: primaryNft.amount,\n secondaryAmount: paymentLeg?.amount ?? null,\n sender: null,\n receiver: minter,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n nft_mint: primaryNft.amount.token.mint,\n nft_name: primaryNft.amount.token.name,\n quantity: totalMinted,\n mint_price: paymentLeg?.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isStakeProtocolById } from \"../protocols/detector\";\n\nexport class StakeDepositClassifier implements Classifier {\n name = \"stake-deposit\";\n priority = 82;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);\n if (!hasStakeProtocol) {\n return null;\n }\n\n const solDebit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n if (!solDebit) {\n return null;\n }\n\n const staker = solDebit.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"stake_deposit\",\n primaryAmount: solDebit.amount,\n secondaryAmount: null,\n sender: staker,\n receiver: null,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n stake_amount: solDebit.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isStakeProtocolById } from \"../protocols/detector\";\n\nexport class StakeWithdrawClassifier implements Classifier {\n name = \"stake-withdraw\";\n priority = 81;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);\n if (!hasStakeProtocol) {\n return null;\n }\n\n const solCredit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n if (!solCredit) {\n return null;\n }\n\n const solDebit = legs.find(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.amount.token.symbol === \"SOL\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n if (solDebit) {\n return null;\n }\n\n const withdrawer = solCredit.accountId.replace(\"external:\", \"\");\n\n return {\n primaryType: \"stake_withdraw\",\n primaryAmount: solCredit.amount,\n secondaryAmount: null,\n sender: null,\n receiver: withdrawer,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n withdraw_amount: solCredit.amount.amountUi,\n protocol: tx.protocol?.id,\n },\n };\n }\n}\n","import type {\n Classifier,\n ClassifierContext,\n} from \"../engine/classifier.interface\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport { isBridgeProtocolById } from \"../protocols/detector\";\n\nexport class BridgeClassifier implements Classifier {\n name = \"bridge\";\n priority = 88;\n\n classify(context: ClassifierContext): TransactionClassification | null {\n const { legs, tx } = context;\n\n const hasBridgeProtocol = isBridgeProtocolById(tx.protocol?.id);\n if (!hasBridgeProtocol) {\n return null;\n }\n\n const tokensOut = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"debit\" &&\n leg.role !== \"fee\" &&\n (leg.role === \"sent\" || leg.role === \"protocol_deposit\")\n );\n\n const tokensIn = legs.filter(\n (leg) =>\n leg.accountId.startsWith(\"external:\") &&\n leg.side === \"credit\" &&\n (leg.role === \"received\" || leg.role === \"protocol_withdraw\")\n );\n\n let primaryType: \"bridge_in\" | \"bridge_out\";\n let primaryAmount = null;\n let participant: string | null = null;\n\n if (tokensIn.length > 0 && tokensOut.length === 0) {\n primaryType = \"bridge_in\";\n const creditLeg = tokensIn[0]!;\n primaryAmount = creditLeg.amount;\n participant = creditLeg.accountId.replace(\"external:\", \"\");\n } else if (tokensOut.length > 0 && tokensIn.length === 0) {\n primaryType = \"bridge_out\";\n const debitLeg = tokensOut[0]!;\n primaryAmount = debitLeg.amount;\n participant = debitLeg.accountId.replace(\"external:\", \"\");\n } else if (tokensIn.length > 0 && tokensOut.length > 0) {\n primaryType = \"bridge_in\";\n const creditLeg = tokensIn[0]!;\n primaryAmount = creditLeg.amount;\n participant = creditLeg.accountId.replace(\"external:\", \"\");\n } else {\n return null;\n }\n\n return {\n primaryType,\n primaryAmount,\n secondaryAmount: null,\n sender: primaryType === \"bridge_out\" ? participant : null,\n receiver: primaryType === \"bridge_in\" ? participant : null,\n counterparty: null,\n confidence: 0.9,\n isRelevant: true,\n metadata: {\n bridge_protocol: tx.protocol?.id,\n bridge_name: tx.protocol?.name,\n },\n };\n }\n}\n","import type { TxLeg, RawTransaction } from \"@tx-indexer/core/tx/tx.types\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport type { Classifier, ClassifierContext } from \"./classifier.interface\";\nimport { TransferClassifier } from \"../classifiers/transfer-classifier\";\nimport { SwapClassifier } from \"../classifiers/swap-classifier\";\nimport { AirdropClassifier } from \"../classifiers/airdrop-classifier\";\nimport { FeeOnlyClassifier } from \"../classifiers/fee-only-classifier\";\nimport { SolanaPayClassifier } from \"../classifiers/solana-pay-classifier\";\nimport { NftMintClassifier } from \"../classifiers/nft-mint-classifier\";\nimport { StakeDepositClassifier } from \"../classifiers/stake-deposit-classifier\";\nimport { StakeWithdrawClassifier } from \"../classifiers/stake-withdraw-classifier\";\nimport { BridgeClassifier } from \"../classifiers/bridge-classifier\";\n\nexport class ClassificationService {\n private classifiers: Classifier[] = [];\n\n constructor() {\n this.registerClassifier(new SolanaPayClassifier());\n this.registerClassifier(new BridgeClassifier());\n this.registerClassifier(new NftMintClassifier());\n this.registerClassifier(new StakeDepositClassifier());\n this.registerClassifier(new StakeWithdrawClassifier());\n this.registerClassifier(new SwapClassifier());\n this.registerClassifier(new AirdropClassifier());\n this.registerClassifier(new TransferClassifier());\n this.registerClassifier(new FeeOnlyClassifier());\n }\n\n registerClassifier(classifier: Classifier): void {\n this.classifiers.push(classifier);\n this.classifiers.sort((a, b) => b.priority - a.priority);\n }\n\n classify(legs: TxLeg[], tx: RawTransaction, walletAddress?: string): TransactionClassification {\n const context: ClassifierContext = { legs, tx, walletAddress };\n\n for (const classifier of this.classifiers) {\n const result = classifier.classify(context);\n if (result && result.isRelevant) {\n return result;\n }\n }\n\n return {\n primaryType: \"other\",\n primaryAmount: null,\n secondaryAmount: null,\n sender: null,\n receiver: null,\n counterparty: null,\n confidence: 0.0,\n isRelevant: false,\n metadata: {},\n };\n }\n}\n\nexport const classificationService = new ClassificationService();\n\n/**\n * Classifies a transaction based on its accounting legs and context.\n *\n * Uses a priority-ordered chain of classifiers (Solana Pay > Bridge > NFT Mint > Stake Deposit > Stake Withdraw > Swap > Airdrop > Transfer > Fee-only)\n * to determine the transaction type, direction, amounts, sender, and receiver.\n *\n * @param legs - Transaction legs representing all balance movements\n * @param tx - Raw transaction data for additional context (protocol, memo, etc.)\n * @param walletAddress - Optional wallet address for perspective-aware classification (e.g., swap direction)\n * @returns Classification result with type, amounts, sender, receiver, and confidence\n */\nexport function classifyTransaction(\n legs: TxLeg[],\n tx: RawTransaction,\n walletAddress?: string\n): TransactionClassification {\n return classificationService.classify(legs, tx, walletAddress);\n}\n","import type { TransactionClassification } from \"./classification.types\";\nimport type { RawTransaction } from \"./tx.types\";\n\nexport interface SpamFilterConfig {\n minSolAmount?: number;\n minTokenAmountUsd?: number;\n minConfidence?: number;\n allowFailed?: boolean;\n}\n\nconst DEFAULT_CONFIG: Required<SpamFilterConfig> = {\n minSolAmount: 0.001,\n minTokenAmountUsd: 0.01,\n minConfidence: 0.5,\n allowFailed: false,\n};\n\n/**\n * Determines if a transaction should be filtered as spam or dust.\n * \n * A transaction is considered spam if it:\n * - Failed (and allowFailed is false)\n * - Has low classification confidence\n * - Is not relevant to the wallet\n * - Involves dust amounts below configured thresholds\n * \n * @param tx - Raw transaction data\n * @param classification - Transaction classification result\n * @param config - Optional spam filter configuration (uses defaults if omitted)\n * @returns True if the transaction should be filtered as spam\n */\nexport function isSpamTransaction(\n tx: RawTransaction,\n classification: TransactionClassification,\n config: SpamFilterConfig = {}\n): boolean {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.allowFailed && tx.err) {\n return true;\n }\n\n if (classification.confidence < cfg.minConfidence) {\n return true;\n }\n\n if (!classification.isRelevant) {\n return true;\n }\n\n if (isDustTransaction(classification, cfg)) {\n return true;\n }\n\n return false;\n}\n\nfunction isDustTransaction(\n classification: TransactionClassification,\n config: Required<SpamFilterConfig>\n): boolean {\n const { primaryAmount } = classification;\n \n if (!primaryAmount) {\n return false;\n }\n\n const { token, amountUi } = primaryAmount;\n\n if (token.symbol === \"SOL\") {\n return Math.abs(amountUi) < config.minSolAmount;\n }\n\n if (token.symbol === \"USDC\") {\n return Math.abs(amountUi) < config.minTokenAmountUsd;\n }\n\n return Math.abs(amountUi) < config.minTokenAmountUsd;\n}\n\n/**\n * Filters an array of transactions to remove spam and dust transactions.\n * \n * Applies spam detection criteria to each transaction while preserving\n * additional properties in the returned array items.\n * \n * @param transactions - Array of transaction objects with tx and classification\n * @param config - Optional spam filter configuration\n * @returns Filtered array with spam transactions removed\n */\nexport function filterSpamTransactions<T extends {\n tx: RawTransaction;\n classification: TransactionClassification;\n}>(\n transactions: T[],\n config?: SpamFilterConfig\n): T[] {\n return transactions.filter(\n ({ tx, classification }) => !isSpamTransaction(tx, classification, config)\n );\n}\n\n","import type { TokenInfo } from \"./money.types\";\nimport { TOKEN_INFO, createUnknownToken } from \"./token-registry\";\n\n/**\n * Jupiter Token API response format\n */\ninterface JupiterToken {\n address: string;\n symbol: string;\n name: string;\n decimals: number;\n logoURI?: string;\n tags?: string[];\n daily_volume?: number;\n}\n\n/**\n * Options for the token fetcher\n */\nexport interface TokenFetcherOptions {\n /**\n * Jupiter API endpoint. Defaults to the strict list (verified tokens).\n * Use \"https://tokens.jup.ag/tokens?tags=verified\" for verified tokens\n * Use \"https://tokens.jup.ag/tokens\" for all tokens\n */\n jupiterApiUrl?: string;\n\n /**\n * Time-to-live for cached tokens in milliseconds.\n * Defaults to 5 minutes.\n */\n cacheTtlMs?: number;\n\n /**\n * Whether to fetch all tokens on initialization.\n * If false, tokens will be fetched on-demand.\n * Defaults to false.\n */\n prefetch?: boolean;\n}\n\nconst DEFAULT_JUPITER_API_URL = \"https://tokens.jup.ag/tokens?tags=verified\";\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetches and caches token metadata from Jupiter's token API.\n *\n * Usage:\n * ```ts\n * const fetcher = createTokenFetcher();\n * const token = await fetcher.getToken(\"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN\");\n * ```\n */\nexport interface TokenFetcher {\n /**\n * Get token info for a single mint address.\n * Returns from cache if available, otherwise fetches from Jupiter.\n * Falls back to static registry, then creates unknown token placeholder.\n */\n getToken(mint: string, decimals?: number): Promise<TokenInfo>;\n\n /**\n * Get token info for multiple mint addresses.\n * More efficient than calling getToken multiple times.\n */\n getTokens(\n mints: string[],\n defaultDecimals?: number,\n ): Promise<Map<string, TokenInfo>>;\n\n /**\n * Force refresh the token cache from Jupiter API.\n */\n refresh(): Promise<void>;\n\n /**\n * Get the number of tokens currently cached.\n */\n getCacheSize(): number;\n}\n\n/**\n * Creates a new token fetcher instance.\n */\nexport function createTokenFetcher(\n options: TokenFetcherOptions = {},\n): TokenFetcher {\n const {\n jupiterApiUrl = DEFAULT_JUPITER_API_URL,\n cacheTtlMs = DEFAULT_CACHE_TTL_MS,\n prefetch = false,\n } = options;\n\n // In-memory cache for Jupiter tokens\n const jupiterCache = new Map<string, TokenInfo>();\n let lastFetchTime = 0;\n let fetchPromise: Promise<void> | null = null;\n\n /**\n * Fetches all tokens from Jupiter API and populates the cache.\n */\n async function fetchJupiterTokens(): Promise<void> {\n // If already fetching, wait for that to complete\n if (fetchPromise) {\n return fetchPromise;\n }\n\n // If cache is still fresh, skip\n if (Date.now() - lastFetchTime < cacheTtlMs && jupiterCache.size > 0) {\n return;\n }\n\n fetchPromise = (async () => {\n try {\n const response = await fetch(jupiterApiUrl);\n\n if (!response.ok) {\n console.warn(\n `Jupiter API returned ${response.status}: ${response.statusText}`,\n );\n return;\n }\n\n const tokens = (await response.json()) as JupiterToken[];\n\n // Clear and repopulate cache\n jupiterCache.clear();\n\n for (const token of tokens) {\n jupiterCache.set(token.address, {\n mint: token.address,\n symbol: token.symbol,\n name: token.name,\n decimals: token.decimals,\n logoURI: token.logoURI,\n });\n }\n\n lastFetchTime = Date.now();\n } catch (error) {\n console.warn(\"Failed to fetch Jupiter tokens:\", error);\n // Keep existing cache on error\n } finally {\n fetchPromise = null;\n }\n })();\n\n return fetchPromise;\n }\n\n /**\n * Gets token info with fallback chain:\n * 1. Static registry (instant, always available)\n * 2. Jupiter cache (if populated)\n * 3. Jupiter API fetch (if cache miss and needed)\n * 4. Unknown token placeholder (last resort)\n */\n async function getToken(mint: string, decimals = 9): Promise<TokenInfo> {\n // 1. Check static registry first (most common tokens, always available)\n const staticToken = TOKEN_INFO[mint];\n if (staticToken) {\n return staticToken;\n }\n\n // 2. Check Jupiter cache\n const cachedToken = jupiterCache.get(mint);\n if (cachedToken) {\n return cachedToken;\n }\n\n // 3. Try to fetch from Jupiter if cache is empty or stale\n await fetchJupiterTokens();\n\n // 4. Check cache again after fetch\n const fetchedToken = jupiterCache.get(mint);\n if (fetchedToken) {\n return fetchedToken;\n }\n\n // 5. Return unknown token placeholder\n return createUnknownToken(mint, decimals);\n }\n\n /**\n * Gets multiple tokens efficiently.\n */\n async function getTokens(\n mints: string[],\n defaultDecimals = 9,\n ): Promise<Map<string, TokenInfo>> {\n const result = new Map<string, TokenInfo>();\n const missingMints: string[] = [];\n\n // First pass: check static registry and cache\n for (const mint of mints) {\n const staticToken = TOKEN_INFO[mint];\n if (staticToken) {\n result.set(mint, staticToken);\n continue;\n }\n\n const cachedToken = jupiterCache.get(mint);\n if (cachedToken) {\n result.set(mint, cachedToken);\n continue;\n }\n\n missingMints.push(mint);\n }\n\n // If we have missing tokens, try to fetch from Jupiter\n if (missingMints.length > 0) {\n await fetchJupiterTokens();\n\n // Second pass for missing tokens\n for (const mint of missingMints) {\n const fetchedToken = jupiterCache.get(mint);\n if (fetchedToken) {\n result.set(mint, fetchedToken);\n } else {\n result.set(mint, createUnknownToken(mint, defaultDecimals));\n }\n }\n }\n\n return result;\n }\n\n async function refresh(): Promise<void> {\n lastFetchTime = 0; // Force refresh\n await fetchJupiterTokens();\n }\n\n function getCacheSize(): number {\n return jupiterCache.size;\n }\n\n // Prefetch if requested\n if (prefetch) {\n fetchJupiterTokens().catch(() => {\n // Ignore prefetch errors\n });\n }\n\n return {\n getToken,\n getTokens,\n refresh,\n getCacheSize,\n };\n}\n\n/**\n * Singleton instance for convenience.\n * Use createTokenFetcher() if you need custom options.\n */\nlet defaultFetcher: TokenFetcher | null = null;\n\nexport function getDefaultTokenFetcher(): TokenFetcher {\n if (!defaultFetcher) {\n defaultFetcher = createTokenFetcher();\n }\n return defaultFetcher;\n}\n","export interface NftMetadata {\n mint: string;\n name: string;\n symbol: string;\n image: string;\n cdnImage?: string;\n description?: string;\n collection?: string;\n attributes?: Array<{ trait_type: string; value: string }>;\n}\n\ninterface DasAssetResponse {\n jsonrpc: string;\n result?: {\n id: string;\n content: {\n metadata: {\n name: string;\n symbol: string;\n description?: string;\n attributes?: Array<{ trait_type: string; value: string }>;\n };\n links: {\n image?: string;\n };\n files?: Array<{\n uri: string;\n cdn_uri?: string;\n mime: string;\n }>;\n };\n grouping?: Array<{\n group_key: string;\n group_value: string;\n }>;\n };\n error?: {\n code: number;\n message: string;\n };\n}\n\n/**\n * Fetches NFT metadata from Helius DAS API.\n *\n * @param rpcUrl - Helius RPC endpoint URL\n * @param mintAddress - NFT mint address\n * @returns NFT metadata including name, image, collection, and attributes, or null if not found\n */\nexport async function fetchNftMetadata(\n rpcUrl: string,\n mintAddress: string\n): Promise<NftMetadata | null> {\n const response = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: \"get-asset\",\n method: \"getAsset\",\n params: { id: mintAddress },\n }),\n });\n\n const data = (await response.json()) as DasAssetResponse;\n\n if (data.error || !data.result?.content?.metadata) {\n return null;\n }\n\n const { result } = data;\n const { content, grouping } = result;\n\n return {\n mint: mintAddress,\n name: content.metadata.name,\n symbol: content.metadata.symbol,\n image: content.links.image ?? content.files?.[0]?.uri ?? \"\",\n cdnImage: content.files?.[0]?.cdn_uri,\n description: content.metadata.description,\n collection: grouping?.find((g) => g.group_key === \"collection\")?.group_value,\n attributes: content.metadata.attributes,\n };\n}\n\n/**\n * Fetches NFT metadata for multiple mints in parallel.\n *\n * @param rpcUrl - Helius RPC endpoint URL\n * @param mintAddresses - Array of NFT mint addresses\n * @returns Map of mint address to NFT metadata (only includes successful fetches)\n */\nexport async function fetchNftMetadataBatch(\n rpcUrl: string,\n mintAddresses: string[]\n): Promise<Map<string, NftMetadata>> {\n const results = await Promise.all(\n mintAddresses.map((mint) => fetchNftMetadata(rpcUrl, mint))\n );\n\n const map = new Map<string, NftMetadata>();\n results.forEach((metadata, index) => {\n if (metadata) {\n map.set(mintAddresses[index]!, metadata);\n }\n });\n\n return map;\n}\n","import type { Address, Signature } from \"@solana/kit\";\nimport {\n createSolanaClient,\n parseSignature,\n type SolanaClient,\n} from \"@tx-indexer/solana/rpc/client\";\nimport { fetchWalletBalance } from \"@tx-indexer/solana/fetcher/balances\";\nimport {\n fetchWalletSignatures,\n fetchTransaction,\n fetchTransactionsBatch,\n} from \"@tx-indexer/solana/fetcher/transactions\";\n\nexport type { FetchTransactionsConfig } from \"@tx-indexer/solana/fetcher/transactions\";\nimport { transactionToLegs } from \"@tx-indexer/solana/mappers/transaction-to-legs\";\nimport { classifyTransaction } from \"@tx-indexer/classification/engine/classification-service\";\nimport { detectProtocol } from \"@tx-indexer/classification/protocols/detector\";\nimport {\n filterSpamTransactions,\n type SpamFilterConfig,\n} from \"@tx-indexer/core/tx/spam-filter\";\nimport type { WalletBalance } from \"@tx-indexer/solana/fetcher/balances\";\nimport type { RawTransaction, TxLeg } from \"@tx-indexer/core/tx/tx.types\";\nimport type { TransactionClassification } from \"@tx-indexer/core/tx/classification.types\";\nimport type {\n TokenInfo,\n MoneyAmount,\n} from \"@tx-indexer/core/money/money.types\";\nimport {\n createTokenFetcher,\n type TokenFetcher,\n} from \"@tx-indexer/core/money/token-fetcher\";\nimport {\n fetchNftMetadata,\n fetchNftMetadataBatch,\n type NftMetadata,\n} from \"./nft\";\n\nconst NFT_TRANSACTION_TYPES = [\"nft_mint\", \"nft_purchase\", \"nft_sale\"] as const;\n\n/**\n * Enriches token metadata in legs and classification using the token fetcher.\n * This replaces \"Unknown Token\" placeholders with actual token metadata from Jupiter.\n */\nasync function enrichTokenMetadata(\n tokenFetcher: TokenFetcher,\n classified: ClassifiedTransaction,\n): Promise<ClassifiedTransaction> {\n // Collect all unique mints from legs\n const mints = new Set<string>();\n const decimalsMap = new Map<string, number>();\n\n for (const leg of classified.legs) {\n const mint = leg.amount.token.mint;\n mints.add(mint);\n decimalsMap.set(mint, leg.amount.token.decimals);\n }\n\n // Also check classification amounts\n if (classified.classification.primaryAmount?.token.mint) {\n const mint = classified.classification.primaryAmount.token.mint;\n mints.add(mint);\n decimalsMap.set(\n mint,\n classified.classification.primaryAmount.token.decimals,\n );\n }\n if (classified.classification.secondaryAmount?.token.mint) {\n const mint = classified.classification.secondaryAmount.token.mint;\n mints.add(mint);\n decimalsMap.set(\n mint,\n classified.classification.secondaryAmount.token.decimals,\n );\n }\n\n if (mints.size === 0) {\n return classified;\n }\n\n // Fetch all token metadata\n const tokenInfoMap = await tokenFetcher.getTokens(\n Array.from(mints),\n 9, // default decimals\n );\n\n // Helper to enrich a MoneyAmount\n function enrichAmount(\n amount: MoneyAmount | null | undefined,\n ): MoneyAmount | null | undefined {\n if (!amount) return amount;\n\n const enrichedToken = tokenInfoMap.get(amount.token.mint);\n if (!enrichedToken || enrichedToken.symbol === amount.token.symbol) {\n return amount;\n }\n\n return {\n ...amount,\n token: {\n ...enrichedToken,\n // Keep the decimals from the original (from RPC) as they're authoritative\n decimals: amount.token.decimals,\n },\n };\n }\n\n // Helper to enrich a leg\n function enrichLeg(leg: TxLeg): TxLeg {\n const enrichedToken = tokenInfoMap.get(leg.amount.token.mint);\n if (!enrichedToken || enrichedToken.symbol === leg.amount.token.symbol) {\n return leg;\n }\n\n return {\n ...leg,\n amount: {\n ...leg.amount,\n token: {\n ...enrichedToken,\n decimals: leg.amount.token.decimals,\n },\n },\n };\n }\n\n // Enrich legs\n const enrichedLegs = classified.legs.map(enrichLeg);\n\n // Enrich classification amounts\n const enrichedClassification: TransactionClassification = {\n ...classified.classification,\n primaryAmount:\n enrichAmount(classified.classification.primaryAmount) ?? null,\n secondaryAmount: enrichAmount(classified.classification.secondaryAmount),\n };\n\n return {\n tx: classified.tx,\n legs: enrichedLegs,\n classification: enrichedClassification,\n };\n}\n\n/**\n * Enriches token metadata for a batch of transactions.\n */\nasync function enrichTokenMetadataBatch(\n tokenFetcher: TokenFetcher,\n transactions: ClassifiedTransaction[],\n): Promise<ClassifiedTransaction[]> {\n // Collect all unique mints across all transactions\n const mints = new Set<string>();\n\n for (const classified of transactions) {\n for (const leg of classified.legs) {\n mints.add(leg.amount.token.mint);\n }\n if (classified.classification.primaryAmount?.token.mint) {\n mints.add(classified.classification.primaryAmount.token.mint);\n }\n if (classified.classification.secondaryAmount?.token.mint) {\n mints.add(classified.classification.secondaryAmount.token.mint);\n }\n }\n\n if (mints.size === 0) {\n return transactions;\n }\n\n // Pre-fetch all tokens in one batch\n await tokenFetcher.getTokens(Array.from(mints));\n\n // Now enrich each transaction (will use cached data)\n return Promise.all(\n transactions.map((tx) => enrichTokenMetadata(tokenFetcher, tx)),\n );\n}\n\nasync function enrichNftClassification(\n rpcUrl: string,\n classified: ClassifiedTransaction,\n): Promise<ClassifiedTransaction> {\n const { classification } = classified;\n\n if (!NFT_TRANSACTION_TYPES.includes(classification.primaryType as any)) {\n return classified;\n }\n\n const nftMint = classification.metadata?.nft_mint as string | undefined;\n if (!nftMint) {\n return classified;\n }\n\n const nftData = await fetchNftMetadata(rpcUrl, nftMint);\n if (!nftData) {\n return classified;\n }\n\n return {\n ...classified,\n classification: {\n ...classification,\n metadata: {\n ...classification.metadata,\n nft_name: nftData.name,\n nft_image: nftData.image,\n nft_cdn_image: nftData.cdnImage,\n nft_collection: nftData.collection,\n nft_symbol: nftData.symbol,\n nft_attributes: nftData.attributes,\n },\n },\n };\n}\n\nexport type TxIndexerOptions =\n | {\n rpcUrl: string;\n wsUrl?: string;\n }\n | {\n client: SolanaClient;\n };\n\nexport interface GetTransactionsOptions {\n limit?: number;\n before?: Signature;\n until?: Signature;\n filterSpam?: boolean;\n spamConfig?: SpamFilterConfig;\n enrichNftMetadata?: boolean;\n /**\n * Enrich token metadata from Jupiter API.\n * Replaces \"Unknown Token\" placeholders with actual token names/symbols/logos.\n * Defaults to true.\n */\n enrichTokenMetadata?: boolean;\n}\n\nexport interface GetTransactionOptions {\n enrichNftMetadata?: boolean;\n /**\n * Enrich token metadata from Jupiter API.\n * Replaces \"Unknown Token\" placeholders with actual token names/symbols/logos.\n * Defaults to true.\n */\n enrichTokenMetadata?: boolean;\n}\n\nexport interface ClassifiedTransaction {\n tx: RawTransaction;\n classification: TransactionClassification;\n legs: ReturnType<typeof transactionToLegs>;\n}\n\nexport interface TxIndexer {\n rpc: ReturnType<typeof createSolanaClient>[\"rpc\"];\n\n getBalance(\n walletAddress: Address,\n tokenMints?: readonly string[],\n ): Promise<WalletBalance>;\n\n getTransactions(\n walletAddress: Address,\n options?: GetTransactionsOptions,\n ): Promise<ClassifiedTransaction[]>;\n\n getTransaction(\n signature: Signature,\n options?: GetTransactionOptions,\n ): Promise<ClassifiedTransaction | null>;\n\n getRawTransaction(signature: Signature): Promise<RawTransaction | null>;\n\n getNftMetadata(mintAddress: string): Promise<NftMetadata | null>;\n\n getNftMetadataBatch(\n mintAddresses: string[],\n ): Promise<Map<string, NftMetadata>>;\n}\n\nexport function createIndexer(options: TxIndexerOptions): TxIndexer {\n const rpcUrl = \"client\" in options ? \"\" : options.rpcUrl;\n const client =\n \"client\" in options\n ? options.client\n : createSolanaClient(options.rpcUrl, options.wsUrl);\n\n // Create a shared token fetcher for this indexer instance\n const tokenFetcher = createTokenFetcher();\n\n return {\n rpc: client.rpc,\n\n async getBalance(\n walletAddress: Address,\n tokenMints?: readonly string[],\n ): Promise<WalletBalance> {\n return fetchWalletBalance(client.rpc, walletAddress, tokenMints);\n },\n\n async getTransactions(\n walletAddress: Address,\n options: GetTransactionsOptions = {},\n ): Promise<ClassifiedTransaction[]> {\n const {\n limit = 10,\n before,\n until,\n filterSpam = true,\n spamConfig,\n enrichNftMetadata = true,\n enrichTokenMetadata: enrichTokens = true,\n } = options;\n\n async function enrichBatch(\n transactions: ClassifiedTransaction[],\n ): Promise<ClassifiedTransaction[]> {\n let result = transactions;\n\n // Enrich token metadata first\n if (enrichTokens) {\n result = await enrichTokenMetadataBatch(tokenFetcher, result);\n }\n\n // Then enrich NFT metadata\n if (enrichNftMetadata && rpcUrl) {\n const nftMints = result\n .filter((t) =>\n NFT_TRANSACTION_TYPES.includes(\n t.classification.primaryType as any,\n ),\n )\n .map((t) => t.classification.metadata?.nft_mint as string)\n .filter(Boolean);\n\n if (nftMints.length > 0) {\n const nftMetadataMap = await fetchNftMetadataBatch(\n rpcUrl,\n nftMints,\n );\n\n result = result.map((t) => {\n const nftMint = t.classification.metadata?.nft_mint as\n | string\n | undefined;\n if (!nftMint || !nftMetadataMap.has(nftMint)) {\n return t;\n }\n\n const nftData = nftMetadataMap.get(nftMint)!;\n return {\n ...t,\n classification: {\n ...t.classification,\n metadata: {\n ...t.classification.metadata,\n nft_name: nftData.name,\n nft_image: nftData.image,\n nft_cdn_image: nftData.cdnImage,\n nft_collection: nftData.collection,\n nft_symbol: nftData.symbol,\n nft_attributes: nftData.attributes,\n },\n },\n };\n });\n }\n }\n\n return result;\n }\n\n if (!filterSpam) {\n const signatures = await fetchWalletSignatures(\n client.rpc,\n walletAddress,\n {\n limit,\n before,\n until,\n },\n );\n\n if (signatures.length === 0) {\n return [];\n }\n\n const signatureObjects = signatures.map((sig) =>\n parseSignature(sig.signature),\n );\n const transactions = await fetchTransactionsBatch(\n client.rpc,\n signatureObjects,\n );\n\n const walletAddressStr = walletAddress.toString();\n const classified = transactions.map((tx) => {\n tx.protocol = detectProtocol(tx.programIds);\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(\n legs,\n tx,\n walletAddressStr,\n );\n return { tx, classification, legs };\n });\n\n return enrichBatch(classified);\n }\n\n const accumulated: ClassifiedTransaction[] = [];\n let currentBefore = before;\n const MAX_ITERATIONS = 10;\n let iteration = 0;\n const walletAddressStr = walletAddress.toString();\n\n while (accumulated.length < limit && iteration < MAX_ITERATIONS) {\n iteration++;\n\n const batchSize = iteration === 1 ? limit : limit * 2;\n\n const signatures = await fetchWalletSignatures(\n client.rpc,\n walletAddress,\n {\n limit: batchSize,\n before: currentBefore,\n until,\n },\n );\n\n if (signatures.length === 0) {\n break;\n }\n\n const signatureObjects = signatures.map((sig) =>\n parseSignature(sig.signature),\n );\n const transactions = await fetchTransactionsBatch(\n client.rpc,\n signatureObjects,\n );\n\n const classified = transactions.map((tx) => {\n tx.protocol = detectProtocol(tx.programIds);\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(\n legs,\n tx,\n walletAddressStr,\n );\n return { tx, classification, legs };\n });\n\n const nonSpam = filterSpamTransactions(classified, spamConfig);\n accumulated.push(...nonSpam);\n\n const lastSignature = signatures[signatures.length - 1];\n if (lastSignature) {\n currentBefore = parseSignature(lastSignature.signature);\n } else {\n break;\n }\n }\n\n const result = accumulated.slice(0, limit);\n return enrichBatch(result);\n },\n\n async getTransaction(\n signature: Signature,\n options: GetTransactionOptions = {},\n ): Promise<ClassifiedTransaction | null> {\n const {\n enrichNftMetadata = true,\n enrichTokenMetadata: enrichTokens = true,\n } = options;\n\n const tx = await fetchTransaction(client.rpc, signature);\n\n if (!tx) {\n return null;\n }\n\n tx.protocol = detectProtocol(tx.programIds);\n\n const legs = transactionToLegs(tx);\n const classification = classifyTransaction(legs, tx);\n\n let classified: ClassifiedTransaction = { tx, classification, legs };\n\n // Enrich token metadata\n if (enrichTokens) {\n classified = await enrichTokenMetadata(tokenFetcher, classified);\n }\n\n // Enrich NFT metadata\n if (enrichNftMetadata && rpcUrl) {\n classified = await enrichNftClassification(rpcUrl, classified);\n }\n\n return classified;\n },\n\n async getRawTransaction(\n signature: Signature,\n ): Promise<RawTransaction | null> {\n return fetchTransaction(client.rpc, signature);\n },\n\n async getNftMetadata(mintAddress: string): Promise<NftMetadata | null> {\n if (!rpcUrl) {\n throw new Error(\"getNftMetadata requires rpcUrl to be set\");\n }\n return fetchNftMetadata(rpcUrl, mintAddress);\n },\n\n async getNftMetadataBatch(\n mintAddresses: string[],\n ): Promise<Map<string, NftMetadata>> {\n if (!rpcUrl) {\n throw new Error(\"getNftMetadataBatch requires rpcUrl to be set\");\n }\n return fetchNftMetadataBatch(rpcUrl, mintAddresses);\n },\n };\n}\n"]}
|