i want to Create a 1-to-1 Transaction
when like this
const alice = bitcoin.ECPair.fromWIF(
'L2uPYXe17xSTqbCjZvL2DsyXPCbXspvcu5mHLDYUgzdUbZGSKrSr',
);
const psbt = new bitcoin.Psbt();
psbt.setVersion(2); // These are defaults. This line is not needed.
psbt.setLocktime(0); // These are defaults. This line is not needed.
psbt.addInput({
hash: '7d067b4a697a09d2c3cff7d4d9506c9955e93bff41bf82d439da7d030382bc3e',
index: 0,
sequence: 0xffffffff, // These are defaults. This line is not needed.
nonWitnessUtxo: Buffer.from(
'0200000001f9f34e95b9d5c8abcd20fc5bd4a825d1517be62f0f775e5f36da944d9' +
'452e550000000006b483045022100c86e9a111afc90f64b4904bd609e9eaed80d48' +
'ca17c162b1aca0a788ac3526f002207bb79b60d4fc6526329bf18a77135dc566020' +
'9e761da46e1c2f1152ec013215801210211755115eabf846720f5cb18f248666fec' +
'631e5e1e66009ce3710ceea5b1ad13ffffffff01' +
// value in satoshis (Int64LE) = 0x015f90 = 90000
'905f010000000000' +
// scriptPubkey length
'19' +
// scriptPubkey
'76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac' +
// locktime
'00000000',
'hex',
),
});
How do I get hash and nonWitnessUtxo? Is it through bitcoinjs?
Hope someone can help me
The hash/index is the hash of the transaction which contains the utx you are going to spend, while the index is the utx index in that tx. Same for the nonWitnessUtxo, is the full transaction containing the utx.
To retrieve these data, you could use a blockexplorer and its api; personally I suggest to use blockstream explorer, api docs are available here: https://github.com/Blockstream/esplora/blob/master/API.md
Endpoints are [testnet ? 'https://blockstream.info/testnet/api' : 'https://blockstream.info/api']
Piggybacking on this question. I try to sweep all uxtos from one testnet address.
First I get the uxtos of this address:
https://blockstream.info/testnet/api/address/mfs8TLBd62Pusu9dsjCugFGkop7qveLASn/utxo
This gives me a list of transaction ids. I guess it's these I have to use as hash in addInput?
Then I find every raw transaction for these ids, e.g. for this tx:
https://blockstream.info/testnet/api/tx/36503c549d044dd64de1e2a5f1ecd3472f2ac6a1d11902ac3b5c5f01f5d61474/hex
Result is
But then, when I try to add this as input
const input = {
hash: u.txid, // The txid from above
index, // A sequential number I'm giving
nonWitnessUtxo: Buffer.from(rawTx.data), // The hex data from above
network: TESTNET, //bitcoin.networks.testnet
}
I get this error:
UnhandledPromiseRejectionWarning: RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 2666. Received 2700
at boundsError (internal/buffer.js:77:9)
at Buffer.readUInt32LE (internal/buffer.js:211:5)
at readUInt32 (/node_modules/bitcoinjs-lib/src/transaction.js:56:24)
at Function.fromBuffer (/node_modules/bitcoinjs-lib/src/transaction.js:102:19)
at addNonWitnessTxCache (/node_modules/bitcoinjs-lib/src/psbt.js:1137:40)
at Psbt.addInput (/node_modules/bitcoinjs-lib/src/psbt.js:165:7)
at /node_modules/bitcoinjs-lib/src/psbt.js:142:42
at Array.forEach (<anonymous>)
at Psbt.addInputs (/node_modules/bitcoinjs-lib/src/psbt.js:142:16)
at createTransaction (file:///createtx.mjs:41:7)
I'm missing something, but I don't know where to start...
You need to tell Buffer.from that the data you have is a hex string. Otherwise it expects a BufferLike Array of numbers from 0 to 255. (ie. Uint8Array etc)
Buffer.from(rawTx.data, 'hex')
Also, network is not needed for the inputs. network is passed to the new Psbt({ network: TESTNET }) call
You need to tell Buffer.from that the data you have is a hex string. Otherwise it expects a BufferLike Array of numbers from 0 to 255. (ie. Uint8Array etc)
Buffer.from(rawTx.data, 'hex')
I knew it had to be something simple, small and easy to overlook :) Thanks!
Going furter:
function createTransaction(inputs, address, value, keyPair) {
const psbt = new bitcoin.Psbt({ network: TESTNET });
psbt.addInputs(inputs); // the inputs are generated from the utxos from before
psbt.addOutput({
address, // The address that will be receiving the sats
value, // The combined value of the utxos minus a transaction fee
});
psbt.signAllInputs(keyPair); // Generated from WIF: keyPair = bitcoin.ECPair.fromWIF(<privateWIFhere>, TESTNET);
psbt.validateSignaturesOfAllInputs();
psbt.finalizeAllInputs();
return psbt.extractTransaction().toHex();
}
Gives this error:
UnhandledPromiseRejectionWarning: Error: No signatures to validate
at Psbt.validateSignaturesOfInput (/node_modules/bitcoinjs-lib/src/psbt.js:265:13)
at /node_modules/bitcoinjs-lib/src/psbt.js:257:12
at Array.map (<anonymous>)
at Psbt.validateSignaturesOfAllInputs (/node_modules/bitcoinjs-lib/src/psbt.js:256:52)
at createTransaction (file:///createtx.mjs:49:7)
at file:///createtx.mjs:32:18
signAllInputs() seems to work, it doesn't complain, but then validateSignaturesOfAllInputs() says that there are no signatures?
signAllInputs works if it signs ANY input.
validateSignaturesOfAllInputs works only if ALL inputs are signed.
So some of your inputs are not signed properly.
Are you sure every single input is spending an output for the same private key, and are you sure you have the correct info in inputs? (ie. your example above is correct for P2PKH addresses, but that's it)
ahh, you are giving the wrong index.
the index you pass to addInput is the index of the output in the nonWitnessUtxo transaction that you are spending.
Aha, is that the vout?
utxos: [
{
txid: 'e6dc8972311082f41cb104f1d3c1c90ffc7a6a7f671d00db48072ae7b8e6c031',
vout: 0,
status: {
confirmed: true,
block_height: 1744094,
block_hash: '0000000000000a2017aebef5be7748d5dedebd686f0ba932738da4fcfc5af096',
block_time: 1589414266
},
value: 22000
},
{
txid: 'fa241e9bb394b4054e638d2da5e8f60e2a6c09a861f8b0e3924d7d513d9f0143',
vout: 0,
status: {
confirmed: true,
block_height: 1744094,
block_hash: '0000000000000a2017aebef5be7748d5dedebd686f0ba932738da4fcfc5af096',
block_time: 1589414266
},
value: 1000000
},
{
txid: '05349143b730137c397ec0dcbbb818ce5badd208062d77c8e0a3814bf9915789',
vout: 0,
status: {
confirmed: true,
block_height: 1746439,
block_hash: '00000000ab90d50bcecbc7929137e7da5f17f69f8eaea2c277985e9b99103db6',
block_time: 1590332162
},
value: 1000000
},
{
txid: 'e4038d0134c99775a55d64b201458f26631cb8668e2935f2ed0bd1714a531e8a',
vout: 1,
status: {
confirmed: true,
block_height: 1740147,
block_hash: '000000000000b015c4a714d4cea2ccbbbe99b825fccd8ee5717867082e1dfb61',
block_time: 1589294874
},
value: 1950926
},
{
txid: 'a6fbb47d84c6d88c9a6dace1eccf4cb41f3d17d87d0e056b70f0a626031ac973',
vout: 1,
status: {
confirmed: true,
block_height: 1740136,
block_hash: '00000000000075b2ad9575d09cf0896521fbbcaf3118606c04196fa17900110d',
block_time: 1589294722
},
value: 1000000
},
{
txid: 'e8ada2814008b4e756cca76cc7eb39e0c991d9ec693c236619154d3f07de1a78',
vout: 20,
status: {
confirmed: true,
block_height: 1742536,
block_hash: '0000000000002f733faf73003c67bfc94a4e8bdc82630d40b1a7d4c8ae16ae36',
block_time: 1589343510
},
value: 74762844
},
{
txid: '36503c549d044dd64de1e2a5f1ecd3472f2ac6a1d11902ac3b5c5f01f5d61474',
vout: 1,
status: {
confirmed: true,
block_height: 1740141,
block_hash: '0000000000002a73be9dc6680c6e54fe1ac2509b9ee655f81087995ae8f4a115',
block_time: 1589294776
},
value: 92000
}
]
It was vout. Thanks for all your help @junderw! Some parts of this low-level bitcoin stuff are still difficult to wrap my head around, but I feel like I'm learning a lot.
Most helpful comment
The hash/index is the hash of the transaction which contains the utx you are going to spend, while the index is the utx index in that tx. Same for the nonWitnessUtxo, is the full transaction containing the utx.
To retrieve these data, you could use a blockexplorer and its api; personally I suggest to use blockstream explorer, api docs are available here: https://github.com/Blockstream/esplora/blob/master/API.md
Endpoints are [testnet ? 'https://blockstream.info/testnet/api' : 'https://blockstream.info/api']