@dynamic-labs-wallet/node-btc 0.0.354 → 1.0.0

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 CHANGED
@@ -66,24 +66,33 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
66
66
  };
67
67
  }
68
68
  /**
69
- * Gets wallet properties and derivation info for a given account address
70
- * @param accountAddress - The account address
71
- * @returns The wallet properties, derivation path, and address type
72
- */ getWalletDerivationInfo(accountAddress) {
73
- const walletProperties = this.walletMap[accountAddress];
74
- if (!walletProperties) {
75
- throw new Error('Wallet not found in walletMap');
76
- }
77
- const derivationPath = walletProperties.derivationPath;
69
+ * Extracts derivation path and address type from walletMetadata.
70
+ * @param walletMetadata - The wallet metadata
71
+ * @returns The derivation path and derived address type
72
+ */ getDerivationInfoFromMetadata(walletMetadata) {
73
+ const derivationPath = walletMetadata.derivationPath;
78
74
  if (!derivationPath) {
79
- throw new Error('Derivation path missing in walletMap');
75
+ throw new Error('Derivation path missing in walletMetadata');
80
76
  }
81
77
  return {
82
- walletProperties,
83
78
  derivationPath,
84
79
  addressType: btcUtils.getAddressTypeFromDerivationPath(derivationPath)
85
80
  };
86
81
  }
82
+ buildWalletMetadata({ walletId, accountAddress, thresholdSignatureScheme, addressType, bitcoinConfig }) {
83
+ const chainConfig = node.getMPCChainConfig(this.chainName, bitcoinConfig);
84
+ return {
85
+ walletId,
86
+ accountAddress,
87
+ chainName: this.chainName,
88
+ thresholdSignatureScheme,
89
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
90
+ index,
91
+ value
92
+ ]))),
93
+ addressType
94
+ };
95
+ }
87
96
  /**
88
97
  * Verifies that the derived address matches the expected address
89
98
  * @param rawPublicKey - The raw public key
@@ -102,10 +111,10 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
102
111
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
103
112
  * @param password - The password to use for the wallet.
104
113
  * @param onError - The function to call if an error occurs.
105
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
114
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
106
115
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
107
116
  * @returns The account address, public key, raw public key, external server key shares, and wallet id.
108
- */ async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, backUpToClientShareService = false, bitcoinConfig }) {
117
+ */ async createWalletAccount({ thresholdSignatureScheme, password, onError, backUpToDynamic = false, bitcoinConfig }) {
109
118
  try {
110
119
  if (!(bitcoinConfig == null ? void 0 : bitcoinConfig.addressType)) {
111
120
  this.logger.warn('[BTC Node Client] addressType not provided for createWalletAccount, defaulting to native_segwit');
@@ -118,6 +127,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
118
127
  addressType,
119
128
  network
120
129
  };
130
+ let resolvedWalletId;
121
131
  let ceremonyCeremonyCompleteResolver;
122
132
  let ceremonyAccountAddress;
123
133
  const ceremonyCompletePromise = new Promise((resolve)=>{
@@ -129,35 +139,17 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
129
139
  thresholdSignatureScheme,
130
140
  skipLock: true,
131
141
  bitcoinConfig: resolvedBitcoinConfig,
142
+ password,
143
+ backUpToDynamic,
132
144
  onError,
133
145
  onCeremonyComplete: (accountAddress, walletId)=>{
134
- // Store the ceremony account address to ensure consistency
135
146
  ceremonyAccountAddress = accountAddress;
136
- // update wallet map
137
- const chainConfig = node.getMPCChainConfig(this.chainName, resolvedBitcoinConfig);
138
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
139
- accountAddress,
140
- walletId,
141
- chainName: this.chainName,
142
- thresholdSignatureScheme,
143
- derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
144
- index,
145
- value
146
- ]))),
147
- externalServerKeySharesBackupInfo: node.getExternalServerKeyShareBackupInfo()
148
- });
149
- this.logger.debug('walletMap updated for wallet', {
150
- context: {
151
- accountAddress,
152
- walletId,
153
- walletMap: this.walletMap
154
- }
155
- });
147
+ resolvedWalletId = walletId;
156
148
  ceremonyCeremonyCompleteResolver(undefined);
157
149
  }
158
150
  });
159
151
  await ceremonyCompletePromise;
160
- if (!rawPublicKey || !externalServerKeyShares) {
152
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId) {
161
153
  throw new Error(ERROR_KEYGEN_FAILED);
162
154
  }
163
155
  const accountAddress = ceremonyAccountAddress || this.deriveAccountAddress({
@@ -165,19 +157,28 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
165
157
  addressType,
166
158
  network
167
159
  }).accountAddress;
168
- const externalKeySharesWithBackupStatus = await this.storeEncryptedBackupByWalletWithRetry({
160
+ const walletMetadata = this.buildWalletMetadata({
161
+ walletId: resolvedWalletId,
162
+ accountAddress,
163
+ thresholdSignatureScheme,
164
+ addressType,
165
+ bitcoinConfig: resolvedBitcoinConfig
166
+ });
167
+ const { keySharesWithBackupStatus, backupInfo } = await this.storeEncryptedBackupByWalletWithRetry({
169
168
  accountAddress,
170
169
  externalServerKeyShares,
171
170
  password,
172
- backUpToClientShareService
171
+ backUpToDynamic,
172
+ walletMetadata
173
173
  });
174
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
174
175
  const publicKeyHex = btcUtils.extractPublicKeyHex(rawPublicKey);
175
176
  return {
176
- accountAddress,
177
+ walletMetadata,
177
178
  rawPublicKey,
178
179
  publicKeyHex,
179
180
  externalServerKeyShares,
180
- externalKeySharesWithBackupStatus
181
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
181
182
  };
182
183
  } catch (error) {
183
184
  logError({
@@ -203,32 +204,29 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
203
204
  * @param onError - Optional. Error callback function
204
205
  * @returns Promise resolving to the BIP-322 signature as a base64 string
205
206
  * @throws Error if required parameters are missing, derivation path is invalid, or signing fails
206
- */ async signMessage({ message, accountAddress, network, password = undefined, externalServerKeyShares, context, onError }) {
207
+ */ async signMessage({ message, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
208
+ const { accountAddress } = walletMetadata;
207
209
  try {
208
- var _this_walletMap_accountAddress;
209
210
  if (!accountAddress) {
210
211
  throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
211
212
  }
212
- const { derivationPath, addressType } = this.getWalletDerivationInfo(accountAddress);
213
- // Attempt to recover key shares from backup if not provided
214
- await this.ensureKeySharesRecovered({
213
+ const { derivationPath, addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
214
+ // Resolve key shares from param or backup
215
+ const resolvedKeyShares = await this.resolveKeyShares({
215
216
  accountAddress,
216
217
  password,
217
218
  walletOperation: node.WalletOperation.SIGN_MESSAGE,
218
219
  externalServerKeyShares,
219
- errorMessage: 'External server key shares are required to sign a message. No backup shares available for recovery.'
220
+ errorMessage: 'External server key shares are required to sign a message. No backup shares available for recovery.',
221
+ walletMetadata
220
222
  });
221
- const resolvedExternalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : (_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.externalServerKeyShares;
222
- if (!resolvedExternalServerKeyShares || resolvedExternalServerKeyShares.length === 0) {
223
- throw new Error('External server key shares are required to sign a message');
224
- }
225
223
  const bitcoinConfig = {
226
224
  addressType,
227
225
  network
228
226
  };
229
227
  const derivedPublicKey = await this.derivePublicKey({
230
228
  chainName: this.chainName,
231
- keyShare: resolvedExternalServerKeyShares[0],
229
+ keyShare: resolvedKeyShares[0],
232
230
  derivationPath: new Uint32Array(Object.values(JSON.parse(derivationPath))),
233
231
  bitcoinConfig
234
232
  });
@@ -255,13 +253,15 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
255
253
  accountAddress,
256
254
  chainName: this.chainName,
257
255
  password,
258
- externalServerKeyShares: resolvedExternalServerKeyShares,
256
+ externalServerKeyShares: resolvedKeyShares,
259
257
  isFormatted: true,
260
258
  context: context != null ? context : {
261
259
  btcMessage: message
262
260
  },
263
261
  bitcoinConfig: completeBitcoinConfig,
264
- onError
262
+ onError,
263
+ walletMetadata,
264
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
265
265
  });
266
266
  const bip322Signature = btcUtils.encodeBip322Signature(toSignPsbt, pubKey, signature, addressType);
267
267
  return bip322Signature;
@@ -276,51 +276,43 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
276
276
  if (onError) {
277
277
  onError(error);
278
278
  }
279
- throw new Error(ERROR_SIGN_MESSAGE);
279
+ throw new Error(ERROR_SIGN_MESSAGE, {
280
+ cause: error
281
+ });
280
282
  }
281
283
  }
282
284
  /**
283
285
  * Signs a Bitcoin transaction (PSBT)
284
286
  *
285
287
  * The address type is automatically derived from the wallet's derivation path.
286
- * Only inputs belonging to the sender address are signed. Supports both TAPROOT
288
+ * Only inputs belonging to the account address are signed. Supports both TAPROOT
287
289
  * (BIP-341) and Native SegWit (BIP-143) signing methods.
288
290
  *
289
291
  * @param transaction - The PSBT to sign as a base64 string
290
- * @param senderAddress - The sender address (must match inputs to be signed)
292
+ * @param accountAddress - The account address (must match inputs to be signed)
291
293
  * @param network - The Bitcoin network (MAINNET or TESTNET)
292
294
  * @param password - Optional password for encrypted backup shares
293
295
  * @param externalServerKeyShares - Optional external server key shares
294
296
  * @param context - Optional. Sign message context for API tracking
295
297
  * @param onError - Optional. Error callback function
296
298
  * @returns Promise resolving to the signed PSBT as a base64 string
297
- * @throws Error if required parameters are missing, no inputs belong to sender address, or signing fails
298
- */ async signTransaction({ transaction, senderAddress, network, password = undefined, externalServerKeyShares, context, onError }) {
299
+ * @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
300
+ */ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
301
+ const { accountAddress } = walletMetadata;
299
302
  try {
300
- await this.verifyPassword({
301
- accountAddress: senderAddress,
302
- password
303
- });
304
- if (!senderAddress) {
303
+ if (!accountAddress) {
305
304
  throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
306
305
  }
307
- const { derivationPath, addressType } = this.getWalletDerivationInfo(senderAddress);
308
- // Attempt to recover key shares from backup if not provided
309
- await this.ensureKeySharesRecovered({
310
- accountAddress: senderAddress,
306
+ const { derivationPath, addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
307
+ // Resolve key shares from param or backup
308
+ const resolvedKeyShares = await this.resolveKeyShares({
309
+ accountAddress,
311
310
  password,
312
311
  walletOperation: node.WalletOperation.SIGN_TRANSACTION,
313
312
  externalServerKeyShares,
314
- errorMessage: 'External server key shares are required to sign transaction. No backup shares available for recovery.'
313
+ errorMessage: 'External server key shares are required to sign transaction. No backup shares available for recovery.',
314
+ walletMetadata
315
315
  });
316
- const updatedWalletProperties = this.walletMap[senderAddress];
317
- if (!updatedWalletProperties) {
318
- throw new Error('Wallet not found in walletMap after key share recovery');
319
- }
320
- const resolvedExternalServerKeyShares = externalServerKeyShares || updatedWalletProperties.externalServerKeyShares;
321
- if (!resolvedExternalServerKeyShares || resolvedExternalServerKeyShares.length === 0) {
322
- throw new Error('External server key shares are required to sign transaction. No backup shares available for recovery.');
323
- }
324
316
  const bitcoinConfig = {
325
317
  addressType,
326
318
  network
@@ -328,7 +320,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
328
320
  const psbt = bitcoin__namespace.Psbt.fromBase64(transaction);
329
321
  const derivedPublicKey = await this.derivePublicKey({
330
322
  chainName: this.chainName,
331
- keyShare: resolvedExternalServerKeyShares[0],
323
+ keyShare: resolvedKeyShares[0],
332
324
  derivationPath: new Uint32Array(Object.values(JSON.parse(derivationPath))),
333
325
  bitcoinConfig
334
326
  });
@@ -341,9 +333,9 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
341
333
  const inputsToSign = psbt.data.inputs.map((input, i)=>({
342
334
  input,
343
335
  index: i
344
- })).filter(({ input })=>btcUtils.doesInputBelongToAddress(input, senderAddress, network));
336
+ })).filter(({ input })=>btcUtils.doesInputBelongToAddress(input, accountAddress, network));
345
337
  if (inputsToSign.length === 0) {
346
- throw new Error('No inputs found that belong to the sender address');
338
+ throw new Error('No inputs found that belong to the account address');
347
339
  }
348
340
  if (addressType === core.BitcoinAddressType.TAPROOT) {
349
341
  const tweak = btcUtils.calculateTaprootTweak(pubKey);
@@ -359,14 +351,16 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
359
351
  const hash = Buffer.from(tx.hashForWitnessV1(i, prevOutScripts, values, bitcoin__namespace.Transaction.SIGHASH_DEFAULT));
360
352
  const signature = await this.sign({
361
353
  message: new Uint8Array(hash),
362
- accountAddress: senderAddress,
354
+ accountAddress,
363
355
  chainName: this.chainName,
364
356
  password,
365
- externalServerKeyShares: resolvedExternalServerKeyShares,
357
+ externalServerKeyShares: resolvedKeyShares,
366
358
  isFormatted: true,
367
359
  context,
368
360
  bitcoinConfig: completeBitcoinConfig,
369
- onError
361
+ onError,
362
+ walletMetadata,
363
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
370
364
  });
371
365
  const sigBuffer = btcUtils.convertSignatureToTaprootBuffer(signature);
372
366
  psbt.updateInput(i, {
@@ -394,14 +388,16 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
394
388
  const hash = tx.hashForWitnessV0(i, scriptCode, value, bitcoin__namespace.Transaction.SIGHASH_ALL);
395
389
  const signature = await this.sign({
396
390
  message: new Uint8Array(hash),
397
- accountAddress: senderAddress,
391
+ accountAddress,
398
392
  chainName: this.chainName,
399
393
  password,
400
- externalServerKeyShares: resolvedExternalServerKeyShares,
394
+ externalServerKeyShares: resolvedKeyShares,
401
395
  isFormatted: true,
402
396
  context,
403
397
  bitcoinConfig: completeBitcoinConfig,
404
- onError
398
+ onError,
399
+ walletMetadata,
400
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
405
401
  });
406
402
  const derSignature = btcUtils.convertSignatureToDER(signature);
407
403
  psbt.updateInput(i, {
@@ -421,7 +417,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
421
417
  message: ERROR_SIGN_TRANSACTION,
422
418
  error: error,
423
419
  context: {
424
- senderAddress
420
+ accountAddress
425
421
  }
426
422
  });
427
423
  if (onError) {
@@ -436,43 +432,21 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
436
432
  * @param password - The password for encrypted backup shares
437
433
  * @param externalServerKeyShares - Optional external server key shares
438
434
  * @returns The private key in WIF format
439
- */ async exportPrivateKey({ accountAddress, password = undefined, externalServerKeyShares }) {
440
- await this.verifyPassword({
441
- accountAddress,
442
- password
443
- });
444
- // Attempt to recover key shares from backup if not provided
445
- await this.ensureKeySharesRecovered({
446
- accountAddress,
447
- password,
448
- walletOperation: node.WalletOperation.EXPORT_PRIVATE_KEY,
449
- externalServerKeyShares,
450
- errorMessage: 'External server key shares are required to export private key. No backup shares available for recovery.'
451
- });
452
- // Re-read wallet from map after recovery (it may have been updated with recovered shares)
453
- const updatedWalletProperties = this.walletMap[accountAddress];
454
- if (!updatedWalletProperties) {
455
- throw new Error('Wallet not found in walletMap after recovery');
456
- }
457
- const derivationPath = updatedWalletProperties.derivationPath;
458
- if (!derivationPath) {
459
- throw new Error('Derivation path missing in walletMap');
460
- }
461
- // Derive address type from derivation path for bitcoinConfig
462
- const addressType = btcUtils.getAddressTypeFromDerivationPath(derivationPath);
435
+ */ async exportPrivateKey({ walletMetadata, password = undefined, externalServerKeyShares }) {
436
+ const { accountAddress } = walletMetadata;
437
+ const { addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
463
438
  const network = core.BitcoinNetwork.MAINNET; // Default to mainnet, could be derived from wallet
464
439
  const bitcoinConfig = {
465
440
  addressType,
466
441
  network
467
442
  };
468
- // Get key shares from wallet map if not provided (recovered from backup)
469
- const resolvedExternalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : updatedWalletProperties.externalServerKeyShares;
470
443
  const { derivedPrivateKey } = await this.exportKey({
471
444
  accountAddress,
472
445
  chainName: this.chainName,
473
446
  password,
474
- externalServerKeyShares: resolvedExternalServerKeyShares,
475
- bitcoinConfig
447
+ externalServerKeyShares,
448
+ bitcoinConfig,
449
+ walletMetadata
476
450
  });
477
451
  if (!derivedPrivateKey) {
478
452
  throw new Error('Derived private key is undefined');
@@ -508,10 +482,10 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
508
482
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet
509
483
  * @param password - The password to use for the wallet
510
484
  * @param onError - The function to call if an error occurs
511
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
485
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
512
486
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
513
487
  * @returns The account address, public key, raw public key, external server key shares
514
- */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, backUpToClientShareService = false, onError, bitcoinConfig }) {
488
+ */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, backUpToDynamic = false, onError, bitcoinConfig }) {
515
489
  try {
516
490
  const { addressType, network = core.BitcoinNetwork.MAINNET } = bitcoinConfig;
517
491
  if (!addressType) {
@@ -520,6 +494,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
520
494
  if (addressType !== core.BitcoinAddressType.NATIVE_SEGWIT && addressType !== core.BitcoinAddressType.TAPROOT) {
521
495
  throw new Error(`Invalid addressType: ${addressType}. Must be one of: ${core.BitcoinAddressType.NATIVE_SEGWIT}, ${core.BitcoinAddressType.TAPROOT}`);
522
496
  }
497
+ let resolvedWalletId;
523
498
  let ceremonyCeremonyCompleteResolver;
524
499
  let ceremonyAccountAddress;
525
500
  const ceremonyCompletePromise = new Promise((resolve)=>{
@@ -539,33 +514,22 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
539
514
  privateKey: formattedPrivateKey,
540
515
  thresholdSignatureScheme,
541
516
  bitcoinConfig,
517
+ password,
518
+ backUpToDynamic,
542
519
  onError,
543
520
  onCeremonyComplete: (accountAddress, walletId)=>{
544
- // Store the ceremony account address to ensure consistency
545
521
  ceremonyAccountAddress = accountAddress;
522
+ resolvedWalletId = walletId;
546
523
  // Verify address matches
547
524
  if (accountAddress !== expectedAddress) {
548
525
  throw new Error(`Public address mismatch: derived address ${accountAddress} !== expected address ${expectedAddress}`);
549
526
  }
550
- // update wallet map
551
- const chainConfig = node.getMPCChainConfig(this.chainName, bitcoinConfig);
552
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
553
- accountAddress,
554
- walletId,
555
- chainName: this.chainName,
556
- thresholdSignatureScheme,
557
- derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
558
- index,
559
- value
560
- ]))),
561
- externalServerKeySharesBackupInfo: node.getExternalServerKeyShareBackupInfo()
562
- });
563
527
  ceremonyCeremonyCompleteResolver(undefined);
564
528
  }
565
529
  });
566
530
  // Wait for the ceremony to complete before proceeding
567
531
  await ceremonyCompletePromise;
568
- if (!rawPublicKey || !externalServerKeyShares) {
532
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId) {
569
533
  throw new Error('Error creating wallet account');
570
534
  }
571
535
  // Use the ceremony account address if available, otherwise derive it from raw public key
@@ -577,19 +541,28 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
577
541
  if (accountAddress !== expectedAddress) {
578
542
  throw new Error(`Public address mismatch: derived address ${accountAddress} !== expected address ${expectedAddress}`);
579
543
  }
580
- const externalKeySharesWithBackupStatus = await this.storeEncryptedBackupByWalletWithRetry({
544
+ const walletMetadata = this.buildWalletMetadata({
545
+ walletId: resolvedWalletId,
546
+ accountAddress,
547
+ thresholdSignatureScheme,
548
+ addressType,
549
+ bitcoinConfig
550
+ });
551
+ const { keySharesWithBackupStatus, backupInfo } = await this.storeEncryptedBackupByWalletWithRetry({
581
552
  accountAddress,
582
553
  externalServerKeyShares,
583
554
  password,
584
- backUpToClientShareService
555
+ backUpToDynamic,
556
+ walletMetadata
585
557
  });
558
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
586
559
  const publicKeyHex = btcUtils.extractPublicKeyHex(rawPublicKey);
587
560
  return {
588
- accountAddress,
561
+ walletMetadata,
589
562
  rawPublicKey,
590
563
  publicKeyHex,
591
564
  externalServerKeyShares,
592
- externalKeySharesWithBackupStatus
565
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
593
566
  };
594
567
  } catch (error) {
595
568
  logError({
package/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createLogError, DynamicWalletClient, getMPCChainConfig, getExternalServerKeyShareBackupInfo, WalletOperation } from '@dynamic-labs-wallet/node';
1
+ import { createLogError, DynamicWalletClient, getMPCChainConfig, WalletOperation } from '@dynamic-labs-wallet/node';
2
2
  import { BitcoinAddressType, BitcoinNetwork } from '@dynamic-labs-wallet/core';
3
3
  import { initEccLib, normalizePublicKey, publicKeyToBitcoinAddress, getAddressTypeFromDerivationPath, extractPublicKeyHex, calculateBip322Hash, calculateTaprootTweak, encodeBip322Signature, doesInputBelongToAddress, collectPSBTInputData, convertSignatureToTaprootBuffer, getBitcoinNetwork, convertSignatureToDER, privateKeyToWIF, wifToPrivateKey, getPublicKeyFromPrivateKey } from '@dynamic-labs-wallet/btc-utils';
4
4
  import * as bitcoin from 'bitcoinjs-lib';
@@ -44,24 +44,33 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
44
44
  };
45
45
  }
46
46
  /**
47
- * Gets wallet properties and derivation info for a given account address
48
- * @param accountAddress - The account address
49
- * @returns The wallet properties, derivation path, and address type
50
- */ getWalletDerivationInfo(accountAddress) {
51
- const walletProperties = this.walletMap[accountAddress];
52
- if (!walletProperties) {
53
- throw new Error('Wallet not found in walletMap');
54
- }
55
- const derivationPath = walletProperties.derivationPath;
47
+ * Extracts derivation path and address type from walletMetadata.
48
+ * @param walletMetadata - The wallet metadata
49
+ * @returns The derivation path and derived address type
50
+ */ getDerivationInfoFromMetadata(walletMetadata) {
51
+ const derivationPath = walletMetadata.derivationPath;
56
52
  if (!derivationPath) {
57
- throw new Error('Derivation path missing in walletMap');
53
+ throw new Error('Derivation path missing in walletMetadata');
58
54
  }
59
55
  return {
60
- walletProperties,
61
56
  derivationPath,
62
57
  addressType: getAddressTypeFromDerivationPath(derivationPath)
63
58
  };
64
59
  }
60
+ buildWalletMetadata({ walletId, accountAddress, thresholdSignatureScheme, addressType, bitcoinConfig }) {
61
+ const chainConfig = getMPCChainConfig(this.chainName, bitcoinConfig);
62
+ return {
63
+ walletId,
64
+ accountAddress,
65
+ chainName: this.chainName,
66
+ thresholdSignatureScheme,
67
+ derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
68
+ index,
69
+ value
70
+ ]))),
71
+ addressType
72
+ };
73
+ }
65
74
  /**
66
75
  * Verifies that the derived address matches the expected address
67
76
  * @param rawPublicKey - The raw public key
@@ -80,10 +89,10 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
80
89
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
81
90
  * @param password - The password to use for the wallet.
82
91
  * @param onError - The function to call if an error occurs.
83
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
92
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
84
93
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
85
94
  * @returns The account address, public key, raw public key, external server key shares, and wallet id.
86
- */ async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, backUpToClientShareService = false, bitcoinConfig }) {
95
+ */ async createWalletAccount({ thresholdSignatureScheme, password, onError, backUpToDynamic = false, bitcoinConfig }) {
87
96
  try {
88
97
  if (!(bitcoinConfig == null ? void 0 : bitcoinConfig.addressType)) {
89
98
  this.logger.warn('[BTC Node Client] addressType not provided for createWalletAccount, defaulting to native_segwit');
@@ -96,6 +105,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
96
105
  addressType,
97
106
  network
98
107
  };
108
+ let resolvedWalletId;
99
109
  let ceremonyCeremonyCompleteResolver;
100
110
  let ceremonyAccountAddress;
101
111
  const ceremonyCompletePromise = new Promise((resolve)=>{
@@ -107,35 +117,17 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
107
117
  thresholdSignatureScheme,
108
118
  skipLock: true,
109
119
  bitcoinConfig: resolvedBitcoinConfig,
120
+ password,
121
+ backUpToDynamic,
110
122
  onError,
111
123
  onCeremonyComplete: (accountAddress, walletId)=>{
112
- // Store the ceremony account address to ensure consistency
113
124
  ceremonyAccountAddress = accountAddress;
114
- // update wallet map
115
- const chainConfig = getMPCChainConfig(this.chainName, resolvedBitcoinConfig);
116
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
117
- accountAddress,
118
- walletId,
119
- chainName: this.chainName,
120
- thresholdSignatureScheme,
121
- derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
122
- index,
123
- value
124
- ]))),
125
- externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
126
- });
127
- this.logger.debug('walletMap updated for wallet', {
128
- context: {
129
- accountAddress,
130
- walletId,
131
- walletMap: this.walletMap
132
- }
133
- });
125
+ resolvedWalletId = walletId;
134
126
  ceremonyCeremonyCompleteResolver(undefined);
135
127
  }
136
128
  });
137
129
  await ceremonyCompletePromise;
138
- if (!rawPublicKey || !externalServerKeyShares) {
130
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId) {
139
131
  throw new Error(ERROR_KEYGEN_FAILED);
140
132
  }
141
133
  const accountAddress = ceremonyAccountAddress || this.deriveAccountAddress({
@@ -143,19 +135,28 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
143
135
  addressType,
144
136
  network
145
137
  }).accountAddress;
146
- const externalKeySharesWithBackupStatus = await this.storeEncryptedBackupByWalletWithRetry({
138
+ const walletMetadata = this.buildWalletMetadata({
139
+ walletId: resolvedWalletId,
140
+ accountAddress,
141
+ thresholdSignatureScheme,
142
+ addressType,
143
+ bitcoinConfig: resolvedBitcoinConfig
144
+ });
145
+ const { keySharesWithBackupStatus, backupInfo } = await this.storeEncryptedBackupByWalletWithRetry({
147
146
  accountAddress,
148
147
  externalServerKeyShares,
149
148
  password,
150
- backUpToClientShareService
149
+ backUpToDynamic,
150
+ walletMetadata
151
151
  });
152
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
152
153
  const publicKeyHex = extractPublicKeyHex(rawPublicKey);
153
154
  return {
154
- accountAddress,
155
+ walletMetadata,
155
156
  rawPublicKey,
156
157
  publicKeyHex,
157
158
  externalServerKeyShares,
158
- externalKeySharesWithBackupStatus
159
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
159
160
  };
160
161
  } catch (error) {
161
162
  logError({
@@ -181,32 +182,29 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
181
182
  * @param onError - Optional. Error callback function
182
183
  * @returns Promise resolving to the BIP-322 signature as a base64 string
183
184
  * @throws Error if required parameters are missing, derivation path is invalid, or signing fails
184
- */ async signMessage({ message, accountAddress, network, password = undefined, externalServerKeyShares, context, onError }) {
185
+ */ async signMessage({ message, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
186
+ const { accountAddress } = walletMetadata;
185
187
  try {
186
- var _this_walletMap_accountAddress;
187
188
  if (!accountAddress) {
188
189
  throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
189
190
  }
190
- const { derivationPath, addressType } = this.getWalletDerivationInfo(accountAddress);
191
- // Attempt to recover key shares from backup if not provided
192
- await this.ensureKeySharesRecovered({
191
+ const { derivationPath, addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
192
+ // Resolve key shares from param or backup
193
+ const resolvedKeyShares = await this.resolveKeyShares({
193
194
  accountAddress,
194
195
  password,
195
196
  walletOperation: WalletOperation.SIGN_MESSAGE,
196
197
  externalServerKeyShares,
197
- errorMessage: 'External server key shares are required to sign a message. No backup shares available for recovery.'
198
+ errorMessage: 'External server key shares are required to sign a message. No backup shares available for recovery.',
199
+ walletMetadata
198
200
  });
199
- const resolvedExternalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : (_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.externalServerKeyShares;
200
- if (!resolvedExternalServerKeyShares || resolvedExternalServerKeyShares.length === 0) {
201
- throw new Error('External server key shares are required to sign a message');
202
- }
203
201
  const bitcoinConfig = {
204
202
  addressType,
205
203
  network
206
204
  };
207
205
  const derivedPublicKey = await this.derivePublicKey({
208
206
  chainName: this.chainName,
209
- keyShare: resolvedExternalServerKeyShares[0],
207
+ keyShare: resolvedKeyShares[0],
210
208
  derivationPath: new Uint32Array(Object.values(JSON.parse(derivationPath))),
211
209
  bitcoinConfig
212
210
  });
@@ -233,13 +231,15 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
233
231
  accountAddress,
234
232
  chainName: this.chainName,
235
233
  password,
236
- externalServerKeyShares: resolvedExternalServerKeyShares,
234
+ externalServerKeyShares: resolvedKeyShares,
237
235
  isFormatted: true,
238
236
  context: context != null ? context : {
239
237
  btcMessage: message
240
238
  },
241
239
  bitcoinConfig: completeBitcoinConfig,
242
- onError
240
+ onError,
241
+ walletMetadata,
242
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
243
243
  });
244
244
  const bip322Signature = encodeBip322Signature(toSignPsbt, pubKey, signature, addressType);
245
245
  return bip322Signature;
@@ -254,51 +254,43 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
254
254
  if (onError) {
255
255
  onError(error);
256
256
  }
257
- throw new Error(ERROR_SIGN_MESSAGE);
257
+ throw new Error(ERROR_SIGN_MESSAGE, {
258
+ cause: error
259
+ });
258
260
  }
259
261
  }
260
262
  /**
261
263
  * Signs a Bitcoin transaction (PSBT)
262
264
  *
263
265
  * The address type is automatically derived from the wallet's derivation path.
264
- * Only inputs belonging to the sender address are signed. Supports both TAPROOT
266
+ * Only inputs belonging to the account address are signed. Supports both TAPROOT
265
267
  * (BIP-341) and Native SegWit (BIP-143) signing methods.
266
268
  *
267
269
  * @param transaction - The PSBT to sign as a base64 string
268
- * @param senderAddress - The sender address (must match inputs to be signed)
270
+ * @param accountAddress - The account address (must match inputs to be signed)
269
271
  * @param network - The Bitcoin network (MAINNET or TESTNET)
270
272
  * @param password - Optional password for encrypted backup shares
271
273
  * @param externalServerKeyShares - Optional external server key shares
272
274
  * @param context - Optional. Sign message context for API tracking
273
275
  * @param onError - Optional. Error callback function
274
276
  * @returns Promise resolving to the signed PSBT as a base64 string
275
- * @throws Error if required parameters are missing, no inputs belong to sender address, or signing fails
276
- */ async signTransaction({ transaction, senderAddress, network, password = undefined, externalServerKeyShares, context, onError }) {
277
+ * @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
278
+ */ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
279
+ const { accountAddress } = walletMetadata;
277
280
  try {
278
- await this.verifyPassword({
279
- accountAddress: senderAddress,
280
- password
281
- });
282
- if (!senderAddress) {
281
+ if (!accountAddress) {
283
282
  throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
284
283
  }
285
- const { derivationPath, addressType } = this.getWalletDerivationInfo(senderAddress);
286
- // Attempt to recover key shares from backup if not provided
287
- await this.ensureKeySharesRecovered({
288
- accountAddress: senderAddress,
284
+ const { derivationPath, addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
285
+ // Resolve key shares from param or backup
286
+ const resolvedKeyShares = await this.resolveKeyShares({
287
+ accountAddress,
289
288
  password,
290
289
  walletOperation: WalletOperation.SIGN_TRANSACTION,
291
290
  externalServerKeyShares,
292
- errorMessage: 'External server key shares are required to sign transaction. No backup shares available for recovery.'
291
+ errorMessage: 'External server key shares are required to sign transaction. No backup shares available for recovery.',
292
+ walletMetadata
293
293
  });
294
- const updatedWalletProperties = this.walletMap[senderAddress];
295
- if (!updatedWalletProperties) {
296
- throw new Error('Wallet not found in walletMap after key share recovery');
297
- }
298
- const resolvedExternalServerKeyShares = externalServerKeyShares || updatedWalletProperties.externalServerKeyShares;
299
- if (!resolvedExternalServerKeyShares || resolvedExternalServerKeyShares.length === 0) {
300
- throw new Error('External server key shares are required to sign transaction. No backup shares available for recovery.');
301
- }
302
294
  const bitcoinConfig = {
303
295
  addressType,
304
296
  network
@@ -306,7 +298,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
306
298
  const psbt = bitcoin.Psbt.fromBase64(transaction);
307
299
  const derivedPublicKey = await this.derivePublicKey({
308
300
  chainName: this.chainName,
309
- keyShare: resolvedExternalServerKeyShares[0],
301
+ keyShare: resolvedKeyShares[0],
310
302
  derivationPath: new Uint32Array(Object.values(JSON.parse(derivationPath))),
311
303
  bitcoinConfig
312
304
  });
@@ -319,9 +311,9 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
319
311
  const inputsToSign = psbt.data.inputs.map((input, i)=>({
320
312
  input,
321
313
  index: i
322
- })).filter(({ input })=>doesInputBelongToAddress(input, senderAddress, network));
314
+ })).filter(({ input })=>doesInputBelongToAddress(input, accountAddress, network));
323
315
  if (inputsToSign.length === 0) {
324
- throw new Error('No inputs found that belong to the sender address');
316
+ throw new Error('No inputs found that belong to the account address');
325
317
  }
326
318
  if (addressType === BitcoinAddressType.TAPROOT) {
327
319
  const tweak = calculateTaprootTweak(pubKey);
@@ -337,14 +329,16 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
337
329
  const hash = Buffer.from(tx.hashForWitnessV1(i, prevOutScripts, values, bitcoin.Transaction.SIGHASH_DEFAULT));
338
330
  const signature = await this.sign({
339
331
  message: new Uint8Array(hash),
340
- accountAddress: senderAddress,
332
+ accountAddress,
341
333
  chainName: this.chainName,
342
334
  password,
343
- externalServerKeyShares: resolvedExternalServerKeyShares,
335
+ externalServerKeyShares: resolvedKeyShares,
344
336
  isFormatted: true,
345
337
  context,
346
338
  bitcoinConfig: completeBitcoinConfig,
347
- onError
339
+ onError,
340
+ walletMetadata,
341
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
348
342
  });
349
343
  const sigBuffer = convertSignatureToTaprootBuffer(signature);
350
344
  psbt.updateInput(i, {
@@ -372,14 +366,16 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
372
366
  const hash = tx.hashForWitnessV0(i, scriptCode, value, bitcoin.Transaction.SIGHASH_ALL);
373
367
  const signature = await this.sign({
374
368
  message: new Uint8Array(hash),
375
- accountAddress: senderAddress,
369
+ accountAddress,
376
370
  chainName: this.chainName,
377
371
  password,
378
- externalServerKeyShares: resolvedExternalServerKeyShares,
372
+ externalServerKeyShares: resolvedKeyShares,
379
373
  isFormatted: true,
380
374
  context,
381
375
  bitcoinConfig: completeBitcoinConfig,
382
- onError
376
+ onError,
377
+ walletMetadata,
378
+ passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
383
379
  });
384
380
  const derSignature = convertSignatureToDER(signature);
385
381
  psbt.updateInput(i, {
@@ -399,7 +395,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
399
395
  message: ERROR_SIGN_TRANSACTION,
400
396
  error: error,
401
397
  context: {
402
- senderAddress
398
+ accountAddress
403
399
  }
404
400
  });
405
401
  if (onError) {
@@ -414,43 +410,21 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
414
410
  * @param password - The password for encrypted backup shares
415
411
  * @param externalServerKeyShares - Optional external server key shares
416
412
  * @returns The private key in WIF format
417
- */ async exportPrivateKey({ accountAddress, password = undefined, externalServerKeyShares }) {
418
- await this.verifyPassword({
419
- accountAddress,
420
- password
421
- });
422
- // Attempt to recover key shares from backup if not provided
423
- await this.ensureKeySharesRecovered({
424
- accountAddress,
425
- password,
426
- walletOperation: WalletOperation.EXPORT_PRIVATE_KEY,
427
- externalServerKeyShares,
428
- errorMessage: 'External server key shares are required to export private key. No backup shares available for recovery.'
429
- });
430
- // Re-read wallet from map after recovery (it may have been updated with recovered shares)
431
- const updatedWalletProperties = this.walletMap[accountAddress];
432
- if (!updatedWalletProperties) {
433
- throw new Error('Wallet not found in walletMap after recovery');
434
- }
435
- const derivationPath = updatedWalletProperties.derivationPath;
436
- if (!derivationPath) {
437
- throw new Error('Derivation path missing in walletMap');
438
- }
439
- // Derive address type from derivation path for bitcoinConfig
440
- const addressType = getAddressTypeFromDerivationPath(derivationPath);
413
+ */ async exportPrivateKey({ walletMetadata, password = undefined, externalServerKeyShares }) {
414
+ const { accountAddress } = walletMetadata;
415
+ const { addressType } = this.getDerivationInfoFromMetadata(walletMetadata);
441
416
  const network = BitcoinNetwork.MAINNET; // Default to mainnet, could be derived from wallet
442
417
  const bitcoinConfig = {
443
418
  addressType,
444
419
  network
445
420
  };
446
- // Get key shares from wallet map if not provided (recovered from backup)
447
- const resolvedExternalServerKeyShares = externalServerKeyShares != null ? externalServerKeyShares : updatedWalletProperties.externalServerKeyShares;
448
421
  const { derivedPrivateKey } = await this.exportKey({
449
422
  accountAddress,
450
423
  chainName: this.chainName,
451
424
  password,
452
- externalServerKeyShares: resolvedExternalServerKeyShares,
453
- bitcoinConfig
425
+ externalServerKeyShares,
426
+ bitcoinConfig,
427
+ walletMetadata
454
428
  });
455
429
  if (!derivedPrivateKey) {
456
430
  throw new Error('Derived private key is undefined');
@@ -486,10 +460,10 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
486
460
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet
487
461
  * @param password - The password to use for the wallet
488
462
  * @param onError - The function to call if an error occurs
489
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
463
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
490
464
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
491
465
  * @returns The account address, public key, raw public key, external server key shares
492
- */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, backUpToClientShareService = false, onError, bitcoinConfig }) {
466
+ */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, backUpToDynamic = false, onError, bitcoinConfig }) {
493
467
  try {
494
468
  const { addressType, network = BitcoinNetwork.MAINNET } = bitcoinConfig;
495
469
  if (!addressType) {
@@ -498,6 +472,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
498
472
  if (addressType !== BitcoinAddressType.NATIVE_SEGWIT && addressType !== BitcoinAddressType.TAPROOT) {
499
473
  throw new Error(`Invalid addressType: ${addressType}. Must be one of: ${BitcoinAddressType.NATIVE_SEGWIT}, ${BitcoinAddressType.TAPROOT}`);
500
474
  }
475
+ let resolvedWalletId;
501
476
  let ceremonyCeremonyCompleteResolver;
502
477
  let ceremonyAccountAddress;
503
478
  const ceremonyCompletePromise = new Promise((resolve)=>{
@@ -517,33 +492,22 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
517
492
  privateKey: formattedPrivateKey,
518
493
  thresholdSignatureScheme,
519
494
  bitcoinConfig,
495
+ password,
496
+ backUpToDynamic,
520
497
  onError,
521
498
  onCeremonyComplete: (accountAddress, walletId)=>{
522
- // Store the ceremony account address to ensure consistency
523
499
  ceremonyAccountAddress = accountAddress;
500
+ resolvedWalletId = walletId;
524
501
  // Verify address matches
525
502
  if (accountAddress !== expectedAddress) {
526
503
  throw new Error(`Public address mismatch: derived address ${accountAddress} !== expected address ${expectedAddress}`);
527
504
  }
528
- // update wallet map
529
- const chainConfig = getMPCChainConfig(this.chainName, bitcoinConfig);
530
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
531
- accountAddress,
532
- walletId,
533
- chainName: this.chainName,
534
- thresholdSignatureScheme,
535
- derivationPath: JSON.stringify(Object.fromEntries(chainConfig.derivationPath.map((value, index)=>[
536
- index,
537
- value
538
- ]))),
539
- externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
540
- });
541
505
  ceremonyCeremonyCompleteResolver(undefined);
542
506
  }
543
507
  });
544
508
  // Wait for the ceremony to complete before proceeding
545
509
  await ceremonyCompletePromise;
546
- if (!rawPublicKey || !externalServerKeyShares) {
510
+ if (!rawPublicKey || !externalServerKeyShares || !resolvedWalletId) {
547
511
  throw new Error('Error creating wallet account');
548
512
  }
549
513
  // Use the ceremony account address if available, otherwise derive it from raw public key
@@ -555,19 +519,28 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
555
519
  if (accountAddress !== expectedAddress) {
556
520
  throw new Error(`Public address mismatch: derived address ${accountAddress} !== expected address ${expectedAddress}`);
557
521
  }
558
- const externalKeySharesWithBackupStatus = await this.storeEncryptedBackupByWalletWithRetry({
522
+ const walletMetadata = this.buildWalletMetadata({
523
+ walletId: resolvedWalletId,
524
+ accountAddress,
525
+ thresholdSignatureScheme,
526
+ addressType,
527
+ bitcoinConfig
528
+ });
529
+ const { keySharesWithBackupStatus, backupInfo } = await this.storeEncryptedBackupByWalletWithRetry({
559
530
  accountAddress,
560
531
  externalServerKeyShares,
561
532
  password,
562
- backUpToClientShareService
533
+ backUpToDynamic,
534
+ walletMetadata
563
535
  });
536
+ walletMetadata.externalServerKeySharesBackupInfo = backupInfo;
564
537
  const publicKeyHex = extractPublicKeyHex(rawPublicKey);
565
538
  return {
566
- accountAddress,
539
+ walletMetadata,
567
540
  rawPublicKey,
568
541
  publicKeyHex,
569
542
  externalServerKeyShares,
570
- externalKeySharesWithBackupStatus
543
+ externalKeySharesWithBackupStatus: keySharesWithBackupStatus
571
544
  };
572
545
  } catch (error) {
573
546
  logError({
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dynamic-labs-wallet/node-btc",
3
- "version": "0.0.354",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
7
- "@dynamic-labs-wallet/core": "0.0.354",
8
- "@dynamic-labs-wallet/node": "0.0.354",
9
- "@dynamic-labs-wallet/btc-utils": "0.0.354",
7
+ "@dynamic-labs-wallet/core": "1.0.0",
8
+ "@dynamic-labs-wallet/node": "1.0.0",
9
+ "@dynamic-labs-wallet/btc-utils": "1.0.0",
10
10
  "@dynamic-labs/sdk-api-core": "^0.0.984",
11
11
  "bitcoinjs-lib": "^7.0.0",
12
12
  "tiny-secp256k1": "^2.2.3"
@@ -1,4 +1,4 @@
1
- import { DynamicWalletClient, type DynamicWalletClientProps, type ServerKeyShare, type ThresholdSignatureScheme, type EcdsaPublicKey, type BIP340KeygenResult, type EcdsaKeygenResult, type WalletProperties } from '@dynamic-labs-wallet/node';
1
+ import { DynamicWalletClient, type DynamicWalletClientProps, type ServerKeyShare, type ThresholdSignatureScheme, type EcdsaPublicKey, type BIP340KeygenResult, type EcdsaKeygenResult, type WalletMetadata, type WalletProperties } from '@dynamic-labs-wallet/node';
2
2
  import type { SignMessageContext } from '@dynamic-labs/sdk-api-core';
3
3
  import { BitcoinAddressType, BitcoinNetwork, type BitcoinConfig } from '@dynamic-labs-wallet/core';
4
4
  export declare class DynamicBtcWalletClient extends DynamicWalletClient {
@@ -22,11 +22,12 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
22
22
  accountAddress: string;
23
23
  };
24
24
  /**
25
- * Gets wallet properties and derivation info for a given account address
26
- * @param accountAddress - The account address
27
- * @returns The wallet properties, derivation path, and address type
25
+ * Extracts derivation path and address type from walletMetadata.
26
+ * @param walletMetadata - The wallet metadata
27
+ * @returns The derivation path and derived address type
28
28
  */
29
- private getWalletDerivationInfo;
29
+ private getDerivationInfoFromMetadata;
30
+ private buildWalletMetadata;
30
31
  /**
31
32
  * Verifies that the derived address matches the expected address
32
33
  * @param rawPublicKey - The raw public key
@@ -40,21 +41,20 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
40
41
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet.
41
42
  * @param password - The password to use for the wallet.
42
43
  * @param onError - The function to call if an error occurs.
43
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
44
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
44
45
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
45
46
  * @returns The account address, public key, raw public key, external server key shares, and wallet id.
46
47
  */
47
- createWalletAccount({ thresholdSignatureScheme, password, onError, backUpToClientShareService, bitcoinConfig, }: {
48
+ createWalletAccount({ thresholdSignatureScheme, password, onError, backUpToDynamic, bitcoinConfig, }: {
48
49
  thresholdSignatureScheme: ThresholdSignatureScheme;
49
50
  password?: string;
50
51
  onError?: (error: Error) => void;
51
- backUpToClientShareService?: boolean;
52
+ backUpToDynamic?: boolean;
52
53
  bitcoinConfig?: BitcoinConfig;
53
54
  }): Promise<{
54
- accountAddress: string;
55
+ walletMetadata: WalletMetadata;
55
56
  publicKeyHex: string;
56
57
  rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
57
- /** @deprecated Use externalKeySharesWithBackupStatus instead */
58
58
  externalServerKeyShares: ServerKeyShare[];
59
59
  externalKeySharesWithBackupStatus: Array<{
60
60
  share: ServerKeyShare;
@@ -77,9 +77,9 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
77
77
  * @returns Promise resolving to the BIP-322 signature as a base64 string
78
78
  * @throws Error if required parameters are missing, derivation path is invalid, or signing fails
79
79
  */
80
- signMessage({ message, accountAddress, network, password, externalServerKeyShares, context, onError, }: {
80
+ signMessage({ message, walletMetadata, network, password, externalServerKeyShares, context, onError, }: {
81
81
  message: string;
82
- accountAddress: string;
82
+ walletMetadata: WalletMetadata;
83
83
  network: BitcoinNetwork;
84
84
  password?: string;
85
85
  externalServerKeyShares?: ServerKeyShare[];
@@ -90,22 +90,22 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
90
90
  * Signs a Bitcoin transaction (PSBT)
91
91
  *
92
92
  * The address type is automatically derived from the wallet's derivation path.
93
- * Only inputs belonging to the sender address are signed. Supports both TAPROOT
93
+ * Only inputs belonging to the account address are signed. Supports both TAPROOT
94
94
  * (BIP-341) and Native SegWit (BIP-143) signing methods.
95
95
  *
96
96
  * @param transaction - The PSBT to sign as a base64 string
97
- * @param senderAddress - The sender address (must match inputs to be signed)
97
+ * @param accountAddress - The account address (must match inputs to be signed)
98
98
  * @param network - The Bitcoin network (MAINNET or TESTNET)
99
99
  * @param password - Optional password for encrypted backup shares
100
100
  * @param externalServerKeyShares - Optional external server key shares
101
101
  * @param context - Optional. Sign message context for API tracking
102
102
  * @param onError - Optional. Error callback function
103
103
  * @returns Promise resolving to the signed PSBT as a base64 string
104
- * @throws Error if required parameters are missing, no inputs belong to sender address, or signing fails
104
+ * @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
105
105
  */
106
- signTransaction({ transaction, senderAddress, network, password, externalServerKeyShares, context, onError, }: {
106
+ signTransaction({ transaction, walletMetadata, network, password, externalServerKeyShares, context, onError, }: {
107
107
  transaction: string;
108
- senderAddress: string;
108
+ walletMetadata: WalletMetadata;
109
109
  network: BitcoinNetwork;
110
110
  password?: string;
111
111
  externalServerKeyShares?: ServerKeyShare[];
@@ -119,8 +119,8 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
119
119
  * @param externalServerKeyShares - Optional external server key shares
120
120
  * @returns The private key in WIF format
121
121
  */
122
- exportPrivateKey({ accountAddress, password, externalServerKeyShares, }: {
123
- accountAddress: string;
122
+ exportPrivateKey({ walletMetadata, password, externalServerKeyShares, }: {
123
+ walletMetadata: WalletMetadata;
124
124
  password?: string;
125
125
  externalServerKeyShares?: ServerKeyShare[];
126
126
  }): Promise<string>;
@@ -143,23 +143,22 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
143
143
  * @param thresholdSignatureScheme - The threshold signature scheme to use for the wallet
144
144
  * @param password - The password to use for the wallet
145
145
  * @param onError - The function to call if an error occurs
146
- * @param backUpToClientShareService - Whether to back up the external server key shares to the client share service. By default, it is false.
146
+ * @param backUpToDynamic - Whether to back up the external server key shares to the client share service. By default, it is false.
147
147
  * @param bitcoinConfig - Bitcoin configuration (addressType, network)
148
148
  * @returns The account address, public key, raw public key, external server key shares
149
149
  */
150
- importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, backUpToClientShareService, onError, bitcoinConfig, }: {
150
+ importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, backUpToDynamic, onError, bitcoinConfig, }: {
151
151
  privateKey: string;
152
152
  chainName: string;
153
153
  thresholdSignatureScheme: ThresholdSignatureScheme;
154
154
  password?: string;
155
- backUpToClientShareService?: boolean;
155
+ backUpToDynamic?: boolean;
156
156
  onError?: (error: Error) => void;
157
157
  bitcoinConfig: BitcoinConfig;
158
158
  }): Promise<{
159
- accountAddress: string;
159
+ walletMetadata: WalletMetadata;
160
160
  publicKeyHex: string;
161
161
  rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
162
- /** @deprecated Use externalKeySharesWithBackupStatus instead */
163
162
  externalServerKeyShares: ServerKeyShare[];
164
163
  externalKeySharesWithBackupStatus: Array<{
165
164
  share: ServerKeyShare;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}