If you’re considering becoming a blockchain developer, this is a good time to get started.
After all, according to Zip Recruiter’s data, an average blockchain developer salary is about $154,550/year.
However, with this article, you don’t need any knowledge of cryptography to follow along. If you know JavaScript, you are good to go.
At the end of this tutorial, you should have a general understanding of how bitcoin transactions work and should be able to send Bitcoin to anyone from your wallet using JavaScript.
To follow along, you should have:
Here’s a simple workflow diagram of the entire bitcoin transaction process.
Here’s the transaction workflow:
First off, let’s define two key terms you’ll notice throughout this tutorial: the blockchain and a bitcoin transaction.
The blockchain can be described as an immutable distributed database of a global log of transactions. A block in the blockchain can be likened to a record in traditional databases.
A transaction is the transfer of value from one bitcoin wallet to another that gets included in the blockchain.
You’ll typically need to install and run your bitcoin node (your copy of the blockchain) on your server to be able to play around with the blockchain development. However, we won’t do that in this tutorial.
Instead, we’ll use third-party services that are already running a bitcoin node.
There is the bitcoin Testnet blockchain and the Mainnet blockchain. The Testnet is a bitcoin blockchain designed to be used for testing. This is what we’ll use in this tutorial.
N.B., do not use real bitcoin in development; bitcoin transactions are not reversible; once lost, they can not be recovered unless you have the private key of the receiving addresses
To get started, we need to have some bitcoins to send, right? So, let’s create a Testnet wallet and load it with some bitcoins. You can quickly use the wallet generator website to generate Testnet wallets.
Or you can generate one with bitcore-core.
Here is the one I just generated from the website.
93F2mUJPKbXW8Q9cMNz4ZmpsjgTbNjrMeCaUesTPE7k1DFhSmnk
(in the real world this private key should not be shown to anyone, but this is a Testnet, so whatever 😀 )mtVE8anM63kQcgKUC6oQQD9K6xiV4wsr7q
Let’s send some bitcoin to it using a bitcoin Testnet faucet website. I will send 0.00 bitcoin to this address (mtVE8anM63kQcgKUC6oQQD9K6xiV4wsr7q
) from this Testnet website.
Now that we have some bitcoin in our wallet, let’s create a simple Node.js application that will allow us to send bitcoin.
Set up your node application with npm init -y
and install the Bitcore open source library — we’ll use the Bitcore library and Axios to interface with the blockchain.
npm install axios, bitcore-lib
Create an index.js file and import the Bitcore and Axios library.
const axios = require("axios"); const bitcore = require("bitcore-lib");
Then create a function sendBitcoin
that will actually send the bitcoin.
We’ll use the SoChain API to connect to the Testnet blockchain.
The code below is the building block of the function definition we’ll use to send bitcoin. It’s heavily commented to help with understanding.
/** @receiverAddress - Address of the person you want to send bitcoin to @amountToSend - This is the amount of bitcoin you want to send to someone from your wallet. This amount will be deducted from your wallet and sent to this address. */ let sendBitcoin = (recieverAddress, amountToSend)=>{ const sochain_network = "BTCTEST"; // the Testnet network for sochain const privateKey = `93F2mUJPKbXW8Q9cMNz4ZmpsjgTbNjrMeCaUesTPE7k1DFhSmnk`;// your privateKey -- the one we just generated /* your bitcoin address. The one you want to send funds from -- the one we just generated */ const sourceAddress = `mtVE8anM63kQcgKUC6oQQD9K6xiV4wsr7q`; /** because the outputs come in satoshis, and 1 Bitcoin is equal to 100,000,000 satoshies, we'll multiply the amount of bitcoin by 100,000,000 to get the value in satoshis. */ const satoshiToSend = amountToSend * 100000000; let fee = 0; let inputCount = 0; let outputCount = 2; // we are going to use 2 as the output count because we'll only send the bitcoin to 2 addresses the receiver's address and our change address. }
Unspent outputs are the transactions you received to your bitcoin wallet that have not been spent. Assuming you receive $100 USD worth of bitcoin in five different transactions, you will have five unspent outputs.
Let’s use the SoChain block explorer to find out how many outputs we have so far in our wallet. If you pass the network and the address to the URL below in a GET request, it will return a result that contains our unspent outputs.
https://sochain.com/api/v2/get_tx_unspent/{Network}/{Address}
For example if we pass our address to it, like so:
https://sochain.com/api/v2/get_tx_unspent/BTCTEST/mtVE8anM63kQcgKUC6oQQD9K6xiV4wsr7q
Here is the result we’ll get:
The txs
part is an array of all the unspent outputs.
That’s just one unspent output we have there. Because I sent Bitcoin once to that address and it has not been spent.
To use that data in our code, let’s Axios to grab that data:
const utxos = await axios.get( `https://sochain.com/api/v2/get_tx_unspent/${sochain_network}/${sourceAddress}` );
Next, initialize a new transaction using the Bitcore lib API.
const transaction = new bitcore.Transaction();
From here onward, we’ll use this transaction instance to complete the entire process.
From the unspent outputs, we need to build a new input. Our input is going to be equal to the unspent outputs.
Let’s grab the essential elements of the outputs we need to create new inputs from the unspent output array. We are doing this because the shape of the object that the Bitcore API requires is not the same as what SoChain returns to us. Below are the required items we’ll be looking out for in our transaction.
utxo.satoshis = Math.floor(Number(element.value) * 100000000); utxo.script = element.script_hex; utxo.address = utxos.data.data.address; utxo.txId = element.txid; utxo.outputIndex = element.output_no;
Grab that data from the array of unspent output and build the new inputs:
let inputs = []; let utxos = response.data.data.txs; for (const element of utxos) { let utxo = {}; utxo.satoshis = Math.floor(Number(element.value) * 100000000); utxo.script = element.script_hex; utxo.address = response.data.data.address; utxo.txId = element.txid; utxo.outputIndex = element.output_no; totalAmountAvailable += utxo.satoshis; inputCount += 1; inputs.push(utxo); }
Now that we’ve got the inputs in an array, let’s set the transaction inputs.
transaction.from(inputs);
If you have played around with bitcoin, you will notice that sometimes the fees are high and other times, they may be close to zero. Well, that’s because there is really no fee. Sounds counterintuitive, right?
Yes, you can decide to send bitcoin without a fee, but it might take a long time before it’ll get picked and added to the blockchain by miners. The fee is a concept that allows miners to be compensated for their effort and to keep the network secure.
Also, because the maximum block size in a bitcoin transaction is 1MB, miners tend to give priority to the transactions with the highest fees. As of this writing, the average priority fee is about 108 satoshis/byte.
So, how do you determine the fee?
Because the fee doesn’t depend on the amount of bitcoin you are sending, and instead upon the size of the transaction, you need to first determine the size of the transaction. Interestingly, the size of the transaction depends on the input and output in the transaction.
This formula can be used to determine the size:
transactionSize = inputCount * 180 + outputCount * 34 + 10 - inputCount;
In every bitcoin transaction, the inputs contribute 180 bytes each to the transaction, while the output contributes 34 bytes each to the transaction. Then there is an extra 10 bytes you add or subtract from the transaction as well.
Assuming you have a transaction with two inputs and two outputs, the transaction size will be 2180+234+10-2 = 436 bytes.
So, if you want to pay 20 satoshis per byte, the fee will be:
Fee = 20*436
Fee = 8720 satoshis
Because 100,000,000 satoshis equal 1 bitcoin, we should divide 8720/100,000,000.
This makes the fee 0.0000872 bitcoin, which is approximately $3.03 USD as of the time of this writing.
That’s how you determine your bitcoin fee.Also, you can use bitcoinfees.earn.com/api to get the recommended fees.
Now that you know the fee for the transaction, you could easily check if your balance is enough to cover the transaction including the fees.
// Check if we have enough funds to cover the transaction and the fees if (totalAmountAvailable - satoshiToSend - fee < 0) { throw new Error("Balance is too low for this transaction"); }
Now that you have calculated your fees and verified that you have enough balance to cover your fees and the entire transaction, you can go ahead and set the receiving address and fees with the Bitcore API.
transaction.to(recieverAddress, satoshiToSend); // receiving address and amount of satoshis to send. transaction.fee(fee);
You can’t send only part of your bitcoin balance out to another address. No, you take out everything and send the amount you want to the receiving address, then send back the change to yourself.
So, the change address is your address — the address you want to get the balance paid into after sending to the receiver.
So, we’ll use the Bitcore function transaction.change
to set the address:
transaction.change(sourceAddress);
Before we can spend bitcoin in a wallet, we must have the private key of that wallet. Your private key is your password to unlock the funds in any bitcoin wallet.
// Sign transaction with your private key transaction.sign(privateKey);
To broadcast the transaction, we need to serialize the transaction in order to get the transaction hex:
const serializedTransaction = transaction.serialize();
It’s this transaction hex we’ll broadcast to the blockchain.
Let’s broadcast the transaction to the blockchain through the SoChain node with a post request the API.
// broadcast transaction const result = await axios({ method: "POST", url: `https://sochain.com/api/v2/send_tx/${sochain_network}`, data: { tx_hex: serializedTX, }, }); return result.data.data
Here is the complete code for everything we’ve built so far:
const sendBitcoin = async (recieverAddress, amountToSend) => { const sochain_network = "BTCTEST"; const privateKey = ""; const sourceAddress = ""; const satoshiToSend = amountToSend * 100000000; let fee = 0; let inputCount = 0; let outputCount = 2; const utxos = await axios.get( `https://sochain.com/api/v2/get_tx_unspent/${sochain_network}/${sourceAddress}` ); const transaction = new bitcore.Transaction(); let totalAmountAvailable = 0; let inputs = []; let utxos = response.data.data.txs; for (const element of utxos) { let utxo = {}; utxo.satoshis = Math.floor(Number(element.value) * 100000000); utxo.script = element.script_hex; utxo.address = response.data.data.address; utxo.txId = element.txid; utxo.outputIndex = element.output_no; totalAmountAvailable += utxo.satoshis; inputCount += 1; inputs.push(utxo); } transactionSize = inputCount * 146 + outputCount * 34 + 10 - inputCount; // Check if we have enough funds to cover the transaction and the fees assuming we want to pay 20 satoshis per byte fee = transactionSize * 20 if (totalAmountAvailable - satoshiToSend - fee < 0) { throw new Error("Balance is too low for this transaction"); } //Set transaction input transaction.from(inputs); // set the recieving address and the amount to send transaction.to(recieverAddress, satoshiToSend); // Set change address - Address to receive the left over funds after transfer transaction.change(sourceAddress); //manually set transaction fees: 20 satoshis per byte transaction.fee(fee); // Sign transaction with your private key transaction.sign(privateKey); // serialize Transactions const serializedTransaction = transaction.serialize(); // Send transaction const result = await axios({ method: "POST", url: `https://sochain.com/api/v2/send_tx/${sochain_network}`, data: { tx_hex: serializedTX, }, }); return result.data.data; };
Congratulations, you’ve successfully created a simple JavaScript function to send bitcoin to your friend using 62 lines of code.
You can simply call the sendBitcoin
function then pass the receiver’s bitcoin address and the amount you wish to send as shown below to send bitcoin to anyone.
sendBitcoin("mtVE8anM63kQcgKUC6oQQD9K6xiV4wsryq", 0.0003)
The response from this API will contain your transaction ID, which you can use to verify the transaction on any bitcoin explorer — in our case, any bitcoin Testnet explorer.
To send real bitcoin, you’ll need to change the network from BTCTEST
to BTC
and use your real bitcoin wallet’s private key and address.
There is a lot more to learn about the blockchain, cryptocurrencies, and how to work with them. I believe this should provide you with basic information on how to use JavaScript to send bitcoin from your wallet and enable you to build up knowledge from there.
If you wish to learn more, I recommend reading the book Programming the Blockchain or Mastering Bitcoin, they are both free books and have a ton of information to get you up started on your journey to becoming a blockchain developer. I’ve also made a video to walk you through, even more, you can check it out on YouTube.
If you enjoyed this post, please share. Happy hacking!
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBackdrop and background have similar meanings, as they both refer to the area behind something. The main difference is that […]
AI tools like IBM API Connect and Postbot can streamline writing and executing API tests and guard against AI hallucinations or other complications.
Explore DOM manipulation patterns in JavaScript, such as choosing the right querySelector, caching elements, improving event handling, and more.
`window.ai` integrates AI capabilities directly into the browser for more sophisticated client-side functionality without relying heavily on server-side processing.
20 Replies to "Send bitcoin from your wallet using JavaScript"
Hey good post!!
I have a problem with the code …
It’s throw a error that say
Error: Some inputs have not been fully signed – For more information please see: https://bitcore.io/api/lib/transaction#serialization-checks
You can helpme with that?
Thanks in advance
Are you sure you are using a valid private key to sign the transaction?
yes , i genereted here https://walletgenerator.net/?currency=Testnet%20Bitcoin# and copy & paste
I upload My test https://bitcoin-send-react-app.herokuapp.com/ can You check the console .. it’s seem that something not Match . I created for the private key new bitcore.PrivateKey(wif)
Hi! Did you fixed “Error: Some inputs have not been fully signed” because I have the same problem
No =(
Please drop the link for main Bitcoin API. Because i have searched for it , I could not find it. Since we can use the code for Bitcoin network as well. And not only btctest network alone. Yes the testnetwork worked perfectly. But I need the main BTC network Link. Where I am out my private key and wallet address
Hi Desmond, I mentioned this -> “To send real bitcoin, you’ll need to change the network from BTCTEST to BTC and use your real bitcoin wallet’s private key and address.”
So, you can do that.
I see a small bug in the calculation of the fee in that final complete code panel. The bytes are being multiplied by 20 twice, via two separate lines of code:
fee = transactionSize * 20
transaction.fee(fee * 20);
I really like this script!
BTW, if anyone runs their own Bitcoin full node, you can comment out the final sochain.com POST statement and instead grab a copy of the final transaction hex string then send that directly to your own full node to get it into the blockchain. Just make sure you reconfigure your full node to use the TESTNET before doing it, otherwise you’ll post to MAINNET.
1) Restart your fullnode to use the bitcoin TESTNET (swap in your config file location):
% bitcoind -testnet -conf=/bitcoin/.bitcoin/bitcoin.conf -printtoconsole # change to location of your conf file!
2) Post the transaction hex string using either the bitcoin REST APIs, or the bitcoin-cli
% bitcoin-cli -testnet -conf=/bitcoin/.bitcoin/bitcoin.conf decoderawtransaction 0200000001a…c00000000
Hello, please i am getting this error:
(node:6480) UnhandledPromiseRejectionWarning: Invalid Argument: Amount is expected to be a positive integer
I need help to correct this please.
were you able to reslove this? facing the exact same issue now
That last point in my previous post should be the “sendrawtransaction” command, not the “decoderawtransaction” command:
% bitcoin-cli -testnet -conf=/bitcoin/.bitcoin/bitcoin.conf sendrawtransaction 0200000001a…c00000000
Also worth noting that this script works for all of the main bitcoin address types, including both legacy addresses and segwit addresses. i.e. p2pkh (legacy), p2wpkh (native segwit), and p2sh_p2wpkh (nested segwit).
This axios API is really awesome, but I would really love to get my hands on that sochain get_tx_unspent API .. that’s super nice!
Your maths for the amounts is incorrect, so probably not enough satoshis to pay for your transaction. Check your totalAmountAvailable, satoshiToSend, fee (from transaction size) to see what the calculations show.
Please how can i reach you???
I have an error, i tryed to use the function in my react app and i am getting transaction.sign(privateKey) error. assertion error. but when i run this alone my function works.
Hi
I got Assertion Faild issue, so could you please guide me how to resolve it?
bitcore.min.js:1 Uncaught (in promise) Error: Assertion failed
at assert (bitcore.min.js:1)
at BN.toBuffer (bitcore.min.js:1)
at Signature.toBuffer.Signature.toDER (bitcore.min.js:1)
at PublicKeyHashInput.addSignature (bitcore.min.js:1)
at Transaction.applySignature (bitcore.min.js:1)
at bitcore.min.js:1
at arrayEach (bitcore.min.js:1)
at Function.forEach (bitcore.min.js:1)
at Transaction.sign (bitcore.min.js:1)
at sendBitcoin ((index):619)
Line no: 619 transaction.sign(privateKey);
Hi,
Firstly thanks for this blog it’s really helpful. I have the following question:
Is the fee structure defined above something standard?
I see a 20 satoshi/byte mechanism has been followed. Do I need to adhere to this or can I reduce the fee or make it something constant as well like $1? Asking this because if someone is using a wallet which has had a lot of transactions previously, the transaction fee will just skyrocket even if the amount of bitcoins transferred is less as transaction size depends on input count.
Thanks.
Hey, the value is not static. You van use lower value but if it is too low you transaction might never get confirmed or might take weeks or months.
Use this api to figured out the value that gets added faster or slower
https://bitcoinfees.earn.com/api
Goodluck
sochain is no longer offering free services. Any other alternative?