diff --git a/class/hd-segwit-bech32-transaction.js b/class/hd-segwit-bech32-transaction.js index c7402c665..af11fe6c4 100644 --- a/class/hd-segwit-bech32-transaction.js +++ b/class/hd-segwit-bech32-transaction.js @@ -180,7 +180,7 @@ export class HDSegwitBech32Transaction { } const fee = wentIn - wasSpent; - let feeRate = Math.floor(fee / (this._txhex.length / 2)); + let feeRate = Math.floor(fee / this._txDecoded.virtualSize()); if (feeRate === 0) feeRate = 1; // lets take a look at change @@ -356,7 +356,7 @@ export class HDSegwitBech32Transaction { myAddress, HDSegwitBech32Wallet.defaultRBFSequence, ); - const combinedFeeRate = (oldFee + fee) / (this._txhex.length / 2 + tx.toHex().length / 2); // avg + const combinedFeeRate = (oldFee + fee) / (this._txDecoded.virtualSize() + tx.virtualSize()); // avg if (Math.round(combinedFeeRate) < newFeerate) { add *= 2; if (!add) add = 2; diff --git a/class/wallets/abstract-hd-electrum-wallet.js b/class/wallets/abstract-hd-electrum-wallet.js index 5a71e0490..55698c40d 100644 --- a/class/wallets/abstract-hd-electrum-wallet.js +++ b/class/wallets/abstract-hd-electrum-wallet.js @@ -853,6 +853,16 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet { */ createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false, masterFingerprint) { if (targets.length === 0) throw new Error('No destination provided'); + // compensating for coinselect inability to deal with segwit inputs, and overriding script length for proper vbytes calculation + for (const u of utxos) { + // this is a hacky way to distinguish native/wrapped segwit, but its good enough for our case since we have only + // those 2 wallet types + if (this._getExternalAddressByIndex(0).startsWith('bc1')) { + u.script = { length: 27 }; + } else if (this._getExternalAddressByIndex(0).startsWith('3')) { + u.script = { length: 50 }; + } + } const { inputs, outputs, fee } = this.coinselect(utxos, targets, feeRate, changeAddress); sequence = sequence || AbstractHDElectrumWallet.defaultRBFSequence; diff --git a/class/wallets/segwit-bech32-wallet.js b/class/wallets/segwit-bech32-wallet.js index c77c9ad21..703f00ef7 100644 --- a/class/wallets/segwit-bech32-wallet.js +++ b/class/wallets/segwit-bech32-wallet.js @@ -58,6 +58,10 @@ export class SegwitBech32Wallet extends LegacyWallet { createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false, masterFingerprint) { if (targets.length === 0) throw new Error('No destination provided'); + // compensating for coinselect inability to deal with segwit inputs, and overriding script length for proper vbytes calculation + for (const u of utxos) { + u.script = { length: 27 }; + } const { inputs, outputs, fee } = this.coinselect(utxos, targets, feeRate, changeAddress); sequence = sequence || 0xffffffff; // disable RBF by default const psbt = new bitcoin.Psbt(); diff --git a/class/wallets/segwit-p2sh-wallet.js b/class/wallets/segwit-p2sh-wallet.js index b58e88d51..6875416c7 100644 --- a/class/wallets/segwit-p2sh-wallet.js +++ b/class/wallets/segwit-p2sh-wallet.js @@ -80,6 +80,10 @@ export class SegwitP2SHWallet extends LegacyWallet { */ createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false, masterFingerprint) { if (targets.length === 0) throw new Error('No destination provided'); + // compensating for coinselect inability to deal with segwit inputs, and overriding script length for proper vbytes calculation + for (const u of utxos) { + u.script = { length: 50 }; + } const { inputs, outputs, fee } = this.coinselect(utxos, targets, feeRate, changeAddress); sequence = sequence || 0xffffffff; // disable RBF by default const psbt = new bitcoin.Psbt(); diff --git a/screen/selftest.js b/screen/selftest.js index 88825872b..a71fa0291 100644 --- a/screen/selftest.js +++ b/screen/selftest.js @@ -130,7 +130,7 @@ export default class Selftest extends Component { const tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); assertStrictEqual( txNew.tx.toHex(), - '020000000001010c86eb9013616e38b4752e56e5683e864cb34fcd7fe790bdc006b60c08446ba50000000017160014139dc70d73097f9d775f8a3280ba3e3435515641ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac6e3303000000000017a914749118baa93fb4b88c28909c8bf0a8202a0484f4870247304402205f0bcb0d9968b3c410e2a3699369bf4149bb56ade18b63356b45285a34d64600022043ac1271f3900ea1000a66b9a9d9ceb3e6e4a4ef45c4da0f55b691ad4b64fcb1012103a5de146762f84055db3202c1316cd9008f16047f4f408c1482fdb108217eda0800000000', + '020000000001010c86eb9013616e38b4752e56e5683e864cb34fcd7fe790bdc006b60c08446ba50000000017160014139dc70d73097f9d775f8a3280ba3e3435515641ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88aca73303000000000017a914749118baa93fb4b88c28909c8bf0a8202a0484f4870248304502210080545d30e3d30dff272ab11c91fd6150170b603239b48c3d56a3fa66bf240085022003762404e1b45975adc89f61ec1569fa19d6d4a8d405e060897754c489ebeade012103a5de146762f84055db3202c1316cd9008f16047f4f408c1482fdb108217eda0800000000', ); assertStrictEqual(tx.ins.length, 1); assertStrictEqual(tx.outs.length, 2); diff --git a/screen/send/create.js b/screen/send/create.js index 27d864844..a7138f6b2 100644 --- a/screen/send/create.js +++ b/screen/send/create.js @@ -15,11 +15,13 @@ import loc from '../../loc'; import { DynamicQRCode } from '../../components/DynamicQRCode'; import { isDesktop } from '../../blue_modules/environment'; import { useNavigation, useRoute, useTheme } from '@react-navigation/native'; +const bitcoin = require('bitcoinjs-lib'); const currency = require('../../blue_modules/currency'); const SendCreate = () => { const { fee, recipients, memo = '', satoshiPerByte, psbt, showAnimatedQr, tx } = useRoute().params; - const size = Math.round(tx.length / 2); + const transaction = bitcoin.Transaction.fromHex(tx); + const size = transaction.virtualSize(); const { colors } = useTheme(); const { setOptions } = useNavigation(); diff --git a/screen/send/psbtMultisig.js b/screen/send/psbtMultisig.js index 98b5dcaf2..53f2e3ff0 100644 --- a/screen/send/psbtMultisig.js +++ b/screen/send/psbtMultisig.js @@ -180,7 +180,7 @@ const PsbtMultisig = () => { try { const tx = psbt.extractTransaction().toHex(); - const satoshiPerByte = Math.round(getFee() / (tx.length / 2)); + const satoshiPerByte = Math.round(getFee() / psbt.extractTransaction().virtualSize()); navigate('Confirm', { fee: new BigNumber(getFee()).dividedBy(100000000).toNumber(), memo, diff --git a/tests/e2e/bluewallet.spec.js b/tests/e2e/bluewallet.spec.js index fe81094f8..db7a04f17 100644 --- a/tests/e2e/bluewallet.spec.js +++ b/tests/e2e/bluewallet.spec.js @@ -527,7 +527,7 @@ describe('BlueWallet UI Tests', () => { await yo('TransactionValue'); expect(element(by.id('TransactionValue'))).toHaveText('0.0001'); const transactionFee = await extractTextFromElementById('TransactionFee'); - assert.ok(transactionFee.startsWith('Fee: 0.00000452 BTC'), 'Unexpected tx fee: ' + transactionFee); + assert.ok(transactionFee.startsWith('Fee: 0.00000292 BTC'), 'Unexpected tx fee: ' + transactionFee); await element(by.id('TransactionDetailsButton')).tap(); let txhex = await extractTextFromElementById('TxhexInput'); @@ -541,7 +541,8 @@ describe('BlueWallet UI Tests', () => { // checking fee rate: const totalIns = 100000; // we hardcode it since we know it in advance const totalOuts = transaction.outs.map(el => el.value).reduce((a, b) => a + b, 0); - assert.strictEqual(Math.round((totalIns - totalOuts) / (txhex.length / 2)), feeRate); + const tx = bitcoin.Transaction.fromHex(txhex); + assert.strictEqual(Math.round((totalIns - totalOuts) / tx.virtualSize()), feeRate); assert.strictEqual(transactionFee.split(' ')[1] * 100000000, totalIns - totalOuts); if (device.getPlatform() === 'ios') { @@ -1109,7 +1110,7 @@ describe('BlueWallet UI Tests', () => { const psbt1 = bitcoin.Psbt.fromHex(psbthex1); assert.strictEqual(psbt1.txOutputs.length, 1); assert.strictEqual(psbt1.txOutputs[0].address, 'bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); - assert.strictEqual(psbt1.txOutputs[0].value, 99808); + assert.strictEqual(psbt1.txOutputs[0].value, 99888); assert.strictEqual(psbt1.data.inputs.length, 1); assert.strictEqual(psbt1.data.inputs[0].witnessUtxo.value, 100000); @@ -1136,7 +1137,7 @@ describe('BlueWallet UI Tests', () => { const psbt2 = bitcoin.Psbt.fromHex(psbthex2); assert.strictEqual(psbt2.txOutputs.length, 1); assert.strictEqual(psbt2.txOutputs[0].address, 'bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); - assert.strictEqual(psbt2.txOutputs[0].value, 5334); + assert.strictEqual(psbt2.txOutputs[0].value, 5414); assert.strictEqual(psbt2.data.inputs.length, 1); assert.strictEqual(psbt2.data.inputs[0].witnessUtxo.value, 5526); diff --git a/tests/integration/hd-segwit-bech32-transaction.test.js b/tests/integration/hd-segwit-bech32-transaction.test.js index 67c7f0d26..1852b3bb0 100644 --- a/tests/integration/hd-segwit-bech32-transaction.test.js +++ b/tests/integration/hd-segwit-bech32-transaction.test.js @@ -78,7 +78,7 @@ describe('HDSegwitBech32Transaction', () => { const { fee, feeRate, targets, changeAmount, utxos } = await tt.getInfo(); assert.strictEqual(fee, 4464); assert.strictEqual(changeAmount, 103686); - assert.strictEqual(feeRate, 12); + assert.strictEqual(feeRate, 21); assert.strictEqual(targets.length, 1); assert.strictEqual(targets[0].value, 200000); assert.strictEqual(targets[0].address, '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); @@ -113,7 +113,7 @@ describe('HDSegwitBech32Transaction', () => { assert.strictEqual(await tt.canCancelTx(), true); - const { tx } = await tt.createRBFcancelTx(15); + const { tx } = await tt.createRBFcancelTx(25); const createdTx = bitcoin.Transaction.fromHex(tx.toHex()); assert.strictEqual(createdTx.ins.length, 2); @@ -121,8 +121,8 @@ describe('HDSegwitBech32Transaction', () => { const addr = SegwitBech32Wallet.scriptPubKeyToAddress(createdTx.outs[0].script); assert.ok(hd.weOwnAddress(addr)); - const actualFeerate = (108150 + 200000 - createdTx.outs[0].value) / (tx.toHex().length / 2); - assert.strictEqual(Math.round(actualFeerate), 15); + const actualFeerate = (108150 + 200000 - createdTx.outs[0].value) / tx.virtualSize(); + assert.strictEqual(Math.round(actualFeerate), 25); const tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); assert.strictEqual(await tt2.canCancelTx(), false); // newly created cancel tx is not cancellable anymore @@ -141,7 +141,7 @@ describe('HDSegwitBech32Transaction', () => { assert.strictEqual(await tt.canCancelTx(), true); assert.strictEqual(await tt.canBumpTx(), true); - const { tx } = await tt.createRBFbumpFee(17); + const { tx } = await tt.createRBFbumpFee(27); const createdTx = bitcoin.Transaction.fromHex(tx.toHex()); assert.strictEqual(createdTx.ins.length, 2); @@ -152,8 +152,8 @@ describe('HDSegwitBech32Transaction', () => { const addr1 = SegwitBech32Wallet.scriptPubKeyToAddress(createdTx.outs[1].script); assert.ok(hd.weOwnAddress(addr1)); - const actualFeerate = (108150 + 200000 - (createdTx.outs[0].value + createdTx.outs[1].value)) / (tx.toHex().length / 2); - assert.strictEqual(Math.round(actualFeerate), 17); + const actualFeerate = (108150 + 200000 - (createdTx.outs[0].value + createdTx.outs[1].value)) / tx.virtualSize(); + assert.strictEqual(Math.round(actualFeerate), 28); const tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); assert.strictEqual(await tt2.canCancelTx(), true); // new tx is still cancellable since we only bumped fees @@ -184,7 +184,7 @@ describe('HDSegwitBech32Transaction', () => { ); const { tx, fee } = await tt.createCPFPbumpFee(20); - const avgFeeRate = (oldFee + fee) / (tt._txhex.length / 2 + tx.toHex().length / 2); + const avgFeeRate = (oldFee + fee) / (tt._txDecoded.virtualSize() + tx.virtualSize()); assert.ok(Math.round(avgFeeRate) >= 20); }); }); diff --git a/tests/integration/hd-segwit-bech32-wallet.test.js b/tests/integration/hd-segwit-bech32-wallet.test.js index 083cdfe27..ef534062b 100644 --- a/tests/integration/hd-segwit-bech32-wallet.test.js +++ b/tests/integration/hd-segwit-bech32-wallet.test.js @@ -230,7 +230,7 @@ describe('Bech32 Segwit HD (BIP84)', () => { changeAddress, ); - assert.strictEqual(Math.round(fee / tx.byteLength()), 13); + assert.strictEqual(Math.round(fee / tx.virtualSize()), 13); let totalInput = 0; for (const inp of inputs) { diff --git a/tests/integration/hd-segwit-p2sh-wallet.test.js b/tests/integration/hd-segwit-p2sh-wallet.test.js index 978f948bf..6a7a1eb73 100644 --- a/tests/integration/hd-segwit-p2sh-wallet.test.js +++ b/tests/integration/hd-segwit-p2sh-wallet.test.js @@ -75,12 +75,12 @@ it('HD (BIP49) can create TX', async () => { let tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); assert.strictEqual( txNew.tx.toHex(), - '0200000000010187c9acd9d5714845343b18abaa26cb83299be2487c22da9c0e270f241b4d9cfe0000000017160014a239b6a0cbc7aadc2e77643de36306a6167fad150000008002f40100000000000017a914a3a65daca3064280ae072b9d6773c027b30abace87ba6200000000000017a9140acff2c37ed45110baece4bb9d4dcc0c6309dbbd8702483045022100a14eb345f26933b29ba2a68075994ecf10f16286611c1d34ccd5850d977c25620220050e80c62ba64d99101253d94f756791f881bdb92100885fbe5ea3e29964573001210202ac3bd159e54dc31e65842ad5f9a10b4eb024e83864a319b27de65ee08b2a3900000000', + '0200000000010187c9acd9d5714845343b18abaa26cb83299be2487c22da9c0e270f241b4d9cfe0000000017160014a239b6a0cbc7aadc2e77643de36306a6167fad150000008002f40100000000000017a914a3a65daca3064280ae072b9d6773c027b30abace87f36200000000000017a9140acff2c37ed45110baece4bb9d4dcc0c6309dbbd8702483045022100fdddfc8f2f85181b0eb95d9f2ebd506b611318b85419889f9b7e4648cb9912e002206c963079673dfcfeea53120592d995dfab5f0e12f4c0054cace0cda90c481d2001210202ac3bd159e54dc31e65842ad5f9a10b4eb024e83864a319b27de65ee08b2a3900000000', ); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 2); assert.strictEqual(tx.outs[0].value, 500); - assert.strictEqual(tx.outs[1].value, 25274); + assert.strictEqual(tx.outs[1].value, 25331); let toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script); const changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script); assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress); @@ -94,6 +94,9 @@ it('HD (BIP49) can create TX', async () => { 5, hd._getInternalAddressByIndex(hd.next_free_change_address_index), ); + const satPerVbyte = txNew.fee / tx.virtualSize(); + + assert.strictEqual(Math.round(satPerVbyte), 6); // so_close.jpg tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 1); diff --git a/tests/unit/legacy-wallet.test.js b/tests/unit/legacy-wallet.test.js index 0ebd2578c..6871948c3 100644 --- a/tests/unit/legacy-wallet.test.js +++ b/tests/unit/legacy-wallet.test.js @@ -23,6 +23,8 @@ describe('Legacy wallet', () => { let txNew = l.createTransaction(utxos, [{ value: 90000, address: '1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB' }], 1, l.getAddress()); let tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); + const satPerVbyte = txNew.fee / tx.virtualSize(); + assert.strictEqual(satPerVbyte, 1); assert.strictEqual( txNew.tx.toHex(), '0200000001c4ce4282c157a7f1e4524d153d3a251669f10673ad24e49f6d2994a033e944cc000000006b48304502210091e58bd2021f2eeea8d39d7f7b053c9ccc52a747b60f1c3584ba33285e2d150602205b2d35a2536cbe157015e8c54a26f5fc350cc7c72b5ca80b9e548917993f652201210337c09b3cb889801638078fd4e6998218b28c92d338ea2602720a88847aedceb3ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac2e260000000000001976a91426e01119d265aa980390c49eece923976c218f1588ac00000000', diff --git a/tests/unit/payjoin-transaction.test.js b/tests/unit/payjoin-transaction.test.js index e4e3b1c72..6b37971c3 100644 --- a/tests/unit/payjoin-transaction.test.js +++ b/tests/unit/payjoin-transaction.test.js @@ -76,12 +76,17 @@ describe('PayjoinTransaction', () => { const w = new HDSegwitBech32Wallet(); w.setSecret(process.env.MNEMONICS_COLDCARD); // bitcoin:bc1qy0ydthpa35m37pvwl5tu76j0srcmcwtmaur3aw?amount=0.0001&pj=https://btc.donate.kukks.org/BTC/pj - const { tx: txOrigin, psbt: psbtOrigin } = w.createTransaction( - utxos, - [{ address: 'bc1qy0ydthpa35m37pvwl5tu76j0srcmcwtmaur3aw', value: 10000 }], - 7, - w._getInternalAddressByIndex(0), + + // because `createTransaction()` has now readjusted coinselect algo, actual created psbt differs, and wont work + // with hardcoded psbt from btcpayserver. so instead of redoing whole process to get fresh psbt, we hardcode + // created cransaction: + const psbtOrigin = bitcoin.Psbt.fromBase64( + 'cHNidP8BAHECAAAAARQ28UTNRyxErPb95WFKR0oaiSTEl4x0MUOLwXkkmIyOAAAAAAAAAACAAhAnAAAAAAAAFgAUI8jV3D2NNx8Fjv0Xz2pPgPG8OXtiWQEAAAAAABYAFF8XCHdkg2yGn81L+plhb9iWamgBAAAAAAABAR+ghgEAAAAAABYAFFS9qGo3Nrma3Tb912mSqTHUqwnKAQhsAkgwRQIhAKsmnGPh1vqoW5zlhjJUUs9rcdG9xMwtlf4Hoij7ul+XAiANlyXTuYshsmTIz6/734ChqQzAGp/HreRulypr0wevswEhAolzW1ViXE+a+hqxD825RNPNdq2Gd7dhUeJ4atRH12vaAAAiAgL1DWeV+AfIP5RRB5zHv5vuXsIt8+rF9rrsji3FhQlhzBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA', ); + const txOrigin = bitcoin.Transaction.fromHex( + '020000000001011436f144cd472c44acf6fde5614a474a1a8924c4978c7431438bc17924988c8e00000000000000008002102700000000000016001423c8d5dc3d8d371f058efd17cf6a4f80f1bc397b62590100000000001600145f17087764836c869fcd4bfa99616fd8966a680102483045022100ab269c63e1d6faa85b9ce586325452cf6b71d1bdc4cc2d95fe07a228fbba5f9702200d9725d3b98b21b264c8cfaffbdf80a1a90cc01a9fc7ade46e972a6bd307afb301210289735b55625c4f9afa1ab10fcdb944d3cd76ad8677b76151e2786ad447d76bda00000000', + ); + assert.strictEqual(txOrigin.ins.length, 1); assert.strictEqual(txOrigin.outs.length, 2); diff --git a/tests/unit/segwit-bech32-wallet.test.js b/tests/unit/segwit-bech32-wallet.test.js index 6dca7846c..895bcb9d0 100644 --- a/tests/unit/segwit-bech32-wallet.test.js +++ b/tests/unit/segwit-bech32-wallet.test.js @@ -20,9 +20,11 @@ describe('Segwit P2SH wallet', () => { let txNew = wallet.createTransaction(utxos, [{ value: 90000, address: '1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB' }], 1, wallet.getAddress()); let tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); + const satPerVbyte = txNew.fee / tx.virtualSize(); + assert.strictEqual(Math.round(satPerVbyte), 1); assert.strictEqual( txNew.tx.toHex(), - '02000000000101ebff950f972e51ea4791f635fef777d5ed0162bacf74f03f5819b976c08bd1570000000000ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac2e2600000000000016001488fefdd8967886b32760995c1c36289f44f791850247304402206272d7ba35177bbcccbf52a49a9466e7692252ebbb36753c50ea99c6de8ddb6402204975c76d894b6811b86bab9f2544e7ade7d4f4f7e6a543a60d0af1b854c493a601210314cf2bf53f221e58c5adc1dd95adba9239b248f39b09eb2c550aadc1926fe7aa00000000', + '02000000000101ebff950f972e51ea4791f635fef777d5ed0162bacf74f03f5819b976c08bd1570000000000ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac7e2600000000000016001488fefdd8967886b32760995c1c36289f44f7918502483045022100fc0ba843588a5156878cd9d6e3c6b0cbce6acd5c8cf04dc09dcb8d0f23da07f002207a2d5bed25936b1eeda7e836a4734f5a0e66b4996aff64b3b3759ae81805722301210314cf2bf53f221e58c5adc1dd95adba9239b248f39b09eb2c550aadc1926fe7aa00000000', ); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 2); diff --git a/tests/unit/segwit-p2sh-wallet.test.js b/tests/unit/segwit-p2sh-wallet.test.js index c2c9cbf40..8355cb47c 100644 --- a/tests/unit/segwit-p2sh-wallet.test.js +++ b/tests/unit/segwit-p2sh-wallet.test.js @@ -21,9 +21,11 @@ describe('Segwit P2SH wallet', () => { let txNew = wallet.createTransaction(utxos, [{ value: 90000, address: '1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB' }], 1, wallet.getAddress()); let tx = bitcoin.Transaction.fromHex(txNew.tx.toHex()); + const satPerVbyte = txNew.fee / tx.virtualSize(); + assert.strictEqual(Math.round(satPerVbyte), 1); assert.strictEqual( txNew.tx.toHex(), - '020000000001010c86eb9013616e38b4752e56e5683e864cb34fcd7fe790bdc006b60c08446ba50000000017160014139dc70d73097f9d775f8a3280ba3e3435515641ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac6e3303000000000017a914749118baa93fb4b88c28909c8bf0a8202a0484f4870247304402205f0bcb0d9968b3c410e2a3699369bf4149bb56ade18b63356b45285a34d64600022043ac1271f3900ea1000a66b9a9d9ceb3e6e4a4ef45c4da0f55b691ad4b64fcb1012103a5de146762f84055db3202c1316cd9008f16047f4f408c1482fdb108217eda0800000000', + '020000000001010c86eb9013616e38b4752e56e5683e864cb34fcd7fe790bdc006b60c08446ba50000000017160014139dc70d73097f9d775f8a3280ba3e3435515641ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88aca73303000000000017a914749118baa93fb4b88c28909c8bf0a8202a0484f4870248304502210080545d30e3d30dff272ab11c91fd6150170b603239b48c3d56a3fa66bf240085022003762404e1b45975adc89f61ec1569fa19d6d4a8d405e060897754c489ebeade012103a5de146762f84055db3202c1316cd9008f16047f4f408c1482fdb108217eda0800000000', ); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 2); diff --git a/tests/unit/watch-only-wallet.test.js b/tests/unit/watch-only-wallet.test.js index 00aad36dc..f325e2b7e 100644 --- a/tests/unit/watch-only-wallet.test.js +++ b/tests/unit/watch-only-wallet.test.js @@ -110,7 +110,7 @@ describe('Watch only wallet', () => { assert.strictEqual( psbt.toBase64(), - 'cHNidP8BAFMCAAAAAfTUAYKfU/lPbuIV0AsoBIURL2tAz7iaObvEMcXQBW94AAAAAAAAAACAAdDPAwAAAAAAF6kUUatl8TFvnlvB8H/KsqbnR6kpUluHAAAAAAABASCQ0AMAAAAAABepFDzN1E7LDjAMNARzCHsU4rXqBf55hwEEFgAUG3vPJhyWYtt/ikPpOCW6jCqkmxsiBgLHMhb0QhE8eyJBnE9syGAtMehGmHe1sxpm+TlxjgFXERgAAAAAMQAAgAAAAIAAAACAAAAAAAAAAAAAAA==', + 'cHNidP8BAFMCAAAAAfTUAYKfU/lPbuIV0AsoBIURL2tAz7iaObvEMcXQBW94AAAAAAAAAACAAQnQAwAAAAAAF6kUUatl8TFvnlvB8H/KsqbnR6kpUluHAAAAAAABASCQ0AMAAAAAABepFDzN1E7LDjAMNARzCHsU4rXqBf55hwEEFgAUG3vPJhyWYtt/ikPpOCW6jCqkmxsiBgLHMhb0QhE8eyJBnE9syGAtMehGmHe1sxpm+TlxjgFXERgAAAAAMQAAgAAAAIAAAACAAAAAAAAAAAAAAA==', ); }); @@ -141,7 +141,7 @@ describe('Watch only wallet', () => { assert.strictEqual( psbt.toBase64(), - 'cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK2OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA', + 'cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOIGOgAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA', ); }); @@ -181,7 +181,7 @@ describe('Watch only wallet', () => { ); assert.strictEqual( psbt.toBase64(), - 'cHNidP8BAHECAAAAASJiwHJP3qYi80+cYjHn/n8TiJJR6jRbJFx67gnclfVdAAAAAAAAAACAAogTAAAAAAAAFgAUb3eWXdETtv7KGyXiUxyIS+Q3wJ003QAAAAAAABYAFF8XCHdkg2yGn81L+plhb9iWamgBAAAAAAABAR8oBAEAAAAAABYAFBAk4ma75DYqawitVrni8qlFzNykIgYDNK9TxoCjQ8P0+qI2Hu4hrnXnJuYAC3h2puZbgRORp+sYFo3WA1QAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgL1DWeV+AfIP5RRB5zHv5vuXsIt8+rF9rrsji3FhQlhzBgWjdYDVAAAgAAAAIAAAACAAQAAAAAAAAAA', + 'cHNidP8BAHECAAAAASJiwHJP3qYi80+cYjHn/n8TiJJR6jRbJFx67gnclfVdAAAAAAAAAACAAogTAAAAAAAAFgAUb3eWXdETtv7KGyXiUxyIS+Q3wJ0U5AAAAAAAABYAFF8XCHdkg2yGn81L+plhb9iWamgBAAAAAAABAR8oBAEAAAAAABYAFBAk4ma75DYqawitVrni8qlFzNykIgYDNK9TxoCjQ8P0+qI2Hu4hrnXnJuYAC3h2puZbgRORp+sYFo3WA1QAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgL1DWeV+AfIP5RRB5zHv5vuXsIt8+rF9rrsji3FhQlhzBgWjdYDVAAAgAAAAIAAAACAAQAAAAAAAAAA', ); }); @@ -221,7 +221,7 @@ describe('Watch only wallet', () => { ); assert.strictEqual( psbt.toBase64(), - 'cHNidP8BAHECAAAAASJiwHJP3qYi80+cYjHn/n8TiJJR6jRbJFx67gnclfVdAAAAAAAAAACAAogTAAAAAAAAFgAUb3eWXdETtv7KGyXiUxyIS+Q3wJ003QAAAAAAABYAFF8XCHdkg2yGn81L+plhb9iWamgBAAAAAAABAR8oBAEAAAAAABYAFBAk4ma75DYqawitVrni8qlFzNykIgYDNK9TxoCjQ8P0+qI2Hu4hrnXnJuYAC3h2puZbgRORp+sYFo3WA1QAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgL1DWeV+AfIP5RRB5zHv5vuXsIt8+rF9rrsji3FhQlhzBgWjdYDVAAAgAAAAIAAAACAAQAAAAAAAAAA', + 'cHNidP8BAHECAAAAASJiwHJP3qYi80+cYjHn/n8TiJJR6jRbJFx67gnclfVdAAAAAAAAAACAAogTAAAAAAAAFgAUb3eWXdETtv7KGyXiUxyIS+Q3wJ0U5AAAAAAAABYAFF8XCHdkg2yGn81L+plhb9iWamgBAAAAAAABAR8oBAEAAAAAABYAFBAk4ma75DYqawitVrni8qlFzNykIgYDNK9TxoCjQ8P0+qI2Hu4hrnXnJuYAC3h2puZbgRORp+sYFo3WA1QAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgL1DWeV+AfIP5RRB5zHv5vuXsIt8+rF9rrsji3FhQlhzBgWjdYDVAAAgAAAAIAAAACAAQAAAAAAAAAA', ); });