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