@veridex/sdk 1.0.0-beta.21 → 1.0.0-beta.23

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.
Files changed (113) hide show
  1. package/dist/EVMClient-CoOR_ywD.d.mts +332 -0
  2. package/dist/auth/prepareAuth.d.mts +1 -1
  3. package/dist/auth/prepareAuth.js +749 -3
  4. package/dist/auth/prepareAuth.js.map +1 -1
  5. package/dist/auth/prepareAuth.mjs +25 -1404
  6. package/dist/auth/prepareAuth.mjs.map +1 -1
  7. package/dist/chains/aptos/index.d.mts +1 -1
  8. package/dist/chains/aptos/index.mjs +5 -574
  9. package/dist/chains/aptos/index.mjs.map +1 -1
  10. package/dist/chains/avalanche/index.d.mts +137 -0
  11. package/dist/chains/avalanche/index.js +1407 -0
  12. package/dist/chains/avalanche/index.js.map +1 -0
  13. package/dist/chains/avalanche/index.mjs +10 -0
  14. package/dist/chains/avalanche/index.mjs.map +1 -0
  15. package/dist/chains/evm/index.d.mts +4 -2
  16. package/dist/chains/evm/index.mjs +8 -1200
  17. package/dist/chains/evm/index.mjs.map +1 -1
  18. package/dist/chains/solana/index.d.mts +1 -1
  19. package/dist/chains/solana/index.mjs +4 -486
  20. package/dist/chains/solana/index.mjs.map +1 -1
  21. package/dist/chains/stacks/index.d.mts +1 -1
  22. package/dist/chains/stacks/index.mjs +36 -1114
  23. package/dist/chains/stacks/index.mjs.map +1 -1
  24. package/dist/chains/starknet/index.d.mts +1 -1
  25. package/dist/chains/starknet/index.mjs +5 -503
  26. package/dist/chains/starknet/index.mjs.map +1 -1
  27. package/dist/chains/sui/index.d.mts +1 -1
  28. package/dist/chains/sui/index.mjs +5 -529
  29. package/dist/chains/sui/index.mjs.map +1 -1
  30. package/dist/chunk-3Q34PMHU.mjs +840 -0
  31. package/dist/chunk-3Q34PMHU.mjs.map +1 -0
  32. package/dist/chunk-72ZA3OYQ.mjs +20 -0
  33. package/dist/chunk-72ZA3OYQ.mjs.map +1 -0
  34. package/dist/chunk-7IEUU6LD.mjs +549 -0
  35. package/dist/chunk-7IEUU6LD.mjs.map +1 -0
  36. package/dist/chunk-ABLEEC5N.mjs +38 -0
  37. package/dist/chunk-ABLEEC5N.mjs.map +1 -0
  38. package/dist/chunk-AORSW75A.mjs +1101 -0
  39. package/dist/chunk-AORSW75A.mjs.map +1 -0
  40. package/dist/chunk-BKTCPT7P.mjs +269 -0
  41. package/dist/chunk-BKTCPT7P.mjs.map +1 -0
  42. package/dist/chunk-CCHASDAI.mjs +330 -0
  43. package/dist/chunk-CCHASDAI.mjs.map +1 -0
  44. package/dist/chunk-FQ2WU7PX.mjs +509 -0
  45. package/dist/chunk-FQ2WU7PX.mjs.map +1 -0
  46. package/dist/chunk-JO74ENTF.mjs +417 -0
  47. package/dist/chunk-JO74ENTF.mjs.map +1 -0
  48. package/dist/chunk-K73Y36KS.mjs +407 -0
  49. package/dist/chunk-K73Y36KS.mjs.map +1 -0
  50. package/dist/chunk-KHV3EP3I.mjs +179 -0
  51. package/dist/chunk-KHV3EP3I.mjs.map +1 -0
  52. package/dist/chunk-MMSTOW4F.mjs +722 -0
  53. package/dist/chunk-MMSTOW4F.mjs.map +1 -0
  54. package/dist/chunk-MWZ5UHCF.mjs +1082 -0
  55. package/dist/chunk-MWZ5UHCF.mjs.map +1 -0
  56. package/dist/chunk-NU6JGI7L.mjs +565 -0
  57. package/dist/chunk-NU6JGI7L.mjs.map +1 -0
  58. package/dist/chunk-PIC2Y5DF.mjs +422 -0
  59. package/dist/chunk-PIC2Y5DF.mjs.map +1 -0
  60. package/dist/chunk-PPN7BG3A.mjs +464 -0
  61. package/dist/chunk-PPN7BG3A.mjs.map +1 -0
  62. package/dist/chunk-RSV7J43V.mjs +438 -0
  63. package/dist/chunk-RSV7J43V.mjs.map +1 -0
  64. package/dist/chunk-UTT6KI7N.mjs +216 -0
  65. package/dist/chunk-UTT6KI7N.mjs.map +1 -0
  66. package/dist/constants.mjs +16 -389
  67. package/dist/constants.mjs.map +1 -1
  68. package/dist/index-Du1PoZqu.d.mts +216 -0
  69. package/dist/index.d.mts +131 -9
  70. package/dist/index.js +12064 -11594
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +4407 -12273
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/passkey.d.mts +142 -0
  75. package/dist/passkey.js +807 -0
  76. package/dist/passkey.js.map +1 -0
  77. package/dist/passkey.mjs +15 -0
  78. package/dist/passkey.mjs.map +1 -0
  79. package/dist/payload.mjs +25 -244
  80. package/dist/payload.mjs.map +1 -1
  81. package/dist/portfolio-UV3LLWKI.mjs +13 -0
  82. package/dist/portfolio-UV3LLWKI.mjs.map +1 -0
  83. package/dist/queries/index.js +39 -1
  84. package/dist/queries/index.js.map +1 -1
  85. package/dist/queries/index.mjs +14 -1591
  86. package/dist/queries/index.mjs.map +1 -1
  87. package/dist/{types-DakHNZIP.d.ts → types-Bmk689Lw.d.mts} +1 -1
  88. package/dist/types.d.mts +10 -0
  89. package/dist/types.js.map +1 -1
  90. package/dist/utils.mjs +19 -385
  91. package/dist/utils.mjs.map +1 -1
  92. package/dist/wormhole.mjs +25 -397
  93. package/dist/wormhole.mjs.map +1 -1
  94. package/package.json +17 -3
  95. package/scripts/patch-noble-curves.js +78 -0
  96. package/dist/auth/prepareAuth.d.ts +0 -25
  97. package/dist/chains/aptos/index.d.ts +0 -146
  98. package/dist/chains/evm/index.d.ts +0 -5
  99. package/dist/chains/solana/index.d.ts +0 -116
  100. package/dist/chains/stacks/index.d.ts +0 -559
  101. package/dist/chains/starknet/index.d.ts +0 -172
  102. package/dist/chains/sui/index.d.ts +0 -182
  103. package/dist/constants.d.ts +0 -150
  104. package/dist/index-Dy29mvBf.d.mts +0 -683
  105. package/dist/index-eXXqodd0.d.ts +0 -683
  106. package/dist/index.d.ts +0 -3442
  107. package/dist/payload.d.ts +0 -125
  108. package/dist/queries/index.d.ts +0 -148
  109. package/dist/types-DakHNZIP.d.mts +0 -571
  110. package/dist/types-DvFRnIBd.d.ts +0 -172
  111. package/dist/types.d.ts +0 -413
  112. package/dist/utils.d.ts +0 -81
  113. package/dist/wormhole.d.ts +0 -167
@@ -1,1596 +1,19 @@
1
- // src/queries/constants.ts
2
- var WORMHOLE_QUERY_PROXY_URLS = {
3
- mainnet: "https://query.wormhole.com/v1/query",
4
- testnet: "https://testnet.query.wormhole.com/v1/query"
5
- };
6
- var WORMHOLE_QUERY_RATE_LIMIT_PER_SECOND = 6;
7
- var WORMHOLE_QUERY_CHAIN_IDS = {
8
- ETHEREUM: 2,
9
- POLYGON: 5,
10
- ARBITRUM: 23,
11
- OPTIMISM: 24,
12
- BASE: 30
13
- };
14
-
15
- // src/queries/hubState.ts
16
- import axios from "axios";
17
- import { Buffer } from "buffer";
18
- import { ethers } from "ethers";
19
1
  import {
20
- EthCallQueryRequest,
21
- EthCallQueryResponse,
22
- PerChainQueryRequest,
23
- QueryRequest,
24
- QueryResponse,
25
- hexToUint8Array,
26
- isValidHexString
27
- } from "@wormhole-foundation/wormhole-query-sdk";
28
-
29
- // src/constants.ts
30
- var TESTNET_CHAINS = {
31
- baseSepolia: {
32
- name: "Base Sepolia",
33
- chainId: 84532,
34
- wormholeChainId: 10004,
35
- rpcUrl: "https://sepolia.base.org",
36
- // Public CORS-friendly RPC
37
- explorerUrl: "https://sepolia.basescan.org",
38
- isEvm: true,
39
- contracts: {
40
- hub: "0x66D87dE68327f48A099c5B9bE97020Feab9a7c82",
41
- vaultFactory: "0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53",
42
- vaultImplementation: "0x0d13367C16c6f0B24eD275CC67C7D9f42878285c",
43
- wormholeCoreBridge: "0x79A1027a6A159502049F10906D333EC57E95F083",
44
- tokenBridge: "0x86F55A04690fd7815A3D802bD587e83eA888B239"
45
- }
46
- },
47
- ethereumSepolia: {
48
- name: "Ethereum Sepolia",
49
- chainId: 11155111,
50
- wormholeChainId: 10002,
51
- rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
52
- explorerUrl: "https://sepolia.etherscan.io",
53
- isEvm: true,
54
- contracts: {
55
- vaultFactory: "0x07F608AFf6d63b68029488b726d895c4Bb593038",
56
- vaultImplementation: "0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6",
57
- wormholeCoreBridge: "0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78",
58
- tokenBridge: "0xDB5492265f6038831E89f495670FF909aDe94bd9"
59
- }
60
- },
61
- optimismSepolia: {
62
- name: "Optimism Sepolia",
63
- chainId: 11155420,
64
- wormholeChainId: 10005,
65
- rpcUrl: "https://sepolia.optimism.io",
66
- explorerUrl: "https://sepolia-optimism.etherscan.io",
67
- isEvm: true,
68
- contracts: {
69
- vaultFactory: "0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A",
70
- vaultImplementation: "0x8099b1406485d2255ff89Ce5Ea18520802AFC150",
71
- wormholeCoreBridge: "0x31377888146f3253211EFEf5c676D41ECe7D58Fe",
72
- tokenBridge: "0x99737Ec4B815d816c49A385943baf0380e75c0Ac"
73
- }
74
- },
75
- arbitrumSepolia: {
76
- name: "Arbitrum Sepolia",
77
- chainId: 421614,
78
- wormholeChainId: 10003,
79
- rpcUrl: "https://sepolia-rollup.arbitrum.io/rpc",
80
- explorerUrl: "https://sepolia.arbiscan.io",
81
- isEvm: true,
82
- contracts: {
83
- vaultFactory: "0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c",
84
- vaultImplementation: "0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4",
85
- wormholeCoreBridge: "0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35",
86
- tokenBridge: "0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e"
87
- }
88
- },
89
- seiTestnet: {
90
- name: "Sei Atlantic-2",
91
- chainId: 1328,
92
- wormholeChainId: 40,
93
- rpcUrl: "https://evm-rpc-testnet.sei-apis.com",
94
- explorerUrl: "https://seitrace.com/?chain=atlantic-2",
95
- isEvm: true,
96
- contracts: {
97
- vaultFactory: "0x07F608AFf6d63b68029488b726d895c4Bb593038",
98
- vaultImplementation: "0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6",
99
- wormholeCoreBridge: "0x0000000000000000000000000000000000000000"
100
- // Mock - not yet deployed
101
- }
102
- },
103
- solanaDevnet: {
104
- name: "Solana Devnet",
105
- chainId: 0,
106
- wormholeChainId: 1,
107
- rpcUrl: "https://api.devnet.solana.com",
108
- explorerUrl: "https://explorer.solana.com",
109
- isEvm: false,
110
- contracts: {
111
- hub: "AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM",
112
- wormholeCoreBridge: "3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5",
113
- tokenBridge: "DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe"
114
- }
115
- },
116
- aptosTestnet: {
117
- name: "Aptos Testnet",
118
- chainId: 0,
119
- wormholeChainId: 22,
120
- rpcUrl: "https://fullnode.testnet.aptoslabs.com/v1",
121
- explorerUrl: "https://explorer.aptoslabs.com",
122
- isEvm: false,
123
- contracts: {
124
- hub: "0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4",
125
- wormholeCoreBridge: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
126
- tokenBridge: "0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f"
127
- }
128
- },
129
- suiTestnet: {
130
- name: "Sui Testnet",
131
- chainId: 0,
132
- wormholeChainId: 21,
133
- rpcUrl: "https://fullnode.testnet.sui.io:443",
134
- explorerUrl: "https://suiscan.xyz/testnet",
135
- isEvm: false,
136
- contracts: {
137
- hub: "0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37",
138
- wormholeCoreBridge: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790"
139
- }
140
- },
141
- starknetSepolia: {
142
- name: "Starknet Sepolia",
143
- chainId: 0,
144
- // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)
145
- wormholeChainId: 50001,
146
- // Custom chain ID (50000+ reserved for non-Wormhole chains)
147
- rpcUrl: "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-",
148
- explorerUrl: "https://sepolia.starkscan.co",
149
- isEvm: false,
150
- contracts: {
151
- // Starknet spoke contract
152
- hub: "0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811",
153
- // Custom bridge contract (NOT Wormhole)
154
- wormholeCoreBridge: "0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8"
155
- },
156
- // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)
157
- hubChainId: 10004
158
- }
159
- };
160
- var MAINNET_CHAINS = {
161
- ethereum: {
162
- name: "Ethereum",
163
- chainId: 1,
164
- wormholeChainId: 2,
165
- rpcUrl: "https://eth.llamarpc.com",
166
- explorerUrl: "https://etherscan.io",
167
- isEvm: true,
168
- contracts: {
169
- wormholeCoreBridge: "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B",
170
- tokenBridge: "0x3ee18B2214AFF97000D974cf647E7C347E8fa585"
171
- }
172
- },
173
- base: {
174
- name: "Base",
175
- chainId: 8453,
176
- wormholeChainId: 30,
177
- rpcUrl: "https://mainnet.base.org",
178
- explorerUrl: "https://basescan.org",
179
- isEvm: true,
180
- contracts: {
181
- wormholeCoreBridge: "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6",
182
- tokenBridge: "0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627"
183
- }
184
- },
185
- optimism: {
186
- name: "Optimism",
187
- chainId: 10,
188
- wormholeChainId: 24,
189
- rpcUrl: "https://mainnet.optimism.io",
190
- explorerUrl: "https://optimistic.etherscan.io",
191
- isEvm: true,
192
- contracts: {
193
- wormholeCoreBridge: "0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722",
194
- tokenBridge: "0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b"
195
- }
196
- },
197
- arbitrum: {
198
- name: "Arbitrum",
199
- chainId: 42161,
200
- wormholeChainId: 23,
201
- rpcUrl: "https://arb1.arbitrum.io/rpc",
202
- explorerUrl: "https://arbiscan.io",
203
- isEvm: true,
204
- contracts: {
205
- wormholeCoreBridge: "0xa5f208e072434bC67592E4C49C1B991BA79BCA46",
206
- tokenBridge: "0x0b2402144Bb366A632D14B83F244D2e0e21bD39c"
207
- }
208
- },
209
- polygon: {
210
- name: "Polygon",
211
- chainId: 137,
212
- wormholeChainId: 5,
213
- rpcUrl: "https://polygon-rpc.com",
214
- explorerUrl: "https://polygonscan.com",
215
- isEvm: true,
216
- contracts: {
217
- wormholeCoreBridge: "0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7",
218
- tokenBridge: "0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE"
219
- }
220
- },
221
- solana: {
222
- name: "Solana",
223
- chainId: 0,
224
- wormholeChainId: 1,
225
- rpcUrl: "https://api.mainnet-beta.solana.com",
226
- explorerUrl: "https://explorer.solana.com",
227
- isEvm: false,
228
- contracts: {
229
- wormholeCoreBridge: "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth",
230
- tokenBridge: "wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb"
231
- }
232
- },
233
- aptos: {
234
- name: "Aptos",
235
- chainId: 0,
236
- wormholeChainId: 22,
237
- rpcUrl: "https://fullnode.mainnet.aptoslabs.com/v1",
238
- explorerUrl: "https://explorer.aptoslabs.com",
239
- isEvm: false,
240
- contracts: {
241
- wormholeCoreBridge: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
242
- tokenBridge: "0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f"
243
- }
244
- },
245
- sui: {
246
- name: "Sui",
247
- chainId: 0,
248
- wormholeChainId: 21,
249
- rpcUrl: "https://fullnode.mainnet.sui.io:443",
250
- explorerUrl: "https://suiscan.xyz/mainnet",
251
- isEvm: false,
252
- contracts: {
253
- wormholeCoreBridge: "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c"
254
- }
255
- }
256
- };
257
-
258
- // src/queries/hubState.ts
259
- var QueryHubStateError = class extends Error {
260
- code;
261
- cause;
262
- constructor(code, message, cause) {
263
- super(message);
264
- this.name = "QueryHubStateError";
265
- this.code = code;
266
- this.cause = cause;
267
- }
268
- };
269
- function resolveNetwork(options) {
270
- if (options?.network) return options.network;
271
- const envCandidates = [
272
- globalThis?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,
273
- globalThis?.process?.env?.VERIDEX_NETWORK,
274
- globalThis?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,
275
- globalThis?.process?.env?.WORMHOLE_NETWORK
276
- ].filter(Boolean);
277
- const env = envCandidates[0]?.toLowerCase();
278
- if (env === "mainnet" || env === "testnet") return env;
279
- return "testnet";
280
- }
281
- function concatBytes(parts) {
282
- const total = parts.reduce((sum, p) => sum + p.length, 0);
283
- const out = new Uint8Array(total);
284
- let offset = 0;
285
- for (const p of parts) {
286
- out.set(p, offset);
287
- offset += p.length;
288
- }
289
- return out;
290
- }
291
- function signaturesToProofBytes(signatures) {
292
- const chunks = [];
293
- for (const sig of signatures) {
294
- if (typeof sig !== "string" || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {
295
- throw new QueryHubStateError(
296
- "PROXY_RESPONSE_INVALID",
297
- `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`
298
- );
299
- }
300
- chunks.push(hexToUint8Array(`0x${sig}`));
301
- }
302
- return concatBytes(chunks);
303
- }
304
- function decodeQueryBytes(bytes) {
305
- if (typeof bytes !== "string" || bytes.length === 0) {
306
- throw new QueryHubStateError("PROXY_RESPONSE_INVALID", "Missing query response bytes");
307
- }
308
- if (isValidHexString(bytes)) {
309
- return hexToUint8Array(bytes);
310
- }
311
- try {
312
- if (typeof atob === "function") {
313
- const raw = atob(bytes);
314
- const arr = new Uint8Array(raw.length);
315
- for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);
316
- return arr;
317
- }
318
- } catch {
319
- }
320
- try {
321
- return new Uint8Array(Buffer.from(bytes, "base64"));
322
- } catch (cause) {
323
- throw new QueryHubStateError("PROXY_RESPONSE_INVALID", "Unrecognized query response bytes encoding", cause);
324
- }
325
- }
326
- function sleep(ms) {
327
- return new Promise((resolve) => setTimeout(resolve, ms));
328
- }
329
- async function withExponentialBackoff(fn, maxAttempts) {
330
- let attempt = 0;
331
- let lastError;
332
- while (attempt < maxAttempts) {
333
- try {
334
- return await fn();
335
- } catch (err) {
336
- lastError = err;
337
- attempt += 1;
338
- if (attempt >= maxAttempts) break;
339
- const baseMs = 250;
340
- const backoffMs = Math.min(5e3, baseMs * 2 ** (attempt - 1));
341
- const jitterMs = Math.floor(Math.random() * 100);
342
- await sleep(backoffMs + jitterMs);
343
- }
344
- }
345
- throw lastError;
346
- }
347
- function getHubConfig(network) {
348
- if (network === "testnet") {
349
- const baseSepolia = TESTNET_CHAINS.baseSepolia;
350
- if (!baseSepolia?.contracts?.hub) {
351
- throw new QueryHubStateError("MISSING_HUB_ADDRESS", "Missing Base Sepolia hub address in SDK constants");
352
- }
353
- return {
354
- wormholeChainId: baseSepolia.wormholeChainId,
355
- hubAddress: baseSepolia.contracts.hub,
356
- endpoint: WORMHOLE_QUERY_PROXY_URLS.testnet,
357
- rpcUrl: baseSepolia.rpcUrl
358
- };
359
- }
360
- if (network === "mainnet") {
361
- const base = MAINNET_CHAINS.base;
362
- const hubAddress = base?.contracts?.hub;
363
- if (!hubAddress) {
364
- throw new QueryHubStateError(
365
- "MISSING_HUB_ADDRESS",
366
- "Missing mainnet hub address in SDK constants (MAINNET_CHAINS.base.contracts.hub)"
367
- );
368
- }
369
- return {
370
- wormholeChainId: base.wormholeChainId,
371
- hubAddress,
372
- endpoint: WORMHOLE_QUERY_PROXY_URLS.mainnet,
373
- rpcUrl: base.rpcUrl
374
- };
375
- }
376
- throw new QueryHubStateError("UNSUPPORTED_NETWORK", `Unsupported network: ${network}`);
377
- }
378
- function encodeHubCalls(hubAddress, userKeyHash) {
379
- const nonceAbiCandidates = [
380
- "function getUserNonce(bytes32 userKeyHash) view returns (uint256)",
381
- "function userNonces(bytes32 userKeyHash) view returns (uint256)",
382
- "function getNonceByHash(bytes32 userKeyHash) view returns (uint256)"
383
- ];
384
- const registeredAbiCandidates = [
385
- "function registeredKeys(bytes32 userKeyHash) view returns (bool)",
386
- "function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)"
387
- ];
388
- const actionHashAbiCandidates = [
389
- "function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)",
390
- "function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)"
391
- ];
392
- const iface = new ethers.Interface([
393
- ...nonceAbiCandidates,
394
- ...registeredAbiCandidates,
395
- ...actionHashAbiCandidates
396
- ]);
397
- const nonceFnNames = ["getUserNonce", "userNonces", "getNonceByHash"];
398
- const regFnNames = ["registeredKeys", "isKeyRegisteredByHash"];
399
- const actionHashFnNames = ["getUserLastActionHash", "userLastActionHash"];
400
- return [
401
- ...nonceFnNames.map((fn) => ({
402
- to: hubAddress,
403
- data: iface.encodeFunctionData(fn, [userKeyHash])
404
- })),
405
- ...regFnNames.map((fn) => ({
406
- to: hubAddress,
407
- data: iface.encodeFunctionData(fn, [userKeyHash])
408
- })),
409
- ...actionHashFnNames.map((fn) => ({
410
- to: hubAddress,
411
- data: iface.encodeFunctionData(fn, [userKeyHash])
412
- }))
413
- ];
414
- }
415
- function decodeFirstNonce(results) {
416
- const candidates = [
417
- "function getUserNonce(bytes32 userKeyHash) view returns (uint256)",
418
- "function userNonces(bytes32 userKeyHash) view returns (uint256)",
419
- "function getNonceByHash(bytes32 userKeyHash) view returns (uint256)"
420
- ];
421
- const iface = new ethers.Interface(candidates);
422
- const fnNames = ["getUserNonce", "userNonces", "getNonceByHash"];
423
- for (let idx = 0; idx < fnNames.length; idx++) {
424
- const fnName = fnNames[idx];
425
- try {
426
- const data = results[idx];
427
- if (!data || data === "0x") continue;
428
- const decoded = iface.decodeFunctionResult(fnName, data);
429
- return decoded[0];
430
- } catch {
431
- }
432
- }
433
- throw new QueryHubStateError("QUERY_RESPONSE_INVALID", "Unable to decode user nonce from query response");
434
- }
435
- function decodeFirstIsRegistered(results) {
436
- const nonceCandidateCount = 3;
437
- const candidates = [
438
- "function registeredKeys(bytes32 userKeyHash) view returns (bool)",
439
- "function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)"
440
- ];
441
- const iface = new ethers.Interface(candidates);
442
- const fnNames = ["registeredKeys", "isKeyRegisteredByHash"];
443
- for (let i = 0; i < fnNames.length; i++) {
444
- const fnName = fnNames[i];
445
- try {
446
- const data = results[nonceCandidateCount + i];
447
- if (!data || data === "0x") continue;
448
- const decoded = iface.decodeFunctionResult(fnName, data);
449
- return Boolean(decoded[0]);
450
- } catch {
451
- }
452
- }
453
- return false;
454
- }
455
- function decodeLastActionHash(results) {
456
- const nonceCandidateCount = 3;
457
- const registeredCandidateCount = 2;
458
- const actionHashOffset = nonceCandidateCount + registeredCandidateCount;
459
- const candidates = [
460
- "function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)",
461
- "function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)"
462
- ];
463
- const iface = new ethers.Interface(candidates);
464
- const fnNames = ["getUserLastActionHash", "userLastActionHash"];
465
- for (let i = 0; i < fnNames.length; i++) {
466
- const fnName = fnNames[i];
467
- try {
468
- const data = results[actionHashOffset + i];
469
- if (!data || data === "0x") continue;
470
- const decoded = iface.decodeFunctionResult(fnName, data);
471
- return decoded[0];
472
- } catch {
473
- }
474
- }
475
- return ethers.ZeroHash;
476
- }
477
- async function queryHubState(userKeyHash, apiKey, options) {
478
- if (typeof userKeyHash !== "string" || userKeyHash.length === 0) {
479
- throw new QueryHubStateError("INVALID_ARGUMENT", "userKeyHash is required");
480
- }
481
- if (!isValidHexString(userKeyHash) || hexToUint8Array(userKeyHash).length !== 32) {
482
- throw new QueryHubStateError("INVALID_ARGUMENT", "userKeyHash must be a 32-byte hex string");
483
- }
484
- if (typeof apiKey !== "string" || apiKey.length === 0) {
485
- throw new QueryHubStateError("INVALID_ARGUMENT", "apiKey is required");
486
- }
487
- const network = resolveNetwork(options);
488
- const maxAgeSeconds = options?.maxAge ?? 60;
489
- const maxAttempts = options?.maxAttempts ?? 4;
490
- const { wormholeChainId, hubAddress, endpoint, rpcUrl } = getHubConfig(network);
491
- const provider = new ethers.JsonRpcProvider(rpcUrl);
492
- const callData = encodeHubCalls(hubAddress, userKeyHash);
493
- const doFetch = async () => {
494
- try {
495
- const latestBlock = await provider.getBlockNumber();
496
- const blockTag = Math.max(0, latestBlock - 2);
497
- const request = new QueryRequest(Date.now() & 4294967295, [
498
- new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, callData))
499
- ]);
500
- const requestHex = Buffer.from(request.serialize()).toString("hex");
501
- const response = await axios.post(
502
- endpoint,
503
- { bytes: requestHex },
504
- {
505
- headers: {
506
- "X-API-Key": apiKey,
507
- "Content-Type": "application/json"
508
- },
509
- timeout: 1e4
510
- }
511
- );
512
- const data = response.data;
513
- const signatures = data?.signatures;
514
- const bytes = data?.bytes;
515
- if (!Array.isArray(signatures) || typeof bytes !== "string") {
516
- throw new QueryHubStateError("PROXY_RESPONSE_INVALID", "Query Proxy response missing signatures/bytes");
517
- }
518
- const proof = signaturesToProofBytes(signatures);
519
- const queryBytes = decodeQueryBytes(bytes);
520
- const parsed = QueryResponse.from(queryBytes);
521
- const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);
522
- if (!perChain) {
523
- throw new QueryHubStateError("QUERY_RESPONSE_INVALID", "Missing per-chain response for hub chain");
524
- }
525
- const chainResp = EthCallQueryResponse.from(perChain.response.serialize());
526
- const blockTime = Number(chainResp.blockTime);
527
- const nowSeconds = Math.floor(Date.now() / 1e3);
528
- if (nowSeconds - blockTime > maxAgeSeconds) {
529
- throw new QueryHubStateError(
530
- "ATTESTATION_STALE",
531
- `Guardian attestation is stale (blockTime=${blockTime}, now=${nowSeconds}, maxAge=${maxAgeSeconds}s)`
532
- );
533
- }
534
- const nonce = decodeFirstNonce(chainResp.results);
535
- const isRegistered = decodeFirstIsRegistered(chainResp.results);
536
- const lastActionHash = decodeLastActionHash(chainResp.results);
537
- return {
538
- nonce,
539
- isRegistered,
540
- blockTime,
541
- proof,
542
- lastActionHash
543
- };
544
- } catch (err) {
545
- if (err instanceof QueryHubStateError) throw err;
546
- if (axios.isAxiosError(err)) {
547
- const ax = err;
548
- const status = ax.response?.status;
549
- const statusText = ax.response?.statusText;
550
- const details = typeof ax.response?.data === "string" ? ax.response?.data : void 0;
551
- throw new QueryHubStateError(
552
- "PROXY_HTTP_ERROR",
553
- `Query Proxy request failed${status ? ` (${status} ${statusText ?? ""})` : ""}${details ? `: ${details}` : ""}`,
554
- err
555
- );
556
- }
557
- throw new QueryHubStateError("PROXY_HTTP_ERROR", "Query Proxy request failed", err);
558
- }
559
- };
560
- return await withExponentialBackoff(doFetch, maxAttempts);
561
- }
562
-
563
- // src/queries/portfolio.ts
564
- import axios2 from "axios";
565
- import { Buffer as Buffer2 } from "buffer";
566
- import { ethers as ethers4 } from "ethers";
567
- import { PublicKey } from "@solana/web3.js";
2
+ QueryPortfolioError,
3
+ queryPortfolio
4
+ } from "../chunk-7IEUU6LD.mjs";
568
5
  import {
569
- EthCallQueryRequest as EthCallQueryRequest2,
570
- EthCallQueryResponse as EthCallQueryResponse2,
571
- PerChainQueryRequest as PerChainQueryRequest2,
572
- QueryRequest as QueryRequest2,
573
- QueryResponse as QueryResponse2,
574
- SolanaAccountQueryRequest,
575
- SolanaAccountQueryResponse,
576
- hexToUint8Array as hexToUint8Array2,
577
- isValidHexString as isValidHexString2
578
- } from "@wormhole-foundation/wormhole-query-sdk";
579
-
580
- // src/core/WalletManager.ts
581
- import { ethers as ethers3 } from "ethers";
582
-
583
- // src/utils.ts
584
- import { ethers as ethers2 } from "ethers";
585
- function computeKeyHash(publicKeyX, publicKeyY) {
586
- return ethers2.keccak256(
587
- ethers2.solidityPacked(["uint256", "uint256"], [publicKeyX, publicKeyY])
588
- );
589
- }
590
-
591
- // src/core/WalletManager.ts
592
- var PROXY_BYTECODE_PREFIX = "0x3d602d80600a3d3981f3363d3d373d3d3d363d73";
593
- var PROXY_BYTECODE_SUFFIX = "5af43d82803e903d91602b57fd5bf3";
594
- var WalletManager = class {
595
- config;
596
- addressCache = /* @__PURE__ */ new Map();
597
- constructor(config = {}) {
598
- this.config = {
599
- cacheAddresses: config.cacheAddresses ?? true,
600
- persistToStorage: config.persistToStorage ?? false,
601
- storageKey: config.storageKey ?? "veridex_wallet_addresses"
602
- };
603
- if (this.config.persistToStorage && typeof window !== "undefined") {
604
- this.loadFromStorage();
605
- }
606
- }
607
- // ========================================================================
608
- // Address Computation
609
- // ========================================================================
610
- /**
611
- * Compute the deterministic vault address for an EVM chain
612
- *
613
- * Uses CREATE2 with EIP-1167 minimal proxy pattern:
614
- * - Salt = keccak256(factoryAddress, ownerKeyHash)
615
- * - InitCode = EIP-1167 proxy bytecode with implementation address
616
- *
617
- * @param keyHash - The owner's key hash (keccak256 of public key coordinates)
618
- * @param factoryAddress - The vault factory contract address
619
- * @param implementationAddress - The vault implementation contract address
620
- * @returns The deterministic vault address
621
- */
622
- computeVaultAddress(keyHash, factoryAddress, implementationAddress) {
623
- const salt = ethers3.keccak256(
624
- ethers3.solidityPacked(
625
- ["address", "bytes32"],
626
- [factoryAddress, keyHash]
627
- )
628
- );
629
- const initCode = this.buildProxyInitCode(implementationAddress);
630
- const initCodeHash = ethers3.keccak256(initCode);
631
- const create2Data = ethers3.solidityPacked(
632
- ["bytes1", "address", "bytes32", "bytes32"],
633
- ["0xff", factoryAddress, salt, initCodeHash]
634
- );
635
- const hash = ethers3.keccak256(create2Data);
636
- return ethers3.getAddress("0x" + hash.slice(26));
637
- }
638
- /**
639
- * Compute vault address from public key coordinates
640
- *
641
- * @param publicKeyX - P-256 public key X coordinate
642
- * @param publicKeyY - P-256 public key Y coordinate
643
- * @param factoryAddress - The vault factory contract address
644
- * @param implementationAddress - The vault implementation contract address
645
- * @returns The deterministic vault address
646
- */
647
- computeVaultAddressFromPublicKey(publicKeyX, publicKeyY, factoryAddress, implementationAddress) {
648
- const keyHash = computeKeyHash(publicKeyX, publicKeyY);
649
- return this.computeVaultAddress(keyHash, factoryAddress, implementationAddress);
650
- }
651
- /**
652
- * Build EIP-1167 minimal proxy initcode
653
- */
654
- buildProxyInitCode(implementationAddress) {
655
- const impl = implementationAddress.toLowerCase().replace("0x", "");
656
- return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;
657
- }
658
- // ========================================================================
659
- // Unified Identity
660
- // ========================================================================
661
- /**
662
- * Get unified identity with addresses across all configured chains
663
- *
664
- * @param credential - The passkey credential
665
- * @param chainConfigs - Map of chain configurations with factory/implementation addresses
666
- * @returns Unified identity with addresses on each chain
667
- */
668
- async getUnifiedIdentity(credential, chainConfigs) {
669
- const addresses = [];
670
- for (const [wormholeChainId, config] of chainConfigs) {
671
- const address = await this.deriveAddressForChain(
672
- credential,
673
- wormholeChainId,
674
- config
675
- );
676
- if (address) {
677
- addresses.push(address);
678
- }
679
- }
680
- const identity = {
681
- keyHash: credential.keyHash,
682
- publicKeyX: credential.publicKeyX,
683
- publicKeyY: credential.publicKeyY,
684
- credentialId: credential.credentialId,
685
- addresses,
686
- createdAt: Date.now(),
687
- updatedAt: Date.now()
688
- };
689
- if (this.config.cacheAddresses) {
690
- this.addressCache.set(credential.keyHash, addresses);
691
- }
692
- if (this.config.persistToStorage) {
693
- this.saveToStorage(identity);
694
- }
695
- return identity;
696
- }
697
- /**
698
- * Derive address for a specific chain
699
- */
700
- async deriveAddressForChain(credential, wormholeChainId, config) {
701
- if (config.isEvm) {
702
- if (!config.factoryAddress || !config.implementationAddress) {
703
- return null;
704
- }
705
- const address = this.computeVaultAddress(
706
- credential.keyHash,
707
- config.factoryAddress,
708
- config.implementationAddress
709
- );
710
- return {
711
- wormholeChainId,
712
- chainName: config.chainName,
713
- address,
714
- isEvm: true,
715
- deployed: false
716
- // Will be checked separately
717
- };
718
- } else {
719
- return this.deriveNonEvmAddress(credential, wormholeChainId, config);
720
- }
721
- }
722
- /**
723
- * Derive address for non-EVM chains
724
- *
725
- * Each chain has its own address format:
726
- * - Solana: Base58 encoded public key hash
727
- * - Aptos: 32-byte hex address
728
- * - Sui: 32-byte hex address with 0x prefix
729
- */
730
- deriveNonEvmAddress(credential, wormholeChainId, _config) {
731
- switch (wormholeChainId) {
732
- case 1:
733
- return {
734
- wormholeChainId: 1,
735
- chainName: "Solana",
736
- address: credential.keyHash,
737
- // PDA will be derived from this
738
- isEvm: false,
739
- derivationType: "pda",
740
- deployed: false
741
- };
742
- case 22:
743
- return {
744
- wormholeChainId: 22,
745
- chainName: "Aptos",
746
- address: credential.keyHash,
747
- isEvm: false,
748
- derivationType: "resource_account",
749
- deployed: false
750
- };
751
- case 21:
752
- return {
753
- wormholeChainId: 21,
754
- chainName: "Sui",
755
- address: credential.keyHash,
756
- isEvm: false,
757
- derivationType: "object",
758
- deployed: false
759
- };
760
- default:
761
- return null;
762
- }
763
- }
764
- // ========================================================================
765
- // Address Lookup
766
- // ========================================================================
767
- /**
768
- * Get cached address for a chain
769
- */
770
- getAddressForChain(keyHash, wormholeChainId) {
771
- const addresses = this.addressCache.get(keyHash);
772
- return addresses?.find((a) => a.wormholeChainId === wormholeChainId);
773
- }
774
- /**
775
- * Get all cached addresses for a key hash
776
- */
777
- getAddresses(keyHash) {
778
- return this.addressCache.get(keyHash) ?? [];
779
- }
780
- /**
781
- * Update deployment status for an address
782
- */
783
- updateDeploymentStatus(keyHash, wormholeChainId, deployed, deploymentTxHash) {
784
- const addresses = this.addressCache.get(keyHash);
785
- if (!addresses) return;
786
- const address = addresses.find((a) => a.wormholeChainId === wormholeChainId);
787
- if (address) {
788
- address.deployed = deployed;
789
- address.deploymentTxHash = deploymentTxHash;
790
- }
791
- if (this.config.persistToStorage) {
792
- this.saveAddressesToStorage(keyHash, addresses);
793
- }
794
- }
795
- // ========================================================================
796
- // Storage
797
- // ========================================================================
798
- /**
799
- * Load addresses from localStorage
800
- */
801
- loadFromStorage() {
802
- if (typeof window === "undefined") return;
803
- try {
804
- const stored = localStorage.getItem(this.config.storageKey);
805
- if (!stored) return;
806
- const data = JSON.parse(stored);
807
- for (const [keyHash, addresses] of Object.entries(data.addresses)) {
808
- this.addressCache.set(keyHash, addresses);
809
- }
810
- } catch (error) {
811
- console.warn("Failed to load wallet addresses from storage:", error);
812
- }
813
- }
814
- /**
815
- * Save identity to localStorage
816
- */
817
- saveToStorage(identity) {
818
- if (typeof window === "undefined") return;
819
- try {
820
- const stored = localStorage.getItem(this.config.storageKey) ?? "{}";
821
- const data = JSON.parse(stored);
822
- if (!data.addresses) {
823
- data.addresses = {};
824
- }
825
- data.addresses[identity.keyHash] = identity.addresses;
826
- data.identities = data.identities ?? {};
827
- data.identities[identity.keyHash] = {
828
- keyHash: identity.keyHash,
829
- publicKeyX: identity.publicKeyX.toString(),
830
- publicKeyY: identity.publicKeyY.toString(),
831
- credentialId: identity.credentialId,
832
- createdAt: identity.createdAt,
833
- updatedAt: identity.updatedAt
834
- };
835
- localStorage.setItem(this.config.storageKey, JSON.stringify(data));
836
- } catch (error) {
837
- console.warn("Failed to save wallet addresses to storage:", error);
838
- }
839
- }
840
- /**
841
- * Save addresses to localStorage
842
- */
843
- saveAddressesToStorage(keyHash, addresses) {
844
- if (typeof window === "undefined") return;
845
- try {
846
- const stored = localStorage.getItem(this.config.storageKey) ?? "{}";
847
- const data = JSON.parse(stored);
848
- if (!data.addresses) {
849
- data.addresses = {};
850
- }
851
- data.addresses[keyHash] = addresses;
852
- localStorage.setItem(this.config.storageKey, JSON.stringify(data));
853
- } catch (error) {
854
- console.warn("Failed to save wallet addresses to storage:", error);
855
- }
856
- }
857
- /**
858
- * Clear all cached data
859
- */
860
- clearCache() {
861
- this.addressCache.clear();
862
- if (this.config.persistToStorage && typeof window !== "undefined") {
863
- localStorage.removeItem(this.config.storageKey);
864
- }
865
- }
866
- /**
867
- * Load identity from storage
868
- */
869
- loadIdentityFromStorage(keyHash) {
870
- if (typeof window === "undefined") return null;
871
- try {
872
- const stored = localStorage.getItem(this.config.storageKey);
873
- if (!stored) return null;
874
- const data = JSON.parse(stored);
875
- const storedIdentity = data.identities?.[keyHash];
876
- const addresses = data.addresses?.[keyHash];
877
- if (!storedIdentity || !addresses) return null;
878
- return {
879
- keyHash: storedIdentity.keyHash,
880
- publicKeyX: BigInt(storedIdentity.publicKeyX),
881
- publicKeyY: BigInt(storedIdentity.publicKeyY),
882
- credentialId: storedIdentity.credentialId,
883
- addresses,
884
- createdAt: storedIdentity.createdAt,
885
- updatedAt: storedIdentity.updatedAt
886
- };
887
- } catch (error) {
888
- console.warn("Failed to load identity from storage:", error);
889
- return null;
890
- }
891
- }
892
- };
893
-
894
- // src/constants/tokens.ts
895
- var NATIVE_TOKEN_ADDRESS = "native";
896
- var EVM_ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
897
- var BASE_SEPOLIA_TOKENS = {
898
- wormholeChainId: 10004,
899
- chainName: "Base Sepolia",
900
- nativeToken: {
901
- symbol: "ETH",
902
- name: "Ether",
903
- address: NATIVE_TOKEN_ADDRESS,
904
- decimals: 18,
905
- isNative: true
906
- },
907
- tokens: [
908
- {
909
- symbol: "USDC",
910
- name: "USD Coin (Test)",
911
- address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
912
- // Circle test USDC
913
- decimals: 6,
914
- isNative: false
915
- },
916
- {
917
- symbol: "WETH",
918
- name: "Wrapped Ether",
919
- address: "0x4200000000000000000000000000000000000006",
920
- decimals: 18,
921
- isNative: false
922
- }
923
- ]
924
- };
925
- var OPTIMISM_SEPOLIA_TOKENS = {
926
- wormholeChainId: 10005,
927
- chainName: "Optimism Sepolia",
928
- nativeToken: {
929
- symbol: "ETH",
930
- name: "Ether",
931
- address: NATIVE_TOKEN_ADDRESS,
932
- decimals: 18,
933
- isNative: true
934
- },
935
- tokens: [
936
- {
937
- symbol: "USDC",
938
- name: "USD Coin (Test)",
939
- address: "0x5fd84259d66Cd46123540766Be93DFE6D43130D7",
940
- // Test USDC
941
- decimals: 6,
942
- isNative: false
943
- },
944
- {
945
- symbol: "WETH",
946
- name: "Wrapped Ether",
947
- address: "0x4200000000000000000000000000000000000006",
948
- decimals: 18,
949
- isNative: false
950
- },
951
- {
952
- symbol: "WETH.base",
953
- name: "Wrapped WETH (Base via Wormhole)",
954
- address: "0xD408f6498f48aE11BcAb518dA39cF7940eE3271d",
955
- // Wormhole-wrapped Base WETH
956
- decimals: 18,
957
- isNative: false
958
- }
959
- ]
960
- };
961
- var ARBITRUM_SEPOLIA_TOKENS = {
962
- wormholeChainId: 10003,
963
- chainName: "Arbitrum Sepolia",
964
- nativeToken: {
965
- symbol: "ETH",
966
- name: "Ether",
967
- address: NATIVE_TOKEN_ADDRESS,
968
- decimals: 18,
969
- isNative: true
970
- },
971
- tokens: [
972
- {
973
- symbol: "USDC",
974
- name: "USD Coin (Test)",
975
- address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
976
- // Circle USDC Arbitrum Sepolia
977
- decimals: 6,
978
- isNative: false
979
- },
980
- {
981
- symbol: "WETH",
982
- name: "Wrapped Ether",
983
- address: "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73",
984
- decimals: 18,
985
- isNative: false
986
- }
987
- ]
988
- };
989
- var ETHEREUM_SEPOLIA_TOKENS = {
990
- wormholeChainId: 10002,
991
- chainName: "Ethereum Sepolia",
992
- nativeToken: {
993
- symbol: "ETH",
994
- name: "Ether",
995
- address: NATIVE_TOKEN_ADDRESS,
996
- decimals: 18,
997
- isNative: true
998
- },
999
- tokens: [
1000
- {
1001
- symbol: "USDC",
1002
- name: "USD Coin (Test)",
1003
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
1004
- // Circle USDC Sepolia
1005
- decimals: 6,
1006
- isNative: false
1007
- },
1008
- {
1009
- symbol: "WETH",
1010
- name: "Wrapped Ether",
1011
- address: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
1012
- // WETH Sepolia
1013
- decimals: 18,
1014
- isNative: false
1015
- },
1016
- {
1017
- symbol: "LINK",
1018
- name: "Chainlink Token",
1019
- address: "0x779877A7B0D9E8603169DdbD7836e478b4624789",
1020
- // LINK Sepolia
1021
- decimals: 18,
1022
- isNative: false
1023
- }
1024
- ]
1025
- };
1026
- var MONAD_TESTNET_TOKENS = {
1027
- wormholeChainId: 10048,
1028
- chainName: "Monad Testnet",
1029
- nativeToken: {
1030
- symbol: "MON",
1031
- name: "Monad",
1032
- decimals: 18,
1033
- address: NATIVE_TOKEN_ADDRESS,
1034
- isNative: true
1035
- },
1036
- tokens: [
1037
- {
1038
- symbol: "USDC",
1039
- name: "USD Coin",
1040
- decimals: 6,
1041
- address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
1042
- isNative: false
1043
- },
1044
- {
1045
- symbol: "AUSD",
1046
- name: "Agora Dollar",
1047
- decimals: 18,
1048
- address: "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a",
1049
- isNative: false
1050
- },
1051
- {
1052
- symbol: "WMON",
1053
- name: "Wrapped MON",
1054
- decimals: 18,
1055
- address: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
1056
- isNative: false
1057
- }
1058
- ]
1059
- };
1060
- var TOKEN_REGISTRY = {
1061
- 10004: BASE_SEPOLIA_TOKENS,
1062
- 10005: OPTIMISM_SEPOLIA_TOKENS,
1063
- 10003: ARBITRUM_SEPOLIA_TOKENS,
1064
- 10002: ETHEREUM_SEPOLIA_TOKENS,
1065
- 10048: MONAD_TESTNET_TOKENS
1066
- };
1067
- function getTokenList(wormholeChainId) {
1068
- return TOKEN_REGISTRY[wormholeChainId] ?? null;
1069
- }
1070
- function getAllTokens(wormholeChainId) {
1071
- const list = getTokenList(wormholeChainId);
1072
- if (!list) return [];
1073
- return [list.nativeToken, ...list.tokens];
1074
- }
1075
- function isNativeToken(address) {
1076
- return address.toLowerCase() === NATIVE_TOKEN_ADDRESS || address === EVM_ZERO_ADDRESS;
1077
- }
1078
-
1079
- // src/queries/portfolio.ts
1080
- var QueryPortfolioError = class extends Error {
1081
- code;
1082
- cause;
1083
- constructor(code, message, cause) {
1084
- super(message);
1085
- this.name = "QueryPortfolioError";
1086
- this.code = code;
1087
- this.cause = cause;
1088
- }
1089
- };
1090
- var PORTFOLIO_CACHE = /* @__PURE__ */ new Map();
1091
- function resolveNetwork2(options) {
1092
- if (options?.network) return options.network;
1093
- const envCandidates = [
1094
- globalThis?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,
1095
- globalThis?.process?.env?.VERIDEX_NETWORK,
1096
- globalThis?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,
1097
- globalThis?.process?.env?.WORMHOLE_NETWORK
1098
- ].filter(Boolean);
1099
- const env = envCandidates[0]?.toLowerCase();
1100
- if (env === "mainnet" || env === "testnet") return env;
1101
- return "testnet";
1102
- }
1103
- function concatBytes2(parts) {
1104
- const total = parts.reduce((sum, p) => sum + p.length, 0);
1105
- const out = new Uint8Array(total);
1106
- let offset = 0;
1107
- for (const p of parts) {
1108
- out.set(p, offset);
1109
- offset += p.length;
1110
- }
1111
- return out;
1112
- }
1113
- function signaturesToProofBytes2(signatures) {
1114
- const chunks = [];
1115
- for (const sig of signatures) {
1116
- if (typeof sig !== "string" || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {
1117
- throw new QueryPortfolioError(
1118
- "PROXY_RESPONSE_INVALID",
1119
- `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`
1120
- );
1121
- }
1122
- chunks.push(hexToUint8Array2(`0x${sig}`));
1123
- }
1124
- return concatBytes2(chunks);
1125
- }
1126
- function decodeQueryBytes2(bytes) {
1127
- if (typeof bytes !== "string" || bytes.length === 0) {
1128
- throw new QueryPortfolioError("PROXY_RESPONSE_INVALID", "Missing query response bytes");
1129
- }
1130
- if (isValidHexString2(bytes)) {
1131
- return hexToUint8Array2(bytes);
1132
- }
1133
- try {
1134
- if (typeof atob === "function") {
1135
- const raw = atob(bytes);
1136
- const arr = new Uint8Array(raw.length);
1137
- for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);
1138
- return arr;
1139
- }
1140
- } catch {
1141
- }
1142
- try {
1143
- return new Uint8Array(Buffer2.from(bytes, "base64"));
1144
- } catch (cause) {
1145
- throw new QueryPortfolioError("PROXY_RESPONSE_INVALID", "Unrecognized query response bytes encoding", cause);
1146
- }
1147
- }
1148
- function sleep2(ms) {
1149
- return new Promise((resolve) => setTimeout(resolve, ms));
1150
- }
1151
- var rateLimiter = {
1152
- queue: [],
1153
- lastRequest: 0,
1154
- minInterval: 170,
1155
- // ~6 req/s with buffer
1156
- async acquire() {
1157
- return new Promise((resolve) => {
1158
- const tryAcquire = () => {
1159
- const now = Date.now();
1160
- const elapsed = now - rateLimiter.lastRequest;
1161
- if (elapsed >= rateLimiter.minInterval) {
1162
- rateLimiter.lastRequest = now;
1163
- resolve();
1164
- } else {
1165
- setTimeout(tryAcquire, rateLimiter.minInterval - elapsed);
1166
- }
1167
- };
1168
- tryAcquire();
1169
- });
1170
- }
1171
- };
1172
- async function withExponentialBackoff2(fn, maxAttempts) {
1173
- let attempt = 0;
1174
- let lastError;
1175
- while (attempt < maxAttempts) {
1176
- try {
1177
- return await fn();
1178
- } catch (err) {
1179
- lastError = err;
1180
- attempt += 1;
1181
- if (attempt >= maxAttempts) break;
1182
- const baseMs = 250;
1183
- const backoffMs = Math.min(5e3, baseMs * 2 ** (attempt - 1));
1184
- const jitterMs = Math.floor(Math.random() * 100);
1185
- await sleep2(backoffMs + jitterMs);
1186
- }
1187
- }
1188
- throw lastError;
1189
- }
1190
- function getChainConfigs(network) {
1191
- return network === "testnet" ? TESTNET_CHAINS : MAINNET_CHAINS;
1192
- }
1193
- function getProxyEndpoint(network, options) {
1194
- if (options?.endpoint) return options.endpoint;
1195
- return network === "testnet" ? WORMHOLE_QUERY_PROXY_URLS.testnet : WORMHOLE_QUERY_PROXY_URLS.mainnet;
1196
- }
1197
- function getDefaultPortfolioChains(network) {
1198
- return network === "testnet" ? [10004, 10005, 10003, 1] : [30, 24, 23, 1];
1199
- }
1200
- function normalizeHex32(hex) {
1201
- if (typeof hex !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(hex)) {
1202
- throw new QueryPortfolioError("INVALID_ARGUMENT", `Invalid userKeyHash (expected 0x + 32 bytes hex): ${hex}`);
1203
- }
1204
- return new Uint8Array(Buffer2.from(hex.slice(2), "hex"));
1205
- }
1206
- function deriveSolanaVaultAddress(programIdBase58, userKeyHash) {
1207
- const programId = new PublicKey(programIdBase58);
1208
- const keyHashBytes = normalizeHex32(userKeyHash);
1209
- const [vaultPda] = PublicKey.findProgramAddressSync([Buffer2.from("vault"), Buffer2.from(keyHashBytes)], programId);
1210
- return vaultPda.toBase58();
1211
- }
1212
- function makeCacheKey(userKeyHash, apiKey, options, chainIds) {
1213
- const payload = {
1214
- userKeyHash,
1215
- network: resolveNetwork2(options),
1216
- chainIds: [...chainIds].sort((a, b) => a - b),
1217
- vaultAddresses: options?.vaultAddresses ?? null,
1218
- evmTokenAddresses: options?.evmTokenAddresses ?? null,
1219
- solanaAccounts: options?.solanaAccounts ?? null,
1220
- endpoint: options?.endpoint ?? null
1221
- };
1222
- void apiKey;
1223
- return JSON.stringify(payload);
1224
- }
1225
- function safeNumberFromBigint(b) {
1226
- const n = Number(b);
1227
- return Number.isFinite(n) ? n : 0;
1228
- }
1229
- function priceLookup(pricesUsd, symbol, assetId) {
1230
- if (!pricesUsd) return void 0;
1231
- if (symbol && pricesUsd[symbol] != null) return pricesUsd[symbol];
1232
- if (assetId && pricesUsd[assetId] != null) return pricesUsd[assetId];
1233
- return void 0;
1234
- }
1235
- function sumUsd(balances, pricesUsd) {
1236
- let total = 0;
1237
- let any = false;
1238
- for (const b of balances) {
1239
- const p = priceLookup(pricesUsd, b.symbol, b.assetId);
1240
- if (p == null) continue;
1241
- if (b.decimals == null) continue;
1242
- const denom = 10 ** b.decimals;
1243
- const amount = Number(b.amount) / denom;
1244
- if (!Number.isFinite(amount)) continue;
1245
- total += amount * p;
1246
- any = true;
1247
- }
1248
- return any ? total : void 0;
1249
- }
1250
- async function getRecentBlockTag(rpcUrl) {
1251
- const provider = new ethers4.JsonRpcProvider(rpcUrl);
1252
- const latest = await provider.getBlockNumber();
1253
- return Math.max(0, latest - 2);
1254
- }
1255
- function encodeErc20BalanceCalls(vaultAddress, tokenAddresses) {
1256
- const iface = new ethers4.Interface(["function balanceOf(address owner) view returns (uint256)"]);
1257
- return tokenAddresses.map((token) => ({
1258
- to: token,
1259
- data: iface.encodeFunctionData("balanceOf", [vaultAddress])
1260
- }));
1261
- }
1262
- function decodeErc20Balances(results, tokenAddresses) {
1263
- const iface = new ethers4.Interface(["function balanceOf(address owner) view returns (uint256)"]);
1264
- const out = [];
1265
- for (let i = 0; i < tokenAddresses.length; i++) {
1266
- const data = results[i];
1267
- if (!data || data === "0x") {
1268
- out.push(0n);
1269
- continue;
1270
- }
1271
- const decoded = iface.decodeFunctionResult("balanceOf", data);
1272
- out.push(decoded[0]);
1273
- }
1274
- return out;
1275
- }
1276
- async function queryPortfolio(userKeyHash, apiKey, options) {
1277
- const network = resolveNetwork2(options);
1278
- const maxAgeSeconds = options?.maxAge ?? 60;
1279
- const maxAttempts = options?.maxAttempts ?? 4;
1280
- const cacheTtlMs = options?.cacheTtlMs ?? 3e4;
1281
- const endpoint = getProxyEndpoint(network, options);
1282
- const chainIds = options?.rpcUrls ? Object.keys(options.rpcUrls).map(Number) : void 0;
1283
- void chainIds;
1284
- const requestedChains = options?.vaultAddresses ? Object.keys(options.vaultAddresses).map(Number) : void 0;
1285
- const defaultChains = getDefaultPortfolioChains(network);
1286
- const wormholeChainIds = options?.evmTokenAddresses ? Array.from(/* @__PURE__ */ new Set([...defaultChains, ...Object.keys(options.evmTokenAddresses).map(Number)])) : defaultChains;
1287
- const finalChainIds = requestedChains ? Array.from(/* @__PURE__ */ new Set([...wormholeChainIds, ...requestedChains])) : wormholeChainIds;
1288
- if (!apiKey || typeof apiKey !== "string") {
1289
- throw new QueryPortfolioError("INVALID_ARGUMENT", "Missing Query Proxy apiKey");
1290
- }
1291
- const cacheKey = makeCacheKey(userKeyHash, apiKey, options, finalChainIds);
1292
- const cached = PORTFOLIO_CACHE.get(cacheKey);
1293
- if (cached && cached.expiresAt > Date.now()) {
1294
- return cached.value;
1295
- }
1296
- const chains = getChainConfigs(network);
1297
- const walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });
1298
- const pricesUsd = {
1299
- USDC: 1,
1300
- ...options?.pricesUsd ?? {}
1301
- };
1302
- const doFetch = async () => {
1303
- try {
1304
- const perChainRequests = [];
1305
- const chainMeta = {};
1306
- const evmChainIds = finalChainIds.filter((id) => {
1307
- const cfg = Object.values(chains).find((c) => c.wormholeChainId === id);
1308
- return cfg?.isEvm;
1309
- });
1310
- const blockTagsByChainId = /* @__PURE__ */ new Map();
1311
- await Promise.all(
1312
- evmChainIds.map(async (wormholeChainId) => {
1313
- const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);
1314
- if (!cfg) return;
1315
- const rpcUrl = options?.rpcUrls?.[wormholeChainId] ?? cfg.rpcUrl;
1316
- const blockTag = await getRecentBlockTag(rpcUrl);
1317
- blockTagsByChainId.set(wormholeChainId, blockTag);
1318
- })
1319
- );
1320
- for (const wormholeChainId of finalChainIds) {
1321
- const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);
1322
- if (wormholeChainId === 22) {
1323
- chainMeta[wormholeChainId] = { kind: "unsupported", chainName: cfg?.name };
1324
- continue;
1325
- }
1326
- if (!cfg) {
1327
- chainMeta[wormholeChainId] = { kind: "unsupported" };
1328
- continue;
1329
- }
1330
- if (cfg.isEvm) {
1331
- const vaultAddress = options?.vaultAddresses?.[wormholeChainId] ?? (cfg.contracts.vaultFactory && cfg.contracts.vaultImplementation ? walletManager.computeVaultAddress(userKeyHash, cfg.contracts.vaultFactory, cfg.contracts.vaultImplementation) : void 0);
1332
- chainMeta[wormholeChainId] = { kind: "evm", vaultAddress, chainName: cfg.name };
1333
- if (!vaultAddress) {
1334
- continue;
1335
- }
1336
- const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId] ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);
1337
- if (!tokenAddresses.length) {
1338
- continue;
1339
- }
1340
- const blockTag = blockTagsByChainId.get(wormholeChainId);
1341
- if (blockTag == null) {
1342
- continue;
1343
- }
1344
- const calls = encodeErc20BalanceCalls(vaultAddress, tokenAddresses);
1345
- perChainRequests.push(new PerChainQueryRequest2(wormholeChainId, new EthCallQueryRequest2(blockTag, calls)));
1346
- continue;
1347
- }
1348
- if (wormholeChainId === 1) {
1349
- const programId = options?.vaultAddresses?.[wormholeChainId] ?? cfg.contracts.hub;
1350
- chainMeta[wormholeChainId] = { kind: "solana", chainName: cfg.name };
1351
- if (!programId) {
1352
- continue;
1353
- }
1354
- const vaultAddress = deriveSolanaVaultAddress(programId, userKeyHash);
1355
- chainMeta[wormholeChainId] = { kind: "solana", chainName: cfg.name, vaultAddress };
1356
- const accounts = [vaultAddress, ...options?.solanaAccounts ?? []];
1357
- perChainRequests.push(
1358
- new PerChainQueryRequest2(
1359
- wormholeChainId,
1360
- new SolanaAccountQueryRequest("finalized", accounts, void 0, 0n, 0n)
1361
- )
1362
- );
1363
- continue;
1364
- }
1365
- chainMeta[wormholeChainId] = { kind: "unsupported", chainName: cfg.name };
1366
- }
1367
- if (perChainRequests.length > 255) {
1368
- throw new QueryPortfolioError(
1369
- "INVALID_ARGUMENT",
1370
- `Too many per-chain requests (${perChainRequests.length}); max is 255 per Query Proxy request`
1371
- );
1372
- }
1373
- if (perChainRequests.length === 0) {
1374
- const chainsOut2 = finalChainIds.map((wormholeChainId) => {
1375
- const meta = chainMeta[wormholeChainId] ?? { kind: "unsupported" };
1376
- return {
1377
- wormholeChainId,
1378
- chainName: meta.chainName,
1379
- vaultAddress: meta.vaultAddress,
1380
- balances: [],
1381
- error: {
1382
- code: "MISSING_VAULT",
1383
- message: "Unable to build query: missing vault address or no tokens configured"
1384
- }
1385
- };
1386
- });
1387
- return { proof: new Uint8Array(), totalUsd: 0, chains: chainsOut2 };
1388
- }
1389
- const request = new QueryRequest2(Date.now() & 4294967295, perChainRequests);
1390
- const requestHex = Buffer2.from(request.serialize()).toString("hex");
1391
- await rateLimiter.acquire();
1392
- let response;
1393
- try {
1394
- console.log("[queryPortfolio] Sending request to:", endpoint);
1395
- console.log("[queryPortfolio] Request bytes length:", requestHex.length);
1396
- const defaultTimeout = network === "testnet" ? 15e3 : 1e4;
1397
- const requestTimeout = options?.timeout ?? defaultTimeout;
1398
- response = await axios2.post(
1399
- endpoint,
1400
- { bytes: requestHex },
1401
- {
1402
- headers: {
1403
- "X-API-Key": apiKey,
1404
- "Content-Type": "application/json"
1405
- },
1406
- timeout: requestTimeout
1407
- }
1408
- );
1409
- } catch (axiosErr) {
1410
- const err = axiosErr;
1411
- if (!err.response) {
1412
- console.error("[queryPortfolio] Network error:", {
1413
- message: err.message,
1414
- code: err.code,
1415
- name: err.name
1416
- });
1417
- throw new QueryPortfolioError(
1418
- "NETWORK_ERROR",
1419
- `Network error: ${err.message} (code: ${err.code})`
1420
- );
1421
- }
1422
- const status = err.response.status;
1423
- const errData = err.response.data;
1424
- console.error("[queryPortfolio] Wormhole Query Proxy error:", { status, data: errData });
1425
- throw new QueryPortfolioError(
1426
- "PROXY_RESPONSE_INVALID",
1427
- `Query Proxy returned ${status}: ${JSON.stringify(errData)}`
1428
- );
1429
- }
1430
- const data = response.data;
1431
- const signatures = data?.signatures;
1432
- const bytes = data?.bytes;
1433
- if (!Array.isArray(signatures) || typeof bytes !== "string") {
1434
- throw new QueryPortfolioError("PROXY_RESPONSE_INVALID", "Query Proxy response missing signatures/bytes");
1435
- }
1436
- const proof = signaturesToProofBytes2(signatures);
1437
- const queryBytes = decodeQueryBytes2(bytes);
1438
- const parsed = QueryResponse2.from(queryBytes);
1439
- const nowSeconds = Math.floor(Date.now() / 1e3);
1440
- const chainsOut = [];
1441
- for (const wormholeChainId of finalChainIds) {
1442
- const meta = chainMeta[wormholeChainId] ?? { kind: "unsupported" };
1443
- if (meta.kind === "unsupported") {
1444
- const msg = wormholeChainId === 22 ? "Aptos Queries are not supported by the Wormhole Query SDK yet" : "Chain is not supported by this portfolio query implementation";
1445
- chainsOut.push({
1446
- wormholeChainId,
1447
- chainName: meta.chainName,
1448
- balances: [],
1449
- error: { code: "UNSUPPORTED_CHAIN", message: msg }
1450
- });
1451
- continue;
1452
- }
1453
- if (!meta.vaultAddress) {
1454
- chainsOut.push({
1455
- wormholeChainId,
1456
- chainName: meta.chainName,
1457
- balances: [],
1458
- error: { code: "MISSING_VAULT", message: "Unable to derive vault address for chain" }
1459
- });
1460
- continue;
1461
- }
1462
- const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);
1463
- if (!perChain) {
1464
- chainsOut.push({
1465
- wormholeChainId,
1466
- chainName: meta.chainName,
1467
- vaultAddress: meta.vaultAddress,
1468
- balances: [],
1469
- error: { code: "DECODE_ERROR", message: "Missing per-chain response from Query Proxy" }
1470
- });
1471
- continue;
1472
- }
1473
- try {
1474
- if (meta.kind === "evm") {
1475
- const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);
1476
- const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId] ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);
1477
- if (!tokenAddresses.length) {
1478
- chainsOut.push({
1479
- wormholeChainId,
1480
- chainName: meta.chainName,
1481
- vaultAddress: meta.vaultAddress,
1482
- balances: [],
1483
- error: { code: "MISSING_TOKENS", message: "No ERC20 tokens configured for EVM portfolio query" }
1484
- });
1485
- continue;
1486
- }
1487
- const chainResp2 = EthCallQueryResponse2.from(perChain.response.serialize());
1488
- const blockTime2 = Number(chainResp2.blockTime);
1489
- const age2 = nowSeconds - blockTime2;
1490
- if (age2 > maxAgeSeconds) {
1491
- chainsOut.push({
1492
- wormholeChainId,
1493
- chainName: meta.chainName,
1494
- vaultAddress: meta.vaultAddress,
1495
- blockTime: blockTime2,
1496
- balances: [],
1497
- error: { code: "ATTESTATION_STALE", message: `Attestation stale by ${age2}s (maxAge=${maxAgeSeconds}s)` }
1498
- });
1499
- continue;
1500
- }
1501
- const amounts = decodeErc20Balances(chainResp2.results, tokenAddresses);
1502
- const tokenInfos = getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address));
1503
- const balances2 = tokenAddresses.map((addr, i) => {
1504
- const info = tokenInfos.find((t) => t.address.toLowerCase() === addr.toLowerCase());
1505
- const symbol = info?.symbol;
1506
- const decimals = info?.decimals;
1507
- const usdPrice = priceLookup(pricesUsd, symbol, addr);
1508
- const usdValue = usdPrice != null && decimals != null ? Number(amounts[i]) / 10 ** decimals * usdPrice : void 0;
1509
- return {
1510
- assetId: addr,
1511
- amount: amounts[i],
1512
- symbol,
1513
- decimals,
1514
- usdValue: Number.isFinite(usdValue ?? NaN) ? usdValue : void 0
1515
- };
1516
- });
1517
- void cfg;
1518
- chainsOut.push({
1519
- wormholeChainId,
1520
- chainName: meta.chainName,
1521
- vaultAddress: meta.vaultAddress,
1522
- blockTime: blockTime2,
1523
- balances: balances2
1524
- });
1525
- continue;
1526
- }
1527
- const chainResp = SolanaAccountQueryResponse.from(perChain.response.serialize());
1528
- const blockTime = safeNumberFromBigint(chainResp.blockTime);
1529
- const age = nowSeconds - blockTime;
1530
- if (age > maxAgeSeconds) {
1531
- chainsOut.push({
1532
- wormholeChainId,
1533
- chainName: meta.chainName,
1534
- vaultAddress: meta.vaultAddress,
1535
- blockTime,
1536
- balances: [],
1537
- error: { code: "ATTESTATION_STALE", message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` }
1538
- });
1539
- continue;
1540
- }
1541
- const vaultResult = chainResp.results[0];
1542
- const lamports = vaultResult?.lamports ?? 0n;
1543
- const balances = [
1544
- {
1545
- assetId: "SOL",
1546
- amount: lamports,
1547
- decimals: 9,
1548
- symbol: "SOL",
1549
- usdValue: priceLookup(pricesUsd, "SOL", "SOL") != null ? Number(lamports) / 1e9 * priceLookup(pricesUsd, "SOL", "SOL") : void 0
1550
- }
1551
- ];
1552
- chainsOut.push({
1553
- wormholeChainId,
1554
- chainName: meta.chainName,
1555
- vaultAddress: meta.vaultAddress,
1556
- blockTime,
1557
- balances
1558
- });
1559
- } catch (cause) {
1560
- chainsOut.push({
1561
- wormholeChainId,
1562
- chainName: meta.chainName,
1563
- vaultAddress: meta.vaultAddress,
1564
- balances: [],
1565
- error: { code: "DECODE_ERROR", message: `Failed to decode chain response: ${String(cause?.message ?? cause)}` }
1566
- });
1567
- }
1568
- }
1569
- const allBalances = chainsOut.flatMap((c) => c.balances);
1570
- const totalUsd = sumUsd(allBalances, pricesUsd);
1571
- const result2 = { proof, totalUsd, chains: chainsOut };
1572
- PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result2 });
1573
- return result2;
1574
- } catch (err) {
1575
- if (err instanceof QueryPortfolioError) throw err;
1576
- if (axios2.isAxiosError(err)) {
1577
- const ax = err;
1578
- const status = ax.response?.status;
1579
- const statusText = ax.response?.statusText;
1580
- const details = typeof ax.response?.data === "string" ? ax.response?.data : void 0;
1581
- throw new QueryPortfolioError(
1582
- "PROXY_HTTP_ERROR",
1583
- `Query Proxy request failed${status ? ` (${status} ${statusText ?? ""})` : ""}${details ? `: ${details}` : ""}`,
1584
- err
1585
- );
1586
- }
1587
- throw new QueryPortfolioError("PROXY_HTTP_ERROR", "Query Proxy request failed", err);
1588
- }
1589
- };
1590
- const result = await withExponentialBackoff2(doFetch, maxAttempts);
1591
- PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });
1592
- return result;
1593
- }
6
+ QueryHubStateError,
7
+ queryHubState
8
+ } from "../chunk-CCHASDAI.mjs";
9
+ import {
10
+ WORMHOLE_QUERY_CHAIN_IDS,
11
+ WORMHOLE_QUERY_PROXY_URLS,
12
+ WORMHOLE_QUERY_RATE_LIMIT_PER_SECOND
13
+ } from "../chunk-72ZA3OYQ.mjs";
14
+ import "../chunk-NU6JGI7L.mjs";
15
+ import "../chunk-KHV3EP3I.mjs";
16
+ import "../chunk-K73Y36KS.mjs";
1594
17
  export {
1595
18
  QueryHubStateError,
1596
19
  QueryPortfolioError,