Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

Send bitcoin from your wallet using JavaScript

8 min read 2248

send bitcoin javascript

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.

Prerequisites

To follow along, you should have:

  • Node.js Installed
  • A basic understanding of JavaScript

Here’s a simple workflow diagram of the entire bitcoin transaction process.

send bitcoin javascript workflow
Bitcoin transaction workflow

Here’s the transaction workflow:

  • Get the unspent transaction outputs
  • Add the inputs to get a new transaction input
  • Calculate transaction fee
  • Check if you have enough balance to cover the transaction
  • Set transaction inputs
  • Set change address
  • Set transaction fee
  • Sign transaction
  • Serialize transaction
  • Broadcast transaction

What is a blockchain?

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.

What is a bitcoin transaction?

A transaction is the transfer of value from one bitcoin wallet to another that gets included in the blockchain.

We made a custom demo for .
No really. Click here to check it out.

Using bitcoin Testnet blockchain and Mainnet 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.

Note: Do not use real bitcoin in development. Bitcoin transactions are not reversible. Once lost, they are not recoverable except if you have the private key of the receiving addresses.

Setting up a Testnet wallet with bitcoin

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.

Here is the one I just generated from the website.

  • Private key = 93F2mUJPKbXW8Q9cMNz4ZmpsjgTbNjrMeCaUesTPE7k1DFhSmnk (in the real world this private key should not be shown to anyone, but this is a Testnet, so whatever 😀 )
  • Address = 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 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 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.
}

Receiving unspent outputs

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:

send bitcoin javascript sochain blockchain
Unspent output

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.

Building new inputs

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:

  • satoshis: the value of the unspent output in satoshi
  • script: an instruction defining how to spend the unspent Output
  • address: your wallet address
  • transaction ID (txid): this a unique id to identify your transaction in the blockchain
  • outputIndex: the index of each output in a 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 totalAmountAvailable = 0;
  let inputs = [];
  utxos.data.data.txs.forEach(async (element) => {
    let utxo = {};

    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;

    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);

Dealing with bitcoin transaction fees

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 counter-intuitive, 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.

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");
  }

Setting the bitcoin receiver address, amount to send, and fees

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.
 // manually set transaction fees: 20 satoshis per byte
  transaction.fee(fee * 20);

Setting up the bitcoin change address

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);

Signing the transaction

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);

Serializing the bitcoin transaction

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.

Broadcasting the bitcoin transaction

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 = [];
  utxos.data.data.txs.forEach(async (element) => {
    let utxo = {};
    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;
    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 * 20);

  // 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.

Conclusion

There is a lot more to learn about the blockchain, cryptocurrencies, and how to work with them. I believe this should you give you an idea and allow you to build up knowledge from there.

If you wish to learn more, I recommend reading the book Programming the Blockchain. It’s a free book and has a ton of information to get you up and running.

If you enjoyed this post, please share. Happy hacking!

: Debug JavaScript errors easier by understanding the context

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 find out exactly what the user did that led to an error.

LogRocket records console logs, page load times, stacktraces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!

.
Eze Sunday Eze Sunday is a full-stack software developer and technical writer passionate about solving problems, one line of code at a time. Currently building Raveshift.com, a crypto exchange and tools for crypto payment solutions.

15 Replies to “Send bitcoin from your wallet using JavaScript”

  1. Hi! Did you fixed “Error: Some inputs have not been fully signed” because I have the same problem

  2. 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

  3. 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.

  4. 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);

  5. 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

  6. 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.

  7. 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!

  8. 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.

  9. 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.

Leave a Reply