@veridex/sdk 1.0.0-beta.9 → 1.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.
Files changed (132) hide show
  1. package/LICENSE +170 -21
  2. package/README.md +574 -117
  3. package/dist/EVMClient-DtqvdfUP.d.mts +376 -0
  4. package/dist/auth/prepareAuth.d.mts +25 -0
  5. package/dist/auth/prepareAuth.js +2406 -0
  6. package/dist/auth/prepareAuth.js.map +1 -0
  7. package/dist/auth/prepareAuth.mjs +151 -0
  8. package/dist/auth/prepareAuth.mjs.map +1 -0
  9. package/dist/chains/aptos/index.d.mts +6 -5
  10. package/dist/chains/aptos/index.js +66 -39
  11. package/dist/chains/aptos/index.js.map +1 -1
  12. package/dist/chains/aptos/index.mjs +5 -547
  13. package/dist/chains/aptos/index.mjs.map +1 -1
  14. package/dist/chains/avalanche/index.d.mts +137 -0
  15. package/dist/chains/avalanche/index.js +1555 -0
  16. package/dist/chains/avalanche/index.js.map +1 -0
  17. package/dist/chains/avalanche/index.mjs +10 -0
  18. package/dist/chains/avalanche/index.mjs.map +1 -0
  19. package/dist/chains/evm/index.d.mts +5 -3
  20. package/dist/chains/evm/index.js +165 -3
  21. package/dist/chains/evm/index.js.map +1 -1
  22. package/dist/chains/evm/index.mjs +8 -1200
  23. package/dist/chains/evm/index.mjs.map +1 -1
  24. package/dist/chains/solana/index.d.mts +1 -1
  25. package/dist/chains/solana/index.js.map +1 -1
  26. package/dist/chains/solana/index.mjs +4 -486
  27. package/dist/chains/solana/index.mjs.map +1 -1
  28. package/dist/chains/stacks/index.d.mts +559 -0
  29. package/dist/chains/stacks/index.js +1207 -0
  30. package/dist/chains/stacks/index.js.map +1 -0
  31. package/dist/chains/stacks/index.mjs +71 -0
  32. package/dist/chains/stacks/index.mjs.map +1 -0
  33. package/dist/chains/starknet/index.d.mts +4 -5
  34. package/dist/chains/starknet/index.js +1 -13
  35. package/dist/chains/starknet/index.js.map +1 -1
  36. package/dist/chains/starknet/index.mjs +5 -503
  37. package/dist/chains/starknet/index.mjs.map +1 -1
  38. package/dist/chains/sui/index.d.mts +4 -4
  39. package/dist/chains/sui/index.js +2 -2
  40. package/dist/chains/sui/index.js.map +1 -1
  41. package/dist/chains/sui/index.mjs +5 -529
  42. package/dist/chains/sui/index.mjs.map +1 -1
  43. package/dist/chunk-5T6KPH7A.mjs +1082 -0
  44. package/dist/chunk-5T6KPH7A.mjs.map +1 -0
  45. package/dist/chunk-72ZA3OYQ.mjs +20 -0
  46. package/dist/chunk-72ZA3OYQ.mjs.map +1 -0
  47. package/dist/chunk-F3YAGZSW.mjs +269 -0
  48. package/dist/chunk-F3YAGZSW.mjs.map +1 -0
  49. package/dist/chunk-GWJRKDSA.mjs +549 -0
  50. package/dist/chunk-GWJRKDSA.mjs.map +1 -0
  51. package/dist/chunk-M3MM4YMF.mjs +417 -0
  52. package/dist/chunk-M3MM4YMF.mjs.map +1 -0
  53. package/dist/chunk-MLXQHIH2.mjs +426 -0
  54. package/dist/chunk-MLXQHIH2.mjs.map +1 -0
  55. package/dist/chunk-N4A2RMUN.mjs +216 -0
  56. package/dist/chunk-N4A2RMUN.mjs.map +1 -0
  57. package/dist/chunk-NUWSMJFJ.mjs +179 -0
  58. package/dist/chunk-NUWSMJFJ.mjs.map +1 -0
  59. package/dist/chunk-OVMMTL6H.mjs +330 -0
  60. package/dist/chunk-OVMMTL6H.mjs.map +1 -0
  61. package/dist/chunk-PDHZ5X5O.mjs +565 -0
  62. package/dist/chunk-PDHZ5X5O.mjs.map +1 -0
  63. package/dist/chunk-Q5O3M5LP.mjs +422 -0
  64. package/dist/chunk-Q5O3M5LP.mjs.map +1 -0
  65. package/dist/chunk-QDO6NQ7P.mjs +840 -0
  66. package/dist/chunk-QDO6NQ7P.mjs.map +1 -0
  67. package/dist/chunk-QT4ZZ4GM.mjs +509 -0
  68. package/dist/chunk-QT4ZZ4GM.mjs.map +1 -0
  69. package/dist/chunk-SXXGTQIR.mjs +464 -0
  70. package/dist/chunk-SXXGTQIR.mjs.map +1 -0
  71. package/dist/chunk-USDA5JTN.mjs +1249 -0
  72. package/dist/chunk-USDA5JTN.mjs.map +1 -0
  73. package/dist/chunk-V636MIV3.mjs +52 -0
  74. package/dist/chunk-V636MIV3.mjs.map +1 -0
  75. package/dist/chunk-X7BZMSPQ.mjs +407 -0
  76. package/dist/chunk-X7BZMSPQ.mjs.map +1 -0
  77. package/dist/chunk-YCUJZ6Z7.mjs +829 -0
  78. package/dist/chunk-YCUJZ6Z7.mjs.map +1 -0
  79. package/dist/constants.d.mts +1 -1
  80. package/dist/constants.js +26 -12
  81. package/dist/constants.js.map +1 -1
  82. package/dist/constants.mjs +16 -375
  83. package/dist/constants.mjs.map +1 -1
  84. package/dist/index-DDalBhAm.d.mts +243 -0
  85. package/dist/index.d.mts +2511 -556
  86. package/dist/index.js +15216 -10262
  87. package/dist/index.js.map +1 -1
  88. package/dist/index.mjs +4125 -7839
  89. package/dist/index.mjs.map +1 -1
  90. package/dist/passkey.d.mts +182 -0
  91. package/dist/passkey.js +914 -0
  92. package/dist/passkey.js.map +1 -0
  93. package/dist/passkey.mjs +15 -0
  94. package/dist/passkey.mjs.map +1 -0
  95. package/dist/payload.js.map +1 -1
  96. package/dist/payload.mjs +25 -244
  97. package/dist/payload.mjs.map +1 -1
  98. package/dist/portfolio-V347KZOL.mjs +13 -0
  99. package/dist/portfolio-V347KZOL.mjs.map +1 -0
  100. package/dist/queries/index.js +145 -12
  101. package/dist/queries/index.js.map +1 -1
  102. package/dist/queries/index.mjs +14 -1496
  103. package/dist/queries/index.mjs.map +1 -1
  104. package/dist/{types-FJL7j6gQ.d.ts → types-B7V5VNbO.d.mts} +6 -2
  105. package/dist/{types-ChIsqCiw.d.mts → types-DP2CQT8p.d.mts} +12 -1
  106. package/dist/types.d.mts +16 -0
  107. package/dist/types.js.map +1 -1
  108. package/dist/utils.js +25 -11
  109. package/dist/utils.js.map +1 -1
  110. package/dist/utils.mjs +19 -371
  111. package/dist/utils.mjs.map +1 -1
  112. package/dist/wormhole.js.map +1 -1
  113. package/dist/wormhole.mjs +25 -397
  114. package/dist/wormhole.mjs.map +1 -1
  115. package/package.json +28 -3
  116. package/scripts/patch-noble-curves.js +78 -0
  117. package/dist/chains/aptos/index.d.ts +0 -145
  118. package/dist/chains/evm/index.d.ts +0 -5
  119. package/dist/chains/solana/index.d.ts +0 -116
  120. package/dist/chains/starknet/index.d.ts +0 -172
  121. package/dist/chains/sui/index.d.ts +0 -182
  122. package/dist/constants.d.ts +0 -150
  123. package/dist/index-0NXfbk0z.d.ts +0 -637
  124. package/dist/index-D0dLVjTA.d.mts +0 -637
  125. package/dist/index.d.ts +0 -3123
  126. package/dist/payload.d.ts +0 -125
  127. package/dist/queries/index.d.ts +0 -148
  128. package/dist/types-ChIsqCiw.d.ts +0 -565
  129. package/dist/types-FJL7j6gQ.d.mts +0 -172
  130. package/dist/types.d.ts +0 -407
  131. package/dist/utils.d.ts +0 -81
  132. package/dist/wormhole.d.ts +0 -167
@@ -0,0 +1,422 @@
1
+ import {
2
+ encodeBridgeAction,
3
+ encodeExecuteAction,
4
+ encodeTransferAction
5
+ } from "./chunk-F3YAGZSW.mjs";
6
+
7
+ // src/chains/solana/SolanaClient.ts
8
+ import {
9
+ Connection,
10
+ PublicKey
11
+ } from "@solana/web3.js";
12
+ import {
13
+ getAssociatedTokenAddressSync
14
+ } from "@solana/spl-token";
15
+ import { createHash } from "crypto";
16
+ var SolanaClient = class {
17
+ config;
18
+ connection;
19
+ programId;
20
+ constructor(config) {
21
+ this.config = {
22
+ name: `Solana ${config.network || "mainnet"}`,
23
+ chainId: config.wormholeChainId,
24
+ wormholeChainId: config.wormholeChainId,
25
+ rpcUrl: config.rpcUrl,
26
+ explorerUrl: config.network === "devnet" ? "https://explorer.solana.com?cluster=devnet" : "https://explorer.solana.com",
27
+ isEvm: false,
28
+ contracts: {
29
+ hub: void 0,
30
+ // Solana is a spoke only
31
+ wormholeCoreBridge: config.wormholeCoreBridge,
32
+ tokenBridge: config.tokenBridge
33
+ }
34
+ };
35
+ this.connection = new Connection(
36
+ config.rpcUrl,
37
+ config.commitment || "confirmed"
38
+ );
39
+ this.programId = new PublicKey(config.programId);
40
+ }
41
+ getConfig() {
42
+ return this.config;
43
+ }
44
+ async getNonce(userKeyHash) {
45
+ try {
46
+ const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);
47
+ const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));
48
+ if (!accountInfo || accountInfo.data.length < 40) {
49
+ return 0n;
50
+ }
51
+ const nonce = accountInfo.data.readBigUInt64LE(8);
52
+ return nonce;
53
+ } catch (error) {
54
+ console.error("Error getting nonce:", error);
55
+ return 0n;
56
+ }
57
+ }
58
+ async getMessageFee() {
59
+ try {
60
+ return 0n;
61
+ } catch (error) {
62
+ console.error("Error getting message fee:", error);
63
+ return 0n;
64
+ }
65
+ }
66
+ async buildTransferPayload(params) {
67
+ return encodeTransferAction(
68
+ params.token,
69
+ params.recipient,
70
+ params.amount
71
+ );
72
+ }
73
+ async buildExecutePayload(params) {
74
+ return encodeExecuteAction(
75
+ params.target,
76
+ params.value,
77
+ params.data
78
+ );
79
+ }
80
+ async buildBridgePayload(params) {
81
+ return encodeBridgeAction(
82
+ params.token,
83
+ params.amount,
84
+ params.destinationChain,
85
+ params.recipient
86
+ );
87
+ }
88
+ async dispatch(signature, publicKeyX, publicKeyY, targetChain, actionPayload, nonce, signer) {
89
+ void signature;
90
+ void publicKeyX;
91
+ void publicKeyY;
92
+ void targetChain;
93
+ void actionPayload;
94
+ void nonce;
95
+ void signer;
96
+ throw new Error(
97
+ "Direct dispatch not supported on Solana spoke chains. Actions must be dispatched from the Hub (EVM) chain. This client is for receiving cross-chain messages only."
98
+ );
99
+ }
100
+ /**
101
+ * Dispatch an action via relayer (gasless)
102
+ * Note: On Solana, this still goes through the Hub chain
103
+ * Solana is a spoke-only chain in Veridex architecture
104
+ */
105
+ async dispatchGasless(signature, publicKeyX, publicKeyY, targetChain, actionPayload, nonce, relayerUrl) {
106
+ const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);
107
+ const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);
108
+ const request = {
109
+ messageHash: message,
110
+ r: "0x" + signature.r.toString(16).padStart(64, "0"),
111
+ s: "0x" + signature.s.toString(16).padStart(64, "0"),
112
+ publicKeyX: "0x" + publicKeyX.toString(16).padStart(64, "0"),
113
+ publicKeyY: "0x" + publicKeyY.toString(16).padStart(64, "0"),
114
+ targetChain,
115
+ actionPayload,
116
+ nonce: Number(nonce)
117
+ };
118
+ const response = await fetch(`${relayerUrl}/api/v1/submit`, {
119
+ method: "POST",
120
+ headers: {
121
+ "Content-Type": "application/json"
122
+ },
123
+ body: JSON.stringify(request)
124
+ });
125
+ if (!response.ok) {
126
+ const error = await response.json().catch(() => ({ error: response.statusText }));
127
+ throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);
128
+ }
129
+ const result = await response.json();
130
+ if (!result.success) {
131
+ throw new Error(`Relayer submission failed: ${result.error}`);
132
+ }
133
+ return {
134
+ transactionHash: result.txHash,
135
+ sequence: BigInt(result.sequence || "0"),
136
+ userKeyHash: keyHash,
137
+ targetChain
138
+ };
139
+ }
140
+ async getVaultAddress(userKeyHash) {
141
+ try {
142
+ const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);
143
+ const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));
144
+ if (!accountInfo) {
145
+ return null;
146
+ }
147
+ return vaultAddress;
148
+ } catch (error) {
149
+ console.error("Error getting vault address:", error);
150
+ return null;
151
+ }
152
+ }
153
+ /**
154
+ * Compute vault address using PDA (Program Derived Address)
155
+ * Seeds: ["vault", userKeyHash]
156
+ */
157
+ computeVaultAddress(userKeyHash) {
158
+ return this.computeVaultAddressFromHash(userKeyHash);
159
+ }
160
+ computeVaultAddressFromHash(userKeyHash) {
161
+ const userKeyHashBuffer = Buffer.from(userKeyHash.replace("0x", ""), "hex");
162
+ const [vaultPda] = PublicKey.findProgramAddressSync(
163
+ [Buffer.from("vault"), userKeyHashBuffer],
164
+ this.programId
165
+ );
166
+ return vaultPda.toBase58();
167
+ }
168
+ async vaultExists(userKeyHash) {
169
+ const address = await this.getVaultAddress(userKeyHash);
170
+ return address !== null;
171
+ }
172
+ async createVault(userKeyHash, signer) {
173
+ void userKeyHash;
174
+ void signer;
175
+ throw new Error(
176
+ "Vault creation on Solana must be done via relayer. Use createVaultViaRelayer() instead."
177
+ );
178
+ }
179
+ async createVaultSponsored(userKeyHash, sponsorPrivateKey, rpcUrl) {
180
+ void userKeyHash;
181
+ void sponsorPrivateKey;
182
+ void rpcUrl;
183
+ throw new Error(
184
+ "Vault creation on Solana must be done via relayer. Use createVaultViaRelayer() instead."
185
+ );
186
+ }
187
+ /**
188
+ * Create a vault via the relayer (sponsored/gasless)
189
+ * This is the recommended way to create Solana vaults
190
+ */
191
+ async createVaultViaRelayer(userKeyHash, relayerUrl) {
192
+ const response = await fetch(`${relayerUrl}/api/v1/solana/vault`, {
193
+ method: "POST",
194
+ headers: {
195
+ "Content-Type": "application/json"
196
+ },
197
+ body: JSON.stringify({
198
+ userKeyHash,
199
+ chainId: this.config.wormholeChainId
200
+ })
201
+ });
202
+ const result = await response.json();
203
+ if (!response.ok || !result.success) {
204
+ throw new Error(result.error || "Failed to create vault via relayer");
205
+ }
206
+ return {
207
+ address: result.vaultAddress,
208
+ transactionHash: result.transactionHash || "",
209
+ blockNumber: 0,
210
+ // Solana doesn't have block numbers like EVM
211
+ gasUsed: 0n,
212
+ // Solana uses compute units, not gas
213
+ alreadyExisted: !result.transactionHash,
214
+ sponsoredBy: "relayer"
215
+ };
216
+ }
217
+ /**
218
+ * Get vault info via relayer (includes existence check)
219
+ */
220
+ async getVaultViaRelayer(userKeyHash, relayerUrl) {
221
+ const response = await fetch(
222
+ `${relayerUrl}/api/v1/solana/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`
223
+ );
224
+ if (!response.ok) {
225
+ throw new Error("Failed to get vault info from relayer");
226
+ }
227
+ const result = await response.json();
228
+ return {
229
+ vaultAddress: result.vaultAddress,
230
+ exists: result.exists
231
+ };
232
+ }
233
+ async estimateVaultCreationGas(userKeyHash) {
234
+ void userKeyHash;
235
+ return 2000000n;
236
+ }
237
+ getFactoryAddress() {
238
+ return void 0;
239
+ }
240
+ getImplementationAddress() {
241
+ return void 0;
242
+ }
243
+ // ========================================================================
244
+ // Balance Methods
245
+ // ========================================================================
246
+ /**
247
+ * Get native SOL balance
248
+ */
249
+ async getNativeBalance(address) {
250
+ const balance = await this.connection.getBalance(new PublicKey(address));
251
+ return BigInt(balance);
252
+ }
253
+ /**
254
+ * Get SPL token balance
255
+ */
256
+ async getTokenBalance(tokenAddress, ownerAddress) {
257
+ try {
258
+ const mint = new PublicKey(tokenAddress);
259
+ const owner = new PublicKey(ownerAddress);
260
+ const ata = getAssociatedTokenAddressSync(mint, owner);
261
+ const balance = await this.connection.getTokenAccountBalance(ata);
262
+ return BigInt(balance.value.amount);
263
+ } catch (error) {
264
+ console.error("Error getting token balance:", error);
265
+ return 0n;
266
+ }
267
+ }
268
+ // ========================================================================
269
+ // Utility Methods
270
+ // ========================================================================
271
+ /**
272
+ * Compute key hash from public key coordinates
273
+ * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))
274
+ */
275
+ computeKeyHash(publicKeyX, publicKeyY) {
276
+ const xBuffer = Buffer.alloc(32);
277
+ const yBuffer = Buffer.alloc(32);
278
+ const xHex = publicKeyX.toString(16).padStart(64, "0");
279
+ const yHex = publicKeyY.toString(16).padStart(64, "0");
280
+ Buffer.from(xHex, "hex").copy(xBuffer);
281
+ Buffer.from(yHex, "hex").copy(yBuffer);
282
+ const combined = Buffer.concat([xBuffer, yBuffer]);
283
+ const hash = createHash("sha256").update(combined).digest();
284
+ return "0x" + hash.toString("hex");
285
+ }
286
+ /**
287
+ * Build message for signing (matches Hub chain format)
288
+ */
289
+ buildMessage(keyHash, targetChain, actionPayload, nonce) {
290
+ const keyHashBuffer = Buffer.from(keyHash.replace("0x", ""), "hex");
291
+ const targetChainBuffer = Buffer.alloc(2);
292
+ targetChainBuffer.writeUInt16BE(targetChain);
293
+ const payloadBuffer = Buffer.from(actionPayload.replace("0x", ""), "hex");
294
+ const nonceBuffer = Buffer.alloc(32);
295
+ const nonceHex = nonce.toString(16).padStart(64, "0");
296
+ Buffer.from(nonceHex, "hex").copy(nonceBuffer);
297
+ const combined = Buffer.concat([
298
+ keyHashBuffer,
299
+ targetChainBuffer,
300
+ payloadBuffer,
301
+ nonceBuffer
302
+ ]);
303
+ const hash = createHash("sha256").update(combined).digest();
304
+ return "0x" + hash.toString("hex");
305
+ }
306
+ /**
307
+ * Get connection instance for advanced usage
308
+ */
309
+ getConnection() {
310
+ return this.connection;
311
+ }
312
+ /**
313
+ * Get program ID
314
+ */
315
+ getProgramId() {
316
+ return this.programId;
317
+ }
318
+ /**
319
+ * Get current slot
320
+ */
321
+ async getSlot() {
322
+ return await this.connection.getSlot();
323
+ }
324
+ /**
325
+ * Get transaction status
326
+ */
327
+ async getTransaction(signature, commitment) {
328
+ return await this.connection.getTransaction(signature, {
329
+ commitment: commitment || "confirmed",
330
+ maxSupportedTransactionVersion: 0
331
+ });
332
+ }
333
+ // ============================================================================
334
+ // Social Recovery Methods (Issue #23)
335
+ // ============================================================================
336
+ //
337
+ // Note: Social recovery is managed on the Hub chain (EVM).
338
+ // Solana spokes receive and execute recovery VAAs broadcast from the Hub.
339
+ // These methods are placeholders that indicate spoke-only chains don't
340
+ // initiate recovery - they only execute recovery instructions from Hub VAAs.
341
+ //
342
+ // The relayer service handles:
343
+ // 1. Fetching recovery VAAs from Wormhole guardians
344
+ // 2. Submitting execute_recovery instruction to Solana spoke
345
+ // 3. Processing OwnerRecovered events
346
+ //
347
+ // SDK users should use EVMClient methods for guardian management and
348
+ // recovery initiation on the Hub chain.
349
+ // ============================================================================
350
+ /**
351
+ * Check if a recovery VAA has been executed on this spoke
352
+ *
353
+ * @param vaaHash - Hash of the recovery VAA
354
+ * @returns Whether the VAA has been processed
355
+ */
356
+ async isRecoveryExecuted(vaaHash) {
357
+ try {
358
+ const vaaHashBuffer = Buffer.from(vaaHash.replace("0x", ""), "hex");
359
+ const [vaaRecordPda] = PublicKey.findProgramAddressSync(
360
+ [Buffer.from("vaa_record"), vaaHashBuffer],
361
+ this.programId
362
+ );
363
+ const accountInfo = await this.connection.getAccountInfo(vaaRecordPda);
364
+ if (!accountInfo || accountInfo.data.length < 9) {
365
+ return false;
366
+ }
367
+ return accountInfo.data[8] === 1;
368
+ } catch (error) {
369
+ console.error("Error checking recovery execution:", error);
370
+ return false;
371
+ }
372
+ }
373
+ /**
374
+ * Get vault owner after potential recovery
375
+ *
376
+ * @param vaultAddress - Vault address to check
377
+ * @returns Current owner key hash
378
+ */
379
+ async getVaultOwner(vaultAddress) {
380
+ try {
381
+ const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));
382
+ if (!accountInfo || accountInfo.data.length < 40) {
383
+ throw new Error("Vault not found");
384
+ }
385
+ const ownerKeyHash = accountInfo.data.slice(8, 40);
386
+ return "0x" + ownerKeyHash.toString("hex");
387
+ } catch (error) {
388
+ console.error("Error getting vault owner:", error);
389
+ throw error;
390
+ }
391
+ }
392
+ /**
393
+ * Get authorized signers for a vault
394
+ *
395
+ * @param vaultAddress - Vault address to check
396
+ * @returns Array of authorized signer key hashes
397
+ */
398
+ async getAuthorizedSigners(vaultAddress) {
399
+ try {
400
+ const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));
401
+ if (!accountInfo || accountInfo.data.length < 235) {
402
+ throw new Error("Vault not found");
403
+ }
404
+ const signerCount = accountInfo.data[66];
405
+ const signers = [];
406
+ for (let i = 0; i < signerCount; i++) {
407
+ const offset = 67 + i * 32;
408
+ const keyHash = accountInfo.data.slice(offset, offset + 32);
409
+ signers.push("0x" + keyHash.toString("hex"));
410
+ }
411
+ return signers;
412
+ } catch (error) {
413
+ console.error("Error getting authorized signers:", error);
414
+ throw error;
415
+ }
416
+ }
417
+ };
418
+
419
+ export {
420
+ SolanaClient
421
+ };
422
+ //# sourceMappingURL=chunk-Q5O3M5LP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chains/solana/SolanaClient.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Solana Chain Client\n * \n * Implementation of ChainClient interface for Solana blockchain\n */\n\nimport {\n Connection,\n PublicKey,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddressSync,\n} from '@solana/spl-token';\nimport { createHash } from 'crypto';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SolanaClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n programId: string; // Veridex Spoke program\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'devnet' | 'testnet';\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// SolanaClient Class\n// ============================================================================\n\n/**\n * Solana implementation of the ChainClient interface\n */\nexport class SolanaClient implements ChainClient {\n private config: ChainConfig;\n private connection: Connection;\n private programId: PublicKey;\n\n constructor(config: SolanaClientConfig) {\n this.config = {\n name: `Solana ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'devnet'\n ? 'https://explorer.solana.com?cluster=devnet'\n : 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Solana is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.connection = new Connection(\n config.rpcUrl,\n config.commitment || 'confirmed'\n );\n this.programId = new PublicKey(config.programId);\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo || accountInfo.data.length < 40) {\n return 0n;\n }\n\n // Nonce is stored at offset 8 (after discriminator)\n // Read as u64 little-endian\n const nonce = accountInfo.data.readBigUInt64LE(8);\n return nonce;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config account\n return 0n; // Solana doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Solana Keypair or similar\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Solana spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Solana, this still goes through the Hub chain\n * Solana is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo) {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address using PDA (Program Derived Address)\n * Seeds: [\"vault\", userKeyHash]\n */\n computeVaultAddress(userKeyHash: string): string {\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n const userKeyHashBuffer = Buffer.from(userKeyHash.replace('0x', ''), 'hex');\n const [vaultPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vault'), userKeyHashBuffer],\n this.programId\n );\n return vaultPda.toBase58();\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Solana vaults\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/solana/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0, // Solana doesn't have block numbers like EVM\n gasUsed: 0n, // Solana uses compute units, not gas\n alreadyExisted: !result.transactionHash,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/solana/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return SOL estimate for vault creation (rent + compute)\n // ~0.002 SOL for rent-exempt account + compute units\n return 2_000_000n; // 0.002 SOL in lamports\n }\n\n getFactoryAddress(): string | undefined {\n // Solana uses program addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Solana uses program addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native SOL balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.connection.getBalance(new PublicKey(address));\n return BigInt(balance);\n }\n\n /**\n * Get SPL token balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n const mint = new PublicKey(tokenAddress);\n const owner = new PublicKey(ownerAddress);\n const ata = getAssociatedTokenAddressSync(mint, owner);\n\n const balance = await this.connection.getTokenAccountBalance(ata);\n return BigInt(balance.value.amount);\n } catch (error) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Use SHA-256 for Solana (Solana doesn't have keccak256 built-in)\n // The relayer will convert this to match EVM format\n const xBuffer = Buffer.alloc(32);\n const yBuffer = Buffer.alloc(32);\n\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n Buffer.from(xHex, 'hex').copy(xBuffer);\n Buffer.from(yHex, 'hex').copy(yBuffer);\n\n // For cross-chain compatibility, we need to match the EVM hash\n // This should be keccak256, but we'll return a format the relayer expects\n const combined = Buffer.concat([xBuffer, yBuffer]);\n const hash = createHash('sha256').update(combined).digest();\n\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n // This should match the EVM message format for cross-chain compatibility\n const keyHashBuffer = Buffer.from(keyHash.replace('0x', ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace('0x', ''), 'hex');\n const nonceBuffer = Buffer.alloc(32);\n const nonceHex = nonce.toString(16).padStart(64, '0');\n Buffer.from(nonceHex, 'hex').copy(nonceBuffer);\n\n const combined = Buffer.concat([\n keyHashBuffer,\n targetChainBuffer,\n payloadBuffer,\n nonceBuffer,\n ]);\n\n const hash = createHash('sha256').update(combined).digest();\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Get connection instance for advanced usage\n */\n getConnection(): Connection {\n return this.connection;\n }\n\n /**\n * Get program ID\n */\n getProgramId(): PublicKey {\n return this.programId;\n }\n\n /**\n * Get current slot\n */\n async getSlot(): Promise<number> {\n return await this.connection.getSlot();\n }\n\n /**\n * Get transaction status\n */\n async getTransaction(signature: string, commitment?: 'confirmed' | 'finalized') {\n return await this.connection.getTransaction(signature, {\n commitment: commitment || 'confirmed',\n maxSupportedTransactionVersion: 0,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Solana spokes receive and execute recovery VAAs broadcast from the Hub.\n // These methods are placeholders that indicate spoke-only chains don't\n // initiate recovery - they only execute recovery instructions from Hub VAAs.\n //\n // The relayer service handles:\n // 1. Fetching recovery VAAs from Wormhole guardians\n // 2. Submitting execute_recovery instruction to Solana spoke\n // 3. Processing OwnerRecovered events\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Check if a recovery VAA has been executed on this spoke\n * \n * @param vaaHash - Hash of the recovery VAA\n * @returns Whether the VAA has been processed\n */\n async isRecoveryExecuted(vaaHash: string): Promise<boolean> {\n try {\n // Derive VAA record PDA\n const vaaHashBuffer = Buffer.from(vaaHash.replace('0x', ''), 'hex');\n const [vaaRecordPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vaa_record'), vaaHashBuffer],\n this.programId\n );\n\n const accountInfo = await this.connection.getAccountInfo(vaaRecordPda);\n if (!accountInfo || accountInfo.data.length < 9) {\n return false;\n }\n\n // First byte after discriminator is 'processed' bool\n return accountInfo.data[8] === 1;\n } catch (error) {\n console.error('Error checking recovery execution:', error);\n return false;\n }\n }\n\n /**\n * Get vault owner after potential recovery\n * \n * @param vaultAddress - Vault address to check\n * @returns Current owner key hash\n */\n async getVaultOwner(vaultAddress: string): Promise<string> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 40) {\n throw new Error('Vault not found');\n }\n\n // Owner key hash is stored after discriminator (8 bytes) at offset 8-40\n const ownerKeyHash = accountInfo.data.slice(8, 40);\n return '0x' + ownerKeyHash.toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n throw error;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultAddress - Vault address to check\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultAddress: string): Promise<string[]> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 235) {\n throw new Error('Vault not found');\n }\n\n // Vault layout:\n // 8 bytes discriminator\n // 32 bytes owner_key_hash\n // 8 bytes nonce\n // 1 byte paused\n // 8 bytes daily_limit\n // 8 bytes daily_spent\n // 8 bytes day_start\n // 1 byte bump\n // 1 byte authorized_signer_count\n // 5 * 32 bytes authorized_signers\n\n const signerCount = accountInfo.data[66]; // offset 8+32+8+1+8+8+1 = 66\n const signers: string[] = [];\n\n for (let i = 0; i < signerCount; i++) {\n const offset = 67 + (i * 32); // Start of authorized_signers array\n const keyHash = accountInfo.data.slice(offset, offset + 32);\n signers.push('0x' + keyHash.toString('hex'));\n }\n\n return signers;\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n throw error;\n }\n }\n}\n"],"mappings":";;;;;;;AAMA;AAAA,EACI;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,OACG;AACP,SAAS,kBAAkB;AAsCpB,IAAM,eAAN,MAA0C;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA4B;AACpC,SAAK,SAAS;AAAA,MACV,MAAM,UAAU,OAAO,WAAW,SAAS;AAAA,MAC3C,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,WAC1B,+CACA;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK;AAAA;AAAA,QACL,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,aAAa,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,cAAc;AAAA,IACzB;AACA,SAAK,YAAY,IAAI,UAAU,OAAO,SAAS;AAAA,EACnD;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,aAAsC;AACjD,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,WAAW;AACjE,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AAEpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,IAAI;AAC9C,eAAO;AAAA,MACX;AAIA,YAAM,QAAQ,YAAY,KAAK,gBAAgB,CAAC;AAChD,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAiC;AACnC,QAAI;AAIA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AAEvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAG1D,UAAM,UAAU,KAAK,aAAa,SAAS,aAAa,eAAe,KAAK;AAG5E,UAAM,UAAU;AAAA,MACZ,aAAa;AAAA,MACb,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAGA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,SAAS,WAAW,EAAE;AAChF,YAAM,IAAI,MAAM,8BAA8B,MAAM,SAAS,SAAS,UAAU,EAAE;AAAA,IACtF;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,MACH,iBAAiB,OAAO;AAAA,MACxB,UAAU,OAAO,OAAO,YAAY,GAAG;AAAA,MACvC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAgB,aAA6C;AAC/D,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,WAAW;AACjE,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AAEpF,UAAI,CAAC,aAAa;AACd,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,aAA6B;AAC7C,WAAO,KAAK,4BAA4B,WAAW;AAAA,EACvD;AAAA,EAEQ,4BAA4B,aAA6B;AAC7D,UAAM,oBAAoB,OAAO,KAAK,YAAY,QAAQ,MAAM,EAAE,GAAG,KAAK;AAC1E,UAAM,CAAC,QAAQ,IAAI,UAAU;AAAA,MACzB,CAAC,OAAO,KAAK,OAAO,GAAG,iBAAiB;AAAA,MACxC,KAAK;AAAA,IACT;AACA,WAAO,SAAS,SAAS;AAAA,EAC7B;AAAA,EAEA,MAAM,YAAY,aAAuC;AACrD,UAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW;AACtD,WAAO,YAAY;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA,EAEA,MAAM,qBACF,aACA,mBACA,QAC4B;AAC5B,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,wBAAwB;AAAA,MAC9D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA;AAAA,MACb,SAAS;AAAA;AAAA,MACT,gBAAgB,CAAC,OAAO;AAAA,MACxB,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,wBAAwB,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IAC3F;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,aAAsC;AACjE,SAAK;AAGL,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AAEpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAE3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,SAAkC;AACrD,UAAM,UAAU,MAAM,KAAK,WAAW,WAAW,IAAI,UAAU,OAAO,CAAC;AACvE,WAAO,OAAO,OAAO;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,cAAsB,cAAuC;AAC/E,QAAI;AACA,YAAM,OAAO,IAAI,UAAU,YAAY;AACvC,YAAM,QAAQ,IAAI,UAAU,YAAY;AACxC,YAAM,MAAM,8BAA8B,MAAM,KAAK;AAErD,YAAM,UAAU,MAAM,KAAK,WAAW,uBAAuB,GAAG;AAChE,aAAO,OAAO,QAAQ,MAAM,MAAM;AAAA,IACtC,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,eAAe,YAAoB,YAA4B;AAGnE,UAAM,UAAU,OAAO,MAAM,EAAE;AAC/B,UAAM,UAAU,OAAO,MAAM,EAAE;AAG/B,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAErD,WAAO,KAAK,MAAM,KAAK,EAAE,KAAK,OAAO;AACrC,WAAO,KAAK,MAAM,KAAK,EAAE,KAAK,OAAO;AAIrC,UAAM,WAAW,OAAO,OAAO,CAAC,SAAS,OAAO,CAAC;AACjD,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO;AAE1D,WAAO,OAAO,KAAK,SAAS,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKQ,aACJ,SACA,aACA,eACA,OACM;AAEN,UAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG,KAAK;AAClE,UAAM,oBAAoB,OAAO,MAAM,CAAC;AACxC,sBAAkB,cAAc,WAAW;AAC3C,UAAM,gBAAgB,OAAO,KAAK,cAAc,QAAQ,MAAM,EAAE,GAAG,KAAK;AACxE,UAAM,cAAc,OAAO,MAAM,EAAE;AACnC,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,WAAO,KAAK,UAAU,KAAK,EAAE,KAAK,WAAW;AAE7C,UAAM,WAAW,OAAO,OAAO;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ,CAAC;AAED,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO;AAC1D,WAAO,OAAO,KAAK,SAAS,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,gBAA4B;AACxB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,eAA0B;AACtB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA2B;AAC7B,WAAO,MAAM,KAAK,WAAW,QAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAmB,YAAwC;AAC5E,WAAO,MAAM,KAAK,WAAW,eAAe,WAAW;AAAA,MACnD,YAAY,cAAc;AAAA,MAC1B,gCAAgC;AAAA,IACpC,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,MAAM,mBAAmB,SAAmC;AACxD,QAAI;AAEA,YAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG,KAAK;AAClE,YAAM,CAAC,YAAY,IAAI,UAAU;AAAA,QAC7B,CAAC,OAAO,KAAK,YAAY,GAAG,aAAa;AAAA,QACzC,KAAK;AAAA,MACT;AAEA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,YAAY;AACrE,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,GAAG;AAC7C,eAAO;AAAA,MACX;AAGA,aAAO,YAAY,KAAK,CAAC,MAAM;AAAA,IACnC,SAAS,OAAO;AACZ,cAAQ,MAAM,sCAAsC,KAAK;AACzD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,cAAuC;AACvD,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AACpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,IAAI;AAC9C,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACrC;AAGA,YAAM,eAAe,YAAY,KAAK,MAAM,GAAG,EAAE;AACjD,aAAO,OAAO,aAAa,SAAS,KAAK;AAAA,IAC7C,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,cAAyC;AAChE,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AACpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,KAAK;AAC/C,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACrC;AAcA,YAAM,cAAc,YAAY,KAAK,EAAE;AACvC,YAAM,UAAoB,CAAC;AAE3B,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,cAAM,SAAS,KAAM,IAAI;AACzB,cAAM,UAAU,YAAY,KAAK,MAAM,QAAQ,SAAS,EAAE;AAC1D,gBAAQ,KAAK,OAAO,QAAQ,SAAS,KAAK,CAAC;AAAA,MAC/C;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,qCAAqC,KAAK;AACxD,YAAM;AAAA,IACV;AAAA,EACJ;AACJ;","names":[]}