Getting Started with BitGo Express

BitGo Express makes it easy to get started developing with the Bitcoin protocol using multi-sig wallets in any language. BitGo Express is a proxy server designed to run within your own network and ensures that all cryptographically secure operations, such as address creation and transaction signing, occur in a trusted environment. Users interact with BitGo Express using BitGo’s SDK through a RESTful interface, and so any language capable of issuing HTTP requests can easily and securely use the Bitcoin protocol. The built-in security suite, trusted by top-tier exchanges like Bitstamp provide developers with the peace-of-mind in knowing that they no longer have to rely on a homebrew security stack. This blog post will take you through the process of using BitGo Express to send and receive Bitcoin from scratch.

Requirements

This tutorial assumes comfort with javascript, and git. Please ensure that you have the following:

This tutorial will provide setup instructions for the Bitcoin testnet network which is recommended starting point for developers new to Bitcoin.

  • A BitGo testnet account on test.bitgo.com
  • An access token from your BitGo testnet account (see Authentication Guide)
  • The latest version of npm.
  • Mac OS X or Linux-based OS

Let’s Get Started!

First you need to install and run the bitgo-express executable. Bitgo-Express is a Nodejs program contained within the BitGo SDK repository, so you need to install the SDK's source code. You can do this two ways, depending on whether you want to use npm or git to install it. Both ways are equally straightforward and give you access to the SDK source code, so choose whichever you like:

# Using git
git clone https://github.com/BitGo/BitGoJS
cd BitGoJS
./bin/bitgo-express
# Using NPM
mkdir bitgo-express
cd bitgo-express
npm init
npm install bitgo
./node_modules/bitgo/bin/bitgo-express

You’ve just installed and started BitGo Express, we’ll get started by authenticating our BitGo access token.

Authentication

We’ll be using cURL to test out our local BitGo Express instance, we recommend following along and then implementing a request wrapper in any language that you would like.

First let’s open up a new tab and set our developer’s token as an environment variable so we can easily access it.

export ACCESS_TOKEN="f193a015bbd2e5...ad9befbce9472aff"

Next we can check the status of our token by calling the session endpoint

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \

-d '{}' \

-H "Content-Type: application/json" \

http://localhost:3080/api/v1/user/session

Your response should resemble the following:

{ “session”: {

“id”: ”5631516fa7c0e8c509bb06ca1c0851d5",

”client”: ”bitgo”,

”user”: ”5582f55d4fe2627d67d914158d99a37c”,

”scope”: [

“wallet_view_all”,

”wallet_spend_all”,

”wallet_manage_all”,

”wallet_create”,

”openid”,

”profile”

],

”created”: ”2015–10–28T22:51:27.575Z”,

”expires”: ”2025–10–25T22:51:27.574Z”,

”origin”: ”test.bitgo.com”,

”label”: ”TEST TOKEN [50.242.80.35]”,

”unlock”: {

“time”: ”2015–10–28T22:51:27.576Z”,

”expires”: ”2025–10–25T22:51:27.574Z”,

”txValueLimit”: 1000000000,

”txValue”: 0

}

}}

Let’s take a moment to double check our token parameters to ensure that we can follow through with the tutorial, make sure that you have the following:

  • A scope that includes wallet_create and wallet_spend_all.
  • The origin is test.bitgo.com.
  • The timestamp under expires is greater than the time you expect it to take you to complete this tutorial.
  • The txValueLimit is greater than 5 BTC or 500,000,000 Satoshis or any value higher than what we would expect to receive from a reasonable testnet faucet.

Creating a wallet

BitGo users have the benefit of creating Bitcoin wallets that are both protected by a unique password as well as two-factor authentication in the web-client. BitGo wallets have the additional benefit of advanced treasury controls that can allow multiple users to share a wallet with a specific set of policies as well as spending limits and address whitelisting. To create a wallet run the following

Your response should resemble the following: 

curl -X POST -H "Content-Type: application/json"

-H "Authorization: Bearer $ACCESS_TOKEN"

-d '{ "passphrase": "superlongpassword", "label": "My BitGo Wallet" }'

http://localhost:3080/api/v1/wallets/simplecreate

"wallet" : {

"_id" : "56315b7b39cccac6090f48f159b6eaa0",

"id" : "2N7GXBJPZQDJKbx53CwXYkrYVRLuqHJoYmA",

"label" : "My BitGo Wallet",

"isActive" : true,

"type" : "safehd",

"freeze" : {},

"adminCount" : 1,

"disableTransactionNotifications" : false,

"private" : {

"keychains" : [{

"xpub" : "xpub661MyMwAqRbcFmMS3GFriiVZh7udk6yQbGM
DGogZbYb PFneMvxxPAqEXfzJnJJa8ZaJKeUax9bcoVAGTBa
z2HAqhYoDqbbBashjb owz7JDy",

"path" : "/0/0"

},

{ "xpub" : "xpub661MyMwAqRbcEYriWo2YkMbspXi7A4n7kSv6HFBmGMJMk31fKu
PsMcLWdD7nbJY391L3xi4rSPVRVanuWXutEG2T8x6Su1ZWYyMfJeEu1Cw",

"path" : "/0/0"

},

{ "xpub" : "xpub661MyMwAqRbcF9zLULZwREofGRBJe1oawABykG5yuYgvuviHnyHU
s9MaEPF28mgVovig8bNCo4HARJerLhps49EALwMwArr1yScYR4aGWde",

"path":"/0/0"

}

]},

"permissions" : "admin,spend,view",

"admin" : {

"users" : [{

"user" : "5582f55d4fe2627d67d914158d99a37c",

"permissions" : "admin,spend,view"

}]

},

"tags" : [],

"spendingAccount" : true,

"pendingApprovals" : [],

"confirmedBalance" : 0,

"balance" : 0,

"unconfirmedSends" : 0,

"unconfirmedReceives" : 0

},

"userKeychain" : {

"xpub" : "xpub661MyMwAqRbcFmMS3GFriiVZh7udk6yQbGMDGogZbYbPFneMvxx
PAqEXfzJnJJa8ZaJKeUax9bcoVAGTBaz2HAqhYoDqbbBashjbowz7JDy",

"xprv" : "xprv9s21ZrQH143K3HGxwEirMaYq9659LeFZE3RcURGx3D4QNzKDPRe8
d2v3pj4M8HekpLHeUxvUCjTRGBq7fmcRNeC3fEcLgnqYf8YNWdD1dQq",

"encryptedXprv" : "
{\"iv\":\"mfjn2Po6jDPNeVIlveI+dA
==\",\"v\":1,\"iter\":10000,\
"ks\":256,\"ts\":64,\"mode\"
:\"ccm\",\"adata\":\"\",\"cipher\"
:\"aes\",\"salt\":\"zuBLupfEbXw=\
",\"ct\":\"IGSKqOmDAR
za4hFLLRj3WZ8mCrjF8LIroWSt7q3LRm4GcRAnDvGgJV0u3+yIkpElOayeRm2
mptJtZ0bBv9+vt8DPA1UaFmvrN5Fmc0jEC8SlPW5f44HYyBBBxWWnK9Gb4Yb1
Vdvdso0 Db+i3HzH3C6lfqdBAae4=\"}"},

"backupKeychain" : {

"xpub" : "xpub661MyMwAqRbcEYriWo2YkMbspXi7A4n7kSv6HFBmGMJMk31fKu
PsMcLWdD7nbJY391L3xi4rSPVRVanuWXutEG2T8x6Su1ZWYyMfJeEu1Cw",

"xprv" : "xprv9s21ZrQH143K24nFQmVYPDf9GVsckc4GPDzVUrn9i1mNsEgW
nN5cop22muoxT1sThSGDKpuam6uj1BQYcjLkBDaViyFjahba8yVRrD87Zqg"

},

"bitgoKeychain" : {

"xpub" : "xpub661MyMwAqRbcF9zLULZwREofGRBJe1oawABykG5yuYgvuviHny
HUs9MaEPF28mgVovig8bNCo4HARJerLhps49EALwMwArr1yScYR4aGWde",

"isBitGo" : true,

"path" : "m"

},

"warning" : "Be sure to backup the backup keychain -- it is not stored anywhere else!"

}

You’ve officially created your first BitGo wallet through the API! If you log in to your BitGo account you will see a new wallet appear on the main dashboard. This wallet is fully accessible and configurable through both the website as well as the API. The next step will be to fund the wallet so that we can attempt to create a Bitcoin transaction using the wallet. You can grab your wallet address from the id: field. The one that I had created was 2N7GXBJPZQDJKbx53CwXYkrYVRLuqHJoYmA. You have two options for funding the address:

  • Tweet me at @lopp with your Testnet wallet id / Bitcoin address to receive some Testnet Bitcoin. Warning: This will take longer than the Testnet Faucet.
  • For those seeking instant gratification, enter your address in a Testnet Faucet to receive Testnet Bitcoin.

Check Balance

Let’s check our balance before proceeding to ensure that we have received some Bitcoin in the wallet. To check your balance run the following request.

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN"
http://localhost:3080/api/v1/wallet/2N7GXBJPZQDJKbx53CwXYkr
YVRLuqHJoYmA

The response will resemble the following:

{"_id" : "56315b7b39cccac6090f48f159b6eaa0",

"id" : "2N7GXBJPZQDJKbx53CwXYkrYVRLuqHJoYmA",

"label" : "My BitGo Wallet",

"isActive" : true,

"type" : "safehd",

"freeze" : {},

"adminCount" : 1,

"disableTransactionNotifications" : false,

"private" : {

"keychains" : [{

"xpub" : "xpub661MyMwAqRbcFmMS3GFriiVZh7udk6yQbGMDGogZbYb
PFneMvxxPAqEXfzJnJJa8ZaJKeUax9bcoVAGTBaz2HAqhYoDqbbBashjb
owz7JDy",

"path" : "/0/0"

},{

"xpub" : "xpub661MyMwAqRbcEYriWo2YkMbspXi7A4n7kSv6HFBmGMJMk31fK
uPsMcLWdD7nbJY391L3xi4rSPVRVanuWXutEG2T8x6Su1ZWYyMfJeEu1Cw",

"path" : "/0/0"

},{

"xpub" : "xpub661MyMwAqRbcF9zLULZwREofGRBJe1oawABykG5yuYgvuviHny
HUs9MaEPF28mgVovig8bNCo4HARJerLhps49EALwMwArr1yScYR4aGWde",

"path" : "/0/0"

}]

},

"permissions" : "admin,spend,view",

"admin" : {

"users" : [{

"user" : "5582f55d4fe2627d67d914158d99a37c",

"permissions" : "admin,spend,view"

}]

},

"tags" : [],

"spendingAccount" : true,

"pendingApprovals" : [],

"confirmedBalance" : 100000000,

"balance" : 100000000,

"unconfirmedSends" : 0,

"unconfirmedReceives" : 0

}

Down at the bottom we can see that there is a balance of 100000000 Satoshis or 1 BTC. Please ensure that you have a balance greater than 50000 Satoshis before proceeding.

Send Bitcoin

Sending Bitcoin is made easy with the BitGo Express. All you need is some identifying information for the originating wallet. As well as the destination wallet address and the amount that is to be sent.

First I need an address to send to, I just generated a new address from our root walletId. BitGo enables BIP32 HD Keys on all wallets so you can generate up to 2^32–1 children addresses per wallet Id.

curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:3080/api/v1/wallet/2N7GXBJPZQDJKbx53CwXYkr
YVRLuqHJoYmA/address/0

Your address should resemble the following:

{"address" : "2MszopwgnnoV7WLouQyQz9U9DkaEVpcTByF",

"chain" : 0,

"index" : 2,

"path" : "/0/2",

"redeemScript" : "522103173104c94359cd0997a0b53e29a6b1e796cfe1f655636b
3ce8c9f6cf597e6328210265bafb62b3d7c111b50dd78b6f133c85ff95c8
6509ac1ab7aad418facb0cf07f2102479ea91897decc12a6683d3dbe3d6
33ff4e2dacf377b16d4344b33612357062a53ae"

}

The generated address was 2MszopwgnnoV7WLouQyQz9U9DkaEVpcTByF,we’ll be using this as the receive address in our transaction.

If we send the full balance out, we will need to handle the fee calculation, so let’s send half of my balance or 0.5 BTC to this generated address.

curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN"

-d '{ "address": "2MszopwgnnoV7WLouQyQz9U9DkaEVpcTByF",

"amount": 50000000,

"walletPassphrase": "superlongpassword" }'

http://localhost:3080/api/v1/wallet/2N7GXBJPZQDJKbx53CwXYkrYVR
LuqHJoYmA/sendcoins

Your response should resemble the following:

{"status": "accepted",

"tx": "0100000001451681137f511a7a5c954b6b69baa3cacc33201c820...",

"hash": "ed8cca0e703f07df7ce7041106784dd4445c19246796d1463f77bc3f55dce6
75",

"fee": 10149,

"feeRate": 27137

}

We can see that the transaction hash can be located on a Testnet Bitcoin blockchain here.

Congratulations, you made it through the entire lifecycle of a Bitcoin transaction using BitGo Express!

We’re excited to see what you’ll build next

BitGo Express helps power and protect some of the largest Bitcoin exchanges and hedge funds around the world. We’re excited to see how Express will help power the next generation of Bitcoin apps. Let us know what you think of BitGo Express on Twitter!