Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@leather.io/bitcoin

Package Overview
Dependencies
Maintainers
2
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@leather.io/bitcoin - npm Package Compare versions

Comparing version
0.37.0
to
0.37.1
+7
-7
.turbo/turbo-build.log
> @leather.io/bitcoin@0.37.0 build /home/runner/work/mono/mono/packages/bitcoin
> @leather.io/bitcoin@0.37.1 build /home/runner/work/mono/mono/packages/bitcoin
> tsdown

@@ -10,7 +10,7 @@

ℹ Build start
ℹ dist/index.js  58.22 kB │ gzip: 13.64 kB
ℹ dist/index.js.map 117.82 kB │ gzip: 27.59 kB
ℹ dist/index.d.ts.map  11.64 kB │ gzip: 4.75 kB
ℹ dist/index.d.ts  33.53 kB │ gzip: 6.95 kB
ℹ 4 files, total: 221.21 kB
✔ Build complete in 4423ms
ℹ dist/index.js  58.24 kB │ gzip: 13.65 kB
ℹ dist/index.js.map 117.86 kB │ gzip: 27.60 kB
ℹ dist/index.d.ts.map  11.65 kB │ gzip: 4.75 kB
ℹ dist/index.d.ts  33.54 kB │ gzip: 6.96 kB
ℹ 4 files, total: 221.29 kB
✔ Build complete in 4248ms

@@ -143,3 +143,4 @@ import { Bip21Options } from "bip21";

feeRate,
recipients
recipients,
isSendMax
}: GetSpendableAmountArgs<T>): {

@@ -492,5 +493,5 @@ spendableAmount: BigNumber;

declare const paymentTypeMap: Record<BtcSignerLibPaymentTypeIdentifers, BitcoinPaymentTypes>;
declare function btcSignerLibPaymentTypeToPaymentTypeMap(payment: BtcSignerLibPaymentTypeIdentifers): "p2wpkh" | "p2tr" | "p2pkh" | "p2sh" | "p2wpkh-p2sh";
declare function btcSignerLibPaymentTypeToPaymentTypeMap(payment: BtcSignerLibPaymentTypeIdentifers): "p2pkh" | "p2sh" | "p2wpkh-p2sh" | "p2wpkh" | "p2tr";
declare function isBtcSignerLibPaymentType(payment: string): payment is BtcSignerLibPaymentTypeIdentifers;
declare function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | BitcoinPaymentTypes): "p2wpkh" | "p2tr" | "p2pkh" | "p2sh" | "p2wpkh-p2sh";
declare function parseKnownPaymentType(payment: BtcSignerLibPaymentTypeIdentifers | BitcoinPaymentTypes): "p2pkh" | "p2sh" | "p2wpkh-p2sh" | "p2wpkh" | "p2tr";
type PaymentTypeMap<T> = Record<BitcoinPaymentTypes, T>;

@@ -497,0 +498,0 @@ declare function whenPaymentType(mode: BitcoinPaymentTypes | BtcSignerLibPaymentTypeIdentifers): <T>(paymentMap: PaymentTypeMap<T>) => T;

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","names":[],"sources":["../src/bip21/bip21.ts","../src/bip322/bip322-utils.ts","../src/bip322/sign-message-bip322-bitcoinjs.ts","../src/coin-selection/coin-selection.ts","../src/coin-selection/coin-selection.utils.ts","../src/coin-selection/calculate-max-spend.ts","../src/fees/bitcoin-fees.ts","../src/fees/btc-size-fee-estimator.ts","../src/mocks/mocks.ts","../src/schemas/address-schema.ts","../src/signer/bitcoin-signer.ts","../src/utils/bitcoin.network.ts","../src/utils/bitcoin.utils.ts","../src/payments/p2tr-address-gen.ts","../src/payments/p2wpkh-address-gen.ts","../src/payments/p2wsh-p2sh-address-gen.ts","../src/psbt/psbt-inputs.ts","../src/psbt/psbt-outputs.ts","../src/psbt/psbt-totals.ts","../src/psbt/psbt-details.ts","../src/psbt/utils.ts","../src/transactions/generate-unsigned-transaction.ts","../src/validation/address-validation.ts","../src/validation/amount-validation.ts","../src/validation/bitcoin-address.ts","../src/validation/bitcoin-error.ts","../src/utils/bitcoin.descriptors.ts","../src/utils/lookup-derivation-by-address.ts","../src/utils/deconstruct-btc-address.ts"],"sourcesContent":[],"mappings":"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"}
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/bip21/bip21.ts","../src/bip322/bip322-utils.ts","../src/bip322/sign-message-bip322-bitcoinjs.ts","../src/coin-selection/coin-selection.ts","../src/coin-selection/coin-selection.utils.ts","../src/coin-selection/calculate-max-spend.ts","../src/fees/bitcoin-fees.ts","../src/fees/btc-size-fee-estimator.ts","../src/mocks/mocks.ts","../src/schemas/address-schema.ts","../src/signer/bitcoin-signer.ts","../src/utils/bitcoin.network.ts","../src/utils/bitcoin.utils.ts","../src/payments/p2tr-address-gen.ts","../src/payments/p2wpkh-address-gen.ts","../src/payments/p2wsh-p2sh-address-gen.ts","../src/psbt/psbt-inputs.ts","../src/psbt/psbt-outputs.ts","../src/psbt/psbt-totals.ts","../src/psbt/psbt-details.ts","../src/psbt/utils.ts","../src/transactions/generate-unsigned-transaction.ts","../src/validation/address-validation.ts","../src/validation/amount-validation.ts","../src/validation/bitcoin-address.ts","../src/validation/bitcoin-error.ts","../src/utils/bitcoin.descriptors.ts","../src/utils/lookup-derivation-by-address.ts","../src/utils/deconstruct-btc-address.ts"],"sourcesContent":[],"mappings":"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"}

@@ -769,7 +769,8 @@ import { decode, encode } from "bip21";

}
function getSpendableAmount({ utxos, feeRate, recipients }) {
function getSpendableAmount({ utxos, feeRate, recipients, isSendMax }) {
const balance = utxos.map((utxo) => utxo.value).reduce((prevVal, curVal) => prevVal + curVal, 0);
const size = getSizeInfo({
utxos,
recipients
recipients,
isSendMax
});

@@ -776,0 +777,0 @@ const fee = Math.ceil(size.txVBytes * feeRate);

@@ -5,3 +5,3 @@ {

"description": "Shared bitcoin utilities",
"version": "0.37.0",
"version": "0.37.1",
"license": "MIT",

@@ -36,6 +36,6 @@ "homepage": "https://github.com/leather.io/mono/tree/dev/packages/bitcoin",

"zod": "4.0.17",
"@leather.io/crypto": "1.12.17",
"@leather.io/crypto": "1.12.18",
"@leather.io/constants": "0.33.0",
"@leather.io/models": "0.54.0",
"@leather.io/utils": "0.50.0",
"@leather.io/constants": "0.32.0"
"@leather.io/utils": "0.50.1"
},

@@ -48,6 +48,6 @@ "devDependencies": {

"vitest": "2.1.9",
"@leather.io/test-config": "0.1.3",
"@leather.io/rpc": "2.21.11",
"@leather.io/prettier-config": "0.9.0",
"@leather.io/rpc": "2.21.12",
"@leather.io/tsconfig-config": "0.11.1",
"@leather.io/prettier-config": "0.9.0"
"@leather.io/test-config": "0.1.3"
},

@@ -54,0 +54,0 @@ "keywords": [

@@ -0,7 +1,18 @@

import { createMoney } from '@leather.io/utils';
import { recipientAddress, taprootAddress } from '../mocks/mocks';
import { createBitcoinAddress } from '../validation/bitcoin-address';
import { calculateMaxSpend } from './calculate-max-spend';
import { mockUtxos } from './coin-selection.mocks';
import { mockTaprootUtxos, mockUtxos } from './coin-selection.mocks';
import { getSizeInfo } from './coin-selection.utils';
const recipient = createBitcoinAddress('');
describe(calculateMaxSpend.name, () => {
test('that empty utxos returns zero', () => {
const result = calculateMaxSpend({ recipient: recipientAddress, utxos: [], feeRate: 1 });
expect(result.spendAllFee).toEqual(0);
expect(result.amount.amount.toNumber()).toEqual(0);
expect(result.spendableBitcoin.toNumber()).toEqual(0);
});
test('with 1 sat/vb fee', () => {

@@ -13,3 +24,4 @@ const maxBitcoinSpend = calculateMaxSpend({

});
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50087948);
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50087979);
expect(maxBitcoinSpend.spendAllFee).toEqual(621);
});

@@ -23,3 +35,4 @@

});
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50085342);
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50085497);
expect(maxBitcoinSpend.spendAllFee).toEqual(3103);
});

@@ -33,3 +46,4 @@

});
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50073585);
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50074515);
expect(maxBitcoinSpend.spendAllFee).toEqual(10485);
});

@@ -43,3 +57,4 @@

});
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50046950);
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(50050050);
expect(maxBitcoinSpend.spendAllFee).toEqual(34950);
});

@@ -53,4 +68,108 @@

});
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(49969100);
expect(maxBitcoinSpend.amount.amount.toNumber()).toEqual(49981500);
expect(maxBitcoinSpend.spendAllFee).toEqual(58500);
});
describe('with taproot UTXOs', () => {
const taprootRecipient = recipientAddress;
test('with 1 sat/vb fee', () => {
const result = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 1,
});
expect(result.amount.amount.toNumber()).toEqual(50088043);
expect(result.spendAllFee).toEqual(557);
expect(result.spendableBitcoin.toNumber()).toEqual(0.50088043);
});
test('with 5 sat/vb fee', () => {
const result = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 5,
});
expect(result.amount.amount.toNumber()).toEqual(50085815);
expect(result.spendAllFee).toEqual(2785);
});
test('with 30 sat/vb fee', () => {
const result = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 30,
});
expect(result.amount.amount.toNumber()).toEqual(50075160);
expect(result.spendAllFee).toEqual(9840);
});
test('with 100 sat/vb fee', () => {
const result = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 100,
});
expect(result.amount.amount.toNumber()).toEqual(50052200);
expect(result.spendAllFee).toEqual(32800);
});
test('with 400 sat/vb fee', () => {
const result = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 400,
});
expect(result.amount.amount.toNumber()).toEqual(49979600);
expect(result.spendAllFee).toEqual(85400);
});
test('taproot inputs have lower fees than native segwit at same fee rate', () => {
const segwitResult = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockUtxos,
feeRate: 30,
});
const taprootResult = calculateMaxSpend({
recipient: taprootRecipient,
utxos: mockTaprootUtxos,
feeRate: 30,
});
expect(taprootResult.spendAllFee).toBeLessThan(segwitResult.spendAllFee);
});
});
test('send-max fee should not include a change output', () => {
const feeRate = 10;
const utxos = mockTaprootUtxos;
const result = calculateMaxSpend({ recipient: recipientAddress, utxos, feeRate });
const correctSize = getSizeInfo({
utxos,
recipients: [{ address: recipientAddress, amount: createMoney(0, 'BTC') }],
isSendMax: true,
});
const correctFee = Math.ceil(correctSize.txVBytes * feeRate);
expect(result.spendAllFee).toEqual(correctFee);
});
describe('with taproot recipient', () => {
test('P2TR output costs more than P2WPKH output', () => {
const segwitRecipientResult = calculateMaxSpend({
recipient: recipientAddress,
utxos: mockUtxos,
feeRate: 30,
});
const taprootRecipientResult = calculateMaxSpend({
recipient: taprootAddress,
utxos: mockUtxos,
feeRate: 30,
});
expect(segwitRecipientResult.amount.amount.toNumber()).toEqual(50073585);
expect(taprootRecipientResult.amount.amount.toNumber()).toEqual(50073225);
expect(taprootRecipientResult.spendAllFee).toBeGreaterThan(segwitRecipientResult.spendAllFee);
});
});
});

@@ -243,2 +243,25 @@ import { BTC_P2WPKH_DUST_AMOUNT } from '@leather.io/constants';

});
test('that spending all taproot utxos with sendMax produces lower fee than native segwit', () => {
const taprootUtxos = generateMockTaprootTransactions([1000, 2000, 3000]);
const segwitUtxos = generateMockTransactions([1000, 2000, 3000]);
const feeRate = 2;
const taprootResult = determineUtxosForSpendAll({
utxos: taprootUtxos,
recipients: [{ address: recipientAddress, amount: createMoney(5000, 'BTC') }],
feeRate,
});
const segwitResult = determineUtxosForSpendAll({
utxos: segwitUtxos,
recipients: [{ address: recipientAddress, amount: createMoney(5000, 'BTC') }],
feeRate,
});
expect(taprootResult.inputs.length).toEqual(3);
expect(taprootResult.outputs.length).toEqual(1);
expect(taprootResult.fee.amount.isLessThan(segwitResult.fee.amount)).toBeTruthy();
expect(taprootResult.size).toBeGreaterThan(200);
expect(taprootResult.size).toBeLessThan(220);
});
});

@@ -285,2 +308,55 @@

});
test('that spending all mixed P2WPKH + P2TR utxos includes inputs from both address types', () => {
const nativeSegwitUtxos = generateMockTransactions([2000, 3000]);
const taprootUtxos = generateMockTaprootTransactions([2000, 3000]);
const allTaprootUtxos = generateMockTaprootTransactions([2000, 3000, 2000, 3000]);
const mixedUtxos = [...nativeSegwitUtxos, ...taprootUtxos];
const feeRate = 4;
const mixedResult = determineUtxosForSpendAll({
utxos: mixedUtxos,
recipients: [{ address: recipientAddress, amount: createMoney(8000, 'BTC') }],
feeRate,
});
const allTaprootResult = determineUtxosForSpendAll({
utxos: allTaprootUtxos,
recipients: [{ address: recipientAddress, amount: createMoney(8000, 'BTC') }],
feeRate,
});
expect(mixedResult.inputs.length).toEqual(4);
expect(mixedResult.outputs.length).toEqual(1);
const hasSegwit = mixedResult.inputs.some(u => u.address.startsWith('tb1q'));
const hasTaproot = mixedResult.inputs.some(u => u.address.startsWith('tb1p'));
expect(hasSegwit).toBeTruthy();
expect(hasTaproot).toBeTruthy();
expect(mixedResult.size).toBeGreaterThan(280);
expect(mixedResult.size).toBeLessThan(300);
expect(mixedResult.fee.amount.isGreaterThan(allTaprootResult.fee.amount)).toBeTruthy();
});
test('that mixed P2WPKH + P2TR inputs are sorted by value descending', () => {
const nativeSegwitUtxos = generateMockTransactions([15_000, 40_000]);
const taprootUtxos = generateMockTaprootTransactions([25_000, 30_000]);
const utxos = [...nativeSegwitUtxos, ...taprootUtxos];
const result = determineUtxosForSpend({
utxos,
recipients: [
{
address: recipientAddress,
amount: createMoney(50_000, 'BTC'),
},
],
feeRate: 20,
});
result.inputs.forEach((input, i) => {
const nextInput = result.inputs[i + 1];
if (!nextInput) return;
expect(input.value >= nextInput.value).toEqual(true);
});
});
});
import { createMoney } from '@leather.io/utils';
import { recipientAddress } from '../mocks/mocks';
import { mockUtxos } from './coin-selection.mocks';
import { filterUneconomicalUtxos } from './coin-selection.utils';
import {
generateMockTaprootTransactions,
generateMockTransactions,
mockTaprootUtxos,
mockUtxos,
} from './coin-selection.mocks';
import {
countInputsByScriptType,
filterUneconomicalUtxos,
getSpendableAmount,
} from './coin-selection.utils';

@@ -65,2 +74,104 @@ describe(filterUneconomicalUtxos.name, () => {

});
describe('with taproot utxos', () => {
test('that every surviving taproot utxo increases spendable amount', () => {
const feeRate = 200;
const survivors = filterUneconomicalUtxos({
utxos: mockTaprootUtxos,
feeRate,
recipients,
});
const { spendableAmount: fullAmount } = getSpendableAmount({
utxos: mockTaprootUtxos,
feeRate,
recipients,
});
for (const utxo of survivors) {
const { spendableAmount: withoutUtxo } = getSpendableAmount({
utxos: mockTaprootUtxos.filter(u => u.txid !== utxo.txid),
feeRate,
recipients,
});
expect(fullAmount.toNumber()).toBeGreaterThan(withoutUtxo.toNumber());
}
});
test('that every filtered taproot utxo does not increase spendable amount', () => {
const feeRate = 200;
const survivors = filterUneconomicalUtxos({
utxos: mockTaprootUtxos,
feeRate,
recipients,
});
const filtered = mockTaprootUtxos.filter(u => !survivors.some(s => s.txid === u.txid));
expect(filtered.length).toBeGreaterThan(0);
const { spendableAmount: fullAmount } = getSpendableAmount({
utxos: mockTaprootUtxos,
feeRate,
recipients,
});
for (const utxo of filtered) {
const { spendableAmount: withoutUtxo } = getSpendableAmount({
utxos: mockTaprootUtxos.filter(u => u.txid !== utxo.txid),
feeRate,
recipients,
});
expect(withoutUtxo.toNumber()).toBeGreaterThanOrEqual(fullAmount.toNumber());
}
});
test('that taproot inputs are cheaper so more survive than native segwit', () => {
const feeRate = 10;
const segwitResult = filterUneconomicalUtxos({
utxos: mockUtxos,
feeRate,
recipients,
});
const taprootResult = filterUneconomicalUtxos({
utxos: mockTaprootUtxos,
feeRate,
recipients,
});
expect(taprootResult.length).toBeGreaterThan(segwitResult.length);
});
test('that taproot utxo below dust threshold is filtered even at low fee rate', () => {
const utxosWithDust = generateMockTaprootTransactions([200, 50000000]);
const result = filterUneconomicalUtxos({
utxos: utxosWithDust,
feeRate: 1,
recipients,
});
expect(result.length).toEqual(1);
expect(result[0].value).toEqual(50000000);
});
});
});
describe(countInputsByScriptType.name, () => {
test('all native segwit utxos', () => {
const result = countInputsByScriptType(mockUtxos);
expect(result).toEqual({ p2wpkh: 9, p2tr: 0 });
});
test('all taproot utxos', () => {
const result = countInputsByScriptType(mockTaprootUtxos);
expect(result).toEqual({ p2wpkh: 0, p2tr: 9 });
});
test('mixed utxos', () => {
const mixed = [
...generateMockTransactions([1000, 2000]),
...generateMockTaprootTransactions([3000, 4000, 5000]),
];
const result = countInputsByScriptType(mixed);
expect(result).toEqual({ p2wpkh: 2, p2tr: 3 });
});
});

@@ -98,2 +98,3 @@ import BigNumber from 'bignumber.js';

recipients,
isSendMax,
}: GetSpendableAmountArgs<T>) {

@@ -105,2 +106,3 @@ const balance = utxos.map(utxo => utxo.value).reduce((prevVal, curVal) => prevVal + curVal, 0);

recipients,
isSendMax,
});

@@ -107,0 +109,0 @@ const fee = Math.ceil(size.txVBytes * feeRate);

@@ -7,3 +7,3 @@ import BigNumber from 'bignumber.js';

import { CoinSelectionRecipient } from '../coin-selection/coin-selection';
import { recipientAddress } from '../mocks/mocks';
import { recipientAddress, taprootAddress } from '../mocks/mocks';
import { getBitcoinFees, getBitcoinTransactionFee } from './bitcoin-fees';

@@ -60,2 +60,70 @@

describe('getBitcoinTransactionFee with taproot', () => {
const mockTxid = '8192e8e20088c5f052fc7351b86b8f60a9454937860b281227e53e19f3e9c3f6';
const defaultRecipients = [{ address: recipientAddress, amount: createMoney(1000, 'BTC') }];
it('should return a lower fee for a taproot UTXO than native segwit', () => {
const segwitFee = getBitcoinTransactionFee({
recipients: defaultRecipients,
utxos: [{ address: recipientAddress, txid: mockTxid, value: 2000 }],
feeRate: 1,
});
const taprootFee = getBitcoinTransactionFee({
recipients: defaultRecipients,
utxos: [{ address: taprootAddress, txid: mockTxid, value: 2000 }],
feeRate: 1,
});
expect(segwitFee).not.toBeNull();
expect(taprootFee).not.toBeNull();
expect(taprootFee!.amount.toNumber()).toBeLessThan(segwitFee!.amount.toNumber());
});
it('should return a lower fee for taproot max send than native segwit', () => {
const maxSendRecipients = [{ address: recipientAddress, amount: createMoney(2000, 'BTC') }];
const segwitFee = getBitcoinTransactionFee({
isSendingMax: true,
recipients: maxSendRecipients,
utxos: [{ address: recipientAddress, txid: mockTxid, value: 2000 }],
feeRate: 2,
});
const taprootFee = getBitcoinTransactionFee({
isSendingMax: true,
recipients: maxSendRecipients,
utxos: [{ address: taprootAddress, txid: mockTxid, value: 2000 }],
feeRate: 2,
});
expect(segwitFee).not.toBeNull();
expect(taprootFee).not.toBeNull();
expect(taprootFee!.amount.toNumber()).toBeLessThan(segwitFee!.amount.toNumber());
});
it('should return a lower fee for mixed UTXOs than all native segwit', () => {
const mixedRecipients = [{ address: recipientAddress, amount: createMoney(15000, 'BTC') }];
const allSegwitFee = getBitcoinTransactionFee({
recipients: mixedRecipients,
utxos: [
{ address: recipientAddress, txid: mockTxid, value: 10000 },
{ address: recipientAddress, txid: mockTxid, value: 10000 },
],
feeRate: 1,
});
const mixedFee = getBitcoinTransactionFee({
recipients: mixedRecipients,
utxos: [
{ address: recipientAddress, txid: mockTxid, value: 10000 },
{ address: taprootAddress, txid: mockTxid, value: 10000 },
],
feeRate: 1,
});
expect(allSegwitFee).not.toBeNull();
expect(mixedFee).not.toBeNull();
expect(mixedFee!.amount.toNumber()).toBeLessThan(allSegwitFee!.amount.toNumber());
});
});
describe('getBitcoinFees', () => {

@@ -62,0 +130,0 @@ it('should return the fees for different fee rates', () => {

@@ -6,5 +6,6 @@ import { hex } from '@scure/base';

import { OwnedUtxo } from '@leather.io/models';
import { createMoney } from '@leather.io/utils';
import { createMoney, hexToNumber } from '@leather.io/utils';
import { getBtcSignerLibNetworkConfigByMode } from '../utils/bitcoin.network';
import { ecdsaPublicKeyToSchnorr } from '../utils/bitcoin.utils';
import { createBitcoinAddress } from '../validation/bitcoin-address';

@@ -18,2 +19,3 @@ import {

const payment = btc.p2wpkh(publicKey, btc.TEST_NETWORK);
const taprootPayment = btc.p2tr(ecdsaPublicKeyToSchnorr(publicKey), undefined, btc.TEST_NETWORK);

@@ -64,7 +66,7 @@ const mockResult = {

],
payerLookup() {
payerLookup(keyOrigin: string) {
return {
paymentType: 'p2wpkh',
address: createBitcoinAddress(payment.address!),
keyOrigin: "deadbeef/84'/1'/0'/0/0",
keyOrigin,
masterKeyFingerprint: 'deadbeef',

@@ -83,8 +85,18 @@ network: 'testnet',

const result = generateBitcoinUnsignedTransaction(mockArgs);
if (result) {
expect(result.inputs).toEqual(mockResult.inputs);
expect(result.fee).toEqual(mockResult.fee);
expect(result.hex).toBeDefined();
expect(result.psbt).toBeDefined();
}
expect(result.inputs).toEqual(mockResult.inputs);
expect(result.fee).toEqual(mockResult.fee);
const psbtMagic = [0x70, 0x73, 0x62, 0x74, 0xff];
expect(Array.from(result.psbt.slice(0, 5))).toEqual(psbtMagic);
expect(result.hex.length).toBeGreaterThan(0);
const psbtInput = result.tx.getInput(0);
expect(psbtInput.bip32Derivation).toHaveLength(1);
expect(psbtInput.bip32Derivation![0][0]).toEqual(publicKey);
expect(psbtInput.bip32Derivation![0][1].fingerprint).toBe(hexToNumber('deadbeef'));
expect(psbtInput.bip32Derivation![0][1].path).toEqual(btc.bip32Path("m/84'/1'/0'/0/1"));
expect(psbtInput.tapInternalKey).toBeUndefined();
expect(psbtInput.witnessUtxo!.script).toEqual(payment.script);
expect(psbtInput.witnessUtxo!.amount).toBe(BigInt(200000));
});

@@ -94,7 +106,12 @@

const result = generateBitcoinUnsignedTransaction(mockArgs);
const fee = BigInt(result.fee.amount.toNumber());
const inputTotal = BigInt(200000);
if (result) {
expect(result.tx.outputsLength).toBe(2);
expect(result.tx.getOutput(1).script).toBeDefined();
}
expect(result.tx.outputsLength).toBe(2);
expect(result.tx.getOutput(0).amount).toBe(BigInt(150000));
expect(result.tx.getOutput(1).script).toBeDefined();
const recipientAmount = result.tx.getOutput(0).amount!;
const changeAmount = result.tx.getOutput(1).amount!;
expect(recipientAmount + changeAmount + fee).toBe(inputTotal);
});

@@ -112,2 +129,323 @@

});
it('should not produce change output when change would be below dust threshold', () => {
const dustArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
...mockArgs,
utxos: [
{
address: payment.address!,
path: "m/84'/1'/0'/0/0",
keyOrigin: "deadbeef/84'/1'/0'/0/0",
txid: '8192e8e20088c5f052fc7351b86b8f60a9454937860b281227e53e19f3e9c3f6',
vout: 0,
value: 150400,
},
],
recipients: [
{
address: 'tb1qsqncyhhqdtfn07t3dhupx7smv5gk83ds6k0gfa',
amount: createMoney(150000, 'BTC'),
},
],
};
const result = generateBitcoinUnsignedTransaction(dustArgs);
const fee = BigInt(result.fee.amount.toNumber());
expect(result.tx.outputsLength).toBe(1);
expect(result.tx.getOutput(0).amount).toBe(BigInt(150000));
// Change (150400 - 150000 - fee) is below dust, so no change output.
// The sub-dust remainder becomes an implicit miner tip.
const remainder = BigInt(150400) - BigInt(150000) - fee;
expect(remainder).toBeGreaterThan(0n);
expect(remainder).toBeLessThan(294n);
});
it('should build correct transaction with isSendingMax for segwit inputs', () => {
const sendMaxArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
...mockArgs,
isSendingMax: true,
};
const result = generateBitcoinUnsignedTransaction(sendMaxArgs);
expect(result.tx.outputsLength).toBe(1);
expect(result.tx.getOutput(0).amount).toBe(BigInt(150000));
expect(result.fee.amount.isGreaterThan(0)).toBe(true);
expect(result.inputs.length).toBeGreaterThanOrEqual(1);
const psbtInput = result.tx.getInput(0);
expect(psbtInput.bip32Derivation).toHaveLength(1);
expect(psbtInput.tapInternalKey).toBeUndefined();
});
describe('taproot inputs', () => {
const taprootMockArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
feeRate: 1,
isSendingMax: false,
network: getBtcSignerLibNetworkConfigByMode('testnet'),
changeAddress: createBitcoinAddress(payment.address!),
recipients: [
{
address: 'tb1qsqncyhhqdtfn07t3dhupx7smv5gk83ds6k0gfa',
amount: createMoney(150000, 'BTC'),
},
],
utxos: [
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/0",
keyOrigin: "deadbeef/86'/1'/0'/0/0",
txid: '8192e8e20088c5f052fc7351b86b8f60a9454937860b281227e53e19f3e9c3f6',
vout: 0,
value: 100000,
},
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/1",
keyOrigin: "deadbeef/86'/1'/0'/0/1",
txid: 'c715ea469c8d794f6dd7e0043148631f69d411c428ef0ab2b04e4528ffe8319f',
vout: 1,
value: 200000,
},
],
payerLookup(keyOrigin: string) {
return {
paymentType: 'p2tr' as const,
address: createBitcoinAddress(taprootPayment.address!),
keyOrigin,
masterKeyFingerprint: 'deadbeef',
network: 'testnet',
payment: taprootPayment,
publicKey,
};
},
};
it('should set tapInternalKey and tapBip32Derivation for p2tr inputs', () => {
const result = generateBitcoinUnsignedTransaction(taprootMockArgs);
expect(result.hex).toBeDefined();
expect(result.psbt).toBeDefined();
expect(result.inputs.length).toBe(1);
const psbtInput = result.tx.getInput(0);
expect(hex.encode(psbtInput.txid!)).toBe(
'c715ea469c8d794f6dd7e0043148631f69d411c428ef0ab2b04e4528ffe8319f'
);
expect(psbtInput.index).toBe(1);
expect(psbtInput.tapInternalKey).toEqual(taprootPayment.tapInternalKey);
expect(psbtInput.tapBip32Derivation).toHaveLength(1);
expect(psbtInput.tapBip32Derivation![0][0]).toEqual(ecdsaPublicKeyToSchnorr(publicKey));
expect(psbtInput.tapBip32Derivation![0][1].hashes).toEqual([]);
expect(psbtInput.tapBip32Derivation![0][1].der.fingerprint).toBe(hexToNumber('deadbeef'));
expect(psbtInput.tapBip32Derivation![0][1].der.path).toEqual(
btc.bip32Path("m/86'/1'/0'/0/1")
);
expect(psbtInput.bip32Derivation).toBeUndefined();
expect(psbtInput.witnessUtxo!.script).toEqual(taprootPayment.script);
expect(psbtInput.witnessUtxo!.amount).toBe(BigInt(200000));
expect(result.tx.outputsLength).toBe(2);
expect(result.tx.getOutput(0).amount).toBe(BigInt(150000));
});
it('should handle mixed p2wpkh and p2tr inputs', () => {
const mixedArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
feeRate: 1,
isSendingMax: false,
network: getBtcSignerLibNetworkConfigByMode('testnet'),
changeAddress: createBitcoinAddress(payment.address!),
recipients: [
{
address: 'tb1qsqncyhhqdtfn07t3dhupx7smv5gk83ds6k0gfa',
amount: createMoney(350000, 'BTC'),
},
],
utxos: [
{
address: payment.address!,
path: "m/84'/1'/0'/0/0",
keyOrigin: "deadbeef/84'/1'/0'/0/0",
txid: '8192e8e20088c5f052fc7351b86b8f60a9454937860b281227e53e19f3e9c3f6',
vout: 0,
value: 300000,
},
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/0",
keyOrigin: "deadbeef/86'/1'/0'/0/0",
txid: 'c715ea469c8d794f6dd7e0043148631f69d411c428ef0ab2b04e4528ffe8319f',
vout: 1,
value: 200000,
},
],
payerLookup(keyOrigin: string) {
if (keyOrigin.includes("86'")) {
return {
paymentType: 'p2tr' as const,
address: createBitcoinAddress(taprootPayment.address!),
keyOrigin,
masterKeyFingerprint: 'deadbeef',
network: 'testnet',
payment: taprootPayment,
publicKey,
};
}
return {
paymentType: 'p2wpkh' as const,
address: createBitcoinAddress(payment.address!),
keyOrigin,
masterKeyFingerprint: 'deadbeef',
network: 'testnet',
payment: { script: payment.script, type: 'p2wpkh' },
publicKey,
};
},
};
const result = generateBitcoinUnsignedTransaction(mixedArgs);
expect(result.inputs.length).toBe(2);
expect(result.fee.amount.isGreaterThan(0)).toBe(true);
const segwitInput = result.tx.getInput(0);
expect(segwitInput.index).toBe(0);
expect(segwitInput.bip32Derivation).toBeDefined();
expect(segwitInput.tapInternalKey).toBeUndefined();
expect(segwitInput.witnessUtxo!.script).toEqual(payment.script);
expect(segwitInput.witnessUtxo!.amount).toBe(BigInt(300000));
const taprootInput = result.tx.getInput(1);
expect(taprootInput.index).toBe(1);
expect(taprootInput.tapBip32Derivation).toBeDefined();
expect(taprootInput.tapInternalKey).toEqual(taprootPayment.tapInternalKey);
expect(taprootInput.bip32Derivation).toBeUndefined();
expect(taprootInput.witnessUtxo!.script).toEqual(taprootPayment.script);
expect(taprootInput.witnessUtxo!.amount).toBe(BigInt(200000));
});
it('should use native segwit change address even with all taproot inputs', () => {
const result = generateBitcoinUnsignedTransaction(taprootMockArgs);
expect(result.tx.outputsLength).toBe(2);
const changeScript = result.tx.getOutput(1).script!;
expect(changeScript[0]).toBe(0x00);
expect(changeScript[1]).toBe(0x14);
expect(changeScript.length).toBe(22);
});
it('should build psbt with isSendingMax for taproot inputs', () => {
const sendMaxArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
feeRate: 1,
isSendingMax: true,
network: getBtcSignerLibNetworkConfigByMode('testnet'),
changeAddress: createBitcoinAddress(payment.address!),
recipients: [
{
address: 'tb1qsqncyhhqdtfn07t3dhupx7smv5gk83ds6k0gfa',
amount: createMoney(1, 'BTC'),
},
],
utxos: [
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/0",
keyOrigin: "deadbeef/86'/1'/0'/0/0",
txid: 'c715ea469c8d794f6dd7e0043148631f69d411c428ef0ab2b04e4528ffe8319f',
vout: 0,
value: 200000,
},
],
payerLookup(keyOrigin: string) {
return {
paymentType: 'p2tr' as const,
address: createBitcoinAddress(taprootPayment.address!),
keyOrigin,
masterKeyFingerprint: 'deadbeef',
network: 'testnet',
payment: taprootPayment,
publicKey,
};
},
};
const result = generateBitcoinUnsignedTransaction(sendMaxArgs);
expect(result.inputs.length).toBe(1);
expect(result.tx.outputsLength).toBe(1);
expect(result.tx.getOutput(0).amount).toBe(1n);
expect(result.fee.amount.isGreaterThan(0)).toBe(true);
const psbtInput = result.tx.getInput(0);
expect(psbtInput.tapInternalKey).toEqual(taprootPayment.tapInternalKey);
expect(psbtInput.tapBip32Derivation).toHaveLength(1);
});
it('should skip inputs when payerLookup returns undefined', () => {
const undefinedPayerArgs: GenerateBitcoinUnsignedTransactionArgs<OwnedUtxo> = {
feeRate: 1,
isSendingMax: false,
network: getBtcSignerLibNetworkConfigByMode('testnet'),
changeAddress: createBitcoinAddress(payment.address!),
recipients: [
{
address: 'tb1qsqncyhhqdtfn07t3dhupx7smv5gk83ds6k0gfa',
amount: createMoney(250000, 'BTC'),
},
],
utxos: [
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/0",
keyOrigin: "deadbeef/86'/1'/0'/0/0",
txid: '8192e8e20088c5f052fc7351b86b8f60a9454937860b281227e53e19f3e9c3f6',
vout: 0,
value: 200000,
},
{
address: taprootPayment.address!,
path: "m/86'/1'/0'/0/1",
keyOrigin: "deadbeef/86'/1'/0'/0/1",
txid: 'c715ea469c8d794f6dd7e0043148631f69d411c428ef0ab2b04e4528ffe8319f',
vout: 1,
value: 100000,
},
],
payerLookup(keyOrigin: string) {
if (keyOrigin === "deadbeef/86'/1'/0'/0/1") return undefined;
return {
paymentType: 'p2tr' as const,
address: createBitcoinAddress(taprootPayment.address!),
keyOrigin,
masterKeyFingerprint: 'deadbeef',
network: 'testnet',
payment: taprootPayment,
publicKey,
};
},
};
const result = generateBitcoinUnsignedTransaction(undefinedPayerArgs);
expect(result.inputs.length).toBe(2);
expect(result.tx.inputsLength).toBe(1);
expect(result.tx.getInput(0).tapInternalKey).toEqual(taprootPayment.tapInternalKey);
// Known limitation: coin selection computed fee for 2 inputs but only 1
// was added to the tx, producing an unbroadcastable transaction where
// total output value exceeds the single input's value
const singleInputValue = BigInt(200000);
let totalOutputValue = 0n;
for (let i = 0; i < result.tx.outputsLength; i++) {
totalOutputValue += result.tx.getOutput(i).amount!;
}
expect(totalOutputValue).toBeGreaterThan(singleInputValue);
});
});
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display