@dynamic-labs-wallet/browser 0.0.29 → 0.0.31
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 +173 -66
- package/index.esm.js +173 -66
- package/package.json +2 -2
- package/src/backup/encryption.d.ts +5 -0
- package/src/backup/encryption.d.ts.map +1 -1
- package/src/backup/providers/googleDrive.d.ts +8 -3
- package/src/backup/providers/googleDrive.d.ts.map +1 -1
- package/src/client.d.ts +18 -15
- package/src/client.d.ts.map +1 -1
- package/src/types.d.ts +18 -0
- package/src/types.d.ts.map +1 -1
- package/src/utils.d.ts +5 -0
- package/src/utils.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -36,6 +36,10 @@ const getMPCSigner = ({ chainName, baseRelayUrl })=>{
|
|
|
36
36
|
return signatureScheme;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
const DEFAULT_LOG_LEVEL = 'INFO';
|
|
40
|
+
const STORAGE_KEY = 'dynamic-waas-wallet-client';
|
|
41
|
+
const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
|
|
42
|
+
|
|
39
43
|
const bytesToBase64 = (arr)=>{
|
|
40
44
|
return btoa(Array.from(arr, (b)=>String.fromCharCode(b)).join(''));
|
|
41
45
|
};
|
|
@@ -56,7 +60,15 @@ const isHexString = (str)=>{
|
|
|
56
60
|
// Check if string contains only hex characters
|
|
57
61
|
return /^[0-9A-Fa-f]+$/.test(hex);
|
|
58
62
|
};
|
|
63
|
+
const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress })=>{
|
|
64
|
+
return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}.json`;
|
|
65
|
+
};
|
|
59
66
|
|
|
67
|
+
const PBKDF2_ALGORITHM = 'PBKDF2';
|
|
68
|
+
const PBKDF2_ITERATIONS = 100000;
|
|
69
|
+
const PBKDF2_HASH_ALGORITHM = 'SHA-256';
|
|
70
|
+
const AES_GCM_ALGORITHM = 'AES-GCM';
|
|
71
|
+
const AES_GCM_LENGTH = 256;
|
|
60
72
|
const getKey = async ({ password, salt })=>{
|
|
61
73
|
const passwordBytes = stringToBytes(password);
|
|
62
74
|
const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
|
|
@@ -65,13 +77,13 @@ const getKey = async ({ password, salt })=>{
|
|
|
65
77
|
'deriveKey'
|
|
66
78
|
]);
|
|
67
79
|
return crypto.subtle.deriveKey({
|
|
68
|
-
name:
|
|
80
|
+
name: PBKDF2_ALGORITHM,
|
|
69
81
|
salt,
|
|
70
|
-
iterations:
|
|
71
|
-
hash:
|
|
82
|
+
iterations: PBKDF2_ITERATIONS,
|
|
83
|
+
hash: PBKDF2_HASH_ALGORITHM
|
|
72
84
|
}, initialKey, {
|
|
73
|
-
name:
|
|
74
|
-
length:
|
|
85
|
+
name: AES_GCM_ALGORITHM,
|
|
86
|
+
length: AES_GCM_LENGTH
|
|
75
87
|
}, false, [
|
|
76
88
|
'encrypt',
|
|
77
89
|
'decrypt'
|
|
@@ -90,7 +102,7 @@ const encryptData = async ({ data, password })=>{
|
|
|
90
102
|
const dataBytes = new TextEncoder().encode(data);
|
|
91
103
|
// Encrypt the data
|
|
92
104
|
const encryptedData = await crypto.subtle.encrypt({
|
|
93
|
-
name:
|
|
105
|
+
name: AES_GCM_ALGORITHM,
|
|
94
106
|
iv
|
|
95
107
|
}, key, dataBytes);
|
|
96
108
|
// Convert to base64 strings, ensure proper padding
|
|
@@ -119,24 +131,42 @@ const decryptData = async ({ data, password })=>{
|
|
|
119
131
|
salt: saltBytes
|
|
120
132
|
});
|
|
121
133
|
const decryptedData = await crypto.subtle.decrypt({
|
|
122
|
-
name:
|
|
134
|
+
name: AES_GCM_ALGORITHM,
|
|
123
135
|
iv: ivBytes
|
|
124
136
|
}, key, cipherBytes);
|
|
125
137
|
return new TextDecoder().decode(decryptedData);
|
|
126
138
|
} catch (error) {
|
|
127
139
|
console.error('Decryption error details:', error);
|
|
128
|
-
throw new Error(
|
|
140
|
+
throw new Error('Decryption failed');
|
|
129
141
|
}
|
|
130
142
|
};
|
|
131
143
|
|
|
132
144
|
const GOOGLE_DRIVE_UPLOAD_API = 'https://www.googleapis.com';
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
const uploadFileToGoogleDriveAppStorage = async ({ accessToken, fileName, jsonData })=>{
|
|
146
|
+
return uploadFileToGoogleDrive({
|
|
147
|
+
accessToken,
|
|
148
|
+
fileName,
|
|
149
|
+
jsonData,
|
|
137
150
|
parents: [
|
|
138
151
|
'appDataFolder'
|
|
139
152
|
]
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
const uploadFileToGoogleDrivePersonal = async ({ accessToken, fileName, jsonData })=>{
|
|
156
|
+
return uploadFileToGoogleDrive({
|
|
157
|
+
accessToken,
|
|
158
|
+
fileName,
|
|
159
|
+
jsonData,
|
|
160
|
+
parents: [
|
|
161
|
+
'root'
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const uploadFileToGoogleDrive = async ({ accessToken, fileName, jsonData, parents })=>{
|
|
166
|
+
const metadata = {
|
|
167
|
+
name: fileName,
|
|
168
|
+
mimeType: 'application/json',
|
|
169
|
+
parents
|
|
140
170
|
};
|
|
141
171
|
const form = new FormData();
|
|
142
172
|
form.append('metadata', new Blob([
|
|
@@ -182,6 +212,9 @@ const downloadFileFromGoogleDrive = async ({ accessToken, name })=>{
|
|
|
182
212
|
accessToken,
|
|
183
213
|
name
|
|
184
214
|
});
|
|
215
|
+
if (!files || files.length === 0) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
185
218
|
// Get the most recent file
|
|
186
219
|
const fileMetadata = files[0];
|
|
187
220
|
// Fetch the file data using the file ID
|
|
@@ -195,14 +228,16 @@ const downloadFileFromGoogleDrive = async ({ accessToken, name })=>{
|
|
|
195
228
|
if (fileRawData.length === 0) {
|
|
196
229
|
return null;
|
|
197
230
|
}
|
|
198
|
-
|
|
231
|
+
try {
|
|
232
|
+
// Just parse and return the data without validation
|
|
233
|
+
// The client will handle validation of the structure
|
|
234
|
+
return JSON.parse(fileRawData);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error('Error parsing backup file:', error);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
199
239
|
};
|
|
200
240
|
|
|
201
|
-
const DEFAULT_LOG_LEVEL = 'INFO';
|
|
202
|
-
const STORAGE_KEY = 'dynamic-waas-wallet-client';
|
|
203
|
-
const BACKUP_FILENAME = 'dynamicWalletKeyShareBackup.json';
|
|
204
|
-
const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
|
|
205
|
-
|
|
206
241
|
const localStorageWriteTest = {
|
|
207
242
|
tested: false,
|
|
208
243
|
writable: false
|
|
@@ -320,13 +355,11 @@ class DynamicWalletClient {
|
|
|
320
355
|
const keygenInitResults = await Promise.all(Array(clientThreshold).fill(null).map(()=>mpcSigner.initKeygen()));
|
|
321
356
|
return keygenInitResults;
|
|
322
357
|
}
|
|
323
|
-
async derivePublicKey({ chainName, keyShare,
|
|
358
|
+
async derivePublicKey({ chainName, keyShare, derivationPath }) {
|
|
324
359
|
const mpcSigner = getMPCSigner({
|
|
325
360
|
chainName,
|
|
326
361
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
327
362
|
});
|
|
328
|
-
const chainConfig = core.getMPCChainConfig(chainName);
|
|
329
|
-
const derivationPath = imported ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
330
363
|
let publicKey;
|
|
331
364
|
if (mpcSigner instanceof web.Ecdsa) {
|
|
332
365
|
publicKey = await mpcSigner.derivePubkey(keyShare, derivationPath);
|
|
@@ -356,10 +389,12 @@ class DynamicWalletClient {
|
|
|
356
389
|
}));
|
|
357
390
|
// only need one client keygen result to derive the public key
|
|
358
391
|
const [clientKeygenResult] = clientKeygenResults;
|
|
392
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
393
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
359
394
|
const rawPublicKey = await this.derivePublicKey({
|
|
360
395
|
chainName,
|
|
361
396
|
keyShare: clientKeygenResult,
|
|
362
|
-
|
|
397
|
+
derivationPath
|
|
363
398
|
});
|
|
364
399
|
return {
|
|
365
400
|
rawPublicKey,
|
|
@@ -405,14 +440,12 @@ class DynamicWalletClient {
|
|
|
405
440
|
});
|
|
406
441
|
return data;
|
|
407
442
|
}
|
|
408
|
-
async clientSign({ chainName, message, roomId, keyShare,
|
|
443
|
+
async clientSign({ chainName, message, roomId, keyShare, derivationPath }) {
|
|
409
444
|
try {
|
|
410
|
-
const chainConfig = core.getMPCChainConfig(chainName);
|
|
411
445
|
const mpcSigner = getMPCSigner({
|
|
412
446
|
chainName,
|
|
413
447
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
414
448
|
});
|
|
415
|
-
const derivationPath = imported ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
416
449
|
let formattedMessage;
|
|
417
450
|
//note: Ecdsa can also be used by bitcoin, but only keccak256 is used by ethereum
|
|
418
451
|
if (mpcSigner instanceof web.Ecdsa) {
|
|
@@ -440,23 +473,23 @@ class DynamicWalletClient {
|
|
|
440
473
|
}
|
|
441
474
|
}
|
|
442
475
|
//todo: need to modify with imported flag
|
|
443
|
-
async sign({ accountAddress, message, chainName
|
|
476
|
+
async sign({ accountAddress, message, chainName }) {
|
|
444
477
|
const wallet = await this.getWallet({
|
|
445
478
|
accountAddress
|
|
446
479
|
});
|
|
447
|
-
this.logger.debug('signing wallet', wallet);
|
|
448
480
|
// Perform the server sign
|
|
449
481
|
const data = await this.serverSign({
|
|
450
482
|
walletId: wallet.walletId,
|
|
451
483
|
message
|
|
452
484
|
});
|
|
485
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
453
486
|
// Perform the client sign and return the signature
|
|
454
487
|
const signature = await this.clientSign({
|
|
455
488
|
chainName,
|
|
456
489
|
message,
|
|
457
490
|
roomId: data.roomId,
|
|
458
491
|
keyShare: wallet.clientKeyShares[0],
|
|
459
|
-
|
|
492
|
+
derivationPath
|
|
460
493
|
});
|
|
461
494
|
return signature;
|
|
462
495
|
}
|
|
@@ -584,7 +617,6 @@ class DynamicWalletClient {
|
|
|
584
617
|
const wallet = await this.getWallet({
|
|
585
618
|
accountAddress
|
|
586
619
|
});
|
|
587
|
-
const chainConfig = core.getMPCChainConfig(chainName);
|
|
588
620
|
const mpcSigner = getMPCSigner({
|
|
589
621
|
chainName,
|
|
590
622
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
@@ -601,7 +633,7 @@ class DynamicWalletClient {
|
|
|
601
633
|
if (!keyExportRaw) {
|
|
602
634
|
throw new Error('Error exporting private key');
|
|
603
635
|
}
|
|
604
|
-
const derivationPath = new Uint32Array(
|
|
636
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
605
637
|
let derivedPrivateKey;
|
|
606
638
|
if (mpcSigner instanceof web.Ecdsa) {
|
|
607
639
|
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
@@ -614,7 +646,7 @@ class DynamicWalletClient {
|
|
|
614
646
|
derivedPrivateKey
|
|
615
647
|
};
|
|
616
648
|
}
|
|
617
|
-
async offlineExportKey({ chainName, keyShares }) {
|
|
649
|
+
async offlineExportKey({ chainName, keyShares, derivationPath }) {
|
|
618
650
|
try {
|
|
619
651
|
if (!keyShares || keyShares.length < 2) {
|
|
620
652
|
throw new Error(`Must provide at least min threshold of key shares`);
|
|
@@ -631,14 +663,14 @@ class DynamicWalletClient {
|
|
|
631
663
|
throw new Error('Error exporting private key: Export returned null');
|
|
632
664
|
}
|
|
633
665
|
const chainConfig = core.getMPCChainConfig(chainName);
|
|
634
|
-
const
|
|
666
|
+
const walletDerivationPath = !derivationPath ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
635
667
|
let derivedPrivateKey;
|
|
636
668
|
if (mpcSigner instanceof web.Ecdsa) {
|
|
637
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw,
|
|
669
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
638
670
|
} else if (mpcSigner instanceof web.Ed25519) {
|
|
639
671
|
derivedPrivateKey = keyExportRaw;
|
|
640
672
|
} else if (mpcSigner instanceof web.BIP340) {
|
|
641
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw,
|
|
673
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
642
674
|
}
|
|
643
675
|
return {
|
|
644
676
|
derivedPrivateKey
|
|
@@ -682,14 +714,15 @@ class DynamicWalletClient {
|
|
|
682
714
|
const deserializedKeyShare = JSON.parse(decryptedKeyShare);
|
|
683
715
|
return deserializedKeyShare;
|
|
684
716
|
}
|
|
685
|
-
async recoverEncryptedBackupByWallet({ accountAddress, password
|
|
717
|
+
async recoverEncryptedBackupByWallet({ accountAddress, password }) {
|
|
686
718
|
const wallet = this.walletMap[accountAddress];
|
|
687
719
|
this.logger.debug('recoverEncryptedBackupByWallet wallet', wallet);
|
|
688
720
|
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
689
|
-
walletId: wallet.walletId
|
|
690
|
-
keyShareIds
|
|
721
|
+
walletId: wallet.walletId
|
|
691
722
|
});
|
|
692
|
-
|
|
723
|
+
// TODO: allow handling backup from other sources
|
|
724
|
+
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === 'dynamic');
|
|
725
|
+
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
693
726
|
keyShare: keyShare.encryptedAccountCredential,
|
|
694
727
|
password: password != null ? password : this.environmentId
|
|
695
728
|
})));
|
|
@@ -699,7 +732,8 @@ class DynamicWalletClient {
|
|
|
699
732
|
accountAddress,
|
|
700
733
|
chainName: data.chainName,
|
|
701
734
|
keyShare,
|
|
702
|
-
thresholdSignatureScheme: wallet.thresholdSignatureScheme
|
|
735
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
736
|
+
derivationPath: wallet.derivationPath
|
|
703
737
|
});
|
|
704
738
|
});
|
|
705
739
|
return decryptedKeyShares;
|
|
@@ -712,7 +746,7 @@ class DynamicWalletClient {
|
|
|
712
746
|
}
|
|
713
747
|
this.walletMap = JSON.parse(wallets);
|
|
714
748
|
}
|
|
715
|
-
async restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme }) {
|
|
749
|
+
async restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme, derivationPath }) {
|
|
716
750
|
var _this_walletMap_accountAddress;
|
|
717
751
|
this.walletMap[accountAddress] = {
|
|
718
752
|
walletId,
|
|
@@ -722,46 +756,109 @@ class DynamicWalletClient {
|
|
|
722
756
|
...((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.clientKeyShares) || [],
|
|
723
757
|
keyShare
|
|
724
758
|
],
|
|
725
|
-
thresholdSignatureScheme
|
|
759
|
+
thresholdSignatureScheme,
|
|
760
|
+
derivationPath
|
|
726
761
|
};
|
|
727
762
|
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
728
763
|
}
|
|
729
|
-
async backupKeySharesToGoogleDrive({ accountAddress, fileName
|
|
730
|
-
|
|
764
|
+
async backupKeySharesToGoogleDrive({ accountAddress, fileName, oauthAccountId, password }) {
|
|
765
|
+
await this.getWallet({
|
|
766
|
+
accountAddress
|
|
767
|
+
});
|
|
768
|
+
const clientKeyShares = this.walletMap[accountAddress].clientKeyShares;
|
|
769
|
+
if (clientKeyShares.length === 0) {
|
|
770
|
+
throw new Error('No key shares found');
|
|
771
|
+
}
|
|
772
|
+
const encryptedKeyShares = await Promise.all(clientKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
731
773
|
keyShare,
|
|
732
774
|
password
|
|
733
775
|
})));
|
|
734
776
|
const accessToken = await this.apiClient.getAccessToken({
|
|
735
777
|
oauthAccountId
|
|
736
778
|
});
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
779
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
780
|
+
const suggestedFileName = getClientKeyShareExportFileName({
|
|
781
|
+
thresholdSignatureScheme,
|
|
782
|
+
accountAddress
|
|
741
783
|
});
|
|
784
|
+
const backupData = {
|
|
785
|
+
keyShares: encryptedKeyShares,
|
|
786
|
+
metadata: {
|
|
787
|
+
version: '1.0',
|
|
788
|
+
createdAt: new Date().toISOString(),
|
|
789
|
+
accountAddress,
|
|
790
|
+
thresholdSignatureScheme,
|
|
791
|
+
hasPassword: true,
|
|
792
|
+
encryption: {
|
|
793
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
794
|
+
keyDerivation: PBKDF2_ALGORITHM,
|
|
795
|
+
iterations: PBKDF2_ITERATIONS,
|
|
796
|
+
hashAlgorithm: PBKDF2_HASH_ALGORITHM,
|
|
797
|
+
algorithmLength: AES_GCM_LENGTH
|
|
798
|
+
},
|
|
799
|
+
shareCount: encryptedKeyShares.length
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
// TODO: handle errors
|
|
803
|
+
const [appUpload, personalUpload] = await Promise.all([
|
|
804
|
+
uploadFileToGoogleDriveAppStorage({
|
|
805
|
+
accessToken,
|
|
806
|
+
fileName: fileName != null ? fileName : suggestedFileName,
|
|
807
|
+
jsonData: backupData
|
|
808
|
+
}),
|
|
809
|
+
uploadFileToGoogleDrivePersonal({
|
|
810
|
+
accessToken,
|
|
811
|
+
fileName: fileName != null ? fileName : suggestedFileName,
|
|
812
|
+
jsonData: backupData
|
|
813
|
+
})
|
|
814
|
+
]);
|
|
742
815
|
await this.apiClient.markKeySharesAsBackedUpGoogleDrive({
|
|
743
816
|
walletId: this.walletMap[accountAddress].walletId
|
|
744
817
|
});
|
|
745
|
-
return
|
|
818
|
+
return {
|
|
819
|
+
appUpload,
|
|
820
|
+
personalUpload
|
|
821
|
+
};
|
|
746
822
|
}
|
|
747
|
-
async restoreBackupFromGoogleDrive({ oauthAccountId, name
|
|
823
|
+
async restoreBackupFromGoogleDrive({ accountAddress, oauthAccountId, name, password }) {
|
|
824
|
+
await this.getWallet({
|
|
825
|
+
accountAddress
|
|
826
|
+
});
|
|
748
827
|
const accessToken = await this.apiClient.getAccessToken({
|
|
749
828
|
oauthAccountId
|
|
750
829
|
});
|
|
751
|
-
const
|
|
830
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
831
|
+
const suggestedFileName = getClientKeyShareExportFileName({
|
|
832
|
+
thresholdSignatureScheme,
|
|
833
|
+
accountAddress
|
|
834
|
+
});
|
|
835
|
+
const backupData = await downloadFileFromGoogleDrive({
|
|
752
836
|
accessToken,
|
|
753
|
-
name
|
|
837
|
+
name: name != null ? name : suggestedFileName
|
|
754
838
|
});
|
|
755
|
-
if (!
|
|
756
|
-
throw new Error('No file found');
|
|
839
|
+
if (!backupData) {
|
|
840
|
+
throw new Error('No backup file found');
|
|
757
841
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
842
|
+
// Validate the backup data structure
|
|
843
|
+
if (!backupData.keyShares || !backupData.metadata) {
|
|
844
|
+
throw new Error('Invalid backup format: missing keyShares or metadata');
|
|
845
|
+
}
|
|
846
|
+
const { keyShares } = backupData;
|
|
847
|
+
const decryptedKeyShares = await Promise.all(keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
762
848
|
keyShare,
|
|
763
|
-
password
|
|
849
|
+
password
|
|
764
850
|
})));
|
|
851
|
+
const existingKeyShares = this.walletMap[accountAddress].clientKeyShares || [];
|
|
852
|
+
const uniqueKeyShares = decryptedKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
|
|
853
|
+
if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
|
|
854
|
+
return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
|
|
855
|
+
}));
|
|
856
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
857
|
+
clientKeyShares: [
|
|
858
|
+
...existingKeyShares,
|
|
859
|
+
...uniqueKeyShares
|
|
860
|
+
]
|
|
861
|
+
});
|
|
765
862
|
return decryptedKeyShares;
|
|
766
863
|
}
|
|
767
864
|
async importRawPrivateKey({ chainName, privateKey, thresholdSignatureScheme }) {
|
|
@@ -801,7 +898,7 @@ class DynamicWalletClient {
|
|
|
801
898
|
const rawPublicKey = await this.derivePublicKey({
|
|
802
899
|
chainName,
|
|
803
900
|
keyShare: clientKeygenResult,
|
|
804
|
-
|
|
901
|
+
derivationPath: undefined
|
|
805
902
|
});
|
|
806
903
|
return {
|
|
807
904
|
rawPublicKey,
|
|
@@ -812,7 +909,14 @@ class DynamicWalletClient {
|
|
|
812
909
|
const clientKeyShares = await this.getClientKeyShares({
|
|
813
910
|
accountAddress
|
|
814
911
|
});
|
|
815
|
-
|
|
912
|
+
if (!accountAddress) {
|
|
913
|
+
throw new Error('Must provide an account address');
|
|
914
|
+
}
|
|
915
|
+
const derivationPath = this.walletMap[accountAddress].derivationPath;
|
|
916
|
+
const text = JSON.stringify({
|
|
917
|
+
keyShares: clientKeyShares,
|
|
918
|
+
derivationPath
|
|
919
|
+
});
|
|
816
920
|
const blob = new Blob([
|
|
817
921
|
text
|
|
818
922
|
], {
|
|
@@ -832,7 +936,7 @@ class DynamicWalletClient {
|
|
|
832
936
|
}
|
|
833
937
|
async getWallet({ accountAddress }) {
|
|
834
938
|
if (accountAddress) {
|
|
835
|
-
if (this.walletMap[accountAddress] && this.walletMap[accountAddress].clientKeyShares.length > 0) {
|
|
939
|
+
if (this.walletMap[accountAddress] && this.walletMap[accountAddress].clientKeyShares.length > 0 && this.walletMap[accountAddress].thresholdSignatureScheme && this.walletMap[accountAddress].derivationPath) {
|
|
836
940
|
this.logger.debug('Wallet already exists', this.walletMap[accountAddress]);
|
|
837
941
|
return this.walletMap[accountAddress];
|
|
838
942
|
} else {
|
|
@@ -848,7 +952,8 @@ class DynamicWalletClient {
|
|
|
848
952
|
walletId: wallet.id,
|
|
849
953
|
chainName: wallet.chainName,
|
|
850
954
|
accountAddress,
|
|
851
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme
|
|
955
|
+
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
956
|
+
derivationPath: walletProperties.derivationPath
|
|
852
957
|
});
|
|
853
958
|
// restore backup
|
|
854
959
|
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
@@ -883,13 +988,15 @@ class DynamicWalletClient {
|
|
|
883
988
|
accountAddress: vc.address
|
|
884
989
|
}));
|
|
885
990
|
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
886
|
-
var
|
|
991
|
+
var _acc_accountAddress, _acc_accountAddress1, _acc_accountAddress2;
|
|
992
|
+
const accountAddress = wallet.accountAddress;
|
|
887
993
|
acc[wallet.accountAddress] = {
|
|
888
994
|
walletId: wallet.walletId,
|
|
889
995
|
chainName: wallet.chainName,
|
|
890
|
-
accountAddress:
|
|
891
|
-
clientKeyShares: ((
|
|
892
|
-
thresholdSignatureScheme: ((
|
|
996
|
+
accountAddress: accountAddress,
|
|
997
|
+
clientKeyShares: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.clientKeyShares) || [],
|
|
998
|
+
thresholdSignatureScheme: ((_acc_accountAddress1 = acc[accountAddress]) == null ? void 0 : _acc_accountAddress1.thresholdSignatureScheme) || undefined,
|
|
999
|
+
derivationPath: ((_acc_accountAddress2 = acc[accountAddress]) == null ? void 0 : _acc_accountAddress2.derivationPath) || undefined
|
|
893
1000
|
};
|
|
894
1001
|
return acc;
|
|
895
1002
|
}, {});
|
package/index.esm.js
CHANGED
|
@@ -36,6 +36,10 @@ const getMPCSigner = ({ chainName, baseRelayUrl })=>{
|
|
|
36
36
|
return signatureScheme;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
const DEFAULT_LOG_LEVEL = 'INFO';
|
|
40
|
+
const STORAGE_KEY = 'dynamic-waas-wallet-client';
|
|
41
|
+
const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
|
|
42
|
+
|
|
39
43
|
const bytesToBase64 = (arr)=>{
|
|
40
44
|
return btoa(Array.from(arr, (b)=>String.fromCharCode(b)).join(''));
|
|
41
45
|
};
|
|
@@ -56,7 +60,15 @@ const isHexString = (str)=>{
|
|
|
56
60
|
// Check if string contains only hex characters
|
|
57
61
|
return /^[0-9A-Fa-f]+$/.test(hex);
|
|
58
62
|
};
|
|
63
|
+
const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress })=>{
|
|
64
|
+
return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}.json`;
|
|
65
|
+
};
|
|
59
66
|
|
|
67
|
+
const PBKDF2_ALGORITHM = 'PBKDF2';
|
|
68
|
+
const PBKDF2_ITERATIONS = 100000;
|
|
69
|
+
const PBKDF2_HASH_ALGORITHM = 'SHA-256';
|
|
70
|
+
const AES_GCM_ALGORITHM = 'AES-GCM';
|
|
71
|
+
const AES_GCM_LENGTH = 256;
|
|
60
72
|
const getKey = async ({ password, salt })=>{
|
|
61
73
|
const passwordBytes = stringToBytes(password);
|
|
62
74
|
const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
|
|
@@ -65,13 +77,13 @@ const getKey = async ({ password, salt })=>{
|
|
|
65
77
|
'deriveKey'
|
|
66
78
|
]);
|
|
67
79
|
return crypto.subtle.deriveKey({
|
|
68
|
-
name:
|
|
80
|
+
name: PBKDF2_ALGORITHM,
|
|
69
81
|
salt,
|
|
70
|
-
iterations:
|
|
71
|
-
hash:
|
|
82
|
+
iterations: PBKDF2_ITERATIONS,
|
|
83
|
+
hash: PBKDF2_HASH_ALGORITHM
|
|
72
84
|
}, initialKey, {
|
|
73
|
-
name:
|
|
74
|
-
length:
|
|
85
|
+
name: AES_GCM_ALGORITHM,
|
|
86
|
+
length: AES_GCM_LENGTH
|
|
75
87
|
}, false, [
|
|
76
88
|
'encrypt',
|
|
77
89
|
'decrypt'
|
|
@@ -90,7 +102,7 @@ const encryptData = async ({ data, password })=>{
|
|
|
90
102
|
const dataBytes = new TextEncoder().encode(data);
|
|
91
103
|
// Encrypt the data
|
|
92
104
|
const encryptedData = await crypto.subtle.encrypt({
|
|
93
|
-
name:
|
|
105
|
+
name: AES_GCM_ALGORITHM,
|
|
94
106
|
iv
|
|
95
107
|
}, key, dataBytes);
|
|
96
108
|
// Convert to base64 strings, ensure proper padding
|
|
@@ -119,24 +131,42 @@ const decryptData = async ({ data, password })=>{
|
|
|
119
131
|
salt: saltBytes
|
|
120
132
|
});
|
|
121
133
|
const decryptedData = await crypto.subtle.decrypt({
|
|
122
|
-
name:
|
|
134
|
+
name: AES_GCM_ALGORITHM,
|
|
123
135
|
iv: ivBytes
|
|
124
136
|
}, key, cipherBytes);
|
|
125
137
|
return new TextDecoder().decode(decryptedData);
|
|
126
138
|
} catch (error) {
|
|
127
139
|
console.error('Decryption error details:', error);
|
|
128
|
-
throw new Error(
|
|
140
|
+
throw new Error('Decryption failed');
|
|
129
141
|
}
|
|
130
142
|
};
|
|
131
143
|
|
|
132
144
|
const GOOGLE_DRIVE_UPLOAD_API = 'https://www.googleapis.com';
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
const uploadFileToGoogleDriveAppStorage = async ({ accessToken, fileName, jsonData })=>{
|
|
146
|
+
return uploadFileToGoogleDrive({
|
|
147
|
+
accessToken,
|
|
148
|
+
fileName,
|
|
149
|
+
jsonData,
|
|
137
150
|
parents: [
|
|
138
151
|
'appDataFolder'
|
|
139
152
|
]
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
const uploadFileToGoogleDrivePersonal = async ({ accessToken, fileName, jsonData })=>{
|
|
156
|
+
return uploadFileToGoogleDrive({
|
|
157
|
+
accessToken,
|
|
158
|
+
fileName,
|
|
159
|
+
jsonData,
|
|
160
|
+
parents: [
|
|
161
|
+
'root'
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const uploadFileToGoogleDrive = async ({ accessToken, fileName, jsonData, parents })=>{
|
|
166
|
+
const metadata = {
|
|
167
|
+
name: fileName,
|
|
168
|
+
mimeType: 'application/json',
|
|
169
|
+
parents
|
|
140
170
|
};
|
|
141
171
|
const form = new FormData();
|
|
142
172
|
form.append('metadata', new Blob([
|
|
@@ -182,6 +212,9 @@ const downloadFileFromGoogleDrive = async ({ accessToken, name })=>{
|
|
|
182
212
|
accessToken,
|
|
183
213
|
name
|
|
184
214
|
});
|
|
215
|
+
if (!files || files.length === 0) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
185
218
|
// Get the most recent file
|
|
186
219
|
const fileMetadata = files[0];
|
|
187
220
|
// Fetch the file data using the file ID
|
|
@@ -195,14 +228,16 @@ const downloadFileFromGoogleDrive = async ({ accessToken, name })=>{
|
|
|
195
228
|
if (fileRawData.length === 0) {
|
|
196
229
|
return null;
|
|
197
230
|
}
|
|
198
|
-
|
|
231
|
+
try {
|
|
232
|
+
// Just parse and return the data without validation
|
|
233
|
+
// The client will handle validation of the structure
|
|
234
|
+
return JSON.parse(fileRawData);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error('Error parsing backup file:', error);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
199
239
|
};
|
|
200
240
|
|
|
201
|
-
const DEFAULT_LOG_LEVEL = 'INFO';
|
|
202
|
-
const STORAGE_KEY = 'dynamic-waas-wallet-client';
|
|
203
|
-
const BACKUP_FILENAME = 'dynamicWalletKeyShareBackup.json';
|
|
204
|
-
const CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX = 'dynamicWalletKeyShareBackup';
|
|
205
|
-
|
|
206
241
|
const localStorageWriteTest = {
|
|
207
242
|
tested: false,
|
|
208
243
|
writable: false
|
|
@@ -320,13 +355,11 @@ class DynamicWalletClient {
|
|
|
320
355
|
const keygenInitResults = await Promise.all(Array(clientThreshold).fill(null).map(()=>mpcSigner.initKeygen()));
|
|
321
356
|
return keygenInitResults;
|
|
322
357
|
}
|
|
323
|
-
async derivePublicKey({ chainName, keyShare,
|
|
358
|
+
async derivePublicKey({ chainName, keyShare, derivationPath }) {
|
|
324
359
|
const mpcSigner = getMPCSigner({
|
|
325
360
|
chainName,
|
|
326
361
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
327
362
|
});
|
|
328
|
-
const chainConfig = getMPCChainConfig(chainName);
|
|
329
|
-
const derivationPath = imported ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
330
363
|
let publicKey;
|
|
331
364
|
if (mpcSigner instanceof Ecdsa) {
|
|
332
365
|
publicKey = await mpcSigner.derivePubkey(keyShare, derivationPath);
|
|
@@ -356,10 +389,12 @@ class DynamicWalletClient {
|
|
|
356
389
|
}));
|
|
357
390
|
// only need one client keygen result to derive the public key
|
|
358
391
|
const [clientKeygenResult] = clientKeygenResults;
|
|
392
|
+
const chainConfig = getMPCChainConfig(chainName);
|
|
393
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
359
394
|
const rawPublicKey = await this.derivePublicKey({
|
|
360
395
|
chainName,
|
|
361
396
|
keyShare: clientKeygenResult,
|
|
362
|
-
|
|
397
|
+
derivationPath
|
|
363
398
|
});
|
|
364
399
|
return {
|
|
365
400
|
rawPublicKey,
|
|
@@ -405,14 +440,12 @@ class DynamicWalletClient {
|
|
|
405
440
|
});
|
|
406
441
|
return data;
|
|
407
442
|
}
|
|
408
|
-
async clientSign({ chainName, message, roomId, keyShare,
|
|
443
|
+
async clientSign({ chainName, message, roomId, keyShare, derivationPath }) {
|
|
409
444
|
try {
|
|
410
|
-
const chainConfig = getMPCChainConfig(chainName);
|
|
411
445
|
const mpcSigner = getMPCSigner({
|
|
412
446
|
chainName,
|
|
413
447
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
414
448
|
});
|
|
415
|
-
const derivationPath = imported ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
416
449
|
let formattedMessage;
|
|
417
450
|
//note: Ecdsa can also be used by bitcoin, but only keccak256 is used by ethereum
|
|
418
451
|
if (mpcSigner instanceof Ecdsa) {
|
|
@@ -440,23 +473,23 @@ class DynamicWalletClient {
|
|
|
440
473
|
}
|
|
441
474
|
}
|
|
442
475
|
//todo: need to modify with imported flag
|
|
443
|
-
async sign({ accountAddress, message, chainName
|
|
476
|
+
async sign({ accountAddress, message, chainName }) {
|
|
444
477
|
const wallet = await this.getWallet({
|
|
445
478
|
accountAddress
|
|
446
479
|
});
|
|
447
|
-
this.logger.debug('signing wallet', wallet);
|
|
448
480
|
// Perform the server sign
|
|
449
481
|
const data = await this.serverSign({
|
|
450
482
|
walletId: wallet.walletId,
|
|
451
483
|
message
|
|
452
484
|
});
|
|
485
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
453
486
|
// Perform the client sign and return the signature
|
|
454
487
|
const signature = await this.clientSign({
|
|
455
488
|
chainName,
|
|
456
489
|
message,
|
|
457
490
|
roomId: data.roomId,
|
|
458
491
|
keyShare: wallet.clientKeyShares[0],
|
|
459
|
-
|
|
492
|
+
derivationPath
|
|
460
493
|
});
|
|
461
494
|
return signature;
|
|
462
495
|
}
|
|
@@ -584,7 +617,6 @@ class DynamicWalletClient {
|
|
|
584
617
|
const wallet = await this.getWallet({
|
|
585
618
|
accountAddress
|
|
586
619
|
});
|
|
587
|
-
const chainConfig = getMPCChainConfig(chainName);
|
|
588
620
|
const mpcSigner = getMPCSigner({
|
|
589
621
|
chainName,
|
|
590
622
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
@@ -601,7 +633,7 @@ class DynamicWalletClient {
|
|
|
601
633
|
if (!keyExportRaw) {
|
|
602
634
|
throw new Error('Error exporting private key');
|
|
603
635
|
}
|
|
604
|
-
const derivationPath = new Uint32Array(
|
|
636
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
605
637
|
let derivedPrivateKey;
|
|
606
638
|
if (mpcSigner instanceof Ecdsa) {
|
|
607
639
|
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
@@ -614,7 +646,7 @@ class DynamicWalletClient {
|
|
|
614
646
|
derivedPrivateKey
|
|
615
647
|
};
|
|
616
648
|
}
|
|
617
|
-
async offlineExportKey({ chainName, keyShares }) {
|
|
649
|
+
async offlineExportKey({ chainName, keyShares, derivationPath }) {
|
|
618
650
|
try {
|
|
619
651
|
if (!keyShares || keyShares.length < 2) {
|
|
620
652
|
throw new Error(`Must provide at least min threshold of key shares`);
|
|
@@ -631,14 +663,14 @@ class DynamicWalletClient {
|
|
|
631
663
|
throw new Error('Error exporting private key: Export returned null');
|
|
632
664
|
}
|
|
633
665
|
const chainConfig = getMPCChainConfig(chainName);
|
|
634
|
-
const
|
|
666
|
+
const walletDerivationPath = !derivationPath ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
635
667
|
let derivedPrivateKey;
|
|
636
668
|
if (mpcSigner instanceof Ecdsa) {
|
|
637
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw,
|
|
669
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
638
670
|
} else if (mpcSigner instanceof Ed25519) {
|
|
639
671
|
derivedPrivateKey = keyExportRaw;
|
|
640
672
|
} else if (mpcSigner instanceof BIP340) {
|
|
641
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw,
|
|
673
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
642
674
|
}
|
|
643
675
|
return {
|
|
644
676
|
derivedPrivateKey
|
|
@@ -682,14 +714,15 @@ class DynamicWalletClient {
|
|
|
682
714
|
const deserializedKeyShare = JSON.parse(decryptedKeyShare);
|
|
683
715
|
return deserializedKeyShare;
|
|
684
716
|
}
|
|
685
|
-
async recoverEncryptedBackupByWallet({ accountAddress, password
|
|
717
|
+
async recoverEncryptedBackupByWallet({ accountAddress, password }) {
|
|
686
718
|
const wallet = this.walletMap[accountAddress];
|
|
687
719
|
this.logger.debug('recoverEncryptedBackupByWallet wallet', wallet);
|
|
688
720
|
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
689
|
-
walletId: wallet.walletId
|
|
690
|
-
keyShareIds
|
|
721
|
+
walletId: wallet.walletId
|
|
691
722
|
});
|
|
692
|
-
|
|
723
|
+
// TODO: allow handling backup from other sources
|
|
724
|
+
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === 'dynamic');
|
|
725
|
+
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
693
726
|
keyShare: keyShare.encryptedAccountCredential,
|
|
694
727
|
password: password != null ? password : this.environmentId
|
|
695
728
|
})));
|
|
@@ -699,7 +732,8 @@ class DynamicWalletClient {
|
|
|
699
732
|
accountAddress,
|
|
700
733
|
chainName: data.chainName,
|
|
701
734
|
keyShare,
|
|
702
|
-
thresholdSignatureScheme: wallet.thresholdSignatureScheme
|
|
735
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
736
|
+
derivationPath: wallet.derivationPath
|
|
703
737
|
});
|
|
704
738
|
});
|
|
705
739
|
return decryptedKeyShares;
|
|
@@ -712,7 +746,7 @@ class DynamicWalletClient {
|
|
|
712
746
|
}
|
|
713
747
|
this.walletMap = JSON.parse(wallets);
|
|
714
748
|
}
|
|
715
|
-
async restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme }) {
|
|
749
|
+
async restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme, derivationPath }) {
|
|
716
750
|
var _this_walletMap_accountAddress;
|
|
717
751
|
this.walletMap[accountAddress] = {
|
|
718
752
|
walletId,
|
|
@@ -722,46 +756,109 @@ class DynamicWalletClient {
|
|
|
722
756
|
...((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.clientKeyShares) || [],
|
|
723
757
|
keyShare
|
|
724
758
|
],
|
|
725
|
-
thresholdSignatureScheme
|
|
759
|
+
thresholdSignatureScheme,
|
|
760
|
+
derivationPath
|
|
726
761
|
};
|
|
727
762
|
await this.storage.setItem(this.storageKey, JSON.stringify(this.walletMap));
|
|
728
763
|
}
|
|
729
|
-
async backupKeySharesToGoogleDrive({ accountAddress, fileName
|
|
730
|
-
|
|
764
|
+
async backupKeySharesToGoogleDrive({ accountAddress, fileName, oauthAccountId, password }) {
|
|
765
|
+
await this.getWallet({
|
|
766
|
+
accountAddress
|
|
767
|
+
});
|
|
768
|
+
const clientKeyShares = this.walletMap[accountAddress].clientKeyShares;
|
|
769
|
+
if (clientKeyShares.length === 0) {
|
|
770
|
+
throw new Error('No key shares found');
|
|
771
|
+
}
|
|
772
|
+
const encryptedKeyShares = await Promise.all(clientKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
731
773
|
keyShare,
|
|
732
774
|
password
|
|
733
775
|
})));
|
|
734
776
|
const accessToken = await this.apiClient.getAccessToken({
|
|
735
777
|
oauthAccountId
|
|
736
778
|
});
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
779
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
780
|
+
const suggestedFileName = getClientKeyShareExportFileName({
|
|
781
|
+
thresholdSignatureScheme,
|
|
782
|
+
accountAddress
|
|
741
783
|
});
|
|
784
|
+
const backupData = {
|
|
785
|
+
keyShares: encryptedKeyShares,
|
|
786
|
+
metadata: {
|
|
787
|
+
version: '1.0',
|
|
788
|
+
createdAt: new Date().toISOString(),
|
|
789
|
+
accountAddress,
|
|
790
|
+
thresholdSignatureScheme,
|
|
791
|
+
hasPassword: true,
|
|
792
|
+
encryption: {
|
|
793
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
794
|
+
keyDerivation: PBKDF2_ALGORITHM,
|
|
795
|
+
iterations: PBKDF2_ITERATIONS,
|
|
796
|
+
hashAlgorithm: PBKDF2_HASH_ALGORITHM,
|
|
797
|
+
algorithmLength: AES_GCM_LENGTH
|
|
798
|
+
},
|
|
799
|
+
shareCount: encryptedKeyShares.length
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
// TODO: handle errors
|
|
803
|
+
const [appUpload, personalUpload] = await Promise.all([
|
|
804
|
+
uploadFileToGoogleDriveAppStorage({
|
|
805
|
+
accessToken,
|
|
806
|
+
fileName: fileName != null ? fileName : suggestedFileName,
|
|
807
|
+
jsonData: backupData
|
|
808
|
+
}),
|
|
809
|
+
uploadFileToGoogleDrivePersonal({
|
|
810
|
+
accessToken,
|
|
811
|
+
fileName: fileName != null ? fileName : suggestedFileName,
|
|
812
|
+
jsonData: backupData
|
|
813
|
+
})
|
|
814
|
+
]);
|
|
742
815
|
await this.apiClient.markKeySharesAsBackedUpGoogleDrive({
|
|
743
816
|
walletId: this.walletMap[accountAddress].walletId
|
|
744
817
|
});
|
|
745
|
-
return
|
|
818
|
+
return {
|
|
819
|
+
appUpload,
|
|
820
|
+
personalUpload
|
|
821
|
+
};
|
|
746
822
|
}
|
|
747
|
-
async restoreBackupFromGoogleDrive({ oauthAccountId, name
|
|
823
|
+
async restoreBackupFromGoogleDrive({ accountAddress, oauthAccountId, name, password }) {
|
|
824
|
+
await this.getWallet({
|
|
825
|
+
accountAddress
|
|
826
|
+
});
|
|
748
827
|
const accessToken = await this.apiClient.getAccessToken({
|
|
749
828
|
oauthAccountId
|
|
750
829
|
});
|
|
751
|
-
const
|
|
830
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
831
|
+
const suggestedFileName = getClientKeyShareExportFileName({
|
|
832
|
+
thresholdSignatureScheme,
|
|
833
|
+
accountAddress
|
|
834
|
+
});
|
|
835
|
+
const backupData = await downloadFileFromGoogleDrive({
|
|
752
836
|
accessToken,
|
|
753
|
-
name
|
|
837
|
+
name: name != null ? name : suggestedFileName
|
|
754
838
|
});
|
|
755
|
-
if (!
|
|
756
|
-
throw new Error('No file found');
|
|
839
|
+
if (!backupData) {
|
|
840
|
+
throw new Error('No backup file found');
|
|
757
841
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
842
|
+
// Validate the backup data structure
|
|
843
|
+
if (!backupData.keyShares || !backupData.metadata) {
|
|
844
|
+
throw new Error('Invalid backup format: missing keyShares or metadata');
|
|
845
|
+
}
|
|
846
|
+
const { keyShares } = backupData;
|
|
847
|
+
const decryptedKeyShares = await Promise.all(keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
762
848
|
keyShare,
|
|
763
|
-
password
|
|
849
|
+
password
|
|
764
850
|
})));
|
|
851
|
+
const existingKeyShares = this.walletMap[accountAddress].clientKeyShares || [];
|
|
852
|
+
const uniqueKeyShares = decryptedKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
|
|
853
|
+
if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
|
|
854
|
+
return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
|
|
855
|
+
}));
|
|
856
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
857
|
+
clientKeyShares: [
|
|
858
|
+
...existingKeyShares,
|
|
859
|
+
...uniqueKeyShares
|
|
860
|
+
]
|
|
861
|
+
});
|
|
765
862
|
return decryptedKeyShares;
|
|
766
863
|
}
|
|
767
864
|
async importRawPrivateKey({ chainName, privateKey, thresholdSignatureScheme }) {
|
|
@@ -801,7 +898,7 @@ class DynamicWalletClient {
|
|
|
801
898
|
const rawPublicKey = await this.derivePublicKey({
|
|
802
899
|
chainName,
|
|
803
900
|
keyShare: clientKeygenResult,
|
|
804
|
-
|
|
901
|
+
derivationPath: undefined
|
|
805
902
|
});
|
|
806
903
|
return {
|
|
807
904
|
rawPublicKey,
|
|
@@ -812,7 +909,14 @@ class DynamicWalletClient {
|
|
|
812
909
|
const clientKeyShares = await this.getClientKeyShares({
|
|
813
910
|
accountAddress
|
|
814
911
|
});
|
|
815
|
-
|
|
912
|
+
if (!accountAddress) {
|
|
913
|
+
throw new Error('Must provide an account address');
|
|
914
|
+
}
|
|
915
|
+
const derivationPath = this.walletMap[accountAddress].derivationPath;
|
|
916
|
+
const text = JSON.stringify({
|
|
917
|
+
keyShares: clientKeyShares,
|
|
918
|
+
derivationPath
|
|
919
|
+
});
|
|
816
920
|
const blob = new Blob([
|
|
817
921
|
text
|
|
818
922
|
], {
|
|
@@ -832,7 +936,7 @@ class DynamicWalletClient {
|
|
|
832
936
|
}
|
|
833
937
|
async getWallet({ accountAddress }) {
|
|
834
938
|
if (accountAddress) {
|
|
835
|
-
if (this.walletMap[accountAddress] && this.walletMap[accountAddress].clientKeyShares.length > 0) {
|
|
939
|
+
if (this.walletMap[accountAddress] && this.walletMap[accountAddress].clientKeyShares.length > 0 && this.walletMap[accountAddress].thresholdSignatureScheme && this.walletMap[accountAddress].derivationPath) {
|
|
836
940
|
this.logger.debug('Wallet already exists', this.walletMap[accountAddress]);
|
|
837
941
|
return this.walletMap[accountAddress];
|
|
838
942
|
} else {
|
|
@@ -848,7 +952,8 @@ class DynamicWalletClient {
|
|
|
848
952
|
walletId: wallet.id,
|
|
849
953
|
chainName: wallet.chainName,
|
|
850
954
|
accountAddress,
|
|
851
|
-
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme
|
|
955
|
+
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
956
|
+
derivationPath: walletProperties.derivationPath
|
|
852
957
|
});
|
|
853
958
|
// restore backup
|
|
854
959
|
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
@@ -883,13 +988,15 @@ class DynamicWalletClient {
|
|
|
883
988
|
accountAddress: vc.address
|
|
884
989
|
}));
|
|
885
990
|
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
886
|
-
var
|
|
991
|
+
var _acc_accountAddress, _acc_accountAddress1, _acc_accountAddress2;
|
|
992
|
+
const accountAddress = wallet.accountAddress;
|
|
887
993
|
acc[wallet.accountAddress] = {
|
|
888
994
|
walletId: wallet.walletId,
|
|
889
995
|
chainName: wallet.chainName,
|
|
890
|
-
accountAddress:
|
|
891
|
-
clientKeyShares: ((
|
|
892
|
-
thresholdSignatureScheme: ((
|
|
996
|
+
accountAddress: accountAddress,
|
|
997
|
+
clientKeyShares: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.clientKeyShares) || [],
|
|
998
|
+
thresholdSignatureScheme: ((_acc_accountAddress1 = acc[accountAddress]) == null ? void 0 : _acc_accountAddress1.thresholdSignatureScheme) || undefined,
|
|
999
|
+
derivationPath: ((_acc_accountAddress2 = acc[accountAddress]) == null ? void 0 : _acc_accountAddress2.derivationPath) || undefined
|
|
893
1000
|
};
|
|
894
1001
|
return acc;
|
|
895
1002
|
}, {});
|
package/package.json
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export declare const PBKDF2_ALGORITHM = "PBKDF2";
|
|
2
|
+
export declare const PBKDF2_ITERATIONS = 100000;
|
|
3
|
+
export declare const PBKDF2_HASH_ALGORITHM = "SHA-256";
|
|
4
|
+
export declare const AES_GCM_ALGORITHM = "AES-GCM";
|
|
5
|
+
export declare const AES_GCM_LENGTH = 256;
|
|
1
6
|
export declare const encryptData: ({ data, password, }: {
|
|
2
7
|
data: string;
|
|
3
8
|
password: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/backup/encryption.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/backup/encryption.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAE/C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,cAAc,MAAM,CAAC;AA4BlC,eAAO,MAAM,WAAW,wBAGrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;;;;EA4BA,CAAC;AAEF,eAAO,MAAM,WAAW,wBAGrB;IACD,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,QAAQ,EAAE,MAAM,CAAC;CAClB,oBA0BA,CAAC"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const uploadFileToGoogleDriveAppStorage: ({ accessToken, fileName, jsonData, }: {
|
|
2
2
|
accessToken: string;
|
|
3
3
|
fileName: string;
|
|
4
|
-
jsonData:
|
|
4
|
+
jsonData: unknown;
|
|
5
|
+
}) => Promise<any>;
|
|
6
|
+
export declare const uploadFileToGoogleDrivePersonal: ({ accessToken, fileName, jsonData, }: {
|
|
7
|
+
accessToken: string;
|
|
8
|
+
fileName: string;
|
|
9
|
+
jsonData: unknown;
|
|
5
10
|
}) => Promise<any>;
|
|
6
11
|
export declare const listFilesFromGoogleDrive: ({ accessToken, name, }: {
|
|
7
12
|
accessToken: string;
|
|
@@ -10,5 +15,5 @@ export declare const listFilesFromGoogleDrive: ({ accessToken, name, }: {
|
|
|
10
15
|
export declare const downloadFileFromGoogleDrive: ({ accessToken, name, }: {
|
|
11
16
|
accessToken: string;
|
|
12
17
|
name: string;
|
|
13
|
-
}) => Promise<
|
|
18
|
+
}) => Promise<unknown | null>;
|
|
14
19
|
//# sourceMappingURL=googleDrive.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"googleDrive.d.ts","sourceRoot":"","sources":["../../../src/backup/providers/googleDrive.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"googleDrive.d.ts","sourceRoot":"","sources":["../../../src/backup/providers/googleDrive.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iCAAiC,yCAI3C;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,iBAOA,CAAC;AAEF,eAAO,MAAM,+BAA+B,yCAIzC;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,iBAOA,CAAC;AAiDF,eAAO,MAAM,wBAAwB,2BAGlC;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,iBAsBA,CAAC;AAEF,eAAO,MAAM,2BAA2B,2BAGrC;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAiCzB,CAAC"}
|
package/src/client.d.ts
CHANGED
|
@@ -31,10 +31,10 @@ export declare class DynamicWalletClient {
|
|
|
31
31
|
chainName: string;
|
|
32
32
|
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
33
33
|
}): Promise<ClientInitKeygenResult[]>;
|
|
34
|
-
derivePublicKey({ chainName, keyShare,
|
|
34
|
+
derivePublicKey({ chainName, keyShare, derivationPath, }: {
|
|
35
35
|
chainName: string;
|
|
36
36
|
keyShare: ClientKeyShare;
|
|
37
|
-
|
|
37
|
+
derivationPath: Uint32Array | undefined;
|
|
38
38
|
}): Promise<EcdsaPublicKey | Uint8Array | undefined>;
|
|
39
39
|
clientKeyGen({ chainName, roomId, serverKeygenIds, clientKeygenInitResults, thresholdSignatureScheme, }: {
|
|
40
40
|
chainName: string;
|
|
@@ -57,18 +57,17 @@ export declare class DynamicWalletClient {
|
|
|
57
57
|
walletId: string;
|
|
58
58
|
message: string | Uint8Array;
|
|
59
59
|
}): Promise<any>;
|
|
60
|
-
clientSign({ chainName, message, roomId, keyShare,
|
|
60
|
+
clientSign({ chainName, message, roomId, keyShare, derivationPath, }: {
|
|
61
61
|
chainName: string;
|
|
62
62
|
message: string | Uint8Array;
|
|
63
63
|
roomId: string;
|
|
64
64
|
keyShare: ClientKeyShare;
|
|
65
|
-
|
|
65
|
+
derivationPath: Uint32Array | undefined;
|
|
66
66
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
67
|
-
sign({ accountAddress, message, chainName,
|
|
67
|
+
sign({ accountAddress, message, chainName, }: {
|
|
68
68
|
accountAddress?: string;
|
|
69
69
|
message: string | Uint8Array;
|
|
70
70
|
chainName: string;
|
|
71
|
-
imported?: boolean;
|
|
72
71
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
73
72
|
refreshWalletAccountShares({ accountAddress, chainName, }: {
|
|
74
73
|
accountAddress: string;
|
|
@@ -115,9 +114,10 @@ export declare class DynamicWalletClient {
|
|
|
115
114
|
}): Promise<{
|
|
116
115
|
derivedPrivateKey: string | undefined;
|
|
117
116
|
}>;
|
|
118
|
-
offlineExportKey({ chainName, keyShares, }: {
|
|
117
|
+
offlineExportKey({ chainName, keyShares, derivationPath, }: {
|
|
119
118
|
chainName: string;
|
|
120
119
|
keyShares: ClientKeyShare[];
|
|
120
|
+
derivationPath?: string;
|
|
121
121
|
}): Promise<{
|
|
122
122
|
derivedPrivateKey: string | undefined;
|
|
123
123
|
}>;
|
|
@@ -132,28 +132,31 @@ export declare class DynamicWalletClient {
|
|
|
132
132
|
decryptKeyShare({ keyShare, password, }: {
|
|
133
133
|
keyShare: string;
|
|
134
134
|
password?: string;
|
|
135
|
-
}): Promise<
|
|
136
|
-
recoverEncryptedBackupByWallet({ accountAddress, password,
|
|
135
|
+
}): Promise<ClientKeyShare>;
|
|
136
|
+
recoverEncryptedBackupByWallet({ accountAddress, password, }: {
|
|
137
137
|
accountAddress: string;
|
|
138
138
|
password?: string;
|
|
139
|
-
keyShareIds?: string[];
|
|
140
139
|
}): Promise<any[]>;
|
|
141
140
|
restoreWallets(): Promise<void>;
|
|
142
|
-
restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme, }: {
|
|
141
|
+
restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme, derivationPath, }: {
|
|
143
142
|
walletId: string;
|
|
144
143
|
accountAddress: string;
|
|
145
144
|
chainName: string;
|
|
146
145
|
keyShare: ClientKeyShare;
|
|
147
146
|
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
147
|
+
derivationPath?: string;
|
|
148
148
|
}): Promise<void>;
|
|
149
|
-
backupKeySharesToGoogleDrive({ accountAddress, fileName,
|
|
149
|
+
backupKeySharesToGoogleDrive({ accountAddress, fileName, oauthAccountId, password, }: {
|
|
150
150
|
accountAddress: string;
|
|
151
151
|
fileName?: string;
|
|
152
|
-
keyShares: ClientKeyShare[];
|
|
153
152
|
oauthAccountId: string;
|
|
154
153
|
password?: string;
|
|
155
|
-
}): Promise<
|
|
156
|
-
|
|
154
|
+
}): Promise<{
|
|
155
|
+
appUpload: any;
|
|
156
|
+
personalUpload: any;
|
|
157
|
+
}>;
|
|
158
|
+
restoreBackupFromGoogleDrive({ accountAddress, oauthAccountId, name, password, }: {
|
|
159
|
+
accountAddress: string;
|
|
157
160
|
oauthAccountId: string;
|
|
158
161
|
name?: string;
|
|
159
162
|
password?: string;
|
package/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,wBAAwB,EACxB,gBAAgB,EAIjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAIL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAElB,cAAc,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"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"}
|
package/src/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface WalletProperties {
|
|
|
9
9
|
accountAddress: string;
|
|
10
10
|
clientKeyShares: ClientKeyShare[];
|
|
11
11
|
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
12
|
+
derivationPath?: string;
|
|
12
13
|
}
|
|
13
14
|
export interface DynamicWalletClientProps {
|
|
14
15
|
environmentId: string;
|
|
@@ -18,4 +19,21 @@ export interface DynamicWalletClientProps {
|
|
|
18
19
|
debug?: boolean;
|
|
19
20
|
baseMPCRelayApiUrl?: string;
|
|
20
21
|
}
|
|
22
|
+
export type BackupData = {
|
|
23
|
+
keyShares: string[];
|
|
24
|
+
metadata: {
|
|
25
|
+
version: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
accountAddress: string;
|
|
28
|
+
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
29
|
+
hasPassword: boolean;
|
|
30
|
+
encryption?: {
|
|
31
|
+
algorithm: string;
|
|
32
|
+
keyDerivation: string;
|
|
33
|
+
iterations: number;
|
|
34
|
+
hashAlgorithm: string;
|
|
35
|
+
};
|
|
36
|
+
shareCount: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
21
39
|
//# sourceMappingURL=types.d.ts.map
|
package/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../packages/src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,wBAAwB,EAAE,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../packages/src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,wBAAwB,EAAE,wBAAwB,CAAC;QACnD,WAAW,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE;YACX,SAAS,EAAE,MAAM,CAAC;YAClB,aAAa,EAAE,MAAM,CAAC;YACtB,UAAU,EAAE,MAAM,CAAC;YACnB,aAAa,EAAE,MAAM,CAAC;SACvB,CAAC;QACF,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC"}
|
package/src/utils.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { ThresholdSignatureScheme } from "@dynamic-labs-wallet/core";
|
|
1
2
|
export declare const bytesToBase64: (arr: Uint8Array) => string;
|
|
2
3
|
export declare const stringToBytes: (str: string) => Uint8Array;
|
|
3
4
|
export declare const base64ToBytes: (base64: string) => Uint8Array;
|
|
4
5
|
export declare const ensureBase64Padding: (str: string) => string;
|
|
5
6
|
export declare const isBrowser: () => boolean;
|
|
6
7
|
export declare const isHexString: (str: string) => boolean;
|
|
8
|
+
export declare const getClientKeyShareExportFileName: ({ thresholdSignatureScheme, accountAddress, }: {
|
|
9
|
+
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
10
|
+
accountAddress: string;
|
|
11
|
+
}) => string;
|
|
7
12
|
//# sourceMappingURL=utils.d.ts.map
|
package/src/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../packages/src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,QAAS,UAAU,WAE5C,CAAC;AAEF,eAAO,MAAM,aAAa,QAAS,MAAM,eAExC,CAAC;AAEF,eAAO,MAAM,aAAa,WAAY,MAAM,eAE3C,CAAC;AAGF,eAAO,MAAM,mBAAmB,QAAS,MAAM,KAAG,MAEjD,CAAC;AAEF,eAAO,MAAM,SAAS,eAAsC,CAAC;AAE7D,eAAO,MAAM,WAAW,QAAS,MAAM,YAKtC,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../packages/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAGrE,eAAO,MAAM,aAAa,QAAS,UAAU,WAE5C,CAAC;AAEF,eAAO,MAAM,aAAa,QAAS,MAAM,eAExC,CAAC;AAEF,eAAO,MAAM,aAAa,WAAY,MAAM,eAE3C,CAAC;AAGF,eAAO,MAAM,mBAAmB,QAAS,MAAM,KAAG,MAEjD,CAAC;AAEF,eAAO,MAAM,SAAS,eAAsC,CAAC;AAE7D,eAAO,MAAM,WAAW,QAAS,MAAM,YAKtC,CAAC;AAEF,eAAO,MAAM,+BAA+B,kDAGzC;IACD,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,cAAc,EAAE,MAAM,CAAC;CACxB,WAEE,CAAC"}
|