@dynamic-labs-wallet/node-btc 1.0.105 → 1.0.106
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 +20 -7
- package/index.esm.js +21 -8
- package/package.json +4 -4
- package/src/client/client.d.ts +3 -1
- package/src/client/client.d.ts.map +1 -1
package/index.cjs
CHANGED
|
@@ -313,7 +313,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
313
313
|
* @param onError - Optional. Error callback function
|
|
314
314
|
* @returns Promise resolving to the signed PSBT as a base64 string
|
|
315
315
|
* @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
|
|
316
|
-
*/ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
|
|
316
|
+
*/ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError, signingIndexes, allowedSighash }) {
|
|
317
317
|
const { accountAddress } = walletMetadata;
|
|
318
318
|
try {
|
|
319
319
|
if (!accountAddress) {
|
|
@@ -346,14 +346,25 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
346
346
|
const pubKey = btcUtils.normalizePublicKey(derivedPublicKey, addressType);
|
|
347
347
|
const tx = psbt.__CACHE.__TX;
|
|
348
348
|
// Filter inputs to only sign those that belong to the current address
|
|
349
|
-
|
|
349
|
+
let inputsToSign = psbt.data.inputs.map((input, i)=>({
|
|
350
350
|
input,
|
|
351
351
|
index: i
|
|
352
352
|
})).filter(({ input })=>btcUtils.doesInputBelongToAddress(input, accountAddress, network));
|
|
353
|
+
if (signingIndexes == null ? void 0 : signingIndexes.length) {
|
|
354
|
+
const walletOwnedIndexSet = new Set(inputsToSign.map(({ index })=>index));
|
|
355
|
+
const invalidIndexes = signingIndexes.filter((i)=>!walletOwnedIndexSet.has(i));
|
|
356
|
+
if (invalidIndexes.length > 0) {
|
|
357
|
+
throw new Error(`signingIndexes contains indexes that do not belong to the signing address: ${invalidIndexes.join(', ')}`);
|
|
358
|
+
}
|
|
359
|
+
const requestedIndexSet = new Set(signingIndexes);
|
|
360
|
+
inputsToSign = inputsToSign.filter(({ index })=>requestedIndexSet.has(index));
|
|
361
|
+
}
|
|
353
362
|
if (inputsToSign.length === 0) {
|
|
354
363
|
throw new Error('No inputs found that belong to the account address');
|
|
355
364
|
}
|
|
356
|
-
|
|
365
|
+
const isTaproot = addressType === core.BitcoinAddressType.TAPROOT;
|
|
366
|
+
btcUtils.assertSighashAllowed(inputsToSign, isTaproot, allowedSighash);
|
|
367
|
+
if (isTaproot) {
|
|
357
368
|
const tweak = btcUtils.calculateTaprootTweak(pubKey);
|
|
358
369
|
const completeBitcoinConfig = _extends({}, bitcoinConfig, {
|
|
359
370
|
addressType,
|
|
@@ -364,7 +375,8 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
364
375
|
if (!input.witnessUtxo) {
|
|
365
376
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
366
377
|
}
|
|
367
|
-
const
|
|
378
|
+
const sigHashType = btcUtils.getSigHashType(input, true);
|
|
379
|
+
const hash = Buffer.from(tx.hashForWitnessV1(i, prevOutScripts, values, sigHashType));
|
|
368
380
|
const signature = await this.sign({
|
|
369
381
|
message: new Uint8Array(hash),
|
|
370
382
|
accountAddress,
|
|
@@ -383,7 +395,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
383
395
|
walletMetadata,
|
|
384
396
|
passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
|
|
385
397
|
});
|
|
386
|
-
const sigBuffer = btcUtils.convertSignatureToTaprootBuffer(signature);
|
|
398
|
+
const sigBuffer = btcUtils.convertSignatureToTaprootBuffer(signature, sigHashType);
|
|
387
399
|
psbt.updateInput(i, {
|
|
388
400
|
tapKeySig: sigBuffer
|
|
389
401
|
});
|
|
@@ -406,7 +418,8 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
406
418
|
if (!scriptCode) {
|
|
407
419
|
throw new Error('Failed to generate scriptCode');
|
|
408
420
|
}
|
|
409
|
-
const
|
|
421
|
+
const sigHashType = btcUtils.getSigHashType(input, false);
|
|
422
|
+
const hash = tx.hashForWitnessV0(i, scriptCode, value, sigHashType);
|
|
410
423
|
const signature = await this.sign({
|
|
411
424
|
message: new Uint8Array(hash),
|
|
412
425
|
accountAddress,
|
|
@@ -425,7 +438,7 @@ class DynamicBtcWalletClient extends node.DynamicWalletClient {
|
|
|
425
438
|
walletMetadata,
|
|
426
439
|
passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
|
|
427
440
|
});
|
|
428
|
-
const derSignature = btcUtils.convertSignatureToDER(signature);
|
|
441
|
+
const derSignature = btcUtils.convertSignatureToDER(signature, sigHashType);
|
|
429
442
|
psbt.updateInput(i, {
|
|
430
443
|
partialSig: [
|
|
431
444
|
{
|
package/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createLogError, DynamicWalletClient, getMPCChainConfig, WalletOperation } from '@dynamic-labs-wallet/node';
|
|
2
2
|
import { BitcoinNetwork, BitcoinAddressType } from '@dynamic-labs-wallet/core';
|
|
3
|
-
import { initEccLib, normalizePublicKey, publicKeyToBitcoinAddress, getAddressTypeFromDerivationPath, extractPublicKeyHex, calculateBip322Hash, calculateTaprootTweak, encodeBip322Signature, doesInputBelongToAddress, collectPSBTInputData, convertSignatureToTaprootBuffer, getBitcoinNetwork, convertSignatureToDER, privateKeyToWIF, wifToPrivateKey, getPublicKeyFromPrivateKey } from '@dynamic-labs-wallet/btc-utils';
|
|
3
|
+
import { initEccLib, normalizePublicKey, publicKeyToBitcoinAddress, getAddressTypeFromDerivationPath, extractPublicKeyHex, calculateBip322Hash, calculateTaprootTweak, encodeBip322Signature, doesInputBelongToAddress, assertSighashAllowed, collectPSBTInputData, getSigHashType, convertSignatureToTaprootBuffer, getBitcoinNetwork, convertSignatureToDER, privateKeyToWIF, wifToPrivateKey, getPublicKeyFromPrivateKey } from '@dynamic-labs-wallet/btc-utils';
|
|
4
4
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
5
5
|
import * as ecc from 'tiny-secp256k1';
|
|
6
6
|
|
|
@@ -291,7 +291,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
291
291
|
* @param onError - Optional. Error callback function
|
|
292
292
|
* @returns Promise resolving to the signed PSBT as a base64 string
|
|
293
293
|
* @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
|
|
294
|
-
*/ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError }) {
|
|
294
|
+
*/ async signTransaction({ transaction, walletMetadata, network, password = undefined, externalServerKeyShares, context, onError, signingIndexes, allowedSighash }) {
|
|
295
295
|
const { accountAddress } = walletMetadata;
|
|
296
296
|
try {
|
|
297
297
|
if (!accountAddress) {
|
|
@@ -324,14 +324,25 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
324
324
|
const pubKey = normalizePublicKey(derivedPublicKey, addressType);
|
|
325
325
|
const tx = psbt.__CACHE.__TX;
|
|
326
326
|
// Filter inputs to only sign those that belong to the current address
|
|
327
|
-
|
|
327
|
+
let inputsToSign = psbt.data.inputs.map((input, i)=>({
|
|
328
328
|
input,
|
|
329
329
|
index: i
|
|
330
330
|
})).filter(({ input })=>doesInputBelongToAddress(input, accountAddress, network));
|
|
331
|
+
if (signingIndexes == null ? void 0 : signingIndexes.length) {
|
|
332
|
+
const walletOwnedIndexSet = new Set(inputsToSign.map(({ index })=>index));
|
|
333
|
+
const invalidIndexes = signingIndexes.filter((i)=>!walletOwnedIndexSet.has(i));
|
|
334
|
+
if (invalidIndexes.length > 0) {
|
|
335
|
+
throw new Error(`signingIndexes contains indexes that do not belong to the signing address: ${invalidIndexes.join(', ')}`);
|
|
336
|
+
}
|
|
337
|
+
const requestedIndexSet = new Set(signingIndexes);
|
|
338
|
+
inputsToSign = inputsToSign.filter(({ index })=>requestedIndexSet.has(index));
|
|
339
|
+
}
|
|
331
340
|
if (inputsToSign.length === 0) {
|
|
332
341
|
throw new Error('No inputs found that belong to the account address');
|
|
333
342
|
}
|
|
334
|
-
|
|
343
|
+
const isTaproot = addressType === BitcoinAddressType.TAPROOT;
|
|
344
|
+
assertSighashAllowed(inputsToSign, isTaproot, allowedSighash);
|
|
345
|
+
if (isTaproot) {
|
|
335
346
|
const tweak = calculateTaprootTweak(pubKey);
|
|
336
347
|
const completeBitcoinConfig = _extends({}, bitcoinConfig, {
|
|
337
348
|
addressType,
|
|
@@ -342,7 +353,8 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
342
353
|
if (!input.witnessUtxo) {
|
|
343
354
|
throw new Error(`Input ${i} missing witnessUtxo`);
|
|
344
355
|
}
|
|
345
|
-
const
|
|
356
|
+
const sigHashType = getSigHashType(input, true);
|
|
357
|
+
const hash = Buffer.from(tx.hashForWitnessV1(i, prevOutScripts, values, sigHashType));
|
|
346
358
|
const signature = await this.sign({
|
|
347
359
|
message: new Uint8Array(hash),
|
|
348
360
|
accountAddress,
|
|
@@ -361,7 +373,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
361
373
|
walletMetadata,
|
|
362
374
|
passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
|
|
363
375
|
});
|
|
364
|
-
const sigBuffer = convertSignatureToTaprootBuffer(signature);
|
|
376
|
+
const sigBuffer = convertSignatureToTaprootBuffer(signature, sigHashType);
|
|
365
377
|
psbt.updateInput(i, {
|
|
366
378
|
tapKeySig: sigBuffer
|
|
367
379
|
});
|
|
@@ -384,7 +396,8 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
384
396
|
if (!scriptCode) {
|
|
385
397
|
throw new Error('Failed to generate scriptCode');
|
|
386
398
|
}
|
|
387
|
-
const
|
|
399
|
+
const sigHashType = getSigHashType(input, false);
|
|
400
|
+
const hash = tx.hashForWitnessV0(i, scriptCode, value, sigHashType);
|
|
388
401
|
const signature = await this.sign({
|
|
389
402
|
message: new Uint8Array(hash),
|
|
390
403
|
accountAddress,
|
|
@@ -403,7 +416,7 @@ class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
403
416
|
walletMetadata,
|
|
404
417
|
passwordPreVerified: !(externalServerKeyShares == null ? void 0 : externalServerKeyShares.length) && !!password
|
|
405
418
|
});
|
|
406
|
-
const derSignature = convertSignatureToDER(signature);
|
|
419
|
+
const derSignature = convertSignatureToDER(signature, sigHashType);
|
|
407
420
|
psbt.updateInput(i, {
|
|
408
421
|
partialSig: [
|
|
409
422
|
{
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/node-btc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.106",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@dynamic-labs-wallet/core": "1.0.
|
|
8
|
-
"@dynamic-labs-wallet/node": "1.0.
|
|
9
|
-
"@dynamic-labs-wallet/btc-utils": "1.0.
|
|
7
|
+
"@dynamic-labs-wallet/core": "1.0.106",
|
|
8
|
+
"@dynamic-labs-wallet/node": "1.0.106",
|
|
9
|
+
"@dynamic-labs-wallet/btc-utils": "1.0.106",
|
|
10
10
|
"@dynamic-labs/sdk-api-core": "^0.0.1093",
|
|
11
11
|
"bitcoinjs-lib": "^7.0.0",
|
|
12
12
|
"tiny-secp256k1": "^2.2.3"
|
package/src/client/client.d.ts
CHANGED
|
@@ -103,7 +103,7 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
103
103
|
* @returns Promise resolving to the signed PSBT as a base64 string
|
|
104
104
|
* @throws Error if required parameters are missing, no inputs belong to account address, or signing fails
|
|
105
105
|
*/
|
|
106
|
-
signTransaction({ transaction, walletMetadata, network, password, externalServerKeyShares, context, onError, }: {
|
|
106
|
+
signTransaction({ transaction, walletMetadata, network, password, externalServerKeyShares, context, onError, signingIndexes, allowedSighash, }: {
|
|
107
107
|
transaction: string;
|
|
108
108
|
walletMetadata: WalletMetadata;
|
|
109
109
|
network: BitcoinNetwork;
|
|
@@ -111,6 +111,8 @@ export declare class DynamicBtcWalletClient extends DynamicWalletClient {
|
|
|
111
111
|
externalServerKeyShares?: ServerKeyShare[];
|
|
112
112
|
context?: SignMessageContext;
|
|
113
113
|
onError?: (error: Error) => void;
|
|
114
|
+
signingIndexes?: number[];
|
|
115
|
+
allowedSighash?: number[];
|
|
114
116
|
}): Promise<string>;
|
|
115
117
|
/**
|
|
116
118
|
* Exports the private key for a wallet
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EAEnB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAItB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EAEnB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAItB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAqCnG,qBAAa,sBAAuB,SAAQ,mBAAmB;IAC7D,QAAQ,CAAC,SAAS,SAAS;gBAEf,EACV,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,MAAM,EACN,KAAK,GACN,EAAE,wBAAwB;IAW3B;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EACnB,YAAY,EACZ,WAAW,EACX,OAAO,GACR,EAAE;QACD,YAAY,EAAE,GAAG,CAAC;QAClB,WAAW,EAAE,kBAAkB,CAAC;QAChC,OAAO,EAAE,cAAc,CAAC;KACzB,GAAG;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE;IAQ9B;;;;OAIG;IACH,OAAO,CAAC,6BAA6B;IAerC,OAAO,CAAC,mBAAmB;IA6B3B;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;;;;;;;OAQG;IACG,mBAAmB,CAAC,EACxB,wBAAwB,EACxB,QAAQ,EACR,OAAO,EACP,eAAuB,EACvB,aAAa,GACd,EAAE;QACD,wBAAwB,EAAE,wBAAwB,CAAC;QACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;QACjC,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B,GAAG,OAAO,CAAC;QACV,cAAc,EAAE,cAAc,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;QAC/D,uBAAuB,EAAE,cAAc,EAAE,CAAC;QAC1C,iCAAiC,EAAE,KAAK,CAAC;YACvC,KAAK,EAAE,cAAc,CAAC;YACtB,+BAA+B,EAAE,OAAO,CAAC;SAC1C,CAAC,CAAC;KACJ,CAAC;IAuFF;;;;;;;;;;;;;;;OAeG;IACG,WAAW,CAAC,EAChB,OAAO,EACP,cAAc,EACd,OAAO,EACP,QAAoB,EACpB,uBAAuB,EACvB,OAAO,EACP,OAAO,GACR,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,cAAc,CAAC;QAC/B,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,uBAAuB,CAAC,EAAE,cAAc,EAAE,CAAC;QAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAC;QAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAClC,GAAG,OAAO,CAAC,MAAM,CAAC;IA2FnB;;;;;;;;;;;;;;;;OAgBG;IACG,eAAe,CAAC,EACpB,WAAW,EACX,cAAc,EACd,OAAO,EACP,QAAoB,EACpB,uBAAuB,EACvB,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,GACf,EAAE;QACD,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,cAAc,CAAC;QAC/B,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,uBAAuB,CAAC,EAAE,cAAc,EAAE,CAAC;QAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAC;QAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;QACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,GAAG,OAAO,CAAC,MAAM,CAAC;IAkMnB;;;;;;OAMG;IACG,gBAAgB,CAAC,EACrB,cAAc,EACd,QAAoB,EACpB,uBAAuB,GACxB,EAAE;QACD,cAAc,EAAE,cAAc,CAAC;QAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,uBAAuB,CAAC,EAAE,cAAc,EAAE,CAAC;KAC5C,GAAG,OAAO,CAAC,MAAM,CAAC;IA6BnB;;;;;;;;;;;OAWG;IACG,uBAAuB,CAAC,EAC5B,SAAS,EACT,cAAc,EACd,aAAa,GACd,EAAE;QACD,SAAS,EAAE,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,EAAE,CAAC;QACtD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnB;;;;;;;;;;OAUG;IACG,gBAAgB,CAAC,EACrB,UAAU,EACV,SAAS,EACT,wBAAwB,EACxB,QAAQ,EACR,eAAuB,EACvB,OAAO,EACP,aAAa,GACd,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,wBAAwB,EAAE,wBAAwB,CAAC;QACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;QACjC,aAAa,EAAE,aAAa,CAAC;KAC9B,GAAG,OAAO,CAAC;QACV,cAAc,EAAE,cAAc,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;QAC/D,uBAAuB,EAAE,cAAc,EAAE,CAAC;QAC1C,iCAAiC,EAAE,KAAK,CAAC;YACvC,KAAK,EAAE,cAAc,CAAC;YACtB,+BAA+B,EAAE,OAAO,CAAC;SAC1C,CAAC,CAAC;KACJ,CAAC;IAoHF;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAQvD"}
|