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,2248 @@
1
+ #!/usr/bin/env node
2
+
3
+ // node_modules/hoodchain/dist/index.js
4
+ import {
5
+ createPublicClient,
6
+ createWalletClient,
7
+ http
8
+ } from "viem";
9
+ import { robinhood, robinhoodTestnet } from "viem/chains";
10
+ import { formatUnits } from "viem";
11
+ import {
12
+ encodeFunctionData,
13
+ encodePacked
14
+ } from "viem";
15
+ import { formatUnits as formatUnits2, parseUnits } from "viem";
16
+ import { parseTransaction, keccak256 } from "viem";
17
+ function createHoodClient(config = {}) {
18
+ const network = config.chain ?? "mainnet";
19
+ const chain = network === "testnet" ? robinhoodTestnet : robinhood;
20
+ const transport = config.transport ?? http(config.rpcUrl);
21
+ const publicClient = createPublicClient({
22
+ chain,
23
+ transport,
24
+ batch: { multicall: true }
25
+ });
26
+ const wallet = config.account ? createWalletClient({ chain, transport, account: config.account }) : null;
27
+ return {
28
+ chain,
29
+ network,
30
+ public: publicClient,
31
+ wallet,
32
+ account: config.account ?? null,
33
+ acknowledgeStockTokenEligibility: config.acknowledgeStockTokenEligibility ?? false
34
+ };
35
+ }
36
+ var MAINNET_ADDRESSES = {
37
+ /** USDG — Paxos Global Dollar, the chain's dollar stablecoin. 6 decimals. */
38
+ usdg: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
39
+ /** Canonical WETH9. */
40
+ weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
41
+ /** Uniswap v3 factory. */
42
+ uniswapV3Factory: "0x1f7d7550B1b028f7571E69A784071F0205FD2EfA",
43
+ /** Uniswap QuoterV2. */
44
+ quoterV2: "0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7",
45
+ /** Uniswap SwapRouter02. */
46
+ swapRouter02: "0xCaf681a66D020601342297493863E78C959E5cb2",
47
+ /** Uniswap UniversalRouter. */
48
+ universalRouter: "0x53BF6B0684Ec7eF91e1387Da3D1a1769bC5A6F77",
49
+ /** Uniswap NonfungiblePositionManager. */
50
+ nonfungiblePositionManager: "0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3",
51
+ /** Multicall3 (canonical deterministic deployment). */
52
+ multicall3: "0xca11bde05977b3631167028862be2a173976ca11"
53
+ };
54
+ var TESTNET_ADDRESSES = {
55
+ /** Testnet USDG ("Global Dollar", 6 decimals). */
56
+ usdg: "0x7E955252E15c84f5768B83c41a71F9eba181802F",
57
+ /** Canonical testnet WETH9 (matches the official protocol-contracts L2 WETH). */
58
+ weth: "0x7943e237c7F95DA44E0301572D358911207852Fa",
59
+ /** Community Uniswap v3 factory (the one with liquid Stock Token pools). */
60
+ uniswapV3Factory: "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865",
61
+ /** QuoterV2 linked to the factory above. */
62
+ quoterV2: "0xcf05Fc31A6B693DD0bEB76e958ae4BCD490dc985",
63
+ /** Classic v3 SwapRouter (struct-level deadline) linked to the factory above. */
64
+ swapRouter: "0x1b81D678ffb9C0263b24A97847620C99d213eB14",
65
+ /** NonfungiblePositionManager linked to the factory above. */
66
+ nonfungiblePositionManager: "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364",
67
+ /** Multicall3 (canonical deterministic deployment, in viem's chain def). */
68
+ multicall3: "0xca11bde05977b3631167028862be2a173976ca11"
69
+ };
70
+ var TESTNET_STOCK_TOKENS = {
71
+ TSLA: "0xC9f9c86933092BbbfFF3CCb4b105A4A94bf3Bd4E",
72
+ AMZN: "0x5884aD2f920c162CFBbACc88C9C51AA75eC09E02",
73
+ PLTR: "0x1FBE1a0e43594b3455993B5dE5Fd0A7A266298d0",
74
+ NFLX: "0x3b8262A63d25f0477c4DDE23F83cfe22Cb768C93",
75
+ AMD: "0x71178BAc73cBeb415514eB542a8995b82669778d"
76
+ };
77
+ var MAINNET_FEED_URL = "wss://feed.mainnet.chain.robinhood.com";
78
+ var MAINNET_EXPLORER_URL = "https://robinhoodchain.blockscout.com";
79
+ var USDG_DECIMALS = 6;
80
+ var STOCK_TOKEN_DECIMALS = 18;
81
+ var FEED_DECIMALS = 8;
82
+ var V3_FEE_TIERS = [100, 500, 3e3, 1e4];
83
+ var HoodchainError = class extends Error {
84
+ name = "HoodchainError";
85
+ };
86
+ var UnknownSymbolError = class extends HoodchainError {
87
+ name = "UnknownSymbolError";
88
+ /** The symbol that failed to resolve. */
89
+ symbol;
90
+ constructor(symbol) {
91
+ super(
92
+ `Unknown Stock Token symbol "${symbol}". Symbols are case-insensitive tickers as listed on-chain (e.g. "AAPL", "TSLA"). Call listStockTokens() to enumerate the registry.`
93
+ );
94
+ this.symbol = symbol;
95
+ }
96
+ };
97
+ var FeedNotFoundError = class extends HoodchainError {
98
+ name = "FeedNotFoundError";
99
+ symbol;
100
+ constructor(symbol) {
101
+ super(
102
+ `Stock Token "${symbol}" has no Chainlink price feed in the registry. Its balance can still be read, but it cannot be priced on-chain.`
103
+ );
104
+ this.symbol = symbol;
105
+ }
106
+ };
107
+ var StaleFeedError = class extends HoodchainError {
108
+ name = "StaleFeedError";
109
+ symbol;
110
+ /** Feed timestamp, seconds since epoch. */
111
+ updatedAt;
112
+ /** Age of the answer in seconds at read time. */
113
+ ageSeconds;
114
+ /** The staleness window that was exceeded. */
115
+ maxAgeSeconds;
116
+ constructor(symbol, updatedAt, ageSeconds, maxAgeSeconds) {
117
+ super(
118
+ `Chainlink feed for "${symbol}" is stale: answer is ${ageSeconds}s old (updatedAt ${new Date(updatedAt * 1e3).toISOString()}), allowed max is ${maxAgeSeconds}s. Stock feeds pause outside market hours (24/5); pass a larger maxAgeSeconds if weekend/holiday reads are acceptable.`
119
+ );
120
+ this.symbol = symbol;
121
+ this.updatedAt = updatedAt;
122
+ this.ageSeconds = ageSeconds;
123
+ this.maxAgeSeconds = maxAgeSeconds;
124
+ }
125
+ };
126
+ var InvalidFeedAnswerError = class extends HoodchainError {
127
+ name = "InvalidFeedAnswerError";
128
+ symbol;
129
+ constructor(symbol, detail) {
130
+ super(`Chainlink feed for "${symbol}" returned an invalid answer: ${detail}`);
131
+ this.symbol = symbol;
132
+ }
133
+ };
134
+ var NoRouteError = class extends HoodchainError {
135
+ name = "NoRouteError";
136
+ tokenIn;
137
+ tokenOut;
138
+ constructor(tokenIn, tokenOut, detail) {
139
+ super(
140
+ `No swappable Uniswap v3 route from ${tokenIn} to ${tokenOut}` + (detail ? `: ${detail}` : ".") + ` Pools may exist without liquidity; try a different intermediate or amount.`
141
+ );
142
+ this.tokenIn = tokenIn;
143
+ this.tokenOut = tokenOut;
144
+ }
145
+ };
146
+ var SlippageExceededError = class extends HoodchainError {
147
+ name = "SlippageExceededError";
148
+ constructor(detail) {
149
+ super(`Slippage bound exceeded: ${detail}`);
150
+ }
151
+ };
152
+ var NoAccountError = class extends HoodchainError {
153
+ name = "NoAccountError";
154
+ constructor(operation) {
155
+ super(
156
+ `${operation} requires a wallet. Pass an \`account\` to createHoodClient (e.g. privateKeyToAccount(process.env.ROBINHOOD_CHAIN_PRIVATE_KEY)).`
157
+ );
158
+ }
159
+ };
160
+ var StockTokenEligibilityError = class extends HoodchainError {
161
+ name = "StockTokenEligibilityError";
162
+ constructor() {
163
+ super(
164
+ "Refusing to build a swap that acquires a Stock Token: eligibility not acknowledged. Stock Tokens may not be offered, sold, or delivered to US persons (issuer: Robinhood Assets (Jersey) Ltd; extra limits: Canada, UK, Switzerland). If the operator of this software is eligible, set `acknowledgeStockTokenEligibility: true` in createHoodClient config."
165
+ );
166
+ }
167
+ };
168
+ var FeedConnectionError = class extends HoodchainError {
169
+ name = "FeedConnectionError";
170
+ constructor(url, attempts, lastError) {
171
+ super(
172
+ `Sequencer feed connection to ${url} failed after ${attempts} attempts` + (lastError ? `: ${lastError}` : ".")
173
+ );
174
+ }
175
+ };
176
+ var stock_tokens_default = {
177
+ $schema: "./stock-tokens.schema.json",
178
+ chainId: 4663,
179
+ generatedAtBlock: 7690522,
180
+ sources: {
181
+ discovery: 'https://robinhoodchain.blockscout.com/api/v2/tokens?q=Robinhood Token (canonical name pattern "<Name> \u2022 Robinhood Token")',
182
+ feeds: "https://reference-data-directory.vercel.app/feeds-robinhood-mainnet.json",
183
+ verification: "on-chain via public RPC: shared beacon slot, symbol/name/decimals/uiMultiplier multicall, feed latestRoundData"
184
+ },
185
+ stockBeacon: "0xe10b6f6B275de231345c20D14Ab812db62151b00",
186
+ tokenCount: 95,
187
+ feedCount: 34,
188
+ tokens: [
189
+ {
190
+ address: "0x521Cf887E6531c6F667b5BC4D896E5d9bfE8EB2E",
191
+ symbol: "AAOI",
192
+ name: "Applied Optoelectronics \u2022 Robinhood Token",
193
+ decimals: 18,
194
+ uiMultiplierAtGeneration: "1000000000000000000",
195
+ feed: null,
196
+ feedDecimals: null
197
+ },
198
+ {
199
+ address: "0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9",
200
+ symbol: "AAPL",
201
+ name: "Apple \u2022 Robinhood Token",
202
+ decimals: 18,
203
+ uiMultiplierAtGeneration: "1000000000000000000",
204
+ feed: "0x6B22A786bAa607d76728168703a39Ea9C99f2cD0",
205
+ feedDecimals: 8,
206
+ feedAnswerAtGeneration: "31550000000",
207
+ feedUpdatedAtGeneration: 1783710274
208
+ },
209
+ {
210
+ address: "0x36046893810a7E7fCE501229d57dc3FC8c8716d0",
211
+ symbol: "AMAT",
212
+ name: "Applied Materials \u2022 Robinhood Token",
213
+ decimals: 18,
214
+ uiMultiplierAtGeneration: "1000000000000000000",
215
+ feed: null,
216
+ feedDecimals: null
217
+ },
218
+ {
219
+ address: "0x86923f96303D656E4aa86D9d42D1e57ad2023fdC",
220
+ symbol: "AMD",
221
+ name: "AMD \u2022 Robinhood Token",
222
+ decimals: 18,
223
+ uiMultiplierAtGeneration: "1000000000000000000",
224
+ feed: "0x943A29E7ae51A4798823ca9eEd2ed533B2A22C72",
225
+ feedDecimals: 8,
226
+ feedAnswerAtGeneration: "55821015000",
227
+ feedUpdatedAtGeneration: 1783713346
228
+ },
229
+ {
230
+ address: "0x12f190a9F9d7D37a250758b26824B97CE941bF54",
231
+ symbol: "AMZN",
232
+ name: "Amazon \u2022 Robinhood Token",
233
+ decimals: 18,
234
+ uiMultiplierAtGeneration: "1000000000000000000",
235
+ feed: "0xD5a1508ceD74c084eBf3cBe853e2C968fB2a651C",
236
+ feedDecimals: 8,
237
+ feedAnswerAtGeneration: "24556770000",
238
+ feedUpdatedAtGeneration: 1783692103
239
+ },
240
+ {
241
+ address: "0xb8DBf92F9741c9ac1c32115E78581f23509916FD",
242
+ symbol: "APLD",
243
+ name: "Applied Digital \u2022 Robinhood Token",
244
+ decimals: 18,
245
+ uiMultiplierAtGeneration: "1000000000000000000",
246
+ feed: null,
247
+ feedDecimals: null
248
+ },
249
+ {
250
+ address: "0x47F93d52cBeC7C6D2CfC080e154002370a60dAEA",
251
+ symbol: "ASML",
252
+ name: "ASML Holding NV \u2022 Robinhood Token",
253
+ decimals: 18,
254
+ uiMultiplierAtGeneration: "1000000000000000000",
255
+ feed: "0xB4106147E8cce40b7d46124090d373A71b70f87D",
256
+ feedDecimals: 8,
257
+ feedAnswerAtGeneration: "179758755000",
258
+ feedUpdatedAtGeneration: 1783710661
259
+ },
260
+ {
261
+ address: "0x1AF6446f07eb1d97c546AFC8c9544cBDF3AD5137",
262
+ symbol: "ASTS",
263
+ name: "AST SpaceMobile \u2022 Robinhood Token",
264
+ decimals: 18,
265
+ uiMultiplierAtGeneration: "1000000000000000000",
266
+ feed: null,
267
+ feedDecimals: null
268
+ },
269
+ {
270
+ address: "0x156E175DD063a8cE274C50654eF40e0032b3fbcF",
271
+ symbol: "AVGO",
272
+ name: "Broadcom \u2022 Robinhood Token",
273
+ decimals: 18,
274
+ uiMultiplierAtGeneration: "1000000000000000000",
275
+ feed: null,
276
+ feedDecimals: null
277
+ },
278
+ {
279
+ address: "0x4D21483a44Bf67a86b77E3dA301411880797D452",
280
+ symbol: "BA",
281
+ name: "Boeing \u2022 Robinhood Token",
282
+ decimals: 18,
283
+ uiMultiplierAtGeneration: "1000000000000000000",
284
+ feed: null,
285
+ feedDecimals: null
286
+ },
287
+ {
288
+ address: "0xad25Ac6C84D497db898fa1E8387bf6Af3532a1c4",
289
+ symbol: "BABA",
290
+ name: "Alibaba \u2022 Robinhood Token",
291
+ decimals: 18,
292
+ uiMultiplierAtGeneration: "1000000000000000000",
293
+ feed: "0x62Cc8F9b5f56a33c9C8A60c8B92779f523c4E984",
294
+ feedDecimals: 8,
295
+ feedAnswerAtGeneration: "11219500000",
296
+ feedUpdatedAtGeneration: 1783707523
297
+ },
298
+ {
299
+ address: "0x822CC93fFD030293E9842c30BBD678F530701867",
300
+ symbol: "BE",
301
+ name: "Bloom Energy \u2022 Robinhood Token",
302
+ decimals: 18,
303
+ uiMultiplierAtGeneration: "1000000000000000000",
304
+ feed: null,
305
+ feedDecimals: null
306
+ },
307
+ {
308
+ address: "0x5c90450Bbb4273D7b2f17CF6917AEB237A569679",
309
+ symbol: "CBRS",
310
+ name: "Cerebras Systems \u2022 Robinhood Token",
311
+ decimals: 18,
312
+ uiMultiplierAtGeneration: "1000000000000000000",
313
+ feed: null,
314
+ feedDecimals: null
315
+ },
316
+ {
317
+ address: "0x9651342CeA770aE9a2969Ba2A52611523146aef9",
318
+ symbol: "CCL",
319
+ name: "Carnival Corporation \u2022 Robinhood Token",
320
+ decimals: 18,
321
+ uiMultiplierAtGeneration: "1000000000000000000",
322
+ feed: null,
323
+ feedDecimals: null
324
+ },
325
+ {
326
+ address: "0x8cF07C5A878945185d327aAa6e33FAa95F95e7bF",
327
+ symbol: "CELH",
328
+ name: "Celsius \u2022 Robinhood Token",
329
+ decimals: 18,
330
+ uiMultiplierAtGeneration: "1000000000000000000",
331
+ feed: null,
332
+ feedDecimals: null
333
+ },
334
+ {
335
+ address: "0xcBB95BBF36099d34dA091dc6Fa6F49EfA257Cee3",
336
+ symbol: "CLSK",
337
+ name: "CleanSpark \u2022 Robinhood Token",
338
+ decimals: 18,
339
+ uiMultiplierAtGeneration: "1000000000000000000",
340
+ feed: "0x810c12D3a554Bc47fd39597Fe3b3AAC4941F50eF",
341
+ feedDecimals: 8,
342
+ feedAnswerAtGeneration: "1286499999",
343
+ feedUpdatedAtGeneration: 1783713313
344
+ },
345
+ {
346
+ address: "0x6330D8C3178a418788dF01a47479c0ce7CCF450b",
347
+ symbol: "COIN",
348
+ name: "Coinbase \u2022 Robinhood Token",
349
+ decimals: 18,
350
+ uiMultiplierAtGeneration: "1000000000000000000",
351
+ feed: "0xA3a468A452940B7D6b69991207B508c609a98Ef2",
352
+ feedDecimals: 8,
353
+ feedAnswerAtGeneration: "15943135000",
354
+ feedUpdatedAtGeneration: 1783703473
355
+ },
356
+ {
357
+ address: "0x4EA005168D7F09a7A0Ba9D1DEf21a479950E44C2",
358
+ symbol: "COST",
359
+ name: "Costco \u2022 Robinhood Token",
360
+ decimals: 18,
361
+ uiMultiplierAtGeneration: "1000000000000000000",
362
+ feed: null,
363
+ feedDecimals: null
364
+ },
365
+ {
366
+ address: "0xdF0992E440dD0be65BD8439b609d6D4366bf1CB5",
367
+ symbol: "CRCL",
368
+ name: "Circle Internet Group \u2022 Robinhood Token",
369
+ decimals: 18,
370
+ uiMultiplierAtGeneration: "1000000000000000000",
371
+ feed: "0x6652eDf64bA3731C4F2D3ce821A0Fb1f1f6b482a",
372
+ feedDecimals: 8,
373
+ feedAnswerAtGeneration: "6634635000",
374
+ feedUpdatedAtGeneration: 1783717360
375
+ },
376
+ {
377
+ address: "0x5f10A1C971B69e47e059e1dC91901B59b3fB49C3",
378
+ symbol: "CRWV",
379
+ name: "CoreWeave \u2022 Robinhood Token",
380
+ decimals: 18,
381
+ uiMultiplierAtGeneration: "1000000000000000000",
382
+ feed: "0xe1b3aABCAFAd1c94708dc1367dcfF8Aa4407487C",
383
+ feedDecimals: 8,
384
+ feedAnswerAtGeneration: "8883970000",
385
+ feedUpdatedAtGeneration: 1783711393
386
+ },
387
+ {
388
+ address: "0x27c99fBde9D0d2AA4f4Bfb4943f237843DdF6958",
389
+ symbol: "DDOG",
390
+ name: "Datadog \u2022 Robinhood Token",
391
+ decimals: 18,
392
+ uiMultiplierAtGeneration: "1000000000000000000",
393
+ feed: null,
394
+ feedDecimals: null
395
+ },
396
+ {
397
+ address: "0x941AE714EC6D8130c7B75d67160Ca08f1e7d11Dd",
398
+ symbol: "DELL",
399
+ name: "Dell \u2022 Robinhood Token",
400
+ decimals: 18,
401
+ uiMultiplierAtGeneration: "1000000000000000000",
402
+ feed: null,
403
+ feedDecimals: null
404
+ },
405
+ {
406
+ address: "0x39EC44Bee4F6A116c6F9B8De566848a985C53C60",
407
+ symbol: "ELF",
408
+ name: "e.l.f. Beauty \u2022 Robinhood Token",
409
+ decimals: 18,
410
+ uiMultiplierAtGeneration: "1000000000000000000",
411
+ feed: null,
412
+ feedDecimals: null
413
+ },
414
+ {
415
+ address: "0x7f0aBeF0C07280F82c6a08ead09dEd6BAE2C13Fc",
416
+ symbol: "EWY",
417
+ name: "iShares MSCI South Korea fund \u2022 Robinhood Token",
418
+ decimals: 18,
419
+ uiMultiplierAtGeneration: "1000000000000000000",
420
+ feed: "0xEFdf54610B62A7753Ec30bDc380847c12D32e1D1",
421
+ feedDecimals: 8,
422
+ feedAnswerAtGeneration: "18377499999",
423
+ feedUpdatedAtGeneration: 1783705547
424
+ },
425
+ {
426
+ address: "0x25C288E6D899b9BC30160965aD9644c67e73bE0C",
427
+ symbol: "F",
428
+ name: "Ford Motor \u2022 Robinhood Token",
429
+ decimals: 18,
430
+ uiMultiplierAtGeneration: "1000000000000000000",
431
+ feed: null,
432
+ feedDecimals: null
433
+ },
434
+ {
435
+ address: "0x282e87451E10fA6679BC7D76C69BE44cD3fC777C",
436
+ symbol: "FLNC",
437
+ name: "Fluence Energy \u2022 Robinhood Token",
438
+ decimals: 18,
439
+ uiMultiplierAtGeneration: "1000000000000000000",
440
+ feed: null,
441
+ feedDecimals: null
442
+ },
443
+ {
444
+ address: "0xeB30663bDFf0622Ef4e4E5cBb4E975F19f33f51D",
445
+ symbol: "FUTU",
446
+ name: "Futu Holdings \u2022 Robinhood Token",
447
+ decimals: 18,
448
+ uiMultiplierAtGeneration: "1000000000000000000",
449
+ feed: null,
450
+ feedDecimals: null
451
+ },
452
+ {
453
+ address: "0x7c04E6A3368F2A1DE3874f0e80d2e0A1a9915da6",
454
+ symbol: "GLW",
455
+ name: "Corning \u2022 Robinhood Token",
456
+ decimals: 18,
457
+ uiMultiplierAtGeneration: "1000000000000000000",
458
+ feed: null,
459
+ feedDecimals: null
460
+ },
461
+ {
462
+ address: "0x1b0E319c6A659F002271B69dB8A7df2F911c153E",
463
+ symbol: "GME",
464
+ name: "GameStop \u2022 Robinhood Token",
465
+ decimals: 18,
466
+ uiMultiplierAtGeneration: "1000000000000000000",
467
+ feed: "0x27C71df6A64fB476468EdF256CF72c038baB5B67",
468
+ feedDecimals: 8,
469
+ feedAnswerAtGeneration: "2176125000",
470
+ feedUpdatedAtGeneration: 1783694006
471
+ },
472
+ {
473
+ address: "0x2e0847E8910a9732eB3fb1bb4b70a580ADAD4FE3",
474
+ symbol: "GOOGL",
475
+ name: "Alphabet Class A \u2022 Robinhood Token",
476
+ decimals: 18,
477
+ uiMultiplierAtGeneration: "1000000000000000000",
478
+ feed: "0xF6f373a037c30F0e5010d854385cA89185AE638b",
479
+ feedDecimals: 8,
480
+ feedAnswerAtGeneration: "35672000000",
481
+ feedUpdatedAtGeneration: 1783711606
482
+ },
483
+ {
484
+ address: "0xf1953DAB6FaD537488d5A022361FfAa8B4c95eC6",
485
+ symbol: "INOD",
486
+ name: "Innodata \u2022 Robinhood Token",
487
+ decimals: 18,
488
+ uiMultiplierAtGeneration: "1000000000000000000",
489
+ feed: null,
490
+ feedDecimals: null
491
+ },
492
+ {
493
+ address: "0xc72b96e0E48ecd4DC75E1e45396e26300BC39681",
494
+ symbol: "INTC",
495
+ name: "Intel \u2022 Robinhood Token",
496
+ decimals: 18,
497
+ uiMultiplierAtGeneration: "1000000000000000000",
498
+ feed: "0x3f390C5C24628Ac7C489515402235FeAD71D1913",
499
+ feedDecimals: 8,
500
+ feedAnswerAtGeneration: "10965095000",
501
+ feedUpdatedAtGeneration: 1783712771
502
+ },
503
+ {
504
+ address: "0x56d23beE5f41A7120170b0c603Dae30128e460e9",
505
+ symbol: "INTU",
506
+ name: "Intuit \u2022 Robinhood Token",
507
+ decimals: 18,
508
+ uiMultiplierAtGeneration: "1000000000000000000",
509
+ feed: null,
510
+ feedDecimals: null
511
+ },
512
+ {
513
+ address: "0x558378E000D634A36593E338eBacdd6207640EfE",
514
+ symbol: "IONQ",
515
+ name: "IonQ \u2022 Robinhood Token",
516
+ decimals: 18,
517
+ uiMultiplierAtGeneration: "1000000000000000000",
518
+ feed: "0x22EfeC4919baf55F360E0EDee4AbEB26DE4971eb",
519
+ feedDecimals: 8,
520
+ feedAnswerAtGeneration: "4308000000",
521
+ feedUpdatedAtGeneration: 1783711226
522
+ },
523
+ {
524
+ address: "0xF0AB0c93bE6F41369d302e55db1A96b3c430212D",
525
+ symbol: "IREN",
526
+ name: "IREN Limited \u2022 Robinhood Token",
527
+ decimals: 18,
528
+ uiMultiplierAtGeneration: "1000000000000000000",
529
+ feed: null,
530
+ feedDecimals: null
531
+ },
532
+ {
533
+ address: "0x8eF20885F94e3D9bc7eB3080279188Bd5ED7c08C",
534
+ symbol: "LITE",
535
+ name: "Lumentum \u2022 Robinhood Token",
536
+ decimals: 18,
537
+ uiMultiplierAtGeneration: "1000000000000000000",
538
+ feed: null,
539
+ feedDecimals: null
540
+ },
541
+ {
542
+ address: "0x8005d266423c7ea827372c9c864491e5786600ea",
543
+ symbol: "LLY",
544
+ name: "Eli Lilly \u2022 Robinhood Token",
545
+ decimals: 18,
546
+ uiMultiplierAtGeneration: "1000000000000000000",
547
+ feed: null,
548
+ feedDecimals: null
549
+ },
550
+ {
551
+ address: "0x4e62068525Ab11FE768e29dfD00ef909B9803016",
552
+ symbol: "LULU",
553
+ name: "Lululemon \u2022 Robinhood Token",
554
+ decimals: 18,
555
+ uiMultiplierAtGeneration: "1000000000000000000",
556
+ feed: null,
557
+ feedDecimals: null
558
+ },
559
+ {
560
+ address: "0xa5D4968421bA94814Be3B136b15cf422101aC1a3",
561
+ symbol: "LUNR",
562
+ name: "Intuitive Machines \u2022 Robinhood Token",
563
+ decimals: 18,
564
+ uiMultiplierAtGeneration: "1000000000000000000",
565
+ feed: null,
566
+ feedDecimals: null
567
+ },
568
+ {
569
+ address: "0xDdf2266b79abf0B48898959B0ed6E6adf512be74",
570
+ symbol: "MDB",
571
+ name: "MongoDB \u2022 Robinhood Token",
572
+ decimals: 18,
573
+ uiMultiplierAtGeneration: "1000000000000000000",
574
+ feed: null,
575
+ feedDecimals: null
576
+ },
577
+ {
578
+ address: "0xc0D6457C16Cc70d6790Dd43521C899C87ce02f35",
579
+ symbol: "META",
580
+ name: "Meta Platforms \u2022 Robinhood Token",
581
+ decimals: 18,
582
+ uiMultiplierAtGeneration: "1000000000000000000",
583
+ feed: "0x7C38C00C30BEe9378381E7B6135d7283356D71b1",
584
+ feedDecimals: 8,
585
+ feedAnswerAtGeneration: "67067485000",
586
+ feedUpdatedAtGeneration: 1783713401
587
+ },
588
+ {
589
+ address: "0x62fd0668e10D8B72339BE2DCF7643001688ff13B",
590
+ symbol: "MRVL",
591
+ name: "Marvell Technology \u2022 Robinhood Token",
592
+ decimals: 18,
593
+ uiMultiplierAtGeneration: "1000000000000000000",
594
+ feed: null,
595
+ feedDecimals: null
596
+ },
597
+ {
598
+ address: "0xe93237C50D904957Cf27E7B1133b510C669c2e74",
599
+ symbol: "MSFT",
600
+ name: "Microsoft \u2022 Robinhood Token",
601
+ decimals: 18,
602
+ uiMultiplierAtGeneration: "1000000000000000000",
603
+ feed: "0x45C3C877C15E6BA2EBB19eA114Ea508d14C1Af2E",
604
+ feedDecimals: 8,
605
+ feedAnswerAtGeneration: "38469000000",
606
+ feedUpdatedAtGeneration: 1783697881
607
+ },
608
+ {
609
+ address: "0xec262a75e413fAfD0dF80480274532C79D42da09",
610
+ symbol: "MSTR",
611
+ name: "Strategy Inc. \u2022 Robinhood Token",
612
+ decimals: 18,
613
+ uiMultiplierAtGeneration: "1000000000000000000",
614
+ feed: "0x396118bdFB181e6240E74D243F266B061c0edc3D",
615
+ feedDecimals: 8,
616
+ feedAnswerAtGeneration: "9469500000",
617
+ feedUpdatedAtGeneration: 1783712395
618
+ },
619
+ {
620
+ address: "0xfF080c8ce2E5feadaCa0Da81314Ae59D232d4afD",
621
+ symbol: "MU",
622
+ name: "Micron Technology \u2022 Robinhood Token",
623
+ decimals: 18,
624
+ uiMultiplierAtGeneration: "1000000000000000000",
625
+ feed: "0x425EEFdCf05ed6526C3cE61Af99429A228a6d596",
626
+ feedDecimals: 8,
627
+ feedAnswerAtGeneration: "97854340000",
628
+ feedUpdatedAtGeneration: 1783713684
629
+ },
630
+ {
631
+ address: "0x48961813349333209994750ffA89b3c5C22eC969",
632
+ symbol: "MXL",
633
+ name: "MaxLinear \u2022 Robinhood Token",
634
+ decimals: 18,
635
+ uiMultiplierAtGeneration: "1000000000000000000",
636
+ feed: null,
637
+ feedDecimals: null
638
+ },
639
+ {
640
+ address: "0x9D9c6684F596F66a64C030B93A886D51Fd4D7931",
641
+ symbol: "NBIS",
642
+ name: "Nebius Group \u2022 Robinhood Token",
643
+ decimals: 18,
644
+ uiMultiplierAtGeneration: "1000000000000000000",
645
+ feed: "0xE1D87B116Ba0fe898998f1D140339D1fA1E09705",
646
+ feedDecimals: 8,
647
+ feedAnswerAtGeneration: "21923750000",
648
+ feedUpdatedAtGeneration: 1783713491
649
+ },
650
+ {
651
+ address: "0xE0444EF8BF4eD74f74FD73686e2ddF4C1c5591E8",
652
+ symbol: "NFLX",
653
+ name: "Netflix \u2022 Robinhood Token",
654
+ decimals: 18,
655
+ uiMultiplierAtGeneration: "1000000000000000000",
656
+ feed: null,
657
+ feedDecimals: null
658
+ },
659
+ {
660
+ address: "0xBEF75684C43c4ea7BD18Dd532a2244674Ee8b926",
661
+ symbol: "NNE",
662
+ name: "Nano Nuclear Energy \u2022 Robinhood Token",
663
+ decimals: 18,
664
+ uiMultiplierAtGeneration: "1000000000000000000",
665
+ feed: null,
666
+ feedDecimals: null
667
+ },
668
+ {
669
+ address: "0x0C3260aF4B8f13a69c4c2dFb84fD667890CDFa14",
670
+ symbol: "NOW",
671
+ name: "ServiceNow \u2022 Robinhood Token",
672
+ decimals: 18,
673
+ uiMultiplierAtGeneration: "1000000000000000000",
674
+ feed: null,
675
+ feedDecimals: null
676
+ },
677
+ {
678
+ address: "0x408c14038a04f7bD235329E26d2bf569ee20e250",
679
+ symbol: "NU",
680
+ name: "Nu \u2022 Robinhood Token",
681
+ decimals: 18,
682
+ uiMultiplierAtGeneration: "1000000000000000000",
683
+ feed: null,
684
+ feedDecimals: null
685
+ },
686
+ {
687
+ address: "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
688
+ symbol: "NVDA",
689
+ name: "NVIDIA \u2022 Robinhood Token",
690
+ decimals: 18,
691
+ uiMultiplierAtGeneration: "1000000000000000000",
692
+ feed: "0x379EC4f7C378F34a1B47E4F3cbeBCbAC3E8E9F15",
693
+ feedDecimals: 8,
694
+ feedAnswerAtGeneration: "21019000000",
695
+ feedUpdatedAtGeneration: 1783700623
696
+ },
697
+ {
698
+ address: "0xbE6702d7b70315376dC48a3293f24f0982F86386",
699
+ symbol: "NVTS",
700
+ name: "Navitas Semiconductor \u2022 Robinhood Token",
701
+ decimals: 18,
702
+ uiMultiplierAtGeneration: "1000000000000000000",
703
+ feed: null,
704
+ feedDecimals: null
705
+ },
706
+ {
707
+ address: "0xb0992820E760d836549ba69BC7598b4af75dEE03",
708
+ symbol: "ORCL",
709
+ name: "Oracle \u2022 Robinhood Token",
710
+ decimals: 18,
711
+ uiMultiplierAtGeneration: "1000000000000000000",
712
+ feed: "0x0e6a64a2B58A6693a531E6c555f3A5d042eEA844",
713
+ feedDecimals: 8,
714
+ feedAnswerAtGeneration: "14108370000",
715
+ feedUpdatedAtGeneration: 1783709137
716
+ },
717
+ {
718
+ address: "0x1Cdad396DB64BDa184d5182A97Dd9B3C62100b7D",
719
+ symbol: "P",
720
+ name: "Everpure \u2022 Robinhood Token",
721
+ decimals: 18,
722
+ uiMultiplierAtGeneration: "1000000000000000000",
723
+ feed: null,
724
+ feedDecimals: null
725
+ },
726
+ {
727
+ address: "0x9b23573b156B52565012F5cE02CDF60AFBaa70Be",
728
+ symbol: "PENG",
729
+ name: "Penguin Solutions \u2022 Robinhood Token",
730
+ decimals: 18,
731
+ uiMultiplierAtGeneration: "1000000000000000000",
732
+ feed: null,
733
+ feedDecimals: null
734
+ },
735
+ {
736
+ address: "0x894E1EC2D74FFE5AEF8Dc8A9e84686acCB964F2A",
737
+ symbol: "PLTR",
738
+ name: "Palantir Technologies \u2022 Robinhood Token",
739
+ decimals: 18,
740
+ uiMultiplierAtGeneration: "1000000000000000000",
741
+ feed: "0x820ABedFF239034956B7A9d2F0a331f9F075eB4c",
742
+ feedDecimals: 8,
743
+ feedAnswerAtGeneration: "12656140000",
744
+ feedUpdatedAtGeneration: 1783714557
745
+ },
746
+ {
747
+ address: "0xcf6B2D875361be807EAfa57458c80f28521F9333",
748
+ symbol: "POET",
749
+ name: "POET Technologies \u2022 Robinhood Token",
750
+ decimals: 18,
751
+ uiMultiplierAtGeneration: "1000000000000000000",
752
+ feed: null,
753
+ feedDecimals: null
754
+ },
755
+ {
756
+ address: "0x4189F0c66EBBB0bfeF1C31f763131361EF32f77C",
757
+ symbol: "PR",
758
+ name: "Permian Resources \u2022 Robinhood Token",
759
+ decimals: 18,
760
+ uiMultiplierAtGeneration: "1000000000000000000",
761
+ feed: null,
762
+ feedDecimals: null
763
+ },
764
+ {
765
+ address: "0xC583c60aeF9Dc401Da72cEC1B404743a93cea1Cc",
766
+ symbol: "QBTS",
767
+ name: "D-Wave Quantum \u2022 Robinhood Token",
768
+ decimals: 18,
769
+ uiMultiplierAtGeneration: "1000000000000000000",
770
+ feed: null,
771
+ feedDecimals: null
772
+ },
773
+ {
774
+ address: "0x0f17206447090e464C277571124dD2688E48AEA9",
775
+ symbol: "QCOM",
776
+ name: "Qualcomm \u2022 Robinhood Token",
777
+ decimals: 18,
778
+ uiMultiplierAtGeneration: "1000000000000000000",
779
+ feed: null,
780
+ feedDecimals: null
781
+ },
782
+ {
783
+ address: "0xD5f3879160bc7c32ebb4dC785F8a4F505888de68",
784
+ symbol: "QQQ",
785
+ name: "Invesco QQQ \u2022 Robinhood Token",
786
+ decimals: 18,
787
+ uiMultiplierAtGeneration: "1000000000000000000",
788
+ feed: "0x80901d846d5D7B030F26B480776EE3b29374C2ae",
789
+ feedDecimals: 8,
790
+ feedAnswerAtGeneration: "72545060000",
791
+ feedUpdatedAtGeneration: 1783702260
792
+ },
793
+ {
794
+ address: "0x59818904ab4cE163b3cE4FfB64f2D6Ca02c434B4",
795
+ symbol: "QUBT",
796
+ name: "Quantum Computing \u2022 Robinhood Token",
797
+ decimals: 18,
798
+ uiMultiplierAtGeneration: "1000000000000000000",
799
+ feed: null,
800
+ feedDecimals: null
801
+ },
802
+ {
803
+ address: "0xF0C4BF4C582cb3836e98394b1d4e7B7281101bE8",
804
+ symbol: "RBLX",
805
+ name: "Roblox \u2022 Robinhood Token",
806
+ decimals: 18,
807
+ uiMultiplierAtGeneration: "1000000000000000000",
808
+ feed: null,
809
+ feedDecimals: null
810
+ },
811
+ {
812
+ address: "0x05b37Fb53A299a1b874A619e1c4C404D52C36F4C",
813
+ symbol: "RDDT",
814
+ name: "Reddit \u2022 Robinhood Token",
815
+ decimals: 18,
816
+ uiMultiplierAtGeneration: "1000000000000000000",
817
+ feed: null,
818
+ feedDecimals: null
819
+ },
820
+ {
821
+ address: "0x92Ef19E82bD8fF36661DE838D5eaE7e5CEF0EfFE",
822
+ symbol: "RDW",
823
+ name: "Redwire \u2022 Robinhood Token",
824
+ decimals: 18,
825
+ uiMultiplierAtGeneration: "1000000000000000000",
826
+ feed: null,
827
+ feedDecimals: null
828
+ },
829
+ {
830
+ address: "0x284358abc07F9359f19f4b5b4aC91901Be2597Ba",
831
+ symbol: "RGTI",
832
+ name: "Rigetti Computing \u2022 Robinhood Token",
833
+ decimals: 18,
834
+ uiMultiplierAtGeneration: "1000000000000000000",
835
+ feed: "0x2A045cF1C49c61c166C036d2f06FA2D2d984f765",
836
+ feedDecimals: 8,
837
+ feedAnswerAtGeneration: "1657150813",
838
+ feedUpdatedAtGeneration: 1783713654
839
+ },
840
+ {
841
+ address: "0xB1BF26c1D20ff267A4f93550d1E0d06ac40a114B",
842
+ symbol: "RIVN",
843
+ name: "Rivian Automotive \u2022 Robinhood Token",
844
+ decimals: 18,
845
+ uiMultiplierAtGeneration: "1000000000000000000",
846
+ feed: null,
847
+ feedDecimals: null
848
+ },
849
+ {
850
+ address: "0x3b14C39E89D60D627b42a1A4CA45b5bb45Fc12e2",
851
+ symbol: "RKLB",
852
+ name: "Rocket Lab Corporation \u2022 Robinhood Token",
853
+ decimals: 18,
854
+ uiMultiplierAtGeneration: "1000000000000000000",
855
+ feed: "0x045477BF65Aef6f4F2386ad0164579e48381CC74",
856
+ feedDecimals: 8,
857
+ feedAnswerAtGeneration: "8128970000",
858
+ feedUpdatedAtGeneration: 1783726597
859
+ },
860
+ {
861
+ address: "0x95052ddcd5DC25641657424A8Cf04834997E1730",
862
+ symbol: "SATS",
863
+ name: "EchoStar \u2022 Robinhood Token",
864
+ decimals: 18,
865
+ uiMultiplierAtGeneration: "1000000000000000000",
866
+ feed: null,
867
+ feedDecimals: null
868
+ },
869
+ {
870
+ address: "0x92FD66527192E3e61d4DDd13322Aa222DE86F9B5",
871
+ symbol: "SGOV",
872
+ name: "iShares 0-3 Month Treasury Bond \u2022 Robinhood Token",
873
+ decimals: 18,
874
+ uiMultiplierAtGeneration: "1000957519890990718",
875
+ feed: "0xa0DF4ee0fFf975306345875E3548Fcc519577A11",
876
+ feedDecimals: 8,
877
+ feedAnswerAtGeneration: "10060428845",
878
+ feedUpdatedAtGeneration: 1783728100
879
+ },
880
+ {
881
+ address: "0xF53F66751B1Eff985311b693531E3290F600c410",
882
+ symbol: "SHOP",
883
+ name: "Shopify \u2022 Robinhood Token",
884
+ decimals: 18,
885
+ uiMultiplierAtGeneration: "1000000000000000000",
886
+ feed: null,
887
+ feedDecimals: null
888
+ },
889
+ {
890
+ address: "0x411eFb0E7f985935DAec3D4C3ebaEa0d0AD7D89f",
891
+ symbol: "SLV",
892
+ name: "iShares Silver Trust \u2022 Robinhood Token",
893
+ decimals: 18,
894
+ uiMultiplierAtGeneration: "1000000000000000000",
895
+ feed: "0x209b73908e92Ae021826eD79609845451Ecba2ce",
896
+ feedDecimals: 8,
897
+ feedAnswerAtGeneration: "5416490000",
898
+ feedUpdatedAtGeneration: 1783719808
899
+ },
900
+ {
901
+ address: "0xc01aA1fECeC0605b13bc84874ff7256C0f5F562a",
902
+ symbol: "SMCI",
903
+ name: "Super Micro Computer \u2022 Robinhood Token",
904
+ decimals: 18,
905
+ uiMultiplierAtGeneration: "1000000000000000000",
906
+ feed: null,
907
+ feedDecimals: null
908
+ },
909
+ {
910
+ address: "0xB90A19fF0Af67f7779afF50A882A9CfF42446400",
911
+ symbol: "SNDK",
912
+ name: "Sandisk Corporation \u2022 Robinhood Token",
913
+ decimals: 18,
914
+ uiMultiplierAtGeneration: "1000000000000000000",
915
+ feed: "0xfb133Fa4B7b385802B693a293606682Df47109A3",
916
+ feedDecimals: 8,
917
+ feedAnswerAtGeneration: "193162665000",
918
+ feedUpdatedAtGeneration: 1783727430
919
+ },
920
+ {
921
+ address: "0x98E75885157C80992A8D41b696D8c9C6Fb30A926",
922
+ symbol: "SOFI",
923
+ name: "SoFi Technologies \u2022 Robinhood Token",
924
+ decimals: 18,
925
+ uiMultiplierAtGeneration: "1000000000000000000",
926
+ feed: null,
927
+ feedDecimals: null
928
+ },
929
+ {
930
+ address: "0x75742c18BC1f1C5c5f448f4C9D9C6F66dafAAa38",
931
+ symbol: "SOXX",
932
+ name: "iShares Semiconductor ETF \u2022 Robinhood Token",
933
+ decimals: 18,
934
+ uiMultiplierAtGeneration: "1000000000000000000",
935
+ feed: null,
936
+ feedDecimals: null
937
+ },
938
+ {
939
+ address: "0x4a0E65A3EcceC6dBe60AE065F2e7bb85Fae35eEa",
940
+ symbol: "SPCX",
941
+ name: "Space Exploration Technologies Corp. Class A Common Stock \u2022 Robinhood Token",
942
+ decimals: 18,
943
+ uiMultiplierAtGeneration: "1000000000000000000",
944
+ feed: "0xB265810950ba6c5C0Ff821c9963014a56fD8Bffb",
945
+ feedDecimals: 8,
946
+ feedAnswerAtGeneration: "14572500000",
947
+ feedUpdatedAtGeneration: 1783713430
948
+ },
949
+ {
950
+ address: "0xAd622320e520de39e72d41EF07438C3Fd3354875",
951
+ symbol: "SPMO",
952
+ name: "Invesco S&P 500 Momentum ETF \u2022 Robinhood Token",
953
+ decimals: 18,
954
+ uiMultiplierAtGeneration: "1000000000000000000",
955
+ feed: null,
956
+ feedDecimals: null
957
+ },
958
+ {
959
+ address: "0x117cc2133c37B721F49dE2A7a74833232B3B4C0C",
960
+ symbol: "SPY",
961
+ name: "SPDR S&P 500 ETF Trust \u2022 Robinhood Token",
962
+ decimals: 18,
963
+ uiMultiplierAtGeneration: "1000000000000000000",
964
+ feed: "0x319724394D3A0e3669269846abE664Cd621f9f6A",
965
+ feedDecimals: 8,
966
+ feedAnswerAtGeneration: "75361500000",
967
+ feedUpdatedAtGeneration: 1783700203
968
+ },
969
+ {
970
+ address: "0x89776d4Cd68193597A2fC132cfaC1fDe36CCeA8a",
971
+ symbol: "TSEM",
972
+ name: "Tower Semiconductor \u2022 Robinhood Token",
973
+ decimals: 18,
974
+ uiMultiplierAtGeneration: "1000000000000000000",
975
+ feed: null,
976
+ feedDecimals: null
977
+ },
978
+ {
979
+ address: "0x322F0929c4625eD5bAd873c95208D54E1c003b2d",
980
+ symbol: "TSLA",
981
+ name: "Tesla \u2022 Robinhood Token",
982
+ decimals: 18,
983
+ uiMultiplierAtGeneration: "1000000000000000000",
984
+ feed: "0x4A1166a659A55625345e9515b32adECea5547C38",
985
+ feedDecimals: 8,
986
+ feedAnswerAtGeneration: "40782500000",
987
+ feedUpdatedAtGeneration: 1783713215
988
+ },
989
+ {
990
+ address: "0x58FfE4a942d3885bAa22D7520691F611EF09e7AA",
991
+ symbol: "TSM",
992
+ name: "Taiwan Semiconductor Manufacturing \u2022 Robinhood Token",
993
+ decimals: 18,
994
+ uiMultiplierAtGeneration: "1000000000000000000",
995
+ feed: "0x874cF94aa8eC88Fd9560094dD065f2fB3E41Fc2F",
996
+ feedDecimals: 8,
997
+ feedAnswerAtGeneration: "43437150000",
998
+ feedUpdatedAtGeneration: 1783713983
999
+ },
1000
+ {
1001
+ address: "0x5e81213613b6B86EaB4c6c50d718d34359459786",
1002
+ symbol: "TTWO",
1003
+ name: "Take-Two Interactive Software \u2022 Robinhood Token",
1004
+ decimals: 18,
1005
+ uiMultiplierAtGeneration: "1000000000000000000",
1006
+ feed: null,
1007
+ feedDecimals: null
1008
+ },
1009
+ {
1010
+ address: "0x0E6e67Ba88e7b5d9B67636A215c76779B948dE79",
1011
+ symbol: "UMC",
1012
+ name: "United Microelectronics \u2022 Robinhood Token",
1013
+ decimals: 18,
1014
+ uiMultiplierAtGeneration: "1000000000000000000",
1015
+ feed: null,
1016
+ feedDecimals: null
1017
+ },
1018
+ {
1019
+ address: "0xf23250dac154D05Bb671CB0d0eBEf3c635c79CE2",
1020
+ symbol: "UPS",
1021
+ name: "UPS \u2022 Robinhood Token",
1022
+ decimals: 18,
1023
+ uiMultiplierAtGeneration: "1000000000000000000",
1024
+ feed: null,
1025
+ feedDecimals: null
1026
+ },
1027
+ {
1028
+ address: "0xd917B029C761D264c6A312BBbcDA868658eF86a6",
1029
+ symbol: "USAR",
1030
+ name: "USA Rare Earth \u2022 Robinhood Token",
1031
+ decimals: 18,
1032
+ uiMultiplierAtGeneration: "1000000000000000000",
1033
+ feed: "0xA994d3684e8400A6c8078226925779FdeE682DD9",
1034
+ feedDecimals: 8,
1035
+ feedAnswerAtGeneration: "1853505000",
1036
+ feedUpdatedAtGeneration: 1783709442
1037
+ },
1038
+ {
1039
+ address: "0xa30FA36Db767ad9eD3f7a60fC79526fB4d56D344",
1040
+ symbol: "USO",
1041
+ name: "United States Oil Fund \u2022 Robinhood Token",
1042
+ decimals: 18,
1043
+ uiMultiplierAtGeneration: "1000000000000000000",
1044
+ feed: "0x75a9c76Ef439e2C7c2E5a34Ab105EcFe3766431c",
1045
+ feedDecimals: 8,
1046
+ feedAnswerAtGeneration: "10868500000",
1047
+ feedUpdatedAtGeneration: 1783708312
1048
+ },
1049
+ {
1050
+ address: "0x82DA4646242e1D962e96e932269Dc644c94a9CaA",
1051
+ symbol: "WDAY",
1052
+ name: "Workday \u2022 Robinhood Token",
1053
+ decimals: 18,
1054
+ uiMultiplierAtGeneration: "1000000000000000000",
1055
+ feed: null,
1056
+ feedDecimals: null
1057
+ },
1058
+ {
1059
+ address: "0xc93a8c440CEa26D7445dF01729f193b27965099f",
1060
+ symbol: "WEEK",
1061
+ name: "Roundhill Weekly T-Bill ETF \u2022 Robinhood Token",
1062
+ decimals: 18,
1063
+ uiMultiplierAtGeneration: "2006182524271844660",
1064
+ feed: null,
1065
+ feedDecimals: null
1066
+ },
1067
+ {
1068
+ address: "0x15Cd20759CE7F3285c29A319dE2D1A2e098c6f43",
1069
+ symbol: "XLK",
1070
+ name: "State Street Technology Select Sector SPDR ETF \u2022 Robinhood Token",
1071
+ decimals: 18,
1072
+ uiMultiplierAtGeneration: "1000000000000000000",
1073
+ feed: null,
1074
+ feedDecimals: null
1075
+ },
1076
+ {
1077
+ address: "0xA8eB3BCcbf2017eE7CBfb652eB51CF2E1B153289",
1078
+ symbol: "XNDU",
1079
+ name: "Xanadu Quantum \u2022 Robinhood Token",
1080
+ decimals: 18,
1081
+ uiMultiplierAtGeneration: "1000000000000000000",
1082
+ feed: null,
1083
+ feedDecimals: null
1084
+ },
1085
+ {
1086
+ address: "0xf9B46d3D1B22199D4D1025a9cEDB540A33F1a2d5",
1087
+ symbol: "XOM",
1088
+ name: "ExxonMobil Holdings Corporation \u2022 Robinhood Token",
1089
+ decimals: 18,
1090
+ uiMultiplierAtGeneration: "1000000000000000000",
1091
+ feed: null,
1092
+ feedDecimals: null
1093
+ },
1094
+ {
1095
+ address: "0x44c4F142009036cF477eD2d09932051843137CF1",
1096
+ symbol: "ZM",
1097
+ name: "Zoom \u2022 Robinhood Token",
1098
+ decimals: 18,
1099
+ uiMultiplierAtGeneration: "1000000000000000000",
1100
+ feed: null,
1101
+ feedDecimals: null
1102
+ },
1103
+ {
1104
+ address: "0x7dc013eB55e436f30d7ED1AFE4E36d6e45e3c3f7",
1105
+ symbol: "ZS",
1106
+ name: "Zscaler \u2022 Robinhood Token",
1107
+ decimals: 18,
1108
+ uiMultiplierAtGeneration: "1000000000000000000",
1109
+ feed: null,
1110
+ feedDecimals: null
1111
+ }
1112
+ ]
1113
+ };
1114
+ var registry = stock_tokens_default;
1115
+ var bySymbol = new Map(registry.tokens.map((t) => [t.symbol.toUpperCase(), t]));
1116
+ var byAddress = new Map(registry.tokens.map((t) => [t.address.toLowerCase(), t]));
1117
+ function getRegistry() {
1118
+ return registry;
1119
+ }
1120
+ function listStockTokens() {
1121
+ return registry.tokens;
1122
+ }
1123
+ function listPricedStockTokens() {
1124
+ return registry.tokens.filter((t) => t.feed !== null);
1125
+ }
1126
+ function getStockToken(symbol) {
1127
+ const token = bySymbol.get(symbol.toUpperCase());
1128
+ if (!token) throw new UnknownSymbolError(symbol);
1129
+ return token;
1130
+ }
1131
+ function getStockTokenByAddress(address) {
1132
+ return byAddress.get(address.toLowerCase()) ?? null;
1133
+ }
1134
+ function isStockTokenSymbol(symbol) {
1135
+ return bySymbol.has(symbol.toUpperCase());
1136
+ }
1137
+ function isStockTokenAddress(address) {
1138
+ return byAddress.has(address.toLowerCase());
1139
+ }
1140
+ var erc20Abi = [
1141
+ { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
1142
+ { type: "function", name: "symbol", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
1143
+ { type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
1144
+ { type: "function", name: "totalSupply", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
1145
+ {
1146
+ type: "function",
1147
+ name: "balanceOf",
1148
+ stateMutability: "view",
1149
+ inputs: [{ name: "account", type: "address" }],
1150
+ outputs: [{ type: "uint256" }]
1151
+ },
1152
+ {
1153
+ type: "function",
1154
+ name: "allowance",
1155
+ stateMutability: "view",
1156
+ inputs: [
1157
+ { name: "owner", type: "address" },
1158
+ { name: "spender", type: "address" }
1159
+ ],
1160
+ outputs: [{ type: "uint256" }]
1161
+ },
1162
+ {
1163
+ type: "function",
1164
+ name: "transfer",
1165
+ stateMutability: "nonpayable",
1166
+ inputs: [
1167
+ { name: "to", type: "address" },
1168
+ { name: "amount", type: "uint256" }
1169
+ ],
1170
+ outputs: [{ type: "bool" }]
1171
+ },
1172
+ {
1173
+ type: "function",
1174
+ name: "approve",
1175
+ stateMutability: "nonpayable",
1176
+ inputs: [
1177
+ { name: "spender", type: "address" },
1178
+ { name: "amount", type: "uint256" }
1179
+ ],
1180
+ outputs: [{ type: "bool" }]
1181
+ },
1182
+ {
1183
+ type: "function",
1184
+ name: "transferFrom",
1185
+ stateMutability: "nonpayable",
1186
+ inputs: [
1187
+ { name: "from", type: "address" },
1188
+ { name: "to", type: "address" },
1189
+ { name: "amount", type: "uint256" }
1190
+ ],
1191
+ outputs: [{ type: "bool" }]
1192
+ },
1193
+ {
1194
+ type: "event",
1195
+ name: "Transfer",
1196
+ inputs: [
1197
+ { name: "from", type: "address", indexed: true },
1198
+ { name: "to", type: "address", indexed: true },
1199
+ { name: "value", type: "uint256", indexed: false }
1200
+ ]
1201
+ },
1202
+ {
1203
+ type: "event",
1204
+ name: "Approval",
1205
+ inputs: [
1206
+ { name: "owner", type: "address", indexed: true },
1207
+ { name: "spender", type: "address", indexed: true },
1208
+ { name: "value", type: "uint256", indexed: false }
1209
+ ]
1210
+ }
1211
+ ];
1212
+ var stockTokenAbi = [
1213
+ ...erc20Abi,
1214
+ /** Shares-per-token ratio, scaled by 1e18 (ERC-8056). */
1215
+ { type: "function", name: "uiMultiplier", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
1216
+ /** Pending multiplier that takes effect at `effectiveAt`. */
1217
+ { type: "function", name: "newUIMultiplier", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
1218
+ /** Timestamp at which `newUIMultiplier` becomes active. */
1219
+ { type: "function", name: "effectiveAt", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
1220
+ /** Share-equivalent balance: `balanceOf(a) * uiMultiplier / 1e18`, computed on-chain. */
1221
+ {
1222
+ type: "function",
1223
+ name: "balanceOfUI",
1224
+ stateMutability: "view",
1225
+ inputs: [{ name: "account", type: "address" }],
1226
+ outputs: [{ type: "uint256" }]
1227
+ },
1228
+ /** Share-equivalent total supply. */
1229
+ { type: "function", name: "totalSupplyUI", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
1230
+ { type: "function", name: "paused", stateMutability: "view", inputs: [], outputs: [{ type: "bool" }] },
1231
+ { type: "function", name: "tokenPaused", stateMutability: "view", inputs: [], outputs: [{ type: "bool" }] },
1232
+ { type: "function", name: "oraclePaused", stateMutability: "view", inputs: [], outputs: [{ type: "bool" }] },
1233
+ /** Issuer terms URI. */
1234
+ { type: "function", name: "terms", stateMutability: "pure", inputs: [], outputs: [{ type: "string" }] },
1235
+ { type: "function", name: "uid", stateMutability: "view", inputs: [], outputs: [{ type: "bytes32" }] },
1236
+ {
1237
+ type: "function",
1238
+ name: "nonces",
1239
+ stateMutability: "view",
1240
+ inputs: [{ name: "owner", type: "address" }],
1241
+ outputs: [{ type: "uint256" }]
1242
+ },
1243
+ {
1244
+ type: "function",
1245
+ name: "permit",
1246
+ stateMutability: "nonpayable",
1247
+ inputs: [
1248
+ { name: "owner", type: "address" },
1249
+ { name: "spender", type: "address" },
1250
+ { name: "value", type: "uint256" },
1251
+ { name: "deadline", type: "uint256" },
1252
+ { name: "v", type: "uint8" },
1253
+ { name: "r", type: "bytes32" },
1254
+ { name: "s", type: "bytes32" }
1255
+ ],
1256
+ outputs: []
1257
+ }
1258
+ ];
1259
+ var aggregatorV3Abi = [
1260
+ { type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
1261
+ { type: "function", name: "description", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
1262
+ {
1263
+ type: "function",
1264
+ name: "latestRoundData",
1265
+ stateMutability: "view",
1266
+ inputs: [],
1267
+ outputs: [
1268
+ { name: "roundId", type: "uint80" },
1269
+ { name: "answer", type: "int256" },
1270
+ { name: "startedAt", type: "uint256" },
1271
+ { name: "updatedAt", type: "uint256" },
1272
+ { name: "answeredInRound", type: "uint80" }
1273
+ ]
1274
+ }
1275
+ ];
1276
+ var quoterV2Abi = [
1277
+ {
1278
+ type: "function",
1279
+ name: "quoteExactInputSingle",
1280
+ stateMutability: "nonpayable",
1281
+ inputs: [
1282
+ {
1283
+ name: "params",
1284
+ type: "tuple",
1285
+ components: [
1286
+ { name: "tokenIn", type: "address" },
1287
+ { name: "tokenOut", type: "address" },
1288
+ { name: "amountIn", type: "uint256" },
1289
+ { name: "fee", type: "uint24" },
1290
+ { name: "sqrtPriceLimitX96", type: "uint160" }
1291
+ ]
1292
+ }
1293
+ ],
1294
+ outputs: [
1295
+ { name: "amountOut", type: "uint256" },
1296
+ { name: "sqrtPriceX96After", type: "uint160" },
1297
+ { name: "initializedTicksCrossed", type: "uint32" },
1298
+ { name: "gasEstimate", type: "uint256" }
1299
+ ]
1300
+ },
1301
+ {
1302
+ type: "function",
1303
+ name: "quoteExactInput",
1304
+ stateMutability: "nonpayable",
1305
+ inputs: [
1306
+ { name: "path", type: "bytes" },
1307
+ { name: "amountIn", type: "uint256" }
1308
+ ],
1309
+ outputs: [
1310
+ { name: "amountOut", type: "uint256" },
1311
+ { name: "sqrtPriceX96AfterList", type: "uint160[]" },
1312
+ { name: "initializedTicksCrossedList", type: "uint32[]" },
1313
+ { name: "gasEstimate", type: "uint256" }
1314
+ ]
1315
+ },
1316
+ { type: "function", name: "factory", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] },
1317
+ { type: "function", name: "WETH9", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] }
1318
+ ];
1319
+ var swapRouter02Abi = [
1320
+ {
1321
+ type: "function",
1322
+ name: "exactInputSingle",
1323
+ stateMutability: "payable",
1324
+ inputs: [
1325
+ {
1326
+ name: "params",
1327
+ type: "tuple",
1328
+ components: [
1329
+ { name: "tokenIn", type: "address" },
1330
+ { name: "tokenOut", type: "address" },
1331
+ { name: "fee", type: "uint24" },
1332
+ { name: "recipient", type: "address" },
1333
+ { name: "amountIn", type: "uint256" },
1334
+ { name: "amountOutMinimum", type: "uint256" },
1335
+ { name: "sqrtPriceLimitX96", type: "uint160" }
1336
+ ]
1337
+ }
1338
+ ],
1339
+ outputs: [{ name: "amountOut", type: "uint256" }]
1340
+ },
1341
+ {
1342
+ type: "function",
1343
+ name: "exactInput",
1344
+ stateMutability: "payable",
1345
+ inputs: [
1346
+ {
1347
+ name: "params",
1348
+ type: "tuple",
1349
+ components: [
1350
+ { name: "path", type: "bytes" },
1351
+ { name: "recipient", type: "address" },
1352
+ { name: "amountIn", type: "uint256" },
1353
+ { name: "amountOutMinimum", type: "uint256" }
1354
+ ]
1355
+ }
1356
+ ],
1357
+ outputs: [{ name: "amountOut", type: "uint256" }]
1358
+ },
1359
+ {
1360
+ type: "function",
1361
+ name: "multicall",
1362
+ stateMutability: "payable",
1363
+ inputs: [
1364
+ { name: "deadline", type: "uint256" },
1365
+ { name: "data", type: "bytes[]" }
1366
+ ],
1367
+ outputs: [{ name: "results", type: "bytes[]" }]
1368
+ },
1369
+ { type: "function", name: "factory", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] },
1370
+ { type: "function", name: "WETH9", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] }
1371
+ ];
1372
+ var swapRouterAbi = [
1373
+ {
1374
+ type: "function",
1375
+ name: "exactInputSingle",
1376
+ stateMutability: "payable",
1377
+ inputs: [
1378
+ {
1379
+ name: "params",
1380
+ type: "tuple",
1381
+ components: [
1382
+ { name: "tokenIn", type: "address" },
1383
+ { name: "tokenOut", type: "address" },
1384
+ { name: "fee", type: "uint24" },
1385
+ { name: "recipient", type: "address" },
1386
+ { name: "deadline", type: "uint256" },
1387
+ { name: "amountIn", type: "uint256" },
1388
+ { name: "amountOutMinimum", type: "uint256" },
1389
+ { name: "sqrtPriceLimitX96", type: "uint160" }
1390
+ ]
1391
+ }
1392
+ ],
1393
+ outputs: [{ name: "amountOut", type: "uint256" }]
1394
+ },
1395
+ {
1396
+ type: "function",
1397
+ name: "exactInput",
1398
+ stateMutability: "payable",
1399
+ inputs: [
1400
+ {
1401
+ name: "params",
1402
+ type: "tuple",
1403
+ components: [
1404
+ { name: "path", type: "bytes" },
1405
+ { name: "recipient", type: "address" },
1406
+ { name: "deadline", type: "uint256" },
1407
+ { name: "amountIn", type: "uint256" },
1408
+ { name: "amountOutMinimum", type: "uint256" }
1409
+ ]
1410
+ }
1411
+ ],
1412
+ outputs: [{ name: "amountOut", type: "uint256" }]
1413
+ },
1414
+ { type: "function", name: "factory", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] },
1415
+ { type: "function", name: "WETH9", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] }
1416
+ ];
1417
+ var weth9Abi = [
1418
+ ...erc20Abi,
1419
+ { type: "function", name: "deposit", stateMutability: "payable", inputs: [], outputs: [] },
1420
+ {
1421
+ type: "function",
1422
+ name: "withdraw",
1423
+ stateMutability: "nonpayable",
1424
+ inputs: [{ name: "wad", type: "uint256" }],
1425
+ outputs: []
1426
+ }
1427
+ ];
1428
+ var uniswapV3FactoryAbi = [
1429
+ {
1430
+ type: "function",
1431
+ name: "getPool",
1432
+ stateMutability: "view",
1433
+ inputs: [
1434
+ { name: "tokenA", type: "address" },
1435
+ { name: "tokenB", type: "address" },
1436
+ { name: "fee", type: "uint24" }
1437
+ ],
1438
+ outputs: [{ type: "address" }]
1439
+ }
1440
+ ];
1441
+ var uniswapV3PoolAbi = [
1442
+ { type: "function", name: "liquidity", stateMutability: "view", inputs: [], outputs: [{ type: "uint128" }] },
1443
+ {
1444
+ type: "function",
1445
+ name: "slot0",
1446
+ stateMutability: "view",
1447
+ inputs: [],
1448
+ outputs: [
1449
+ { name: "sqrtPriceX96", type: "uint160" },
1450
+ { name: "tick", type: "int24" },
1451
+ { name: "observationIndex", type: "uint16" },
1452
+ { name: "observationCardinality", type: "uint16" },
1453
+ { name: "observationCardinalityNext", type: "uint16" },
1454
+ { name: "feeProtocol", type: "uint8" },
1455
+ { name: "unlocked", type: "bool" }
1456
+ ]
1457
+ }
1458
+ ];
1459
+ var DEFAULT_MAX_FEED_AGE_SECONDS = 3 * 24 * 60 * 60;
1460
+ async function getQuote(client, symbol, options = {}) {
1461
+ const token = getStockToken(symbol);
1462
+ if (!token.feed) throw new FeedNotFoundError(token.symbol);
1463
+ const [roundId, answer, , updatedAtRaw] = await client.public.readContract({
1464
+ address: token.feed,
1465
+ abi: aggregatorV3Abi,
1466
+ functionName: "latestRoundData"
1467
+ });
1468
+ return toQuote(token, { roundId, answer, updatedAt: Number(updatedAtRaw) }, options);
1469
+ }
1470
+ function toQuote(token, round, options) {
1471
+ const maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_MAX_FEED_AGE_SECONDS;
1472
+ const answerDecimals = token.feedDecimals ?? 8;
1473
+ if (round.answer <= 0n) {
1474
+ throw new InvalidFeedAnswerError(token.symbol, `answer=${round.answer}`);
1475
+ }
1476
+ if (round.updatedAt === 0) {
1477
+ throw new InvalidFeedAnswerError(token.symbol, "round not complete (updatedAt=0)");
1478
+ }
1479
+ const ageSeconds = Math.max(0, Math.floor(Date.now() / 1e3) - round.updatedAt);
1480
+ if (ageSeconds > maxAgeSeconds) {
1481
+ throw new StaleFeedError(token.symbol, round.updatedAt, ageSeconds, maxAgeSeconds);
1482
+ }
1483
+ return {
1484
+ symbol: token.symbol,
1485
+ address: token.address,
1486
+ feed: token.feed,
1487
+ priceUsd: Number(formatUnits(round.answer, answerDecimals)),
1488
+ answer: round.answer,
1489
+ answerDecimals,
1490
+ roundId: round.roundId,
1491
+ updatedAt: round.updatedAt,
1492
+ ageSeconds
1493
+ };
1494
+ }
1495
+ async function getMultiplier(client, symbol) {
1496
+ const token = getStockToken(symbol);
1497
+ try {
1498
+ return await client.public.readContract({
1499
+ address: token.address,
1500
+ abi: stockTokenAbi,
1501
+ functionName: "uiMultiplier"
1502
+ });
1503
+ } catch {
1504
+ return null;
1505
+ }
1506
+ }
1507
+ async function getPosition(client, owner, symbol, options = {}) {
1508
+ const token = getStockToken(symbol);
1509
+ const [position] = await readPositions(client, owner, [token], options);
1510
+ return position;
1511
+ }
1512
+ async function getPortfolio(client, owner, options = {}) {
1513
+ const tokens = listStockTokens();
1514
+ const balances = await client.public.multicall({
1515
+ contracts: tokens.map((t) => ({
1516
+ address: t.address,
1517
+ abi: stockTokenAbi,
1518
+ functionName: "balanceOf",
1519
+ args: [owner]
1520
+ })),
1521
+ allowFailure: false
1522
+ });
1523
+ const held = tokens.filter((_, i) => balances[i] > 0n);
1524
+ const positions = await readPositions(client, owner, held, options);
1525
+ const priced = positions.filter((p) => p.valueUsd !== null);
1526
+ return {
1527
+ owner,
1528
+ positions,
1529
+ totalUsd: priced.reduce((sum, p) => sum + p.valueUsd, 0),
1530
+ unpricedSymbols: positions.filter((p) => p.valueUsd === null).map((p) => p.symbol)
1531
+ };
1532
+ }
1533
+ async function readPositions(client, owner, tokens, options) {
1534
+ if (tokens.length === 0) return [];
1535
+ const reads = await client.public.multicall({
1536
+ contracts: tokens.flatMap((t) => [
1537
+ { address: t.address, abi: stockTokenAbi, functionName: "balanceOf", args: [owner] },
1538
+ { address: t.address, abi: stockTokenAbi, functionName: "uiMultiplier" }
1539
+ ]),
1540
+ allowFailure: false
1541
+ });
1542
+ const feedTokens = tokens.filter((t) => t.feed !== null);
1543
+ const feedReads = await client.public.multicall({
1544
+ contracts: feedTokens.map((t) => ({
1545
+ address: t.feed,
1546
+ abi: aggregatorV3Abi,
1547
+ functionName: "latestRoundData"
1548
+ })),
1549
+ allowFailure: true
1550
+ });
1551
+ const quoteBySymbol = /* @__PURE__ */ new Map();
1552
+ feedTokens.forEach((t, i) => {
1553
+ const read = feedReads[i];
1554
+ if (!read || read.status !== "success") {
1555
+ quoteBySymbol.set(t.symbol, null);
1556
+ return;
1557
+ }
1558
+ const [roundId, answer, , updatedAt] = read.result;
1559
+ try {
1560
+ quoteBySymbol.set(t.symbol, toQuote(t, { roundId, answer, updatedAt: Number(updatedAt) }, options));
1561
+ } catch {
1562
+ quoteBySymbol.set(t.symbol, null);
1563
+ }
1564
+ });
1565
+ return tokens.map((t, i) => {
1566
+ const balance = reads[i * 2];
1567
+ const uiMultiplier = reads[i * 2 + 1];
1568
+ const balanceTokens = Number(formatUnits(balance, t.decimals));
1569
+ const quote = quoteBySymbol.get(t.symbol) ?? null;
1570
+ return {
1571
+ symbol: t.symbol,
1572
+ address: t.address,
1573
+ balance,
1574
+ balanceTokens,
1575
+ uiMultiplier,
1576
+ shareEquivalent: Number(formatUnits(balance * uiMultiplier / 10n ** 18n, t.decimals)),
1577
+ valueUsd: quote ? balanceTokens * quote.priceUsd : null,
1578
+ quote
1579
+ };
1580
+ });
1581
+ }
1582
+ function swapAddresses(client) {
1583
+ if (client.network === "testnet") {
1584
+ return {
1585
+ quoterV2: TESTNET_ADDRESSES.quoterV2,
1586
+ router: TESTNET_ADDRESSES.swapRouter,
1587
+ routerKind: "swapRouter",
1588
+ weth: TESTNET_ADDRESSES.weth,
1589
+ usdg: TESTNET_ADDRESSES.usdg
1590
+ };
1591
+ }
1592
+ return {
1593
+ quoterV2: MAINNET_ADDRESSES.quoterV2,
1594
+ router: MAINNET_ADDRESSES.swapRouter02,
1595
+ routerKind: "swapRouter02",
1596
+ weth: MAINNET_ADDRESSES.weth,
1597
+ usdg: MAINNET_ADDRESSES.usdg
1598
+ };
1599
+ }
1600
+ function encodePath(path, fees) {
1601
+ const types = [];
1602
+ const values = [];
1603
+ path.forEach((token, i) => {
1604
+ types.push("address");
1605
+ values.push(token);
1606
+ if (i < fees.length) {
1607
+ types.push("uint24");
1608
+ values.push(fees[i]);
1609
+ }
1610
+ });
1611
+ return encodePacked(types, values);
1612
+ }
1613
+ async function quoteSwap(client, args, options = {}) {
1614
+ const { quoterV2, weth, usdg } = swapAddresses(client);
1615
+ const { tokenIn, tokenOut, amountIn } = args;
1616
+ const feeTiers = options.feeTiers ?? V3_FEE_TIERS;
1617
+ const candidates = [];
1618
+ for (const fee of feeTiers) {
1619
+ candidates.push({ fees: [fee], path: [tokenIn, tokenOut], encodedPath: encodePath([tokenIn, tokenOut], [fee]) });
1620
+ }
1621
+ const intermediates = (options.intermediates ?? [weth, usdg]).filter(
1622
+ (mid) => mid.toLowerCase() !== tokenIn.toLowerCase() && mid.toLowerCase() !== tokenOut.toLowerCase()
1623
+ );
1624
+ for (const mid of intermediates) {
1625
+ for (const feeA of [500, 3e3]) {
1626
+ for (const feeB of [500, 3e3]) {
1627
+ candidates.push({
1628
+ fees: [feeA, feeB],
1629
+ path: [tokenIn, mid, tokenOut],
1630
+ encodedPath: encodePath([tokenIn, mid, tokenOut], [feeA, feeB])
1631
+ });
1632
+ }
1633
+ }
1634
+ }
1635
+ const results = await Promise.all(
1636
+ candidates.map(async (route) => {
1637
+ try {
1638
+ if (route.fees.length === 1) {
1639
+ const { result: result2 } = await client.public.simulateContract({
1640
+ address: quoterV2,
1641
+ abi: quoterV2Abi,
1642
+ functionName: "quoteExactInputSingle",
1643
+ args: [
1644
+ {
1645
+ tokenIn,
1646
+ tokenOut,
1647
+ amountIn,
1648
+ fee: route.fees[0],
1649
+ sqrtPriceLimitX96: 0n
1650
+ }
1651
+ ]
1652
+ });
1653
+ return { route, amountIn, amountOut: result2[0], gasEstimate: result2[3] };
1654
+ }
1655
+ const { result } = await client.public.simulateContract({
1656
+ address: quoterV2,
1657
+ abi: quoterV2Abi,
1658
+ functionName: "quoteExactInput",
1659
+ args: [route.encodedPath, amountIn]
1660
+ });
1661
+ return { route, amountIn, amountOut: result[0], gasEstimate: result[3] };
1662
+ } catch {
1663
+ return null;
1664
+ }
1665
+ })
1666
+ );
1667
+ const best = results.filter((q) => q !== null && q.amountOut > 0n).sort((a, b) => b.amountOut > a.amountOut ? 1 : b.amountOut < a.amountOut ? -1 : 0)[0];
1668
+ if (!best) {
1669
+ throw new NoRouteError(
1670
+ tokenIn,
1671
+ tokenOut,
1672
+ `no direct pool (fees ${feeTiers.join("/")}) or two-hop route via ${intermediates.length} intermediates produced output for amountIn=${amountIn}`
1673
+ );
1674
+ }
1675
+ return best;
1676
+ }
1677
+ function buildSwapTx(client, quote, options = {}) {
1678
+ const { router, routerKind } = swapAddresses(client);
1679
+ const tokenOut = quote.route.path[quote.route.path.length - 1];
1680
+ if (client.network === "mainnet" && isStockTokenAddress(tokenOut) && !client.acknowledgeStockTokenEligibility) {
1681
+ throw new StockTokenEligibilityError();
1682
+ }
1683
+ const recipient = options.recipient ?? client.account?.address;
1684
+ if (!recipient) throw new NoAccountError("buildSwapTx (or pass options.recipient)");
1685
+ const slippageBps = options.slippageBps ?? 50;
1686
+ const amountOutMinimum = quote.amountOut * BigInt(1e4 - slippageBps) / 10000n;
1687
+ const deadline = BigInt(Math.floor(Date.now() / 1e3) + (options.deadlineSeconds ?? 600));
1688
+ const singleHop = quote.route.fees.length === 1;
1689
+ let data;
1690
+ if (routerKind === "swapRouter") {
1691
+ data = singleHop ? encodeFunctionData({
1692
+ abi: swapRouterAbi,
1693
+ functionName: "exactInputSingle",
1694
+ args: [
1695
+ {
1696
+ tokenIn: quote.route.path[0],
1697
+ tokenOut,
1698
+ fee: quote.route.fees[0],
1699
+ recipient,
1700
+ deadline,
1701
+ amountIn: quote.amountIn,
1702
+ amountOutMinimum,
1703
+ sqrtPriceLimitX96: 0n
1704
+ }
1705
+ ]
1706
+ }) : encodeFunctionData({
1707
+ abi: swapRouterAbi,
1708
+ functionName: "exactInput",
1709
+ args: [
1710
+ {
1711
+ path: quote.route.encodedPath,
1712
+ recipient,
1713
+ deadline,
1714
+ amountIn: quote.amountIn,
1715
+ amountOutMinimum
1716
+ }
1717
+ ]
1718
+ });
1719
+ } else {
1720
+ const inner = singleHop ? encodeFunctionData({
1721
+ abi: swapRouter02Abi,
1722
+ functionName: "exactInputSingle",
1723
+ args: [
1724
+ {
1725
+ tokenIn: quote.route.path[0],
1726
+ tokenOut,
1727
+ fee: quote.route.fees[0],
1728
+ recipient,
1729
+ amountIn: quote.amountIn,
1730
+ amountOutMinimum,
1731
+ sqrtPriceLimitX96: 0n
1732
+ }
1733
+ ]
1734
+ }) : encodeFunctionData({
1735
+ abi: swapRouter02Abi,
1736
+ functionName: "exactInput",
1737
+ args: [
1738
+ {
1739
+ path: quote.route.encodedPath,
1740
+ recipient,
1741
+ amountIn: quote.amountIn,
1742
+ amountOutMinimum
1743
+ }
1744
+ ]
1745
+ });
1746
+ data = encodeFunctionData({
1747
+ abi: swapRouter02Abi,
1748
+ functionName: "multicall",
1749
+ args: [deadline, [inner]]
1750
+ });
1751
+ }
1752
+ return { to: router, data, value: 0n, quote, amountOutMinimum, deadline };
1753
+ }
1754
+ async function ensureApproval(client, token, amount) {
1755
+ if (!client.wallet || !client.account) throw new NoAccountError("ensureApproval");
1756
+ const { router } = swapAddresses(client);
1757
+ const allowance = await client.public.readContract({
1758
+ address: token,
1759
+ abi: erc20Abi,
1760
+ functionName: "allowance",
1761
+ args: [client.account.address, router]
1762
+ });
1763
+ if (allowance >= amount) return null;
1764
+ const hash = await client.wallet.writeContract({
1765
+ address: token,
1766
+ abi: erc20Abi,
1767
+ functionName: "approve",
1768
+ args: [router, amount]
1769
+ });
1770
+ await client.public.waitForTransactionReceipt({ hash });
1771
+ return hash;
1772
+ }
1773
+ async function executeSwap(client, args, options = {}) {
1774
+ if (!client.wallet || !client.account) throw new NoAccountError("executeSwap");
1775
+ const quote = await quoteSwap(client, args, options);
1776
+ const tx = buildSwapTx(client, quote, options);
1777
+ await ensureApproval(client, args.tokenIn, args.amountIn);
1778
+ const hash = await client.wallet.sendTransaction({
1779
+ to: tx.to,
1780
+ data: tx.data,
1781
+ value: tx.value,
1782
+ account: client.account,
1783
+ chain: client.chain
1784
+ });
1785
+ const receipt = await client.public.waitForTransactionReceipt({ hash });
1786
+ return { hash, receipt, quote, amountOutMinimum: tx.amountOutMinimum };
1787
+ }
1788
+ function usdgAddress(client) {
1789
+ return client.network === "testnet" ? TESTNET_ADDRESSES.usdg : MAINNET_ADDRESSES.usdg;
1790
+ }
1791
+ function formatUsdg(amount) {
1792
+ return formatUnits2(amount, USDG_DECIMALS);
1793
+ }
1794
+ function parseUsdg(amount) {
1795
+ return parseUnits(amount, USDG_DECIMALS);
1796
+ }
1797
+ async function getUsdgBalance(client, owner) {
1798
+ return client.public.readContract({
1799
+ address: usdgAddress(client),
1800
+ abi: erc20Abi,
1801
+ functionName: "balanceOf",
1802
+ args: [owner]
1803
+ });
1804
+ }
1805
+ async function getUsdgTotalSupply(client) {
1806
+ return client.public.readContract({
1807
+ address: usdgAddress(client),
1808
+ abi: erc20Abi,
1809
+ functionName: "totalSupply"
1810
+ });
1811
+ }
1812
+ async function transferUsdg(client, to, amount) {
1813
+ if (!client.wallet) throw new NoAccountError("transferUsdg");
1814
+ return client.wallet.writeContract({
1815
+ address: usdgAddress(client),
1816
+ abi: erc20Abi,
1817
+ functionName: "transfer",
1818
+ args: [to, amount]
1819
+ });
1820
+ }
1821
+ async function approveUsdg(client, spender, amount) {
1822
+ if (!client.wallet) throw new NoAccountError("approveUsdg");
1823
+ return client.wallet.writeContract({
1824
+ address: usdgAddress(client),
1825
+ abi: erc20Abi,
1826
+ functionName: "approve",
1827
+ args: [spender, amount]
1828
+ });
1829
+ }
1830
+ async function getUsdgAllowance(client, owner, spender) {
1831
+ return client.public.readContract({
1832
+ address: usdgAddress(client),
1833
+ abi: erc20Abi,
1834
+ functionName: "allowance",
1835
+ args: [owner, spender]
1836
+ });
1837
+ }
1838
+ var NOXA_ADDRESSES = {
1839
+ launchFactory: "0xD9eC2db5f3D1b236843925949fe5bd8a3836FCcB",
1840
+ locker: "0x7F03effbd7ceB22A3f80Dd468f67eF27826acD85",
1841
+ feeRouter: "0x9eFdC1A8e6E94f16A228e44f3025E1f346EE0417",
1842
+ /** First block with factory activity — lower bound for historical scans. */
1843
+ deployBlock: 61688n
1844
+ };
1845
+ var ODYSSEY_ADDRESSES = {
1846
+ /** Current bonding-curve factory. */
1847
+ bondingCurveFactory: "0xEb3FeeD2716cF0eEAda05B22e67424794e1f5a80",
1848
+ /** Variant that pays reflections in a reward token. */
1849
+ reflectionFactory: "0x6Ce85c4b7cE12903E5867652C265bCcce57f935F",
1850
+ /** Variant that skips the curve and lists instantly. */
1851
+ instantFactory: "0xD7601cEe401306fdea5833c6898181D9c770F800",
1852
+ robinLock: "0x5B41D59Fa0ce65750bc64e06D85bC999084493CD",
1853
+ /** Legacy first-generation factory (still emits historical launches). */
1854
+ legacyFactory: "0xAf9f3ce1d34909F59E88c23027f89d5807B0F915"
1855
+ };
1856
+ var noxaTokenLaunchedEvent = {
1857
+ type: "event",
1858
+ name: "TokenLaunched",
1859
+ inputs: [
1860
+ { name: "token", type: "address", indexed: true },
1861
+ { name: "deployer", type: "address", indexed: true },
1862
+ { name: "dexFactory", type: "address", indexed: true },
1863
+ { name: "pairToken", type: "address", indexed: false },
1864
+ { name: "pool", type: "address", indexed: false },
1865
+ { name: "dexId", type: "uint256", indexed: false },
1866
+ { name: "launchConfigId", type: "uint256", indexed: false },
1867
+ { name: "positionId", type: "uint256", indexed: false },
1868
+ { name: "restrictionsEndBlock", type: "uint256", indexed: false },
1869
+ { name: "initialBuyAmount", type: "uint256", indexed: false }
1870
+ ]
1871
+ };
1872
+ var odysseyTokenCreatedEvent = {
1873
+ type: "event",
1874
+ name: "TokenCreated",
1875
+ inputs: [
1876
+ { name: "token", type: "address", indexed: true },
1877
+ { name: "creator", type: "address", indexed: true },
1878
+ { name: "backingWallet", type: "address", indexed: false },
1879
+ { name: "isMarginBacked", type: "bool", indexed: false },
1880
+ { name: "threshold", type: "uint256", indexed: false }
1881
+ ]
1882
+ };
1883
+ var odysseyTradedEvent = {
1884
+ type: "event",
1885
+ name: "Traded",
1886
+ inputs: [
1887
+ { name: "token", type: "address", indexed: true },
1888
+ { name: "trader", type: "address", indexed: true },
1889
+ { name: "isBuy", type: "bool", indexed: false },
1890
+ { name: "tokenAmount", type: "uint256", indexed: false },
1891
+ { name: "quoteAmount", type: "uint256", indexed: false },
1892
+ { name: "fee", type: "uint256", indexed: false },
1893
+ { name: "virtualQuote", type: "uint256", indexed: false },
1894
+ { name: "virtualToken", type: "uint256", indexed: false }
1895
+ ]
1896
+ };
1897
+ var odysseyPoolMigratedEvent = {
1898
+ type: "event",
1899
+ name: "PoolMigrated",
1900
+ inputs: [
1901
+ { name: "token", type: "address", indexed: true },
1902
+ { name: "pool", type: "address", indexed: false },
1903
+ { name: "tokenId", type: "uint256", indexed: false },
1904
+ { name: "liquidity", type: "uint128", indexed: false },
1905
+ { name: "tokenUsed", type: "uint256", indexed: false },
1906
+ { name: "usdcUsed", type: "uint256", indexed: false }
1907
+ ]
1908
+ };
1909
+ var ODYSSEY_FACTORIES = [
1910
+ ODYSSEY_ADDRESSES.bondingCurveFactory,
1911
+ ODYSSEY_ADDRESSES.reflectionFactory,
1912
+ ODYSSEY_ADDRESSES.instantFactory
1913
+ ];
1914
+ async function getRecentLaunches(client, options = {}) {
1915
+ const latest = await client.public.getBlockNumber();
1916
+ const lookback = options.lookbackBlocks ?? 30000n;
1917
+ const chunk = options.chunkSize ?? 10000n;
1918
+ const fromBlock = latest > lookback ? latest - lookback : 0n;
1919
+ const launches = [];
1920
+ for (let start = fromBlock; start <= latest; start += chunk) {
1921
+ const end = start + chunk - 1n > latest ? latest : start + chunk - 1n;
1922
+ const [noxaLogs, odysseyLogs] = await Promise.all([
1923
+ options.launchpad === "odyssey" ? Promise.resolve([]) : client.public.getLogs({
1924
+ address: NOXA_ADDRESSES.launchFactory,
1925
+ event: noxaTokenLaunchedEvent,
1926
+ fromBlock: start,
1927
+ toBlock: end
1928
+ }),
1929
+ options.launchpad === "noxa" ? Promise.resolve([]) : client.public.getLogs({
1930
+ address: ODYSSEY_FACTORIES,
1931
+ event: odysseyTokenCreatedEvent,
1932
+ fromBlock: start,
1933
+ toBlock: end
1934
+ })
1935
+ ]);
1936
+ for (const log of noxaLogs) {
1937
+ launches.push({
1938
+ launchpad: "noxa",
1939
+ token: log.args.token,
1940
+ creator: log.args.deployer,
1941
+ pool: log.args.pool ?? null,
1942
+ blockNumber: log.blockNumber,
1943
+ transactionHash: log.transactionHash
1944
+ });
1945
+ }
1946
+ for (const log of odysseyLogs) {
1947
+ launches.push({
1948
+ launchpad: "odyssey",
1949
+ token: log.args.token,
1950
+ creator: log.args.creator,
1951
+ pool: null,
1952
+ blockNumber: log.blockNumber,
1953
+ transactionHash: log.transactionHash
1954
+ });
1955
+ }
1956
+ }
1957
+ return launches.sort((a, b) => a.blockNumber < b.blockNumber ? -1 : 1);
1958
+ }
1959
+ function watchLaunches(client, onLaunch, options = {}) {
1960
+ const unwatchers = [];
1961
+ const pollingInterval = options.pollingInterval ?? 2e3;
1962
+ if (options.launchpad !== "odyssey") {
1963
+ unwatchers.push(
1964
+ client.public.watchContractEvent({
1965
+ address: NOXA_ADDRESSES.launchFactory,
1966
+ abi: [noxaTokenLaunchedEvent],
1967
+ eventName: "TokenLaunched",
1968
+ pollingInterval,
1969
+ onError: options.onError,
1970
+ onLogs: (logs) => {
1971
+ for (const log of logs) {
1972
+ onLaunch({
1973
+ launchpad: "noxa",
1974
+ token: log.args.token,
1975
+ creator: log.args.deployer,
1976
+ pool: log.args.pool ?? null,
1977
+ blockNumber: log.blockNumber,
1978
+ transactionHash: log.transactionHash
1979
+ });
1980
+ }
1981
+ }
1982
+ })
1983
+ );
1984
+ }
1985
+ if (options.launchpad !== "noxa") {
1986
+ unwatchers.push(
1987
+ client.public.watchContractEvent({
1988
+ address: ODYSSEY_FACTORIES,
1989
+ abi: [odysseyTokenCreatedEvent],
1990
+ eventName: "TokenCreated",
1991
+ pollingInterval,
1992
+ onError: options.onError,
1993
+ onLogs: (logs) => {
1994
+ for (const log of logs) {
1995
+ onLaunch({
1996
+ launchpad: "odyssey",
1997
+ token: log.args.token,
1998
+ creator: log.args.creator,
1999
+ pool: null,
2000
+ blockNumber: log.blockNumber,
2001
+ transactionHash: log.transactionHash
2002
+ });
2003
+ }
2004
+ }
2005
+ })
2006
+ );
2007
+ }
2008
+ return () => unwatchers.forEach((u) => u());
2009
+ }
2010
+ function watchCurveTrades(client, onTrade, options = {}) {
2011
+ return client.public.watchContractEvent({
2012
+ address: ODYSSEY_FACTORIES,
2013
+ abi: [odysseyTradedEvent],
2014
+ eventName: "Traded",
2015
+ ...options.token ? { args: { token: options.token } } : {},
2016
+ pollingInterval: options.pollingInterval ?? 2e3,
2017
+ onError: options.onError,
2018
+ onLogs: (logs) => {
2019
+ for (const log of logs) {
2020
+ onTrade({
2021
+ launchpad: "odyssey",
2022
+ token: log.args.token,
2023
+ trader: log.args.trader,
2024
+ isBuy: log.args.isBuy,
2025
+ tokenAmount: log.args.tokenAmount,
2026
+ quoteAmount: log.args.quoteAmount,
2027
+ fee: log.args.fee,
2028
+ blockNumber: log.blockNumber,
2029
+ transactionHash: log.transactionHash
2030
+ });
2031
+ }
2032
+ }
2033
+ });
2034
+ }
2035
+ function watchGraduations(client, onGraduation, options = {}) {
2036
+ return client.public.watchContractEvent({
2037
+ address: ODYSSEY_FACTORIES,
2038
+ abi: [odysseyPoolMigratedEvent],
2039
+ eventName: "PoolMigrated",
2040
+ pollingInterval: options.pollingInterval ?? 2e3,
2041
+ onError: options.onError,
2042
+ onLogs: (logs) => {
2043
+ for (const log of logs) {
2044
+ onGraduation({
2045
+ token: log.args.token,
2046
+ pool: log.args.pool,
2047
+ blockNumber: log.blockNumber,
2048
+ transactionHash: log.transactionHash
2049
+ });
2050
+ }
2051
+ }
2052
+ });
2053
+ }
2054
+ var L2MSG_KIND_BATCH = 3;
2055
+ var L2MSG_KIND_SIGNED_TX = 4;
2056
+ function decodeL2Msg(bytes, depth = 0) {
2057
+ if (bytes.length < 2 || depth > 4) return [];
2058
+ const kind = bytes[0];
2059
+ const body = bytes.subarray(1);
2060
+ if (kind === L2MSG_KIND_SIGNED_TX) {
2061
+ const raw = `0x${Buffer.from(body).toString("hex")}`;
2062
+ try {
2063
+ return [{ hash: keccak256(raw), transaction: parseTransaction(raw), raw }];
2064
+ } catch {
2065
+ return [];
2066
+ }
2067
+ }
2068
+ if (kind === L2MSG_KIND_BATCH) {
2069
+ const out = [];
2070
+ let offset = 0;
2071
+ while (offset + 8 <= body.length) {
2072
+ const view = new DataView(body.buffer, body.byteOffset + offset, 8);
2073
+ const length = Number(view.getBigUint64(0));
2074
+ offset += 8;
2075
+ if (length <= 0 || offset + length > body.length) break;
2076
+ out.push(...decodeL2Msg(body.subarray(offset, offset + length), depth + 1));
2077
+ offset += length;
2078
+ }
2079
+ return out;
2080
+ }
2081
+ return [];
2082
+ }
2083
+ async function resolveWebSocket() {
2084
+ const g = globalThis;
2085
+ if (typeof g.WebSocket === "function") return g.WebSocket;
2086
+ try {
2087
+ const ws = await import("ws");
2088
+ return ws.default;
2089
+ } catch {
2090
+ throw new FeedConnectionError(
2091
+ MAINNET_FEED_URL,
2092
+ 0,
2093
+ 'no WebSocket implementation available \u2014 use Node \u2265 22 or install the optional "ws" peer dependency'
2094
+ );
2095
+ }
2096
+ }
2097
+ async function subscribeFeed(onMessage, options = {}) {
2098
+ const url = options.url ?? MAINNET_FEED_URL;
2099
+ const maxReconnects = options.maxReconnects ?? 10;
2100
+ const WS = await resolveWebSocket();
2101
+ let socket = null;
2102
+ let closed = false;
2103
+ let attempts = 0;
2104
+ const connect = () => {
2105
+ if (closed) return;
2106
+ socket = new WS(url);
2107
+ socket.onopen = () => {
2108
+ attempts = 0;
2109
+ options.onConnect?.();
2110
+ };
2111
+ socket.onmessage = (event) => {
2112
+ let payload;
2113
+ try {
2114
+ payload = JSON.parse(typeof event.data === "string" ? event.data : Buffer.from(event.data).toString());
2115
+ } catch {
2116
+ return;
2117
+ }
2118
+ for (const entry of payload.messages ?? []) {
2119
+ const m = entry;
2120
+ const header = m.message?.message?.header;
2121
+ const l2Msg = m.message?.message?.l2Msg;
2122
+ if (!header || typeof l2Msg !== "string") continue;
2123
+ onMessage({
2124
+ sequenceNumber: m.sequenceNumber ?? 0,
2125
+ kind: header.kind ?? 0,
2126
+ sender: header.sender ?? "0x0000000000000000000000000000000000000000",
2127
+ l1BlockNumber: header.blockNumber ?? 0,
2128
+ timestamp: header.timestamp ?? 0,
2129
+ l2MsgBase64: l2Msg,
2130
+ transactions: header.kind === 3 ? decodeL2Msg(Buffer.from(l2Msg, "base64")) : []
2131
+ });
2132
+ }
2133
+ };
2134
+ socket.onerror = () => {
2135
+ options.onError?.(new Error(`sequencer feed socket error (${url})`));
2136
+ };
2137
+ socket.onclose = () => {
2138
+ if (closed) return;
2139
+ attempts += 1;
2140
+ if (attempts > maxReconnects) {
2141
+ options.onError?.(new FeedConnectionError(url, attempts));
2142
+ return;
2143
+ }
2144
+ const delay = Math.min((options.reconnectDelayMs ?? 1e3) * 2 ** (attempts - 1), 3e4);
2145
+ setTimeout(connect, delay);
2146
+ };
2147
+ };
2148
+ connect();
2149
+ return {
2150
+ close: () => {
2151
+ closed = true;
2152
+ socket?.close();
2153
+ }
2154
+ };
2155
+ }
2156
+ function watchTransfers(client, args, onTransfer) {
2157
+ return client.public.watchContractEvent({
2158
+ address: args.token,
2159
+ abi: erc20Abi,
2160
+ eventName: "Transfer",
2161
+ pollingInterval: args.pollingInterval ?? 2e3,
2162
+ onError: args.onError,
2163
+ onLogs: (logs) => {
2164
+ for (const log of logs) {
2165
+ const a = log.args;
2166
+ if (!a.from || !a.to || a.value === void 0) continue;
2167
+ onTransfer({
2168
+ token: args.token,
2169
+ from: a.from,
2170
+ to: a.to,
2171
+ value: a.value,
2172
+ blockNumber: log.blockNumber,
2173
+ transactionHash: log.transactionHash
2174
+ });
2175
+ }
2176
+ }
2177
+ });
2178
+ }
2179
+
2180
+ export {
2181
+ createHoodClient,
2182
+ MAINNET_ADDRESSES,
2183
+ TESTNET_ADDRESSES,
2184
+ TESTNET_STOCK_TOKENS,
2185
+ MAINNET_FEED_URL,
2186
+ MAINNET_EXPLORER_URL,
2187
+ USDG_DECIMALS,
2188
+ STOCK_TOKEN_DECIMALS,
2189
+ FEED_DECIMALS,
2190
+ V3_FEE_TIERS,
2191
+ HoodchainError,
2192
+ UnknownSymbolError,
2193
+ FeedNotFoundError,
2194
+ StaleFeedError,
2195
+ InvalidFeedAnswerError,
2196
+ NoRouteError,
2197
+ SlippageExceededError,
2198
+ NoAccountError,
2199
+ StockTokenEligibilityError,
2200
+ FeedConnectionError,
2201
+ getRegistry,
2202
+ listStockTokens,
2203
+ listPricedStockTokens,
2204
+ getStockToken,
2205
+ getStockTokenByAddress,
2206
+ isStockTokenSymbol,
2207
+ isStockTokenAddress,
2208
+ erc20Abi,
2209
+ stockTokenAbi,
2210
+ aggregatorV3Abi,
2211
+ quoterV2Abi,
2212
+ swapRouter02Abi,
2213
+ swapRouterAbi,
2214
+ weth9Abi,
2215
+ uniswapV3FactoryAbi,
2216
+ uniswapV3PoolAbi,
2217
+ DEFAULT_MAX_FEED_AGE_SECONDS,
2218
+ getQuote,
2219
+ getMultiplier,
2220
+ getPosition,
2221
+ getPortfolio,
2222
+ swapAddresses,
2223
+ quoteSwap,
2224
+ buildSwapTx,
2225
+ ensureApproval,
2226
+ executeSwap,
2227
+ usdgAddress,
2228
+ formatUsdg,
2229
+ parseUsdg,
2230
+ getUsdgBalance,
2231
+ getUsdgTotalSupply,
2232
+ transferUsdg,
2233
+ approveUsdg,
2234
+ getUsdgAllowance,
2235
+ NOXA_ADDRESSES,
2236
+ ODYSSEY_ADDRESSES,
2237
+ noxaTokenLaunchedEvent,
2238
+ odysseyTokenCreatedEvent,
2239
+ odysseyTradedEvent,
2240
+ odysseyPoolMigratedEvent,
2241
+ getRecentLaunches,
2242
+ watchLaunches,
2243
+ watchCurveTrades,
2244
+ watchGraduations,
2245
+ subscribeFeed,
2246
+ watchTransfers
2247
+ };
2248
+ //# sourceMappingURL=chunk-CWEBZB3L.js.map