@dynamic-labs-wallet/browser 0.0.228 → 0.0.230
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 +207 -73
- package/index.esm.js +207 -74
- package/package.json +2 -2
- package/src/client.d.ts +27 -13
- package/src/client.d.ts.map +1 -1
- package/src/mpc/index.d.ts.map +1 -1
- package/src/mpc/mpc.d.ts +3 -1
- package/src/mpc/mpc.d.ts.map +1 -1
- package/src/mpc/types.d.ts +3 -2
- package/src/mpc/types.d.ts.map +1 -1
- package/src/types.d.ts +2 -1
- package/src/types.d.ts.map +1 -1
- package/src/utils.d.ts +6 -1
- package/src/utils.d.ts.map +1 -1
package/index.esm.js
CHANGED
|
@@ -34,8 +34,8 @@ const getMPCSignatureScheme = ({ signingAlgorithm, baseRelayUrl = MPC_RELAY_PROD
|
|
|
34
34
|
throw new Error(`Unsupported signing algorithm: ${signingAlgorithm}`);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
const getMPCSigner = ({ chainName, baseRelayUrl })=>{
|
|
38
|
-
const chainConfig = getMPCChainConfig(chainName);
|
|
37
|
+
const getMPCSigner = ({ chainName, baseRelayUrl, bitcoinConfig })=>{
|
|
38
|
+
const chainConfig = getMPCChainConfig(chainName, bitcoinConfig);
|
|
39
39
|
const signatureScheme = getMPCSignatureScheme({
|
|
40
40
|
signingAlgorithm: chainConfig.signingAlgorithm,
|
|
41
41
|
baseRelayUrl
|
|
@@ -468,7 +468,28 @@ const ROOM_EXPIRATION_TIME = 1000 * 60 * 10; // 10 minutes
|
|
|
468
468
|
const ROOM_CACHE_COUNT = 5;
|
|
469
469
|
const WALLET_BUSY_LOCK_TIMEOUT_MS = 20000; // 20 seconds
|
|
470
470
|
|
|
471
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
471
472
|
const isBrowser = ()=>typeof window !== 'undefined';
|
|
473
|
+
/**
|
|
474
|
+
* Helper function to extract pubkey from potentially nested structure
|
|
475
|
+
* Handles cases where pubkey is stored as {pubkey: {0: 33, 1: 209, ...}} in localStorage
|
|
476
|
+
*/ const extractPubkey = (pubkey)=>{
|
|
477
|
+
var _pubkey_pubkey;
|
|
478
|
+
// Handle nested pubkey structure (e.g., {pubkey: {0: 33, 1: 209, ...}})
|
|
479
|
+
const actualPubkey = (_pubkey_pubkey = pubkey == null ? void 0 : pubkey.pubkey) != null ? _pubkey_pubkey : pubkey;
|
|
480
|
+
if (actualPubkey instanceof Uint8Array) {
|
|
481
|
+
return actualPubkey;
|
|
482
|
+
}
|
|
483
|
+
// Convert object with numeric keys to Uint8Array
|
|
484
|
+
if (typeof actualPubkey === 'object' && actualPubkey !== null) {
|
|
485
|
+
const keys = Object.keys(actualPubkey).map(Number).filter((k)=>!Number.isNaN(k)).sort((a, b)=>a - b);
|
|
486
|
+
if (keys.length > 0) {
|
|
487
|
+
const result = new Uint8Array(keys.map((k)=>actualPubkey[k]));
|
|
488
|
+
return result;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return actualPubkey;
|
|
492
|
+
};
|
|
472
493
|
const getClientKeyShareExportFileName = ({ thresholdSignatureScheme, accountAddress, isGoogleDrive = false })=>{
|
|
473
494
|
const suffix = isGoogleDrive ? '-google-drive' : '';
|
|
474
495
|
return `${CLIENT_KEYSHARE_EXPORT_FILENAME_PREFIX}-${thresholdSignatureScheme}-${accountAddress}${suffix}.json`;
|
|
@@ -581,6 +602,17 @@ const formatSolanaMessage = (message)=>{
|
|
|
581
602
|
return message;
|
|
582
603
|
}
|
|
583
604
|
};
|
|
605
|
+
const formatTonMessage = (message)=>{
|
|
606
|
+
if (typeof message === 'string') {
|
|
607
|
+
if (!isHexString(message)) {
|
|
608
|
+
return Buffer.from(message).toString('hex');
|
|
609
|
+
} else {
|
|
610
|
+
return new Uint8Array(Buffer.from(message, 'hex'));
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
return message;
|
|
614
|
+
}
|
|
615
|
+
};
|
|
584
616
|
const formatMessage = (chainName, message)=>{
|
|
585
617
|
switch(chainName){
|
|
586
618
|
case 'EVM':
|
|
@@ -589,6 +621,8 @@ const formatMessage = (chainName, message)=>{
|
|
|
589
621
|
return formatSolanaMessage(message);
|
|
590
622
|
case 'SUI':
|
|
591
623
|
return message;
|
|
624
|
+
case 'TON':
|
|
625
|
+
return formatTonMessage(message);
|
|
592
626
|
default:
|
|
593
627
|
throw new Error('Unsupported chain name');
|
|
594
628
|
}
|
|
@@ -826,21 +860,21 @@ class WalletBusyError extends Error {
|
|
|
826
860
|
}
|
|
827
861
|
}
|
|
828
862
|
const createDelegationWithGoogleDriveDistribution = ({ existingShares, delegatedShare })=>({
|
|
829
|
-
|
|
863
|
+
clientShares: existingShares,
|
|
830
864
|
googleDriveShares: existingShares,
|
|
831
865
|
delegatedShare
|
|
832
866
|
});
|
|
833
867
|
const createDelegationOnlyDistribution = ({ existingShares, delegatedShare })=>({
|
|
834
|
-
|
|
868
|
+
clientShares: existingShares,
|
|
835
869
|
googleDriveShares: [],
|
|
836
870
|
delegatedShare
|
|
837
871
|
});
|
|
838
872
|
const createGoogleDriveOnlyDistribution = ({ allShares })=>({
|
|
839
|
-
|
|
873
|
+
clientShares: allShares.slice(0, -1),
|
|
840
874
|
googleDriveShares: allShares.slice(-1)
|
|
841
875
|
});
|
|
842
876
|
const createDynamicOnlyDistribution = ({ allShares })=>({
|
|
843
|
-
|
|
877
|
+
clientShares: allShares,
|
|
844
878
|
googleDriveShares: []
|
|
845
879
|
});
|
|
846
880
|
const hasGoogleDriveBackup = (backupInfo)=>{
|
|
@@ -858,10 +892,11 @@ const hasDelegatedBackup = (backupInfo)=>{
|
|
|
858
892
|
* Client's shares go to both Dynamic and Google Drive.
|
|
859
893
|
* delegatedShare is undefined - we don't re-publish, but preserve the location.
|
|
860
894
|
*/ const createAddGoogleDriveToExistingDelegationDistribution = ({ clientShares })=>({
|
|
861
|
-
|
|
895
|
+
clientShares: clientShares,
|
|
862
896
|
googleDriveShares: clientShares
|
|
863
897
|
});
|
|
864
898
|
|
|
899
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
865
900
|
class DynamicWalletClient {
|
|
866
901
|
async initializeForwardMPCClient() {
|
|
867
902
|
try {
|
|
@@ -1032,47 +1067,53 @@ class DynamicWalletClient {
|
|
|
1032
1067
|
};
|
|
1033
1068
|
}
|
|
1034
1069
|
}
|
|
1035
|
-
async serverInitializeKeyGen({ chainName, clientKeygenIds, dynamicRequestId, thresholdSignatureScheme, onError, onCeremonyComplete }) {
|
|
1070
|
+
async serverInitializeKeyGen({ chainName, clientKeygenIds, dynamicRequestId, thresholdSignatureScheme, bitcoinConfig, onError, onCeremonyComplete }) {
|
|
1036
1071
|
// Initialize keygen, create room, and create the wallet account on the server
|
|
1037
1072
|
const data = await this.apiClient.createWalletAccount({
|
|
1038
1073
|
chainName,
|
|
1039
1074
|
clientKeygenIds,
|
|
1040
1075
|
dynamicRequestId,
|
|
1041
1076
|
thresholdSignatureScheme,
|
|
1077
|
+
bitcoinConfig,
|
|
1042
1078
|
onError,
|
|
1043
1079
|
onCeremonyComplete
|
|
1044
1080
|
});
|
|
1045
1081
|
this.logger.debug(`[DynamicWaasWalletClient] Initialized client key generation with IDs: ${clientKeygenIds.join(', ')} for chain: ${chainName} using scheme: ${thresholdSignatureScheme}`);
|
|
1046
1082
|
return data;
|
|
1047
1083
|
}
|
|
1048
|
-
async clientInitializeKeyGen({ chainName, thresholdSignatureScheme }) {
|
|
1084
|
+
async clientInitializeKeyGen({ chainName, thresholdSignatureScheme, bitcoinConfig }) {
|
|
1049
1085
|
// Get the mpc signer
|
|
1050
1086
|
const mpcSigner = getMPCSigner({
|
|
1051
1087
|
chainName,
|
|
1052
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1088
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1089
|
+
bitcoinConfig
|
|
1053
1090
|
});
|
|
1054
1091
|
const clientThreshold = getClientThreshold(thresholdSignatureScheme);
|
|
1055
1092
|
const keygenInitResults = await Promise.all(Array(clientThreshold).fill(null).map(()=>mpcSigner.initKeygen()));
|
|
1056
1093
|
return keygenInitResults;
|
|
1057
1094
|
}
|
|
1058
|
-
async derivePublicKey({ chainName, keyShare, derivationPath }) {
|
|
1095
|
+
async derivePublicKey({ chainName, keyShare, derivationPath, bitcoinConfig }) {
|
|
1059
1096
|
const mpcSigner = getMPCSigner({
|
|
1060
1097
|
chainName,
|
|
1061
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1098
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1099
|
+
bitcoinConfig
|
|
1062
1100
|
});
|
|
1063
1101
|
let publicKey;
|
|
1064
1102
|
if (mpcSigner instanceof Ecdsa) {
|
|
1065
1103
|
publicKey = await mpcSigner.derivePubkey(keyShare, derivationPath);
|
|
1066
1104
|
} else if (mpcSigner instanceof ExportableEd25519) {
|
|
1067
1105
|
publicKey = await mpcSigner.getPubkey(keyShare);
|
|
1106
|
+
} else if (mpcSigner instanceof BIP340) {
|
|
1107
|
+
publicKey = await mpcSigner.deriveTweakPubkey(keyShare, derivationPath);
|
|
1068
1108
|
}
|
|
1069
1109
|
return publicKey;
|
|
1070
1110
|
}
|
|
1071
|
-
async clientKeyGen({ chainName, roomId, serverKeygenIds, clientKeygenInitResults, thresholdSignatureScheme }) {
|
|
1111
|
+
async clientKeyGen({ chainName, roomId, serverKeygenIds, clientKeygenInitResults, thresholdSignatureScheme, bitcoinConfig }) {
|
|
1072
1112
|
// Get the chain config and the mpc signer
|
|
1073
1113
|
const mpcSigner = getMPCSigner({
|
|
1074
1114
|
chainName,
|
|
1075
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1115
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1116
|
+
bitcoinConfig
|
|
1076
1117
|
});
|
|
1077
1118
|
// Get the MPC config for the threshold signature scheme
|
|
1078
1119
|
const mpcConfig = MPC_CONFIG[thresholdSignatureScheme];
|
|
@@ -1095,24 +1136,26 @@ class DynamicWalletClient {
|
|
|
1095
1136
|
}));
|
|
1096
1137
|
// only need one client keygen result to derive the public key
|
|
1097
1138
|
const [clientKeygenResult] = clientKeygenResults;
|
|
1098
|
-
const chainConfig = getMPCChainConfig(chainName);
|
|
1139
|
+
const chainConfig = getMPCChainConfig(chainName, bitcoinConfig);
|
|
1099
1140
|
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
1100
1141
|
const rawPublicKey = await this.derivePublicKey({
|
|
1101
1142
|
chainName,
|
|
1102
1143
|
keyShare: clientKeygenResult,
|
|
1103
|
-
derivationPath
|
|
1144
|
+
derivationPath,
|
|
1145
|
+
bitcoinConfig
|
|
1104
1146
|
});
|
|
1105
1147
|
return {
|
|
1106
1148
|
rawPublicKey,
|
|
1107
1149
|
clientKeygenResults
|
|
1108
1150
|
};
|
|
1109
1151
|
}
|
|
1110
|
-
async keyGen({ chainName, thresholdSignatureScheme, onError, onCeremonyComplete, traceContext }) {
|
|
1152
|
+
async keyGen({ chainName, thresholdSignatureScheme, bitcoinConfig, onError, onCeremonyComplete, traceContext }) {
|
|
1111
1153
|
const dynamicRequestId = v4();
|
|
1112
1154
|
try {
|
|
1113
1155
|
const clientKeygenInitResults = await this.clientInitializeKeyGen({
|
|
1114
1156
|
chainName,
|
|
1115
|
-
thresholdSignatureScheme
|
|
1157
|
+
thresholdSignatureScheme,
|
|
1158
|
+
bitcoinConfig
|
|
1116
1159
|
});
|
|
1117
1160
|
const clientKeygenIds = clientKeygenInitResults.map((result)=>result.keygenId);
|
|
1118
1161
|
this.instrument('[DynamicWaasWalletClient] Initialized client key generation', _extends({
|
|
@@ -1126,6 +1169,7 @@ class DynamicWalletClient {
|
|
|
1126
1169
|
clientKeygenIds,
|
|
1127
1170
|
dynamicRequestId,
|
|
1128
1171
|
thresholdSignatureScheme,
|
|
1172
|
+
bitcoinConfig,
|
|
1129
1173
|
onCeremonyComplete
|
|
1130
1174
|
});
|
|
1131
1175
|
this.instrument('[DynamicWaasWalletClient] Server key generation initialized', _extends({
|
|
@@ -1141,7 +1185,8 @@ class DynamicWalletClient {
|
|
|
1141
1185
|
roomId,
|
|
1142
1186
|
serverKeygenIds,
|
|
1143
1187
|
clientKeygenInitResults,
|
|
1144
|
-
thresholdSignatureScheme
|
|
1188
|
+
thresholdSignatureScheme,
|
|
1189
|
+
bitcoinConfig
|
|
1145
1190
|
});
|
|
1146
1191
|
this.instrument('[DynamicWaasWalletClient] Client key generation completed', _extends({
|
|
1147
1192
|
roomId,
|
|
@@ -1257,7 +1302,7 @@ class DynamicWalletClient {
|
|
|
1257
1302
|
throw error;
|
|
1258
1303
|
}
|
|
1259
1304
|
}
|
|
1260
|
-
async serverSign({ walletId, message, isFormatted, mfaToken, roomId, context, onError, dynamicRequestId, traceContext }) {
|
|
1305
|
+
async serverSign({ walletId, message, isFormatted, mfaToken, roomId, context, onError, dynamicRequestId, traceContext, bitcoinConfig }) {
|
|
1261
1306
|
// Create the room and sign the message
|
|
1262
1307
|
if (typeof message !== 'string') {
|
|
1263
1308
|
message = `0x${Buffer.from(message).toString('hex')}`;
|
|
@@ -1272,7 +1317,8 @@ class DynamicWalletClient {
|
|
|
1272
1317
|
context: context ? JSON.parse(JSON.stringify(context, (_key, value)=>typeof value === 'bigint' ? value.toString() : value)) : undefined,
|
|
1273
1318
|
onError,
|
|
1274
1319
|
forwardMPCClientEnabled: this.forwardMPCEnabled,
|
|
1275
|
-
traceContext
|
|
1320
|
+
traceContext,
|
|
1321
|
+
bitcoinConfig
|
|
1276
1322
|
});
|
|
1277
1323
|
return data;
|
|
1278
1324
|
}
|
|
@@ -1320,11 +1366,12 @@ class DynamicWalletClient {
|
|
|
1320
1366
|
throw error;
|
|
1321
1367
|
}
|
|
1322
1368
|
}
|
|
1323
|
-
async clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted, dynamicRequestId, traceContext }) {
|
|
1369
|
+
async clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted, dynamicRequestId, traceContext, bitcoinConfig }) {
|
|
1324
1370
|
try {
|
|
1325
1371
|
const mpcSigner = getMPCSigner({
|
|
1326
1372
|
chainName,
|
|
1327
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1373
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1374
|
+
bitcoinConfig
|
|
1328
1375
|
});
|
|
1329
1376
|
const formattedMessage = isFormatted ? new MessageHash(message) : formatMessage(chainName, message);
|
|
1330
1377
|
this.logger.debug('[DynamicWaasWalletClient] Starting client sign', _extends({
|
|
@@ -1347,7 +1394,13 @@ class DynamicWalletClient {
|
|
|
1347
1394
|
traceContext
|
|
1348
1395
|
});
|
|
1349
1396
|
}
|
|
1350
|
-
|
|
1397
|
+
// Unwrap MessageHash for BIP340 as it expects Uint8Array or hex string
|
|
1398
|
+
let messageToSign = formattedMessage;
|
|
1399
|
+
if (mpcSigner instanceof BIP340 && formattedMessage instanceof MessageHash) {
|
|
1400
|
+
messageToSign = formattedMessage.bytes;
|
|
1401
|
+
}
|
|
1402
|
+
const tweak = bitcoinConfig == null ? void 0 : bitcoinConfig.tweak;
|
|
1403
|
+
const signature = await mpcSigner.sign(roomId, keyShare, messageToSign, derivationPath, tweak);
|
|
1351
1404
|
return signature;
|
|
1352
1405
|
} catch (error) {
|
|
1353
1406
|
logError({
|
|
@@ -1365,7 +1418,7 @@ class DynamicWalletClient {
|
|
|
1365
1418
|
}
|
|
1366
1419
|
}
|
|
1367
1420
|
//todo: need to modify with imported flag
|
|
1368
|
-
async sign({ accountAddress, message, chainName, password = undefined, isFormatted = false, signedSessionId, mfaToken, context, onError, traceContext }) {
|
|
1421
|
+
async sign({ accountAddress, message, chainName, password = undefined, isFormatted = false, signedSessionId, mfaToken, context, onError, traceContext, bitcoinConfig }) {
|
|
1369
1422
|
const dynamicRequestId = v4();
|
|
1370
1423
|
try {
|
|
1371
1424
|
await this.waitForWalletNotBusy(accountAddress);
|
|
@@ -1396,7 +1449,7 @@ class DynamicWalletClient {
|
|
|
1396
1449
|
}, this.getTraceContext(traceContext)));
|
|
1397
1450
|
}
|
|
1398
1451
|
}
|
|
1399
|
-
// Perform the server sign
|
|
1452
|
+
// Perform the server sign
|
|
1400
1453
|
const serverSignPromise = this.serverSign({
|
|
1401
1454
|
walletId: wallet.walletId,
|
|
1402
1455
|
message,
|
|
@@ -1406,7 +1459,8 @@ class DynamicWalletClient {
|
|
|
1406
1459
|
context,
|
|
1407
1460
|
onError,
|
|
1408
1461
|
dynamicRequestId,
|
|
1409
|
-
traceContext
|
|
1462
|
+
traceContext,
|
|
1463
|
+
bitcoinConfig
|
|
1410
1464
|
});
|
|
1411
1465
|
// Only await if roomId is not provided
|
|
1412
1466
|
roomId = roomId != null ? roomId : (await serverSignPromise).roomId;
|
|
@@ -1432,7 +1486,8 @@ class DynamicWalletClient {
|
|
|
1432
1486
|
derivationPath,
|
|
1433
1487
|
isFormatted,
|
|
1434
1488
|
dynamicRequestId,
|
|
1435
|
-
traceContext
|
|
1489
|
+
traceContext,
|
|
1490
|
+
bitcoinConfig
|
|
1436
1491
|
});
|
|
1437
1492
|
this.instrument('[DynamicWaasWalletClient] Client sign completed', _extends({
|
|
1438
1493
|
accountAddress,
|
|
@@ -1526,13 +1581,38 @@ class DynamicWalletClient {
|
|
|
1526
1581
|
throw error;
|
|
1527
1582
|
}
|
|
1528
1583
|
}
|
|
1529
|
-
async getExportId({ chainName, clientKeyShare }) {
|
|
1584
|
+
async getExportId({ chainName, clientKeyShare, bitcoinConfig }) {
|
|
1530
1585
|
const mpcSigner = getMPCSigner({
|
|
1531
1586
|
chainName,
|
|
1532
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1587
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1588
|
+
bitcoinConfig
|
|
1533
1589
|
});
|
|
1534
|
-
|
|
1535
|
-
|
|
1590
|
+
try {
|
|
1591
|
+
// For BIP340, try passing the secretShare as a string directly
|
|
1592
|
+
// The exportID accepts either BIP340KeygenResult or string (secretShare)
|
|
1593
|
+
let exportId;
|
|
1594
|
+
if (mpcSigner instanceof BIP340) {
|
|
1595
|
+
const secretShareString = clientKeyShare.secretShare;
|
|
1596
|
+
exportId = await mpcSigner.exportID(secretShareString);
|
|
1597
|
+
} else {
|
|
1598
|
+
exportId = await mpcSigner.exportID(clientKeyShare);
|
|
1599
|
+
}
|
|
1600
|
+
this.logger.debug('[DynamicWaasWalletClient] getExportId succeeded', {
|
|
1601
|
+
chainName,
|
|
1602
|
+
exportId
|
|
1603
|
+
});
|
|
1604
|
+
return exportId;
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
var _clientKeyShare_secretShare;
|
|
1607
|
+
this.logger.error('[DynamicWaasWalletClient] Error in getExportId', {
|
|
1608
|
+
chainName,
|
|
1609
|
+
error,
|
|
1610
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
1611
|
+
clientKeyShareType: clientKeyShare.constructor.name,
|
|
1612
|
+
secretSharePrefix: (_clientKeyShare_secretShare = clientKeyShare.secretShare) == null ? void 0 : _clientKeyShare_secretShare.substring(0, 100)
|
|
1613
|
+
});
|
|
1614
|
+
throw error;
|
|
1615
|
+
}
|
|
1536
1616
|
}
|
|
1537
1617
|
/**
|
|
1538
1618
|
* Helper function to create client shares required to complete a reshare ceremony.
|
|
@@ -1657,21 +1737,6 @@ class DynamicWalletClient {
|
|
|
1657
1737
|
Promise.all(existingResharePromises),
|
|
1658
1738
|
Promise.all(newResharePromises)
|
|
1659
1739
|
]);
|
|
1660
|
-
const clientKeysharesToLocalStorage = delegateToProjectEnvironment ? [
|
|
1661
|
-
...existingReshareResults
|
|
1662
|
-
] : [
|
|
1663
|
-
...existingReshareResults,
|
|
1664
|
-
...newReshareResults
|
|
1665
|
-
];
|
|
1666
|
-
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1667
|
-
thresholdSignatureScheme: newThresholdSignatureScheme
|
|
1668
|
-
});
|
|
1669
|
-
// store client key shares to localStorage
|
|
1670
|
-
await this.setClientKeySharesToLocalStorage({
|
|
1671
|
-
accountAddress,
|
|
1672
|
-
clientKeyShares: clientKeysharesToLocalStorage,
|
|
1673
|
-
overwriteOrMerge: 'overwrite'
|
|
1674
|
-
});
|
|
1675
1740
|
const allClientShares = [
|
|
1676
1741
|
...existingReshareResults,
|
|
1677
1742
|
...newReshareResults
|
|
@@ -1703,6 +1768,14 @@ class DynamicWalletClient {
|
|
|
1703
1768
|
allShares: allClientShares
|
|
1704
1769
|
});
|
|
1705
1770
|
}
|
|
1771
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1772
|
+
thresholdSignatureScheme: newThresholdSignatureScheme
|
|
1773
|
+
});
|
|
1774
|
+
await this.setClientKeySharesToLocalStorage({
|
|
1775
|
+
accountAddress,
|
|
1776
|
+
clientKeyShares: distribution.clientShares,
|
|
1777
|
+
overwriteOrMerge: 'overwrite'
|
|
1778
|
+
});
|
|
1706
1779
|
await this.backupSharesWithDistribution({
|
|
1707
1780
|
accountAddress,
|
|
1708
1781
|
password,
|
|
@@ -1798,7 +1871,16 @@ class DynamicWalletClient {
|
|
|
1798
1871
|
operationName: 'revokeDelegation'
|
|
1799
1872
|
});
|
|
1800
1873
|
}
|
|
1801
|
-
|
|
1874
|
+
createKeygenResult(mpcSigner, extractedPubkey, secretShare) {
|
|
1875
|
+
if (mpcSigner instanceof Ecdsa) {
|
|
1876
|
+
return new EcdsaKeygenResult(extractedPubkey, secretShare);
|
|
1877
|
+
}
|
|
1878
|
+
if (mpcSigner instanceof ExportableEd25519) {
|
|
1879
|
+
return new ExportableEd25519KeygenResult(extractedPubkey, secretShare);
|
|
1880
|
+
}
|
|
1881
|
+
return new BIP340KeygenResult(extractedPubkey, secretShare);
|
|
1882
|
+
}
|
|
1883
|
+
async exportKey({ accountAddress, chainName, bitcoinConfig, password = undefined, signedSessionId, mfaToken, traceContext }) {
|
|
1802
1884
|
const dynamicRequestId = v4();
|
|
1803
1885
|
try {
|
|
1804
1886
|
const wallet = await this.getWallet({
|
|
@@ -1809,18 +1891,19 @@ class DynamicWalletClient {
|
|
|
1809
1891
|
});
|
|
1810
1892
|
const mpcSigner = getMPCSigner({
|
|
1811
1893
|
chainName,
|
|
1812
|
-
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1813
|
-
|
|
1814
|
-
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
1815
|
-
accountAddress
|
|
1894
|
+
baseRelayUrl: this.baseMPCRelayApiUrl,
|
|
1895
|
+
bitcoinConfig
|
|
1816
1896
|
});
|
|
1897
|
+
const reconstructedKeyShare = await this.getReconstructedKeyShare(accountAddress, mpcSigner);
|
|
1817
1898
|
const exportId = await this.getExportId({
|
|
1818
1899
|
chainName,
|
|
1819
|
-
clientKeyShare:
|
|
1900
|
+
clientKeyShare: reconstructedKeyShare,
|
|
1901
|
+
bitcoinConfig
|
|
1820
1902
|
});
|
|
1821
1903
|
const data = await this.apiClient.exportKey({
|
|
1822
1904
|
walletId: wallet.walletId,
|
|
1823
1905
|
exportId,
|
|
1906
|
+
bitcoinConfig,
|
|
1824
1907
|
dynamicRequestId,
|
|
1825
1908
|
mfaToken
|
|
1826
1909
|
});
|
|
@@ -1831,10 +1914,7 @@ class DynamicWalletClient {
|
|
|
1831
1914
|
exportId,
|
|
1832
1915
|
roomId: data.roomId
|
|
1833
1916
|
}, this.getTraceContext(traceContext)));
|
|
1834
|
-
const keyExportRaw = await
|
|
1835
|
-
if (!keyExportRaw) {
|
|
1836
|
-
throw new Error('Error exporting private key');
|
|
1837
|
-
}
|
|
1917
|
+
const keyExportRaw = await this.performMPCExport(mpcSigner, reconstructedKeyShare, data.roomId, exportId, accountAddress, chainName);
|
|
1838
1918
|
this.logger.debug('[DynamicWaasWalletClient] Completed export of private key', _extends({
|
|
1839
1919
|
accountAddress,
|
|
1840
1920
|
chainName,
|
|
@@ -1842,15 +1922,7 @@ class DynamicWalletClient {
|
|
|
1842
1922
|
exportId,
|
|
1843
1923
|
roomId: data.roomId
|
|
1844
1924
|
}, this.getTraceContext(traceContext)));
|
|
1845
|
-
const
|
|
1846
|
-
let derivedPrivateKey;
|
|
1847
|
-
if (mpcSigner instanceof Ecdsa) {
|
|
1848
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1849
|
-
} else if (mpcSigner instanceof ExportableEd25519) {
|
|
1850
|
-
derivedPrivateKey = keyExportRaw;
|
|
1851
|
-
} else if (mpcSigner instanceof BIP340) {
|
|
1852
|
-
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1853
|
-
}
|
|
1925
|
+
const derivedPrivateKey = await this.derivePrivateKeyFromExport(mpcSigner, keyExportRaw, wallet);
|
|
1854
1926
|
return {
|
|
1855
1927
|
derivedPrivateKey
|
|
1856
1928
|
};
|
|
@@ -1867,6 +1939,63 @@ class DynamicWalletClient {
|
|
|
1867
1939
|
throw error;
|
|
1868
1940
|
}
|
|
1869
1941
|
}
|
|
1942
|
+
async getReconstructedKeyShare(accountAddress, mpcSigner) {
|
|
1943
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
1944
|
+
accountAddress
|
|
1945
|
+
});
|
|
1946
|
+
if (!clientKeyShares || clientKeyShares.length === 0) {
|
|
1947
|
+
throw new Error('No client key shares found for account');
|
|
1948
|
+
}
|
|
1949
|
+
// Reconstruct the keygen result from the stored clientKeyShare
|
|
1950
|
+
// This is necessary because localStorage stores plain objects, not class instances
|
|
1951
|
+
const clientKeyShare = clientKeyShares[0];
|
|
1952
|
+
const extractedPubkey = extractPubkey(clientKeyShare.pubkey);
|
|
1953
|
+
return this.createKeygenResult(mpcSigner, extractedPubkey, clientKeyShare.secretShare);
|
|
1954
|
+
}
|
|
1955
|
+
async performMPCExport(mpcSigner, reconstructedKeyShare, roomId, exportId, accountAddress, chainName) {
|
|
1956
|
+
try {
|
|
1957
|
+
// For BIP340, try passing the secretShare as a string directly if the keygenResult doesn't work
|
|
1958
|
+
// The exportFullPrivateKey accepts either BIP340KeygenResult or string (secretShare)
|
|
1959
|
+
const secretShareString = reconstructedKeyShare.secretShare;
|
|
1960
|
+
const keygenResultToPass = mpcSigner instanceof BIP340 ? secretShareString || reconstructedKeyShare : reconstructedKeyShare;
|
|
1961
|
+
const keyExportRaw = await mpcSigner.exportFullPrivateKey(roomId, keygenResultToPass, exportId);
|
|
1962
|
+
if (!keyExportRaw) {
|
|
1963
|
+
throw new Error('Error exporting private key');
|
|
1964
|
+
}
|
|
1965
|
+
return keyExportRaw;
|
|
1966
|
+
} catch (exportError) {
|
|
1967
|
+
var _reconstructedKeyShare_secretShare, _reconstructedKeyShare_secretShare1;
|
|
1968
|
+
this.logger.error('[DynamicWaasWalletClient] Error in exportFullPrivateKey', {
|
|
1969
|
+
accountAddress,
|
|
1970
|
+
chainName,
|
|
1971
|
+
error: exportError,
|
|
1972
|
+
errorMessage: exportError instanceof Error ? exportError.message : String(exportError),
|
|
1973
|
+
errorStack: exportError instanceof Error ? exportError.stack : undefined,
|
|
1974
|
+
reconstructedKeyShareType: reconstructedKeyShare.constructor.name,
|
|
1975
|
+
reconstructedKeyShare: {
|
|
1976
|
+
pubkeyType: reconstructedKeyShare.pubkey instanceof Uint8Array ? 'Uint8Array' : typeof reconstructedKeyShare.pubkey,
|
|
1977
|
+
pubkeyLength: reconstructedKeyShare.pubkey instanceof Uint8Array ? reconstructedKeyShare.pubkey.length : 'N/A',
|
|
1978
|
+
secretShareType: typeof reconstructedKeyShare.secretShare,
|
|
1979
|
+
secretShareLength: (_reconstructedKeyShare_secretShare = reconstructedKeyShare.secretShare) == null ? void 0 : _reconstructedKeyShare_secretShare.length,
|
|
1980
|
+
secretSharePrefix: (_reconstructedKeyShare_secretShare1 = reconstructedKeyShare.secretShare) == null ? void 0 : _reconstructedKeyShare_secretShare1.substring(0, 100)
|
|
1981
|
+
},
|
|
1982
|
+
roomId: roomId,
|
|
1983
|
+
exportId
|
|
1984
|
+
});
|
|
1985
|
+
throw exportError;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
async derivePrivateKeyFromExport(mpcSigner, keyExportRaw, wallet) {
|
|
1989
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
1990
|
+
if (mpcSigner instanceof Ecdsa) {
|
|
1991
|
+
return mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1992
|
+
} else if (mpcSigner instanceof ExportableEd25519) {
|
|
1993
|
+
return keyExportRaw;
|
|
1994
|
+
} else if (mpcSigner instanceof BIP340) {
|
|
1995
|
+
return mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
1996
|
+
}
|
|
1997
|
+
return undefined;
|
|
1998
|
+
}
|
|
1870
1999
|
async offlineExportKey({ chainName, keyShares, derivationPath }) {
|
|
1871
2000
|
try {
|
|
1872
2001
|
if (!keyShares || keyShares.length < 2) {
|
|
@@ -1877,7 +2006,7 @@ class DynamicWalletClient {
|
|
|
1877
2006
|
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
1878
2007
|
});
|
|
1879
2008
|
const walletKeyShares = keyShares.map((keyShare)=>{
|
|
1880
|
-
return mpcSigner
|
|
2009
|
+
return this.createKeygenResult(mpcSigner, extractPubkey(keyShare.pubkey), keyShare.secretShare);
|
|
1881
2010
|
});
|
|
1882
2011
|
const keyExportRaw = await mpcSigner.offlineExportFullPrivateKey(walletKeyShares);
|
|
1883
2012
|
if (!keyExportRaw) {
|
|
@@ -1979,8 +2108,8 @@ class DynamicWalletClient {
|
|
|
1979
2108
|
throw error;
|
|
1980
2109
|
}
|
|
1981
2110
|
const locations = [];
|
|
1982
|
-
if (distribution.
|
|
1983
|
-
const encryptedDynamicShares = await Promise.all(distribution.
|
|
2111
|
+
if (distribution.clientShares.length > 0) {
|
|
2112
|
+
const encryptedDynamicShares = await Promise.all(distribution.clientShares.map((keyShare)=>this.encryptKeyShare({
|
|
1984
2113
|
keyShare,
|
|
1985
2114
|
password
|
|
1986
2115
|
})));
|
|
@@ -2140,6 +2269,7 @@ class DynamicWalletClient {
|
|
|
2140
2269
|
preserveDelegatedLocation = true;
|
|
2141
2270
|
} else if (shouldBackupToGoogleDrive && keySharesToBackup.length >= 2) {
|
|
2142
2271
|
// Google Drive only (no delegation): Split shares between Dynamic (N-1) and Google Drive (1).
|
|
2272
|
+
// The last share (new share) goes to Google Drive.
|
|
2143
2273
|
distribution = createGoogleDriveOnlyDistribution({
|
|
2144
2274
|
allShares: keySharesToBackup
|
|
2145
2275
|
});
|
|
@@ -2728,7 +2858,8 @@ class DynamicWalletClient {
|
|
|
2728
2858
|
derivationPath: walletProperties.derivationPath,
|
|
2729
2859
|
clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
|
|
2730
2860
|
walletProperties
|
|
2731
|
-
})
|
|
2861
|
+
}),
|
|
2862
|
+
addressType: walletProperties.addressType
|
|
2732
2863
|
});
|
|
2733
2864
|
if (walletOperation !== WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
2734
2865
|
accountAddress,
|
|
@@ -2782,7 +2913,7 @@ class DynamicWalletClient {
|
|
|
2782
2913
|
this.userId = user.id;
|
|
2783
2914
|
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
2784
2915
|
const wallets = waasWallets.map((vc)=>{
|
|
2785
|
-
var _this_walletMap_vc_address, _vc_walletProperties;
|
|
2916
|
+
var _this_walletMap_vc_address, _vc_walletProperties, _vc_walletProperties1;
|
|
2786
2917
|
var _this_walletMap_vc_address_derivationPath;
|
|
2787
2918
|
return {
|
|
2788
2919
|
walletId: vc.id,
|
|
@@ -2792,7 +2923,8 @@ class DynamicWalletClient {
|
|
|
2792
2923
|
walletProperties: vc.walletProperties || {}
|
|
2793
2924
|
}),
|
|
2794
2925
|
derivationPath: (_this_walletMap_vc_address_derivationPath = (_this_walletMap_vc_address = this.walletMap[vc.address]) == null ? void 0 : _this_walletMap_vc_address.derivationPath) != null ? _this_walletMap_vc_address_derivationPath : undefined,
|
|
2795
|
-
thresholdSignatureScheme: (_vc_walletProperties = vc.walletProperties) == null ? void 0 : _vc_walletProperties.thresholdSignatureScheme
|
|
2926
|
+
thresholdSignatureScheme: (_vc_walletProperties = vc.walletProperties) == null ? void 0 : _vc_walletProperties.thresholdSignatureScheme,
|
|
2927
|
+
addressType: (_vc_walletProperties1 = vc.walletProperties) == null ? void 0 : _vc_walletProperties1.addressType
|
|
2796
2928
|
};
|
|
2797
2929
|
});
|
|
2798
2930
|
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
@@ -2804,7 +2936,8 @@ class DynamicWalletClient {
|
|
|
2804
2936
|
accountAddress: wallet.accountAddress,
|
|
2805
2937
|
clientKeySharesBackupInfo: wallet.clientKeySharesBackupInfo,
|
|
2806
2938
|
derivationPath: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.derivationPath) || undefined,
|
|
2807
|
-
thresholdSignatureScheme: wallet.thresholdSignatureScheme
|
|
2939
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
2940
|
+
addressType: wallet.addressType
|
|
2808
2941
|
};
|
|
2809
2942
|
return acc;
|
|
2810
2943
|
}, {});
|
|
@@ -3007,4 +3140,4 @@ const ERROR_VERIFY_TRANSACTION_SIGNATURE = '[DynamicWaasWalletClient]: Error ver
|
|
|
3007
3140
|
const ERROR_EXPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error exporting private key';
|
|
3008
3141
|
const ERROR_IMPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error importing private key';
|
|
3009
3142
|
|
|
3010
|
-
export { DynamicWalletClient, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_CREATE_WALLET_ACCOUNT, ERROR_EXPORT_PRIVATE_KEY, ERROR_IMPORT_PRIVATE_KEY, ERROR_KEYGEN_FAILED, ERROR_SIGN_MESSAGE, ERROR_SIGN_TYPED_DATA, ERROR_VERIFY_MESSAGE_SIGNATURE, ERROR_VERIFY_TRANSACTION_SIGNATURE, WalletBusyError, createAddGoogleDriveToExistingDelegationDistribution, createBackupData, createDelegationOnlyDistribution, createDelegationWithGoogleDriveDistribution, createDynamicOnlyDistribution, createGoogleDriveOnlyDistribution, downloadStringAsFile, formatEvmMessage, formatMessage, getClientKeyShareBackupInfo, getClientKeyShareExportFileName, getGoogleOAuthAccountId, getMPCSignatureScheme, getMPCSigner, hasDelegatedBackup, hasGoogleDriveBackup, isBrowser, isHexString, mergeUniqueKeyShares, retryPromise, timeoutPromise };
|
|
3143
|
+
export { DynamicWalletClient, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_CREATE_WALLET_ACCOUNT, ERROR_EXPORT_PRIVATE_KEY, ERROR_IMPORT_PRIVATE_KEY, ERROR_KEYGEN_FAILED, ERROR_SIGN_MESSAGE, ERROR_SIGN_TYPED_DATA, ERROR_VERIFY_MESSAGE_SIGNATURE, ERROR_VERIFY_TRANSACTION_SIGNATURE, WalletBusyError, createAddGoogleDriveToExistingDelegationDistribution, createBackupData, createDelegationOnlyDistribution, createDelegationWithGoogleDriveDistribution, createDynamicOnlyDistribution, createGoogleDriveOnlyDistribution, downloadStringAsFile, extractPubkey, formatEvmMessage, formatMessage, getClientKeyShareBackupInfo, getClientKeyShareExportFileName, getGoogleOAuthAccountId, getMPCSignatureScheme, getMPCSigner, hasDelegatedBackup, hasGoogleDriveBackup, isBrowser, isHexString, mergeUniqueKeyShares, retryPromise, timeoutPromise };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.230",
|
|
4
4
|
"license": "Licensed under the Dynamic Labs, Inc. Terms Of Service (https://www.dynamic.xyz/terms-conditions)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@dynamic-labs-wallet/core": "0.0.
|
|
7
|
+
"@dynamic-labs-wallet/core": "0.0.230",
|
|
8
8
|
"@dynamic-labs/logger": "^4.25.3",
|
|
9
9
|
"@dynamic-labs/sdk-api-core": "^0.0.828",
|
|
10
10
|
"argon2id": "1.0.1",
|