@nerochain/mpc-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/aa.d.mts +185 -0
  4. package/dist/aa.d.ts +185 -0
  5. package/dist/aa.js +520 -0
  6. package/dist/aa.js.map +1 -0
  7. package/dist/aa.mjs +511 -0
  8. package/dist/aa.mjs.map +1 -0
  9. package/dist/chain-manager-C3eHsVt9.d.mts +98 -0
  10. package/dist/chain-manager-C3eHsVt9.d.ts +98 -0
  11. package/dist/chains.d.mts +17 -0
  12. package/dist/chains.d.ts +17 -0
  13. package/dist/chains.js +331 -0
  14. package/dist/chains.js.map +1 -0
  15. package/dist/chains.mjs +315 -0
  16. package/dist/chains.mjs.map +1 -0
  17. package/dist/index.d.mts +656 -0
  18. package/dist/index.d.ts +656 -0
  19. package/dist/index.js +6627 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/index.mjs +6502 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/modal.d.mts +68 -0
  24. package/dist/modal.d.ts +68 -0
  25. package/dist/modal.js +4867 -0
  26. package/dist/modal.js.map +1 -0
  27. package/dist/modal.mjs +4850 -0
  28. package/dist/modal.mjs.map +1 -0
  29. package/dist/nero-sdk-Cm8gzHZJ.d.mts +684 -0
  30. package/dist/nero-sdk-IhuTBrXZ.d.ts +684 -0
  31. package/dist/no-modal.d.mts +56 -0
  32. package/dist/no-modal.d.ts +56 -0
  33. package/dist/no-modal.js +4060 -0
  34. package/dist/no-modal.js.map +1 -0
  35. package/dist/no-modal.mjs +4041 -0
  36. package/dist/no-modal.mjs.map +1 -0
  37. package/dist/react.d.mts +28 -0
  38. package/dist/react.d.ts +28 -0
  39. package/dist/react.js +4033 -0
  40. package/dist/react.js.map +1 -0
  41. package/dist/react.mjs +4016 -0
  42. package/dist/react.mjs.map +1 -0
  43. package/dist/useNeroWallet-PZh940vV.d.ts +164 -0
  44. package/dist/useNeroWallet-awIYqM6e.d.mts +164 -0
  45. package/package.json +126 -0
@@ -0,0 +1,4060 @@
1
+ 'use strict';
2
+
3
+ var sha256 = require('@noble/hashes/sha256');
4
+ var utils = require('@noble/hashes/utils');
5
+ var secp256k1 = require('@noble/curves/secp256k1');
6
+ var sha3 = require('@noble/hashes/sha3');
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
11
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
12
+ }) : x)(function(x) {
13
+ if (typeof require !== "undefined") return require.apply(this, arguments);
14
+ throw Error('Dynamic require of "' + x + '" is not supported');
15
+ });
16
+ var __esm = (fn, res) => function __init() {
17
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, { get: all[name], enumerable: true });
22
+ };
23
+
24
+ // src/core/crypto-primitives.ts
25
+ var crypto_primitives_exports = {};
26
+ __export(crypto_primitives_exports, {
27
+ bytesToHex: () => utils.bytesToHex,
28
+ computeCommitment: () => computeCommitment,
29
+ decryptWithKey: () => decryptWithKey,
30
+ decryptWithPassword: () => decryptWithPassword,
31
+ deriveKeyFromDeviceInfo: () => deriveKeyFromDeviceInfo,
32
+ deriveKeyFromPassword: () => deriveKeyFromPassword,
33
+ encryptWithKey: () => encryptWithKey,
34
+ encryptWithPassword: () => encryptWithPassword,
35
+ generateRandomBytes: () => generateRandomBytes,
36
+ generateRandomHex: () => generateRandomHex,
37
+ hashSha256: () => hashSha256,
38
+ hexToBytes: () => utils.hexToBytes,
39
+ utf8ToBytes: () => utils.utf8ToBytes
40
+ });
41
+ function getSubtleCrypto() {
42
+ if (typeof globalThis.crypto?.subtle !== "undefined") {
43
+ return globalThis.crypto.subtle;
44
+ }
45
+ throw new Error("WebCrypto API not available in this environment");
46
+ }
47
+ function getRandomValues(length) {
48
+ const buffer = new Uint8Array(length);
49
+ if (typeof globalThis.crypto?.getRandomValues !== "undefined") {
50
+ globalThis.crypto.getRandomValues(buffer);
51
+ return buffer;
52
+ }
53
+ throw new Error("Secure random not available in this environment");
54
+ }
55
+ function toBuffer(data) {
56
+ return data.buffer.slice(
57
+ data.byteOffset,
58
+ data.byteOffset + data.byteLength
59
+ );
60
+ }
61
+ async function deriveKeyFromPassword(password, salt) {
62
+ const subtle = getSubtleCrypto();
63
+ const passwordKey = await subtle.importKey(
64
+ "raw",
65
+ toBuffer(utils.utf8ToBytes(password)),
66
+ "PBKDF2",
67
+ false,
68
+ ["deriveKey"]
69
+ );
70
+ return subtle.deriveKey(
71
+ {
72
+ name: "PBKDF2",
73
+ salt: toBuffer(salt),
74
+ iterations: PBKDF2_ITERATIONS,
75
+ hash: "SHA-256"
76
+ },
77
+ passwordKey,
78
+ { name: "AES-GCM", length: KEY_LENGTH },
79
+ false,
80
+ ["encrypt", "decrypt"]
81
+ );
82
+ }
83
+ async function deriveKeyFromDeviceInfo(deviceId, userId) {
84
+ const combined = `${deviceId}:${userId}`;
85
+ const hash = sha256.sha256(utils.utf8ToBytes(combined));
86
+ const subtle = getSubtleCrypto();
87
+ return subtle.importKey(
88
+ "raw",
89
+ toBuffer(hash),
90
+ { name: "AES-GCM", length: KEY_LENGTH },
91
+ false,
92
+ ["encrypt", "decrypt"]
93
+ );
94
+ }
95
+ async function encryptWithPassword(plaintext, password) {
96
+ const subtle = getSubtleCrypto();
97
+ const salt = getRandomValues(SALT_LENGTH);
98
+ const iv = getRandomValues(IV_LENGTH);
99
+ const key = await deriveKeyFromPassword(password, salt);
100
+ const ciphertext = await subtle.encrypt(
101
+ { name: "AES-GCM", iv: toBuffer(iv) },
102
+ key,
103
+ toBuffer(utils.utf8ToBytes(plaintext))
104
+ );
105
+ return {
106
+ ciphertext: utils.bytesToHex(new Uint8Array(ciphertext)),
107
+ iv: utils.bytesToHex(iv),
108
+ salt: utils.bytesToHex(salt)
109
+ };
110
+ }
111
+ async function decryptWithPassword(encrypted, password) {
112
+ const subtle = getSubtleCrypto();
113
+ const salt = utils.hexToBytes(encrypted.salt);
114
+ const iv = utils.hexToBytes(encrypted.iv);
115
+ const ciphertext = utils.hexToBytes(encrypted.ciphertext);
116
+ const key = await deriveKeyFromPassword(password, salt);
117
+ const plaintext = await subtle.decrypt(
118
+ { name: "AES-GCM", iv: toBuffer(iv) },
119
+ key,
120
+ toBuffer(ciphertext)
121
+ );
122
+ return new TextDecoder().decode(plaintext);
123
+ }
124
+ async function encryptWithKey(plaintext, key) {
125
+ const subtle = getSubtleCrypto();
126
+ const iv = getRandomValues(IV_LENGTH);
127
+ const ciphertext = await subtle.encrypt(
128
+ { name: "AES-GCM", iv: toBuffer(iv) },
129
+ key,
130
+ toBuffer(utils.utf8ToBytes(plaintext))
131
+ );
132
+ return {
133
+ ciphertext: utils.bytesToHex(new Uint8Array(ciphertext)),
134
+ iv: utils.bytesToHex(iv)
135
+ };
136
+ }
137
+ async function decryptWithKey(ciphertext, iv, key) {
138
+ const subtle = getSubtleCrypto();
139
+ const plaintext = await subtle.decrypt(
140
+ { name: "AES-GCM", iv: toBuffer(utils.hexToBytes(iv)) },
141
+ key,
142
+ toBuffer(utils.hexToBytes(ciphertext))
143
+ );
144
+ return new TextDecoder().decode(plaintext);
145
+ }
146
+ function generateRandomBytes(length) {
147
+ return getRandomValues(length);
148
+ }
149
+ function generateRandomHex(length) {
150
+ return utils.bytesToHex(getRandomValues(length));
151
+ }
152
+ function hashSha256(data) {
153
+ const input = typeof data === "string" ? utils.utf8ToBytes(data) : data;
154
+ return utils.bytesToHex(sha256.sha256(input));
155
+ }
156
+ function computeCommitment(value, blinding) {
157
+ const combined = `${value}:${blinding}`;
158
+ return hashSha256(combined);
159
+ }
160
+ var PBKDF2_ITERATIONS, SALT_LENGTH, IV_LENGTH, KEY_LENGTH;
161
+ var init_crypto_primitives = __esm({
162
+ "src/core/crypto-primitives.ts"() {
163
+ PBKDF2_ITERATIONS = 1e5;
164
+ SALT_LENGTH = 16;
165
+ IV_LENGTH = 12;
166
+ KEY_LENGTH = 256;
167
+ }
168
+ });
169
+
170
+ // src/chains/configs.ts
171
+ var NERO_TESTNET = {
172
+ chainId: 689,
173
+ chainName: "nero-testnet",
174
+ displayName: "NERO Testnet",
175
+ nativeCurrency: {
176
+ name: "NERO",
177
+ symbol: "NERO",
178
+ decimals: 18
179
+ },
180
+ rpcUrls: ["https://testnet.nerochain.io"],
181
+ blockExplorerUrls: ["https://testnetscan.nerochain.io"],
182
+ isTestnet: true,
183
+ bundlerUrl: "https://bundler.testnet.nerochain.io",
184
+ paymasterUrl: "https://paymaster.testnet.nerochain.io",
185
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
186
+ simpleAccountFactoryAddress: "0x9406Cc6185a346906296840746125a0E44976454"
187
+ };
188
+ var NERO_MAINNET = {
189
+ chainId: 1689,
190
+ chainName: "nero-mainnet",
191
+ displayName: "NERO Mainnet",
192
+ nativeCurrency: {
193
+ name: "NERO",
194
+ symbol: "NERO",
195
+ decimals: 18
196
+ },
197
+ rpcUrls: ["https://rpc.nerochain.io"],
198
+ blockExplorerUrls: ["https://scan.nerochain.io"],
199
+ isTestnet: false,
200
+ bundlerUrl: "https://bundler.nerochain.io",
201
+ paymasterUrl: "https://paymaster.nerochain.io",
202
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
203
+ simpleAccountFactoryAddress: "0x9406Cc6185a346906296840746125a0E44976454"
204
+ };
205
+ var ETHEREUM_MAINNET = {
206
+ chainId: 1,
207
+ chainName: "ethereum",
208
+ displayName: "Ethereum",
209
+ nativeCurrency: {
210
+ name: "Ether",
211
+ symbol: "ETH",
212
+ decimals: 18
213
+ },
214
+ rpcUrls: ["https://eth.llamarpc.com", "https://rpc.ankr.com/eth"],
215
+ blockExplorerUrls: ["https://etherscan.io"],
216
+ isTestnet: false,
217
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
218
+ };
219
+ var ETHEREUM_SEPOLIA = {
220
+ chainId: 11155111,
221
+ chainName: "sepolia",
222
+ displayName: "Sepolia Testnet",
223
+ nativeCurrency: {
224
+ name: "Sepolia Ether",
225
+ symbol: "ETH",
226
+ decimals: 18
227
+ },
228
+ rpcUrls: ["https://rpc.sepolia.org", "https://rpc.ankr.com/eth_sepolia"],
229
+ blockExplorerUrls: ["https://sepolia.etherscan.io"],
230
+ isTestnet: true,
231
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
232
+ };
233
+ var POLYGON_MAINNET = {
234
+ chainId: 137,
235
+ chainName: "polygon",
236
+ displayName: "Polygon",
237
+ nativeCurrency: {
238
+ name: "MATIC",
239
+ symbol: "MATIC",
240
+ decimals: 18
241
+ },
242
+ rpcUrls: ["https://polygon-rpc.com", "https://rpc.ankr.com/polygon"],
243
+ blockExplorerUrls: ["https://polygonscan.com"],
244
+ isTestnet: false,
245
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
246
+ };
247
+ var ARBITRUM_ONE = {
248
+ chainId: 42161,
249
+ chainName: "arbitrum",
250
+ displayName: "Arbitrum One",
251
+ nativeCurrency: {
252
+ name: "Ether",
253
+ symbol: "ETH",
254
+ decimals: 18
255
+ },
256
+ rpcUrls: ["https://arb1.arbitrum.io/rpc", "https://rpc.ankr.com/arbitrum"],
257
+ blockExplorerUrls: ["https://arbiscan.io"],
258
+ isTestnet: false,
259
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
260
+ };
261
+ var BASE_MAINNET = {
262
+ chainId: 8453,
263
+ chainName: "base",
264
+ displayName: "Base",
265
+ nativeCurrency: {
266
+ name: "Ether",
267
+ symbol: "ETH",
268
+ decimals: 18
269
+ },
270
+ rpcUrls: ["https://mainnet.base.org", "https://base.llamarpc.com"],
271
+ blockExplorerUrls: ["https://basescan.org"],
272
+ isTestnet: false,
273
+ entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
274
+ };
275
+ var BUILTIN_CHAINS = /* @__PURE__ */ new Map([
276
+ [NERO_TESTNET.chainId, NERO_TESTNET],
277
+ [NERO_MAINNET.chainId, NERO_MAINNET],
278
+ [ETHEREUM_MAINNET.chainId, ETHEREUM_MAINNET],
279
+ [ETHEREUM_SEPOLIA.chainId, ETHEREUM_SEPOLIA],
280
+ [POLYGON_MAINNET.chainId, POLYGON_MAINNET],
281
+ [ARBITRUM_ONE.chainId, ARBITRUM_ONE],
282
+ [BASE_MAINNET.chainId, BASE_MAINNET]
283
+ ]);
284
+ function getChainConfig(chainId) {
285
+ return BUILTIN_CHAINS.get(chainId);
286
+ }
287
+ function getAllChains() {
288
+ return Array.from(BUILTIN_CHAINS.values());
289
+ }
290
+
291
+ // src/chains/chain-manager.ts
292
+ var ChainManager = class {
293
+ constructor(initialChainId = 689) {
294
+ this.customChains = /* @__PURE__ */ new Map();
295
+ this.listeners = /* @__PURE__ */ new Set();
296
+ this.rpcConnections = /* @__PURE__ */ new Map();
297
+ this.currentChainId = initialChainId;
298
+ }
299
+ get chainId() {
300
+ return this.currentChainId;
301
+ }
302
+ get chainConfig() {
303
+ return this.getConfig(this.currentChainId);
304
+ }
305
+ getConfig(chainId) {
306
+ return getChainConfig(chainId) ?? this.customChains.get(chainId);
307
+ }
308
+ getSupportedChains() {
309
+ const builtins = Array.from(BUILTIN_CHAINS.values());
310
+ const custom = Array.from(this.customChains.values());
311
+ return [...builtins, ...custom];
312
+ }
313
+ getSupportedChainIds() {
314
+ return this.getSupportedChains().map((c) => c.chainId);
315
+ }
316
+ isChainSupported(chainId) {
317
+ return this.getConfig(chainId) !== void 0;
318
+ }
319
+ addChain(config) {
320
+ this.customChains.set(config.chainId, config);
321
+ }
322
+ removeChain(chainId) {
323
+ if (BUILTIN_CHAINS.has(chainId)) {
324
+ return false;
325
+ }
326
+ return this.customChains.delete(chainId);
327
+ }
328
+ async switchChain(chainId) {
329
+ const config = this.getConfig(chainId);
330
+ if (!config) {
331
+ throw new Error(`Chain ${chainId} is not supported`);
332
+ }
333
+ const previousChainId = this.currentChainId;
334
+ this.currentChainId = chainId;
335
+ if (previousChainId !== chainId) {
336
+ this.notifyListeners(chainId, config);
337
+ }
338
+ return config;
339
+ }
340
+ onChainChange(listener) {
341
+ this.listeners.add(listener);
342
+ return () => this.listeners.delete(listener);
343
+ }
344
+ notifyListeners(chainId, config) {
345
+ for (const listener of this.listeners) {
346
+ try {
347
+ listener(chainId, config);
348
+ } catch {
349
+ }
350
+ }
351
+ }
352
+ getRpcConnection(chainId) {
353
+ const targetChainId = chainId ?? this.currentChainId;
354
+ let connection = this.rpcConnections.get(targetChainId);
355
+ if (!connection) {
356
+ const config = this.getConfig(targetChainId);
357
+ if (!config) {
358
+ throw new Error(`Chain ${targetChainId} is not supported`);
359
+ }
360
+ connection = new RpcConnection(config);
361
+ this.rpcConnections.set(targetChainId, connection);
362
+ }
363
+ return connection;
364
+ }
365
+ getTestnets() {
366
+ return this.getSupportedChains().filter((c) => c.isTestnet);
367
+ }
368
+ getMainnets() {
369
+ return this.getSupportedChains().filter((c) => !c.isTestnet);
370
+ }
371
+ };
372
+ var RpcConnection = class {
373
+ constructor(config) {
374
+ this.currentRpcIndex = 0;
375
+ this.config = config;
376
+ }
377
+ get chainId() {
378
+ return this.config.chainId;
379
+ }
380
+ get rpcUrl() {
381
+ return this.config.rpcUrls[this.currentRpcIndex];
382
+ }
383
+ async call(method, params = []) {
384
+ const maxRetries = this.config.rpcUrls.length;
385
+ let lastError = null;
386
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
387
+ try {
388
+ return await this.executeCall(method, params);
389
+ } catch (error) {
390
+ lastError = error;
391
+ this.rotateRpc();
392
+ }
393
+ }
394
+ throw lastError ?? new Error("RPC call failed");
395
+ }
396
+ async executeCall(method, params) {
397
+ const response = await fetch(this.rpcUrl, {
398
+ method: "POST",
399
+ headers: { "Content-Type": "application/json" },
400
+ body: JSON.stringify({
401
+ jsonrpc: "2.0",
402
+ id: Date.now(),
403
+ method,
404
+ params
405
+ })
406
+ });
407
+ if (!response.ok) {
408
+ throw new Error(`RPC request failed: ${response.status}`);
409
+ }
410
+ const data = await response.json();
411
+ if (data.error) {
412
+ throw new Error(data.error.message ?? "RPC error");
413
+ }
414
+ return data.result;
415
+ }
416
+ rotateRpc() {
417
+ this.currentRpcIndex = (this.currentRpcIndex + 1) % this.config.rpcUrls.length;
418
+ }
419
+ async getBlockNumber() {
420
+ const result = await this.call("eth_blockNumber");
421
+ return BigInt(result);
422
+ }
423
+ async getBalance(address) {
424
+ const result = await this.call("eth_getBalance", [
425
+ address,
426
+ "latest"
427
+ ]);
428
+ return BigInt(result);
429
+ }
430
+ async getTransactionCount(address) {
431
+ const result = await this.call("eth_getTransactionCount", [
432
+ address,
433
+ "latest"
434
+ ]);
435
+ return BigInt(result);
436
+ }
437
+ async getGasPrice() {
438
+ const result = await this.call("eth_gasPrice");
439
+ return BigInt(result);
440
+ }
441
+ async estimateGas(tx) {
442
+ const result = await this.call("eth_estimateGas", [tx]);
443
+ return BigInt(result);
444
+ }
445
+ async getCode(address) {
446
+ return this.call("eth_getCode", [address, "latest"]);
447
+ }
448
+ async sendRawTransaction(signedTx) {
449
+ return this.call("eth_sendRawTransaction", [signedTx]);
450
+ }
451
+ async getTransactionReceipt(hash) {
452
+ return this.call("eth_getTransactionReceipt", [
453
+ hash
454
+ ]);
455
+ }
456
+ async waitForTransaction(hash, confirmations = 1, timeout = 6e4) {
457
+ const startTime = Date.now();
458
+ while (Date.now() - startTime < timeout) {
459
+ const receipt = await this.getTransactionReceipt(hash);
460
+ if (receipt?.blockNumber) {
461
+ const currentBlock = await this.getBlockNumber();
462
+ const txBlock = BigInt(receipt.blockNumber);
463
+ if (currentBlock - txBlock >= BigInt(confirmations - 1)) {
464
+ return receipt;
465
+ }
466
+ }
467
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
468
+ }
469
+ throw new Error(`Transaction ${hash} not confirmed within timeout`);
470
+ }
471
+ };
472
+ function createChainManager(initialChainId) {
473
+ return new ChainManager(initialChainId);
474
+ }
475
+
476
+ // src/types/index.ts
477
+ var SDKError = class extends Error {
478
+ constructor(message, code, statusCode) {
479
+ super(message);
480
+ this.code = code;
481
+ this.statusCode = statusCode;
482
+ this.name = "SDKError";
483
+ }
484
+ };
485
+
486
+ // src/core/client-key-manager.ts
487
+ init_crypto_primitives();
488
+
489
+ // src/core/secure-storage.ts
490
+ init_crypto_primitives();
491
+ var DB_NAME = "nero-mpc-sdk";
492
+ var DB_VERSION = 1;
493
+ var STORE_NAME = "encrypted-data";
494
+ function openDatabase() {
495
+ return new Promise((resolve, reject) => {
496
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
497
+ request.onerror = () => {
498
+ reject(new Error(`Failed to open IndexedDB: ${request.error?.message}`));
499
+ };
500
+ request.onsuccess = () => {
501
+ resolve(request.result);
502
+ };
503
+ request.onupgradeneeded = (event) => {
504
+ const db = event.target.result;
505
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
506
+ db.createObjectStore(STORE_NAME, { keyPath: "key" });
507
+ }
508
+ };
509
+ });
510
+ }
511
+ var IndexedDBStorage = class {
512
+ constructor(prefix = "nero") {
513
+ this.prefix = prefix;
514
+ }
515
+ prefixKey(key) {
516
+ return `${this.prefix}:${key}`;
517
+ }
518
+ async get(key) {
519
+ const db = await openDatabase();
520
+ return new Promise((resolve, reject) => {
521
+ const transaction = db.transaction(STORE_NAME, "readonly");
522
+ const store = transaction.objectStore(STORE_NAME);
523
+ const request = store.get(this.prefixKey(key));
524
+ request.onerror = () => reject(request.error);
525
+ request.onsuccess = () => {
526
+ const item = request.result;
527
+ resolve(item?.value ?? null);
528
+ };
529
+ });
530
+ }
531
+ async set(key, value) {
532
+ const db = await openDatabase();
533
+ return new Promise((resolve, reject) => {
534
+ const transaction = db.transaction(STORE_NAME, "readwrite");
535
+ const store = transaction.objectStore(STORE_NAME);
536
+ const now = Date.now();
537
+ const item = {
538
+ key: this.prefixKey(key),
539
+ value,
540
+ createdAt: now,
541
+ updatedAt: now
542
+ };
543
+ const request = store.put(item);
544
+ request.onerror = () => reject(request.error);
545
+ request.onsuccess = () => resolve();
546
+ });
547
+ }
548
+ async delete(key) {
549
+ const db = await openDatabase();
550
+ return new Promise((resolve, reject) => {
551
+ const transaction = db.transaction(STORE_NAME, "readwrite");
552
+ const store = transaction.objectStore(STORE_NAME);
553
+ const request = store.delete(this.prefixKey(key));
554
+ request.onerror = () => reject(request.error);
555
+ request.onsuccess = () => resolve();
556
+ });
557
+ }
558
+ async clear() {
559
+ const db = await openDatabase();
560
+ return new Promise((resolve, reject) => {
561
+ const transaction = db.transaction(STORE_NAME, "readwrite");
562
+ const store = transaction.objectStore(STORE_NAME);
563
+ const cursorRequest = store.openCursor();
564
+ cursorRequest.onerror = () => reject(cursorRequest.error);
565
+ cursorRequest.onsuccess = (event) => {
566
+ const cursor = event.target.result;
567
+ if (cursor) {
568
+ const key = cursor.key;
569
+ if (key.startsWith(`${this.prefix}:`)) {
570
+ cursor.delete();
571
+ }
572
+ cursor.continue();
573
+ } else {
574
+ resolve();
575
+ }
576
+ };
577
+ });
578
+ }
579
+ };
580
+ var MemoryStorage = class {
581
+ constructor(prefix = "nero") {
582
+ this.store = /* @__PURE__ */ new Map();
583
+ this.prefix = prefix;
584
+ }
585
+ prefixKey(key) {
586
+ return `${this.prefix}:${key}`;
587
+ }
588
+ async get(key) {
589
+ return this.store.get(this.prefixKey(key)) ?? null;
590
+ }
591
+ async set(key, value) {
592
+ this.store.set(this.prefixKey(key), value);
593
+ }
594
+ async delete(key) {
595
+ this.store.delete(this.prefixKey(key));
596
+ }
597
+ async clear() {
598
+ const keysToDelete = [];
599
+ for (const key of this.store.keys()) {
600
+ if (key.startsWith(`${this.prefix}:`)) {
601
+ keysToDelete.push(key);
602
+ }
603
+ }
604
+ for (const key of keysToDelete) {
605
+ this.store.delete(key);
606
+ }
607
+ }
608
+ };
609
+ var ENCRYPTION_VERSION = 1;
610
+ var SecureKeyStorage = class {
611
+ constructor(storage, deviceKey) {
612
+ this.storage = storage;
613
+ this.deviceKey = deviceKey;
614
+ }
615
+ getStorageKey(userId) {
616
+ return `keyshare:${hashSha256(userId)}`;
617
+ }
618
+ getPartySharesKey(userId) {
619
+ return `partyshares:${hashSha256(userId)}`;
620
+ }
621
+ async storeKeyShare(userId, keyShare) {
622
+ const plaintext = JSON.stringify(keyShare);
623
+ const encrypted = await encryptWithPassword(plaintext, this.deviceKey);
624
+ const storedData = {
625
+ ciphertext: encrypted.ciphertext,
626
+ iv: encrypted.iv,
627
+ salt: encrypted.salt,
628
+ version: ENCRYPTION_VERSION
629
+ };
630
+ await this.storage.set(
631
+ this.getStorageKey(userId),
632
+ JSON.stringify(storedData)
633
+ );
634
+ }
635
+ async getKeyShare(userId) {
636
+ const stored = await this.storage.get(this.getStorageKey(userId));
637
+ if (!stored) {
638
+ return null;
639
+ }
640
+ const encryptedData = JSON.parse(stored);
641
+ if (encryptedData.version !== ENCRYPTION_VERSION) {
642
+ throw new Error(
643
+ `Unsupported encryption version: ${encryptedData.version}`
644
+ );
645
+ }
646
+ const encrypted = {
647
+ ciphertext: encryptedData.ciphertext,
648
+ iv: encryptedData.iv,
649
+ salt: encryptedData.salt
650
+ };
651
+ const plaintext = await decryptWithPassword(encrypted, this.deviceKey);
652
+ return JSON.parse(plaintext);
653
+ }
654
+ async hasKeyShare(userId) {
655
+ const stored = await this.storage.get(this.getStorageKey(userId));
656
+ return stored !== null;
657
+ }
658
+ async deleteKeyShare(userId) {
659
+ await this.storage.delete(this.getStorageKey(userId));
660
+ }
661
+ async storePartyPublicShares(userId, shares) {
662
+ const sharesArray = Array.from(shares.entries());
663
+ const plaintext = JSON.stringify(sharesArray);
664
+ const encrypted = await encryptWithPassword(plaintext, this.deviceKey);
665
+ const storedData = {
666
+ ciphertext: encrypted.ciphertext,
667
+ iv: encrypted.iv,
668
+ salt: encrypted.salt,
669
+ version: ENCRYPTION_VERSION
670
+ };
671
+ await this.storage.set(
672
+ this.getPartySharesKey(userId),
673
+ JSON.stringify(storedData)
674
+ );
675
+ }
676
+ async getPartyPublicShares(userId) {
677
+ const stored = await this.storage.get(this.getPartySharesKey(userId));
678
+ if (!stored) {
679
+ return null;
680
+ }
681
+ const encryptedData = JSON.parse(stored);
682
+ if (encryptedData.version !== ENCRYPTION_VERSION) {
683
+ throw new Error(
684
+ `Unsupported encryption version: ${encryptedData.version}`
685
+ );
686
+ }
687
+ const encrypted = {
688
+ ciphertext: encryptedData.ciphertext,
689
+ iv: encryptedData.iv,
690
+ salt: encryptedData.salt
691
+ };
692
+ const plaintext = await decryptWithPassword(encrypted, this.deviceKey);
693
+ const sharesArray = JSON.parse(plaintext);
694
+ return new Map(sharesArray);
695
+ }
696
+ async deletePartyPublicShares(userId) {
697
+ await this.storage.delete(this.getPartySharesKey(userId));
698
+ }
699
+ async clearAll() {
700
+ await this.storage.clear();
701
+ }
702
+ };
703
+ function createSecureStorage(deviceKey, prefix = "nero") {
704
+ const isIndexedDBAvailable = typeof indexedDB !== "undefined" && indexedDB !== null;
705
+ const adapter = isIndexedDBAvailable ? new IndexedDBStorage(prefix) : new MemoryStorage(prefix);
706
+ return new SecureKeyStorage(adapter, deviceKey);
707
+ }
708
+
709
+ // src/core/client-key-manager.ts
710
+ var ClientKeyManager = class {
711
+ constructor(deviceKey, config = {}) {
712
+ this.currentUserId = null;
713
+ this.cachedKeyShare = null;
714
+ this.cachedPartyShares = null;
715
+ this.storage = createSecureStorage(
716
+ deviceKey,
717
+ config.storagePrefix ?? "nero"
718
+ );
719
+ }
720
+ async initialize(userId) {
721
+ this.currentUserId = userId;
722
+ this.cachedKeyShare = await this.storage.getKeyShare(userId);
723
+ }
724
+ async hasKeyShare() {
725
+ if (!this.currentUserId) {
726
+ return false;
727
+ }
728
+ return this.storage.hasKeyShare(this.currentUserId);
729
+ }
730
+ async getKeyShare() {
731
+ if (this.cachedKeyShare) {
732
+ return this.cachedKeyShare;
733
+ }
734
+ if (!this.currentUserId) {
735
+ return null;
736
+ }
737
+ this.cachedKeyShare = await this.storage.getKeyShare(this.currentUserId);
738
+ return this.cachedKeyShare;
739
+ }
740
+ async storeKeyShare(keyShare) {
741
+ if (!this.currentUserId) {
742
+ throw new SDKError("User not initialized", "USER_NOT_INITIALIZED");
743
+ }
744
+ await this.storage.storeKeyShare(this.currentUserId, keyShare);
745
+ this.cachedKeyShare = keyShare;
746
+ }
747
+ async getPartyPublicShares() {
748
+ if (this.cachedPartyShares) {
749
+ return this.cachedPartyShares;
750
+ }
751
+ if (!this.currentUserId) {
752
+ return null;
753
+ }
754
+ this.cachedPartyShares = await this.storage.getPartyPublicShares(
755
+ this.currentUserId
756
+ );
757
+ return this.cachedPartyShares;
758
+ }
759
+ async storePartyPublicShares(shares) {
760
+ if (!this.currentUserId) {
761
+ throw new SDKError("User not initialized", "USER_NOT_INITIALIZED");
762
+ }
763
+ await this.storage.storePartyPublicShares(this.currentUserId, shares);
764
+ this.cachedPartyShares = shares;
765
+ }
766
+ async deleteKeyShare() {
767
+ if (!this.currentUserId) {
768
+ return;
769
+ }
770
+ await this.storage.deleteKeyShare(this.currentUserId);
771
+ this.cachedKeyShare = null;
772
+ }
773
+ async rotateKeyShare(newKeyShare) {
774
+ if (!this.currentUserId) {
775
+ throw new SDKError("User not initialized", "USER_NOT_INITIALIZED");
776
+ }
777
+ const existingShare = await this.getKeyShare();
778
+ if (!existingShare) {
779
+ throw new SDKError("No existing key share to rotate", "NO_KEY_SHARE");
780
+ }
781
+ if (existingShare.partyId !== newKeyShare.partyId) {
782
+ throw new SDKError(
783
+ "Party ID mismatch during rotation",
784
+ "PARTY_ID_MISMATCH"
785
+ );
786
+ }
787
+ await this.storeKeyShare(newKeyShare);
788
+ }
789
+ async exportBackup(password) {
790
+ const keyShare = await this.getKeyShare();
791
+ if (!keyShare) {
792
+ throw new SDKError("No key share to export", "NO_KEY_SHARE");
793
+ }
794
+ const { encryptWithPassword: encryptWithPassword2 } = await Promise.resolve().then(() => (init_crypto_primitives(), crypto_primitives_exports));
795
+ const encrypted = await encryptWithPassword2(
796
+ JSON.stringify(keyShare),
797
+ password
798
+ );
799
+ const backup = {
800
+ version: 1,
801
+ type: "nero-mpc-backup",
802
+ data: encrypted,
803
+ createdAt: Date.now()
804
+ };
805
+ return btoa(JSON.stringify(backup));
806
+ }
807
+ async importBackup(backupString, password) {
808
+ const backup = JSON.parse(atob(backupString));
809
+ if (backup.type !== "nero-mpc-backup") {
810
+ throw new SDKError("Invalid backup format", "INVALID_BACKUP");
811
+ }
812
+ if (backup.version !== 1) {
813
+ throw new SDKError(
814
+ `Unsupported backup version: ${backup.version}`,
815
+ "UNSUPPORTED_VERSION"
816
+ );
817
+ }
818
+ const { decryptWithPassword: decryptWithPassword2 } = await Promise.resolve().then(() => (init_crypto_primitives(), crypto_primitives_exports));
819
+ const plaintext = await decryptWithPassword2(backup.data, password);
820
+ const keyShare = JSON.parse(plaintext);
821
+ return keyShare;
822
+ }
823
+ getWalletInfo(publicKey, chainId) {
824
+ const eoaAddress = this.deriveEOAAddress(publicKey);
825
+ return {
826
+ eoaAddress,
827
+ publicKey,
828
+ chainId
829
+ };
830
+ }
831
+ deriveEOAAddress(publicKey) {
832
+ let pubKeyBytes;
833
+ const pubKeyHex = publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey;
834
+ if (pubKeyHex.length === 130) {
835
+ pubKeyBytes = hexToBytes2(pubKeyHex.slice(2));
836
+ } else if (pubKeyHex.length === 128) {
837
+ pubKeyBytes = hexToBytes2(pubKeyHex);
838
+ } else {
839
+ throw new SDKError("Invalid public key format", "INVALID_PUBLIC_KEY");
840
+ }
841
+ const hash = keccak256(pubKeyBytes);
842
+ const addressBytes = hash.slice(-20);
843
+ return `0x${bytesToHex2(addressBytes)}`;
844
+ }
845
+ async clear() {
846
+ await this.storage.clearAll();
847
+ this.currentUserId = null;
848
+ this.cachedKeyShare = null;
849
+ this.cachedPartyShares = null;
850
+ }
851
+ };
852
+ function hexToBytes2(hex) {
853
+ const bytes = new Uint8Array(hex.length / 2);
854
+ for (let i = 0; i < bytes.length; i++) {
855
+ bytes[i] = Number.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
856
+ }
857
+ return bytes;
858
+ }
859
+ function bytesToHex2(bytes) {
860
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
861
+ }
862
+ function keccak256(data) {
863
+ const { keccak_256: keccak_2565 } = __require("@noble/hashes/sha3");
864
+ return keccak_2565(data);
865
+ }
866
+ function generateDeviceKey() {
867
+ return generateRandomHex(32);
868
+ }
869
+
870
+ // src/core/index.ts
871
+ init_crypto_primitives();
872
+
873
+ // src/core/provider-types.ts
874
+ var EIP1193_ERROR_CODES = {
875
+ UNAUTHORIZED: 4100,
876
+ UNSUPPORTED_METHOD: 4200,
877
+ DISCONNECTED: 4900,
878
+ CHAIN_DISCONNECTED: 4901,
879
+ INTERNAL_ERROR: -32603,
880
+ CHAIN_NOT_ADDED: 4902
881
+ };
882
+ function createProviderRpcError(code, message, data) {
883
+ const error = new Error(message);
884
+ error.code = code;
885
+ error.data = data;
886
+ return error;
887
+ }
888
+
889
+ // src/core/provider.ts
890
+ var NeroProvider = class {
891
+ constructor(config) {
892
+ this.listeners = /* @__PURE__ */ new Map();
893
+ this.connected = false;
894
+ this.customChains = /* @__PURE__ */ new Map();
895
+ this.config = config;
896
+ this.chainId = config.chainId;
897
+ this.chainConfig = getChainConfig(config.chainId);
898
+ }
899
+ get isNero() {
900
+ return true;
901
+ }
902
+ get isConnected() {
903
+ return this.connected;
904
+ }
905
+ async request(args) {
906
+ const { method, params } = args;
907
+ switch (method) {
908
+ case "eth_chainId":
909
+ return this.toHexChainId(this.chainId);
910
+ case "net_version":
911
+ return String(this.chainId);
912
+ case "eth_accounts":
913
+ case "eth_requestAccounts":
914
+ return this.handleRequestAccounts();
915
+ case "eth_sign":
916
+ return this.handleEthSign(params);
917
+ case "personal_sign":
918
+ return this.handlePersonalSign(params);
919
+ case "eth_signTypedData":
920
+ case "eth_signTypedData_v3":
921
+ case "eth_signTypedData_v4":
922
+ return this.handleSignTypedData(params);
923
+ case "eth_sendTransaction":
924
+ return this.handleSendTransaction(params);
925
+ case "wallet_switchEthereumChain":
926
+ return this.handleSwitchChain(params);
927
+ case "wallet_addEthereumChain":
928
+ return this.handleAddChain(params);
929
+ case "wallet_watchAsset":
930
+ return true;
931
+ case "eth_call":
932
+ case "eth_estimateGas":
933
+ case "eth_getBalance":
934
+ case "eth_getBlockByNumber":
935
+ case "eth_getBlockByHash":
936
+ case "eth_getTransactionByHash":
937
+ case "eth_getTransactionReceipt":
938
+ case "eth_getCode":
939
+ case "eth_getStorageAt":
940
+ case "eth_blockNumber":
941
+ case "eth_gasPrice":
942
+ case "eth_getTransactionCount":
943
+ case "eth_getLogs":
944
+ case "eth_feeHistory":
945
+ case "eth_maxPriorityFeePerGas":
946
+ return this.forwardToRpc(method, params);
947
+ default:
948
+ throw createProviderRpcError(
949
+ EIP1193_ERROR_CODES.UNSUPPORTED_METHOD,
950
+ `Method ${method} is not supported`
951
+ );
952
+ }
953
+ }
954
+ on(event, listener) {
955
+ if (!this.listeners.has(event)) {
956
+ this.listeners.set(event, /* @__PURE__ */ new Set());
957
+ }
958
+ this.listeners.get(event)?.add(listener);
959
+ return this;
960
+ }
961
+ removeListener(event, listener) {
962
+ this.listeners.get(event)?.delete(listener);
963
+ return this;
964
+ }
965
+ removeAllListeners(event) {
966
+ if (event) {
967
+ this.listeners.delete(event);
968
+ } else {
969
+ this.listeners.clear();
970
+ }
971
+ return this;
972
+ }
973
+ emit(event, ...args) {
974
+ const listeners = this.listeners.get(event);
975
+ if (!listeners || listeners.size === 0) {
976
+ return false;
977
+ }
978
+ for (const listener of listeners) {
979
+ try {
980
+ listener(...args);
981
+ } catch {
982
+ }
983
+ }
984
+ return true;
985
+ }
986
+ connect() {
987
+ if (this.connected) return;
988
+ this.connected = true;
989
+ const info = {
990
+ chainId: this.toHexChainId(this.chainId)
991
+ };
992
+ this.emit("connect", info);
993
+ }
994
+ disconnect(error) {
995
+ if (!this.connected) return;
996
+ this.connected = false;
997
+ this.emit(
998
+ "disconnect",
999
+ error ?? createProviderRpcError(
1000
+ EIP1193_ERROR_CODES.DISCONNECTED,
1001
+ "Provider disconnected"
1002
+ )
1003
+ );
1004
+ }
1005
+ async switchChain(chainId) {
1006
+ const config = this.getChainConfigById(chainId);
1007
+ if (!config) {
1008
+ throw createProviderRpcError(
1009
+ EIP1193_ERROR_CODES.CHAIN_NOT_ADDED,
1010
+ `Chain ${chainId} has not been added`
1011
+ );
1012
+ }
1013
+ const previousChainId = this.chainId;
1014
+ this.chainId = chainId;
1015
+ this.chainConfig = config;
1016
+ if (previousChainId !== chainId) {
1017
+ this.emit("chainChanged", this.toHexChainId(chainId));
1018
+ this.config.onChainChanged?.(chainId);
1019
+ }
1020
+ }
1021
+ addChain(config) {
1022
+ this.customChains.set(config.chainId, config);
1023
+ }
1024
+ getChainId() {
1025
+ return this.chainId;
1026
+ }
1027
+ getChainConfig() {
1028
+ return this.chainConfig;
1029
+ }
1030
+ getChainConfigById(chainId) {
1031
+ return getChainConfig(chainId) ?? this.customChains.get(chainId);
1032
+ }
1033
+ async handleRequestAccounts() {
1034
+ const accounts = this.config.getAccounts();
1035
+ if (accounts.length === 0) {
1036
+ throw createProviderRpcError(
1037
+ EIP1193_ERROR_CODES.UNAUTHORIZED,
1038
+ "No accounts available"
1039
+ );
1040
+ }
1041
+ if (!this.connected) {
1042
+ this.connect();
1043
+ }
1044
+ return accounts;
1045
+ }
1046
+ async handleEthSign(params) {
1047
+ const [address, message] = params;
1048
+ this.validateAddress(address);
1049
+ return this.config.signMessage(utils.hexToBytes(message.slice(2)));
1050
+ }
1051
+ async handlePersonalSign(params) {
1052
+ const [message, address] = params;
1053
+ this.validateAddress(address);
1054
+ const messageBytes = message.startsWith("0x") ? utils.hexToBytes(message.slice(2)) : utils.utf8ToBytes(message);
1055
+ return this.config.signMessage(messageBytes);
1056
+ }
1057
+ async handleSignTypedData(params) {
1058
+ const [address, typedDataJson] = params;
1059
+ this.validateAddress(address);
1060
+ const typedData = JSON.parse(typedDataJson);
1061
+ const { domain, types, primaryType, message } = typedData;
1062
+ const typesWithoutEIP712Domain = { ...types };
1063
+ typesWithoutEIP712Domain.EIP712Domain = void 0;
1064
+ return this.config.signTypedData(
1065
+ domain,
1066
+ typesWithoutEIP712Domain,
1067
+ primaryType,
1068
+ message
1069
+ );
1070
+ }
1071
+ async handleSendTransaction(params) {
1072
+ const [tx] = params;
1073
+ return this.config.sendTransaction(tx);
1074
+ }
1075
+ async handleSwitchChain(params) {
1076
+ const [{ chainId }] = params;
1077
+ const numericChainId = Number.parseInt(chainId, 16);
1078
+ await this.switchChain(numericChainId);
1079
+ return null;
1080
+ }
1081
+ async handleAddChain(params) {
1082
+ const [chainParams] = params;
1083
+ const chainId = Number.parseInt(chainParams.chainId, 16);
1084
+ const config = {
1085
+ chainId,
1086
+ chainName: chainParams.chainName.toLowerCase().replace(/\s+/g, "-"),
1087
+ displayName: chainParams.chainName,
1088
+ nativeCurrency: chainParams.nativeCurrency,
1089
+ rpcUrls: chainParams.rpcUrls,
1090
+ blockExplorerUrls: chainParams.blockExplorerUrls,
1091
+ isTestnet: false
1092
+ };
1093
+ this.addChain(config);
1094
+ return null;
1095
+ }
1096
+ async forwardToRpc(method, params) {
1097
+ if (!this.chainConfig?.rpcUrls?.[0]) {
1098
+ throw createProviderRpcError(
1099
+ EIP1193_ERROR_CODES.CHAIN_DISCONNECTED,
1100
+ "No RPC URL available for current chain"
1101
+ );
1102
+ }
1103
+ const response = await fetch(this.chainConfig.rpcUrls[0], {
1104
+ method: "POST",
1105
+ headers: { "Content-Type": "application/json" },
1106
+ body: JSON.stringify({
1107
+ jsonrpc: "2.0",
1108
+ id: Date.now(),
1109
+ method,
1110
+ params: params ?? []
1111
+ })
1112
+ });
1113
+ const data = await response.json();
1114
+ if (data.error) {
1115
+ throw createProviderRpcError(
1116
+ data.error.code ?? EIP1193_ERROR_CODES.INTERNAL_ERROR,
1117
+ data.error.message,
1118
+ data.error.data
1119
+ );
1120
+ }
1121
+ return data.result;
1122
+ }
1123
+ validateAddress(address) {
1124
+ const accounts = this.config.getAccounts();
1125
+ const normalizedAddress = address.toLowerCase();
1126
+ const hasAccount = accounts.some(
1127
+ (a) => a.toLowerCase() === normalizedAddress
1128
+ );
1129
+ if (!hasAccount) {
1130
+ throw createProviderRpcError(
1131
+ EIP1193_ERROR_CODES.UNAUTHORIZED,
1132
+ `Address ${address} is not authorized`
1133
+ );
1134
+ }
1135
+ }
1136
+ toHexChainId(chainId) {
1137
+ return `0x${chainId.toString(16)}`;
1138
+ }
1139
+ };
1140
+ function createNeroProvider(config) {
1141
+ return new NeroProvider(config);
1142
+ }
1143
+ var CURVE_ORDER = secp256k1.secp256k1.CURVE.n;
1144
+ function generateRandomScalar() {
1145
+ const bytes = new Uint8Array(32);
1146
+ crypto.getRandomValues(bytes);
1147
+ const scalar = bytesToBigInt(bytes) % CURVE_ORDER;
1148
+ return scalar === 0n ? generateRandomScalar() : scalar;
1149
+ }
1150
+ function generatePolynomial(degree) {
1151
+ if (degree < 0 || !Number.isInteger(degree)) {
1152
+ throw new Error(`Invalid polynomial degree: ${degree}`);
1153
+ }
1154
+ const coefficients = [];
1155
+ for (let i = 0; i <= degree; i++) {
1156
+ coefficients.push(generateRandomScalar());
1157
+ }
1158
+ return coefficients;
1159
+ }
1160
+ function evaluatePolynomial(coefficients, x) {
1161
+ let result = 0n;
1162
+ let xPower = 1n;
1163
+ for (const coeff of coefficients) {
1164
+ result = mod(result + mod(coeff * xPower, CURVE_ORDER), CURVE_ORDER);
1165
+ xPower = mod(xPower * x, CURVE_ORDER);
1166
+ }
1167
+ return result;
1168
+ }
1169
+ function aggregateShares(receivedShares, ownShare) {
1170
+ let combined = ownShare;
1171
+ for (const share of receivedShares.values()) {
1172
+ combined = mod(combined + share, CURVE_ORDER);
1173
+ }
1174
+ return combined;
1175
+ }
1176
+ function scalarToHex(scalar) {
1177
+ return scalar.toString(16).padStart(64, "0");
1178
+ }
1179
+ function hexToScalar(hex) {
1180
+ return BigInt(`0x${hex}`);
1181
+ }
1182
+ function mod(n, m) {
1183
+ return (n % m + m) % m;
1184
+ }
1185
+ function bytesToBigInt(bytes) {
1186
+ let result = 0n;
1187
+ for (const byte of bytes) {
1188
+ result = (result << 8n) + BigInt(byte);
1189
+ }
1190
+ return result;
1191
+ }
1192
+
1193
+ // src/protocols/dkg/commitments.ts
1194
+ function createVSSSCommitments(partyId, coefficients) {
1195
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
1196
+ const coefficientCommitments = coefficients.map(
1197
+ (coeff) => G2.multiply(coeff).toHex(true)
1198
+ );
1199
+ const proof = createProofOfKnowledge(
1200
+ partyId,
1201
+ coefficients[0],
1202
+ coefficientCommitments[0]
1203
+ );
1204
+ return {
1205
+ partyId,
1206
+ coefficientCommitments,
1207
+ proofOfKnowledge: proof
1208
+ };
1209
+ }
1210
+ function verifyVSSSCommitment(commitment, share, receiverPartyId) {
1211
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
1212
+ const sharePoint = G2.multiply(share);
1213
+ let expectedPoint = secp256k1.secp256k1.ProjectivePoint.fromHex(
1214
+ commitment.coefficientCommitments[0]
1215
+ );
1216
+ const x = BigInt(receiverPartyId);
1217
+ let xPower = x;
1218
+ for (let i = 1; i < commitment.coefficientCommitments.length; i++) {
1219
+ const commitmentPoint = secp256k1.secp256k1.ProjectivePoint.fromHex(
1220
+ commitment.coefficientCommitments[i]
1221
+ );
1222
+ const scaled = commitmentPoint.multiply(xPower);
1223
+ expectedPoint = expectedPoint.add(scaled);
1224
+ xPower = mod(xPower * x, CURVE_ORDER);
1225
+ }
1226
+ return sharePoint.equals(expectedPoint);
1227
+ }
1228
+ function createProofOfKnowledge(partyId, secret, publicCommitment) {
1229
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
1230
+ const k = generateRandomScalar();
1231
+ const R = G2.multiply(k);
1232
+ const challenge = computeChallenge(partyId, publicCommitment, R.toHex(true));
1233
+ const response = mod(k + secret * challenge, CURVE_ORDER);
1234
+ return JSON.stringify({
1235
+ R: R.toHex(true),
1236
+ s: scalarToHex(response)
1237
+ });
1238
+ }
1239
+ function verifyProofOfKnowledge(proof, partyId, publicCommitment) {
1240
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
1241
+ const { R, s } = JSON.parse(proof);
1242
+ const RPoint = secp256k1.secp256k1.ProjectivePoint.fromHex(R);
1243
+ const response = BigInt(`0x${s}`);
1244
+ const challenge = computeChallenge(partyId, publicCommitment, R);
1245
+ const leftSide = G2.multiply(response);
1246
+ const commitmentPoint = secp256k1.secp256k1.ProjectivePoint.fromHex(publicCommitment);
1247
+ const rightSide = RPoint.add(commitmentPoint.multiply(challenge));
1248
+ return leftSide.equals(rightSide);
1249
+ }
1250
+ function computeChallenge(partyId, commitment, R) {
1251
+ const input = `${partyId}:${commitment}:${R}`;
1252
+ const hash = sha256.sha256(utils.utf8ToBytes(input));
1253
+ return mod(BigInt(`0x${utils.bytesToHex(hash)}`), CURVE_ORDER);
1254
+ }
1255
+ function combineVSSSCommitments(commitments) {
1256
+ let combined = secp256k1.secp256k1.ProjectivePoint.fromHex(
1257
+ commitments[0].coefficientCommitments[0]
1258
+ );
1259
+ for (let i = 1; i < commitments.length; i++) {
1260
+ const point = secp256k1.secp256k1.ProjectivePoint.fromHex(
1261
+ commitments[i].coefficientCommitments[0]
1262
+ );
1263
+ combined = combined.add(point);
1264
+ }
1265
+ return combined.toHex(false);
1266
+ }
1267
+ function toBuffer2(data) {
1268
+ return data.buffer.slice(
1269
+ data.byteOffset,
1270
+ data.byteOffset + data.byteLength
1271
+ );
1272
+ }
1273
+ async function deriveSharedSecret(privateKey, publicKey) {
1274
+ const pubPoint = secp256k1.secp256k1.ProjectivePoint.fromHex(publicKey);
1275
+ const sharedPoint = pubPoint.multiply(privateKey);
1276
+ const sharedBytes = utils.hexToBytes(sharedPoint.toHex(true));
1277
+ return sha256.sha256(sharedBytes);
1278
+ }
1279
+ async function aesGcmEncrypt(plaintext, key, nonce) {
1280
+ const cryptoKey = await crypto.subtle.importKey(
1281
+ "raw",
1282
+ toBuffer2(key),
1283
+ { name: "AES-GCM" },
1284
+ false,
1285
+ ["encrypt"]
1286
+ );
1287
+ const encrypted = await crypto.subtle.encrypt(
1288
+ { name: "AES-GCM", iv: toBuffer2(nonce), tagLength: 128 },
1289
+ cryptoKey,
1290
+ toBuffer2(plaintext)
1291
+ );
1292
+ const encryptedArray = new Uint8Array(encrypted);
1293
+ const ciphertext = encryptedArray.slice(0, -16);
1294
+ const tag = encryptedArray.slice(-16);
1295
+ return { ciphertext, tag };
1296
+ }
1297
+ async function aesGcmDecrypt(ciphertext, tag, key, nonce) {
1298
+ const cryptoKey = await crypto.subtle.importKey(
1299
+ "raw",
1300
+ toBuffer2(key),
1301
+ { name: "AES-GCM" },
1302
+ false,
1303
+ ["decrypt"]
1304
+ );
1305
+ const combined = new Uint8Array(ciphertext.length + tag.length);
1306
+ combined.set(ciphertext);
1307
+ combined.set(tag, ciphertext.length);
1308
+ const decrypted = await crypto.subtle.decrypt(
1309
+ { name: "AES-GCM", iv: toBuffer2(nonce), tagLength: 128 },
1310
+ cryptoKey,
1311
+ toBuffer2(combined)
1312
+ );
1313
+ return new Uint8Array(decrypted);
1314
+ }
1315
+ async function encryptShare(share, fromPartyId, toPartyId, recipientPublicKey) {
1316
+ const ephemeralPrivateKey = generateSecureScalar();
1317
+ const ephemeralPublicKey = secp256k1.secp256k1.ProjectivePoint.BASE.multiply(ephemeralPrivateKey).toHex(true);
1318
+ const sharedSecret = await deriveSharedSecret(
1319
+ ephemeralPrivateKey,
1320
+ recipientPublicKey
1321
+ );
1322
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
1323
+ const shareHex = scalarToHex(share);
1324
+ const plaintext = utils.utf8ToBytes(shareHex);
1325
+ const { ciphertext, tag } = await aesGcmEncrypt(
1326
+ plaintext,
1327
+ sharedSecret,
1328
+ nonce
1329
+ );
1330
+ return {
1331
+ fromPartyId,
1332
+ toPartyId,
1333
+ ephemeralPublicKey,
1334
+ ciphertext: utils.bytesToHex(ciphertext),
1335
+ nonce: utils.bytesToHex(nonce),
1336
+ tag: utils.bytesToHex(tag)
1337
+ };
1338
+ }
1339
+ async function decryptShare(encryptedShare, recipientPrivateKey) {
1340
+ const sharedSecret = await deriveSharedSecret(
1341
+ recipientPrivateKey,
1342
+ encryptedShare.ephemeralPublicKey
1343
+ );
1344
+ const ciphertext = utils.hexToBytes(encryptedShare.ciphertext);
1345
+ const nonce = utils.hexToBytes(encryptedShare.nonce);
1346
+ const tag = utils.hexToBytes(encryptedShare.tag);
1347
+ const plaintext = await aesGcmDecrypt(ciphertext, tag, sharedSecret, nonce);
1348
+ const shareHex = new TextDecoder().decode(plaintext);
1349
+ const share = hexToScalar(shareHex);
1350
+ return {
1351
+ fromPartyId: encryptedShare.fromPartyId,
1352
+ share
1353
+ };
1354
+ }
1355
+ function generateSecureScalar() {
1356
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
1357
+ const scalar = mod(BigInt(`0x${utils.bytesToHex(bytes)}`), CURVE_ORDER);
1358
+ if (scalar === 0n) {
1359
+ throw new Error("RNG failure: generated zero scalar");
1360
+ }
1361
+ return scalar;
1362
+ }
1363
+ function generateEphemeralKeyPair() {
1364
+ const privateKey = generateSecureScalar();
1365
+ const publicKey = secp256k1.secp256k1.ProjectivePoint.BASE.multiply(privateKey).toHex(true);
1366
+ return { privateKey, publicKey };
1367
+ }
1368
+
1369
+ // src/protocols/dkg/dkg-client.ts
1370
+ var PROTOCOL_VERSION = "pedersen-dkg-v1";
1371
+ var DKGClient = class {
1372
+ constructor(config) {
1373
+ this.state = null;
1374
+ this.polynomial = [];
1375
+ this.ephemeralKeyPair = null;
1376
+ this.receivedCommitments = /* @__PURE__ */ new Map();
1377
+ this.receivedShares = /* @__PURE__ */ new Map();
1378
+ this.apiClient = config.apiClient;
1379
+ this.wsClient = config.wsClient;
1380
+ this.timeout = config.timeout ?? 6e4;
1381
+ }
1382
+ async execute() {
1383
+ try {
1384
+ await this.initializeSession();
1385
+ await this.runCommitmentPhase();
1386
+ await this.runShareExchangePhase();
1387
+ await this.runVerificationPhase();
1388
+ return await this.completeProtocol();
1389
+ } catch (error) {
1390
+ const message = error instanceof Error ? error.message : "DKG failed";
1391
+ return {
1392
+ success: false,
1393
+ error: message
1394
+ };
1395
+ }
1396
+ }
1397
+ async initializeSession() {
1398
+ const { sessionId, partyId, participantCount, threshold } = await this.apiClient.initiateDKG();
1399
+ if (threshold < 2) {
1400
+ throw new SDKError(
1401
+ "Threshold must be at least 2 for security",
1402
+ "INVALID_THRESHOLD"
1403
+ );
1404
+ }
1405
+ if (participantCount < 2) {
1406
+ throw new SDKError(
1407
+ "Participant count must be at least 2",
1408
+ "INVALID_PARTICIPANT_COUNT"
1409
+ );
1410
+ }
1411
+ if (threshold > participantCount) {
1412
+ throw new SDKError(
1413
+ "Threshold cannot exceed participant count",
1414
+ "INVALID_THRESHOLD"
1415
+ );
1416
+ }
1417
+ this.state = {
1418
+ sessionId,
1419
+ round: "commitment",
1420
+ partyId,
1421
+ participantCount,
1422
+ threshold,
1423
+ commitments: /* @__PURE__ */ new Map(),
1424
+ receivedShares: /* @__PURE__ */ new Map()
1425
+ };
1426
+ this.polynomial = generatePolynomial(threshold - 1);
1427
+ this.ephemeralKeyPair = generateEphemeralKeyPair();
1428
+ if (this.wsClient) {
1429
+ await this.wsClient.connect();
1430
+ this.wsClient.setAccessToken(
1431
+ this.apiClient.getTokens()?.accessToken ?? ""
1432
+ );
1433
+ }
1434
+ }
1435
+ async runCommitmentPhase() {
1436
+ if (!this.state) throw new SDKError("State not initialized", "STATE_ERROR");
1437
+ const commitment = createVSSSCommitments(
1438
+ this.state.partyId,
1439
+ this.polynomial
1440
+ );
1441
+ const apiCommitment = {
1442
+ partyId: this.state.partyId,
1443
+ commitments: commitment.coefficientCommitments,
1444
+ publicKey: this.ephemeralKeyPair?.publicKey ?? "",
1445
+ proofOfKnowledge: commitment.proofOfKnowledge
1446
+ };
1447
+ await this.apiClient.submitDKGCommitment(
1448
+ this.state.sessionId,
1449
+ apiCommitment
1450
+ );
1451
+ this.receivedCommitments.set(this.state.partyId, commitment);
1452
+ const otherCommitments = await this.waitForCommitments();
1453
+ for (const [partyId, comm] of otherCommitments) {
1454
+ if (!comm.proofOfKnowledge) {
1455
+ throw new SDKError(
1456
+ `Missing proof of knowledge from party ${comm.partyId}. Backend must relay proofs for client-side verification.`,
1457
+ "MISSING_COMMITMENT_PROOF"
1458
+ );
1459
+ }
1460
+ if (comm.partyId !== partyId) {
1461
+ throw new SDKError(
1462
+ `Party ID mismatch: expected ${partyId}, got ${comm.partyId}`,
1463
+ "PARTY_ID_MISMATCH"
1464
+ );
1465
+ }
1466
+ if (!verifyProofOfKnowledge(
1467
+ comm.proofOfKnowledge,
1468
+ comm.partyId,
1469
+ comm.coefficientCommitments[0]
1470
+ )) {
1471
+ throw new SDKError(
1472
+ `Invalid proof of knowledge from party ${comm.partyId}`,
1473
+ "INVALID_COMMITMENT_PROOF"
1474
+ );
1475
+ }
1476
+ this.receivedCommitments.set(comm.partyId, comm);
1477
+ }
1478
+ this.state.round = "share_exchange";
1479
+ }
1480
+ async runShareExchangePhase() {
1481
+ if (!this.state) throw new SDKError("State not initialized", "STATE_ERROR");
1482
+ for (let partyId = 1; partyId <= this.state.participantCount; partyId++) {
1483
+ if (partyId === this.state.partyId) continue;
1484
+ const share = evaluatePolynomial(this.polynomial, BigInt(partyId));
1485
+ const commitment = this.receivedCommitments.get(partyId);
1486
+ if (!commitment) {
1487
+ throw new SDKError(
1488
+ `Missing commitment from party ${partyId}`,
1489
+ "MISSING_COMMITMENT"
1490
+ );
1491
+ }
1492
+ const apiCommitment = await this.apiClient.getDKGCommitments(
1493
+ this.state.sessionId
1494
+ );
1495
+ const partyCommitment = apiCommitment.commitments.find(
1496
+ (c) => c.partyId === partyId
1497
+ );
1498
+ if (!partyCommitment) {
1499
+ throw new SDKError(
1500
+ `Missing public key from party ${partyId}`,
1501
+ "MISSING_PUBLIC_KEY"
1502
+ );
1503
+ }
1504
+ const encrypted = await encryptShare(
1505
+ share,
1506
+ this.state.partyId,
1507
+ partyId,
1508
+ partyCommitment.publicKey
1509
+ );
1510
+ await this.apiClient.submitDKGShare(
1511
+ this.state.sessionId,
1512
+ JSON.stringify(encrypted),
1513
+ partyId
1514
+ );
1515
+ }
1516
+ const ownShare = evaluatePolynomial(
1517
+ this.polynomial,
1518
+ BigInt(this.state.partyId)
1519
+ );
1520
+ this.receivedShares.set(this.state.partyId, ownShare);
1521
+ const receivedShares = await this.waitForShares();
1522
+ for (const [partyId, encryptedShare] of receivedShares) {
1523
+ const decrypted = await decryptShare(
1524
+ encryptedShare,
1525
+ this.ephemeralKeyPair?.privateKey ?? 0n
1526
+ );
1527
+ const commitment = this.receivedCommitments.get(partyId);
1528
+ if (!commitment) {
1529
+ throw new SDKError(
1530
+ `Missing commitment from party ${partyId}`,
1531
+ "MISSING_COMMITMENT"
1532
+ );
1533
+ }
1534
+ if (!verifyVSSSCommitment(commitment, decrypted.share, this.state.partyId)) {
1535
+ throw new SDKError(
1536
+ `Invalid share from party ${partyId}`,
1537
+ "INVALID_SHARE"
1538
+ );
1539
+ }
1540
+ this.receivedShares.set(partyId, decrypted.share);
1541
+ }
1542
+ this.state.round = "verification";
1543
+ }
1544
+ async runVerificationPhase() {
1545
+ if (!this.state) throw new SDKError("State not initialized", "STATE_ERROR");
1546
+ const finalShare = aggregateShares(this.receivedShares, 0n);
1547
+ const allCommitments = Array.from(this.receivedCommitments.values());
1548
+ const publicKey = combineVSSSCommitments(allCommitments);
1549
+ this.state.privateShare = finalShare;
1550
+ this.state.publicKey = publicKey;
1551
+ this.state.round = "complete";
1552
+ }
1553
+ async completeProtocol() {
1554
+ if (!this.state || !this.state.privateShare || !this.state.publicKey) {
1555
+ throw new SDKError("Protocol not complete", "PROTOCOL_INCOMPLETE");
1556
+ }
1557
+ const walletAddress = this.deriveWalletAddress(this.state.publicKey);
1558
+ await this.apiClient.completeDKG(
1559
+ this.state.sessionId,
1560
+ this.state.partyId,
1561
+ this.state.publicKey,
1562
+ walletAddress
1563
+ );
1564
+ return {
1565
+ success: true,
1566
+ publicKey: this.state.publicKey,
1567
+ walletAddress,
1568
+ partyId: this.state.partyId
1569
+ };
1570
+ }
1571
+ getKeyShare() {
1572
+ if (!this.state?.privateShare) return null;
1573
+ return {
1574
+ partyId: this.state.partyId,
1575
+ privateShare: scalarToHex(this.state.privateShare),
1576
+ publicShare: secp256k1.secp256k1.ProjectivePoint.BASE.multiply(
1577
+ this.state.privateShare
1578
+ ).toHex(true),
1579
+ commitment: this.computeShareCommitment(this.state.privateShare),
1580
+ threshold: this.state.threshold,
1581
+ totalParties: this.state.participantCount,
1582
+ protocolVersion: PROTOCOL_VERSION
1583
+ };
1584
+ }
1585
+ getPartyPublicShares() {
1586
+ const shares = /* @__PURE__ */ new Map();
1587
+ for (const [partyId, commitment] of this.receivedCommitments) {
1588
+ if (commitment.coefficientCommitments.length > 0) {
1589
+ shares.set(partyId, commitment.coefficientCommitments[0]);
1590
+ }
1591
+ }
1592
+ return shares;
1593
+ }
1594
+ async waitForCommitments() {
1595
+ const startTime = Date.now();
1596
+ const commitments = /* @__PURE__ */ new Map();
1597
+ while (Date.now() - startTime < this.timeout) {
1598
+ const result = await this.apiClient.getDKGCommitments(
1599
+ this.state?.sessionId ?? ""
1600
+ );
1601
+ for (const comm of result.commitments) {
1602
+ if (comm.partyId !== this.state?.partyId && !commitments.has(comm.partyId)) {
1603
+ commitments.set(comm.partyId, {
1604
+ partyId: comm.partyId,
1605
+ coefficientCommitments: comm.commitments,
1606
+ proofOfKnowledge: comm.proofOfKnowledge ?? ""
1607
+ });
1608
+ }
1609
+ }
1610
+ if (result.ready || commitments.size >= (this.state?.participantCount ?? 1) - 1) {
1611
+ return commitments;
1612
+ }
1613
+ await this.delay(1e3);
1614
+ }
1615
+ throw new SDKError("Timeout waiting for commitments", "COMMITMENT_TIMEOUT");
1616
+ }
1617
+ async waitForShares() {
1618
+ const startTime = Date.now();
1619
+ const shares = /* @__PURE__ */ new Map();
1620
+ while (Date.now() - startTime < this.timeout) {
1621
+ const result = await this.apiClient.getDKGShares(
1622
+ this.state?.sessionId ?? "",
1623
+ this.state?.partyId ?? 0
1624
+ );
1625
+ for (const share of result.shares) {
1626
+ if (!shares.has(share.fromPartyId)) {
1627
+ shares.set(share.fromPartyId, JSON.parse(share.encryptedShare));
1628
+ }
1629
+ }
1630
+ if (result.ready || shares.size >= (this.state?.participantCount ?? 1) - 1) {
1631
+ return shares;
1632
+ }
1633
+ await this.delay(1e3);
1634
+ }
1635
+ throw new SDKError("Timeout waiting for shares", "SHARE_TIMEOUT");
1636
+ }
1637
+ deriveWalletAddress(publicKey) {
1638
+ const pubKeyBytes = utils.hexToBytes(
1639
+ publicKey.startsWith("04") ? publicKey.slice(2) : publicKey
1640
+ );
1641
+ const hash = sha3.keccak_256(pubKeyBytes);
1642
+ const addressBytes = hash.slice(-20);
1643
+ return `0x${utils.bytesToHex(addressBytes)}`;
1644
+ }
1645
+ computeShareCommitment(share) {
1646
+ const shareHex = scalarToHex(share);
1647
+ return utils.bytesToHex(sha256.sha256(utils.hexToBytes(shareHex)));
1648
+ }
1649
+ delay(ms) {
1650
+ return new Promise((resolve) => setTimeout(resolve, ms));
1651
+ }
1652
+ cleanup() {
1653
+ this.state = null;
1654
+ this.polynomial = [];
1655
+ this.ephemeralKeyPair = null;
1656
+ this.receivedCommitments.clear();
1657
+ this.receivedShares.clear();
1658
+ }
1659
+ };
1660
+
1661
+ // src/transport/api-client.ts
1662
+ var APIClient = class {
1663
+ constructor(config) {
1664
+ this.tokens = null;
1665
+ this.refreshPromise = null;
1666
+ this.baseUrl = config.backendUrl.replace(/\/$/, "");
1667
+ }
1668
+ setTokens(tokens) {
1669
+ this.tokens = tokens;
1670
+ }
1671
+ getTokens() {
1672
+ return this.tokens;
1673
+ }
1674
+ clearTokens() {
1675
+ this.tokens = null;
1676
+ }
1677
+ async request(method, path, body, requiresAuth = true) {
1678
+ if (requiresAuth && this.tokens) {
1679
+ if (Date.now() >= this.tokens.expiresAt - 6e4) {
1680
+ await this.refreshAccessToken();
1681
+ }
1682
+ }
1683
+ const headers = {
1684
+ "Content-Type": "application/json"
1685
+ };
1686
+ if (requiresAuth && this.tokens) {
1687
+ headers.Authorization = `Bearer ${this.tokens.accessToken}`;
1688
+ }
1689
+ const response = await fetch(`${this.baseUrl}${path}`, {
1690
+ method,
1691
+ headers,
1692
+ body: body ? JSON.stringify(body) : void 0,
1693
+ credentials: "include"
1694
+ });
1695
+ const data = await response.json();
1696
+ if (!data.success) {
1697
+ throw new SDKError(
1698
+ data.error?.message ?? "Request failed",
1699
+ data.error?.code ?? "REQUEST_FAILED",
1700
+ response.status
1701
+ );
1702
+ }
1703
+ return data.data;
1704
+ }
1705
+ async refreshAccessToken() {
1706
+ if (this.refreshPromise) {
1707
+ return this.refreshPromise;
1708
+ }
1709
+ this.refreshPromise = (async () => {
1710
+ if (!this.tokens?.refreshToken) {
1711
+ throw new SDKError("No refresh token available", "NO_REFRESH_TOKEN");
1712
+ }
1713
+ const response = await fetch(`${this.baseUrl}/api/auth/refresh`, {
1714
+ method: "POST",
1715
+ headers: { "Content-Type": "application/json" },
1716
+ body: JSON.stringify({ refreshToken: this.tokens.refreshToken })
1717
+ });
1718
+ const data = await response.json();
1719
+ if (!data.success || !data.data) {
1720
+ this.tokens = null;
1721
+ throw new SDKError("Token refresh failed", "TOKEN_REFRESH_FAILED");
1722
+ }
1723
+ this.tokens = {
1724
+ accessToken: data.data.accessToken,
1725
+ refreshToken: data.data.refreshToken,
1726
+ expiresAt: Date.now() + data.data.expiresIn * 1e3
1727
+ };
1728
+ })();
1729
+ try {
1730
+ await this.refreshPromise;
1731
+ } finally {
1732
+ this.refreshPromise = null;
1733
+ }
1734
+ }
1735
+ async getOAuthUrl(provider, redirectUri) {
1736
+ return this.request(
1737
+ "POST",
1738
+ "/api/auth/oauth/url",
1739
+ { provider, redirectUri },
1740
+ false
1741
+ );
1742
+ }
1743
+ async handleOAuthCallback(provider, code, state, fingerprint) {
1744
+ const result = await this.request(
1745
+ "POST",
1746
+ "/api/auth/oauth/callback",
1747
+ { provider, code, state, fingerprint },
1748
+ false
1749
+ );
1750
+ this.tokens = {
1751
+ accessToken: result.accessToken,
1752
+ refreshToken: result.refreshToken,
1753
+ expiresAt: Date.now() + result.expiresIn * 1e3
1754
+ };
1755
+ return {
1756
+ user: result.user,
1757
+ tokens: this.tokens,
1758
+ wallet: result.wallet,
1759
+ requiresDKG: result.requiresDKG
1760
+ };
1761
+ }
1762
+ async getCurrentUser() {
1763
+ return this.request("GET", "/api/user/me");
1764
+ }
1765
+ async logout() {
1766
+ await this.request("POST", "/api/auth/logout");
1767
+ this.tokens = null;
1768
+ }
1769
+ async initiateDKG() {
1770
+ return this.request("POST", "/api/mpc/dkg/initiate");
1771
+ }
1772
+ async submitDKGCommitment(sessionId, commitment) {
1773
+ return this.request("POST", "/api/mpc/dkg/commitment", {
1774
+ sessionId,
1775
+ commitment
1776
+ });
1777
+ }
1778
+ async getDKGCommitments(sessionId) {
1779
+ return this.request("GET", `/api/mpc/dkg/${sessionId}/commitments`);
1780
+ }
1781
+ async submitDKGShare(sessionId, encryptedShare, toPartyId) {
1782
+ return this.request("POST", "/api/mpc/dkg/share", {
1783
+ sessionId,
1784
+ encryptedShare,
1785
+ toPartyId
1786
+ });
1787
+ }
1788
+ async getDKGShares(sessionId, partyId) {
1789
+ return this.request("GET", `/api/mpc/dkg/${sessionId}/shares/${partyId}`);
1790
+ }
1791
+ async completeDKG(sessionId, partyId, publicKey, walletAddress) {
1792
+ return this.request("POST", "/api/mpc/dkg/complete", {
1793
+ sessionId,
1794
+ partyId,
1795
+ publicKey,
1796
+ walletAddress
1797
+ });
1798
+ }
1799
+ async initiateSigningSession(messageHash, messageType) {
1800
+ return this.request("POST", "/api/mpc/signing/initiate", {
1801
+ messageHash,
1802
+ messageType
1803
+ });
1804
+ }
1805
+ async submitNonceCommitment(sessionId, partyId, commitment) {
1806
+ return this.request("POST", "/api/mpc/signing/nonce-commitment", {
1807
+ sessionId,
1808
+ partyId,
1809
+ commitment
1810
+ });
1811
+ }
1812
+ async getNonceCommitments(sessionId) {
1813
+ return this.request(
1814
+ "GET",
1815
+ `/api/mpc/signing/${sessionId}/nonce-commitments`
1816
+ );
1817
+ }
1818
+ async submitPartialSignature(sessionId, partyId, partialSignature) {
1819
+ return this.request("POST", "/api/mpc/signing/partial", {
1820
+ sessionId,
1821
+ partyId,
1822
+ partialSignature
1823
+ });
1824
+ }
1825
+ async getPartialSignatures(sessionId) {
1826
+ return this.request("GET", `/api/mpc/signing/${sessionId}/partials`);
1827
+ }
1828
+ async getSigningResult(sessionId) {
1829
+ return this.request("GET", `/api/mpc/signing/${sessionId}/result`);
1830
+ }
1831
+ async getWalletInfo() {
1832
+ return this.request("GET", "/api/wallet/info");
1833
+ }
1834
+ async getPartyPublicShares() {
1835
+ return this.request("GET", "/api/wallet/party-shares");
1836
+ }
1837
+ // DKLS V2 API Methods
1838
+ async dklsKeygenInit() {
1839
+ return this.request("POST", "/api/v2/dkls/keygen/init");
1840
+ }
1841
+ async dklsKeygenCommitment(sessionId, clientCommitment) {
1842
+ return this.request("POST", "/api/v2/dkls/keygen/commitment", {
1843
+ sessionId,
1844
+ clientCommitment
1845
+ });
1846
+ }
1847
+ async dklsKeygenComplete(sessionId, clientPublicShare) {
1848
+ return this.request("POST", "/api/v2/dkls/keygen/complete", {
1849
+ sessionId,
1850
+ clientPublicShare
1851
+ });
1852
+ }
1853
+ async dklsSigningInit(params) {
1854
+ return this.request("POST", "/api/v2/dkls/signing/init", params);
1855
+ }
1856
+ async dklsSigningNonce(sessionId, clientNonceCommitment) {
1857
+ return this.request("POST", "/api/v2/dkls/signing/nonce", {
1858
+ sessionId,
1859
+ clientNonceCommitment
1860
+ });
1861
+ }
1862
+ /**
1863
+ * @deprecated This method defeats threshold security by transmitting the full key share.
1864
+ * Use the MtA-based signing flow instead: dklsMtaRound1 -> dklsMtaRound2 -> dklsSigningPartial.
1865
+ * This endpoint is only available in test mode (DKLS_LOCAL_TESTING_MODE=true).
1866
+ */
1867
+ async dklsSigningComplete(sessionId, clientKeyShare) {
1868
+ console.warn(
1869
+ "[DEPRECATED] dklsSigningComplete defeats threshold security. Use MtA-based signing (dklsMtaRound1/dklsMtaRound2/dklsSigningPartial) instead."
1870
+ );
1871
+ return this.request("POST", "/api/v2/dkls/signing/complete", {
1872
+ sessionId,
1873
+ clientKeyShare
1874
+ });
1875
+ }
1876
+ async dklsSigningStatus(sessionId) {
1877
+ return this.request("GET", `/api/v2/dkls/signing/${sessionId}`);
1878
+ }
1879
+ async dklsSigningCancel(sessionId) {
1880
+ return this.request("DELETE", `/api/v2/dkls/signing/${sessionId}`);
1881
+ }
1882
+ async dklsMtaRound1(sessionId, mta1Setup, mta2Setup) {
1883
+ return this.request("POST", "/api/v2/dkls/signing/mta/round1", {
1884
+ sessionId,
1885
+ mta1Setup,
1886
+ mta2Setup
1887
+ });
1888
+ }
1889
+ async dklsMtaRound2(sessionId, mta1Encrypted, mta2Encrypted) {
1890
+ return this.request("POST", "/api/v2/dkls/signing/mta/round2", {
1891
+ sessionId,
1892
+ mta1Encrypted,
1893
+ mta2Encrypted
1894
+ });
1895
+ }
1896
+ async dklsSigningPartial(sessionId, clientPartialSignature) {
1897
+ return this.request("POST", "/api/v2/dkls/signing/partial", {
1898
+ sessionId,
1899
+ clientPartialSignature
1900
+ });
1901
+ }
1902
+ async initiateDeviceVerification(fingerprint, deviceName) {
1903
+ return this.request("POST", "/api/user/devices/verify/initiate", {
1904
+ fingerprint,
1905
+ deviceName
1906
+ });
1907
+ }
1908
+ async completeDeviceVerification(verificationId, code, fingerprint) {
1909
+ return this.request("POST", "/api/user/devices/verify/complete", {
1910
+ verificationId,
1911
+ code,
1912
+ fingerprint
1913
+ });
1914
+ }
1915
+ };
1916
+
1917
+ // src/transport/websocket-client.ts
1918
+ var RECONNECT_DELAYS = [1e3, 2e3, 5e3, 1e4, 3e4];
1919
+ var PING_INTERVAL = 3e4;
1920
+ var MESSAGE_QUEUE_MAX = 100;
1921
+ var WebSocketClient = class {
1922
+ constructor(url) {
1923
+ this.ws = null;
1924
+ this.accessToken = null;
1925
+ this.messageHandlers = /* @__PURE__ */ new Map();
1926
+ this.globalHandlers = /* @__PURE__ */ new Set();
1927
+ this.onConnectHandlers = /* @__PURE__ */ new Set();
1928
+ this.onDisconnectHandlers = /* @__PURE__ */ new Set();
1929
+ this.onErrorHandlers = /* @__PURE__ */ new Set();
1930
+ this.reconnectAttempt = 0;
1931
+ this.reconnectTimeout = null;
1932
+ this.pingInterval = null;
1933
+ this.messageQueue = [];
1934
+ this.isConnecting = false;
1935
+ this.url = url;
1936
+ }
1937
+ setAccessToken(token) {
1938
+ this.accessToken = token;
1939
+ }
1940
+ async connect() {
1941
+ if (this.ws?.readyState === WebSocket.OPEN) {
1942
+ return;
1943
+ }
1944
+ if (this.isConnecting) {
1945
+ return;
1946
+ }
1947
+ this.isConnecting = true;
1948
+ return new Promise((resolve, reject) => {
1949
+ const wsUrl = this.accessToken ? `${this.url}?token=${encodeURIComponent(this.accessToken)}` : this.url;
1950
+ this.ws = new WebSocket(wsUrl);
1951
+ this.ws.onopen = () => {
1952
+ this.isConnecting = false;
1953
+ this.reconnectAttempt = 0;
1954
+ this.startPingInterval();
1955
+ this.flushMessageQueue();
1956
+ this.onConnectHandlers.forEach((handler) => handler());
1957
+ resolve();
1958
+ };
1959
+ this.ws.onmessage = (event) => {
1960
+ this.handleMessage(event.data);
1961
+ };
1962
+ this.ws.onerror = () => {
1963
+ const error = new Error("WebSocket error");
1964
+ this.onErrorHandlers.forEach((handler) => handler(error));
1965
+ };
1966
+ this.ws.onclose = (event) => {
1967
+ this.isConnecting = false;
1968
+ this.stopPingInterval();
1969
+ this.onDisconnectHandlers.forEach((handler) => handler());
1970
+ if (!event.wasClean) {
1971
+ this.scheduleReconnect();
1972
+ }
1973
+ if (this.isConnecting) {
1974
+ reject(new SDKError("Connection failed", "CONNECTION_FAILED"));
1975
+ }
1976
+ };
1977
+ });
1978
+ }
1979
+ disconnect() {
1980
+ this.stopReconnect();
1981
+ this.stopPingInterval();
1982
+ if (this.ws) {
1983
+ this.ws.close(1e3, "Client disconnect");
1984
+ this.ws = null;
1985
+ }
1986
+ }
1987
+ isConnected() {
1988
+ return this.ws?.readyState === WebSocket.OPEN;
1989
+ }
1990
+ send(message) {
1991
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
1992
+ this.queueMessage(message);
1993
+ return;
1994
+ }
1995
+ this.ws.send(JSON.stringify(message));
1996
+ }
1997
+ on(type, handler) {
1998
+ if (!this.messageHandlers.has(type)) {
1999
+ this.messageHandlers.set(type, /* @__PURE__ */ new Set());
2000
+ }
2001
+ this.messageHandlers.get(type)?.add(handler);
2002
+ return () => {
2003
+ this.messageHandlers.get(type)?.delete(handler);
2004
+ };
2005
+ }
2006
+ onAny(handler) {
2007
+ this.globalHandlers.add(handler);
2008
+ return () => {
2009
+ this.globalHandlers.delete(handler);
2010
+ };
2011
+ }
2012
+ onConnect(handler) {
2013
+ this.onConnectHandlers.add(handler);
2014
+ return () => {
2015
+ this.onConnectHandlers.delete(handler);
2016
+ };
2017
+ }
2018
+ onDisconnect(handler) {
2019
+ this.onDisconnectHandlers.add(handler);
2020
+ return () => {
2021
+ this.onDisconnectHandlers.delete(handler);
2022
+ };
2023
+ }
2024
+ onError(handler) {
2025
+ this.onErrorHandlers.add(handler);
2026
+ return () => {
2027
+ this.onErrorHandlers.delete(handler);
2028
+ };
2029
+ }
2030
+ waitForMessage(type, sessionId, timeout = 3e4) {
2031
+ return new Promise((resolve, reject) => {
2032
+ const timer = setTimeout(() => {
2033
+ unsubscribe();
2034
+ reject(new SDKError(`Timeout waiting for ${type}`, "MESSAGE_TIMEOUT"));
2035
+ }, timeout);
2036
+ const unsubscribe = this.on(type, (message) => {
2037
+ if (message.sessionId === sessionId) {
2038
+ clearTimeout(timer);
2039
+ unsubscribe();
2040
+ resolve(message);
2041
+ }
2042
+ });
2043
+ });
2044
+ }
2045
+ handleMessage(data) {
2046
+ let message;
2047
+ try {
2048
+ message = JSON.parse(data);
2049
+ } catch {
2050
+ return;
2051
+ }
2052
+ if (message.type === "pong") {
2053
+ return;
2054
+ }
2055
+ this.globalHandlers.forEach((handler) => handler(message));
2056
+ const typeHandlers = this.messageHandlers.get(message.type);
2057
+ if (typeHandlers) {
2058
+ typeHandlers.forEach((handler) => handler(message));
2059
+ }
2060
+ }
2061
+ queueMessage(message) {
2062
+ if (this.messageQueue.length >= MESSAGE_QUEUE_MAX) {
2063
+ this.messageQueue.shift();
2064
+ }
2065
+ this.messageQueue.push({
2066
+ message,
2067
+ timestamp: Date.now()
2068
+ });
2069
+ }
2070
+ flushMessageQueue() {
2071
+ const now = Date.now();
2072
+ const validMessages = this.messageQueue.filter(
2073
+ (item) => now - item.timestamp < 6e4
2074
+ );
2075
+ this.messageQueue = [];
2076
+ for (const item of validMessages) {
2077
+ this.send(item.message);
2078
+ }
2079
+ }
2080
+ scheduleReconnect() {
2081
+ if (this.reconnectTimeout) {
2082
+ return;
2083
+ }
2084
+ const delay = RECONNECT_DELAYS[Math.min(this.reconnectAttempt, RECONNECT_DELAYS.length - 1)];
2085
+ this.reconnectTimeout = setTimeout(() => {
2086
+ this.reconnectTimeout = null;
2087
+ this.reconnectAttempt++;
2088
+ this.connect().catch(() => {
2089
+ });
2090
+ }, delay);
2091
+ }
2092
+ stopReconnect() {
2093
+ if (this.reconnectTimeout) {
2094
+ clearTimeout(this.reconnectTimeout);
2095
+ this.reconnectTimeout = null;
2096
+ }
2097
+ this.reconnectAttempt = 0;
2098
+ }
2099
+ startPingInterval() {
2100
+ this.pingInterval = setInterval(() => {
2101
+ if (this.ws?.readyState === WebSocket.OPEN) {
2102
+ this.ws.send(JSON.stringify({ type: "ping" }));
2103
+ }
2104
+ }, PING_INTERVAL);
2105
+ }
2106
+ stopPingInterval() {
2107
+ if (this.pingInterval) {
2108
+ clearInterval(this.pingInterval);
2109
+ this.pingInterval = null;
2110
+ }
2111
+ }
2112
+ };
2113
+ var CURVE_ORDER2 = secp256k1.secp256k1.CURVE.n;
2114
+ function mod2(n, m) {
2115
+ return (n % m + m) % m;
2116
+ }
2117
+ function generateRandomScalar2() {
2118
+ const bytes = new Uint8Array(32);
2119
+ crypto.getRandomValues(bytes);
2120
+ let result = 0n;
2121
+ for (const byte of bytes) {
2122
+ result = (result << 8n) + BigInt(byte);
2123
+ }
2124
+ const scalar = mod2(result, CURVE_ORDER2);
2125
+ return scalar === 0n ? generateRandomScalar2() : scalar;
2126
+ }
2127
+ function generateNonceShare() {
2128
+ return {
2129
+ k: generateRandomScalar2(),
2130
+ gamma: generateRandomScalar2()
2131
+ };
2132
+ }
2133
+ function createNonceCommitment(partyId, nonce) {
2134
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
2135
+ const D = G2.multiply(nonce.gamma);
2136
+ const E = G2.multiply(nonce.k);
2137
+ const proof = createNonceProof(partyId, nonce.k, nonce.gamma, D, E);
2138
+ return {
2139
+ partyId,
2140
+ D: D.toHex(true),
2141
+ E: E.toHex(true),
2142
+ proof
2143
+ };
2144
+ }
2145
+ function verifyNonceCommitment(commitment) {
2146
+ try {
2147
+ secp256k1.secp256k1.ProjectivePoint.fromHex(commitment.D);
2148
+ secp256k1.secp256k1.ProjectivePoint.fromHex(commitment.E);
2149
+ return true;
2150
+ } catch {
2151
+ return false;
2152
+ }
2153
+ }
2154
+ function verifyNonceProof(commitment) {
2155
+ try {
2156
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
2157
+ const D = secp256k1.secp256k1.ProjectivePoint.fromHex(commitment.D);
2158
+ const E = secp256k1.secp256k1.ProjectivePoint.fromHex(commitment.E);
2159
+ const { R1, R2, s1, s2 } = JSON.parse(commitment.proof);
2160
+ if (!/^[0-9a-fA-F]{1,64}$/.test(s1) || !/^[0-9a-fA-F]{1,64}$/.test(s2)) {
2161
+ return false;
2162
+ }
2163
+ const R1Point = secp256k1.secp256k1.ProjectivePoint.fromHex(R1);
2164
+ const R2Point = secp256k1.secp256k1.ProjectivePoint.fromHex(R2);
2165
+ const s1Scalar = BigInt(`0x${s1}`);
2166
+ const s2Scalar = BigInt(`0x${s2}`);
2167
+ if (s1Scalar <= 0n || s1Scalar >= CURVE_ORDER2) return false;
2168
+ if (s2Scalar <= 0n || s2Scalar >= CURVE_ORDER2) return false;
2169
+ const challenge = computeNonceChallenge(
2170
+ commitment.partyId,
2171
+ commitment.D,
2172
+ commitment.E,
2173
+ R1,
2174
+ R2
2175
+ );
2176
+ const leftSide1 = G2.multiply(s1Scalar);
2177
+ const rightSide1 = R1Point.add(D.multiply(challenge));
2178
+ if (!leftSide1.equals(rightSide1)) return false;
2179
+ const leftSide2 = G2.multiply(s2Scalar);
2180
+ const rightSide2 = R2Point.add(E.multiply(challenge));
2181
+ if (!leftSide2.equals(rightSide2)) return false;
2182
+ return true;
2183
+ } catch {
2184
+ return false;
2185
+ }
2186
+ }
2187
+ function createNonceProof(partyId, k, gamma, D, E) {
2188
+ const G2 = secp256k1.secp256k1.ProjectivePoint.BASE;
2189
+ const r1 = generateRandomScalar2();
2190
+ const r2 = generateRandomScalar2();
2191
+ const R1 = G2.multiply(r1);
2192
+ const R2 = G2.multiply(r2);
2193
+ const challenge = computeNonceChallenge(
2194
+ partyId,
2195
+ D.toHex(true),
2196
+ E.toHex(true),
2197
+ R1.toHex(true),
2198
+ R2.toHex(true)
2199
+ );
2200
+ const s1 = mod2(r1 + gamma * challenge, CURVE_ORDER2);
2201
+ const s2 = mod2(r2 + k * challenge, CURVE_ORDER2);
2202
+ return JSON.stringify({
2203
+ R1: R1.toHex(true),
2204
+ R2: R2.toHex(true),
2205
+ s1: s1.toString(16).padStart(64, "0"),
2206
+ s2: s2.toString(16).padStart(64, "0")
2207
+ });
2208
+ }
2209
+ function computeNonceChallenge(partyId, D, E, R1, R2) {
2210
+ const input = `${partyId}:${D}:${E}:${R1}:${R2}`;
2211
+ const hash = sha256.sha256(utils.utf8ToBytes(input));
2212
+ return mod2(BigInt(`0x${utils.bytesToHex(hash)}`), CURVE_ORDER2);
2213
+ }
2214
+ function combineNonceCommitments(commitments) {
2215
+ let combinedD = secp256k1.secp256k1.ProjectivePoint.fromHex(commitments[0].D);
2216
+ let combinedE = secp256k1.secp256k1.ProjectivePoint.fromHex(commitments[0].E);
2217
+ for (let i = 1; i < commitments.length; i++) {
2218
+ combinedD = combinedD.add(
2219
+ secp256k1.secp256k1.ProjectivePoint.fromHex(commitments[i].D)
2220
+ );
2221
+ combinedE = combinedE.add(
2222
+ secp256k1.secp256k1.ProjectivePoint.fromHex(commitments[i].E)
2223
+ );
2224
+ }
2225
+ return {
2226
+ R: combinedE.toHex(true),
2227
+ combinedGamma: combinedD.toHex(true)
2228
+ };
2229
+ }
2230
+ function computeR(combinedE) {
2231
+ const R = secp256k1.secp256k1.ProjectivePoint.fromHex(combinedE);
2232
+ const rFull = R.toAffine();
2233
+ const r = mod2(rFull.x, CURVE_ORDER2);
2234
+ return {
2235
+ r,
2236
+ R: R.toHex(true),
2237
+ rPoint: { x: rFull.x, y: rFull.y }
2238
+ };
2239
+ }
2240
+ var CURVE_ORDER3 = secp256k1.secp256k1.CURVE.n;
2241
+ var G = secp256k1.secp256k1.ProjectivePoint.BASE;
2242
+ function mod3(n, m) {
2243
+ return (n % m + m) % m;
2244
+ }
2245
+ function modInverse(a, m) {
2246
+ let [oldR, r] = [a, m];
2247
+ let [oldS, s] = [1n, 0n];
2248
+ while (r !== 0n) {
2249
+ const quotient = oldR / r;
2250
+ [oldR, r] = [r, oldR - quotient * r];
2251
+ [oldS, s] = [s, oldS - quotient * s];
2252
+ }
2253
+ return mod3(oldS, m);
2254
+ }
2255
+ function computeLagrangeCoefficient(partyId, participatingParties) {
2256
+ let numerator = 1n;
2257
+ let denominator = 1n;
2258
+ const i = BigInt(partyId);
2259
+ for (const j of participatingParties) {
2260
+ if (j !== partyId) {
2261
+ const jBig = BigInt(j);
2262
+ numerator = mod3(numerator * (CURVE_ORDER3 - jBig), CURVE_ORDER3);
2263
+ denominator = mod3(denominator * mod3(i - jBig, CURVE_ORDER3), CURVE_ORDER3);
2264
+ }
2265
+ }
2266
+ const denominatorInverse = modInverse(denominator, CURVE_ORDER3);
2267
+ return mod3(numerator * denominatorInverse, CURVE_ORDER3);
2268
+ }
2269
+ function computePartialSignature(partyId, keyShare, nonceK, _nonceGamma, messageHash, r, participatingParties) {
2270
+ const lambda = computeLagrangeCoefficient(partyId, participatingParties);
2271
+ const kInverse = modInverse(nonceK, CURVE_ORDER3);
2272
+ const adjustedShare = mod3(keyShare * lambda, CURVE_ORDER3);
2273
+ const sigma = mod3(kInverse * (messageHash + r * adjustedShare), CURVE_ORDER3);
2274
+ const publicShare = G.multiply(keyShare).toHex(true);
2275
+ const nonceCommitment = G.multiply(nonceK).toHex(true);
2276
+ return {
2277
+ partyId,
2278
+ sigma,
2279
+ publicShare,
2280
+ nonceCommitment
2281
+ };
2282
+ }
2283
+ function verifyPartialSignature(partial, expectedPublicShare, expectedNonceCommitment, r, messageHash, participatingParties) {
2284
+ if (partial.sigma <= 0n || partial.sigma >= CURVE_ORDER3) {
2285
+ return false;
2286
+ }
2287
+ if (!partial.publicShare || !partial.nonceCommitment) {
2288
+ return false;
2289
+ }
2290
+ if (expectedPublicShare && partial.publicShare !== expectedPublicShare) {
2291
+ return false;
2292
+ }
2293
+ if (expectedNonceCommitment && partial.nonceCommitment !== expectedNonceCommitment) {
2294
+ return false;
2295
+ }
2296
+ let R_i;
2297
+ try {
2298
+ R_i = secp256k1.secp256k1.ProjectivePoint.fromHex(partial.nonceCommitment);
2299
+ } catch {
2300
+ return false;
2301
+ }
2302
+ let P_i;
2303
+ try {
2304
+ P_i = secp256k1.secp256k1.ProjectivePoint.fromHex(partial.publicShare);
2305
+ } catch {
2306
+ return false;
2307
+ }
2308
+ const lambda = computeLagrangeCoefficient(
2309
+ partial.partyId,
2310
+ participatingParties
2311
+ );
2312
+ const rTimesLambda = mod3(r * lambda, CURVE_ORDER3);
2313
+ const leftSide = R_i.multiply(partial.sigma);
2314
+ const rightSide = G.multiply(messageHash).add(P_i.multiply(rTimesLambda));
2315
+ return leftSide.equals(rightSide);
2316
+ }
2317
+ function parseMessageHash(hash) {
2318
+ const cleanHash = hash.startsWith("0x") ? hash.slice(2) : hash;
2319
+ return BigInt(`0x${cleanHash}`);
2320
+ }
2321
+
2322
+ // src/protocols/signing/signing-client.ts
2323
+ var SigningClient = class {
2324
+ constructor(config) {
2325
+ this.state = null;
2326
+ this.nonceShare = null;
2327
+ this.receivedCommitments = /* @__PURE__ */ new Map();
2328
+ this.expectedPublicShares = /* @__PURE__ */ new Map();
2329
+ this.r = null;
2330
+ this.apiClient = config.apiClient;
2331
+ this.wsClient = config.wsClient;
2332
+ this.keyShare = config.keyShare;
2333
+ this.expectedPublicShares = new Map(config.partyPublicShares);
2334
+ this.timeout = config.timeout ?? 3e4;
2335
+ }
2336
+ async sign(request) {
2337
+ try {
2338
+ await this.initializeSession(request);
2339
+ await this.runNonceCommitmentPhase();
2340
+ await this.runPartialSignaturePhase();
2341
+ return await this.completeProtocol();
2342
+ } catch (error) {
2343
+ const message = error instanceof Error ? error.message : "Signing failed";
2344
+ return {
2345
+ success: false,
2346
+ error: message
2347
+ };
2348
+ } finally {
2349
+ this.cleanup();
2350
+ }
2351
+ }
2352
+ async initializeSession(request) {
2353
+ const { sessionId, participatingParties } = await this.apiClient.initiateSigningSession(
2354
+ request.messageHash,
2355
+ request.messageType
2356
+ );
2357
+ if (participatingParties.length < this.keyShare.threshold) {
2358
+ throw new SDKError(
2359
+ `Insufficient participating parties: got ${participatingParties.length}, need ${this.keyShare.threshold}`,
2360
+ "INSUFFICIENT_PARTIES"
2361
+ );
2362
+ }
2363
+ this.state = {
2364
+ sessionId,
2365
+ round: "nonce_commitment",
2366
+ messageHash: request.messageHash,
2367
+ participatingParties,
2368
+ nonceCommitments: /* @__PURE__ */ new Map(),
2369
+ partialSignatures: /* @__PURE__ */ new Map()
2370
+ };
2371
+ this.nonceShare = generateNonceShare();
2372
+ if (this.wsClient) {
2373
+ await this.wsClient.connect();
2374
+ }
2375
+ }
2376
+ async runNonceCommitmentPhase() {
2377
+ if (!this.state || !this.nonceShare) {
2378
+ throw new SDKError("State not initialized", "STATE_ERROR");
2379
+ }
2380
+ const commitment = createNonceCommitment(
2381
+ this.keyShare.partyId,
2382
+ this.nonceShare
2383
+ );
2384
+ await this.apiClient.submitNonceCommitment(
2385
+ this.state.sessionId,
2386
+ this.keyShare.partyId,
2387
+ JSON.stringify(commitment)
2388
+ );
2389
+ this.receivedCommitments.set(this.keyShare.partyId, commitment);
2390
+ const otherCommitments = await this.waitForNonceCommitments();
2391
+ for (const [partyId, comm] of otherCommitments) {
2392
+ if (!verifyNonceCommitment(comm)) {
2393
+ throw new SDKError(
2394
+ `Invalid nonce commitment from party ${partyId}`,
2395
+ "INVALID_NONCE_COMMITMENT"
2396
+ );
2397
+ }
2398
+ if (!verifyNonceProof(comm)) {
2399
+ throw new SDKError(
2400
+ `Invalid nonce proof from party ${partyId}`,
2401
+ "INVALID_NONCE_PROOF"
2402
+ );
2403
+ }
2404
+ this.receivedCommitments.set(partyId, comm);
2405
+ }
2406
+ const allCommitments = Array.from(this.receivedCommitments.values());
2407
+ const { R } = combineNonceCommitments(allCommitments);
2408
+ const { r } = computeR(R);
2409
+ this.r = r;
2410
+ this.state.round = "partial_signature";
2411
+ }
2412
+ async runPartialSignaturePhase() {
2413
+ if (!this.state || !this.nonceShare || this.r === null) {
2414
+ throw new SDKError("State not initialized", "STATE_ERROR");
2415
+ }
2416
+ const messageHashBigInt = parseMessageHash(this.state.messageHash);
2417
+ const keyShareBigInt = BigInt(`0x${this.keyShare.privateShare}`);
2418
+ const partial = computePartialSignature(
2419
+ this.keyShare.partyId,
2420
+ keyShareBigInt,
2421
+ this.nonceShare.k,
2422
+ this.nonceShare.gamma,
2423
+ messageHashBigInt,
2424
+ this.r,
2425
+ this.state.participatingParties
2426
+ );
2427
+ await this.apiClient.submitPartialSignature(
2428
+ this.state.sessionId,
2429
+ this.keyShare.partyId,
2430
+ {
2431
+ r: this.r.toString(16).padStart(64, "0"),
2432
+ s: partial.sigma.toString(16).padStart(64, "0"),
2433
+ publicShare: partial.publicShare,
2434
+ nonceCommitment: partial.nonceCommitment
2435
+ }
2436
+ );
2437
+ this.state.partialSignatures.set(this.keyShare.partyId, {
2438
+ partyId: this.keyShare.partyId,
2439
+ r: this.r.toString(16).padStart(64, "0"),
2440
+ s: partial.sigma.toString(16).padStart(64, "0"),
2441
+ publicShare: partial.publicShare,
2442
+ nonceCommitment: partial.nonceCommitment
2443
+ });
2444
+ const otherPartials = await this.waitForPartialSignatures();
2445
+ await this.verifyOtherPartials(otherPartials, messageHashBigInt);
2446
+ this.state.round = "complete";
2447
+ }
2448
+ async waitForPartialSignatures() {
2449
+ const startTime = Date.now();
2450
+ const partials = /* @__PURE__ */ new Map();
2451
+ while (Date.now() - startTime < this.timeout) {
2452
+ const result = await this.apiClient.getPartialSignatures(
2453
+ this.state?.sessionId ?? ""
2454
+ );
2455
+ for (const p of result.partials) {
2456
+ if (p.partyId !== this.keyShare.partyId && !partials.has(p.partyId)) {
2457
+ let sigma;
2458
+ try {
2459
+ if (!/^[0-9a-fA-F]{1,64}$/.test(p.s)) {
2460
+ throw new SDKError(
2461
+ `Invalid sigma hex from party ${p.partyId}`,
2462
+ "INVALID_PARTIAL_FORMAT"
2463
+ );
2464
+ }
2465
+ sigma = BigInt(`0x${p.s}`);
2466
+ } catch (e) {
2467
+ if (e instanceof SDKError) throw e;
2468
+ throw new SDKError(
2469
+ `Failed to parse sigma from party ${p.partyId}`,
2470
+ "INVALID_PARTIAL_FORMAT"
2471
+ );
2472
+ }
2473
+ partials.set(p.partyId, {
2474
+ partyId: p.partyId,
2475
+ sigma,
2476
+ publicShare: p.publicShare,
2477
+ nonceCommitment: p.nonceCommitment
2478
+ });
2479
+ }
2480
+ }
2481
+ const expectedCount = (this.state?.participatingParties.length ?? 1) - 1;
2482
+ if (result.ready || partials.size >= expectedCount) {
2483
+ return partials;
2484
+ }
2485
+ await this.delay(500);
2486
+ }
2487
+ throw new SDKError(
2488
+ "Timeout waiting for partial signatures",
2489
+ "PARTIAL_SIGNATURE_TIMEOUT"
2490
+ );
2491
+ }
2492
+ async verifyOtherPartials(partials, messageHash) {
2493
+ for (const [partyId, partial] of partials) {
2494
+ const expectedNonceCommitment = this.receivedCommitments.get(partyId);
2495
+ if (!expectedNonceCommitment) {
2496
+ throw new SDKError(
2497
+ `Missing nonce commitment for party ${partyId}`,
2498
+ "MISSING_NONCE_COMMITMENT"
2499
+ );
2500
+ }
2501
+ const expectedPublicShare = this.expectedPublicShares.get(partyId);
2502
+ if (!expectedPublicShare) {
2503
+ throw new SDKError(
2504
+ `Missing expected public share for party ${partyId}. Public shares from DKG must be provided via partyPublicShares config.`,
2505
+ "MISSING_PUBLIC_SHARE"
2506
+ );
2507
+ }
2508
+ const isValid = verifyPartialSignature(
2509
+ partial,
2510
+ expectedPublicShare,
2511
+ expectedNonceCommitment.E,
2512
+ this.r,
2513
+ messageHash,
2514
+ this.state?.participatingParties ?? []
2515
+ );
2516
+ if (!isValid) {
2517
+ throw new SDKError(
2518
+ `Invalid partial signature from party ${partyId}`,
2519
+ "INVALID_PARTIAL_SIGNATURE"
2520
+ );
2521
+ }
2522
+ this.state?.partialSignatures.set(partyId, {
2523
+ partyId,
2524
+ r: this.r?.toString(16).padStart(64, "0") ?? "",
2525
+ s: partial.sigma.toString(16).padStart(64, "0"),
2526
+ publicShare: partial.publicShare,
2527
+ nonceCommitment: partial.nonceCommitment
2528
+ });
2529
+ }
2530
+ }
2531
+ async completeProtocol() {
2532
+ if (!this.state || this.r === null) {
2533
+ throw new SDKError("Protocol not complete", "PROTOCOL_INCOMPLETE");
2534
+ }
2535
+ const result = await this.waitForSigningResult();
2536
+ if (!result.complete || !result.signature) {
2537
+ throw new SDKError("Signing not complete", "SIGNING_INCOMPLETE");
2538
+ }
2539
+ return {
2540
+ success: true,
2541
+ signature: result.signature
2542
+ };
2543
+ }
2544
+ async waitForNonceCommitments() {
2545
+ const startTime = Date.now();
2546
+ const commitments = /* @__PURE__ */ new Map();
2547
+ while (Date.now() - startTime < this.timeout) {
2548
+ const result = await this.apiClient.getNonceCommitments(
2549
+ this.state?.sessionId ?? ""
2550
+ );
2551
+ for (const [partyIdStr, commitmentStr] of Object.entries(
2552
+ result.commitments
2553
+ )) {
2554
+ const partyId = Number.parseInt(partyIdStr, 10);
2555
+ if (partyId !== this.keyShare.partyId && !commitments.has(partyId)) {
2556
+ commitments.set(partyId, JSON.parse(commitmentStr));
2557
+ }
2558
+ }
2559
+ if (result.ready) {
2560
+ return commitments;
2561
+ }
2562
+ const expectedCount = (this.state?.participatingParties.length ?? 1) - 1;
2563
+ if (commitments.size >= expectedCount) {
2564
+ return commitments;
2565
+ }
2566
+ await this.delay(500);
2567
+ }
2568
+ throw new SDKError(
2569
+ "Timeout waiting for nonce commitments",
2570
+ "NONCE_COMMITMENT_TIMEOUT"
2571
+ );
2572
+ }
2573
+ async waitForSigningResult() {
2574
+ const startTime = Date.now();
2575
+ while (Date.now() - startTime < this.timeout) {
2576
+ const result = await this.apiClient.getSigningResult(
2577
+ this.state?.sessionId ?? ""
2578
+ );
2579
+ if (result.complete && result.signature) {
2580
+ return result;
2581
+ }
2582
+ await this.delay(500);
2583
+ }
2584
+ throw new SDKError(
2585
+ "Timeout waiting for signing result",
2586
+ "SIGNING_RESULT_TIMEOUT"
2587
+ );
2588
+ }
2589
+ delay(ms) {
2590
+ return new Promise((resolve) => setTimeout(resolve, ms));
2591
+ }
2592
+ cleanup() {
2593
+ this.state = null;
2594
+ this.nonceShare = null;
2595
+ this.receivedCommitments.clear();
2596
+ this.expectedPublicShares.clear();
2597
+ this.r = null;
2598
+ }
2599
+ };
2600
+ function deriveEOAAddress(publicKey) {
2601
+ let pubKeyHex = publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey;
2602
+ if (pubKeyHex.startsWith("04")) {
2603
+ pubKeyHex = pubKeyHex.slice(2);
2604
+ }
2605
+ if (pubKeyHex.length !== 128) {
2606
+ throw new Error(
2607
+ `Invalid public key length: expected 128 hex chars (64 bytes), got ${pubKeyHex.length}`
2608
+ );
2609
+ }
2610
+ const pubKeyBytes = utils.hexToBytes(pubKeyHex);
2611
+ const hash = sha3.keccak_256(pubKeyBytes);
2612
+ const addressBytes = hash.slice(-20);
2613
+ return `0x${utils.bytesToHex(addressBytes)}`;
2614
+ }
2615
+ function checksumAddress(address) {
2616
+ const addr = address.toLowerCase().replace("0x", "");
2617
+ const hash = utils.bytesToHex(sha3.keccak_256(new TextEncoder().encode(addr)));
2618
+ let checksummed = "0x";
2619
+ for (let i = 0; i < 40; i++) {
2620
+ if (Number.parseInt(hash[i], 16) >= 8) {
2621
+ checksummed += addr[i].toUpperCase();
2622
+ } else {
2623
+ checksummed += addr[i];
2624
+ }
2625
+ }
2626
+ return checksummed;
2627
+ }
2628
+
2629
+ // src/wallet/smart-wallet.ts
2630
+ function stripHexPrefix(value) {
2631
+ return value.startsWith("0x") ? value.slice(2) : value;
2632
+ }
2633
+ var DEFAULT_ENTRY_POINT = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
2634
+ var DEFAULT_FACTORY = "0x9406Cc6185a346906296840746125a0E44976454";
2635
+ var GET_ADDRESS_SELECTOR = "8cb84e18";
2636
+ var SmartWallet = class {
2637
+ constructor(config) {
2638
+ this._smartWalletAddress = null;
2639
+ this._isDeployed = null;
2640
+ this._cachedNonce = null;
2641
+ this.apiClient = config.apiClient;
2642
+ this.keyShare = config.keyShare;
2643
+ this.partyPublicShares = config.partyPublicShares;
2644
+ this.publicKey = config.publicKey;
2645
+ this.chainId = config.chainId;
2646
+ this.rpcConnection = config.rpcConnection;
2647
+ this.bundlerUrl = config.bundlerUrl;
2648
+ this.entryPointAddress = config.entryPointAddress ?? DEFAULT_ENTRY_POINT;
2649
+ this.factoryAddress = config.factoryAddress ?? DEFAULT_FACTORY;
2650
+ this.paymasterUrl = config.paymasterUrl;
2651
+ this._eoaAddress = deriveEOAAddress(this.publicKey);
2652
+ }
2653
+ get eoaAddress() {
2654
+ return checksumAddress(this._eoaAddress);
2655
+ }
2656
+ /**
2657
+ * @deprecated Use getSmartWalletAddress() instead.
2658
+ */
2659
+ get smartWalletAddress() {
2660
+ if (this._smartWalletAddress) {
2661
+ return checksumAddress(this._smartWalletAddress);
2662
+ }
2663
+ throw new Error(
2664
+ "SmartWallet.smartWalletAddress is deprecated. Use 'await wallet.getSmartWalletAddress()' instead."
2665
+ );
2666
+ }
2667
+ async getSmartWalletAddress() {
2668
+ if (this._smartWalletAddress) {
2669
+ return checksumAddress(this._smartWalletAddress);
2670
+ }
2671
+ const ownerPadded = this._eoaAddress.slice(2).padStart(64, "0");
2672
+ const saltPadded = "0".padStart(64, "0");
2673
+ const result = await this.rpcConnection.call("eth_call", [
2674
+ {
2675
+ to: this.factoryAddress,
2676
+ data: `0x${GET_ADDRESS_SELECTOR}${ownerPadded}${saltPadded}`
2677
+ },
2678
+ "latest"
2679
+ ]);
2680
+ this._smartWalletAddress = `0x${result.slice(-40)}`;
2681
+ return checksumAddress(this._smartWalletAddress);
2682
+ }
2683
+ async getWalletInfo() {
2684
+ return {
2685
+ eoaAddress: this.eoaAddress,
2686
+ smartWalletAddress: await this.getSmartWalletAddress(),
2687
+ publicKey: this.publicKey,
2688
+ chainId: this.chainId
2689
+ };
2690
+ }
2691
+ async buildUserOperation(transactions) {
2692
+ const txArray = Array.isArray(transactions) ? transactions : [transactions];
2693
+ const callData = this.encodeExecuteBatch(txArray);
2694
+ const smartWalletAddress = await this.getSmartWalletAddress();
2695
+ const nonce = await this.getNonce();
2696
+ const isDeployed = await this.isDeployed();
2697
+ const initCode = isDeployed ? "0x" : this.getInitCode();
2698
+ const feeData = await this.getFeeData();
2699
+ const userOp = {
2700
+ sender: smartWalletAddress,
2701
+ nonce,
2702
+ initCode,
2703
+ callData,
2704
+ callGasLimit: 200000n,
2705
+ verificationGasLimit: isDeployed ? 100000n : 400000n,
2706
+ preVerificationGas: 50000n,
2707
+ maxFeePerGas: feeData.maxFeePerGas,
2708
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
2709
+ paymasterAndData: "0x",
2710
+ signature: "0x"
2711
+ };
2712
+ if (this.paymasterUrl) {
2713
+ const paymasterData = await this.getPaymasterData(userOp);
2714
+ userOp.paymasterAndData = paymasterData;
2715
+ }
2716
+ return userOp;
2717
+ }
2718
+ async signUserOperation(userOp) {
2719
+ const userOpHash = this.computeUserOpHash(userOp);
2720
+ const signingClient = new SigningClient({
2721
+ apiClient: this.apiClient,
2722
+ keyShare: this.keyShare,
2723
+ partyPublicShares: this.partyPublicShares
2724
+ });
2725
+ const result = await signingClient.sign({
2726
+ messageHash: userOpHash,
2727
+ messageType: "transaction"
2728
+ });
2729
+ if (!result.success || !result.signature) {
2730
+ throw new SDKError(result.error ?? "Signing failed", "SIGNING_FAILED");
2731
+ }
2732
+ return {
2733
+ ...userOp,
2734
+ signature: result.signature.fullSignature
2735
+ };
2736
+ }
2737
+ async sendUserOperation(userOp) {
2738
+ const signedUserOp = userOp.signature === "0x" ? await this.signUserOperation(userOp) : userOp;
2739
+ const userOpHex = this.userOpToHex(signedUserOp);
2740
+ const response = await fetch(this.bundlerUrl, {
2741
+ method: "POST",
2742
+ headers: { "Content-Type": "application/json" },
2743
+ body: JSON.stringify({
2744
+ jsonrpc: "2.0",
2745
+ id: 1,
2746
+ method: "eth_sendUserOperation",
2747
+ params: [userOpHex, this.entryPointAddress]
2748
+ })
2749
+ });
2750
+ const data = await response.json();
2751
+ if (data.error) {
2752
+ throw new SDKError(
2753
+ `Bundler error: ${data.error.message}`,
2754
+ "BUNDLER_ERROR"
2755
+ );
2756
+ }
2757
+ const userOpHash = data.result;
2758
+ return {
2759
+ userOpHash,
2760
+ wait: async () => {
2761
+ await this.waitForUserOperationReceipt(userOpHash);
2762
+ this._isDeployed = true;
2763
+ this._cachedNonce = null;
2764
+ }
2765
+ };
2766
+ }
2767
+ async waitForUserOperationReceipt(userOpHash) {
2768
+ const maxAttempts = 60;
2769
+ const intervalMs = 2e3;
2770
+ for (let i = 0; i < maxAttempts; i++) {
2771
+ const response = await fetch(this.bundlerUrl, {
2772
+ method: "POST",
2773
+ headers: { "Content-Type": "application/json" },
2774
+ body: JSON.stringify({
2775
+ jsonrpc: "2.0",
2776
+ id: 1,
2777
+ method: "eth_getUserOperationReceipt",
2778
+ params: [userOpHash]
2779
+ })
2780
+ });
2781
+ const data = await response.json();
2782
+ if (data.result) {
2783
+ return;
2784
+ }
2785
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
2786
+ }
2787
+ throw new SDKError("UserOperation receipt not found", "TIMEOUT");
2788
+ }
2789
+ userOpToHex(userOp) {
2790
+ return {
2791
+ sender: userOp.sender,
2792
+ nonce: `0x${userOp.nonce.toString(16)}`,
2793
+ initCode: userOp.initCode,
2794
+ callData: userOp.callData,
2795
+ callGasLimit: `0x${userOp.callGasLimit.toString(16)}`,
2796
+ verificationGasLimit: `0x${userOp.verificationGasLimit.toString(16)}`,
2797
+ preVerificationGas: `0x${userOp.preVerificationGas.toString(16)}`,
2798
+ maxFeePerGas: `0x${userOp.maxFeePerGas.toString(16)}`,
2799
+ maxPriorityFeePerGas: `0x${userOp.maxPriorityFeePerGas.toString(16)}`,
2800
+ paymasterAndData: userOp.paymasterAndData,
2801
+ signature: userOp.signature
2802
+ };
2803
+ }
2804
+ async signMessage(message) {
2805
+ const messageBytes = typeof message === "string" ? utils.utf8ToBytes(message) : message;
2806
+ const prefix = utils.utf8ToBytes(
2807
+ `Ethereum Signed Message:
2808
+ ${messageBytes.length}`
2809
+ );
2810
+ const prefixedMessage = new Uint8Array(prefix.length + messageBytes.length);
2811
+ prefixedMessage.set(prefix);
2812
+ prefixedMessage.set(messageBytes, prefix.length);
2813
+ const messageHash = `0x${utils.bytesToHex(sha3.keccak_256(prefixedMessage))}`;
2814
+ const signingClient = new SigningClient({
2815
+ apiClient: this.apiClient,
2816
+ keyShare: this.keyShare,
2817
+ partyPublicShares: this.partyPublicShares
2818
+ });
2819
+ const result = await signingClient.sign({
2820
+ messageHash,
2821
+ messageType: "message"
2822
+ });
2823
+ if (!result.success || !result.signature) {
2824
+ throw new SDKError(
2825
+ result.error ?? "Message signing failed",
2826
+ "MESSAGE_SIGNING_FAILED"
2827
+ );
2828
+ }
2829
+ return result.signature;
2830
+ }
2831
+ async signTypedData(domain, types, primaryType, value) {
2832
+ const domainSeparator = this.hashTypedDataDomain(domain);
2833
+ const structHash = this.hashTypedDataStruct(types, primaryType, value);
2834
+ const messageHash = `0x${utils.bytesToHex(
2835
+ sha3.keccak_256(
2836
+ utils.hexToBytes(`1901${domainSeparator.slice(2)}${structHash.slice(2)}`)
2837
+ )
2838
+ )}`;
2839
+ const signingClient = new SigningClient({
2840
+ apiClient: this.apiClient,
2841
+ keyShare: this.keyShare,
2842
+ partyPublicShares: this.partyPublicShares
2843
+ });
2844
+ const result = await signingClient.sign({
2845
+ messageHash,
2846
+ messageType: "typed_data"
2847
+ });
2848
+ if (!result.success || !result.signature) {
2849
+ throw new SDKError(
2850
+ result.error ?? "Typed data signing failed",
2851
+ "TYPED_DATA_SIGNING_FAILED"
2852
+ );
2853
+ }
2854
+ return result.signature;
2855
+ }
2856
+ computeUserOpHash(userOp) {
2857
+ const packed = this.packUserOp(userOp);
2858
+ const userOpHash = sha3.keccak_256(packed);
2859
+ const finalHash = sha3.keccak_256(
2860
+ utils.hexToBytes(
2861
+ utils.bytesToHex(userOpHash) + this.entryPointAddress.slice(2).toLowerCase().padStart(64, "0") + this.chainId.toString(16).padStart(64, "0")
2862
+ )
2863
+ );
2864
+ return `0x${utils.bytesToHex(finalHash)}`;
2865
+ }
2866
+ packUserOp(userOp) {
2867
+ const initCodeHash = sha3.keccak_256(utils.hexToBytes(userOp.initCode.slice(2) || ""));
2868
+ const callDataHash = sha3.keccak_256(utils.hexToBytes(userOp.callData.slice(2) || ""));
2869
+ const paymasterAndDataHash = sha3.keccak_256(
2870
+ utils.hexToBytes(userOp.paymasterAndData.slice(2) || "")
2871
+ );
2872
+ const packed = userOp.sender.slice(2).toLowerCase().padStart(64, "0") + userOp.nonce.toString(16).padStart(64, "0") + utils.bytesToHex(initCodeHash) + utils.bytesToHex(callDataHash) + userOp.callGasLimit.toString(16).padStart(64, "0") + userOp.verificationGasLimit.toString(16).padStart(64, "0") + userOp.preVerificationGas.toString(16).padStart(64, "0") + userOp.maxFeePerGas.toString(16).padStart(64, "0") + userOp.maxPriorityFeePerGas.toString(16).padStart(64, "0") + utils.bytesToHex(paymasterAndDataHash);
2873
+ return utils.hexToBytes(packed);
2874
+ }
2875
+ encodeExecuteBatch(transactions) {
2876
+ if (transactions.length === 1) {
2877
+ const tx = transactions[0];
2878
+ const selector = "b61d27f6";
2879
+ const to = tx.to.slice(2).toLowerCase().padStart(64, "0");
2880
+ const value = (tx.value ?? 0n).toString(16).padStart(64, "0");
2881
+ const dataOffset = "60".padStart(64, "0");
2882
+ const data = tx.data?.slice(2) ?? "";
2883
+ const dataLength = (data.length / 2).toString(16).padStart(64, "0");
2884
+ return `0x${selector}${to}${value}${dataOffset}${dataLength}${data}`;
2885
+ }
2886
+ const n = transactions.length;
2887
+ const destArraySize = 32 + n * 32;
2888
+ const valueArraySize = 32 + n * 32;
2889
+ const destOffset = 96;
2890
+ const valueOffset = destOffset + destArraySize;
2891
+ const funcOffset = valueOffset + valueArraySize;
2892
+ let encoded = "18dfb3c7";
2893
+ encoded += destOffset.toString(16).padStart(64, "0");
2894
+ encoded += valueOffset.toString(16).padStart(64, "0");
2895
+ encoded += funcOffset.toString(16).padStart(64, "0");
2896
+ encoded += n.toString(16).padStart(64, "0");
2897
+ for (const tx of transactions) {
2898
+ encoded += tx.to.slice(2).toLowerCase().padStart(64, "0");
2899
+ }
2900
+ encoded += n.toString(16).padStart(64, "0");
2901
+ for (const tx of transactions) {
2902
+ encoded += (tx.value ?? 0n).toString(16).padStart(64, "0");
2903
+ }
2904
+ const funcDatas = transactions.map((tx) => {
2905
+ const data = tx.data ?? "0x";
2906
+ return data.startsWith("0x") ? data.slice(2) : data;
2907
+ });
2908
+ const funcElementOffsets = [];
2909
+ let currentOffset = 32 + n * 32;
2910
+ for (const funcData of funcDatas) {
2911
+ funcElementOffsets.push(currentOffset);
2912
+ const dataLen = funcData.length / 2;
2913
+ const paddedLen = Math.ceil(dataLen / 32) * 32;
2914
+ currentOffset += 32 + paddedLen;
2915
+ }
2916
+ encoded += n.toString(16).padStart(64, "0");
2917
+ for (const offset of funcElementOffsets) {
2918
+ encoded += offset.toString(16).padStart(64, "0");
2919
+ }
2920
+ for (const funcData of funcDatas) {
2921
+ const dataLen = funcData.length / 2;
2922
+ encoded += dataLen.toString(16).padStart(64, "0");
2923
+ if (funcData.length > 0) {
2924
+ const paddedLen = Math.ceil(dataLen / 32) * 32;
2925
+ encoded += funcData.padEnd(paddedLen * 2, "0");
2926
+ }
2927
+ }
2928
+ return `0x${encoded}`;
2929
+ }
2930
+ getInitCode() {
2931
+ const selector = "5fbfb9cf";
2932
+ const owner = this._eoaAddress.slice(2).toLowerCase().padStart(64, "0");
2933
+ const salt = "0".padStart(64, "0");
2934
+ return this.factoryAddress.toLowerCase() + selector + owner + salt;
2935
+ }
2936
+ async getNonce() {
2937
+ const isDeployed = await this.isDeployed();
2938
+ if (!isDeployed) {
2939
+ return 0n;
2940
+ }
2941
+ if (this._cachedNonce !== null) {
2942
+ return this._cachedNonce;
2943
+ }
2944
+ const smartWalletAddress = await this.getSmartWalletAddress();
2945
+ const nonceKey = 0n;
2946
+ const nonceData = await this.rpcConnection.call("eth_call", [
2947
+ {
2948
+ to: this.entryPointAddress,
2949
+ data: `0x35567e1a${smartWalletAddress.slice(2).padStart(64, "0")}${nonceKey.toString(16).padStart(64, "0")}`
2950
+ },
2951
+ "latest"
2952
+ ]);
2953
+ const nonce = BigInt(nonceData);
2954
+ this._cachedNonce = nonce;
2955
+ return nonce;
2956
+ }
2957
+ async isDeployed() {
2958
+ if (this._isDeployed !== null) {
2959
+ return this._isDeployed;
2960
+ }
2961
+ try {
2962
+ const smartWalletAddress = await this.getSmartWalletAddress();
2963
+ const code = await this.rpcConnection.getCode(smartWalletAddress);
2964
+ this._isDeployed = code !== "0x" && code.length > 2;
2965
+ return this._isDeployed;
2966
+ } catch {
2967
+ return false;
2968
+ }
2969
+ }
2970
+ async getFeeData() {
2971
+ try {
2972
+ const gasPrice = await this.rpcConnection.getGasPrice();
2973
+ return {
2974
+ maxFeePerGas: gasPrice * 2n,
2975
+ maxPriorityFeePerGas: gasPrice / 10n
2976
+ };
2977
+ } catch {
2978
+ return {
2979
+ maxFeePerGas: 1000000000n,
2980
+ maxPriorityFeePerGas: 1000000000n
2981
+ };
2982
+ }
2983
+ }
2984
+ async getPaymasterData(userOp) {
2985
+ if (!this.paymasterUrl) {
2986
+ return "0x";
2987
+ }
2988
+ try {
2989
+ const userOpHex = this.userOpToHex(userOp);
2990
+ const response = await fetch(this.paymasterUrl, {
2991
+ method: "POST",
2992
+ headers: { "Content-Type": "application/json" },
2993
+ body: JSON.stringify({
2994
+ jsonrpc: "2.0",
2995
+ id: 1,
2996
+ method: "pm_sponsorUserOperation",
2997
+ params: [userOpHex, this.entryPointAddress, {}]
2998
+ })
2999
+ });
3000
+ const data = await response.json();
3001
+ if (data.error || !data.result?.paymasterAndData) {
3002
+ return "0x";
3003
+ }
3004
+ return data.result.paymasterAndData;
3005
+ } catch {
3006
+ return "0x";
3007
+ }
3008
+ }
3009
+ hashTypedDataDomain(domain) {
3010
+ const domainFields = [];
3011
+ let domainValues = "";
3012
+ if (domain.name !== void 0) {
3013
+ domainFields.push({ name: "name", type: "string" });
3014
+ domainValues += utils.bytesToHex(
3015
+ sha3.keccak_256(utils.utf8ToBytes(domain.name))
3016
+ );
3017
+ }
3018
+ if (domain.version !== void 0) {
3019
+ domainFields.push({ name: "version", type: "string" });
3020
+ domainValues += utils.bytesToHex(
3021
+ sha3.keccak_256(utils.utf8ToBytes(domain.version))
3022
+ );
3023
+ }
3024
+ if (domain.chainId !== void 0) {
3025
+ domainFields.push({ name: "chainId", type: "uint256" });
3026
+ domainValues += BigInt(domain.chainId).toString(16).padStart(64, "0");
3027
+ }
3028
+ if (domain.verifyingContract !== void 0) {
3029
+ domainFields.push({ name: "verifyingContract", type: "address" });
3030
+ domainValues += stripHexPrefix(domain.verifyingContract).toLowerCase().padStart(64, "0");
3031
+ }
3032
+ if (domain.salt !== void 0) {
3033
+ domainFields.push({ name: "salt", type: "bytes32" });
3034
+ domainValues += stripHexPrefix(domain.salt).padStart(64, "0");
3035
+ }
3036
+ const domainTypeString = this.formatType("EIP712Domain", domainFields);
3037
+ const domainTypeHash = `0x${utils.bytesToHex(sha3.keccak_256(utils.utf8ToBytes(domainTypeString)))}`;
3038
+ return `0x${utils.bytesToHex(sha3.keccak_256(utils.hexToBytes(domainTypeHash.slice(2) + domainValues)))}`;
3039
+ }
3040
+ hashTypedDataStruct(types, primaryType, value) {
3041
+ return this.hashStruct(primaryType, types, value);
3042
+ }
3043
+ encodeType(typeName, types) {
3044
+ const fields = types[typeName];
3045
+ if (!fields) {
3046
+ throw new SDKError(`Unknown type: ${typeName}`, "INVALID_TYPE");
3047
+ }
3048
+ const deps = this.findTypeDependencies(typeName, types, /* @__PURE__ */ new Set());
3049
+ deps.delete(typeName);
3050
+ const sortedDeps = Array.from(deps).sort();
3051
+ let result = this.formatType(typeName, fields);
3052
+ for (const dep of sortedDeps) {
3053
+ result += this.formatType(dep, types[dep]);
3054
+ }
3055
+ return result;
3056
+ }
3057
+ formatType(typeName, fields) {
3058
+ return `${typeName}(${fields.map((f) => `${f.type} ${f.name}`).join(",")})`;
3059
+ }
3060
+ findTypeDependencies(typeName, types, found) {
3061
+ if (found.has(typeName)) return found;
3062
+ const fields = types[typeName];
3063
+ if (!fields) return found;
3064
+ found.add(typeName);
3065
+ for (const field of fields) {
3066
+ let baseType = field.type;
3067
+ if (baseType.endsWith("[]")) {
3068
+ baseType = baseType.slice(0, -2);
3069
+ }
3070
+ if (types[baseType]) {
3071
+ this.findTypeDependencies(baseType, types, found);
3072
+ }
3073
+ }
3074
+ return found;
3075
+ }
3076
+ hashType(typeName, types) {
3077
+ const encodedType = this.encodeType(typeName, types);
3078
+ return `0x${utils.bytesToHex(sha3.keccak_256(utils.utf8ToBytes(encodedType)))}`;
3079
+ }
3080
+ hashStruct(typeName, types, value) {
3081
+ const fields = types[typeName];
3082
+ if (!fields) {
3083
+ throw new SDKError(`Unknown type: ${typeName}`, "INVALID_TYPE");
3084
+ }
3085
+ const typeHash = this.hashType(typeName, types);
3086
+ let encodedValues = "";
3087
+ for (const field of fields) {
3088
+ const fieldValue = value[field.name];
3089
+ encodedValues += this.encodeField(field.type, fieldValue, types);
3090
+ }
3091
+ return `0x${utils.bytesToHex(sha3.keccak_256(utils.hexToBytes(typeHash.slice(2) + encodedValues)))}`;
3092
+ }
3093
+ encodeField(type, value, types) {
3094
+ if (type === "string") {
3095
+ return utils.bytesToHex(sha3.keccak_256(utils.utf8ToBytes(value)));
3096
+ }
3097
+ if (type === "bytes") {
3098
+ const bytesValue = stripHexPrefix(value);
3099
+ return utils.bytesToHex(sha3.keccak_256(utils.hexToBytes(bytesValue)));
3100
+ }
3101
+ if (type === "bool") {
3102
+ return (value ? 1n : 0n).toString(16).padStart(64, "0");
3103
+ }
3104
+ if (type === "address") {
3105
+ return stripHexPrefix(value).toLowerCase().padStart(64, "0");
3106
+ }
3107
+ if (type.startsWith("uint") || type.startsWith("int")) {
3108
+ const n = BigInt(value);
3109
+ if (type.startsWith("int") && n < 0n) {
3110
+ return ((1n << 256n) + n).toString(16).padStart(64, "0");
3111
+ }
3112
+ return n.toString(16).padStart(64, "0");
3113
+ }
3114
+ if (type.startsWith("bytes")) {
3115
+ const bytesValue = stripHexPrefix(value);
3116
+ return bytesValue.padEnd(64, "0");
3117
+ }
3118
+ if (types[type]) {
3119
+ return this.hashStruct(
3120
+ type,
3121
+ types,
3122
+ value
3123
+ ).slice(2);
3124
+ }
3125
+ if (type.endsWith("[]")) {
3126
+ const arrayType = type.slice(0, -2);
3127
+ const arrayValue = value;
3128
+ const encodedItems = arrayValue.map(
3129
+ (item) => this.encodeField(arrayType, item, types)
3130
+ );
3131
+ return utils.bytesToHex(sha3.keccak_256(utils.hexToBytes(encodedItems.join(""))));
3132
+ }
3133
+ throw new SDKError(`Unsupported type: ${type}`, "UNSUPPORTED_TYPE");
3134
+ }
3135
+ };
3136
+ function createSmartWallet(config) {
3137
+ return new SmartWallet(config);
3138
+ }
3139
+
3140
+ // src/nero-sdk.ts
3141
+ var NeroMpcSDK = class {
3142
+ constructor(config) {
3143
+ this.wsClient = null;
3144
+ this.keyManager = null;
3145
+ this.deviceKey = null;
3146
+ this._user = null;
3147
+ this._wallet = null;
3148
+ this._publicKey = null;
3149
+ this._partyPublicShares = /* @__PURE__ */ new Map();
3150
+ this._provider = null;
3151
+ this._connectionStatus = "disconnected";
3152
+ this._customChains = /* @__PURE__ */ new Map();
3153
+ this._cachedWalletInfo = null;
3154
+ this.config = {
3155
+ chainId: 689,
3156
+ storagePrefix: "nero",
3157
+ autoConnect: true,
3158
+ ...config
3159
+ };
3160
+ this._chainId = this.config.chainId;
3161
+ this.apiClient = new APIClient(this.config);
3162
+ this.chainManager = new ChainManager(this._chainId);
3163
+ if (this.config.wsUrl) {
3164
+ this.wsClient = new WebSocketClient(this.config.wsUrl);
3165
+ }
3166
+ }
3167
+ get isAuthenticated() {
3168
+ return this._user !== null && this.apiClient.getTokens() !== null;
3169
+ }
3170
+ get hasWallet() {
3171
+ return this._wallet !== null;
3172
+ }
3173
+ get user() {
3174
+ return this._user;
3175
+ }
3176
+ get wallet() {
3177
+ return this._wallet;
3178
+ }
3179
+ get chainId() {
3180
+ return this._chainId;
3181
+ }
3182
+ get connected() {
3183
+ return this._connectionStatus === "connected";
3184
+ }
3185
+ get status() {
3186
+ return this._connectionStatus;
3187
+ }
3188
+ get provider() {
3189
+ return this._provider;
3190
+ }
3191
+ get state() {
3192
+ return {
3193
+ isAuthenticated: this.isAuthenticated,
3194
+ isInitialized: this.keyManager !== null,
3195
+ hasWallet: this.hasWallet,
3196
+ user: this._user,
3197
+ walletInfo: this._cachedWalletInfo,
3198
+ chainId: this._chainId,
3199
+ isConnected: this.connected
3200
+ };
3201
+ }
3202
+ async getWalletInfo() {
3203
+ if (!this._wallet) return null;
3204
+ this._cachedWalletInfo = await this._wallet.getWalletInfo();
3205
+ return this._cachedWalletInfo;
3206
+ }
3207
+ async initialize() {
3208
+ this.deviceKey = this.loadOrGenerateDeviceKey();
3209
+ this.keyManager = new ClientKeyManager(this.deviceKey, {
3210
+ storagePrefix: this.config.storagePrefix
3211
+ });
3212
+ const storedTokens = this.loadStoredTokens();
3213
+ if (storedTokens) {
3214
+ this.apiClient.setTokens(storedTokens);
3215
+ try {
3216
+ this._user = await this.apiClient.getCurrentUser();
3217
+ await this.initializeWallet();
3218
+ } catch {
3219
+ this.apiClient.clearTokens();
3220
+ this.clearStoredTokens();
3221
+ }
3222
+ }
3223
+ }
3224
+ async getOAuthUrl(provider, redirectUri) {
3225
+ return this.apiClient.getOAuthUrl(provider, redirectUri);
3226
+ }
3227
+ async handleOAuthCallback(provider, code, state) {
3228
+ const fingerprint = this.getDeviceFingerprint();
3229
+ const result = await this.apiClient.handleOAuthCallback(
3230
+ provider,
3231
+ code,
3232
+ state,
3233
+ fingerprint
3234
+ );
3235
+ this._user = result.user;
3236
+ this.storeTokens(result.tokens);
3237
+ if (this.keyManager && this._user) {
3238
+ await this.keyManager.initialize(this._user.id);
3239
+ }
3240
+ if (!result.requiresDKG && result.wallet) {
3241
+ await this.initializeWallet();
3242
+ await this.connect();
3243
+ }
3244
+ return {
3245
+ user: result.user,
3246
+ requiresDKG: result.requiresDKG
3247
+ };
3248
+ }
3249
+ async loginWithGoogle(redirectUri) {
3250
+ const { url } = await this.getOAuthUrl(
3251
+ "google",
3252
+ redirectUri ?? window.location.href
3253
+ );
3254
+ window.location.href = url;
3255
+ }
3256
+ async loginWithGithub(redirectUri) {
3257
+ const { url } = await this.getOAuthUrl(
3258
+ "github",
3259
+ redirectUri ?? window.location.href
3260
+ );
3261
+ window.location.href = url;
3262
+ }
3263
+ async loginWithApple(redirectUri) {
3264
+ const { url } = await this.getOAuthUrl(
3265
+ "apple",
3266
+ redirectUri ?? window.location.href
3267
+ );
3268
+ window.location.href = url;
3269
+ }
3270
+ async generateWallet() {
3271
+ if (!this._user) {
3272
+ throw new SDKError("User not authenticated", "NOT_AUTHENTICATED");
3273
+ }
3274
+ if (!this.keyManager) {
3275
+ throw new SDKError("SDK not initialized", "NOT_INITIALIZED");
3276
+ }
3277
+ const dkgClient = new DKGClient({
3278
+ apiClient: this.apiClient,
3279
+ wsClient: this.wsClient ?? void 0
3280
+ });
3281
+ const result = await dkgClient.execute();
3282
+ if (!result.success) {
3283
+ throw new SDKError(result.error ?? "DKG failed", "DKG_FAILED");
3284
+ }
3285
+ const keyShare = dkgClient.getKeyShare();
3286
+ if (!keyShare) {
3287
+ throw new SDKError("Failed to get key share", "KEY_SHARE_ERROR");
3288
+ }
3289
+ await this.keyManager.storeKeyShare(keyShare);
3290
+ this._publicKey = result.publicKey;
3291
+ this._partyPublicShares = dkgClient.getPartyPublicShares();
3292
+ await this.keyManager.storePartyPublicShares(this._partyPublicShares);
3293
+ this._wallet = this.createSmartWallet(
3294
+ keyShare,
3295
+ this._partyPublicShares,
3296
+ this._publicKey
3297
+ );
3298
+ dkgClient.cleanup();
3299
+ await this.connect();
3300
+ this._cachedWalletInfo = await this._wallet.getWalletInfo();
3301
+ return this._cachedWalletInfo;
3302
+ }
3303
+ async logout() {
3304
+ try {
3305
+ await this.apiClient.logout();
3306
+ } catch {
3307
+ }
3308
+ this._user = null;
3309
+ this._wallet = null;
3310
+ this._publicKey = null;
3311
+ this._connectionStatus = "disconnected";
3312
+ this.apiClient.clearTokens();
3313
+ this.clearStoredTokens();
3314
+ if (this._provider) {
3315
+ this._provider.disconnect();
3316
+ }
3317
+ if (this.wsClient) {
3318
+ this.wsClient.disconnect();
3319
+ }
3320
+ }
3321
+ async connect() {
3322
+ if (!this._wallet) {
3323
+ throw new SDKError("Wallet not available", "NO_WALLET");
3324
+ }
3325
+ this._connectionStatus = "connecting";
3326
+ try {
3327
+ this._provider = new NeroProvider({
3328
+ chainId: this._chainId,
3329
+ getAccounts: () => this.getAccounts(),
3330
+ signMessage: (message) => this.signMessageInternal(message),
3331
+ signTypedData: (domain, types, primaryType, message) => this.signTypedDataInternal(domain, types, primaryType, message),
3332
+ sendTransaction: (tx) => this.sendTransactionInternal(tx),
3333
+ onChainChanged: (chainId) => this.handleChainChanged(chainId)
3334
+ });
3335
+ this._provider.connect();
3336
+ this._connectionStatus = "connected";
3337
+ return this._provider;
3338
+ } catch (error) {
3339
+ this._connectionStatus = "errored";
3340
+ throw error;
3341
+ }
3342
+ }
3343
+ async disconnect() {
3344
+ if (this._provider) {
3345
+ this._provider.disconnect();
3346
+ }
3347
+ this._connectionStatus = "disconnected";
3348
+ await this.logout();
3349
+ }
3350
+ getProvider() {
3351
+ return this._provider;
3352
+ }
3353
+ getUserInfo() {
3354
+ if (!this._user) return null;
3355
+ return {
3356
+ email: this._user.email,
3357
+ name: this._user.displayName,
3358
+ profileImage: this._user.profilePicture,
3359
+ verifier: "nero-mpc",
3360
+ verifierId: this._user.id,
3361
+ typeOfLogin: "social"
3362
+ };
3363
+ }
3364
+ async switchChain(chainId) {
3365
+ const config = this.getChainConfigForId(chainId);
3366
+ if (!config) {
3367
+ throw new SDKError(`Chain ${chainId} not supported`, "UNSUPPORTED_CHAIN");
3368
+ }
3369
+ this._chainId = chainId;
3370
+ await this.chainManager.switchChain(chainId);
3371
+ if (this._provider) {
3372
+ await this._provider.switchChain(chainId);
3373
+ }
3374
+ if (this._wallet && this.keyManager) {
3375
+ const keyShare = await this.keyManager.getKeyShare();
3376
+ if (keyShare) {
3377
+ this._wallet = this.createSmartWallet(
3378
+ keyShare,
3379
+ this._partyPublicShares,
3380
+ this._publicKey
3381
+ );
3382
+ this._cachedWalletInfo = await this._wallet.getWalletInfo();
3383
+ }
3384
+ }
3385
+ }
3386
+ addChain(config) {
3387
+ this._customChains.set(config.chainId, config);
3388
+ this.chainManager.addChain(config);
3389
+ if (this._provider) {
3390
+ this._provider.addChain(config);
3391
+ }
3392
+ }
3393
+ getChainConfig(chainId) {
3394
+ const targetChainId = chainId ?? this._chainId;
3395
+ return this.getChainConfigForId(targetChainId);
3396
+ }
3397
+ getSupportedChainIds() {
3398
+ const builtinIds = Array.from(BUILTIN_CHAINS.keys());
3399
+ const customIds = Array.from(this._customChains.keys());
3400
+ return [.../* @__PURE__ */ new Set([...builtinIds, ...customIds])];
3401
+ }
3402
+ getAccounts() {
3403
+ if (!this._wallet) return [];
3404
+ return [this._wallet.eoaAddress];
3405
+ }
3406
+ async signMessageInternal(message) {
3407
+ if (!this._wallet) {
3408
+ throw new SDKError("Wallet not available", "NO_WALLET");
3409
+ }
3410
+ const signature = await this._wallet.signMessage(message);
3411
+ return signature.fullSignature;
3412
+ }
3413
+ async signTypedDataInternal(domain, types, primaryType, message) {
3414
+ if (!this._wallet) {
3415
+ throw new SDKError("Wallet not available", "NO_WALLET");
3416
+ }
3417
+ const signature = await this._wallet.signTypedData(
3418
+ domain,
3419
+ types,
3420
+ primaryType,
3421
+ message
3422
+ );
3423
+ return signature.fullSignature;
3424
+ }
3425
+ async sendTransactionInternal(tx) {
3426
+ if (!this._wallet) {
3427
+ throw new SDKError("Wallet not available", "NO_WALLET");
3428
+ }
3429
+ const txRequest = tx;
3430
+ const userOp = await this._wallet.buildUserOperation({
3431
+ to: txRequest.to,
3432
+ value: txRequest.value ? BigInt(txRequest.value) : void 0,
3433
+ data: txRequest.data
3434
+ });
3435
+ const result = await this._wallet.sendUserOperation(userOp);
3436
+ return result.userOpHash;
3437
+ }
3438
+ handleChainChanged(chainId) {
3439
+ this._chainId = chainId;
3440
+ }
3441
+ getChainConfigForId(chainId) {
3442
+ return getChainConfig(chainId) ?? this._customChains.get(chainId);
3443
+ }
3444
+ createSmartWallet(keyShare, partyPublicShares, publicKey) {
3445
+ const chainConfig = this.getChainConfigForId(this._chainId);
3446
+ const rpcConnection = this.chainManager.getRpcConnection();
3447
+ const bundlerUrl = chainConfig?.bundlerUrl ?? `${this.config.backendUrl}/api/v1/bundler`;
3448
+ return new SmartWallet({
3449
+ apiClient: this.apiClient,
3450
+ keyShare,
3451
+ partyPublicShares,
3452
+ publicKey,
3453
+ chainId: this._chainId,
3454
+ rpcConnection,
3455
+ bundlerUrl,
3456
+ entryPointAddress: chainConfig?.entryPointAddress,
3457
+ factoryAddress: chainConfig?.simpleAccountFactoryAddress,
3458
+ paymasterUrl: chainConfig?.paymasterUrl
3459
+ });
3460
+ }
3461
+ async exportBackup(password) {
3462
+ if (!this.keyManager) {
3463
+ throw new SDKError("SDK not initialized", "NOT_INITIALIZED");
3464
+ }
3465
+ return this.keyManager.exportBackup(password);
3466
+ }
3467
+ async importBackup(backupString, password) {
3468
+ if (!this.keyManager || !this._user) {
3469
+ throw new SDKError("SDK not initialized", "NOT_INITIALIZED");
3470
+ }
3471
+ const keyShare = await this.keyManager.importBackup(backupString, password);
3472
+ await this.keyManager.storeKeyShare(keyShare);
3473
+ await this.initializeWallet();
3474
+ }
3475
+ async initializeWallet() {
3476
+ if (!this.keyManager || !this._user) {
3477
+ return;
3478
+ }
3479
+ const keyShare = await this.keyManager.getKeyShare();
3480
+ if (!keyShare) {
3481
+ return;
3482
+ }
3483
+ const storedPartyShares = await this.keyManager.getPartyPublicShares();
3484
+ if (!storedPartyShares) {
3485
+ return;
3486
+ }
3487
+ try {
3488
+ const walletInfo = await this.apiClient.getWalletInfo();
3489
+ this._publicKey = walletInfo.publicKey;
3490
+ this._partyPublicShares = storedPartyShares;
3491
+ this._wallet = this.createSmartWallet(
3492
+ keyShare,
3493
+ this._partyPublicShares,
3494
+ this._publicKey
3495
+ );
3496
+ this._cachedWalletInfo = await this._wallet.getWalletInfo();
3497
+ } catch {
3498
+ }
3499
+ }
3500
+ getDeviceFingerprint() {
3501
+ return {
3502
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown"
3503
+ };
3504
+ }
3505
+ loadOrGenerateDeviceKey() {
3506
+ const storageKey = `${this.config.storagePrefix}:device_key`;
3507
+ if (typeof localStorage !== "undefined") {
3508
+ const stored = localStorage.getItem(storageKey);
3509
+ if (stored) {
3510
+ return stored;
3511
+ }
3512
+ }
3513
+ const newKey = generateDeviceKey();
3514
+ if (typeof localStorage !== "undefined") {
3515
+ localStorage.setItem(storageKey, newKey);
3516
+ }
3517
+ return newKey;
3518
+ }
3519
+ storeTokens(tokens) {
3520
+ if (typeof localStorage !== "undefined") {
3521
+ localStorage.setItem(
3522
+ `${this.config.storagePrefix}:tokens`,
3523
+ JSON.stringify(tokens)
3524
+ );
3525
+ }
3526
+ }
3527
+ loadStoredTokens() {
3528
+ if (typeof localStorage === "undefined") {
3529
+ return null;
3530
+ }
3531
+ const stored = localStorage.getItem(`${this.config.storagePrefix}:tokens`);
3532
+ if (!stored) {
3533
+ return null;
3534
+ }
3535
+ try {
3536
+ return JSON.parse(stored);
3537
+ } catch {
3538
+ return null;
3539
+ }
3540
+ }
3541
+ clearStoredTokens() {
3542
+ if (typeof localStorage !== "undefined") {
3543
+ localStorage.removeItem(`${this.config.storagePrefix}:tokens`);
3544
+ }
3545
+ }
3546
+ };
3547
+ function createNeroSDK(config) {
3548
+ return new NeroMpcSDK(config);
3549
+ }
3550
+
3551
+ // src/aa/types.ts
3552
+ function userOpToHex(userOp) {
3553
+ return {
3554
+ sender: userOp.sender,
3555
+ nonce: `0x${userOp.nonce.toString(16)}`,
3556
+ initCode: userOp.initCode,
3557
+ callData: userOp.callData,
3558
+ callGasLimit: `0x${userOp.callGasLimit.toString(16)}`,
3559
+ verificationGasLimit: `0x${userOp.verificationGasLimit.toString(16)}`,
3560
+ preVerificationGas: `0x${userOp.preVerificationGas.toString(16)}`,
3561
+ maxFeePerGas: `0x${userOp.maxFeePerGas.toString(16)}`,
3562
+ maxPriorityFeePerGas: `0x${userOp.maxPriorityFeePerGas.toString(16)}`,
3563
+ paymasterAndData: userOp.paymasterAndData,
3564
+ signature: userOp.signature
3565
+ };
3566
+ }
3567
+
3568
+ // src/aa/bundler-client.ts
3569
+ var BundlerClient = class {
3570
+ constructor(config) {
3571
+ this.requestId = 0;
3572
+ this.bundlerUrl = config.bundlerUrl;
3573
+ this.entryPointAddress = config.entryPointAddress;
3574
+ }
3575
+ async sendUserOperation(userOp) {
3576
+ const userOpHex = userOpToHex(userOp);
3577
+ return this.call("eth_sendUserOperation", [
3578
+ userOpHex,
3579
+ this.entryPointAddress
3580
+ ]);
3581
+ }
3582
+ async estimateUserOperationGas(userOp) {
3583
+ const partialOpHex = {};
3584
+ if (userOp.sender) partialOpHex.sender = userOp.sender;
3585
+ if (userOp.nonce !== void 0)
3586
+ partialOpHex.nonce = `0x${userOp.nonce.toString(16)}`;
3587
+ if (userOp.initCode) partialOpHex.initCode = userOp.initCode;
3588
+ if (userOp.callData) partialOpHex.callData = userOp.callData;
3589
+ if (userOp.callGasLimit !== void 0)
3590
+ partialOpHex.callGasLimit = `0x${userOp.callGasLimit.toString(16)}`;
3591
+ if (userOp.verificationGasLimit !== void 0)
3592
+ partialOpHex.verificationGasLimit = `0x${userOp.verificationGasLimit.toString(16)}`;
3593
+ if (userOp.preVerificationGas !== void 0)
3594
+ partialOpHex.preVerificationGas = `0x${userOp.preVerificationGas.toString(16)}`;
3595
+ if (userOp.maxFeePerGas !== void 0)
3596
+ partialOpHex.maxFeePerGas = `0x${userOp.maxFeePerGas.toString(16)}`;
3597
+ if (userOp.maxPriorityFeePerGas !== void 0)
3598
+ partialOpHex.maxPriorityFeePerGas = `0x${userOp.maxPriorityFeePerGas.toString(16)}`;
3599
+ if (userOp.paymasterAndData)
3600
+ partialOpHex.paymasterAndData = userOp.paymasterAndData;
3601
+ if (userOp.signature) partialOpHex.signature = userOp.signature;
3602
+ const result = await this.call("eth_estimateUserOperationGas", [partialOpHex, this.entryPointAddress]);
3603
+ return {
3604
+ preVerificationGas: BigInt(result.preVerificationGas),
3605
+ verificationGasLimit: BigInt(result.verificationGasLimit),
3606
+ callGasLimit: BigInt(result.callGasLimit)
3607
+ };
3608
+ }
3609
+ async getUserOperationByHash(hash) {
3610
+ try {
3611
+ return await this.call(
3612
+ "eth_getUserOperationByHash",
3613
+ [hash]
3614
+ );
3615
+ } catch {
3616
+ return null;
3617
+ }
3618
+ }
3619
+ async getUserOperationReceipt(hash) {
3620
+ try {
3621
+ return await this.call(
3622
+ "eth_getUserOperationReceipt",
3623
+ [hash]
3624
+ );
3625
+ } catch {
3626
+ return null;
3627
+ }
3628
+ }
3629
+ async getSupportedEntryPoints() {
3630
+ return this.call("eth_supportedEntryPoints", []);
3631
+ }
3632
+ async getChainId() {
3633
+ const result = await this.call("eth_chainId", []);
3634
+ return Number.parseInt(result, 16);
3635
+ }
3636
+ async waitForUserOperationReceipt(hash, timeout = 6e4, interval = 2e3) {
3637
+ const startTime = Date.now();
3638
+ while (Date.now() - startTime < timeout) {
3639
+ const receipt = await this.getUserOperationReceipt(hash);
3640
+ if (receipt) {
3641
+ return receipt;
3642
+ }
3643
+ await new Promise((resolve) => setTimeout(resolve, interval));
3644
+ }
3645
+ throw new Error(`UserOperation ${hash} not confirmed within timeout`);
3646
+ }
3647
+ async call(method, params) {
3648
+ const response = await fetch(this.bundlerUrl, {
3649
+ method: "POST",
3650
+ headers: { "Content-Type": "application/json" },
3651
+ body: JSON.stringify({
3652
+ jsonrpc: "2.0",
3653
+ id: ++this.requestId,
3654
+ method,
3655
+ params
3656
+ })
3657
+ });
3658
+ if (!response.ok) {
3659
+ throw new Error(`Bundler request failed: ${response.status}`);
3660
+ }
3661
+ const data = await response.json();
3662
+ if (data.error) {
3663
+ throw new Error(
3664
+ `Bundler error: ${data.error.message} (code: ${data.error.code})`
3665
+ );
3666
+ }
3667
+ return data.result;
3668
+ }
3669
+ };
3670
+ function createBundlerClient(config) {
3671
+ return new BundlerClient(config);
3672
+ }
3673
+
3674
+ // src/aa/paymaster-client.ts
3675
+ var PaymasterClient = class {
3676
+ constructor(config) {
3677
+ this.requestId = 0;
3678
+ this.paymasterUrl = config.paymasterUrl;
3679
+ this.entryPointAddress = config.entryPointAddress;
3680
+ this.chainId = config.chainId;
3681
+ }
3682
+ async getPaymasterData(userOp, context) {
3683
+ const partialOpHex = this.partialUserOpToHex(userOp);
3684
+ const result = await this.call(
3685
+ "pm_sponsorUserOperation",
3686
+ [partialOpHex, this.entryPointAddress, context ?? {}]
3687
+ );
3688
+ return {
3689
+ paymasterAndData: result.paymasterAndData,
3690
+ preVerificationGas: result.preVerificationGas ? BigInt(result.preVerificationGas) : void 0,
3691
+ verificationGasLimit: result.verificationGasLimit ? BigInt(result.verificationGasLimit) : void 0,
3692
+ callGasLimit: result.callGasLimit ? BigInt(result.callGasLimit) : void 0
3693
+ };
3694
+ }
3695
+ async validatePaymasterUserOp(userOp) {
3696
+ const userOpHex = userOpToHex(userOp);
3697
+ try {
3698
+ const result = await this.call("pm_validatePaymasterUserOp", [userOpHex, this.entryPointAddress]);
3699
+ return {
3700
+ valid: result.valid,
3701
+ validAfter: result.validAfter ? BigInt(result.validAfter) : void 0,
3702
+ validUntil: result.validUntil ? BigInt(result.validUntil) : void 0
3703
+ };
3704
+ } catch {
3705
+ return { valid: false };
3706
+ }
3707
+ }
3708
+ async getSupportedTokens() {
3709
+ try {
3710
+ return await this.call("pm_supportedTokens", [this.chainId.toString()]);
3711
+ } catch {
3712
+ return [];
3713
+ }
3714
+ }
3715
+ async getTokenPaymasterData(userOp, tokenAddress) {
3716
+ return this.getPaymasterData(userOp, {
3717
+ mode: "erc20",
3718
+ token: tokenAddress
3719
+ });
3720
+ }
3721
+ partialUserOpToHex(userOp) {
3722
+ const result = {};
3723
+ if (userOp.sender) result.sender = userOp.sender;
3724
+ if (userOp.nonce !== void 0)
3725
+ result.nonce = `0x${userOp.nonce.toString(16)}`;
3726
+ if (userOp.initCode) result.initCode = userOp.initCode;
3727
+ if (userOp.callData) result.callData = userOp.callData;
3728
+ if (userOp.callGasLimit !== void 0)
3729
+ result.callGasLimit = `0x${userOp.callGasLimit.toString(16)}`;
3730
+ if (userOp.verificationGasLimit !== void 0)
3731
+ result.verificationGasLimit = `0x${userOp.verificationGasLimit.toString(16)}`;
3732
+ if (userOp.preVerificationGas !== void 0)
3733
+ result.preVerificationGas = `0x${userOp.preVerificationGas.toString(16)}`;
3734
+ if (userOp.maxFeePerGas !== void 0)
3735
+ result.maxFeePerGas = `0x${userOp.maxFeePerGas.toString(16)}`;
3736
+ if (userOp.maxPriorityFeePerGas !== void 0)
3737
+ result.maxPriorityFeePerGas = `0x${userOp.maxPriorityFeePerGas.toString(16)}`;
3738
+ if (userOp.paymasterAndData)
3739
+ result.paymasterAndData = userOp.paymasterAndData;
3740
+ if (userOp.signature) result.signature = userOp.signature;
3741
+ return result;
3742
+ }
3743
+ async call(method, params) {
3744
+ const response = await fetch(this.paymasterUrl, {
3745
+ method: "POST",
3746
+ headers: { "Content-Type": "application/json" },
3747
+ body: JSON.stringify({
3748
+ jsonrpc: "2.0",
3749
+ id: ++this.requestId,
3750
+ method,
3751
+ params
3752
+ })
3753
+ });
3754
+ if (!response.ok) {
3755
+ throw new Error(`Paymaster request failed: ${response.status}`);
3756
+ }
3757
+ const data = await response.json();
3758
+ if (data.error) {
3759
+ throw new Error(
3760
+ `Paymaster error: ${data.error.message} (code: ${data.error.code})`
3761
+ );
3762
+ }
3763
+ return data.result;
3764
+ }
3765
+ };
3766
+ function createPaymasterClient(config) {
3767
+ return new PaymasterClient(config);
3768
+ }
3769
+ var EXECUTE_SELECTOR = "b61d27f6";
3770
+ var EXECUTE_BATCH_SELECTOR = "18dfb3c7";
3771
+ var CREATE_ACCOUNT_SELECTOR = "5fbfb9cf";
3772
+ var GET_ADDRESS_SELECTOR2 = "8cb84e18";
3773
+ var SimpleAccount = class {
3774
+ constructor(config) {
3775
+ this._accountAddress = null;
3776
+ this._isDeployed = null;
3777
+ this._cachedNonce = null;
3778
+ this.ownerAddress = config.ownerAddress.toLowerCase();
3779
+ this.factoryAddress = config.factoryAddress.toLowerCase();
3780
+ this.entryPointAddress = config.entryPointAddress.toLowerCase();
3781
+ this.salt = config.salt ?? 0n;
3782
+ this.chainId = config.chainId;
3783
+ this.rpcConnection = config.rpcConnection;
3784
+ this.bundlerClient = new BundlerClient({
3785
+ bundlerUrl: config.bundlerUrl,
3786
+ entryPointAddress: config.entryPointAddress,
3787
+ chainId: config.chainId
3788
+ });
3789
+ this.paymasterClient = config.paymasterUrl ? new PaymasterClient({
3790
+ paymasterUrl: config.paymasterUrl,
3791
+ entryPointAddress: config.entryPointAddress,
3792
+ chainId: config.chainId
3793
+ }) : null;
3794
+ }
3795
+ /**
3796
+ * @deprecated Use getAccountAddress() instead. This sync getter is removed
3797
+ * because address derivation now requires an RPC call to the factory.
3798
+ */
3799
+ get accountAddress() {
3800
+ if (this._accountAddress) {
3801
+ return this._accountAddress;
3802
+ }
3803
+ throw new Error(
3804
+ "SimpleAccount.accountAddress is deprecated. Use 'await account.getAccountAddress()' instead. Address derivation now requires an RPC call to factory.getAddress()."
3805
+ );
3806
+ }
3807
+ async getAccountAddress() {
3808
+ if (this._accountAddress) {
3809
+ return this._accountAddress;
3810
+ }
3811
+ this._accountAddress = await this.fetchAccountAddressFromFactory();
3812
+ return this._accountAddress;
3813
+ }
3814
+ async isDeployed() {
3815
+ if (this._isDeployed !== null) {
3816
+ return this._isDeployed;
3817
+ }
3818
+ try {
3819
+ const code = await this.getAccountCode();
3820
+ this._isDeployed = code !== "0x" && code.length > 2;
3821
+ return this._isDeployed;
3822
+ } catch {
3823
+ return false;
3824
+ }
3825
+ }
3826
+ invalidateDeploymentCache() {
3827
+ this._isDeployed = null;
3828
+ }
3829
+ async buildUserOperation(transactions, options) {
3830
+ const txArray = Array.isArray(transactions) ? transactions : [transactions];
3831
+ const callData = this.encodeExecute(txArray);
3832
+ const accountAddress = await this.getAccountAddress();
3833
+ const isDeployed = await this.isDeployed();
3834
+ const initCode = isDeployed ? "0x" : this.getInitCode();
3835
+ const nonce = await this.getNonce();
3836
+ let userOp = {
3837
+ sender: accountAddress,
3838
+ nonce,
3839
+ initCode,
3840
+ callData,
3841
+ callGasLimit: 0n,
3842
+ verificationGasLimit: 0n,
3843
+ preVerificationGas: 0n,
3844
+ maxFeePerGas: 0n,
3845
+ maxPriorityFeePerGas: 0n,
3846
+ paymasterAndData: "0x",
3847
+ signature: this.getDummySignature()
3848
+ };
3849
+ const gasEstimate = await this.estimateGas(userOp);
3850
+ const feeData = await this.getFeeData();
3851
+ userOp = {
3852
+ ...userOp,
3853
+ callGasLimit: gasEstimate.callGasLimit,
3854
+ verificationGasLimit: gasEstimate.verificationGasLimit,
3855
+ preVerificationGas: gasEstimate.preVerificationGas,
3856
+ maxFeePerGas: feeData.maxFeePerGas,
3857
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
3858
+ };
3859
+ if (options?.usePaymaster && this.paymasterClient) {
3860
+ const paymasterData = await this.paymasterClient.getPaymasterData(
3861
+ userOp,
3862
+ options.paymasterContext
3863
+ );
3864
+ userOp.paymasterAndData = paymasterData.paymasterAndData;
3865
+ if (paymasterData.preVerificationGas) {
3866
+ userOp.preVerificationGas = paymasterData.preVerificationGas;
3867
+ }
3868
+ if (paymasterData.verificationGasLimit) {
3869
+ userOp.verificationGasLimit = paymasterData.verificationGasLimit;
3870
+ }
3871
+ if (paymasterData.callGasLimit) {
3872
+ userOp.callGasLimit = paymasterData.callGasLimit;
3873
+ }
3874
+ }
3875
+ userOp.signature = "0x";
3876
+ return userOp;
3877
+ }
3878
+ computeUserOpHash(userOp) {
3879
+ const packed = this.packUserOp(userOp);
3880
+ const userOpHash = sha3.keccak_256(packed);
3881
+ const finalHash = sha3.keccak_256(
3882
+ utils.hexToBytes(
3883
+ utils.bytesToHex(userOpHash) + this.entryPointAddress.slice(2).padStart(64, "0") + this.chainId.toString(16).padStart(64, "0")
3884
+ )
3885
+ );
3886
+ return `0x${utils.bytesToHex(finalHash)}`;
3887
+ }
3888
+ async sendUserOperation(userOp) {
3889
+ const userOpHash = await this.bundlerClient.sendUserOperation(userOp);
3890
+ return {
3891
+ userOpHash,
3892
+ wait: async () => {
3893
+ await this.bundlerClient.waitForUserOperationReceipt(userOpHash);
3894
+ this._isDeployed = true;
3895
+ this.invalidateNonceCache();
3896
+ }
3897
+ };
3898
+ }
3899
+ async fetchAccountAddressFromFactory() {
3900
+ const ownerPadded = this.ownerAddress.slice(2).padStart(64, "0");
3901
+ const saltPadded = this.salt.toString(16).padStart(64, "0");
3902
+ const result = await this.rpcConnection.call("eth_call", [
3903
+ {
3904
+ to: this.factoryAddress,
3905
+ data: `0x${GET_ADDRESS_SELECTOR2}${ownerPadded}${saltPadded}`
3906
+ },
3907
+ "latest"
3908
+ ]);
3909
+ return `0x${result.slice(-40)}`;
3910
+ }
3911
+ getInitCode() {
3912
+ const ownerPadded = this.ownerAddress.slice(2).padStart(64, "0");
3913
+ const saltPadded = this.salt.toString(16).padStart(64, "0");
3914
+ return this.factoryAddress + CREATE_ACCOUNT_SELECTOR + ownerPadded + saltPadded;
3915
+ }
3916
+ encodeExecute(transactions) {
3917
+ if (transactions.length === 1) {
3918
+ const tx = transactions[0];
3919
+ const to = tx.to.slice(2).toLowerCase().padStart(64, "0");
3920
+ const value = (tx.value ?? 0n).toString(16).padStart(64, "0");
3921
+ const dataOffset = "60".padStart(64, "0");
3922
+ const data = tx.data?.slice(2) ?? "";
3923
+ const dataLength = (data.length / 2).toString(16).padStart(64, "0");
3924
+ return `0x${EXECUTE_SELECTOR}${to}${value}${dataOffset}${dataLength}${data}`;
3925
+ }
3926
+ const n = transactions.length;
3927
+ const destArraySize = 32 + n * 32;
3928
+ const valueArraySize = 32 + n * 32;
3929
+ const destOffset = 96;
3930
+ const valueOffset = destOffset + destArraySize;
3931
+ const funcOffset = valueOffset + valueArraySize;
3932
+ let encoded = EXECUTE_BATCH_SELECTOR;
3933
+ encoded += destOffset.toString(16).padStart(64, "0");
3934
+ encoded += valueOffset.toString(16).padStart(64, "0");
3935
+ encoded += funcOffset.toString(16).padStart(64, "0");
3936
+ encoded += n.toString(16).padStart(64, "0");
3937
+ for (const tx of transactions) {
3938
+ encoded += tx.to.slice(2).toLowerCase().padStart(64, "0");
3939
+ }
3940
+ encoded += n.toString(16).padStart(64, "0");
3941
+ for (const tx of transactions) {
3942
+ encoded += (tx.value ?? 0n).toString(16).padStart(64, "0");
3943
+ }
3944
+ const funcDatas = transactions.map((tx) => {
3945
+ const data = tx.data ?? "0x";
3946
+ return data.startsWith("0x") ? data.slice(2) : data;
3947
+ });
3948
+ const funcElementOffsets = [];
3949
+ let currentOffset = 32 + n * 32;
3950
+ for (const funcData of funcDatas) {
3951
+ funcElementOffsets.push(currentOffset);
3952
+ const dataLen = funcData.length / 2;
3953
+ const paddedLen = Math.ceil(dataLen / 32) * 32;
3954
+ currentOffset += 32 + paddedLen;
3955
+ }
3956
+ encoded += n.toString(16).padStart(64, "0");
3957
+ for (const offset of funcElementOffsets) {
3958
+ encoded += offset.toString(16).padStart(64, "0");
3959
+ }
3960
+ for (const funcData of funcDatas) {
3961
+ const dataLen = funcData.length / 2;
3962
+ encoded += dataLen.toString(16).padStart(64, "0");
3963
+ if (funcData.length > 0) {
3964
+ const paddedLen = Math.ceil(dataLen / 32) * 32;
3965
+ encoded += funcData.padEnd(paddedLen * 2, "0");
3966
+ }
3967
+ }
3968
+ return `0x${encoded}`;
3969
+ }
3970
+ packUserOp(userOp) {
3971
+ const initCodeHash = sha3.keccak_256(utils.hexToBytes(userOp.initCode.slice(2) || ""));
3972
+ const callDataHash = sha3.keccak_256(utils.hexToBytes(userOp.callData.slice(2) || ""));
3973
+ const paymasterAndDataHash = sha3.keccak_256(
3974
+ utils.hexToBytes(userOp.paymasterAndData.slice(2) || "")
3975
+ );
3976
+ const packed = userOp.sender.slice(2).toLowerCase().padStart(64, "0") + userOp.nonce.toString(16).padStart(64, "0") + utils.bytesToHex(initCodeHash) + utils.bytesToHex(callDataHash) + userOp.callGasLimit.toString(16).padStart(64, "0") + userOp.verificationGasLimit.toString(16).padStart(64, "0") + userOp.preVerificationGas.toString(16).padStart(64, "0") + userOp.maxFeePerGas.toString(16).padStart(64, "0") + userOp.maxPriorityFeePerGas.toString(16).padStart(64, "0") + utils.bytesToHex(paymasterAndDataHash);
3977
+ return utils.hexToBytes(packed);
3978
+ }
3979
+ getDummySignature() {
3980
+ return `0x${"00".repeat(65)}`;
3981
+ }
3982
+ async getNonce() {
3983
+ const isDeployed = await this.isDeployed();
3984
+ if (!isDeployed) {
3985
+ return 0n;
3986
+ }
3987
+ if (this._cachedNonce !== null) {
3988
+ return this._cachedNonce;
3989
+ }
3990
+ const accountAddress = await this.getAccountAddress();
3991
+ const nonceKey = 0n;
3992
+ const nonceData = await this.rpcConnection.call("eth_call", [
3993
+ {
3994
+ to: this.entryPointAddress,
3995
+ data: `0x35567e1a${accountAddress.slice(2).padStart(64, "0")}${nonceKey.toString(16).padStart(64, "0")}`
3996
+ },
3997
+ "latest"
3998
+ ]);
3999
+ const nonce = BigInt(nonceData);
4000
+ this._cachedNonce = nonce;
4001
+ return nonce;
4002
+ }
4003
+ invalidateNonceCache() {
4004
+ this._cachedNonce = null;
4005
+ }
4006
+ async estimateGas(userOp) {
4007
+ try {
4008
+ return await this.bundlerClient.estimateUserOperationGas(userOp);
4009
+ } catch {
4010
+ const isDeployed = await this.isDeployed();
4011
+ return {
4012
+ preVerificationGas: 50000n,
4013
+ verificationGasLimit: isDeployed ? 100000n : 400000n,
4014
+ callGasLimit: 200000n
4015
+ };
4016
+ }
4017
+ }
4018
+ async getFeeData() {
4019
+ try {
4020
+ const gasPrice = await this.rpcConnection.getGasPrice();
4021
+ return {
4022
+ maxFeePerGas: gasPrice * 2n,
4023
+ maxPriorityFeePerGas: gasPrice / 10n
4024
+ };
4025
+ } catch {
4026
+ return {
4027
+ maxFeePerGas: 1000000000n,
4028
+ maxPriorityFeePerGas: 1000000000n
4029
+ };
4030
+ }
4031
+ }
4032
+ async getAccountCode() {
4033
+ const accountAddress = await this.getAccountAddress();
4034
+ return this.rpcConnection.getCode(accountAddress);
4035
+ }
4036
+ };
4037
+ function createSimpleAccount(config) {
4038
+ return new SimpleAccount(config);
4039
+ }
4040
+
4041
+ exports.BundlerClient = BundlerClient;
4042
+ exports.ChainManager = ChainManager;
4043
+ exports.NeroMpcSDK = NeroMpcSDK;
4044
+ exports.NeroProvider = NeroProvider;
4045
+ exports.PaymasterClient = PaymasterClient;
4046
+ exports.RpcConnection = RpcConnection;
4047
+ exports.SDKError = SDKError;
4048
+ exports.SimpleAccount = SimpleAccount;
4049
+ exports.SmartWallet = SmartWallet;
4050
+ exports.createBundlerClient = createBundlerClient;
4051
+ exports.createChainManager = createChainManager;
4052
+ exports.createNeroProvider = createNeroProvider;
4053
+ exports.createNeroSDK = createNeroSDK;
4054
+ exports.createPaymasterClient = createPaymasterClient;
4055
+ exports.createSimpleAccount = createSimpleAccount;
4056
+ exports.createSmartWallet = createSmartWallet;
4057
+ exports.getAllChains = getAllChains;
4058
+ exports.getChainConfig = getChainConfig;
4059
+ //# sourceMappingURL=no-modal.js.map
4060
+ //# sourceMappingURL=no-modal.js.map