- Blockchain By Example
- Bellaj Badr Richard Horrocks Xun (Brian) Wu
- 647字
- 2021-06-10 18:53:30
Let's code
Start by creating a hello.js file and importing the bitcoinjs-lib and request-promise modules using the require directive as follows:
var bitcoin = require('bitcoinjs-lib');
var rp = require('request-promise');
Then we declare and define the necessary variables:
var data = Buffer.from('Hello World', 'utf8');
var testnet = bitcoin.networks.testnet;
var privateKey = 'cQx4Ucd3uXEpa3bNnS1JJ84gWn5djChfChtfHSkRaDNZQYA1FYnr';
var SourceAddress = "n3CKupfRCJ6Bnmr78mw9eyeszUSkfyHcPy";
They represent respectively:
- The message to be embedded in the transaction
- The network—testnet
- The private key in WIF (short for Wallet Import Format)
- The source address from which we spend the UTXO
Then we ask the API to provide us with the available unspent output belonging to a specific address. We read the response from the API to define the available amount and the output txid.
We also define the fee (5,000 satoshis) to pay the network (miners) for processing the transaction, as follows:
var url = "https://chain.so/api/v2/get_tx_unspent/BTCTEST/"+SourceAddress;
var DestionationAddress = '2MsHsi4CHXsaNZSq5krnrpP4WShNgtuRa9U';
var options = {
uri: url,
json: true
};
rp(options).then(function (response) {
var index = response.data.txs.length - 1;
console.log(response.data.txs[index]);
var UtxoId = response.data.txs[index].txid;
var vout = response.data.txs[index].output_no;
var amount = Number(response.data.txs[index].value*100000000);
var fee = 0.0005*100000000;
}).catch(function (err) { console.error(err);});
You can use console.log() at any point to print the received values in the console.
Now it's time to create our transaction. Inside the previous GET request, add the following lines:
const RawTransaction = new bitcoin.TransactionBuilder(testnet);
RawTransaction.addInput(UtxoId, vout);
RawTransaction.addOutput(DestionationAddress, parseInt(amount-fee));
scrypt = bitcoin.script.compile([bitcoin.opcodes.OP_RETURN,data]);
RawTransaction.addOutput(scrypt, 0);
Here we are using TransactionBuilder from bitcoinjs-lib to create our new raw transaction. Then we add the output we requested earlier from the API as input to our transaction.
We add two outputs: the first is an OP_RETURN output with 0 bitcoins, and the second is the output with 100,000,000 satoshis (one bitcoin), minus the fees.
Great! Everything is set! The only thing we have to do right now is to sign the transaction with our private key, and send it to the bitcoin blockchain:
var keyPair = bitcoin.ECPair.fromWIF(privateKeyWIF, testnet);
tx.sign(0, keyPair);
The second line—tx.sign(0, keyPair)—is because we are consuming a Pay-to-Public-Key-Hash (P2PKH) output. However, in bitcoin we have different types of transaction and addresses. The addresses beginning with 2 receive Pay-to-Script-Hash (P2SH) transactions, instead of the common P2PKH transactions received by addresses starting with m or n.
Of course, this changes the way we spend the output; therefore, we need to know the type of the output prior to signing the new transaction. For P2SH transactions, we need to use the following code instead:
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: bitcoin.networks.testnet });
const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: bitcoin.networks.testnet});
RawTransaction.sign(0, keyPair, p2sh.redeem.output, null, parseInt(amount));
Lastly, we take the signed transaction in and send it to the specified network using a POST request with the API. We provide in our request a JSON object, which contains a hex representation of the signed transaction, as follows:
var Transaction=RawTransaction.build().toHex();
var Sendingoptions = { method: 'POST', url: 'https://chain.so/api/v2/send_tx/BTCTEST',
body: {tx_hex: Transaction}, json: true};
rp(Sendingoptions).then(function (response) {
var Jresponse = JSON.stringify(response);
console.log("Transaction ID:\n"+Jresponse);
}).catch(function (err) { console.error(err); });
Once you have saved the file, run it with the node hello.js command. If the raw transaction is valid and delivered successfully to the network, you will receive a message back that's similar to the following:
We get the used output details, along with a success message returning the transaction ID.
As before, we can check the transaction processing using a testnet explorer.
Congratulations, you have successfully built your first Node.js application to send bitcoins and to store data into a blockchain. Based on that, you can create advanced applications or develop your own protocol on top of the blockchain.
As a bonus, the full code is available in the following Github repository: https://github.com/bellaj/HelloWorld.