@dynamic-labs-wallet/node-evm 0.0.0-pr384.1 → 0.0.0-pr506.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.
package/index.esm.js CHANGED
@@ -1,6 +1,19 @@
1
- import { MessageHash, DynamicWalletClient, getExternalServerKeyShareBackupInfo, WalletOperation } from '@dynamic-labs-wallet/node';
2
- import { getAddress, serializeSignature, createPublicClient, http, serializeTransaction } from 'viem';
1
+ import { toAccount } from 'viem/accounts';
2
+ import { MessageHash, createDelegatedWalletClient, delegatedSignMessage as delegatedSignMessage$1, revokeDelegation as revokeDelegation$1, DynamicWalletClient, getMPCChainConfig, getExternalServerKeyShareBackupInfo, WalletOperation } from '@dynamic-labs-wallet/node';
3
+ import { stringToHex, bytesToHex, size, concat, hashTypedData, serializeSignature, getAddress, serializeTransaction, parseSignature, createPublicClient, http, defineChain, createWalletClient } from 'viem';
4
+ import { hashAuthorization } from 'viem/utils';
5
+ import { Logger } from '@dynamic-labs/logger';
6
+ import { AxiosError } from 'axios';
7
+ import { handleAxiosError } from '@dynamic-labs-wallet/core';
3
8
  import { mainnet } from 'viem/chains';
9
+ import { initializeClient, refreshUser, getNetworksData, createDynamicClient } from '@dynamic-labs-sdk/client';
10
+ import { assertDefined } from '@dynamic-labs-sdk/client/core';
11
+ import { mapNetworkDataToViemChain } from '@dynamic-labs-sdk/evm/viem';
12
+ import { addWaasEvmExtension } from '@dynamic-labs-sdk/evm/waas';
13
+ import { addZerodevExtension } from '@dynamic-labs-sdk/zerodev';
14
+ import { getZerodevRpc, getPaymasterConfig, getZerodevProviderFromSettings, getEntryPoint, getKernelVersion, getEcdsaValidator } from '@dynamic-labs-sdk/zerodev/core';
15
+ import { createEcdsaKernelMigrationAccount } from '@zerodev/ecdsa-validator';
16
+ import { createKernelAccountClient, getUserOperationGasPrice, createKernelAccount, constants } from '@zerodev/sdk';
4
17
 
5
18
  function _extends() {
6
19
  _extends = Object.assign || function assign(target) {
@@ -18,11 +31,24 @@ const EVM_SIGN_MESSAGE_PREFIX = `\x19Ethereum Signed Message:\n`;
18
31
  const ERROR_KEYGEN_FAILED = 'Error with keygen';
19
32
  const ERROR_CREATE_WALLET_ACCOUNT = 'Error creating evm wallet account';
20
33
  const ERROR_SIGN_MESSAGE = 'Error signing message';
34
+ const ERROR_SIGN_TYPED_DATA = 'Error signing typed data';
21
35
  const ERROR_ACCOUNT_ADDRESS_REQUIRED = 'Account address is required';
22
36
  const ERROR_VERIFY_MESSAGE_SIGNATURE = 'Error verifying message signature';
23
37
 
24
- const formatEVMMessage = (message)=>{
25
- return `${EVM_SIGN_MESSAGE_PREFIX}${message.length}${message}`;
38
+ const formatEVMMessage = (message_)=>{
39
+ const message = (()=>{
40
+ if (typeof message_ === 'string') return stringToHex(message_);
41
+ if (typeof message_.raw === 'string') return message_.raw;
42
+ return bytesToHex(message_.raw);
43
+ })();
44
+ const prefix = stringToHex(`${EVM_SIGN_MESSAGE_PREFIX}${size(message)}`);
45
+ return concat([
46
+ prefix,
47
+ message
48
+ ]);
49
+ };
50
+ const formatTypedData = (typedData)=>{
51
+ return hashTypedData(typedData).slice(2);
26
52
  };
27
53
  const serializeECDSASignature = (signature)=>{
28
54
  return serializeSignature({
@@ -44,13 +70,327 @@ const deriveAccountAddress = ({ rawPublicKey })=>{
44
70
  };
45
71
  };
46
72
 
73
+ const logger = new Logger('DynamicWaasWalletClient');
74
+ const logError = ({ message, error, context })=>{
75
+ if (error instanceof AxiosError) {
76
+ handleAxiosError(error, message, context, logger);
77
+ }
78
+ logger.error('[DynamicWaasWalletClient] Error in node-evm client', {
79
+ error: error instanceof Error ? error.message : String(error),
80
+ context
81
+ });
82
+ };
83
+
84
+ /**
85
+ * Creates a delegated EVM wallet client for functional operations
86
+ */ const createDelegatedEvmWalletClient = ({ environmentId, baseApiUrl, baseMPCRelayApiUrl, apiKey, debug = false })=>{
87
+ const baseClient = createDelegatedWalletClient({
88
+ environmentId,
89
+ baseApiUrl,
90
+ baseMPCRelayApiUrl,
91
+ apiKey,
92
+ debug
93
+ });
94
+ const evmClient = _extends({}, baseClient, {
95
+ chainName: 'EVM'
96
+ });
97
+ return evmClient;
98
+ };
99
+ /**
100
+ * Signs a message using delegated signing for EVM
101
+ */ const delegatedSignMessage = async (client, { walletId, walletApiKey, keyShare, message, context, onError })=>{
102
+ try {
103
+ if (!keyShare || !walletId || !walletApiKey) {
104
+ throw new Error('Delegated key share, wallet ID, and wallet API key are required to sign a message');
105
+ }
106
+ const formattedMessage = formatEVMMessage(message);
107
+ const resolvedContext = context != null ? context : {
108
+ evmMessage: message
109
+ };
110
+ const signatureEcdsa = await delegatedSignMessage$1(client, {
111
+ walletId,
112
+ walletApiKey,
113
+ keyShare,
114
+ message: formattedMessage,
115
+ chainName: client.chainName,
116
+ context: resolvedContext,
117
+ onError
118
+ });
119
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
120
+ return serializedSignature;
121
+ } catch (error) {
122
+ logError({
123
+ message: 'Error in delegatedSignMessage',
124
+ error: error,
125
+ context: {
126
+ walletId
127
+ }
128
+ });
129
+ throw error;
130
+ }
131
+ };
132
+ /**
133
+ * Signs a transaction using delegated signing for EVM
134
+ */ const delegatedSignTransaction = async (client, { walletId, walletApiKey, keyShare, transaction })=>{
135
+ try {
136
+ // Serialize the transaction
137
+ const serializedTx = serializeTransaction(transaction);
138
+ const serializedTxBytes = Uint8Array.from(Buffer.from(serializedTx.slice(2), 'hex'));
139
+ if (!(serializedTxBytes instanceof Uint8Array)) {
140
+ throw new Error('Invalid serializedTxBytes');
141
+ }
142
+ // Use the delegated sign message function from node package
143
+ const signatureEcdsa = await delegatedSignMessage$1(client, {
144
+ walletId,
145
+ walletApiKey,
146
+ keyShare,
147
+ message: serializedTxBytes,
148
+ chainName: client.chainName
149
+ });
150
+ if (!('r' in signatureEcdsa && 's' in signatureEcdsa && 'v' in signatureEcdsa)) {
151
+ throw new Error('Invalid signature format returned from MPC signing');
152
+ }
153
+ // Construct the signed transaction
154
+ const r = `0x${Buffer.from(signatureEcdsa.r).toString('hex')}`;
155
+ const s = `0x${Buffer.from(signatureEcdsa.s).toString('hex')}`;
156
+ const v = BigInt(signatureEcdsa.v);
157
+ const signedTx = _extends({}, transaction, {
158
+ r: r,
159
+ s: s,
160
+ v: v
161
+ });
162
+ const serializedSignedTx = serializeTransaction(signedTx);
163
+ return serializedSignedTx;
164
+ } catch (error) {
165
+ logError({
166
+ message: 'Error in delegatedSignTransaction',
167
+ error: error,
168
+ context: {
169
+ walletId
170
+ }
171
+ });
172
+ throw error;
173
+ }
174
+ };
175
+ /**
176
+ * Signs typed data using delegated signing for EVM
177
+ */ const delegatedSignTypedData = async (client, { walletId, walletApiKey, keyShare, typedData })=>{
178
+ try {
179
+ if (!keyShare || !walletId || !walletApiKey) {
180
+ throw new Error('Delegated key share, wallet ID, and wallet API key are required to sign typed data');
181
+ }
182
+ const formattedTypedData = formatTypedData(typedData);
183
+ const signatureEcdsa = await delegatedSignMessage$1(client, {
184
+ walletId,
185
+ walletApiKey,
186
+ keyShare,
187
+ message: formattedTypedData,
188
+ chainName: client.chainName,
189
+ isFormatted: true,
190
+ context: {
191
+ evmTypedData: typedData
192
+ }
193
+ });
194
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
195
+ return serializedSignature;
196
+ } catch (error) {
197
+ logError({
198
+ message: 'Error in delegatedSignTypedData',
199
+ error: error,
200
+ context: {
201
+ walletId
202
+ }
203
+ });
204
+ throw error;
205
+ }
206
+ };
207
+ /**
208
+ * Signs EIP-7702 authorization using delegated signing for EVM
209
+ */ const delegatedSignAuthorization = async (client, { walletId, walletApiKey, keyShare, authorization })=>{
210
+ try {
211
+ if (!keyShare || !walletId || !walletApiKey) {
212
+ throw new Error('Delegated key share, wallet ID, and wallet API key are required to sign authorization');
213
+ }
214
+ const digest = hashAuthorization(authorization);
215
+ const prehashed = digest.startsWith('0x') ? digest.slice(2) : digest;
216
+ const signatureEcdsa = await delegatedSignMessage$1(client, {
217
+ walletId,
218
+ walletApiKey,
219
+ keyShare,
220
+ message: prehashed,
221
+ chainName: client.chainName,
222
+ isFormatted: true,
223
+ context: {
224
+ eip7702Auth: authorization
225
+ }
226
+ });
227
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
228
+ const signature = parseSignature(serializedSignature);
229
+ return signature;
230
+ } catch (error) {
231
+ logError({
232
+ message: 'Error in delegatedSignAuthorization',
233
+ error: error,
234
+ context: {
235
+ walletId
236
+ }
237
+ });
238
+ throw error;
239
+ }
240
+ };
241
+ /**
242
+ * Revoke delegation - delegates to the node package
243
+ */ const revokeDelegation = async (client, params)=>{
244
+ return revokeDelegation$1(client, params);
245
+ };
246
+
247
+ const createAccountAdapter = ({ evmClient, accountAddress, password, externalServerKeyShares, delegated })=>{
248
+ return toAccount({
249
+ address: accountAddress,
250
+ signMessage: async ({ message })=>{
251
+ if (delegated) {
252
+ return delegatedSignMessage(delegated.delegatedClient, {
253
+ walletId: delegated.walletId,
254
+ walletApiKey: delegated.walletApiKey,
255
+ keyShare: delegated.keyShare,
256
+ message: message
257
+ });
258
+ }
259
+ const signature = await evmClient.signMessage({
260
+ message: message,
261
+ accountAddress,
262
+ password,
263
+ externalServerKeyShares
264
+ });
265
+ return signature;
266
+ },
267
+ signTypedData: async (typedData)=>{
268
+ if (delegated) {
269
+ return delegatedSignTypedData(delegated.delegatedClient, {
270
+ walletId: delegated.walletId,
271
+ walletApiKey: delegated.walletApiKey,
272
+ keyShare: delegated.keyShare,
273
+ typedData: typedData
274
+ });
275
+ }
276
+ return evmClient.signTypedData({
277
+ accountAddress,
278
+ typedData: typedData,
279
+ password: password,
280
+ externalServerKeyShares
281
+ });
282
+ },
283
+ signTransaction: async (transaction)=>{
284
+ if (delegated) {
285
+ return delegatedSignTransaction(delegated.delegatedClient, {
286
+ walletId: delegated.walletId,
287
+ walletApiKey: delegated.walletApiKey,
288
+ keyShare: delegated.keyShare,
289
+ transaction
290
+ });
291
+ }
292
+ const signedTx = await evmClient.signTransaction({
293
+ senderAddress: accountAddress,
294
+ transaction,
295
+ password,
296
+ externalServerKeyShares
297
+ });
298
+ return signedTx;
299
+ },
300
+ signAuthorization: async (authorization)=>{
301
+ if (delegated) {
302
+ const signature = await delegatedSignAuthorization(delegated.delegatedClient, {
303
+ walletId: delegated.walletId,
304
+ walletApiKey: delegated.walletApiKey,
305
+ keyShare: delegated.keyShare,
306
+ authorization
307
+ });
308
+ var _authorization_address;
309
+ const signedAuthorization = {
310
+ address: (_authorization_address = authorization.address) != null ? _authorization_address : authorization.contractAddress,
311
+ chainId: authorization.chainId,
312
+ nonce: authorization.nonce,
313
+ r: signature.r,
314
+ s: signature.s,
315
+ v: signature.v,
316
+ yParity: signature.yParity
317
+ };
318
+ return signedAuthorization;
319
+ }
320
+ const signature = await evmClient.signAuthorization({
321
+ authorization,
322
+ accountAddress,
323
+ password,
324
+ externalServerKeyShares
325
+ });
326
+ var _authorization_address1;
327
+ const signedAuthorization = {
328
+ address: (_authorization_address1 = authorization.address) != null ? _authorization_address1 : authorization.contractAddress,
329
+ chainId: authorization.chainId,
330
+ nonce: authorization.nonce,
331
+ r: signature.r,
332
+ s: signature.s,
333
+ v: signature.v,
334
+ yParity: signature.yParity
335
+ };
336
+ return signedAuthorization;
337
+ }
338
+ });
339
+ };
340
+
47
341
  class DynamicEvmWalletClient extends DynamicWalletClient {
342
+ get jwtAuthToken() {
343
+ return this.baseJWTAuthToken;
344
+ }
345
+ get apiUrl() {
346
+ var _this_baseApiUrl;
347
+ return (_this_baseApiUrl = this.baseApiUrl) != null ? _this_baseApiUrl : 'https://app.dynamicauth.com';
348
+ }
48
349
  createViemPublicClient({ chain, rpcUrl }) {
49
350
  return createPublicClient({
50
351
  chain,
51
352
  transport: http(rpcUrl)
52
353
  });
53
354
  }
355
+ async getWalletClient({ accountAddress, password, externalServerKeyShares, chain, chainId, rpcUrl }) {
356
+ const account = createAccountAdapter({
357
+ evmClient: this,
358
+ accountAddress: accountAddress,
359
+ password,
360
+ externalServerKeyShares
361
+ });
362
+ let viemChain;
363
+ if (chain) {
364
+ viemChain = chain;
365
+ } else if (chainId) {
366
+ if (!rpcUrl) {
367
+ throw new Error('rpcUrl is required when providing chainId. Please provide a valid RPC URL for the chain.');
368
+ }
369
+ viemChain = defineChain({
370
+ id: chainId,
371
+ name: `Chain ${chainId}`,
372
+ nativeCurrency: {
373
+ name: 'Ether',
374
+ symbol: 'ETH',
375
+ decimals: 18
376
+ },
377
+ rpcUrls: {
378
+ default: {
379
+ http: [
380
+ rpcUrl
381
+ ]
382
+ }
383
+ }
384
+ });
385
+ } else {
386
+ viemChain = mainnet;
387
+ }
388
+ return createWalletClient({
389
+ account,
390
+ chain: viemChain,
391
+ transport: http(rpcUrl)
392
+ });
393
+ }
54
394
  /**
55
395
  * Creates a new wallet account and stores the key shares in the wallet map.
56
396
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
@@ -68,15 +408,21 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
68
408
  const { rawPublicKey, externalServerKeyShares } = await this.keyGen({
69
409
  chainName: this.chainName,
70
410
  thresholdSignatureScheme,
411
+ skipLock: true,
71
412
  onError,
72
413
  onCeremonyComplete: (accountAddress, walletId)=>{
73
414
  // update wallet map
74
415
  const checksumAddress = getAddress(accountAddress);
416
+ const chainConfig = getMPCChainConfig(this.chainName);
75
417
  this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
76
418
  accountAddress: checksumAddress,
77
419
  walletId,
78
420
  chainName: this.chainName,
79
421
  thresholdSignatureScheme,
422
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
423
+ index,
424
+ value
425
+ ]))),
80
426
  externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
81
427
  });
82
428
  this.logger.debug('walletMap updated for wallet', {
@@ -112,42 +458,138 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
112
458
  externalServerKeyShares
113
459
  };
114
460
  } catch (error) {
115
- // this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
461
+ logError({
462
+ message: ERROR_CREATE_WALLET_ACCOUNT,
463
+ error: error,
464
+ context: {}
465
+ });
116
466
  throw new Error(ERROR_CREATE_WALLET_ACCOUNT);
117
467
  }
118
468
  }
119
- async signMessage({ message, accountAddress, password = undefined, externalServerKeyShares }) {
120
- await this.verifyPassword({
121
- accountAddress,
122
- password,
123
- walletOperation: WalletOperation.SIGN_MESSAGE
124
- });
125
- await this.getWallet({
126
- accountAddress,
127
- walletOperation: WalletOperation.SIGN_MESSAGE
128
- });
469
+ async signMessage({ message, accountAddress, password = undefined, externalServerKeyShares, context, onError }) {
129
470
  try {
130
471
  if (!accountAddress) {
131
472
  throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
132
473
  }
133
474
  // Format the message for EVM signing
134
475
  const formattedMessage = formatEVMMessage(message);
135
- // Sign the message using MPC
476
+ const resolvedContext = context != null ? context : {
477
+ evmMessage: message
478
+ };
479
+ // Attempt to recover key shares from backup if not provided
480
+ await this.ensureKeySharesRecovered({
481
+ accountAddress,
482
+ password,
483
+ walletOperation: WalletOperation.SIGN_MESSAGE,
484
+ externalServerKeyShares,
485
+ errorMessage: 'External server key shares are required to sign a message. No backup shares available for recovery.'
486
+ });
136
487
  const signatureEcdsa = await this.sign({
137
488
  message: formattedMessage,
138
489
  accountAddress: accountAddress,
139
490
  chainName: this.chainName,
140
491
  password,
141
- externalServerKeyShares
492
+ externalServerKeyShares,
493
+ context: resolvedContext,
494
+ onError
142
495
  });
143
496
  // Serialize the signature
144
497
  const serializedSignature = serializeECDSASignature(signatureEcdsa);
145
498
  return serializedSignature;
146
499
  } catch (error) {
147
- this.logger.error(ERROR_SIGN_MESSAGE, error);
500
+ logError({
501
+ message: ERROR_SIGN_MESSAGE,
502
+ error: error,
503
+ context: {
504
+ accountAddress
505
+ }
506
+ });
148
507
  throw new Error(ERROR_SIGN_MESSAGE);
149
508
  }
150
509
  }
510
+ isSignAuthorizationSupported() {
511
+ return true;
512
+ }
513
+ async signAuthorization({ authorization, accountAddress, password = undefined, externalServerKeyShares, onError }) {
514
+ try {
515
+ if (!accountAddress) {
516
+ throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
517
+ }
518
+ const digest = hashAuthorization(authorization);
519
+ const prehashed = digest.startsWith('0x') ? digest.slice(2) : digest;
520
+ // Attempt to recover key shares from backup if not provided
521
+ await this.ensureKeySharesRecovered({
522
+ accountAddress,
523
+ password,
524
+ walletOperation: WalletOperation.SIGN_MESSAGE,
525
+ externalServerKeyShares,
526
+ errorMessage: 'External server key shares are required to sign authorization. No backup shares available for recovery.'
527
+ });
528
+ const signatureEcdsa = await this.sign({
529
+ message: prehashed,
530
+ accountAddress: accountAddress,
531
+ chainName: this.chainName,
532
+ password,
533
+ externalServerKeyShares,
534
+ isFormatted: true,
535
+ context: {
536
+ eip7702Auth: authorization
537
+ },
538
+ onError
539
+ });
540
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
541
+ const signature = parseSignature(serializedSignature);
542
+ return signature;
543
+ } catch (error) {
544
+ logError({
545
+ message: ERROR_SIGN_MESSAGE,
546
+ error: error,
547
+ context: {
548
+ accountAddress
549
+ }
550
+ });
551
+ throw new Error(ERROR_SIGN_MESSAGE);
552
+ }
553
+ }
554
+ async signTypedData({ accountAddress, typedData, password = undefined, externalServerKeyShares, onError }) {
555
+ try {
556
+ if (!accountAddress) {
557
+ throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
558
+ }
559
+ const formattedTypedData = formatTypedData(typedData);
560
+ // Attempt to recover key shares from backup if not provided
561
+ await this.ensureKeySharesRecovered({
562
+ accountAddress,
563
+ password,
564
+ walletOperation: WalletOperation.SIGN_MESSAGE,
565
+ externalServerKeyShares,
566
+ errorMessage: 'External server key shares are required to sign typed data. No backup shares available for recovery.'
567
+ });
568
+ const signatureEcdsa = await this.sign({
569
+ message: formattedTypedData,
570
+ accountAddress: accountAddress,
571
+ chainName: this.chainName,
572
+ password,
573
+ externalServerKeyShares,
574
+ isFormatted: true,
575
+ context: {
576
+ evmTypedData: typedData
577
+ },
578
+ onError
579
+ });
580
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
581
+ return serializedSignature;
582
+ } catch (error) {
583
+ logError({
584
+ message: ERROR_SIGN_TYPED_DATA,
585
+ error: error,
586
+ context: {
587
+ accountAddress
588
+ }
589
+ });
590
+ throw new Error(ERROR_SIGN_TYPED_DATA);
591
+ }
592
+ }
151
593
  async verifyMessageSignature({ accountAddress, message, signature }) {
152
594
  try {
153
595
  // Verify the signature using the public client
@@ -161,7 +603,13 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
161
603
  });
162
604
  return verified;
163
605
  } catch (error) {
164
- this.logger.error(ERROR_VERIFY_MESSAGE_SIGNATURE, error);
606
+ logError({
607
+ message: ERROR_VERIFY_MESSAGE_SIGNATURE,
608
+ error: error,
609
+ context: {
610
+ accountAddress
611
+ }
612
+ });
165
613
  throw new Error(ERROR_VERIFY_MESSAGE_SIGNATURE);
166
614
  }
167
615
  }
@@ -171,6 +619,14 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
171
619
  password,
172
620
  walletOperation: WalletOperation.SIGN_TRANSACTION
173
621
  });
622
+ // Attempt to recover key shares from backup if not provided
623
+ await this.ensureKeySharesRecovered({
624
+ accountAddress: senderAddress,
625
+ password,
626
+ walletOperation: WalletOperation.SIGN_TRANSACTION,
627
+ externalServerKeyShares,
628
+ errorMessage: 'External server key shares are required to sign transaction. No backup shares available for recovery.'
629
+ });
174
630
  const serializedTx = serializeTransaction(transaction);
175
631
  const serializedTxBytes = Uint8Array.from(Buffer.from(serializedTx.slice(2), 'hex'));
176
632
  if (!(serializedTxBytes instanceof Uint8Array)) {
@@ -199,7 +655,13 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
199
655
  const serializedSignedTx = serializeTransaction(signedTx);
200
656
  return serializedSignedTx;
201
657
  } catch (error) {
202
- this.logger.error('Error signing transaction:', error);
658
+ logError({
659
+ message: 'Error signing transaction:',
660
+ error: error,
661
+ context: {
662
+ senderAddress
663
+ }
664
+ });
203
665
  throw error;
204
666
  }
205
667
  }
@@ -209,6 +671,14 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
209
671
  password,
210
672
  walletOperation: WalletOperation.EXPORT_PRIVATE_KEY
211
673
  });
674
+ // Attempt to recover key shares from backup if not provided
675
+ await this.ensureKeySharesRecovered({
676
+ accountAddress,
677
+ password,
678
+ walletOperation: WalletOperation.EXPORT_PRIVATE_KEY,
679
+ externalServerKeyShares,
680
+ errorMessage: 'External server key shares are required to export private key. No backup shares available for recovery.'
681
+ });
212
682
  const { derivedPrivateKey } = await this.exportKey({
213
683
  accountAddress,
214
684
  chainName: this.chainName,
@@ -251,16 +721,28 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
251
721
  onCeremonyComplete: (accountAddress, walletId)=>{
252
722
  // update wallet map
253
723
  const checksumAddress = getAddress(accountAddress);
724
+ const chainConfig = getMPCChainConfig(this.chainName);
254
725
  this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
255
726
  accountAddress: checksumAddress,
256
727
  walletId,
257
728
  chainName: this.chainName,
258
729
  thresholdSignatureScheme,
730
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
731
+ index,
732
+ value
733
+ ]))),
259
734
  externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
260
735
  });
261
736
  ceremonyCeremonyCompleteResolver(undefined);
262
737
  },
263
- onError
738
+ onError: (e)=>{
739
+ logError({
740
+ message: 'importPrivateKey: onError',
741
+ error: e,
742
+ context: {}
743
+ });
744
+ onError == null ? void 0 : onError(e);
745
+ }
264
746
  });
265
747
  // Wait for the ceremony to complete before proceeding
266
748
  await ceremonyCompletePromise;
@@ -288,14 +770,198 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
288
770
  const evmWallets = wallets.filter((wallet)=>wallet.chainName === 'eip155');
289
771
  return evmWallets;
290
772
  }
291
- constructor({ environmentId, baseApiUrl, baseMPCRelayApiUrl, debug }){
773
+ constructor({ environmentId, baseApiUrl, baseMPCRelayApiUrl, debug, enableMPCAccelerator }){
292
774
  super({
293
775
  environmentId,
294
776
  baseApiUrl,
295
777
  baseMPCRelayApiUrl,
296
- debug
778
+ debug,
779
+ enableMPCAccelerator
297
780
  }), this.chainName = 'EVM';
298
781
  }
299
782
  }
300
783
 
301
- export { DynamicEvmWalletClient };
784
+ const getJwtExpiration = (jwt)=>{
785
+ if (!jwt) {
786
+ return 0;
787
+ }
788
+ return JSON.parse(Buffer.from(jwt.split('.')[1], 'base64').toString()).exp * 1000;
789
+ };
790
+ class MemoryStorageAdapter {
791
+ async getItem(key) {
792
+ if (key.includes('session')) {
793
+ // This is a workaround so we can pass the JWT that the authenticate the node SDK to
794
+ // the vanilla client, once set we can refresh the user and populate the user data, wallets and etc.
795
+ return JSON.stringify({
796
+ value: {
797
+ token: this.jwt,
798
+ sessionExpiration: getJwtExpiration(this.jwt),
799
+ legacyToken: null,
800
+ mfaToken: null,
801
+ captchaToken: null,
802
+ sessionKeys: null
803
+ }
804
+ });
805
+ }
806
+ var _this_store_get;
807
+ return (_this_store_get = this.store.get(key)) != null ? _this_store_get : null;
808
+ }
809
+ async setItem(key, value) {
810
+ this.store.set(key, value);
811
+ }
812
+ async removeItem(key) {
813
+ this.store.delete(key);
814
+ }
815
+ clear() {
816
+ this.store.clear();
817
+ }
818
+ get size() {
819
+ return this.store.size;
820
+ }
821
+ constructor(jwt){
822
+ this.store = new Map();
823
+ this.jwt = jwt;
824
+ }
825
+ }
826
+ const createMemoryStorageAdapter = (jwt)=>{
827
+ return new MemoryStorageAdapter(jwt);
828
+ };
829
+
830
+ class DynamicEvmZeroDevClient {
831
+ async initialize() {
832
+ await initializeClient(this.dynamicClient);
833
+ if ('jwtAuthToken' in this.evmClient) {
834
+ // Fetch user data to populate wallet accounts
835
+ await refreshUser(this.dynamicClient);
836
+ }
837
+ }
838
+ /**
839
+ * Get network data by networkId from project configuration
840
+ */ getNetworkData(networkId) {
841
+ const networksData = getNetworksData(this.dynamicClient);
842
+ const networkData = networksData.find((n)=>n.networkId === networkId);
843
+ assertDefined(networkData, `No network found with networkId: ${networkId}. Available networks: ${networksData.map((n)=>n.networkId).join(', ')}`);
844
+ return networkData;
845
+ }
846
+ async createKernelClientForAddress(options) {
847
+ const viemSigner = createAccountAdapter({
848
+ evmClient: this.evmClient,
849
+ accountAddress: options.address,
850
+ password: options.password,
851
+ externalServerKeyShares: options.externalServerKeyShares,
852
+ delegated: options.delegated
853
+ });
854
+ const activeNetworkData = this.getNetworkData(options.networkId);
855
+ const viemChain = mapNetworkDataToViemChain(activeNetworkData);
856
+ var _options_bundlerRpc;
857
+ const bundlerRpc = (_options_bundlerRpc = options.bundlerRpc) != null ? _options_bundlerRpc : getZerodevRpc({
858
+ bundlerProvider: options.bundlerProvider,
859
+ networkId: activeNetworkData.networkId,
860
+ rpcType: 'bundler'
861
+ }, this.dynamicClient);
862
+ const bundlerTransport = http(bundlerRpc);
863
+ const publicClient = createPublicClient({
864
+ chain: viemChain,
865
+ transport: bundlerTransport
866
+ });
867
+ const account = await this.createKernelAccountWithCustomSigner({
868
+ publicClient,
869
+ signer: viemSigner
870
+ });
871
+ var _options_paymasterRpc;
872
+ const paymasterRpc = (_options_paymasterRpc = options.paymasterRpc) != null ? _options_paymasterRpc : getZerodevRpc({
873
+ bundlerProvider: options.bundlerProvider,
874
+ networkId: activeNetworkData.networkId,
875
+ rpcType: 'paymaster'
876
+ }, this.dynamicClient);
877
+ var _options_withSponsorship;
878
+ const paymasterConfig = ((_options_withSponsorship = options.withSponsorship) != null ? _options_withSponsorship : true) ? getPaymasterConfig({
879
+ chain: viemChain,
880
+ gasTokenAddress: options.gasTokenAddress,
881
+ paymasterRpc
882
+ }) : {};
883
+ const kernelClient = createKernelAccountClient(_extends({
884
+ account,
885
+ bundlerTransport,
886
+ chain: viemChain,
887
+ client: publicClient,
888
+ userOperation: {
889
+ estimateFeesPerGas: async ({ bundlerClient })=>getUserOperationGasPrice(bundlerClient)
890
+ }
891
+ }, paymasterConfig));
892
+ return kernelClient;
893
+ }
894
+ async createKernelAccountWithCustomSigner({ publicClient, signer }) {
895
+ const zerodevProvider = getZerodevProviderFromSettings(this.dynamicClient);
896
+ assertDefined(zerodevProvider, 'Zerodev provider is not enabled in project settings');
897
+ const useEIP7702 = zerodevProvider.enableEIP7702;
898
+ const entryPointVersion = zerodevProvider.entryPointVersion;
899
+ const entryPoint = getEntryPoint(entryPointVersion);
900
+ if (useEIP7702) {
901
+ return createKernelAccount(publicClient, {
902
+ eip7702Account: signer,
903
+ entryPoint,
904
+ kernelVersion: constants.KERNEL_V3_3
905
+ });
906
+ }
907
+ const kernelVersionValue = zerodevProvider.kernelVersion;
908
+ const kernelVersion = getKernelVersion({
909
+ entryPoint,
910
+ kernelVersion: kernelVersionValue
911
+ });
912
+ var _zerodevProvider_enableKernelV3Migration;
913
+ const kernelV3MigrationEnabled = (_zerodevProvider_enableKernelV3Migration = zerodevProvider.enableKernelV3Migration) != null ? _zerodevProvider_enableKernelV3Migration : false;
914
+ if (kernelV3MigrationEnabled) {
915
+ const apiKernelVersion = getKernelVersion({
916
+ entryPoint,
917
+ kernelVersion: zerodevProvider.kernelVersion
918
+ });
919
+ return createEcdsaKernelMigrationAccount(publicClient, {
920
+ entryPoint,
921
+ migrationVersion: {
922
+ from: kernelVersion,
923
+ to: apiKernelVersion
924
+ },
925
+ signer
926
+ });
927
+ }
928
+ const validator = await getEcdsaValidator({
929
+ ecdsaProviderType: zerodevProvider.ecdsaProviderType,
930
+ entryPoint,
931
+ kernelVersion,
932
+ publicClient,
933
+ signer
934
+ });
935
+ return createKernelAccount(publicClient, {
936
+ entryPoint,
937
+ kernelVersion,
938
+ plugins: {
939
+ sudo: validator
940
+ }
941
+ });
942
+ }
943
+ constructor(evmClient){
944
+ this.evmClient = evmClient;
945
+ var _evmClient_jwtAuthToken;
946
+ const authToken = 'jwtAuthToken' in evmClient ? (_evmClient_jwtAuthToken = evmClient.jwtAuthToken) != null ? _evmClient_jwtAuthToken : null : null;
947
+ const storageAdapter = createMemoryStorageAdapter(authToken);
948
+ this.dynamicClient = createDynamicClient({
949
+ environmentId: evmClient.environmentId,
950
+ autoInitialize: false,
951
+ coreConfig: {
952
+ storageAdapter,
953
+ fetch: fetch,
954
+ apiBaseUrl: `${evmClient.apiUrl}/api/v0`
955
+ }
956
+ });
957
+ addZerodevExtension(this.dynamicClient);
958
+ addWaasEvmExtension(this.dynamicClient);
959
+ }
960
+ }
961
+ const createZerodevClient = async (evmClient)=>{
962
+ const client = new DynamicEvmZeroDevClient(evmClient);
963
+ await client.initialize();
964
+ return client;
965
+ };
966
+
967
+ export { DynamicEvmWalletClient, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_CREATE_WALLET_ACCOUNT, ERROR_KEYGEN_FAILED, ERROR_SIGN_MESSAGE, ERROR_SIGN_TYPED_DATA, ERROR_VERIFY_MESSAGE_SIGNATURE, EVM_SIGN_MESSAGE_PREFIX, createAccountAdapter, createDelegatedEvmWalletClient, createZerodevClient, delegatedSignAuthorization, delegatedSignMessage, delegatedSignTransaction, delegatedSignTypedData, deriveAccountAddress, formatEVMMessage, formatTypedData, revokeDelegation, serializeECDSASignature };