@dynamic-labs-wallet/browser 0.0.229 → 0.0.231

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -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
  }
@@ -862,6 +896,7 @@ const hasDelegatedBackup = (backupInfo)=>{
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
- const signature = await mpcSigner.sign(roomId, keyShare, formattedMessage, derivationPath);
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 - always call, but only await if roomId is not provided
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
- const exportId = await mpcSigner.exportID(clientKeyShare);
1535
- return exportId;
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.
@@ -1791,7 +1871,16 @@ class DynamicWalletClient {
1791
1871
  operationName: 'revokeDelegation'
1792
1872
  });
1793
1873
  }
1794
- async exportKey({ accountAddress, chainName, password = undefined, signedSessionId, mfaToken, traceContext }) {
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 }) {
1795
1884
  const dynamicRequestId = v4();
1796
1885
  try {
1797
1886
  const wallet = await this.getWallet({
@@ -1802,18 +1891,19 @@ class DynamicWalletClient {
1802
1891
  });
1803
1892
  const mpcSigner = getMPCSigner({
1804
1893
  chainName,
1805
- baseRelayUrl: this.baseMPCRelayApiUrl
1806
- });
1807
- const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
1808
- accountAddress
1894
+ baseRelayUrl: this.baseMPCRelayApiUrl,
1895
+ bitcoinConfig
1809
1896
  });
1897
+ const reconstructedKeyShare = await this.getReconstructedKeyShare(accountAddress, mpcSigner);
1810
1898
  const exportId = await this.getExportId({
1811
1899
  chainName,
1812
- clientKeyShare: clientKeyShares[0]
1900
+ clientKeyShare: reconstructedKeyShare,
1901
+ bitcoinConfig
1813
1902
  });
1814
1903
  const data = await this.apiClient.exportKey({
1815
1904
  walletId: wallet.walletId,
1816
1905
  exportId,
1906
+ bitcoinConfig,
1817
1907
  dynamicRequestId,
1818
1908
  mfaToken
1819
1909
  });
@@ -1824,10 +1914,7 @@ class DynamicWalletClient {
1824
1914
  exportId,
1825
1915
  roomId: data.roomId
1826
1916
  }, this.getTraceContext(traceContext)));
1827
- const keyExportRaw = await mpcSigner.exportFullPrivateKey(data.roomId, clientKeyShares[0], exportId);
1828
- if (!keyExportRaw) {
1829
- throw new Error('Error exporting private key');
1830
- }
1917
+ const keyExportRaw = await this.performMPCExport(mpcSigner, reconstructedKeyShare, data.roomId, exportId, accountAddress, chainName);
1831
1918
  this.logger.debug('[DynamicWaasWalletClient] Completed export of private key', _extends({
1832
1919
  accountAddress,
1833
1920
  chainName,
@@ -1835,15 +1922,7 @@ class DynamicWalletClient {
1835
1922
  exportId,
1836
1923
  roomId: data.roomId
1837
1924
  }, this.getTraceContext(traceContext)));
1838
- const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
1839
- let derivedPrivateKey;
1840
- if (mpcSigner instanceof Ecdsa) {
1841
- derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
1842
- } else if (mpcSigner instanceof ExportableEd25519) {
1843
- derivedPrivateKey = keyExportRaw;
1844
- } else if (mpcSigner instanceof BIP340) {
1845
- derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
1846
- }
1925
+ const derivedPrivateKey = await this.derivePrivateKeyFromExport(mpcSigner, keyExportRaw, wallet);
1847
1926
  return {
1848
1927
  derivedPrivateKey
1849
1928
  };
@@ -1860,6 +1939,63 @@ class DynamicWalletClient {
1860
1939
  throw error;
1861
1940
  }
1862
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
+ }
1863
1999
  async offlineExportKey({ chainName, keyShares, derivationPath }) {
1864
2000
  try {
1865
2001
  if (!keyShares || keyShares.length < 2) {
@@ -1870,7 +2006,7 @@ class DynamicWalletClient {
1870
2006
  baseRelayUrl: this.baseMPCRelayApiUrl
1871
2007
  });
1872
2008
  const walletKeyShares = keyShares.map((keyShare)=>{
1873
- return mpcSigner instanceof Ecdsa ? new EcdsaKeygenResult(keyShare.pubkey, keyShare.secretShare) : mpcSigner instanceof ExportableEd25519 ? new ExportableEd25519KeygenResult(keyShare.pubkey, keyShare.secretShare) : new BIP340KeygenResult(keyShare.pubkey, keyShare.secretShare);
2009
+ return this.createKeygenResult(mpcSigner, extractPubkey(keyShare.pubkey), keyShare.secretShare);
1874
2010
  });
1875
2011
  const keyExportRaw = await mpcSigner.offlineExportFullPrivateKey(walletKeyShares);
1876
2012
  if (!keyExportRaw) {
@@ -2133,6 +2269,7 @@ class DynamicWalletClient {
2133
2269
  preserveDelegatedLocation = true;
2134
2270
  } else if (shouldBackupToGoogleDrive && keySharesToBackup.length >= 2) {
2135
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.
2136
2273
  distribution = createGoogleDriveOnlyDistribution({
2137
2274
  allShares: keySharesToBackup
2138
2275
  });
@@ -2721,7 +2858,8 @@ class DynamicWalletClient {
2721
2858
  derivationPath: walletProperties.derivationPath,
2722
2859
  clientKeySharesBackupInfo: getClientKeyShareBackupInfo({
2723
2860
  walletProperties
2724
- })
2861
+ }),
2862
+ addressType: walletProperties.addressType
2725
2863
  });
2726
2864
  if (walletOperation !== WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
2727
2865
  accountAddress,
@@ -2775,7 +2913,7 @@ class DynamicWalletClient {
2775
2913
  this.userId = user.id;
2776
2914
  const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
2777
2915
  const wallets = waasWallets.map((vc)=>{
2778
- var _this_walletMap_vc_address, _vc_walletProperties;
2916
+ var _this_walletMap_vc_address, _vc_walletProperties, _vc_walletProperties1;
2779
2917
  var _this_walletMap_vc_address_derivationPath;
2780
2918
  return {
2781
2919
  walletId: vc.id,
@@ -2785,7 +2923,8 @@ class DynamicWalletClient {
2785
2923
  walletProperties: vc.walletProperties || {}
2786
2924
  }),
2787
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,
2788
- 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
2789
2928
  };
2790
2929
  });
2791
2930
  this.walletMap = wallets.reduce((acc, wallet)=>{
@@ -2797,7 +2936,8 @@ class DynamicWalletClient {
2797
2936
  accountAddress: wallet.accountAddress,
2798
2937
  clientKeySharesBackupInfo: wallet.clientKeySharesBackupInfo,
2799
2938
  derivationPath: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.derivationPath) || undefined,
2800
- thresholdSignatureScheme: wallet.thresholdSignatureScheme
2939
+ thresholdSignatureScheme: wallet.thresholdSignatureScheme,
2940
+ addressType: wallet.addressType
2801
2941
  };
2802
2942
  return acc;
2803
2943
  }, {});
@@ -3000,4 +3140,4 @@ const ERROR_VERIFY_TRANSACTION_SIGNATURE = '[DynamicWaasWalletClient]: Error ver
3000
3140
  const ERROR_EXPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error exporting private key';
3001
3141
  const ERROR_IMPORT_PRIVATE_KEY = '[DynamicWaasWalletClient]: Error importing private key';
3002
3142
 
3003
- 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.229",
3
+ "version": "0.0.231",
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.229",
7
+ "@dynamic-labs-wallet/core": "0.0.231",
8
8
  "@dynamic-labs/logger": "^4.25.3",
9
9
  "@dynamic-labs/sdk-api-core": "^0.0.828",
10
10
  "argon2id": "1.0.1",
package/src/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { BIP340KeygenResult, EcdsaKeygenResult, type EcdsaPublicKey, EcdsaSignature, ExportableEd25519KeygenResult, MessageHash } from '#internal/web';
2
- import { AuthMode, BackupLocation, type BackupLocationWithExternalKeyShareId, DynamicApiClient, type DynamicWalletClientProps, type FeatureFlags, type InitializeResult, type KeyShareBackupInfo, ThresholdSignatureScheme, type TraceContext, WalletOperation } from '@dynamic-labs-wallet/core';
1
+ import { type EcdsaPublicKey, EcdsaSignature, MessageHash } from '#internal/web';
2
+ import { AuthMode, BackupLocation, type BackupLocationWithExternalKeyShareId, type BitcoinConfig, DynamicApiClient, type DynamicWalletClientProps, type FeatureFlags, type InitializeResult, type KeyShareBackupInfo, ThresholdSignatureScheme, type TraceContext, WalletOperation } from '@dynamic-labs-wallet/core';
3
3
  import { type InstrumentOptions } from '@dynamic-labs/logger';
4
4
  import { RoomTypeEnum, type SignMessageContext } from '@dynamic-labs/sdk-api-core';
5
5
  import type { ClientInitKeygenResult, ClientKeyShare } from './mpc/types.js';
@@ -51,36 +51,41 @@ export declare class DynamicWalletClient {
51
51
  * Client initialization logic
52
52
  */
53
53
  protected _initialize(traceContext?: TraceContext): Promise<InitializeResult>;
54
- serverInitializeKeyGen({ chainName, clientKeygenIds, dynamicRequestId, thresholdSignatureScheme, onError, onCeremonyComplete, }: {
54
+ serverInitializeKeyGen({ chainName, clientKeygenIds, dynamicRequestId, thresholdSignatureScheme, bitcoinConfig, onError, onCeremonyComplete, }: {
55
55
  chainName: string;
56
56
  clientKeygenIds: string[];
57
57
  dynamicRequestId: string;
58
58
  thresholdSignatureScheme: ThresholdSignatureScheme;
59
+ bitcoinConfig?: BitcoinConfig;
59
60
  onError?: (error: Error) => void;
60
61
  onCeremonyComplete?: (accountAddress: string, walletId: string) => void;
61
62
  }): Promise<import("@dynamic-labs-wallet/core").KeygenCompleteResponse>;
62
- clientInitializeKeyGen({ chainName, thresholdSignatureScheme, }: {
63
+ clientInitializeKeyGen({ chainName, thresholdSignatureScheme, bitcoinConfig, }: {
63
64
  chainName: string;
64
65
  thresholdSignatureScheme: ThresholdSignatureScheme;
66
+ bitcoinConfig?: BitcoinConfig;
65
67
  }): Promise<ClientInitKeygenResult[]>;
66
- derivePublicKey({ chainName, keyShare, derivationPath, }: {
68
+ derivePublicKey({ chainName, keyShare, derivationPath, bitcoinConfig, }: {
67
69
  chainName: string;
68
70
  keyShare: ClientKeyShare;
69
71
  derivationPath: Uint32Array | undefined;
72
+ bitcoinConfig?: BitcoinConfig;
70
73
  }): Promise<EcdsaPublicKey | Uint8Array | string | undefined>;
71
- clientKeyGen({ chainName, roomId, serverKeygenIds, clientKeygenInitResults, thresholdSignatureScheme, }: {
74
+ clientKeyGen({ chainName, roomId, serverKeygenIds, clientKeygenInitResults, thresholdSignatureScheme, bitcoinConfig, }: {
72
75
  chainName: string;
73
76
  roomId: string;
74
77
  serverKeygenIds: string[];
75
78
  clientKeygenInitResults: ClientInitKeygenResult[];
76
79
  thresholdSignatureScheme: ThresholdSignatureScheme;
80
+ bitcoinConfig?: BitcoinConfig;
77
81
  }): Promise<{
78
82
  rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
79
83
  clientKeygenResults: ClientKeyShare[];
80
84
  }>;
81
- keyGen({ chainName, thresholdSignatureScheme, onError, onCeremonyComplete, traceContext, }: {
85
+ keyGen({ chainName, thresholdSignatureScheme, bitcoinConfig, onError, onCeremonyComplete, traceContext, }: {
82
86
  chainName: string;
83
87
  thresholdSignatureScheme: ThresholdSignatureScheme;
88
+ bitcoinConfig?: BitcoinConfig;
84
89
  onError?: (error: Error) => void;
85
90
  onCeremonyComplete?: (accountAddress: string, walletId: string) => void;
86
91
  traceContext?: TraceContext;
@@ -99,7 +104,7 @@ export declare class DynamicWalletClient {
99
104
  rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
100
105
  clientKeyShares: ClientKeyShare[];
101
106
  }>;
102
- serverSign({ walletId, message, isFormatted, mfaToken, roomId, context, onError, dynamicRequestId, traceContext, }: {
107
+ serverSign({ walletId, message, isFormatted, mfaToken, roomId, context, onError, dynamicRequestId, traceContext, bitcoinConfig, }: {
103
108
  walletId: string;
104
109
  message: string | Uint8Array;
105
110
  dynamicRequestId: string;
@@ -109,6 +114,7 @@ export declare class DynamicWalletClient {
109
114
  context?: SignMessageContext;
110
115
  onError?: (error: Error) => void;
111
116
  traceContext?: TraceContext;
117
+ bitcoinConfig?: BitcoinConfig;
112
118
  }): Promise<import("@dynamic-labs-wallet/core").OpenRoomResponse>;
113
119
  forwardMPCClientSign({ chainName, message, roomId, keyShare, derivationPath, formattedMessage, dynamicRequestId, isFormatted, traceContext, }: {
114
120
  chainName: string;
@@ -121,7 +127,7 @@ export declare class DynamicWalletClient {
121
127
  isFormatted?: boolean;
122
128
  traceContext?: TraceContext;
123
129
  }): Promise<Uint8Array | EcdsaSignature>;
124
- clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted, dynamicRequestId, traceContext, }: {
130
+ clientSign({ chainName, message, roomId, keyShare, derivationPath, isFormatted, dynamicRequestId, traceContext, bitcoinConfig, }: {
125
131
  chainName: string;
126
132
  message: string | Uint8Array;
127
133
  roomId: string;
@@ -130,8 +136,9 @@ export declare class DynamicWalletClient {
130
136
  derivationPath: Uint32Array | undefined;
131
137
  isFormatted?: boolean;
132
138
  traceContext?: TraceContext;
139
+ bitcoinConfig?: BitcoinConfig;
133
140
  }): Promise<Uint8Array | EcdsaSignature>;
134
- sign({ accountAddress, message, chainName, password, isFormatted, signedSessionId, mfaToken, context, onError, traceContext, }: {
141
+ sign({ accountAddress, message, chainName, password, isFormatted, signedSessionId, mfaToken, context, onError, traceContext, bitcoinConfig, }: {
135
142
  accountAddress: string;
136
143
  message: string | Uint8Array;
137
144
  chainName: string;
@@ -142,6 +149,7 @@ export declare class DynamicWalletClient {
142
149
  context?: SignMessageContext;
143
150
  onError?: (error: Error) => void;
144
151
  traceContext?: TraceContext;
152
+ bitcoinConfig?: BitcoinConfig;
145
153
  }): Promise<Uint8Array | EcdsaSignature>;
146
154
  refreshWalletAccountShares({ accountAddress, chainName, password, signedSessionId, mfaToken, traceContext, }: {
147
155
  accountAddress: string;
@@ -152,9 +160,10 @@ export declare class DynamicWalletClient {
152
160
  traceContext?: TraceContext;
153
161
  }): Promise<void>;
154
162
  private internalRefreshWalletAccountShares;
155
- getExportId({ chainName, clientKeyShare, }: {
163
+ getExportId({ chainName, clientKeyShare, bitcoinConfig, }: {
156
164
  chainName: string;
157
- clientKeyShare: EcdsaKeygenResult | ExportableEd25519KeygenResult | BIP340KeygenResult;
165
+ clientKeyShare: ClientKeyShare;
166
+ bitcoinConfig?: BitcoinConfig;
158
167
  }): Promise<string>;
159
168
  /**
160
169
  * Helper function to create client shares required to complete a reshare ceremony.
@@ -208,9 +217,11 @@ export declare class DynamicWalletClient {
208
217
  signedSessionId: string;
209
218
  mfaToken?: string;
210
219
  }): Promise<void>;
211
- exportKey({ accountAddress, chainName, password, signedSessionId, mfaToken, traceContext, }: {
220
+ private createKeygenResult;
221
+ exportKey({ accountAddress, chainName, bitcoinConfig, password, signedSessionId, mfaToken, traceContext, }: {
212
222
  accountAddress: string;
213
223
  chainName: string;
224
+ bitcoinConfig?: BitcoinConfig;
214
225
  password?: string;
215
226
  signedSessionId: string;
216
227
  mfaToken?: string;
@@ -218,6 +229,9 @@ export declare class DynamicWalletClient {
218
229
  }): Promise<{
219
230
  derivedPrivateKey: string | undefined;
220
231
  }>;
232
+ private getReconstructedKeyShare;
233
+ private performMPCExport;
234
+ private derivePrivateKeyFromExport;
221
235
  offlineExportKey({ chainName, keyShares, derivationPath, }: {
222
236
  chainName: string;
223
237
  keyShares: ClientKeyShare[];