hood-cli 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../node_modules/hoodchain/src/client.ts","../node_modules/hoodchain/src/addresses.ts","../node_modules/hoodchain/src/errors.ts","../node_modules/hoodchain/src/registry/stock-tokens.json","../node_modules/hoodchain/src/registry/index.ts","../node_modules/hoodchain/src/stocks.ts","../node_modules/hoodchain/src/abis.ts","../node_modules/hoodchain/src/swap.ts","../node_modules/hoodchain/src/usdg.ts","../node_modules/hoodchain/src/launchpads.ts","../node_modules/hoodchain/src/feed.ts"],"sourcesContent":["import {\n createPublicClient,\n createWalletClient,\n http,\n type Account,\n type Chain,\n type PublicClient,\n type Transport,\n type WalletClient,\n} from 'viem'\nimport { robinhood, robinhoodTestnet } from 'viem/chains'\n\n/** Network selector for {@link createHoodClient}. */\nexport type HoodNetwork = 'mainnet' | 'testnet'\n\n/** Configuration for {@link createHoodClient}. */\nexport interface HoodClientConfig {\n /**\n * Which Robinhood Chain network to target.\n * `'mainnet'` = chain 4663, `'testnet'` = chain 46630.\n * @defaultValue `'mainnet'`\n */\n chain?: HoodNetwork\n /**\n * Custom RPC URL (e.g. an Alchemy endpoint\n * `https://robinhood-mainnet.g.alchemy.com/v2/{key}`). Defaults to the\n * public RPC from viem's official chain definition.\n */\n rpcUrl?: string\n /** Fully custom viem transport. Takes precedence over `rpcUrl`. */\n transport?: Transport\n /**\n * Wallet account for write operations (swaps, transfers). Create one with\n * `privateKeyToAccount(process.env.ROBINHOOD_CHAIN_PRIVATE_KEY)` from\n * `viem/accounts`. Omit for read-only usage.\n */\n account?: Account\n /**\n * Stock Tokens are tokenized debt securities (issuer: Robinhood Assets\n * (Jersey) Ltd) and may not be offered, sold, or delivered to US persons\n * (additional limits: Canada, UK, Switzerland). Swaps that ACQUIRE a Stock\n * Token throw {@link StockTokenEligibilityError} until the operator sets\n * this flag to `true`, affirming they are eligible. Reads and sells are\n * never gated.\n * @defaultValue `false`\n */\n acknowledgeStockTokenEligibility?: boolean\n}\n\n/**\n * A connected hoodchain client: a viem public client (multicall batching on),\n * an optional wallet client, and the resolved chain.\n */\nexport interface HoodClient {\n /** The resolved viem chain object (`robinhood` or `robinhoodTestnet`). */\n chain: Chain\n /** Network name this client was created with. */\n network: HoodNetwork\n /** viem public client for reads. Multicall batching is enabled by default. */\n public: PublicClient\n /** viem wallet client for writes, or `null` when no account was provided. */\n wallet: WalletClient<Transport, Chain, Account> | null\n /** The wallet account, or `null` in read-only mode. */\n account: Account | null\n /** Whether the operator affirmed Stock Token acquisition eligibility. */\n acknowledgeStockTokenEligibility: boolean\n}\n\n/**\n * Create a hoodchain client.\n *\n * @example Read-only client on mainnet\n * ```ts\n * import { createHoodClient } from 'hoodchain'\n * const hood = createHoodClient()\n * const block = await hood.public.getBlockNumber()\n * ```\n *\n * @example Wallet client on testnet\n * ```ts\n * import { createHoodClient } from 'hoodchain'\n * import { privateKeyToAccount } from 'viem/accounts'\n * const hood = createHoodClient({\n * chain: 'testnet',\n * account: privateKeyToAccount(process.env.ROBINHOOD_CHAIN_PRIVATE_KEY as `0x${string}`),\n * })\n * ```\n */\nexport function createHoodClient(config: HoodClientConfig = {}): HoodClient {\n const network = config.chain ?? 'mainnet'\n const chain = network === 'testnet' ? robinhoodTestnet : robinhood\n const transport = config.transport ?? http(config.rpcUrl)\n\n const publicClient = createPublicClient({\n chain,\n transport,\n batch: { multicall: true },\n })\n\n const wallet = config.account\n ? createWalletClient({ chain, transport, account: config.account })\n : null\n\n return {\n chain,\n network,\n public: publicClient as PublicClient,\n wallet,\n account: config.account ?? null,\n acknowledgeStockTokenEligibility: config.acknowledgeStockTokenEligibility ?? false,\n }\n}\n","import type { Address } from 'viem'\n\n/**\n * Canonical contract addresses on Robinhood Chain mainnet (chain ID 4663).\n *\n * Every address was verified during SDK development:\n * - `usdg` / `weth` from https://docs.robinhood.com/chain/contracts, verified\n * as deployed + source-verified contracts on Blockscout.\n * - The Uniswap v3 stack was resolved on-chain: `SwapRouter02.factory()` and\n * `QuoterV2.factory()` both return `uniswapV3Factory`, and both routers\n * report `WETH9() == weth`. All five contracts were deployed by the same\n * deployer (`0x9701fb0aDe1E269c8f64Ec0C7b3cfADB31A13A52`) in the chain's\n * genesis-era Uniswap deployment and are the addresses the public\n * ecosystem (hood.markets and others) routes through.\n * - `multicall3` is the canonical cross-chain Multicall3, present in viem's\n * official `robinhood` chain definition.\n */\nexport const MAINNET_ADDRESSES = {\n /** USDG — Paxos Global Dollar, the chain's dollar stablecoin. 6 decimals. */\n usdg: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168' as Address,\n /** Canonical WETH9. */\n weth: '0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73' as Address,\n /** Uniswap v3 factory. */\n uniswapV3Factory: '0x1f7d7550B1b028f7571E69A784071F0205FD2EfA' as Address,\n /** Uniswap QuoterV2. */\n quoterV2: '0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7' as Address,\n /** Uniswap SwapRouter02. */\n swapRouter02: '0xCaf681a66D020601342297493863E78C959E5cb2' as Address,\n /** Uniswap UniversalRouter. */\n universalRouter: '0x53BF6B0684Ec7eF91e1387Da3D1a1769bC5A6F77' as Address,\n /** Uniswap NonfungiblePositionManager. */\n nonfungiblePositionManager: '0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3' as Address,\n /** Multicall3 (canonical deterministic deployment). */\n multicall3: '0xca11bde05977b3631167028862be2a173976ca11' as Address,\n} as const\n\n/**\n * Contract addresses on Robinhood Chain testnet (chain ID 46630).\n *\n * There is NO official Uniswap deployment on the testnet: none of the mainnet\n * addresses have code there (`eth_getCode` returns `0x` for all six) and the\n * mainnet Uniswap deployer has zero testnet transactions. The addresses below\n * are the one community v3 deployment that actually has a liquid Stock Token\n * pool, and its internal linkage was verified on-chain during SDK\n * development: `router.factory()`, `quoterV2.factory()`,\n * `positionManager.factory()` and the live pool's `factory()` all return\n * `uniswapV3Factory`, and `router.WETH9()` matches the chain's canonical\n * WETH (which is also the L2 WETH listed at\n * https://docs.robinhood.com/chain/protocol-contracts).\n *\n * NOTE the router flavor difference: testnet uses the classic v3\n * `SwapRouter` whose `exactInputSingle` struct carries a `deadline` field;\n * mainnet uses `SwapRouter02` (deadline via `multicall`). The swap module\n * handles both.\n *\n * Testnet Stock Tokens (faucet-dripped) and USDG were resolved from the\n * testnet Blockscout (https://explorer.testnet.chain.robinhood.com) —\n * canonical testnet tokens use plain company names, not the mainnet\n * \"<Name> • Robinhood Token\" pattern.\n */\nexport const TESTNET_ADDRESSES = {\n /** Testnet USDG (\"Global Dollar\", 6 decimals). */\n usdg: '0x7E955252E15c84f5768B83c41a71F9eba181802F' as Address,\n /** Canonical testnet WETH9 (matches the official protocol-contracts L2 WETH). */\n weth: '0x7943e237c7F95DA44E0301572D358911207852Fa' as Address,\n /** Community Uniswap v3 factory (the one with liquid Stock Token pools). */\n uniswapV3Factory: '0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865' as Address,\n /** QuoterV2 linked to the factory above. */\n quoterV2: '0xcf05Fc31A6B693DD0bEB76e958ae4BCD490dc985' as Address,\n /** Classic v3 SwapRouter (struct-level deadline) linked to the factory above. */\n swapRouter: '0x1b81D678ffb9C0263b24A97847620C99d213eB14' as Address,\n /** NonfungiblePositionManager linked to the factory above. */\n nonfungiblePositionManager: '0x46A15B0b27311cedF172AB29E4f4766fbE7F4364' as Address,\n /** Multicall3 (canonical deterministic deployment, in viem's chain def). */\n multicall3: '0xca11bde05977b3631167028862be2a173976ca11' as Address,\n} as const\n\n/**\n * Faucet-dripped Stock Tokens on testnet 46630 (18 decimals each). These are\n * plain test ERC-20s — the testnet does not mirror the mainnet registry.\n */\nexport const TESTNET_STOCK_TOKENS = {\n TSLA: '0xC9f9c86933092BbbfFF3CCb4b105A4A94bf3Bd4E' as Address,\n AMZN: '0x5884aD2f920c162CFBbACc88C9C51AA75eC09E02' as Address,\n PLTR: '0x1FBE1a0e43594b3455993B5dE5Fd0A7A266298d0' as Address,\n NFLX: '0x3b8262A63d25f0477c4DDE23F83cfe22Cb768C93' as Address,\n AMD: '0x71178BAc73cBeb415514eB542a8995b82669778d' as Address,\n} as const\n\n/** Sequencer firehose WebSocket endpoint (mainnet). */\nexport const MAINNET_FEED_URL = 'wss://feed.mainnet.chain.robinhood.com'\n\n/** Blockscout explorer base URL (mainnet). */\nexport const MAINNET_EXPLORER_URL = 'https://robinhoodchain.blockscout.com'\n\n/** USDG has 6 decimals (verified on-chain — unlike most L2-native stables' 18). */\nexport const USDG_DECIMALS = 6\n\n/** Every canonical Stock Token uses 18 decimals. */\nexport const STOCK_TOKEN_DECIMALS = 18\n\n/** Chainlink stock/crypto feeds on Robinhood Chain answer with 8 decimals. */\nexport const FEED_DECIMALS = 8\n\n/** Fee tiers probed when discovering Uniswap v3 routes. */\nexport const V3_FEE_TIERS = [100, 500, 3000, 10000] as const\n","/**\n * Typed error hierarchy for hoodchain.\n *\n * Every error thrown by this SDK is an instance of {@link HoodchainError}, so\n * consumers can catch SDK failures with a single `instanceof` check and then\n * narrow on the specific subclass.\n */\n\n/** Base class for every error thrown by hoodchain. */\nexport class HoodchainError extends Error {\n override name = 'HoodchainError'\n}\n\n/** Thrown when a symbol is not present in the Stock Token registry. */\nexport class UnknownSymbolError extends HoodchainError {\n override name = 'UnknownSymbolError'\n /** The symbol that failed to resolve. */\n readonly symbol: string\n\n constructor(symbol: string) {\n super(\n `Unknown Stock Token symbol \"${symbol}\". ` +\n `Symbols are case-insensitive tickers as listed on-chain (e.g. \"AAPL\", \"TSLA\"). ` +\n `Call listStockTokens() to enumerate the registry.`,\n )\n this.symbol = symbol\n }\n}\n\n/**\n * Thrown when a Stock Token exists in the registry but has no live Chainlink\n * price feed. 95 canonical Stock Tokens exist on-chain, but Chainlink's\n * public directory currently lists feeds for a subset of them.\n */\nexport class FeedNotFoundError extends HoodchainError {\n override name = 'FeedNotFoundError'\n readonly symbol: string\n\n constructor(symbol: string) {\n super(\n `Stock Token \"${symbol}\" has no Chainlink price feed in the registry. ` +\n `Its balance can still be read, but it cannot be priced on-chain.`,\n )\n this.symbol = symbol\n }\n}\n\n/**\n * Thrown when a Chainlink feed's `updatedAt` is older than the configured\n * `maxAgeSeconds`. Stock feeds update 24/5 (market hours), so weekend reads\n * are expected to be up to ~65h old — the default staleness window accounts\n * for this.\n */\nexport class StaleFeedError extends HoodchainError {\n override name = 'StaleFeedError'\n readonly symbol: string\n /** Feed timestamp, seconds since epoch. */\n readonly updatedAt: number\n /** Age of the answer in seconds at read time. */\n readonly ageSeconds: number\n /** The staleness window that was exceeded. */\n readonly maxAgeSeconds: number\n\n constructor(symbol: string, updatedAt: number, ageSeconds: number, maxAgeSeconds: number) {\n super(\n `Chainlink feed for \"${symbol}\" is stale: answer is ${ageSeconds}s old ` +\n `(updatedAt ${new Date(updatedAt * 1000).toISOString()}), ` +\n `allowed max is ${maxAgeSeconds}s. Stock feeds pause outside market hours (24/5); ` +\n `pass a larger maxAgeSeconds if weekend/holiday reads are acceptable.`,\n )\n this.symbol = symbol\n this.updatedAt = updatedAt\n this.ageSeconds = ageSeconds\n this.maxAgeSeconds = maxAgeSeconds\n }\n}\n\n/** Thrown when a Chainlink feed returns a non-positive or incomplete answer. */\nexport class InvalidFeedAnswerError extends HoodchainError {\n override name = 'InvalidFeedAnswerError'\n readonly symbol: string\n\n constructor(symbol: string, detail: string) {\n super(`Chainlink feed for \"${symbol}\" returned an invalid answer: ${detail}`)\n this.symbol = symbol\n }\n}\n\n/**\n * Thrown when no Uniswap v3 route with usable liquidity exists between two\n * tokens. Many Stock Token pools exist but hold zero liquidity — a quote\n * against them reverts inside the pool, which surfaces as this error.\n */\nexport class NoRouteError extends HoodchainError {\n override name = 'NoRouteError'\n readonly tokenIn: string\n readonly tokenOut: string\n\n constructor(tokenIn: string, tokenOut: string, detail?: string) {\n super(\n `No swappable Uniswap v3 route from ${tokenIn} to ${tokenOut}` +\n (detail ? `: ${detail}` : '.') +\n ` Pools may exist without liquidity; try a different intermediate or amount.`,\n )\n this.tokenIn = tokenIn\n this.tokenOut = tokenOut\n }\n}\n\n/** Thrown when a swap's quoted output falls below the slippage-adjusted minimum. */\nexport class SlippageExceededError extends HoodchainError {\n override name = 'SlippageExceededError'\n\n constructor(detail: string) {\n super(`Slippage bound exceeded: ${detail}`)\n }\n}\n\n/**\n * Thrown when an operation requires a wallet but the client was created\n * without an account.\n */\nexport class NoAccountError extends HoodchainError {\n override name = 'NoAccountError'\n\n constructor(operation: string) {\n super(\n `${operation} requires a wallet. Pass an \\`account\\` to createHoodClient ` +\n `(e.g. privateKeyToAccount(process.env.ROBINHOOD_CHAIN_PRIVATE_KEY)).`,\n )\n }\n}\n\n/**\n * Thrown when Stock Token acquisition is attempted without the operator\n * affirming eligibility. Stock Tokens are tokenized debt securities issued by\n * Robinhood Assets (Jersey) Ltd and may not be offered, sold, or delivered to\n * US persons (additional limits apply in Canada, the UK, and Switzerland).\n * The restriction is legal, not contract-level; this SDK ships with Stock\n * Token acquisition disabled until `acknowledgeStockTokenEligibility: true`\n * is set on the client config.\n */\nexport class StockTokenEligibilityError extends HoodchainError {\n override name = 'StockTokenEligibilityError'\n\n constructor() {\n super(\n 'Refusing to build a swap that acquires a Stock Token: eligibility not acknowledged. ' +\n 'Stock Tokens may not be offered, sold, or delivered to US persons ' +\n '(issuer: Robinhood Assets (Jersey) Ltd; extra limits: Canada, UK, Switzerland). ' +\n 'If the operator of this software is eligible, set ' +\n '`acknowledgeStockTokenEligibility: true` in createHoodClient config.',\n )\n }\n}\n\n/** Thrown when the sequencer feed client exhausts its reconnect budget. */\nexport class FeedConnectionError extends HoodchainError {\n override name = 'FeedConnectionError'\n\n constructor(url: string, attempts: number, lastError?: string) {\n super(\n `Sequencer feed connection to ${url} failed after ${attempts} attempts` +\n (lastError ? `: ${lastError}` : '.'),\n )\n }\n}\n","{\n \"$schema\": \"./stock-tokens.schema.json\",\n \"chainId\": 4663,\n \"generatedAtBlock\": 7690522,\n \"sources\": {\n \"discovery\": \"https://robinhoodchain.blockscout.com/api/v2/tokens?q=Robinhood Token (canonical name pattern \\\"<Name> • Robinhood Token\\\")\",\n \"feeds\": \"https://reference-data-directory.vercel.app/feeds-robinhood-mainnet.json\",\n \"verification\": \"on-chain via public RPC: shared beacon slot, symbol/name/decimals/uiMultiplier multicall, feed latestRoundData\"\n },\n \"stockBeacon\": \"0xe10b6f6B275de231345c20D14Ab812db62151b00\",\n \"tokenCount\": 95,\n \"feedCount\": 34,\n \"tokens\": [\n {\n \"address\": \"0x521Cf887E6531c6F667b5BC4D896E5d9bfE8EB2E\",\n \"symbol\": \"AAOI\",\n \"name\": \"Applied Optoelectronics • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9\",\n \"symbol\": \"AAPL\",\n \"name\": \"Apple • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x6B22A786bAa607d76728168703a39Ea9C99f2cD0\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"31550000000\",\n \"feedUpdatedAtGeneration\": 1783710274\n },\n {\n \"address\": \"0x36046893810a7E7fCE501229d57dc3FC8c8716d0\",\n \"symbol\": \"AMAT\",\n \"name\": \"Applied Materials • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x86923f96303D656E4aa86D9d42D1e57ad2023fdC\",\n \"symbol\": \"AMD\",\n \"name\": \"AMD • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x943A29E7ae51A4798823ca9eEd2ed533B2A22C72\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"55821015000\",\n \"feedUpdatedAtGeneration\": 1783713346\n },\n {\n \"address\": \"0x12f190a9F9d7D37a250758b26824B97CE941bF54\",\n \"symbol\": \"AMZN\",\n \"name\": \"Amazon • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xD5a1508ceD74c084eBf3cBe853e2C968fB2a651C\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"24556770000\",\n \"feedUpdatedAtGeneration\": 1783692103\n },\n {\n \"address\": \"0xb8DBf92F9741c9ac1c32115E78581f23509916FD\",\n \"symbol\": \"APLD\",\n \"name\": \"Applied Digital • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x47F93d52cBeC7C6D2CfC080e154002370a60dAEA\",\n \"symbol\": \"ASML\",\n \"name\": \"ASML Holding NV • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xB4106147E8cce40b7d46124090d373A71b70f87D\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"179758755000\",\n \"feedUpdatedAtGeneration\": 1783710661\n },\n {\n \"address\": \"0x1AF6446f07eb1d97c546AFC8c9544cBDF3AD5137\",\n \"symbol\": \"ASTS\",\n \"name\": \"AST SpaceMobile • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x156E175DD063a8cE274C50654eF40e0032b3fbcF\",\n \"symbol\": \"AVGO\",\n \"name\": \"Broadcom • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x4D21483a44Bf67a86b77E3dA301411880797D452\",\n \"symbol\": \"BA\",\n \"name\": \"Boeing • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xad25Ac6C84D497db898fa1E8387bf6Af3532a1c4\",\n \"symbol\": \"BABA\",\n \"name\": \"Alibaba • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x62Cc8F9b5f56a33c9C8A60c8B92779f523c4E984\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"11219500000\",\n \"feedUpdatedAtGeneration\": 1783707523\n },\n {\n \"address\": \"0x822CC93fFD030293E9842c30BBD678F530701867\",\n \"symbol\": \"BE\",\n \"name\": \"Bloom Energy • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x5c90450Bbb4273D7b2f17CF6917AEB237A569679\",\n \"symbol\": \"CBRS\",\n \"name\": \"Cerebras Systems • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x9651342CeA770aE9a2969Ba2A52611523146aef9\",\n \"symbol\": \"CCL\",\n \"name\": \"Carnival Corporation • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x8cF07C5A878945185d327aAa6e33FAa95F95e7bF\",\n \"symbol\": \"CELH\",\n \"name\": \"Celsius • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xcBB95BBF36099d34dA091dc6Fa6F49EfA257Cee3\",\n \"symbol\": \"CLSK\",\n \"name\": \"CleanSpark • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x810c12D3a554Bc47fd39597Fe3b3AAC4941F50eF\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"1286499999\",\n \"feedUpdatedAtGeneration\": 1783713313\n },\n {\n \"address\": \"0x6330D8C3178a418788dF01a47479c0ce7CCF450b\",\n \"symbol\": \"COIN\",\n \"name\": \"Coinbase • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xA3a468A452940B7D6b69991207B508c609a98Ef2\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"15943135000\",\n \"feedUpdatedAtGeneration\": 1783703473\n },\n {\n \"address\": \"0x4EA005168D7F09a7A0Ba9D1DEf21a479950E44C2\",\n \"symbol\": \"COST\",\n \"name\": \"Costco • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xdF0992E440dD0be65BD8439b609d6D4366bf1CB5\",\n \"symbol\": \"CRCL\",\n \"name\": \"Circle Internet Group • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x6652eDf64bA3731C4F2D3ce821A0Fb1f1f6b482a\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"6634635000\",\n \"feedUpdatedAtGeneration\": 1783717360\n },\n {\n \"address\": \"0x5f10A1C971B69e47e059e1dC91901B59b3fB49C3\",\n \"symbol\": \"CRWV\",\n \"name\": \"CoreWeave • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xe1b3aABCAFAd1c94708dc1367dcfF8Aa4407487C\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"8883970000\",\n \"feedUpdatedAtGeneration\": 1783711393\n },\n {\n \"address\": \"0x27c99fBde9D0d2AA4f4Bfb4943f237843DdF6958\",\n \"symbol\": \"DDOG\",\n \"name\": \"Datadog • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x941AE714EC6D8130c7B75d67160Ca08f1e7d11Dd\",\n \"symbol\": \"DELL\",\n \"name\": \"Dell • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x39EC44Bee4F6A116c6F9B8De566848a985C53C60\",\n \"symbol\": \"ELF\",\n \"name\": \"e.l.f. Beauty • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x7f0aBeF0C07280F82c6a08ead09dEd6BAE2C13Fc\",\n \"symbol\": \"EWY\",\n \"name\": \"iShares MSCI South Korea fund • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xEFdf54610B62A7753Ec30bDc380847c12D32e1D1\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"18377499999\",\n \"feedUpdatedAtGeneration\": 1783705547\n },\n {\n \"address\": \"0x25C288E6D899b9BC30160965aD9644c67e73bE0C\",\n \"symbol\": \"F\",\n \"name\": \"Ford Motor • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x282e87451E10fA6679BC7D76C69BE44cD3fC777C\",\n \"symbol\": \"FLNC\",\n \"name\": \"Fluence Energy • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xeB30663bDFf0622Ef4e4E5cBb4E975F19f33f51D\",\n \"symbol\": \"FUTU\",\n \"name\": \"Futu Holdings • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x7c04E6A3368F2A1DE3874f0e80d2e0A1a9915da6\",\n \"symbol\": \"GLW\",\n \"name\": \"Corning • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x1b0E319c6A659F002271B69dB8A7df2F911c153E\",\n \"symbol\": \"GME\",\n \"name\": \"GameStop • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x27C71df6A64fB476468EdF256CF72c038baB5B67\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"2176125000\",\n \"feedUpdatedAtGeneration\": 1783694006\n },\n {\n \"address\": \"0x2e0847E8910a9732eB3fb1bb4b70a580ADAD4FE3\",\n \"symbol\": \"GOOGL\",\n \"name\": \"Alphabet Class A • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xF6f373a037c30F0e5010d854385cA89185AE638b\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"35672000000\",\n \"feedUpdatedAtGeneration\": 1783711606\n },\n {\n \"address\": \"0xf1953DAB6FaD537488d5A022361FfAa8B4c95eC6\",\n \"symbol\": \"INOD\",\n \"name\": \"Innodata • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xc72b96e0E48ecd4DC75E1e45396e26300BC39681\",\n \"symbol\": \"INTC\",\n \"name\": \"Intel • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x3f390C5C24628Ac7C489515402235FeAD71D1913\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"10965095000\",\n \"feedUpdatedAtGeneration\": 1783712771\n },\n {\n \"address\": \"0x56d23beE5f41A7120170b0c603Dae30128e460e9\",\n \"symbol\": \"INTU\",\n \"name\": \"Intuit • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x558378E000D634A36593E338eBacdd6207640EfE\",\n \"symbol\": \"IONQ\",\n \"name\": \"IonQ • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x22EfeC4919baf55F360E0EDee4AbEB26DE4971eb\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"4308000000\",\n \"feedUpdatedAtGeneration\": 1783711226\n },\n {\n \"address\": \"0xF0AB0c93bE6F41369d302e55db1A96b3c430212D\",\n \"symbol\": \"IREN\",\n \"name\": \"IREN Limited • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x8eF20885F94e3D9bc7eB3080279188Bd5ED7c08C\",\n \"symbol\": \"LITE\",\n \"name\": \"Lumentum • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x8005d266423c7ea827372c9c864491e5786600ea\",\n \"symbol\": \"LLY\",\n \"name\": \"Eli Lilly • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x4e62068525Ab11FE768e29dfD00ef909B9803016\",\n \"symbol\": \"LULU\",\n \"name\": \"Lululemon • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xa5D4968421bA94814Be3B136b15cf422101aC1a3\",\n \"symbol\": \"LUNR\",\n \"name\": \"Intuitive Machines • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xDdf2266b79abf0B48898959B0ed6E6adf512be74\",\n \"symbol\": \"MDB\",\n \"name\": \"MongoDB • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xc0D6457C16Cc70d6790Dd43521C899C87ce02f35\",\n \"symbol\": \"META\",\n \"name\": \"Meta Platforms • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x7C38C00C30BEe9378381E7B6135d7283356D71b1\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"67067485000\",\n \"feedUpdatedAtGeneration\": 1783713401\n },\n {\n \"address\": \"0x62fd0668e10D8B72339BE2DCF7643001688ff13B\",\n \"symbol\": \"MRVL\",\n \"name\": \"Marvell Technology • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xe93237C50D904957Cf27E7B1133b510C669c2e74\",\n \"symbol\": \"MSFT\",\n \"name\": \"Microsoft • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x45C3C877C15E6BA2EBB19eA114Ea508d14C1Af2E\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"38469000000\",\n \"feedUpdatedAtGeneration\": 1783697881\n },\n {\n \"address\": \"0xec262a75e413fAfD0dF80480274532C79D42da09\",\n \"symbol\": \"MSTR\",\n \"name\": \"Strategy Inc. • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x396118bdFB181e6240E74D243F266B061c0edc3D\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"9469500000\",\n \"feedUpdatedAtGeneration\": 1783712395\n },\n {\n \"address\": \"0xfF080c8ce2E5feadaCa0Da81314Ae59D232d4afD\",\n \"symbol\": \"MU\",\n \"name\": \"Micron Technology • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x425EEFdCf05ed6526C3cE61Af99429A228a6d596\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"97854340000\",\n \"feedUpdatedAtGeneration\": 1783713684\n },\n {\n \"address\": \"0x48961813349333209994750ffA89b3c5C22eC969\",\n \"symbol\": \"MXL\",\n \"name\": \"MaxLinear • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x9D9c6684F596F66a64C030B93A886D51Fd4D7931\",\n \"symbol\": \"NBIS\",\n \"name\": \"Nebius Group • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xE1D87B116Ba0fe898998f1D140339D1fA1E09705\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"21923750000\",\n \"feedUpdatedAtGeneration\": 1783713491\n },\n {\n \"address\": \"0xE0444EF8BF4eD74f74FD73686e2ddF4C1c5591E8\",\n \"symbol\": \"NFLX\",\n \"name\": \"Netflix • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xBEF75684C43c4ea7BD18Dd532a2244674Ee8b926\",\n \"symbol\": \"NNE\",\n \"name\": \"Nano Nuclear Energy • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x0C3260aF4B8f13a69c4c2dFb84fD667890CDFa14\",\n \"symbol\": \"NOW\",\n \"name\": \"ServiceNow • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x408c14038a04f7bD235329E26d2bf569ee20e250\",\n \"symbol\": \"NU\",\n \"name\": \"Nu • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC\",\n \"symbol\": \"NVDA\",\n \"name\": \"NVIDIA • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x379EC4f7C378F34a1B47E4F3cbeBCbAC3E8E9F15\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"21019000000\",\n \"feedUpdatedAtGeneration\": 1783700623\n },\n {\n \"address\": \"0xbE6702d7b70315376dC48a3293f24f0982F86386\",\n \"symbol\": \"NVTS\",\n \"name\": \"Navitas Semiconductor • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xb0992820E760d836549ba69BC7598b4af75dEE03\",\n \"symbol\": \"ORCL\",\n \"name\": \"Oracle • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x0e6a64a2B58A6693a531E6c555f3A5d042eEA844\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"14108370000\",\n \"feedUpdatedAtGeneration\": 1783709137\n },\n {\n \"address\": \"0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D\",\n \"symbol\": \"P\",\n \"name\": \"Everpure • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x9b23573b156B52565012F5cE02CDF60AFBaa70Be\",\n \"symbol\": \"PENG\",\n \"name\": \"Penguin Solutions • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x894E1EC2D74FFE5AEF8Dc8A9e84686acCB964F2A\",\n \"symbol\": \"PLTR\",\n \"name\": \"Palantir Technologies • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x820ABedFF239034956B7A9d2F0a331f9F075eB4c\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"12656140000\",\n \"feedUpdatedAtGeneration\": 1783714557\n },\n {\n \"address\": \"0xcf6B2D875361be807EAfa57458c80f28521F9333\",\n \"symbol\": \"POET\",\n \"name\": \"POET Technologies • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x4189F0c66EBBB0bfeF1C31f763131361EF32f77C\",\n \"symbol\": \"PR\",\n \"name\": \"Permian Resources • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xC583c60aeF9Dc401Da72cEC1B404743a93cea1Cc\",\n \"symbol\": \"QBTS\",\n \"name\": \"D-Wave Quantum • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x0f17206447090e464C277571124dD2688E48AEA9\",\n \"symbol\": \"QCOM\",\n \"name\": \"Qualcomm • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xD5f3879160bc7c32ebb4dC785F8a4F505888de68\",\n \"symbol\": \"QQQ\",\n \"name\": \"Invesco QQQ • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x80901d846d5D7B030F26B480776EE3b29374C2ae\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"72545060000\",\n \"feedUpdatedAtGeneration\": 1783702260\n },\n {\n \"address\": \"0x59818904ab4cE163b3cE4FfB64f2D6Ca02c434B4\",\n \"symbol\": \"QUBT\",\n \"name\": \"Quantum Computing • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xF0C4BF4C582cb3836e98394b1d4e7B7281101bE8\",\n \"symbol\": \"RBLX\",\n \"name\": \"Roblox • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x05b37Fb53A299a1b874A619e1c4C404D52C36F4C\",\n \"symbol\": \"RDDT\",\n \"name\": \"Reddit • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x92Ef19E82bD8fF36661DE838D5eaE7e5CEF0EfFE\",\n \"symbol\": \"RDW\",\n \"name\": \"Redwire • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x284358abc07F9359f19f4b5b4aC91901Be2597Ba\",\n \"symbol\": \"RGTI\",\n \"name\": \"Rigetti Computing • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x2A045cF1C49c61c166C036d2f06FA2D2d984f765\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"1657150813\",\n \"feedUpdatedAtGeneration\": 1783713654\n },\n {\n \"address\": \"0xB1BF26c1D20ff267A4f93550d1E0d06ac40a114B\",\n \"symbol\": \"RIVN\",\n \"name\": \"Rivian Automotive • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x3b14C39E89D60D627b42a1A4CA45b5bb45Fc12e2\",\n \"symbol\": \"RKLB\",\n \"name\": \"Rocket Lab Corporation • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x045477BF65Aef6f4F2386ad0164579e48381CC74\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"8128970000\",\n \"feedUpdatedAtGeneration\": 1783726597\n },\n {\n \"address\": \"0x95052ddcd5DC25641657424A8Cf04834997E1730\",\n \"symbol\": \"SATS\",\n \"name\": \"EchoStar • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x92FD66527192E3e61d4DDd13322Aa222DE86F9B5\",\n \"symbol\": \"SGOV\",\n \"name\": \"iShares 0-3 Month Treasury Bond • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000957519890990718\",\n \"feed\": \"0xa0DF4ee0fFf975306345875E3548Fcc519577A11\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"10060428845\",\n \"feedUpdatedAtGeneration\": 1783728100\n },\n {\n \"address\": \"0xF53F66751B1Eff985311b693531E3290F600c410\",\n \"symbol\": \"SHOP\",\n \"name\": \"Shopify • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x411eFb0E7f985935DAec3D4C3ebaEa0d0AD7D89f\",\n \"symbol\": \"SLV\",\n \"name\": \"iShares Silver Trust • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x209b73908e92Ae021826eD79609845451Ecba2ce\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"5416490000\",\n \"feedUpdatedAtGeneration\": 1783719808\n },\n {\n \"address\": \"0xc01aA1fECeC0605b13bc84874ff7256C0f5F562a\",\n \"symbol\": \"SMCI\",\n \"name\": \"Super Micro Computer • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xB90A19fF0Af67f7779afF50A882A9CfF42446400\",\n \"symbol\": \"SNDK\",\n \"name\": \"Sandisk Corporation • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xfb133Fa4B7b385802B693a293606682Df47109A3\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"193162665000\",\n \"feedUpdatedAtGeneration\": 1783727430\n },\n {\n \"address\": \"0x98E75885157C80992A8D41b696D8c9C6Fb30A926\",\n \"symbol\": \"SOFI\",\n \"name\": \"SoFi Technologies • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x75742c18BC1f1C5c5f448f4C9D9C6F66dafAAa38\",\n \"symbol\": \"SOXX\",\n \"name\": \"iShares Semiconductor ETF • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x4a0E65A3EcceC6dBe60AE065F2e7bb85Fae35eEa\",\n \"symbol\": \"SPCX\",\n \"name\": \"Space Exploration Technologies Corp. Class A Common Stock • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xB265810950ba6c5C0Ff821c9963014a56fD8Bffb\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"14572500000\",\n \"feedUpdatedAtGeneration\": 1783713430\n },\n {\n \"address\": \"0xAd622320e520de39e72d41EF07438C3Fd3354875\",\n \"symbol\": \"SPMO\",\n \"name\": \"Invesco S&P 500 Momentum ETF • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x117cc2133c37B721F49dE2A7a74833232B3B4C0C\",\n \"symbol\": \"SPY\",\n \"name\": \"SPDR S&P 500 ETF Trust • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x319724394D3A0e3669269846abE664Cd621f9f6A\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"75361500000\",\n \"feedUpdatedAtGeneration\": 1783700203\n },\n {\n \"address\": \"0x89776d4Cd68193597A2fC132cfaC1fDe36CCeA8a\",\n \"symbol\": \"TSEM\",\n \"name\": \"Tower Semiconductor • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x322F0929c4625eD5bAd873c95208D54E1c003b2d\",\n \"symbol\": \"TSLA\",\n \"name\": \"Tesla • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x4A1166a659A55625345e9515b32adECea5547C38\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"40782500000\",\n \"feedUpdatedAtGeneration\": 1783713215\n },\n {\n \"address\": \"0x58FfE4a942d3885bAa22D7520691F611EF09e7AA\",\n \"symbol\": \"TSM\",\n \"name\": \"Taiwan Semiconductor Manufacturing • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x874cF94aa8eC88Fd9560094dD065f2fB3E41Fc2F\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"43437150000\",\n \"feedUpdatedAtGeneration\": 1783713983\n },\n {\n \"address\": \"0x5e81213613b6B86EaB4c6c50d718d34359459786\",\n \"symbol\": \"TTWO\",\n \"name\": \"Take-Two Interactive Software • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x0E6e67Ba88e7b5d9B67636A215c76779B948dE79\",\n \"symbol\": \"UMC\",\n \"name\": \"United Microelectronics • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xf23250dac154D05Bb671CB0d0eBEf3c635c79CE2\",\n \"symbol\": \"UPS\",\n \"name\": \"UPS • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xd917B029C761D264c6A312BBbcDA868658eF86a6\",\n \"symbol\": \"USAR\",\n \"name\": \"USA Rare Earth • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0xA994d3684e8400A6c8078226925779FdeE682DD9\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"1853505000\",\n \"feedUpdatedAtGeneration\": 1783709442\n },\n {\n \"address\": \"0xa30FA36Db767ad9eD3f7a60fC79526fB4d56D344\",\n \"symbol\": \"USO\",\n \"name\": \"United States Oil Fund • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": \"0x75a9c76Ef439e2C7c2E5a34Ab105EcFe3766431c\",\n \"feedDecimals\": 8,\n \"feedAnswerAtGeneration\": \"10868500000\",\n \"feedUpdatedAtGeneration\": 1783708312\n },\n {\n \"address\": \"0x82DA4646242e1D962e96e932269Dc644c94a9CaA\",\n \"symbol\": \"WDAY\",\n \"name\": \"Workday • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xc93a8c440CEa26D7445dF01729f193b27965099f\",\n \"symbol\": \"WEEK\",\n \"name\": \"Roundhill Weekly T-Bill ETF • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"2006182524271844660\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x15Cd20759CE7F3285c29A319dE2D1A2e098c6f43\",\n \"symbol\": \"XLK\",\n \"name\": \"State Street Technology Select Sector SPDR ETF • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xA8eB3BCcbf2017eE7CBfb652eB51CF2E1B153289\",\n \"symbol\": \"XNDU\",\n \"name\": \"Xanadu Quantum • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0xf9B46d3D1B22199D4D1025a9cEDB540A33F1a2d5\",\n \"symbol\": \"XOM\",\n \"name\": \"ExxonMobil Holdings Corporation • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x44c4F142009036cF477eD2d09932051843137CF1\",\n \"symbol\": \"ZM\",\n \"name\": \"Zoom • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n },\n {\n \"address\": \"0x7dc013eB55e436f30d7ED1AFE4E36d6e45e3c3f7\",\n \"symbol\": \"ZS\",\n \"name\": \"Zscaler • Robinhood Token\",\n \"decimals\": 18,\n \"uiMultiplierAtGeneration\": \"1000000000000000000\",\n \"feed\": null,\n \"feedDecimals\": null\n }\n ]\n}\n","import type { Address } from 'viem'\nimport { UnknownSymbolError } from '../errors.js'\nimport registryJson from './stock-tokens.json' with { type: 'json' }\n\n/** One canonical Stock Token registry entry. */\nexport interface StockToken {\n /** Checksummed token contract address on chain 4663. */\n address: Address\n /** On-chain ticker, e.g. `\"TSLA\"`. The on-chain symbol is the source of truth. */\n symbol: string\n /** On-chain name, e.g. `\"Tesla • Robinhood Token\"`. */\n name: string\n /** Token decimals (18 for every canonical Stock Token). */\n decimals: number\n /**\n * Chainlink feed proxy for this token, or `null` when Chainlink's public\n * directory lists no feed for it. Feed answers are already\n * multiplier-adjusted (price of one TOKEN, not one share).\n */\n feed: Address | null\n /** Feed answer decimals (8), or `null` when there is no feed. */\n feedDecimals: number | null\n /** `uiMultiplier()` snapshot taken when the registry was generated (1e18-scaled string). */\n uiMultiplierAtGeneration: string\n}\n\n/** Registry metadata: where the data came from and how it was verified. */\nexport interface StockTokenRegistry {\n chainId: number\n generatedAtBlock: number\n /** The shared EIP-1967 beacon behind every canonical Stock Token proxy. */\n stockBeacon: Address\n tokenCount: number\n feedCount: number\n tokens: StockToken[]\n}\n\nconst registry = registryJson as unknown as StockTokenRegistry\n\nconst bySymbol = new Map<string, StockToken>(registry.tokens.map((t) => [t.symbol.toUpperCase(), t]))\nconst byAddress = new Map<string, StockToken>(registry.tokens.map((t) => [t.address.toLowerCase(), t]))\n\n/**\n * The full Stock Token registry, generated from Blockscout discovery +\n * on-chain verification + Chainlink's official feed directory. Regenerate\n * with `npm run refresh-registry`.\n */\nexport function getRegistry(): StockTokenRegistry {\n return registry\n}\n\n/** All canonical Stock Tokens, sorted by symbol. */\nexport function listStockTokens(): StockToken[] {\n return registry.tokens\n}\n\n/** Stock Tokens that have a live Chainlink price feed. */\nexport function listPricedStockTokens(): StockToken[] {\n return registry.tokens.filter((t) => t.feed !== null)\n}\n\n/**\n * Look up a Stock Token by ticker (case-insensitive).\n * @throws {@link UnknownSymbolError} when the symbol is not in the registry.\n */\nexport function getStockToken(symbol: string): StockToken {\n const token = bySymbol.get(symbol.toUpperCase())\n if (!token) throw new UnknownSymbolError(symbol)\n return token\n}\n\n/** Look up a Stock Token by contract address, or `null` if not canonical. */\nexport function getStockTokenByAddress(address: Address): StockToken | null {\n return byAddress.get(address.toLowerCase()) ?? null\n}\n\n/** `true` when `symbol` resolves to a canonical Stock Token. */\nexport function isStockTokenSymbol(symbol: string): boolean {\n return bySymbol.has(symbol.toUpperCase())\n}\n\n/** `true` when `address` is a canonical Stock Token contract. */\nexport function isStockTokenAddress(address: Address): boolean {\n return byAddress.has(address.toLowerCase())\n}\n","import { formatUnits, type Address } from 'viem'\nimport { aggregatorV3Abi, stockTokenAbi } from './abis.js'\nimport type { HoodClient } from './client.js'\nimport { FeedNotFoundError, InvalidFeedAnswerError, StaleFeedError } from './errors.js'\nimport { getStockToken, listStockTokens, type StockToken } from './registry/index.js'\n\n/**\n * Default staleness window for Chainlink stock feeds: 3 days.\n *\n * Stock feeds update 24/5, following market hours, so a Saturday read of a\n * Friday-close answer is normal and NOT stale. 72h tolerates the weekend gap;\n * pass a tighter `maxAgeSeconds` during market hours if you need fresher\n * guarantees (heartbeat is 86400s), or a looser one across long holiday\n * weekends.\n */\nexport const DEFAULT_MAX_FEED_AGE_SECONDS = 3 * 24 * 60 * 60\n\n/** Options accepted by {@link getQuote}. */\nexport interface GetQuoteOptions {\n /**\n * Maximum acceptable feed answer age in seconds.\n * @defaultValue {@link DEFAULT_MAX_FEED_AGE_SECONDS} (72h — tolerates the 24/5 weekend gap)\n */\n maxAgeSeconds?: number\n}\n\n/** A Chainlink price quote for one Stock Token. */\nexport interface StockQuote {\n symbol: string\n /** Token contract address. */\n address: Address\n /** Feed proxy the answer came from. */\n feed: Address\n /**\n * Price of ONE TOKEN in USD, as a float. Chainlink's Robinhood feeds are\n * already multiplier-adjusted: this is the token's total-return price, not\n * the underlying share price. Divide by `uiMultiplier` (1e18-scaled) for\n * the underlying share price.\n */\n priceUsd: number\n /** Raw feed answer (8 decimals unless `answerDecimals` says otherwise). */\n answer: bigint\n /** Decimals of `answer`. */\n answerDecimals: number\n /** Chainlink round id. */\n roundId: bigint\n /** Feed update timestamp (seconds). */\n updatedAt: number\n /** Age of the answer in seconds at read time. */\n ageSeconds: number\n}\n\n/**\n * Read the Chainlink price for a Stock Token.\n *\n * The answer is the price of one token — Chainlink applies the ERC-8056\n * multiplier upstream, so do NOT multiply by `uiMultiplier` again.\n *\n * @throws {@link FeedNotFoundError} when the token has no feed in the registry.\n * @throws {@link StaleFeedError} when the answer is older than `maxAgeSeconds`.\n * @throws {@link InvalidFeedAnswerError} on a non-positive or incomplete answer.\n *\n * @example\n * ```ts\n * const quote = await getQuote(hood, 'AAPL')\n * console.log(`AAPL token: $${quote.priceUsd}`)\n * ```\n */\nexport async function getQuote(\n client: HoodClient,\n symbol: string,\n options: GetQuoteOptions = {},\n): Promise<StockQuote> {\n const token = getStockToken(symbol)\n if (!token.feed) throw new FeedNotFoundError(token.symbol)\n\n const [roundId, answer, , updatedAtRaw] = await client.public.readContract({\n address: token.feed,\n abi: aggregatorV3Abi,\n functionName: 'latestRoundData',\n })\n return toQuote(token, { roundId, answer, updatedAt: Number(updatedAtRaw) }, options)\n}\n\nfunction toQuote(\n token: StockToken,\n round: { roundId: bigint; answer: bigint; updatedAt: number },\n options: GetQuoteOptions,\n): StockQuote {\n const maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_MAX_FEED_AGE_SECONDS\n const answerDecimals = token.feedDecimals ?? 8\n if (round.answer <= 0n) {\n throw new InvalidFeedAnswerError(token.symbol, `answer=${round.answer}`)\n }\n if (round.updatedAt === 0) {\n throw new InvalidFeedAnswerError(token.symbol, 'round not complete (updatedAt=0)')\n }\n const ageSeconds = Math.max(0, Math.floor(Date.now() / 1000) - round.updatedAt)\n if (ageSeconds > maxAgeSeconds) {\n throw new StaleFeedError(token.symbol, round.updatedAt, ageSeconds, maxAgeSeconds)\n }\n return {\n symbol: token.symbol,\n address: token.address,\n feed: token.feed as Address,\n priceUsd: Number(formatUnits(round.answer, answerDecimals)),\n answer: round.answer,\n answerDecimals,\n roundId: round.roundId,\n updatedAt: round.updatedAt,\n ageSeconds,\n }\n}\n\n/**\n * Read a Stock Token's ERC-8056 `uiMultiplier()`: the shares-per-token ratio,\n * scaled by 1e18. `1000000000000000000n` means 1 token = 1 share; after a\n * reinvested dividend it rises above 1e18.\n *\n * Every canonical Stock Token on chain 4663 implements the interface, so a\n * missing implementation means the address is not a canonical Stock Token —\n * in that case (`CALL` reverts / returns no data) this resolves to `null`\n * rather than throwing, as the prompt for tokens predating ERC-8056.\n */\nexport async function getMultiplier(client: HoodClient, symbol: string): Promise<bigint | null> {\n const token = getStockToken(symbol)\n try {\n return await client.public.readContract({\n address: token.address,\n abi: stockTokenAbi,\n functionName: 'uiMultiplier',\n })\n } catch {\n return null\n }\n}\n\n/** One holding inside a {@link Portfolio}. */\nexport interface StockPosition {\n symbol: string\n address: Address\n /** Raw ERC-20 token balance (18 decimals). */\n balance: bigint\n /** Token balance as a float. */\n balanceTokens: number\n /** ERC-8056 multiplier at read time (1e18-scaled). */\n uiMultiplier: bigint\n /**\n * Share-equivalent units: `balance * uiMultiplier / 1e18`. After splits or\n * reinvested dividends this diverges from `balanceTokens` — trackers that\n * show raw balances as \"shares\" misstate positions.\n */\n shareEquivalent: number\n /**\n * USD value: `balanceTokens * feedPrice`. The feed price is already\n * multiplier-adjusted (price per TOKEN), so the multiplier must NOT be\n * applied again here — doing so double-counts corporate actions.\n * `null` when the token has no Chainlink feed or the feed was stale.\n */\n valueUsd: number | null\n /** The quote used for valuation, or `null` if unavailable. */\n quote: StockQuote | null\n}\n\n/** Result of {@link getPortfolio}. */\nexport interface Portfolio {\n owner: Address\n positions: StockPosition[]\n /** Sum of `valueUsd` over positions that could be priced. */\n totalUsd: number\n /** Symbols held but not priceable (no feed / stale feed). */\n unpricedSymbols: string[]\n}\n\n/**\n * Read one Stock Token position with multiplier-correct share equivalents and\n * USD valuation. Returns `null`-valued fields rather than throwing when the\n * token cannot be priced.\n */\nexport async function getPosition(\n client: HoodClient,\n owner: Address,\n symbol: string,\n options: GetQuoteOptions = {},\n): Promise<StockPosition> {\n const token = getStockToken(symbol)\n const [position] = await readPositions(client, owner, [token], options)\n return position as StockPosition\n}\n\n/**\n * Read every registry Stock Token balance for `owner` in one multicall sweep\n * and value the non-zero holdings.\n *\n * Correctness notes (the two mistakes generic trackers make):\n * 1. USD value is `balance × feed price` — the Robinhood Chainlink feeds are\n * already multiplier-adjusted, so applying `uiMultiplier` to the value\n * double-counts corporate actions.\n * 2. Share-equivalent units are `balance × uiMultiplier ÷ 1e18` — raw token\n * balances understate positions after splits/dividends. Both numbers are\n * exposed per position, and `shareEquivalent` is cross-checkable on-chain\n * against the token's own `balanceOfUI()`.\n */\nexport async function getPortfolio(\n client: HoodClient,\n owner: Address,\n options: GetQuoteOptions = {},\n): Promise<Portfolio> {\n const tokens = listStockTokens()\n const balances = await client.public.multicall({\n contracts: tokens.map((t) => ({\n address: t.address,\n abi: stockTokenAbi,\n functionName: 'balanceOf' as const,\n args: [owner] as const,\n })),\n allowFailure: false,\n })\n\n const held = tokens.filter((_, i) => (balances[i] as bigint) > 0n)\n const positions = await readPositions(client, owner, held, options)\n\n const priced = positions.filter((p) => p.valueUsd !== null)\n return {\n owner,\n positions,\n totalUsd: priced.reduce((sum, p) => sum + (p.valueUsd as number), 0),\n unpricedSymbols: positions.filter((p) => p.valueUsd === null).map((p) => p.symbol),\n }\n}\n\nasync function readPositions(\n client: HoodClient,\n owner: Address,\n tokens: StockToken[],\n options: GetQuoteOptions,\n): Promise<StockPosition[]> {\n if (tokens.length === 0) return []\n\n const reads = await client.public.multicall({\n contracts: tokens.flatMap((t) => [\n { address: t.address, abi: stockTokenAbi, functionName: 'balanceOf' as const, args: [owner] as const },\n { address: t.address, abi: stockTokenAbi, functionName: 'uiMultiplier' as const },\n ]),\n allowFailure: false,\n })\n\n const feedTokens = tokens.filter((t) => t.feed !== null)\n const feedReads = await client.public.multicall({\n contracts: feedTokens.map((t) => ({\n address: t.feed as Address,\n abi: aggregatorV3Abi,\n functionName: 'latestRoundData' as const,\n })),\n allowFailure: true,\n })\n const quoteBySymbol = new Map<string, StockQuote | null>()\n feedTokens.forEach((t, i) => {\n const read = feedReads[i]\n if (!read || read.status !== 'success') {\n quoteBySymbol.set(t.symbol, null)\n return\n }\n const [roundId, answer, , updatedAt] = read.result as readonly [bigint, bigint, bigint, bigint, bigint]\n try {\n quoteBySymbol.set(t.symbol, toQuote(t, { roundId, answer, updatedAt: Number(updatedAt) }, options))\n } catch {\n quoteBySymbol.set(t.symbol, null)\n }\n })\n\n return tokens.map((t, i) => {\n const balance = reads[i * 2] as bigint\n const uiMultiplier = reads[i * 2 + 1] as bigint\n const balanceTokens = Number(formatUnits(balance, t.decimals))\n const quote = quoteBySymbol.get(t.symbol) ?? null\n return {\n symbol: t.symbol,\n address: t.address,\n balance,\n balanceTokens,\n uiMultiplier,\n shareEquivalent: Number(formatUnits((balance * uiMultiplier) / 10n ** 18n, t.decimals)),\n valueUsd: quote ? balanceTokens * quote.priceUsd : null,\n quote,\n }\n })\n}\n","/**\n * ABIs used by hoodchain. Every ABI here was read from a verified contract on\n * Robinhood Chain Blockscout (https://robinhoodchain.blockscout.com) during\n * SDK development:\n *\n * - `stockTokenAbi` — the `Stock` implementation behind every canonical Stock\n * Token BeaconProxy (impl `0xb35490d6f9163DE4F80d88dc75c3516eb64C5aE2`).\n * - `usdgAbi` — the USDG (Paxos Global Dollar) implementation behind the\n * ERC-1967 proxy at `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168`.\n * Note: USDG does NOT implement EIP-2612 `permit` (verified on Blockscout).\n * - `aggregatorV3Abi` — standard Chainlink AggregatorV3Interface.\n * - `quoterV2Abi` / `swapRouter02Abi` — canonical Uniswap v3 periphery on\n * chain 4663 (QuoterV2 `0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7`,\n * SwapRouter02 `0xCaf681a66D020601342297493863E78C959E5cb2`).\n */\n\n/** Minimal ERC-20 surface (shared by USDG, WETH, memecoins, Stock Tokens). */\nexport const erc20Abi = [\n { type: 'function', name: 'name', stateMutability: 'view', inputs: [], outputs: [{ type: 'string' }] },\n { type: 'function', name: 'symbol', stateMutability: 'view', inputs: [], outputs: [{ type: 'string' }] },\n { type: 'function', name: 'decimals', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint8' }] },\n { type: 'function', name: 'totalSupply', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n {\n type: 'function',\n name: 'balanceOf',\n stateMutability: 'view',\n inputs: [{ name: 'account', type: 'address' }],\n outputs: [{ type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [{ type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'transfer',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ type: 'bool' }],\n },\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ type: 'bool' }],\n },\n {\n type: 'function',\n name: 'transferFrom',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ type: 'bool' }],\n },\n {\n type: 'event',\n name: 'Transfer',\n inputs: [\n { name: 'from', type: 'address', indexed: true },\n { name: 'to', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Approval',\n inputs: [\n { name: 'owner', type: 'address', indexed: true },\n { name: 'spender', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n] as const\n\n/**\n * Canonical Stock Token surface (ERC-20 + ERC-8056 corporate-action fields +\n * EIP-2612 permit). Read from the verified `Stock` implementation on\n * Blockscout.\n */\nexport const stockTokenAbi = [\n ...erc20Abi,\n /** Shares-per-token ratio, scaled by 1e18 (ERC-8056). */\n { type: 'function', name: 'uiMultiplier', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n /** Pending multiplier that takes effect at `effectiveAt`. */\n { type: 'function', name: 'newUIMultiplier', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n /** Timestamp at which `newUIMultiplier` becomes active. */\n { type: 'function', name: 'effectiveAt', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n /** Share-equivalent balance: `balanceOf(a) * uiMultiplier / 1e18`, computed on-chain. */\n {\n type: 'function',\n name: 'balanceOfUI',\n stateMutability: 'view',\n inputs: [{ name: 'account', type: 'address' }],\n outputs: [{ type: 'uint256' }],\n },\n /** Share-equivalent total supply. */\n { type: 'function', name: 'totalSupplyUI', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },\n { type: 'function', name: 'paused', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },\n { type: 'function', name: 'tokenPaused', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },\n { type: 'function', name: 'oraclePaused', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },\n /** Issuer terms URI. */\n { type: 'function', name: 'terms', stateMutability: 'pure', inputs: [], outputs: [{ type: 'string' }] },\n { type: 'function', name: 'uid', stateMutability: 'view', inputs: [], outputs: [{ type: 'bytes32' }] },\n {\n type: 'function',\n name: 'nonces',\n stateMutability: 'view',\n inputs: [{ name: 'owner', type: 'address' }],\n outputs: [{ type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'permit',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n { name: 'v', type: 'uint8' },\n { name: 'r', type: 'bytes32' },\n { name: 's', type: 'bytes32' },\n ],\n outputs: [],\n },\n] as const\n\n/** Standard Chainlink AggregatorV3Interface. */\nexport const aggregatorV3Abi = [\n { type: 'function', name: 'decimals', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint8' }] },\n { type: 'function', name: 'description', stateMutability: 'view', inputs: [], outputs: [{ type: 'string' }] },\n {\n type: 'function',\n name: 'latestRoundData',\n stateMutability: 'view',\n inputs: [],\n outputs: [\n { name: 'roundId', type: 'uint80' },\n { name: 'answer', type: 'int256' },\n { name: 'startedAt', type: 'uint256' },\n { name: 'updatedAt', type: 'uint256' },\n { name: 'answeredInRound', type: 'uint80' },\n ],\n },\n] as const\n\n/** Uniswap v3 QuoterV2 (quote functions are nonpayable and must be simulated). */\nexport const quoterV2Abi = [\n {\n type: 'function',\n name: 'quoteExactInputSingle',\n stateMutability: 'nonpayable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'fee', type: 'uint24' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'sqrtPriceX96After', type: 'uint160' },\n { name: 'initializedTicksCrossed', type: 'uint32' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n {\n type: 'function',\n name: 'quoteExactInput',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'path', type: 'bytes' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'sqrtPriceX96AfterList', type: 'uint160[]' },\n { name: 'initializedTicksCrossedList', type: 'uint32[]' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n { type: 'function', name: 'factory', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n { type: 'function', name: 'WETH9', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n] as const\n\n/**\n * Uniswap SwapRouter02. Unlike the v1 SwapRouter, `exactInputSingle` /\n * `exactInput` structs carry no deadline; deadlines are enforced via\n * `multicall(uint256 deadline, bytes[] data)`.\n */\nexport const swapRouter02Abi = [\n {\n type: 'function',\n name: 'exactInputSingle',\n stateMutability: 'payable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'recipient', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'exactInput',\n stateMutability: 'payable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'path', type: 'bytes' },\n { name: 'recipient', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n ],\n },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'multicall',\n stateMutability: 'payable',\n inputs: [\n { name: 'deadline', type: 'uint256' },\n { name: 'data', type: 'bytes[]' },\n ],\n outputs: [{ name: 'results', type: 'bytes[]' }],\n },\n { type: 'function', name: 'factory', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n { type: 'function', name: 'WETH9', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n] as const\n\n/**\n * Classic Uniswap v3 SwapRouter (the flavor deployed on Robinhood testnet):\n * `exactInputSingle` / `exactInput` structs carry a `deadline` field.\n */\nexport const swapRouterAbi = [\n {\n type: 'function',\n name: 'exactInputSingle',\n stateMutability: 'payable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'exactInput',\n stateMutability: 'payable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'path', type: 'bytes' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n ],\n },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n { type: 'function', name: 'factory', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n { type: 'function', name: 'WETH9', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },\n] as const\n\n/** WETH9 deposit/withdraw surface (for wrapping gas ETH before a swap). */\nexport const weth9Abi = [\n ...erc20Abi,\n { type: 'function', name: 'deposit', stateMutability: 'payable', inputs: [], outputs: [] },\n {\n type: 'function',\n name: 'withdraw',\n stateMutability: 'nonpayable',\n inputs: [{ name: 'wad', type: 'uint256' }],\n outputs: [],\n },\n] as const\n\n/** Uniswap v3 factory (pool discovery). */\nexport const uniswapV3FactoryAbi = [\n {\n type: 'function',\n name: 'getPool',\n stateMutability: 'view',\n inputs: [\n { name: 'tokenA', type: 'address' },\n { name: 'tokenB', type: 'address' },\n { name: 'fee', type: 'uint24' },\n ],\n outputs: [{ type: 'address' }],\n },\n] as const\n\n/** Uniswap v3 pool (liquidity checks). */\nexport const uniswapV3PoolAbi = [\n { type: 'function', name: 'liquidity', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint128' }] },\n {\n type: 'function',\n name: 'slot0',\n stateMutability: 'view',\n inputs: [],\n outputs: [\n { name: 'sqrtPriceX96', type: 'uint160' },\n { name: 'tick', type: 'int24' },\n { name: 'observationIndex', type: 'uint16' },\n { name: 'observationCardinality', type: 'uint16' },\n { name: 'observationCardinalityNext', type: 'uint16' },\n { name: 'feeProtocol', type: 'uint8' },\n { name: 'unlocked', type: 'bool' },\n ],\n },\n] as const\n","import {\n encodeFunctionData,\n encodePacked,\n type Address,\n type Hash,\n type Hex,\n} from 'viem'\nimport { erc20Abi, quoterV2Abi, swapRouter02Abi, swapRouterAbi } from './abis.js'\nimport { MAINNET_ADDRESSES, TESTNET_ADDRESSES, V3_FEE_TIERS } from './addresses.js'\nimport type { HoodClient } from './client.js'\nimport {\n NoAccountError,\n NoRouteError,\n StockTokenEligibilityError,\n} from './errors.js'\nimport { isStockTokenAddress } from './registry/index.js'\n\n/**\n * Uniswap v3 swaps on Robinhood Chain.\n *\n * Works for memecoins and Stock Tokens alike. **Stock Token eligibility:**\n * Stock Tokens are tokenized debt securities (issuer: Robinhood Assets\n * (Jersey) Ltd) and may not be offered, sold, or delivered to US persons\n * (additional limits: Canada, UK, Switzerland). The restriction is legal and\n * front-end enforced, not contract-level. Any swap whose OUTPUT is a\n * canonical Stock Token therefore throws {@link StockTokenEligibilityError}\n * unless the client was created with `acknowledgeStockTokenEligibility:\n * true`, which is the operator's affirmation of eligibility. Selling a Stock\n * Token and displaying data are never gated.\n *\n * Router flavors (verified on-chain): mainnet routes through `SwapRouter02`\n * (no deadline in the params struct — enforced via `multicall(deadline,\n * data)`); the testnet community deployment uses the classic `SwapRouter`\n * (deadline inside the struct). `buildSwapTx` handles both.\n */\n\n/** Router/quoter/WETH set used for swaps on the client's network. */\nexport function swapAddresses(client: HoodClient): {\n quoterV2: Address\n router: Address\n routerKind: 'swapRouter02' | 'swapRouter'\n weth: Address\n usdg: Address\n} {\n if (client.network === 'testnet') {\n return {\n quoterV2: TESTNET_ADDRESSES.quoterV2,\n router: TESTNET_ADDRESSES.swapRouter,\n routerKind: 'swapRouter',\n weth: TESTNET_ADDRESSES.weth,\n usdg: TESTNET_ADDRESSES.usdg,\n }\n }\n return {\n quoterV2: MAINNET_ADDRESSES.quoterV2,\n router: MAINNET_ADDRESSES.swapRouter02,\n routerKind: 'swapRouter02',\n weth: MAINNET_ADDRESSES.weth,\n usdg: MAINNET_ADDRESSES.usdg,\n }\n}\n\n/** A candidate route: direct single-pool hop or two hops via an intermediate. */\nexport interface SwapRoute {\n /** Pool fee tiers along the route (one entry per hop). */\n fees: number[]\n /** Token path: `[tokenIn, ...intermediates, tokenOut]`. */\n path: Address[]\n /** Uniswap encoded path (`token(20) fee(3) token(20)...`). */\n encodedPath: Hex\n}\n\n/** A quote for a concrete route. */\nexport interface SwapQuote {\n route: SwapRoute\n amountIn: bigint\n amountOut: bigint\n /** QuoterV2's gas estimate for the swap. */\n gasEstimate: bigint\n}\n\n/** Options for {@link quoteSwap}. */\nexport interface QuoteSwapOptions {\n /**\n * Intermediate tokens tried for two-hop routes when quoting. Defaults to\n * the network's WETH and USDG.\n */\n intermediates?: Address[]\n /** Restrict single-hop probing to these fee tiers. Defaults to all four v3 tiers. */\n feeTiers?: readonly number[]\n}\n\nfunction encodePath(path: Address[], fees: number[]): Hex {\n const types: ('address' | 'uint24')[] = []\n const values: (Address | number)[] = []\n path.forEach((token, i) => {\n types.push('address')\n values.push(token)\n if (i < fees.length) {\n types.push('uint24')\n values.push(fees[i] as number)\n }\n })\n return encodePacked(types, values)\n}\n\n/**\n * Quote the best route from `tokenIn` to `tokenOut` for `amountIn`.\n *\n * Probes every fee tier for a direct hop, plus two-hop routes through WETH\n * and USDG (0.05%/0.3% legs), all via QuoterV2 `eth_call` simulation, and\n * returns the route with the highest output. Pools that exist without\n * liquidity revert inside the quoter and are simply skipped.\n *\n * @throws {@link NoRouteError} when no probed route can fill the swap.\n *\n * @example Quote 100 USDG → WETH on mainnet\n * ```ts\n * const quote = await quoteSwap(hood, {\n * tokenIn: MAINNET_ADDRESSES.usdg,\n * tokenOut: MAINNET_ADDRESSES.weth,\n * amountIn: parseUsdg('100'),\n * })\n * ```\n */\nexport async function quoteSwap(\n client: HoodClient,\n args: { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n options: QuoteSwapOptions = {},\n): Promise<SwapQuote> {\n const { quoterV2, weth, usdg } = swapAddresses(client)\n const { tokenIn, tokenOut, amountIn } = args\n const feeTiers = options.feeTiers ?? V3_FEE_TIERS\n\n const candidates: SwapRoute[] = []\n for (const fee of feeTiers) {\n candidates.push({ fees: [fee], path: [tokenIn, tokenOut], encodedPath: encodePath([tokenIn, tokenOut], [fee]) })\n }\n const intermediates = (options.intermediates ?? [weth, usdg]).filter(\n (mid) => mid.toLowerCase() !== tokenIn.toLowerCase() && mid.toLowerCase() !== tokenOut.toLowerCase(),\n )\n for (const mid of intermediates) {\n for (const feeA of [500, 3000]) {\n for (const feeB of [500, 3000]) {\n candidates.push({\n fees: [feeA, feeB],\n path: [tokenIn, mid, tokenOut],\n encodedPath: encodePath([tokenIn, mid, tokenOut], [feeA, feeB]),\n })\n }\n }\n }\n\n const results = await Promise.all(\n candidates.map(async (route): Promise<SwapQuote | null> => {\n try {\n if (route.fees.length === 1) {\n const { result } = await client.public.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactInputSingle',\n args: [\n {\n tokenIn,\n tokenOut,\n amountIn,\n fee: route.fees[0] as number,\n sqrtPriceLimitX96: 0n,\n },\n ],\n })\n return { route, amountIn, amountOut: result[0], gasEstimate: result[3] }\n }\n const { result } = await client.public.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactInput',\n args: [route.encodedPath, amountIn],\n })\n return { route, amountIn, amountOut: result[0], gasEstimate: result[3] }\n } catch {\n return null\n }\n }),\n )\n\n const best = results\n .filter((q): q is SwapQuote => q !== null && q.amountOut > 0n)\n .sort((a, b) => (b.amountOut > a.amountOut ? 1 : b.amountOut < a.amountOut ? -1 : 0))[0]\n if (!best) {\n throw new NoRouteError(\n tokenIn,\n tokenOut,\n `no direct pool (fees ${feeTiers.join('/')}) or two-hop route via ${intermediates.length} intermediates produced output for amountIn=${amountIn}`,\n )\n }\n return best\n}\n\n/** Options for {@link buildSwapTx} / {@link executeSwap}. */\nexport interface SwapTxOptions {\n /**\n * Slippage tolerance in basis points applied to the quoted output.\n * @defaultValue `50` (0.5%)\n */\n slippageBps?: number\n /**\n * Seconds until the swap transaction expires.\n * @defaultValue `600` (10 minutes)\n */\n deadlineSeconds?: number\n /** Recipient of the output tokens. Defaults to the client's account. */\n recipient?: Address\n}\n\n/** A ready-to-send swap transaction. */\nexport interface SwapTx {\n to: Address\n data: Hex\n value: bigint\n /** Quoted output the calldata's minimum was derived from. */\n quote: SwapQuote\n /** `amountOutMinimum` embedded in the calldata. */\n amountOutMinimum: bigint\n deadline: bigint\n}\n\n/**\n * Build swap calldata for the network's canonical router from a quote.\n *\n * The caller must hold `quote.amountIn` of the input token and have approved\n * the router for it (see {@link ensureApproval}).\n *\n * @throws {@link StockTokenEligibilityError} when the output token is a\n * canonical Stock Token and the client did not acknowledge eligibility.\n */\nexport function buildSwapTx(client: HoodClient, quote: SwapQuote, options: SwapTxOptions = {}): SwapTx {\n const { router, routerKind } = swapAddresses(client)\n const tokenOut = quote.route.path[quote.route.path.length - 1] as Address\n\n if (client.network === 'mainnet' && isStockTokenAddress(tokenOut) && !client.acknowledgeStockTokenEligibility) {\n throw new StockTokenEligibilityError()\n }\n\n const recipient = options.recipient ?? client.account?.address\n if (!recipient) throw new NoAccountError('buildSwapTx (or pass options.recipient)')\n\n const slippageBps = options.slippageBps ?? 50\n const amountOutMinimum = (quote.amountOut * BigInt(10_000 - slippageBps)) / 10_000n\n const deadline = BigInt(Math.floor(Date.now() / 1000) + (options.deadlineSeconds ?? 600))\n const singleHop = quote.route.fees.length === 1\n\n let data: Hex\n if (routerKind === 'swapRouter') {\n // Classic SwapRouter: deadline lives in the params struct.\n data = singleHop\n ? encodeFunctionData({\n abi: swapRouterAbi,\n functionName: 'exactInputSingle',\n args: [\n {\n tokenIn: quote.route.path[0] as Address,\n tokenOut,\n fee: quote.route.fees[0] as number,\n recipient,\n deadline,\n amountIn: quote.amountIn,\n amountOutMinimum,\n sqrtPriceLimitX96: 0n,\n },\n ],\n })\n : encodeFunctionData({\n abi: swapRouterAbi,\n functionName: 'exactInput',\n args: [\n {\n path: quote.route.encodedPath,\n recipient,\n deadline,\n amountIn: quote.amountIn,\n amountOutMinimum,\n },\n ],\n })\n } else {\n // SwapRouter02: wrap the call in multicall(deadline, [data]).\n const inner = singleHop\n ? encodeFunctionData({\n abi: swapRouter02Abi,\n functionName: 'exactInputSingle',\n args: [\n {\n tokenIn: quote.route.path[0] as Address,\n tokenOut,\n fee: quote.route.fees[0] as number,\n recipient,\n amountIn: quote.amountIn,\n amountOutMinimum,\n sqrtPriceLimitX96: 0n,\n },\n ],\n })\n : encodeFunctionData({\n abi: swapRouter02Abi,\n functionName: 'exactInput',\n args: [\n {\n path: quote.route.encodedPath,\n recipient,\n amountIn: quote.amountIn,\n amountOutMinimum,\n },\n ],\n })\n data = encodeFunctionData({\n abi: swapRouter02Abi,\n functionName: 'multicall',\n args: [deadline, [inner]],\n })\n }\n\n return { to: router, data, value: 0n, quote, amountOutMinimum, deadline }\n}\n\n/**\n * Ensure the router is approved to spend `amountIn` of the input token,\n * sending an `approve` transaction only when the current allowance is short.\n * Returns the approval tx hash, or `null` when no approval was needed.\n */\nexport async function ensureApproval(\n client: HoodClient,\n token: Address,\n amount: bigint,\n): Promise<Hash | null> {\n if (!client.wallet || !client.account) throw new NoAccountError('ensureApproval')\n const { router } = swapAddresses(client)\n const allowance = await client.public.readContract({\n address: token,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [client.account.address, router],\n })\n if (allowance >= amount) return null\n const hash = await client.wallet.writeContract({\n address: token,\n abi: erc20Abi,\n functionName: 'approve',\n args: [router, amount],\n })\n await client.public.waitForTransactionReceipt({ hash })\n return hash\n}\n\n/**\n * Quote, build, approve (if needed), send, and confirm a swap in one call.\n *\n * @returns The swap transaction hash and the receipt.\n *\n * @example Swap 0.0001 WETH → NFLX on testnet\n * ```ts\n * const { hash, receipt, quote } = await executeSwap(hood, {\n * tokenIn: TESTNET_ADDRESSES.weth,\n * tokenOut: TESTNET_STOCK_TOKENS.NFLX,\n * amountIn: parseEther('0.0001'),\n * })\n * ```\n */\nexport async function executeSwap(\n client: HoodClient,\n args: { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n options: SwapTxOptions & QuoteSwapOptions = {},\n) {\n if (!client.wallet || !client.account) throw new NoAccountError('executeSwap')\n const quote = await quoteSwap(client, args, options)\n const tx = buildSwapTx(client, quote, options)\n await ensureApproval(client, args.tokenIn, args.amountIn)\n const hash = await client.wallet.sendTransaction({\n to: tx.to,\n data: tx.data,\n value: tx.value,\n account: client.account,\n chain: client.chain,\n })\n const receipt = await client.public.waitForTransactionReceipt({ hash })\n return { hash, receipt, quote, amountOutMinimum: tx.amountOutMinimum }\n}\n","import { formatUnits, parseUnits, type Address, type Hash } from 'viem'\nimport { erc20Abi } from './abis.js'\nimport { MAINNET_ADDRESSES, TESTNET_ADDRESSES, USDG_DECIMALS } from './addresses.js'\nimport type { HoodClient } from './client.js'\nimport { NoAccountError } from './errors.js'\n\n/**\n * USDG — Paxos Global Dollar, Robinhood Chain's dollar stablecoin.\n *\n * Facts verified on Blockscout during SDK development:\n * - Mainnet address `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` (ERC-1967\n * proxy onto Paxos' verified `USDG` implementation), **6 decimals**.\n * - USDG does **not** implement EIP-2612 `permit` — the verified\n * implementation ABI has no `permit`, `nonces`, or EIP-2612 surface, so\n * gasless approvals are not possible; use a normal `approve`.\n */\n\n/** USDG contract address for the client's network. */\nexport function usdgAddress(client: HoodClient): Address {\n return client.network === 'testnet' ? TESTNET_ADDRESSES.usdg : MAINNET_ADDRESSES.usdg\n}\n\n/** Format a raw 6-decimal USDG amount as a decimal string. */\nexport function formatUsdg(amount: bigint): string {\n return formatUnits(amount, USDG_DECIMALS)\n}\n\n/** Parse a decimal string (e.g. `\"12.50\"`) into a raw 6-decimal USDG amount. */\nexport function parseUsdg(amount: string): bigint {\n return parseUnits(amount, USDG_DECIMALS)\n}\n\n/** USDG balance of `owner` (raw, 6 decimals — use {@link formatUsdg} to display). */\nexport async function getUsdgBalance(client: HoodClient, owner: Address): Promise<bigint> {\n return client.public.readContract({\n address: usdgAddress(client),\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [owner],\n })\n}\n\n/** USDG total supply on the client's network (raw, 6 decimals). */\nexport async function getUsdgTotalSupply(client: HoodClient): Promise<bigint> {\n return client.public.readContract({\n address: usdgAddress(client),\n abi: erc20Abi,\n functionName: 'totalSupply',\n })\n}\n\n/**\n * Transfer USDG. Requires a wallet account on the client.\n * @returns The transaction hash. Await confirmation with\n * `client.public.waitForTransactionReceipt({ hash })`.\n */\nexport async function transferUsdg(client: HoodClient, to: Address, amount: bigint): Promise<Hash> {\n if (!client.wallet) throw new NoAccountError('transferUsdg')\n return client.wallet.writeContract({\n address: usdgAddress(client),\n abi: erc20Abi,\n functionName: 'transfer',\n args: [to, amount],\n })\n}\n\n/**\n * Approve `spender` for `amount` USDG. Requires a wallet account.\n *\n * USDG has no EIP-2612 `permit` (verified on the Blockscout-verified\n * implementation), so on-chain `approve` is the only allowance mechanism.\n */\nexport async function approveUsdg(client: HoodClient, spender: Address, amount: bigint): Promise<Hash> {\n if (!client.wallet) throw new NoAccountError('approveUsdg')\n return client.wallet.writeContract({\n address: usdgAddress(client),\n abi: erc20Abi,\n functionName: 'approve',\n args: [spender, amount],\n })\n}\n\n/** Current USDG allowance from `owner` to `spender` (raw, 6 decimals). */\nexport async function getUsdgAllowance(\n client: HoodClient,\n owner: Address,\n spender: Address,\n): Promise<bigint> {\n return client.public.readContract({\n address: usdgAddress(client),\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, spender],\n })\n}\n","import type { Address, Hash } from 'viem'\nimport type { HoodClient } from './client.js'\n\n/**\n * Memecoin launchpad watchers for Robinhood Chain mainnet.\n *\n * Two launchpads operate on chain 4663 (addresses extracted from each\n * platform's official frontend bundle and confirmed against live on-chain\n * logs during SDK development — neither publishes verified source on\n * Blockscout):\n *\n * - **NOXA** (fun.noxa.fi/robinhood) — an instant launcher, not a bonding\n * curve: one transaction deploys the ERC-20, creates a Uniswap v3 pool at\n * the 1% tier, seeds single-sided liquidity, and permanently locks the LP\n * NFT. There is no graduation; trading is normal Uniswap v3 swapping on\n * the token's pool from block one.\n * - **The Odyssey** (theodyssey.fun) — a pump.fun-style native-ETH bonding\n * curve with virtual reserves. Curve trades emit `Traded` on the factory;\n * when the curve fills, `PoolCompleted` + `PoolMigrated` fire and\n * liquidity moves to a locked Uniswap v3 pool.\n */\n\n/** NOXA launchpad contracts (mainnet 4663). */\nexport const NOXA_ADDRESSES = {\n launchFactory: '0xD9eC2db5f3D1b236843925949fe5bd8a3836FCcB' as Address,\n locker: '0x7F03effbd7ceB22A3f80Dd468f67eF27826acD85' as Address,\n feeRouter: '0x9eFdC1A8e6E94f16A228e44f3025E1f346EE0417' as Address,\n /** First block with factory activity — lower bound for historical scans. */\n deployBlock: 61688n,\n} as const\n\n/** The Odyssey launchpad contracts (mainnet 4663). */\nexport const ODYSSEY_ADDRESSES = {\n /** Current bonding-curve factory. */\n bondingCurveFactory: '0xEb3FeeD2716cF0eEAda05B22e67424794e1f5a80' as Address,\n /** Variant that pays reflections in a reward token. */\n reflectionFactory: '0x6Ce85c4b7cE12903E5867652C265bCcce57f935F' as Address,\n /** Variant that skips the curve and lists instantly. */\n instantFactory: '0xD7601cEe401306fdea5833c6898181D9c770F800' as Address,\n robinLock: '0x5B41D59Fa0ce65750bc64e06D85bC999084493CD' as Address,\n /** Legacy first-generation factory (still emits historical launches). */\n legacyFactory: '0xAf9f3ce1d34909F59E88c23027f89d5807B0F915' as Address,\n} as const\n\n/** NOXA `TokenLaunched` — fired once per launch, carries the pool. */\nexport const noxaTokenLaunchedEvent = {\n type: 'event',\n name: 'TokenLaunched',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'deployer', type: 'address', indexed: true },\n { name: 'dexFactory', type: 'address', indexed: true },\n { name: 'pairToken', type: 'address', indexed: false },\n { name: 'pool', type: 'address', indexed: false },\n { name: 'dexId', type: 'uint256', indexed: false },\n { name: 'launchConfigId', type: 'uint256', indexed: false },\n { name: 'positionId', type: 'uint256', indexed: false },\n { name: 'restrictionsEndBlock', type: 'uint256', indexed: false },\n { name: 'initialBuyAmount', type: 'uint256', indexed: false },\n ],\n} as const\n\n/** The Odyssey `TokenCreated` — fired when a curve opens. */\nexport const odysseyTokenCreatedEvent = {\n type: 'event',\n name: 'TokenCreated',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'creator', type: 'address', indexed: true },\n { name: 'backingWallet', type: 'address', indexed: false },\n { name: 'isMarginBacked', type: 'bool', indexed: false },\n { name: 'threshold', type: 'uint256', indexed: false },\n ],\n} as const\n\n/** The Odyssey `Traded` — every curve buy/sell. */\nexport const odysseyTradedEvent = {\n type: 'event',\n name: 'Traded',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'trader', type: 'address', indexed: true },\n { name: 'isBuy', type: 'bool', indexed: false },\n { name: 'tokenAmount', type: 'uint256', indexed: false },\n { name: 'quoteAmount', type: 'uint256', indexed: false },\n { name: 'fee', type: 'uint256', indexed: false },\n { name: 'virtualQuote', type: 'uint256', indexed: false },\n { name: 'virtualToken', type: 'uint256', indexed: false },\n ],\n} as const\n\n/** The Odyssey `PoolMigrated` — graduation to a locked Uniswap v3 pool. */\nexport const odysseyPoolMigratedEvent = {\n type: 'event',\n name: 'PoolMigrated',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'pool', type: 'address', indexed: false },\n { name: 'tokenId', type: 'uint256', indexed: false },\n { name: 'liquidity', type: 'uint128', indexed: false },\n { name: 'tokenUsed', type: 'uint256', indexed: false },\n { name: 'usdcUsed', type: 'uint256', indexed: false },\n ],\n} as const\n\n/** Which launchpad a launch came from. */\nexport type LaunchpadName = 'noxa' | 'odyssey'\n\n/** A decoded token launch. */\nexport interface Launch {\n launchpad: LaunchpadName\n /** The new token's contract address. */\n token: Address\n /** The wallet that launched it. */\n creator: Address\n /**\n * The Uniswap v3 pool. Present immediately for NOXA (instant listing);\n * `null` for Odyssey launches still on the bonding curve (appears at\n * graduation via `PoolMigrated`).\n */\n pool: Address | null\n blockNumber: bigint\n transactionHash: Hash\n}\n\n/** A decoded Odyssey bonding-curve trade. */\nexport interface CurveTrade {\n launchpad: 'odyssey'\n token: Address\n trader: Address\n isBuy: boolean\n /** Token amount bought/sold (18 decimals). */\n tokenAmount: bigint\n /** Native ETH paid/received (wei). */\n quoteAmount: bigint\n fee: bigint\n blockNumber: bigint\n transactionHash: Hash\n}\n\nconst ODYSSEY_FACTORIES: Address[] = [\n ODYSSEY_ADDRESSES.bondingCurveFactory,\n ODYSSEY_ADDRESSES.reflectionFactory,\n ODYSSEY_ADDRESSES.instantFactory,\n]\n\n/** Options for {@link getRecentLaunches}. */\nexport interface GetRecentLaunchesOptions {\n /**\n * How many blocks back to scan. Robinhood Chain produces a block roughly\n * every 100–130ms, so 30 000 blocks ≈ the last hour.\n * @defaultValue `30_000n`\n */\n lookbackBlocks?: bigint\n /** Restrict to one launchpad. Defaults to both. */\n launchpad?: LaunchpadName\n /** Max blocks per `eth_getLogs` request (public-RPC friendly chunking). */\n chunkSize?: bigint\n}\n\n/**\n * Fetch recent launches from NOXA and The Odyssey via RPC logs.\n *\n * @example\n * ```ts\n * const launches = await getRecentLaunches(hood, { lookbackBlocks: 100_000n })\n * for (const l of launches) console.log(l.launchpad, l.token, l.creator)\n * ```\n */\nexport async function getRecentLaunches(\n client: HoodClient,\n options: GetRecentLaunchesOptions = {},\n): Promise<Launch[]> {\n const latest = await client.public.getBlockNumber()\n const lookback = options.lookbackBlocks ?? 30_000n\n const chunk = options.chunkSize ?? 10_000n\n const fromBlock = latest > lookback ? latest - lookback : 0n\n\n const launches: Launch[] = []\n for (let start = fromBlock; start <= latest; start += chunk) {\n const end = start + chunk - 1n > latest ? latest : start + chunk - 1n\n const [noxaLogs, odysseyLogs] = await Promise.all([\n options.launchpad === 'odyssey'\n ? Promise.resolve([])\n : client.public.getLogs({\n address: NOXA_ADDRESSES.launchFactory,\n event: noxaTokenLaunchedEvent,\n fromBlock: start,\n toBlock: end,\n }),\n options.launchpad === 'noxa'\n ? Promise.resolve([])\n : client.public.getLogs({\n address: ODYSSEY_FACTORIES,\n event: odysseyTokenCreatedEvent,\n fromBlock: start,\n toBlock: end,\n }),\n ])\n for (const log of noxaLogs) {\n launches.push({\n launchpad: 'noxa',\n token: log.args.token as Address,\n creator: log.args.deployer as Address,\n pool: (log.args.pool as Address) ?? null,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n for (const log of odysseyLogs) {\n launches.push({\n launchpad: 'odyssey',\n token: log.args.token as Address,\n creator: log.args.creator as Address,\n pool: null,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n }\n return launches.sort((a, b) => (a.blockNumber < b.blockNumber ? -1 : 1))\n}\n\n/** Options for {@link watchLaunches} / {@link watchCurveTrades}. */\nexport interface WatchOptions {\n /** Restrict to one launchpad. Defaults to both. */\n launchpad?: LaunchpadName\n /** Poll interval in ms for the underlying log watcher. @defaultValue `2000` */\n pollingInterval?: number\n /** Called when a watcher errors (it keeps polling afterwards). */\n onError?: (error: Error) => void\n}\n\n/**\n * Watch NOXA and The Odyssey for new token launches in real time.\n *\n * @returns An unwatch function.\n *\n * @example\n * ```ts\n * const unwatch = watchLaunches(hood, (launch) => {\n * console.log(`${launch.launchpad}: ${launch.token} by ${launch.creator}`)\n * })\n * // later: unwatch()\n * ```\n */\nexport function watchLaunches(\n client: HoodClient,\n onLaunch: (launch: Launch) => void,\n options: WatchOptions = {},\n): () => void {\n const unwatchers: (() => void)[] = []\n const pollingInterval = options.pollingInterval ?? 2000\n\n if (options.launchpad !== 'odyssey') {\n unwatchers.push(\n client.public.watchContractEvent({\n address: NOXA_ADDRESSES.launchFactory,\n abi: [noxaTokenLaunchedEvent],\n eventName: 'TokenLaunched',\n pollingInterval,\n onError: options.onError,\n onLogs: (logs) => {\n for (const log of logs) {\n onLaunch({\n launchpad: 'noxa',\n token: log.args.token as Address,\n creator: log.args.deployer as Address,\n pool: (log.args.pool as Address) ?? null,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n },\n }),\n )\n }\n if (options.launchpad !== 'noxa') {\n unwatchers.push(\n client.public.watchContractEvent({\n address: ODYSSEY_FACTORIES,\n abi: [odysseyTokenCreatedEvent],\n eventName: 'TokenCreated',\n pollingInterval,\n onError: options.onError,\n onLogs: (logs) => {\n for (const log of logs) {\n onLaunch({\n launchpad: 'odyssey',\n token: log.args.token as Address,\n creator: log.args.creator as Address,\n pool: null,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n },\n }),\n )\n }\n return () => unwatchers.forEach((u) => u())\n}\n\n/**\n * Watch The Odyssey's bonding curves for live buys/sells (`Traded` events).\n * NOXA has no curve — its tokens trade as normal Uniswap v3 swaps.\n *\n * @returns An unwatch function.\n */\nexport function watchCurveTrades(\n client: HoodClient,\n onTrade: (trade: CurveTrade) => void,\n options: Omit<WatchOptions, 'launchpad'> & { token?: Address } = {},\n): () => void {\n return client.public.watchContractEvent({\n address: ODYSSEY_FACTORIES,\n abi: [odysseyTradedEvent],\n eventName: 'Traded',\n ...(options.token ? { args: { token: options.token } } : {}),\n pollingInterval: options.pollingInterval ?? 2000,\n onError: options.onError,\n onLogs: (logs) => {\n for (const log of logs) {\n onTrade({\n launchpad: 'odyssey',\n token: log.args.token as Address,\n trader: log.args.trader as Address,\n isBuy: log.args.isBuy as boolean,\n tokenAmount: log.args.tokenAmount as bigint,\n quoteAmount: log.args.quoteAmount as bigint,\n fee: log.args.fee as bigint,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n },\n })\n}\n\n/**\n * Watch for Odyssey graduations — the moment a curve fills and liquidity\n * migrates to a locked Uniswap v3 pool.\n *\n * @returns An unwatch function.\n */\nexport function watchGraduations(\n client: HoodClient,\n onGraduation: (g: { token: Address; pool: Address; blockNumber: bigint; transactionHash: Hash }) => void,\n options: Omit<WatchOptions, 'launchpad'> = {},\n): () => void {\n return client.public.watchContractEvent({\n address: ODYSSEY_FACTORIES,\n abi: [odysseyPoolMigratedEvent],\n eventName: 'PoolMigrated',\n pollingInterval: options.pollingInterval ?? 2000,\n onError: options.onError,\n onLogs: (logs) => {\n for (const log of logs) {\n onGraduation({\n token: log.args.token as Address,\n pool: log.args.pool as Address,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n },\n })\n}\n","import { parseTransaction, keccak256, type Address, type Hash, type TransactionSerializable } from 'viem'\nimport { erc20Abi } from './abis.js'\nimport { MAINNET_FEED_URL } from './addresses.js'\nimport type { HoodClient } from './client.js'\nimport { FeedConnectionError } from './errors.js'\n\n/**\n * Sequencer firehose client for Robinhood Chain.\n *\n * The chain publishes its Arbitrum Nitro sequencer feed at\n * `wss://feed.mainnet.chain.robinhood.com` — no auth, frames of the exact\n * Nitro broadcast shape (verified live during SDK development):\n *\n * ```json\n * { \"version\": 1, \"messages\": [ {\n * \"sequenceNumber\": 123,\n * \"message\": { \"message\": { \"header\": { \"kind\": 3, \"sender\": \"0x…\",\n * \"blockNumber\": 456, \"timestamp\": 1780000000 },\n * \"l2Msg\": \"<base64>\" }, \"delayedMessagesRead\": 7 },\n * \"blockHash\": \"0x…\" } ] }\n * ```\n *\n * `l2Msg` is a Nitro L2 message: first byte is the kind — `0x04`\n * (SignedTx: the rest is one RLP/typed raw transaction) or `0x03` (Batch:\n * length-prefixed nested L2 messages). This client decodes both into viem\n * transactions and hands everything else through raw.\n *\n * Works in Node ≥ 20. Uses the global `WebSocket` when available (Node 22+,\n * browsers, bun/deno) and falls back to the optional `ws` peer dependency.\n */\n\n/** One frame from the sequencer feed, decoded. */\nexport interface FeedMessage {\n sequenceNumber: number\n /** L1 message kind from the Nitro header (3 = L2Message, the common case). */\n kind: number\n /** Header sender (the sequencer for kind-3 messages). */\n sender: Address\n /** L1 block number stamped in the header. */\n l1BlockNumber: number\n /** Header timestamp (seconds). */\n timestamp: number\n /** Raw base64 `l2Msg` payload. */\n l2MsgBase64: string\n /**\n * Transactions decoded out of the payload (empty for non-transaction\n * kinds or unparseable payloads — never throws).\n */\n transactions: DecodedFeedTransaction[]\n}\n\n/** A transaction recovered from the firehose before it lands in a block. */\nexport interface DecodedFeedTransaction {\n /** keccak256 of the raw signed bytes — the eventual transaction hash. */\n hash: Hash\n /** Parsed viem transaction (type, to, value, data, …). */\n transaction: TransactionSerializable\n /** The raw signed transaction bytes. */\n raw: `0x${string}`\n}\n\n/** Options for {@link subscribeFeed}. */\nexport interface FeedOptions {\n /** Feed endpoint. @defaultValue {@link MAINNET_FEED_URL} */\n url?: string\n /** Max reconnect attempts before giving up. @defaultValue `10` */\n maxReconnects?: number\n /** Base reconnect delay in ms (doubles per attempt, capped at 30s). @defaultValue `1000` */\n reconnectDelayMs?: number\n /** Called on connection errors (the client keeps reconnecting). */\n onError?: (error: Error) => void\n /** Called on (re)connect. */\n onConnect?: () => void\n}\n\n/** Handle returned by {@link subscribeFeed}. */\nexport interface FeedSubscription {\n /** Close the socket and stop reconnecting. */\n close: () => void\n}\n\nconst L2MSG_KIND_BATCH = 0x03\nconst L2MSG_KIND_SIGNED_TX = 0x04\n\nfunction decodeL2Msg(bytes: Uint8Array, depth = 0): DecodedFeedTransaction[] {\n if (bytes.length < 2 || depth > 4) return []\n const kind = bytes[0]\n const body = bytes.subarray(1)\n if (kind === L2MSG_KIND_SIGNED_TX) {\n const raw = `0x${Buffer.from(body).toString('hex')}` as const\n try {\n return [{ hash: keccak256(raw), transaction: parseTransaction(raw), raw }]\n } catch {\n return []\n }\n }\n if (kind === L2MSG_KIND_BATCH) {\n // Batch: repeated [8-byte big-endian length][nested L2 message].\n const out: DecodedFeedTransaction[] = []\n let offset = 0\n while (offset + 8 <= body.length) {\n const view = new DataView(body.buffer, body.byteOffset + offset, 8)\n const length = Number(view.getBigUint64(0))\n offset += 8\n if (length <= 0 || offset + length > body.length) break\n out.push(...decodeL2Msg(body.subarray(offset, offset + length), depth + 1))\n offset += length\n }\n return out\n }\n return []\n}\n\nasync function resolveWebSocket(): Promise<new (url: string) => WebSocket> {\n const g = globalThis as { WebSocket?: new (url: string) => WebSocket }\n if (typeof g.WebSocket === 'function') return g.WebSocket\n try {\n const ws = await import('ws')\n return ws.default as unknown as new (url: string) => WebSocket\n } catch {\n throw new FeedConnectionError(\n MAINNET_FEED_URL,\n 0,\n 'no WebSocket implementation available — use Node ≥ 22 or install the optional \"ws\" peer dependency',\n )\n }\n}\n\n/**\n * Subscribe to the sequencer firehose: every L2 message the sequencer\n * publishes, decoded to transactions ~100–300ms before they are queryable\n * over RPC. Reconnects automatically with exponential backoff.\n *\n * @example Print every transaction hash the sequencer emits\n * ```ts\n * const sub = await subscribeFeed((msg) => {\n * for (const tx of msg.transactions) console.log(tx.hash, tx.transaction.to)\n * })\n * // later: sub.close()\n * ```\n */\nexport async function subscribeFeed(\n onMessage: (message: FeedMessage) => void,\n options: FeedOptions = {},\n): Promise<FeedSubscription> {\n const url = options.url ?? MAINNET_FEED_URL\n const maxReconnects = options.maxReconnects ?? 10\n const WS = await resolveWebSocket()\n\n let socket: WebSocket | null = null\n let closed = false\n let attempts = 0\n\n const connect = () => {\n if (closed) return\n socket = new WS(url)\n socket.onopen = () => {\n attempts = 0\n options.onConnect?.()\n }\n socket.onmessage = (event: MessageEvent) => {\n let payload: { messages?: unknown[] }\n try {\n payload = JSON.parse(typeof event.data === 'string' ? event.data : Buffer.from(event.data as ArrayBuffer).toString())\n } catch {\n return\n }\n for (const entry of payload.messages ?? []) {\n const m = entry as {\n sequenceNumber?: number\n message?: { message?: { header?: { kind?: number; sender?: string; blockNumber?: number; timestamp?: number }; l2Msg?: string } }\n }\n const header = m.message?.message?.header\n const l2Msg = m.message?.message?.l2Msg\n if (!header || typeof l2Msg !== 'string') continue\n onMessage({\n sequenceNumber: m.sequenceNumber ?? 0,\n kind: header.kind ?? 0,\n sender: (header.sender ?? '0x0000000000000000000000000000000000000000') as Address,\n l1BlockNumber: header.blockNumber ?? 0,\n timestamp: header.timestamp ?? 0,\n l2MsgBase64: l2Msg,\n transactions: header.kind === 3 ? decodeL2Msg(Buffer.from(l2Msg, 'base64')) : [],\n })\n }\n }\n socket.onerror = () => {\n options.onError?.(new Error(`sequencer feed socket error (${url})`))\n }\n socket.onclose = () => {\n if (closed) return\n attempts += 1\n if (attempts > maxReconnects) {\n options.onError?.(new FeedConnectionError(url, attempts))\n return\n }\n const delay = Math.min((options.reconnectDelayMs ?? 1000) * 2 ** (attempts - 1), 30_000)\n setTimeout(connect, delay)\n }\n }\n connect()\n\n return {\n close: () => {\n closed = true\n socket?.close()\n },\n }\n}\n\n/** A decoded ERC-20 transfer from {@link watchTransfers}. */\nexport interface TokenTransfer {\n token: Address\n from: Address\n to: Address\n value: bigint\n blockNumber: bigint\n transactionHash: Hash\n}\n\n/**\n * Simpler event stream for consumers who don't need the firehose: watch\n * confirmed `Transfer` logs for a token over RPC polling.\n *\n * @returns An unwatch function.\n *\n * @example Watch USDG transfers\n * ```ts\n * const unwatch = watchTransfers(hood, { token: MAINNET_ADDRESSES.usdg }, (t) => {\n * console.log(`${t.from} → ${t.to}: ${formatUsdg(t.value)} USDG`)\n * })\n * ```\n */\nexport function watchTransfers(\n client: HoodClient,\n args: { token: Address; pollingInterval?: number; onError?: (error: Error) => void },\n onTransfer: (transfer: TokenTransfer) => void,\n): () => void {\n return client.public.watchContractEvent({\n address: args.token,\n abi: erc20Abi,\n eventName: 'Transfer',\n pollingInterval: args.pollingInterval ?? 2000,\n onError: args.onError,\n onLogs: (logs) => {\n for (const log of logs) {\n const a = log.args as { from?: Address; to?: Address; value?: bigint }\n if (!a.from || !a.to || a.value === undefined) continue\n onTransfer({\n token: args.token,\n from: a.from,\n to: a.to,\n value: a.value,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n })\n }\n },\n })\n}\n"],"mappings":"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","names":["formatUnits","result"]}