@veridex/sdk 1.0.0-beta.1

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 (82) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/LICENSE +21 -0
  3. package/README.md +212 -0
  4. package/dist/chains/aptos/index.d.mts +140 -0
  5. package/dist/chains/aptos/index.d.ts +140 -0
  6. package/dist/chains/aptos/index.js +563 -0
  7. package/dist/chains/aptos/index.js.map +1 -0
  8. package/dist/chains/aptos/index.mjs +536 -0
  9. package/dist/chains/aptos/index.mjs.map +1 -0
  10. package/dist/chains/evm/index.d.mts +5 -0
  11. package/dist/chains/evm/index.d.ts +5 -0
  12. package/dist/chains/evm/index.js +1233 -0
  13. package/dist/chains/evm/index.js.map +1 -0
  14. package/dist/chains/evm/index.mjs +1205 -0
  15. package/dist/chains/evm/index.mjs.map +1 -0
  16. package/dist/chains/solana/index.d.mts +116 -0
  17. package/dist/chains/solana/index.d.ts +116 -0
  18. package/dist/chains/solana/index.js +513 -0
  19. package/dist/chains/solana/index.js.map +1 -0
  20. package/dist/chains/solana/index.mjs +491 -0
  21. package/dist/chains/solana/index.mjs.map +1 -0
  22. package/dist/chains/starknet/index.d.mts +172 -0
  23. package/dist/chains/starknet/index.d.ts +172 -0
  24. package/dist/chains/starknet/index.js +534 -0
  25. package/dist/chains/starknet/index.js.map +1 -0
  26. package/dist/chains/starknet/index.mjs +507 -0
  27. package/dist/chains/starknet/index.mjs.map +1 -0
  28. package/dist/chains/sui/index.d.mts +182 -0
  29. package/dist/chains/sui/index.d.ts +182 -0
  30. package/dist/chains/sui/index.js +560 -0
  31. package/dist/chains/sui/index.js.map +1 -0
  32. package/dist/chains/sui/index.mjs +533 -0
  33. package/dist/chains/sui/index.mjs.map +1 -0
  34. package/dist/constants.d.mts +150 -0
  35. package/dist/constants.d.ts +150 -0
  36. package/dist/constants.js +430 -0
  37. package/dist/constants.js.map +1 -0
  38. package/dist/constants.mjs +392 -0
  39. package/dist/constants.mjs.map +1 -0
  40. package/dist/index-0NXfbk0z.d.ts +637 -0
  41. package/dist/index-D0dLVjTA.d.mts +637 -0
  42. package/dist/index.d.mts +3101 -0
  43. package/dist/index.d.ts +3101 -0
  44. package/dist/index.js +13186 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/index.mjs +13011 -0
  47. package/dist/index.mjs.map +1 -0
  48. package/dist/payload.d.mts +125 -0
  49. package/dist/payload.d.ts +125 -0
  50. package/dist/payload.js +315 -0
  51. package/dist/payload.js.map +1 -0
  52. package/dist/payload.mjs +269 -0
  53. package/dist/payload.mjs.map +1 -0
  54. package/dist/queries/index.d.mts +148 -0
  55. package/dist/queries/index.d.ts +148 -0
  56. package/dist/queries/index.js +1533 -0
  57. package/dist/queries/index.js.map +1 -0
  58. package/dist/queries/index.mjs +1508 -0
  59. package/dist/queries/index.mjs.map +1 -0
  60. package/dist/types-ChIsqCiw.d.mts +565 -0
  61. package/dist/types-ChIsqCiw.d.ts +565 -0
  62. package/dist/types-FJL7j6gQ.d.mts +172 -0
  63. package/dist/types-FJL7j6gQ.d.ts +172 -0
  64. package/dist/types.d.mts +407 -0
  65. package/dist/types.d.ts +407 -0
  66. package/dist/types.js +19 -0
  67. package/dist/types.js.map +1 -0
  68. package/dist/types.mjs +1 -0
  69. package/dist/types.mjs.map +1 -0
  70. package/dist/utils.d.mts +81 -0
  71. package/dist/utils.d.ts +81 -0
  72. package/dist/utils.js +430 -0
  73. package/dist/utils.js.map +1 -0
  74. package/dist/utils.mjs +390 -0
  75. package/dist/utils.mjs.map +1 -0
  76. package/dist/wormhole.d.mts +167 -0
  77. package/dist/wormhole.d.ts +167 -0
  78. package/dist/wormhole.js +468 -0
  79. package/dist/wormhole.js.map +1 -0
  80. package/dist/wormhole.mjs +422 -0
  81. package/dist/wormhole.mjs.map +1 -0
  82. package/package.json +151 -0
@@ -0,0 +1,533 @@
1
+ // src/chains/sui/SuiClient.ts
2
+ import { SuiClient as MystenSuiClient } from "@mysten/sui/client";
3
+ import { createHash } from "crypto";
4
+
5
+ // src/payload.ts
6
+ import { ethers } from "ethers";
7
+
8
+ // src/constants.ts
9
+ var ACTION_TRANSFER = 1;
10
+ var ACTION_EXECUTE = 2;
11
+ var ACTION_BRIDGE = 4;
12
+
13
+ // src/payload.ts
14
+ function encodeTransferAction(token, recipient, amount) {
15
+ const tokenPadded = padTo32Bytes(token);
16
+ const recipientPadded = padTo32Bytes(recipient);
17
+ const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);
18
+ return ethers.concat([
19
+ ethers.toBeHex(ACTION_TRANSFER, 1),
20
+ tokenPadded,
21
+ recipientPadded,
22
+ amountBytes
23
+ ]);
24
+ }
25
+ function encodeBridgeAction(token, amount, targetChain, recipient) {
26
+ const tokenPadded = padTo32Bytes(token);
27
+ const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);
28
+ const targetChainBytes = ethers.toBeHex(targetChain, 2);
29
+ const recipientPadded = padTo32Bytes(recipient);
30
+ return ethers.concat([
31
+ ethers.toBeHex(ACTION_BRIDGE, 1),
32
+ tokenPadded,
33
+ amountBytes,
34
+ targetChainBytes,
35
+ recipientPadded
36
+ ]);
37
+ }
38
+ function encodeExecuteAction(target, value, data) {
39
+ const targetPadded = padTo32Bytes(target);
40
+ const valueBytes = ethers.zeroPadValue(ethers.toBeHex(value), 32);
41
+ const dataBytes = ethers.getBytes(data);
42
+ const dataLengthBytes = ethers.toBeHex(dataBytes.length, 2);
43
+ return ethers.concat([
44
+ ethers.toBeHex(ACTION_EXECUTE, 1),
45
+ targetPadded,
46
+ valueBytes,
47
+ dataLengthBytes,
48
+ data
49
+ ]);
50
+ }
51
+ function padTo32Bytes(address) {
52
+ if (address.toLowerCase() === "native") {
53
+ return "0x" + "0".repeat(64);
54
+ }
55
+ if (address.startsWith("0x")) {
56
+ const hex2 = address.replace("0x", "");
57
+ if (!/^[0-9a-fA-F]*$/.test(hex2)) {
58
+ throw new Error(`Invalid address: ${address}. Expected hex string or 'native'.`);
59
+ }
60
+ return "0x" + hex2.padStart(64, "0");
61
+ }
62
+ const base58Chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
63
+ for (const char of address) {
64
+ if (!base58Chars.includes(char)) {
65
+ throw new Error(`Invalid address: ${address}. Contains invalid base58 character '${char}'.`);
66
+ }
67
+ }
68
+ let value = BigInt(0);
69
+ for (const char of address) {
70
+ value = value * 58n + BigInt(base58Chars.indexOf(char));
71
+ }
72
+ let hex = value.toString(16);
73
+ if (hex.length > 64) {
74
+ throw new Error(`Invalid address: ${address}. Decoded value too large for 32 bytes.`);
75
+ }
76
+ return "0x" + hex.padStart(64, "0");
77
+ }
78
+
79
+ // src/chains/sui/SuiClient.ts
80
+ var SuiClient = class {
81
+ config;
82
+ client;
83
+ packageId;
84
+ hubRpcUrl;
85
+ hubContractAddress;
86
+ constructor(config) {
87
+ this.config = {
88
+ name: `Sui ${config.network || "mainnet"}`,
89
+ chainId: 0,
90
+ wormholeChainId: config.wormholeChainId,
91
+ rpcUrl: config.rpcUrl,
92
+ explorerUrl: config.network === "testnet" ? "https://suiscan.xyz/testnet" : config.network === "devnet" ? "https://suiscan.xyz/devnet" : "https://suiscan.xyz/mainnet",
93
+ isEvm: false,
94
+ contracts: {
95
+ hub: config.packageId,
96
+ wormholeCoreBridge: config.wormholeCoreBridge,
97
+ tokenBridge: config.tokenBridge
98
+ }
99
+ };
100
+ this.client = new MystenSuiClient({ url: config.rpcUrl });
101
+ this.packageId = config.packageId;
102
+ this.hubRpcUrl = config.hubRpcUrl;
103
+ this.hubContractAddress = config.hubContractAddress;
104
+ }
105
+ getConfig() {
106
+ return this.config;
107
+ }
108
+ async getNonce(_userKeyHash) {
109
+ return 0n;
110
+ }
111
+ async getMessageFee() {
112
+ return 0n;
113
+ }
114
+ async buildTransferPayload(params) {
115
+ return encodeTransferAction(params.token, params.recipient, params.amount);
116
+ }
117
+ async buildExecutePayload(params) {
118
+ return encodeExecuteAction(params.target, params.value, params.data);
119
+ }
120
+ async buildBridgePayload(params) {
121
+ return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);
122
+ }
123
+ async dispatch(signature, publicKeyX, publicKeyY, targetChain, actionPayload, nonce, signer) {
124
+ void signature;
125
+ void publicKeyX;
126
+ void publicKeyY;
127
+ void targetChain;
128
+ void actionPayload;
129
+ void nonce;
130
+ void signer;
131
+ throw new Error(
132
+ "Direct dispatch not supported on Sui spoke chains. Actions must be dispatched from the Hub (EVM) chain. "
133
+ );
134
+ }
135
+ async dispatchGasless(signature, publicKeyX, publicKeyY, targetChain, actionPayload, nonce, relayerUrl) {
136
+ const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);
137
+ const messageHash = this.buildMessageHash(keyHash, targetChain, actionPayload, nonce);
138
+ const request = {
139
+ messageHash,
140
+ r: "0x" + signature.r.toString(16).padStart(64, "0"),
141
+ s: "0x" + signature.s.toString(16).padStart(64, "0"),
142
+ publicKeyX: "0x" + publicKeyX.toString(16).padStart(64, "0"),
143
+ publicKeyY: "0x" + publicKeyY.toString(16).padStart(64, "0"),
144
+ targetChain,
145
+ actionPayload,
146
+ nonce: Number(nonce)
147
+ };
148
+ const response = await fetch(`${relayerUrl}/api/v1/submit`, {
149
+ method: "POST",
150
+ headers: { "Content-Type": "application/json" },
151
+ body: JSON.stringify(request)
152
+ });
153
+ if (!response.ok) {
154
+ throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);
155
+ }
156
+ const result = await response.json();
157
+ return {
158
+ transactionHash: result.transactionHash ?? result.txHash,
159
+ sequence: BigInt(result.sequence || 0),
160
+ userKeyHash: keyHash,
161
+ targetChain
162
+ };
163
+ }
164
+ async getVaultAddress(userKeyHash) {
165
+ return this.computeVaultAddress(userKeyHash);
166
+ }
167
+ computeVaultAddress(userKeyHash) {
168
+ const clean = userKeyHash.replace(/^0x/, "").padStart(64, "0");
169
+ return "0x" + clean;
170
+ }
171
+ async vaultExists(_userKeyHash) {
172
+ return true;
173
+ }
174
+ async createVault(userKeyHash, signer) {
175
+ void signer;
176
+ throw new Error(
177
+ `Vault creation on Sui must be done via cross-chain message from Hub. Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`
178
+ );
179
+ }
180
+ async createVaultSponsored(userKeyHash, sponsorPrivateKey, rpcUrl) {
181
+ void userKeyHash;
182
+ void sponsorPrivateKey;
183
+ void rpcUrl;
184
+ throw new Error(
185
+ "Vault creation on Sui must be done via cross-chain message from Hub. Use relayer gasless submission to create vault."
186
+ );
187
+ }
188
+ /**
189
+ * Create a vault via the relayer (sponsored/gasless)
190
+ * This is the recommended way to create Sui vaults
191
+ *
192
+ * The relayer will dispatch a vault creation action from Hub to Sui spoke
193
+ */
194
+ async createVaultViaRelayer(userKeyHash, relayerUrl) {
195
+ const response = await fetch(`${relayerUrl}/api/v1/sui/vault`, {
196
+ method: "POST",
197
+ headers: {
198
+ "Content-Type": "application/json"
199
+ },
200
+ body: JSON.stringify({
201
+ userKeyHash,
202
+ chainId: this.config.wormholeChainId
203
+ })
204
+ });
205
+ const result = await response.json();
206
+ if (!response.ok || !result.success) {
207
+ throw new Error(result.error || "Failed to create vault via relayer");
208
+ }
209
+ return {
210
+ address: result.vaultAddress,
211
+ transactionHash: result.transactionHash || "",
212
+ blockNumber: 0,
213
+ gasUsed: 0n,
214
+ alreadyExisted: result.alreadyExists || false,
215
+ sponsoredBy: "relayer"
216
+ };
217
+ }
218
+ /**
219
+ * Get vault info via relayer (includes existence check)
220
+ */
221
+ async getVaultViaRelayer(userKeyHash, relayerUrl) {
222
+ const response = await fetch(
223
+ `${relayerUrl}/api/v1/sui/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`
224
+ );
225
+ if (!response.ok) {
226
+ throw new Error("Failed to get vault info from relayer");
227
+ }
228
+ const result = await response.json();
229
+ return {
230
+ vaultAddress: result.vaultAddress,
231
+ exists: result.exists
232
+ };
233
+ }
234
+ async estimateVaultCreationGas(_userKeyHash) {
235
+ return 5000n;
236
+ }
237
+ getFactoryAddress() {
238
+ return void 0;
239
+ }
240
+ getImplementationAddress() {
241
+ return void 0;
242
+ }
243
+ // ========================================================================
244
+ // Balance utilities (used by VeridexSDK multichain)
245
+ // ========================================================================
246
+ async getNativeBalance(address) {
247
+ const balance = await this.client.getBalance({ owner: address });
248
+ return BigInt(balance.totalBalance);
249
+ }
250
+ async getTokenBalance(coinType, ownerAddress) {
251
+ const balance = await this.client.getBalance({ owner: ownerAddress, coinType });
252
+ return BigInt(balance.totalBalance);
253
+ }
254
+ getClient() {
255
+ return this.client;
256
+ }
257
+ getPackageId() {
258
+ return this.packageId;
259
+ }
260
+ // ========================================================================
261
+ // Session Management (Issue #13)
262
+ // ========================================================================
263
+ /**
264
+ * Register a session key on the Hub (must be called via Hub client)
265
+ * Sui spokes validate sessions via CCQ, but registration happens on Hub
266
+ *
267
+ * @throws Error - Session management must be done via Hub chain
268
+ */
269
+ async registerSession(_params) {
270
+ throw new Error(
271
+ "Session registration must be performed on the Hub chain (Base). Use EVMClient connected to the Hub to call registerSession()."
272
+ );
273
+ }
274
+ /**
275
+ * Revoke a session key on the Hub (must be called via Hub client)
276
+ *
277
+ * @throws Error - Session management must be done via Hub chain
278
+ */
279
+ async revokeSession(_params) {
280
+ throw new Error(
281
+ "Session revocation must be performed on the Hub chain (Base). Use EVMClient connected to the Hub to call revokeSession()."
282
+ );
283
+ }
284
+ /**
285
+ * Check if a session is active by querying the Hub
286
+ * This method queries the Hub contract directly for session validation
287
+ *
288
+ * @param userKeyHash - Hash of user's Passkey public key
289
+ * @param sessionKeyHash - Hash of session key to validate
290
+ * @returns Session validation result with expiry and limits
291
+ */
292
+ async isSessionActive(_userKeyHash, _sessionKeyHash) {
293
+ if (!this.hubRpcUrl || !this.hubContractAddress) {
294
+ throw new Error(
295
+ "Hub configuration required for session validation. Provide hubRpcUrl and hubContractAddress in SuiClientConfig."
296
+ );
297
+ }
298
+ throw new Error(
299
+ "isSessionActive requires Hub client integration. Use EVMClient.isSessionActive() on the Hub chain, then pass the result to session execution on Sui."
300
+ );
301
+ }
302
+ /**
303
+ * Get all sessions for a user from the Hub
304
+ *
305
+ * @param userKeyHash - Hash of user's Passkey public key
306
+ * @returns Array of all sessions (active and expired/revoked)
307
+ */
308
+ async getUserSessions(userKeyHash) {
309
+ if (!this.hubRpcUrl || !this.hubContractAddress) {
310
+ throw new Error(
311
+ "Hub configuration required for session queries. Provide hubRpcUrl and hubContractAddress in SuiClientConfig."
312
+ );
313
+ }
314
+ throw new Error(
315
+ `getUserSessions requires Hub client integration. Use EVMClient.getUserSessions() on the Hub chain. User: ${userKeyHash}`
316
+ );
317
+ }
318
+ // ========================================================================
319
+ // Query-Based Execution (Issue #9/#10)
320
+ // ========================================================================
321
+ /**
322
+ * Get user state from Hub (comprehensive state query)
323
+ * Returns key hash, nonce, and last action hash for CCQ validation
324
+ *
325
+ * @param userKeyHash - Hash of user's Passkey public key
326
+ * @returns User state with nonce and last action hash
327
+ */
328
+ async getUserState(userKeyHash) {
329
+ if (!this.hubRpcUrl || !this.hubContractAddress) {
330
+ throw new Error(
331
+ "Hub configuration required for state queries. Provide hubRpcUrl and hubContractAddress in SuiClientConfig."
332
+ );
333
+ }
334
+ throw new Error(
335
+ `getUserState requires Hub client integration. Use EVMClient.getUserState() on the Hub chain. User: ${userKeyHash}`
336
+ );
337
+ }
338
+ /**
339
+ * Get user's last action hash from Hub
340
+ * Used for optimistic execution and nonce validation
341
+ *
342
+ * @param userKeyHash - Hash of user's Passkey public key
343
+ * @returns Last action hash (zero hash if no actions)
344
+ */
345
+ async getUserLastActionHash(userKeyHash) {
346
+ if (!this.hubRpcUrl || !this.hubContractAddress) {
347
+ throw new Error(
348
+ "Hub configuration required for action hash queries. Provide hubRpcUrl and hubContractAddress in SuiClientConfig."
349
+ );
350
+ }
351
+ throw new Error(
352
+ `getUserLastActionHash requires Hub client integration. Use EVMClient.getUserLastActionHash() on the Hub chain. User: ${userKeyHash}`
353
+ );
354
+ }
355
+ /**
356
+ * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)
357
+ * Uses Wormhole CCQ to validate Hub state, then executes on Sui
358
+ *
359
+ * @param params Query execution parameters with CCQ response
360
+ * @returns Dispatch result with transaction hash
361
+ *
362
+ * @remarks
363
+ * Query-based execution flow:
364
+ * 1. Query Hub state via Wormhole CCQ
365
+ * 2. Validate Guardian signatures on query response
366
+ * 3. Execute on Sui with validated state
367
+ * 4. Hub state must be < 60s stale (enforced by QueryVerifier)
368
+ */
369
+ async executeWithQuery(_params) {
370
+ throw new Error(
371
+ "Query-based execution on Sui requires relayer integration. Use relayer API to submit query-validated transactions. Relayer will call veridex_spoke::execute_with_query on Sui."
372
+ );
373
+ }
374
+ // ========================================================================
375
+ // Internal helpers
376
+ // ========================================================================
377
+ computeKeyHash(publicKeyX, publicKeyY) {
378
+ const xHex = publicKeyX.toString(16).padStart(64, "0");
379
+ const yHex = publicKeyY.toString(16).padStart(64, "0");
380
+ const combined = Buffer.from(xHex + yHex, "hex");
381
+ const hash = createHash("sha256").update(combined).digest("hex");
382
+ return "0x" + hash;
383
+ }
384
+ buildMessageHash(keyHash, targetChain, actionPayload, nonce) {
385
+ const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ""), "hex");
386
+ const targetChainBuffer = Buffer.alloc(2);
387
+ targetChainBuffer.writeUInt16BE(targetChain);
388
+ const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ""), "hex");
389
+ const nonceHex = nonce.toString(16).padStart(64, "0");
390
+ const nonceBuffer = Buffer.from(nonceHex, "hex");
391
+ const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);
392
+ const hash = createHash("sha256").update(combined).digest("hex");
393
+ return "0x" + hash;
394
+ }
395
+ // ============================================================================
396
+ // Social Recovery Methods (Issue #23)
397
+ // ============================================================================
398
+ //
399
+ // Note: Social recovery is managed on the Hub chain (EVM).
400
+ // Sui spokes receive and execute recovery VAAs broadcast from the Hub.
401
+ // The relayer service handles submitting recovery transactions to Sui.
402
+ //
403
+ // SDK users should use EVMClient methods for guardian management and
404
+ // recovery initiation on the Hub chain.
405
+ // ============================================================================
406
+ /**
407
+ * Get vault object ID by owner key hash
408
+ *
409
+ * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)
410
+ * @param configObjectId - Shared Config object ID
411
+ * @param registryObjectId - Shared VaultRegistry object ID
412
+ * @returns Vault object ID or null if not found
413
+ */
414
+ async getVaultId(ownerKeyHash, registryObjectId) {
415
+ try {
416
+ const registryObject = await this.client.getObject({
417
+ id: registryObjectId,
418
+ options: { showContent: true }
419
+ });
420
+ if (!registryObject.data?.content) {
421
+ return null;
422
+ }
423
+ console.warn("getVaultId requires dynamic field query - use Move view function");
424
+ return null;
425
+ } catch (error) {
426
+ console.error("Error getting vault ID:", error);
427
+ return null;
428
+ }
429
+ }
430
+ /**
431
+ * Get vault owner key hash from vault object
432
+ *
433
+ * @param vaultObjectId - Vault object ID
434
+ * @returns Owner key hash as hex string
435
+ */
436
+ async getVaultOwner(vaultObjectId) {
437
+ try {
438
+ const vaultObject = await this.client.getObject({
439
+ id: vaultObjectId,
440
+ options: { showContent: true }
441
+ });
442
+ if (!vaultObject.data?.content || vaultObject.data.content.dataType !== "moveObject") {
443
+ return null;
444
+ }
445
+ const fields = vaultObject.data.content.fields;
446
+ const ownerKeyHash = fields["owner_key_hash"];
447
+ if (!ownerKeyHash) {
448
+ return null;
449
+ }
450
+ return "0x" + Buffer.from(ownerKeyHash).toString("hex");
451
+ } catch (error) {
452
+ console.error("Error getting vault owner:", error);
453
+ return null;
454
+ }
455
+ }
456
+ /**
457
+ * Get authorized signers for a vault
458
+ *
459
+ * @param vaultObjectId - Vault object ID
460
+ * @returns Array of authorized signer key hashes
461
+ */
462
+ async getAuthorizedSigners(vaultObjectId) {
463
+ try {
464
+ const vaultObject = await this.client.getObject({
465
+ id: vaultObjectId,
466
+ options: { showContent: true }
467
+ });
468
+ if (!vaultObject.data?.content || vaultObject.data.content.dataType !== "moveObject") {
469
+ return [];
470
+ }
471
+ const fields = vaultObject.data.content.fields;
472
+ const authorizedSigners = fields["authorized_signers"];
473
+ if (!authorizedSigners) {
474
+ return [];
475
+ }
476
+ return authorizedSigners.map(
477
+ (signer) => "0x" + Buffer.from(signer).toString("hex")
478
+ );
479
+ } catch (error) {
480
+ console.error("Error getting authorized signers:", error);
481
+ return [];
482
+ }
483
+ }
484
+ /**
485
+ * Check if a VAA has been processed (for replay protection)
486
+ *
487
+ * @param vaaHash - VAA hash as hex string
488
+ * @param processedVaasObjectId - ProcessedVAAs shared object ID
489
+ * @returns Whether the VAA has been processed
490
+ */
491
+ async isVaaProcessed(vaaHash, processedVaasObjectId) {
492
+ try {
493
+ const processedObject = await this.client.getObject({
494
+ id: processedVaasObjectId,
495
+ options: { showContent: true }
496
+ });
497
+ if (!processedObject.data?.content) {
498
+ return false;
499
+ }
500
+ console.warn("isVaaProcessed requires dynamic field query");
501
+ return false;
502
+ } catch (error) {
503
+ console.error("Error checking VAA status:", error);
504
+ return false;
505
+ }
506
+ }
507
+ /**
508
+ * Check if protocol is paused
509
+ *
510
+ * @param configObjectId - Config shared object ID
511
+ * @returns Whether the protocol is paused
512
+ */
513
+ async isProtocolPaused(configObjectId) {
514
+ try {
515
+ const configObject = await this.client.getObject({
516
+ id: configObjectId,
517
+ options: { showContent: true }
518
+ });
519
+ if (!configObject.data?.content || configObject.data.content.dataType !== "moveObject") {
520
+ return false;
521
+ }
522
+ const fields = configObject.data.content.fields;
523
+ return fields["paused"] === true;
524
+ } catch (error) {
525
+ console.error("Error checking pause status:", error);
526
+ return false;
527
+ }
528
+ }
529
+ };
530
+ export {
531
+ SuiClient
532
+ };
533
+ //# sourceMappingURL=index.mjs.map