@dynamic-labs-wallet/evm 0.0.46 → 0.0.47

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.cjs.js CHANGED
@@ -42,55 +42,39 @@ class DynamicEvmWalletClient extends browser.DynamicWalletClient {
42
42
  });
43
43
  }
44
44
  async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError }) {
45
- let ceremonyCompleted = false;
46
45
  try {
47
46
  // Generate key shares for given threshold signature scheme (TSS)
48
47
  const { rawPublicKey, clientKeyShares } = await this.keyGen({
49
48
  chainName: this.chainName,
50
49
  thresholdSignatureScheme,
51
50
  onError,
52
- onCeremonyComplete: ()=>{
53
- ceremonyCompleted = true;
51
+ onCeremonyComplete: (accountAddress, walletId)=>{
52
+ // update wallet map
53
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
54
+ accountAddress,
55
+ walletId,
56
+ chainName: this.chainName,
57
+ thresholdSignatureScheme,
58
+ clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
59
+ });
54
60
  }
55
61
  });
56
- // Wait for the ceremony to complete, timeout after 5 seconds
57
- await Promise.race([
58
- (async ()=>{
59
- while(!ceremonyCompleted){
60
- await new Promise((resolve)=>setTimeout(resolve, 100));
61
- }
62
- })(),
63
- browser.timeoutPromise({
64
- timeInMs: 5000,
65
- activity: 'Ceremony'
66
- })
67
- ]);
68
62
  if (!rawPublicKey || !clientKeyShares) {
69
63
  throw new Error(ERROR_KEYGEN_FAILED);
70
64
  }
71
- // Get EVM address from public key
72
65
  const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
73
66
  rawPublicKey: rawPublicKey
74
67
  });
75
- // Refresh user to get the latest user data
76
- const refreshedUser = await this.apiClient.refreshUser();
77
- // Find the new wallet in the user's verified credentials
78
- const newWallet = refreshedUser.user.verifiedCredentials.find((wallet)=>wallet.address.toLowerCase() === accountAddress.toLowerCase());
79
- if (!newWallet) {
80
- throw new Error('Wallet not found after ceremony completion');
81
- }
82
- // Store the new wallet in the wallet map
83
- this.walletMap[accountAddress] = {
84
- accountAddress,
85
- walletId: newWallet.id,
86
- chainName: this.chainName,
87
- clientKeyShares: clientKeyShares,
88
- thresholdSignatureScheme,
89
- clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
90
- };
91
- // Backup the new wallet
92
- await this.storeEncryptedBackupByWallet({
68
+ // Update client key shares in wallet map
69
+ // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
70
+ // TODO: remove this once iframe handling for secret shares is implemented
71
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
72
+ clientKeyShares
73
+ });
74
+ // Backup the new wallet without waiting for the promise to resolve
75
+ void this.storeEncryptedBackupByWalletWithRetry({
93
76
  accountAddress,
77
+ clientKeyShares,
94
78
  password
95
79
  });
96
80
  return {
@@ -227,48 +211,39 @@ class DynamicEvmWalletClient extends browser.DynamicWalletClient {
227
211
  };
228
212
  }
229
213
  async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError }) {
230
- let ceremonyCompleted = false;
231
214
  // TODO: validate private key for EVM
232
215
  const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
233
216
  chainName,
234
217
  privateKey,
235
218
  thresholdSignatureScheme,
236
219
  onError,
237
- onCeremonyComplete: ()=>{
238
- ceremonyCompleted = true;
220
+ onCeremonyComplete: (accountAddress, walletId)=>{
221
+ // update wallet map
222
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
223
+ accountAddress,
224
+ walletId,
225
+ chainName: this.chainName,
226
+ thresholdSignatureScheme,
227
+ clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
228
+ });
239
229
  }
240
230
  });
241
- // Wait for the ceremony to complete, timeout after 5 seconds
242
- await Promise.race([
243
- (async ()=>{
244
- while(!ceremonyCompleted){
245
- await new Promise((resolve)=>setTimeout(resolve, 100));
246
- }
247
- })(),
248
- browser.timeoutPromise({
249
- timeInMs: 5000,
250
- activity: 'Ceremony'
251
- })
252
- ]);
253
231
  if (!rawPublicKey || !clientKeyShares) {
254
232
  throw new Error('Error creating wallet account');
255
233
  }
256
234
  const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
257
235
  rawPublicKey: rawPublicKey
258
236
  });
259
- const refreshedUser = await this.apiClient.refreshUser();
260
- const newWallet = refreshedUser.user.verifiedCredentials.find((wallet)=>wallet.address.toLowerCase() === accountAddress.toLowerCase());
261
- const newWalletId = newWallet.id;
262
- this.walletMap[accountAddress] = {
237
+ // Update client key shares in wallet map
238
+ // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
239
+ // TODO: remove this once iframe handling for secret shares is implemented
240
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
241
+ clientKeyShares
242
+ });
243
+ // Backup the new wallet without waiting for the promise to resolve
244
+ void this.storeEncryptedBackupByWalletWithRetry({
263
245
  accountAddress,
264
- walletId: newWalletId,
265
- chainName: this.chainName,
266
246
  clientKeyShares,
267
- thresholdSignatureScheme,
268
- clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
269
- };
270
- await this.storeEncryptedBackupByWallet({
271
- accountAddress,
272
247
  password
273
248
  });
274
249
  return {
package/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DynamicWalletClient, timeoutPromise, getClientKeyShareBackupInfo, WalletOperation, MessageHash } from '@dynamic-labs-wallet/browser';
1
+ import { DynamicWalletClient, getClientKeyShareBackupInfo, WalletOperation, MessageHash } from '@dynamic-labs-wallet/browser';
2
2
  import { serializeSignature, createPublicClient, http, serializeTransaction, getAddress } from 'viem';
3
3
  import { mainnet } from 'viem/chains';
4
4
 
@@ -40,55 +40,39 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
40
40
  });
41
41
  }
42
42
  async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError }) {
43
- let ceremonyCompleted = false;
44
43
  try {
45
44
  // Generate key shares for given threshold signature scheme (TSS)
46
45
  const { rawPublicKey, clientKeyShares } = await this.keyGen({
47
46
  chainName: this.chainName,
48
47
  thresholdSignatureScheme,
49
48
  onError,
50
- onCeremonyComplete: ()=>{
51
- ceremonyCompleted = true;
49
+ onCeremonyComplete: (accountAddress, walletId)=>{
50
+ // update wallet map
51
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
52
+ accountAddress,
53
+ walletId,
54
+ chainName: this.chainName,
55
+ thresholdSignatureScheme,
56
+ clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
57
+ });
52
58
  }
53
59
  });
54
- // Wait for the ceremony to complete, timeout after 5 seconds
55
- await Promise.race([
56
- (async ()=>{
57
- while(!ceremonyCompleted){
58
- await new Promise((resolve)=>setTimeout(resolve, 100));
59
- }
60
- })(),
61
- timeoutPromise({
62
- timeInMs: 5000,
63
- activity: 'Ceremony'
64
- })
65
- ]);
66
60
  if (!rawPublicKey || !clientKeyShares) {
67
61
  throw new Error(ERROR_KEYGEN_FAILED);
68
62
  }
69
- // Get EVM address from public key
70
63
  const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
71
64
  rawPublicKey: rawPublicKey
72
65
  });
73
- // Refresh user to get the latest user data
74
- const refreshedUser = await this.apiClient.refreshUser();
75
- // Find the new wallet in the user's verified credentials
76
- const newWallet = refreshedUser.user.verifiedCredentials.find((wallet)=>wallet.address.toLowerCase() === accountAddress.toLowerCase());
77
- if (!newWallet) {
78
- throw new Error('Wallet not found after ceremony completion');
79
- }
80
- // Store the new wallet in the wallet map
81
- this.walletMap[accountAddress] = {
82
- accountAddress,
83
- walletId: newWallet.id,
84
- chainName: this.chainName,
85
- clientKeyShares: clientKeyShares,
86
- thresholdSignatureScheme,
87
- clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
88
- };
89
- // Backup the new wallet
90
- await this.storeEncryptedBackupByWallet({
66
+ // Update client key shares in wallet map
67
+ // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
68
+ // TODO: remove this once iframe handling for secret shares is implemented
69
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
70
+ clientKeyShares
71
+ });
72
+ // Backup the new wallet without waiting for the promise to resolve
73
+ void this.storeEncryptedBackupByWalletWithRetry({
91
74
  accountAddress,
75
+ clientKeyShares,
92
76
  password
93
77
  });
94
78
  return {
@@ -225,48 +209,39 @@ class DynamicEvmWalletClient extends DynamicWalletClient {
225
209
  };
226
210
  }
227
211
  async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError }) {
228
- let ceremonyCompleted = false;
229
212
  // TODO: validate private key for EVM
230
213
  const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
231
214
  chainName,
232
215
  privateKey,
233
216
  thresholdSignatureScheme,
234
217
  onError,
235
- onCeremonyComplete: ()=>{
236
- ceremonyCompleted = true;
218
+ onCeremonyComplete: (accountAddress, walletId)=>{
219
+ // update wallet map
220
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
221
+ accountAddress,
222
+ walletId,
223
+ chainName: this.chainName,
224
+ thresholdSignatureScheme,
225
+ clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
226
+ });
237
227
  }
238
228
  });
239
- // Wait for the ceremony to complete, timeout after 5 seconds
240
- await Promise.race([
241
- (async ()=>{
242
- while(!ceremonyCompleted){
243
- await new Promise((resolve)=>setTimeout(resolve, 100));
244
- }
245
- })(),
246
- timeoutPromise({
247
- timeInMs: 5000,
248
- activity: 'Ceremony'
249
- })
250
- ]);
251
229
  if (!rawPublicKey || !clientKeyShares) {
252
230
  throw new Error('Error creating wallet account');
253
231
  }
254
232
  const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
255
233
  rawPublicKey: rawPublicKey
256
234
  });
257
- const refreshedUser = await this.apiClient.refreshUser();
258
- const newWallet = refreshedUser.user.verifiedCredentials.find((wallet)=>wallet.address.toLowerCase() === accountAddress.toLowerCase());
259
- const newWalletId = newWallet.id;
260
- this.walletMap[accountAddress] = {
235
+ // Update client key shares in wallet map
236
+ // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
237
+ // TODO: remove this once iframe handling for secret shares is implemented
238
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
239
+ clientKeyShares
240
+ });
241
+ // Backup the new wallet without waiting for the promise to resolve
242
+ void this.storeEncryptedBackupByWalletWithRetry({
261
243
  accountAddress,
262
- walletId: newWalletId,
263
- chainName: this.chainName,
264
244
  clientKeyShares,
265
- thresholdSignatureScheme,
266
- clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
267
- };
268
- await this.storeEncryptedBackupByWallet({
269
- accountAddress,
270
245
  password
271
246
  });
272
247
  return {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@dynamic-labs-wallet/evm",
3
- "version": "0.0.46",
3
+ "version": "0.0.47",
4
4
  "license": "MIT",
5
5
  "dependencies": {
6
- "@dynamic-labs-wallet/browser": "0.0.46"
6
+ "@dynamic-labs-wallet/browser": "0.0.47"
7
7
  },
8
8
  "peerDependencies": {
9
9
  "viem": "^2.22.1"
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/client/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qCAAmC,CAAC;AAGxE,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,sCAAsC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/client/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qCAAmC,CAAC;AAGxE,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,sCACN,CAAC"}