@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.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
- dynamicBackendShares: existingShares,
863
+ clientShares: existingShares,
830
864
  googleDriveShares: existingShares,
831
865
  delegatedShare
832
866
  });
833
867
  const createDelegationOnlyDistribution = ({ existingShares, delegatedShare })=>({
834
- dynamicBackendShares: existingShares,
868
+ clientShares: existingShares,
835
869
  googleDriveShares: [],
836
870
  delegatedShare
837
871
  });
838
872
  const createGoogleDriveOnlyDistribution = ({ allShares })=>({
839
- dynamicBackendShares: allShares.slice(0, -1),
873
+ clientShares: allShares.slice(0, -1),
840
874
  googleDriveShares: allShares.slice(-1)
841
875
  });
842
876
  const createDynamicOnlyDistribution = ({ allShares })=>({
843
- dynamicBackendShares: allShares,
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
- dynamicBackendShares: clientShares,
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
- 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.
@@ -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
- 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 }) {
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: clientKeyShares[0]
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 mpcSigner.exportFullPrivateKey(data.roomId, clientKeyShares[0], exportId);
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 derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
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 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);
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.dynamicBackendShares.length > 0) {
1983
- const encryptedDynamicShares = await Promise.all(distribution.dynamicBackendShares.map((keyShare)=>this.encryptKeyShare({
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.228",
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.228",
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",