@leather.io/bitcoin
Advanced tools
| > @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 @@ | ||
| [34mℹ[39m Build start | ||
| [34mℹ[39m [2mdist/[22m[1mindex.js[22m [2m 58.22 kB[22m [2m│ gzip: 13.64 kB[22m | ||
| [34mℹ[39m [2mdist/[22mindex.js.map [2m117.82 kB[22m [2m│ gzip: 27.59 kB[22m | ||
| [34mℹ[39m [2mdist/[22mindex.d.ts.map [2m 11.64 kB[22m [2m│ gzip: 4.75 kB[22m | ||
| [34mℹ[39m [2mdist/[22m[32m[1mindex.d.ts[22m[39m [2m 33.53 kB[22m [2m│ gzip: 6.95 kB[22m | ||
| [34mℹ[39m 4 files, total: 221.21 kB | ||
| [32m✔[39m Build complete in [32m4423ms[39m | ||
| [34mℹ[39m [2mdist/[22m[1mindex.js[22m [2m 58.24 kB[22m [2m│ gzip: 13.65 kB[22m | ||
| [34mℹ[39m [2mdist/[22mindex.js.map [2m117.86 kB[22m [2m│ gzip: 27.60 kB[22m | ||
| [34mℹ[39m [2mdist/[22mindex.d.ts.map [2m 11.65 kB[22m [2m│ gzip: 4.75 kB[22m | ||
| [34mℹ[39m [2mdist/[22m[32m[1mindex.d.ts[22m[39m [2m 33.54 kB[22m [2m│ gzip: 6.96 kB[22m | ||
| [34mℹ[39m 4 files, total: 221.29 kB | ||
| [32m✔[39m Build complete in [32m4248ms[39m |
+4
-3
@@ -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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"} |
+3
-2
@@ -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); |
+7
-7
@@ -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
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
490136
5.7%7411
9.34%4
33.33%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated
Updated