diff --git a/transaction.go b/transaction.go index 6dd8019..4d12755 100644 --- a/transaction.go +++ b/transaction.go @@ -14,13 +14,13 @@ const ( // Spec: https://github.com/bitcoin-sv-specs/brfc-misc/tree/master/feespec // DefaultDataRate is the default rate for feeType: data (500 satoshis per X bytes) - DefaultDataRate uint64 = 500 + DefaultDataRate int = 500 // DefaultStandardRate is the default rate for feeType: standard (500 satoshis per X bytes) - DefaultStandardRate uint64 = 500 + DefaultStandardRate int = 500 // DefaultRateBytes is the default amount of bytes to calculate fees (X Satoshis per X bytes) - DefaultRateBytes uint64 = 1000 + DefaultRateBytes int = 1000 // DustLimit is the minimum value for a tx that can be spent // Note: this is being deprecated in the new node software (TBD) @@ -62,7 +62,7 @@ func TxFromHex(rawHex string) (*bt.Tx, error) { // // Use this if you don't want to figure out fees/change for a tx func CreateTxWithChange(utxos []*Utxo, payToAddresses []*PayToAddress, opReturns []OpReturnData, - changeAddress string, standardRate, dataRate *FeeAmount, + changeAddress string, standardRate, dataRate *bt.Fee, privateKey *bsvec.PrivateKey) (*bt.Tx, error) { // Missing utxo(s) or change address @@ -106,7 +106,7 @@ func CreateTxWithChange(utxos []*Utxo, payToAddresses []*PayToAddress, opReturns // Calculate the fees for the "Draft tx" fee := CalculateFeeForTx(tx, standardRate, dataRate) - // todo: replace with Libsv's new way to create change tx (when released) + // todo: replace with go-bt way to create change tx (when released) // for now (hacking the fee) (ensure we are over the min fee for the miner) fee++ @@ -137,7 +137,7 @@ func CreateTxWithChange(utxos []*Utxo, payToAddresses []*PayToAddress, opReturns // // Use this if you don't want to figure out fees/change for a tx func CreateTxWithChangeUsingWif(utxos []*Utxo, payToAddresses []*PayToAddress, opReturns []OpReturnData, - changeAddress string, standardRate, dataRate *FeeAmount, wif string) (*bt.Tx, error) { + changeAddress string, standardRate, dataRate *bt.Fee, wif string) (*bt.Tx, error) { // Decode the WIF privateKey, err := WifToPrivateKey(wif) @@ -239,41 +239,42 @@ func CreateTxUsingWif(utxos []*Utxo, addresses []*PayToAddress, // Rate(s) can be derived from MinerAPI (default is DefaultDataRate and DefaultStandardRate) // If rate is nil it will use default rates (0.5 sat per byte) // Reference: https://tncpw.co/c215a75c -func CalculateFeeForTx(tx *bt.Tx, standardRate, dataRate *FeeAmount) uint64 { +func CalculateFeeForTx(tx *bt.Tx, standardRate, dataRate *bt.Fee) uint64 { // Set the totals - var totalFee uint64 - var totalDataBytes uint64 + var totalFee int + var totalDataBytes int // Set defaults if not found if standardRate == nil { - standardRate = &FeeAmount{Bytes: DefaultRateBytes, Satoshis: DefaultStandardRate} + standardRate = bt.DefaultStandardFee() } if dataRate == nil { - dataRate = &FeeAmount{Bytes: DefaultRateBytes, Satoshis: DefaultDataRate} + dataRate = bt.DefaultStandardFee() + // todo: adjusted to 5/10 for now, since all miners accept that rate + dataRate.FeeType = bt.FeeTypeData } // Set the total bytes of the tx - totalBytes := uint64(len(tx.ToBytes())) + totalBytes := len(tx.ToBytes()) // Loop all outputs and accumulate size (find data related outputs) for _, out := range tx.GetOutputs() { - // todo: once libsv has outs.data.ToBytes() this can be removed/optimized outHexString := out.GetLockingScriptHexString() if strings.HasPrefix(outHexString, "006a") || strings.HasPrefix(outHexString, "6a") { - totalDataBytes += uint64(len(out.ToBytes())) + totalDataBytes += len(out.ToBytes()) } } // Got some data bytes? if totalDataBytes > 0 { totalBytes = totalBytes - totalDataBytes - totalFee += (dataRate.Satoshis * totalDataBytes) / dataRate.Bytes + totalFee += (dataRate.MiningFee.Satoshis * totalDataBytes) / dataRate.MiningFee.Bytes } // Still have regular standard bytes? if totalBytes > 0 { - totalFee += (standardRate.Satoshis * totalBytes) / standardRate.Bytes + totalFee += (standardRate.MiningFee.Satoshis * totalBytes) / standardRate.MiningFee.Bytes } // Safety check (possible division by zero?) @@ -282,5 +283,5 @@ func CalculateFeeForTx(tx *bt.Tx, standardRate, dataRate *FeeAmount) uint64 { } // Return the total fee as a uint (easier to use with satoshi values) - return totalFee + return uint64(totalFee) } diff --git a/transaction_test.go b/transaction_test.go index 87e32fc..92dce1d 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -62,58 +62,54 @@ func BenchmarkTxFromHex(b *testing.B) { // TestCreateTx will test the method CreateTx() func TestCreateTx(t *testing.T) { + t.Parallel() - // Example from: https://github.com/libsv/go-bt - - // Use a new UTXO - utxo := &Utxo{ - TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", - Vout: 0, - ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", - Satoshis: 1000, - } + t.Run("basic valid tx", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } - // Add a pay-to address - payTo := &PayToAddress{ - Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", - Satoshis: 500, - } + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } - // Add some op return data - opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} - opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} - // Private key (from wif) - privateKey, err := WifToPrivateKey("L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu") - assert.NoError(t, err) - assert.NotNil(t, privateKey) + privateKey, err := WifToPrivateKey("L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu") + assert.NoError(t, err) + assert.NotNil(t, privateKey) - // Generate the TX - var tx *bt.Tx - tx, err = CreateTx( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - privateKey, - ) - assert.NoError(t, err) - assert.NotNil(t, tx) - assert.Equal(t, - "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006b483045022100eea3d606bd1627be6459a9de4860919225db74843d2fc7f4e7caa5e01f42c2d0022017978d9c6a0e934955a70e7dda71d68cb614f7dd89eb7b9d560aea761834ddd4412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff03f4010000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac00000000000000001a006a07707265666978310c6578616d706c65206461746102133700000000000000001c006a0770726566697832116d6f7265206578616d706c65206461746100000000", - tx.ToString(), - ) -} + var tx *bt.Tx + tx, err = CreateTx( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + privateKey, + ) + assert.NoError(t, err) + assert.NotNil(t, tx) + assert.Equal(t, + "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006b483045022100eea3d606bd1627be6459a9de4860919225db74843d2fc7f4e7caa5e01f42c2d0022017978d9c6a0e934955a70e7dda71d68cb614f7dd89eb7b9d560aea761834ddd4412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff03f4010000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac00000000000000001a006a07707265666978310c6578616d706c65206461746102133700000000000000001c006a0770726566697832116d6f7265206578616d706c65206461746100000000", + tx.ToString(), + ) + }) -func TestCreateEmptyTx(t *testing.T) { - tx, err := CreateTx( - nil, - nil, - nil, - nil, - ) - assert.NoError(t, err) - assert.NotNil(t, tx) - assert.Equal(t, "01000000000000000000", tx.ToString()) + t.Run("empty tx", func(t *testing.T) { + tx, err := CreateTx( + nil, + nil, + nil, + nil, + ) + assert.NoError(t, err) + assert.NotNil(t, tx) + assert.Equal(t, "01000000000000000000", tx.ToString()) + }) } // ExampleCreateTx example using CreateTx() @@ -327,46 +323,59 @@ func TestCreateTxErrors(t *testing.T) { // TestCreateTxUsingWif will test the method CreateTxUsingWif() func TestCreateTxUsingWif(t *testing.T) { + t.Parallel() - // Example from: https://github.com/libsv/go-bt + t.Run("valid tx", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } - // Use a new UTXO - utxo := &Utxo{ - TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", - Vout: 0, - ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", - Satoshis: 1000, - } + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } - // Add a pay-to address - payTo := &PayToAddress{ - Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", - Satoshis: 500, - } + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} - // Add some op return data - opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} - opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + tx, err := CreateTxUsingWif( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + "L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu", + ) + assert.NoError(t, err) + assert.NotNil(t, tx) + }) - // Generate the TX - tx, err := CreateTxUsingWif( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - "L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu", - ) - assert.NoError(t, err) - assert.NotNil(t, tx) + t.Run("invalid wif", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } - // Invalid wif - tx, err = CreateTxUsingWif( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - "", - ) - assert.Error(t, err) - assert.Nil(t, tx) + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } + + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + + tx, err := CreateTxUsingWif( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + "", + ) + assert.Error(t, err) + assert.Nil(t, tx) + }) } // ExampleCreateTxUsingWif example using CreateTxUsingWif() @@ -474,79 +483,142 @@ func TestCalculateFeeForTxVariousTxs(t *testing.T) { // Create the list of tests var tests = []struct { + name string inputHex string - inputStandardRate *FeeAmount - inputDataRate *FeeAmount + inputStandardRate *bt.Fee + inputDataRate *bt.Fee expectedTxID string expectedSatoshis uint64 }{ - {"0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006b483045022100e07b7661af4e4b521c012a146b25da2c7b9d606e9ceaae28fa73eb347ef6da6f0220527f0638a89ff11cbe53d5f8c4c2962484a370dcd9463a6330f45d31247c2512412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff0364030000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac00000000000000001a006a07707265666978310c6578616d706c65206461746102133700000000000000001c006a0770726566697832116d6f7265206578616d706c65206461746100000000", + { + "tx-132", + "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006b483045022100e07b7661af4e4b521c012a146b25da2c7b9d606e9ceaae28fa73eb347ef6da6f0220527f0638a89ff11cbe53d5f8c4c2962484a370dcd9463a6330f45d31247c2512412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff0364030000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac00000000000000001a006a07707265666978310c6578616d706c65206461746102133700000000000000001c006a0770726566697832116d6f7265206578616d706c65206461746100000000", nil, nil, "e75fa79ee5fbb589201f769c01835e14ca595b7bbfa0e602050a2a90cf28d129", 132, }, - {"0200000001203d3a9d8e2ccfe2d6bb1bce6ad8a9c1251a58f9c788737b21e3e19588e89110010000006a47304402201e7fe22f20d02a5cd6978b21bc68aa31eb74530c6b75b47caef19d6f2a95f47802206b20de32c7398fa822397b49389a49224742a9d3c175a851376a25deb6428cb24121023bc787128d6296be6a534b32e90724413179545a0ec2720a7258de330fc54544ffffffff02000000000000000053006a4c4fe5b08fe881aae6b8b8e6888f3130e69c883234e697a5e6b7b1e59cb3e7babfe4b88be994a6e6a087e8b59befbc8ce586a0e5869b425356e5a596e98791e7ad89e4bda0e69da5e68c91e68898efbc817c0c0000000000001976a9146382643e30d2ea7e52eb07eac8767ed219c53e3a88ac00000000", + { + "tx-141", + "0200000001203d3a9d8e2ccfe2d6bb1bce6ad8a9c1251a58f9c788737b21e3e19588e89110010000006a47304402201e7fe22f20d02a5cd6978b21bc68aa31eb74530c6b75b47caef19d6f2a95f47802206b20de32c7398fa822397b49389a49224742a9d3c175a851376a25deb6428cb24121023bc787128d6296be6a534b32e90724413179545a0ec2720a7258de330fc54544ffffffff02000000000000000053006a4c4fe5b08fe881aae6b8b8e6888f3130e69c883234e697a5e6b7b1e59cb3e7babfe4b88be994a6e6a087e8b59befbc8ce586a0e5869b425356e5a596e98791e7ad89e4bda0e69da5e68c91e68898efbc817c0c0000000000001976a9146382643e30d2ea7e52eb07eac8767ed219c53e3a88ac00000000", nil, nil, "1affabe9b5adc3a6930a06002a447e834681004a5e6767a649d0371a806e7b1d", 141, }, - {"0200000001a39b865acf5d100aa35341a63e4ba6dc7da101f3b740cd5372e25b0fb23306c5000000006a47304402207cdcab521641801cd0427501c0264073cfd11f2693bb9a109d00482c643f16b30220798801d1acc9dea23013f17cbd7cc0edec996abc1493f9b9a8ba61723b4ec01d41210250a932cf2543f8f35dba3fce46f53ca821409f4e233d9f8090a165f5ac42a0e8ffffffff014a060000000000001976a914f21ff89bd2259699d229ebc1f9c29ac3c3e0411888ac00000000", + { + "tx-95", + "0200000001a39b865acf5d100aa35341a63e4ba6dc7da101f3b740cd5372e25b0fb23306c5000000006a47304402207cdcab521641801cd0427501c0264073cfd11f2693bb9a109d00482c643f16b30220798801d1acc9dea23013f17cbd7cc0edec996abc1493f9b9a8ba61723b4ec01d41210250a932cf2543f8f35dba3fce46f53ca821409f4e233d9f8090a165f5ac42a0e8ffffffff014a060000000000001976a914f21ff89bd2259699d229ebc1f9c29ac3c3e0411888ac00000000", nil, nil, "175fc22ffbd76f1cdb7ec2c40474abedbb4bb6080e9c8d22736ffc2d48e85fd2", 95, }, - {"010000000129cdf21be448b28b0f88ecc9317d9ea1a385a6928d855f55b2d62a3bbc8631cd000000006b483045022100a8b7d34e10e817647f753a9a1380606945bd9c255ebb87c7a00a701903abc6e20220284651051ef520eb5f13901c0f792d7eae2e75b9e85fff36258d9592839227614121029843434e00940e0829196042983e46fe801364b1a586f3d4160556684d63e8d1ffffffff030000000000000000fd48026a2231394878696756345179427633744870515663554551797131707a5a56646f4175744cff545742544348205457455443482054574554534820545745544348205457455443482054574554434820545745544348205457455443482054564554434820545745544348205457454943482054574554434820545745544348205457455453482054574554434820545745544348205457415443482054574554434820545745574348205457455443482054574554434820545745544548205457455443482054574554434820545745545348205457455443482054574554434820545745544f482054574554434820544d45544348205457455443482054574554454820545745544348205768617427732077697468696e205457455443483f203a500a746578742f706c61696e04746578741f7477657463685f7477746578745f313536383139363330383230372e747874017c223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540b7477646174615f6a736f6e046e756c6c0375726c046e756c6c07636f6d6d656e74046e756c6c076d625f757365720434363631047479706504706f73740974696d657374616d700f3638343131393038353536373938330361707006747765746368017c22313550636948473232534e4c514a584d6f53556157566937575371633768436676610d424954434f494e5f45434453412231414b48566959674247626d78693871694a6b4e766f484e654475396d334d665045102323636f6d70757465645f7369672323953f0000000000001976a9147346219a70740418422b19c0ecd696671d3ce17088acdbdf0500000000001976a914b4376ffbd47974340a0a0d940681e168c1d6ae0788ac00000000", + { + "tx-410", + "010000000129cdf21be448b28b0f88ecc9317d9ea1a385a6928d855f55b2d62a3bbc8631cd000000006b483045022100a8b7d34e10e817647f753a9a1380606945bd9c255ebb87c7a00a701903abc6e20220284651051ef520eb5f13901c0f792d7eae2e75b9e85fff36258d9592839227614121029843434e00940e0829196042983e46fe801364b1a586f3d4160556684d63e8d1ffffffff030000000000000000fd48026a2231394878696756345179427633744870515663554551797131707a5a56646f4175744cff545742544348205457455443482054574554534820545745544348205457455443482054574554434820545745544348205457455443482054564554434820545745544348205457454943482054574554434820545745544348205457455453482054574554434820545745544348205457415443482054574554434820545745574348205457455443482054574554434820545745544548205457455443482054574554434820545745545348205457455443482054574554434820545745544f482054574554434820544d45544348205457455443482054574554454820545745544348205768617427732077697468696e205457455443483f203a500a746578742f706c61696e04746578741f7477657463685f7477746578745f313536383139363330383230372e747874017c223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540b7477646174615f6a736f6e046e756c6c0375726c046e756c6c07636f6d6d656e74046e756c6c076d625f757365720434363631047479706504706f73740974696d657374616d700f3638343131393038353536373938330361707006747765746368017c22313550636948473232534e4c514a584d6f53556157566937575371633768436676610d424954434f494e5f45434453412231414b48566959674247626d78693871694a6b4e766f484e654475396d334d665045102323636f6d70757465645f7369672323953f0000000000001976a9147346219a70740418422b19c0ecd696671d3ce17088acdbdf0500000000001976a914b4376ffbd47974340a0a0d940681e168c1d6ae0788ac00000000", nil, nil, "d612aed6c3f12756ea1d3e9a48eef2faf05eaf20ff6031911d8610332f8d3f9a", 410, }, - {"01000000018558c697a0bb502f9aec70b27c48d3c87f0df28e16f9c8f43a43b1327ea69304010000006b483045022100e0114cf815c0d60fc72e7c8a4c39b03920ac03e62b5c98c68882c1235f2e0ac90220278319c67e79c4397ad989cb9be453acfbbb8e8a9f927c6f4509d9a1da4a17eb412103637720f48f059b854605da3d5a959d204e1e6cbd0d03ee91a38a067bdee90558ffffffff020000000000000000d96a2231394878696756345179427633744870515663554551797131707a5a56646f4175742c436865636b6f757420546f6e6963506f773a2068747470733a2f2f746e6370772e636f2f36313239373839330d746578742f6d61726b646f776e055554462d38017c223150755161374b36324d694b43747373534c4b79316b683536575755374d745552350353455403617070086d6574616c656e73047479706507636f6d6d656e740375726c2268747470733a2f2f6f66666572732e746f6e6963706f772e636f6d2f6f666665727304757365720444756465d3bb1100000000001976a914e0190be1c0ced1e92c26b3c6d5ccbbe853b57e7288ac00000000", + { + "tx-209", + "01000000018558c697a0bb502f9aec70b27c48d3c87f0df28e16f9c8f43a43b1327ea69304010000006b483045022100e0114cf815c0d60fc72e7c8a4c39b03920ac03e62b5c98c68882c1235f2e0ac90220278319c67e79c4397ad989cb9be453acfbbb8e8a9f927c6f4509d9a1da4a17eb412103637720f48f059b854605da3d5a959d204e1e6cbd0d03ee91a38a067bdee90558ffffffff020000000000000000d96a2231394878696756345179427633744870515663554551797131707a5a56646f4175742c436865636b6f757420546f6e6963506f773a2068747470733a2f2f746e6370772e636f2f36313239373839330d746578742f6d61726b646f776e055554462d38017c223150755161374b36324d694b43747373534c4b79316b683536575755374d745552350353455403617070086d6574616c656e73047479706507636f6d6d656e740375726c2268747470733a2f2f6f66666572732e746f6e6963706f772e636f6d2f6f666665727304757365720444756465d3bb1100000000001976a914e0190be1c0ced1e92c26b3c6d5ccbbe853b57e7288ac00000000", nil, nil, "ef3fe744c7be4b81f2881f9c11433bc4905a032a0bf15bcda31f90c28ba1b356", 209, }, - {"010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", + { + "tx-220-1", + "010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", nil, nil, "8785ca5f11795a38eb1f50f62562cb5e0335b283762fe8a2c7e96d5f7f79bb15", 220, }, - {"01000000014179d984eb4738acddf290d1cbcb6ec0b44d945dc00020a9337738a4b5d4d0c5020000006b483045022100acc8301fb2f9bf70089e03f2a28ff8a384c0525e94a8ee5bb1ccb9b1f044bb91022012b5fb696bb92b2208f901e8bd43264a161cf97f72024cc1809224eee5fd7bab412102ad7b9a78da643560d0ffa411d27070d2468eccfcbb5b39ec30d69724a181944cffffffff045d020000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac9e170000000000001976a9141531448d45a7985230d2ad467acc22f635f0d10988ac985b8800000000001976a914cf500ad6b6852a13017d60080e58522716e33b9088ac0000000000000000ac006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f6964023239106f666665725f73657373696f6e5f6964403361303930636439393361346564386239626261303438643030653134666466303931633266616134333735396236366434363136396634613066313463343900000000", + { + "tx-220-2", + "01000000014179d984eb4738acddf290d1cbcb6ec0b44d945dc00020a9337738a4b5d4d0c5020000006b483045022100acc8301fb2f9bf70089e03f2a28ff8a384c0525e94a8ee5bb1ccb9b1f044bb91022012b5fb696bb92b2208f901e8bd43264a161cf97f72024cc1809224eee5fd7bab412102ad7b9a78da643560d0ffa411d27070d2468eccfcbb5b39ec30d69724a181944cffffffff045d020000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac9e170000000000001976a9141531448d45a7985230d2ad467acc22f635f0d10988ac985b8800000000001976a914cf500ad6b6852a13017d60080e58522716e33b9088ac0000000000000000ac006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f6964023239106f666665725f73657373696f6e5f6964403361303930636439393361346564386239626261303438643030653134666466303931633266616134333735396236366434363136396634613066313463343900000000", nil, nil, "32050b05bf48440bbb3e7c4fa79aa6cb36a69e2921965780334ee168de41f676", 220, - }, {"0100000001462c8567bdd70e5f4d36204c239eb1149e15f778925d5e4d36c3a0e7862bf887020000006b483045022100c55116cad7dd3c6bfba1ac4b696ebf60792032c4189c2c30735cfcad300a1c8f02201db5aa8fc38db419b559ff01a07a6dfaac1d5d7b940e89b398fa92bf387b1899412102ad7b9a78da643560d0ffa411d27070d2468eccfcbb5b39ec30d69724a181944cffffffff045c020000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac9b170000000000001976a9141531448d45a7985230d2ad467acc22f635f0d10988acf3258800000000001976a914cf500ad6b6852a13017d60080e58522716e33b9088ac0000000000000000ac006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f6964023239106f666665725f73657373696f6e5f6964403634353530346139663966383533393862323434363339336237393066303265666236343738366661666533326535333737373062653064646437663532323700000000", + }, + { + "tx-220-3", + "0100000001462c8567bdd70e5f4d36204c239eb1149e15f778925d5e4d36c3a0e7862bf887020000006b483045022100c55116cad7dd3c6bfba1ac4b696ebf60792032c4189c2c30735cfcad300a1c8f02201db5aa8fc38db419b559ff01a07a6dfaac1d5d7b940e89b398fa92bf387b1899412102ad7b9a78da643560d0ffa411d27070d2468eccfcbb5b39ec30d69724a181944cffffffff045c020000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac9b170000000000001976a9141531448d45a7985230d2ad467acc22f635f0d10988acf3258800000000001976a914cf500ad6b6852a13017d60080e58522716e33b9088ac0000000000000000ac006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f6964023239106f666665725f73657373696f6e5f6964403634353530346139663966383533393862323434363339336237393066303265666236343738366661666533326535333737373062653064646437663532323700000000", nil, nil, "4232216b35ebaa9301e386010eaaba05902be7bd4db60e2f588ae9d0e3e583e9", 220, - }, {"01000000014c0b196f630c02005b9c17069deef60dff492bdfd0a54a140aaaaf3769ab3d09020000006a47304402207b9acc2cb029617b625fe2a7fc4553b4b70d9f9ec87afc5aa5289866841cbf3702203047baf62881a098cb24bfa85e7f20c37513a8cbbd27efb4b30ad3519118ed7d4121028ae3c8bf25ae420e3e451be1b40f7edb8ff64e0ce32a2398b1d9374c1d50733cffffffff045c020000000000001976a914806773d8c6f90c544b98755e9a80915488357bbe88ac93170000000000001976a914a16150864dc3041666ab055f154da6c35335b6fb88acc2dd7500000000001976a914d1fc52081c4cf54454eeed6982d6b2977c40196088ac0000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403313532106f666665725f73657373696f6e5f6964406637343736653061343763333863616664663061616164336564643539363831306235616539396130633737396637643035383438346330323933326238393500000000", + }, + { + "tx-220-4", + "01000000014c0b196f630c02005b9c17069deef60dff492bdfd0a54a140aaaaf3769ab3d09020000006a47304402207b9acc2cb029617b625fe2a7fc4553b4b70d9f9ec87afc5aa5289866841cbf3702203047baf62881a098cb24bfa85e7f20c37513a8cbbd27efb4b30ad3519118ed7d4121028ae3c8bf25ae420e3e451be1b40f7edb8ff64e0ce32a2398b1d9374c1d50733cffffffff045c020000000000001976a914806773d8c6f90c544b98755e9a80915488357bbe88ac93170000000000001976a914a16150864dc3041666ab055f154da6c35335b6fb88acc2dd7500000000001976a914d1fc52081c4cf54454eeed6982d6b2977c40196088ac0000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403313532106f666665725f73657373696f6e5f6964406637343736653061343763333863616664663061616164336564643539363831306235616539396130633737396637643035383438346330323933326238393500000000", nil, nil, "7a868c8529e598195c6c2cbf30006cb09fd55e9f3d3d809a38f191a586a3ce82", 220, }, - {"010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", - &FeeAmount{Bytes: DefaultRateBytes, Satoshis: 1000}, - &FeeAmount{Bytes: DefaultRateBytes, Satoshis: 1000}, + { + "tx-1000", + "010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", + &bt.Fee{FeeType: bt.FeeTypeStandard, MiningFee: bt.FeeUnit{ + Satoshis: 1000, + Bytes: DefaultRateBytes, + }, RelayFee: bt.FeeUnit{ + Satoshis: 1000, + Bytes: DefaultRateBytes, + }}, + &bt.Fee{FeeType: bt.FeeTypeData, MiningFee: bt.FeeUnit{ + Satoshis: 1000, + Bytes: DefaultRateBytes, + }, RelayFee: bt.FeeUnit{ + Satoshis: 1000, + Bytes: DefaultRateBytes, + }}, "8785ca5f11795a38eb1f50f62562cb5e0335b283762fe8a2c7e96d5f7f79bb15", 441, }, - {"010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", - &FeeAmount{Bytes: DefaultRateBytes, Satoshis: 250}, - &FeeAmount{Bytes: DefaultRateBytes, Satoshis: 250}, + { + "tx-250", + "010000000190c5208bed05b4e54746bab5a5d4a5e4324e2999c180b7ea7105047f1f16b84a030000006a47304402202ca5d7a2cfb2388babb549b10c47ed20cdadafb845af835c7d5ff04e933ba1c102200a8b7289bbd3c0cc62172afe0006ba374ddd0132a7e4fb4e92ebcff5ce9217db412102812d641ff356c362815f8fc03bd061c2ae57e02f5dc3083f61785c0e5b198039ffffffff040000000000000000ad006a223150755161374b36324d694b43747373534c4b79316b683536575755374d74555235035345540361707008746f6e6963706f7704747970650b6f666665725f636c69636b0f6f666665725f636f6e6669675f696403323934106f666665725f73657373696f6e5f696440653638616631393439626131633239326131376431393635343638383234383663653635313830663465363439383235613561363532376634646132303761661f0c0000000000001976a91409cc4559bdcb84cb35c107743f0dbb10d66679cc88ac31790000000000001976a9147c8ced9ee0f48192822a0148f27b5a1f24aa42d388ac53f74600000000001976a914852f89e9b05d6adfc905842ee0d301947d675df988ac00000000", + &bt.Fee{FeeType: bt.FeeTypeStandard, MiningFee: bt.FeeUnit{ + Satoshis: 250, + Bytes: DefaultRateBytes, + }, RelayFee: bt.FeeUnit{ + Satoshis: 250, + Bytes: DefaultRateBytes, + }}, + &bt.Fee{FeeType: bt.FeeTypeData, MiningFee: bt.FeeUnit{ + Satoshis: 250, + Bytes: DefaultRateBytes, + }, RelayFee: bt.FeeUnit{ + Satoshis: 250, + Bytes: DefaultRateBytes, + }}, "8785ca5f11795a38eb1f50f62562cb5e0335b283762fe8a2c7e96d5f7f79bb15", 109, }, - {"0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006a47304402200083bb297d53210cf9379b3f47de2eff38e6906e5982fbfeef9bf59778750f3e022046da020811e9a2d1e6db8da103d17598abc194125612be6b108d49cb60cbca95412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff0000000000", - &FeeAmount{Bytes: 157, Satoshis: 1}, - &FeeAmount{Bytes: 157, Satoshis: 1}, + { + "tx-157-1", + "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006a47304402200083bb297d53210cf9379b3f47de2eff38e6906e5982fbfeef9bf59778750f3e022046da020811e9a2d1e6db8da103d17598abc194125612be6b108d49cb60cbca95412102ea87d1fd77d169bd56a71e700628113d0f8dfe57faa0ba0e55a36f9ce8e10be3ffffffff0000000000", + &bt.Fee{FeeType: bt.FeeTypeStandard, MiningFee: bt.FeeUnit{ + Satoshis: 1, + Bytes: 157, + }, RelayFee: bt.FeeUnit{ + Satoshis: 1, + Bytes: 157, + }}, + &bt.Fee{FeeType: bt.FeeTypeData, MiningFee: bt.FeeUnit{ + Satoshis: 1, + Bytes: 157, + }, RelayFee: bt.FeeUnit{ + Satoshis: 1, + Bytes: 157, + }}, "d3350a4ef4b2c72b23e5117979590d768e61f2102337e2ae956d152a80cd37ac", 1, }, @@ -555,19 +627,15 @@ func TestCalculateFeeForTxVariousTxs(t *testing.T) { // Run tests var satoshis uint64 for _, test := range tests { - - // Get the tx from hex string - tx, err := TxFromHex(test.inputHex) - assert.NoError(t, err) - assert.NotNil(t, tx) - - // Test the function - if satoshis = CalculateFeeForTx(tx, test.inputStandardRate, test.inputDataRate); satoshis != test.expectedSatoshis { - t.Log("tx size: ", len(tx.ToBytes())) - t.Fatalf("%s Failed: [%s] [%v] [%v] inputted [%d] expected but got: %d", t.Name(), test.inputHex, test.inputStandardRate, test.inputDataRate, test.expectedSatoshis, satoshis) - } else if tx.GetTxID() != test.expectedTxID { - t.Fatalf("%s Failed: [%s] [%v] [%v] inputted [%s] expected but got: %s", t.Name(), test.inputHex, test.inputStandardRate, test.inputDataRate, test.expectedTxID, tx.GetTxID()) - } + t.Run(test.name, func(t *testing.T) { + tx, err := TxFromHex(test.inputHex) + assert.NoError(t, err) + assert.NotNil(t, tx) + + satoshis = CalculateFeeForTx(tx, test.inputStandardRate, test.inputDataRate) + assert.Equal(t, test.expectedSatoshis, satoshis, satoshis) + assert.Equal(t, test.expectedTxID, tx.GetTxID()) + }) } } @@ -629,55 +697,50 @@ func TestCalculateFeeForTxPanic(t *testing.T) { // TestCreateTxWithChange tests for nil case in CreateTxWithChange() func TestCreateTxWithChange(t *testing.T) { + t.Parallel() - // Use a new UTXO - utxo := &Utxo{ - TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", - Vout: 0, - ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", - Satoshis: 1000, - } - - // Add a pay-to address - payTo := &PayToAddress{ - Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", - Satoshis: 500, - } + t.Run("valid tx", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } - // Add some op return data - opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} - opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } - // Private key (from wif) - privateKey, err := WifToPrivateKey("L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu") - assert.NoError(t, err) - assert.NotNil(t, privateKey) + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} - // Generate the TX - var rawTx *bt.Tx - rawTx, err = CreateTxWithChange( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", - nil, - nil, - privateKey, - ) - assert.NoError(t, err) + privateKey, err := WifToPrivateKey("L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu") + assert.NoError(t, err) + assert.NotNil(t, privateKey) - // Show the results - // t.Logf("created tx: %s", rawTx.ToString()) + var rawTx *bt.Tx + rawTx, err = CreateTxWithChange( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", + nil, + nil, + privateKey, + ) + assert.NoError(t, err) - // Test the right fee - assert.Equal(t, uint64(149), CalculateFeeForTx(rawTx, nil, nil)) + // Test the right fee + assert.Equal(t, uint64(149), CalculateFeeForTx(rawTx, nil, nil)) - // Test that we got the right amount of change (satoshis) - for _, out := range rawTx.GetOutputs() { - if out.GetLockingScriptHexString() == "76a914c9d8699bdea34b131e737447b50a8b1af0b040bf88ac" { - assert.Equal(t, uint64(351), out.Satoshis) + // Test that we got the right amount of change (satoshis) + for _, out := range rawTx.GetOutputs() { + if out.GetLockingScriptHexString() == "76a914c9d8699bdea34b131e737447b50a8b1af0b040bf88ac" { + assert.Equal(t, uint64(351), out.Satoshis) + } } - } + }) } // TestCreateTxWithChangeErrors tests for nil case in CreateTxWithChange() @@ -691,8 +754,8 @@ func TestCreateTxWithChangeErrors(t *testing.T) { inputOpReturns []OpReturnData inputWif string inputChangeAddress string - inputStandardRate *FeeAmount - inputDataRate *FeeAmount + inputStandardRate *bt.Fee + inputDataRate *bt.Fee expectedRawTx string expectedNil bool expectedError bool @@ -976,60 +1039,75 @@ func BenchmarkCreateTxWithChange(b *testing.B) { // TestCreateTxWithChangeUsingWif tests for nil case in CreateTxWithChangeUsingWif() func TestCreateTxWithChangeUsingWif(t *testing.T) { + t.Parallel() - // Use a new UTXO - utxo := &Utxo{ - TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", - Vout: 0, - ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", - Satoshis: 1000, - } + t.Run("valid tx", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } - // Add a pay-to address - payTo := &PayToAddress{ - Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", - Satoshis: 500, - } + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } - // Add some op return data - opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} - opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} - // Generate the TX - rawTx, err := CreateTxWithChangeUsingWif( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", - nil, - nil, - "L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu", - ) - assert.NoError(t, err) - assert.NotNil(t, rawTx) + rawTx, err := CreateTxWithChangeUsingWif( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", + nil, + nil, + "L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu", + ) + assert.NoError(t, err) + assert.NotNil(t, rawTx) - // Test the right fee - assert.Equal(t, uint64(149), CalculateFeeForTx(rawTx, nil, nil)) + // Test the right fee + assert.Equal(t, uint64(149), CalculateFeeForTx(rawTx, nil, nil)) - // Test that we got the right amount of change (satoshis) - for _, out := range rawTx.GetOutputs() { - if out.GetLockingScriptHexString() == "76a914c9d8699bdea34b131e737447b50a8b1af0b040bf88ac" { - assert.Equal(t, uint64(351), out.Satoshis) + // Test that we got the right amount of change (satoshis) + for _, out := range rawTx.GetOutputs() { + if out.GetLockingScriptHexString() == "76a914c9d8699bdea34b131e737447b50a8b1af0b040bf88ac" { + assert.Equal(t, uint64(351), out.Satoshis) + } } - } + }) - // Invalid wif - rawTx, err = CreateTxWithChangeUsingWif( - []*Utxo{utxo}, - []*PayToAddress{payTo}, - []OpReturnData{opReturn1, opReturn2}, - "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", - nil, - nil, - "", - ) - assert.Error(t, err) - assert.Nil(t, rawTx) + t.Run("invalid wif", func(t *testing.T) { + utxo := &Utxo{ + TxID: "b7b0650a7c3a1bd4716369783876348b59f5404784970192cec1996e86950576", + Vout: 0, + ScriptPubKey: "76a9149cbe9f5e72fa286ac8a38052d1d5337aa363ea7f88ac", + Satoshis: 1000, + } + + payTo := &PayToAddress{ + Address: "1C8bzHM8XFBHZ2ZZVvFy2NSoAZbwCXAicL", + Satoshis: 500, + } + + opReturn1 := OpReturnData{[]byte("prefix1"), []byte("example data"), []byte{0x13, 0x37}} + opReturn2 := OpReturnData{[]byte("prefix2"), []byte("more example data")} + + rawTx, err := CreateTxWithChangeUsingWif( + []*Utxo{utxo}, + []*PayToAddress{payTo}, + []OpReturnData{opReturn1, opReturn2}, + "1KQG5AY9GrPt3b5xrFqVh2C3YEhzSdu4kc", + nil, + nil, + "", + ) + assert.Error(t, err) + assert.Nil(t, rawTx) + }) } // ExampleCreateTxWithChangeUsingWif example using CreateTxWithChangeUsingWif()