You are on page 1of 12

coinbase

The Coinbase API for Node.js


The official Node.js library for the Coinbase API.

Features
Full Test coverage.
Support for both API Key + Secret and OAuth 2 authentication.
Convenient methods for making calls to the API.
Automatic parsing of API responses into relevant Javascript objects.
Adheres to the nodejs error-first callback protocol.
Continuous Integration testing against node 0.10, 0.11, and 0.12.

Installation
npm install coinbase

Version Compatibility
Version GitHub repository
1.0.x
This repository
0.1.x
mateodelnorte/coinbase
Npm coinbase package name used to refer to the unofficial coinbase library
maintained by Matt Walters. Matt graciously allowed us to use the name for
this package instead. You can still find that package on Github. Thanks, Matt.

Quick Start
The first thing you'll need to do is sign up for coinbase.

API Key + Secret


If you're writing code for your own Coinbase account, enable an API key. Next,
create a Client object for interacting with the API:
var Client = require('coinbase').Client;
var client = new Client({'apiKey': mykey, 'apiSecret': mysecret});

OAuth2
If you're writing code that will act on behalf of another user, start by creating a
new OAuth 2 application. You will need to do some work to obtain OAuth
credentials for your users; while outside the scope of this document, please
refer to our OAuth 2 tutorial and documentation. Once you have these
credentials, create a client:
var Client = require('coinbase').Client;
var client = new Client({

'apiKey'
'apiSecret'

: mykey,
: mysecret,

'accessToken' : accessToken,
'refreshToken' : refreshToken
});

Making API Calls


With a client instance, you can now make API calls. We've included some
examples below, but in general the library has Javascript prototypes for each of
the objects described in our REST API documentation. These classes each have
methods for making the relevant API calls; for instance,
coinbase.model.Transaction.complete maps to the complete bitcoin request API
endpoint. The comments of each method in the code references the endpoint it
implements. Each API method returns an object representing the JSON
response from the API.
Listing available accounts
var coinbase = require('coinbase');
var client = new coinbase.Client({'apiKey': mykey, 'apiSecret': mysecret});
client.getAccounts(function(err, accounts) {
accounts.forEach(function(acct) {
console.log('my bal: ' + acct.balance.amount + ' for ' + acct.name);
});
});
Get Balance from an Account Id
var Account = require('coinbase').model.Account;
var myBtcAcct = new Account(client, {'id': '<SOME_ACCOUNT_ID>'});
myBtcAcct.getBalance(function(err, bal) {
console.log('bal: ' + bal.amount + ' currency: ' + bal.currency);
});
Selling bitcoin
var args = {
"qty": "12"
};
account.sell(args, function(err, xfer) {
console.log('my xfer id is: ' + xfer.id);

});
Sending bitcoin
var args = {
"to": "user1@example.com",
"amount": "1.234",
"notes": "Sample transaction for you"
};
account.sendMoney(args, function(err, txn) {
console.log('my txn id is: ' + txn.id);
});
Requesting bitcoin
var args = {
"from": "user1@example.com",
"amount": "1.234",
"notes": "Sample transaction for you"
};
account.requestMoney(args, function(err, txn) {
console.log('my txn id is: ' + txn.id);
});
Listing current transactions
account.getTransactions(null, null, function(err, txns) {
txns.forEach(function(txn) {
console.log('my txn status: ' + txn.status);
});
});
Checking bitcoin prices
client.getBuyPrice({'qty': 100, 'currency': 'USD'}, function(err, obj) {
console.log('total amount: ' + obj.total.amount);
});

Error Handling
Errors are thrown for invalid arguments but are otherwise returned as the first
argument to callback functions.
Errors contain type properties so that you can route the error to the right
handler code. The possible types are:
Type
Description
AuthenticationError
returned if there was an authentication error

Type

Description
returned when the current access token is no longer
InvalidAccessToken
valid
ExpiredAccessToken
returned when the current access token is expired
returned when there is a failure refreshing the access
TokenRefreshError
token
returned when a user's Two Factor Auth token needs
TwoFactorTokenRequired
to be included in the request
returned for errors related to interacting with the
APIError
Coinbase API server
acct.getBalance(function(err, bal) {
switch (err.type) {
case 'ExpiredAccessToken':
// use the client.refresh API to get a new access_token
break;
case 'InvalidAccessToken':
//handle error
break;
case 'AuthenticationError':
//handle error
break;
}
});
Errors are always of the type Error and can print a trace:
acct.getBalance(function(err, bal) {
if (err) console.log('Where did this error come from?\n' + err.stack);
});
Errors that are related to an http request will have a response field with the
entire http response:
acct.getBalance(function(err, bal) {
if (err) console.log('http error code: ' + err.response.statusCode);
});

Testing / Contributing
Any and all contributions are welcome! The process is simple:
1. Fork this repo
2. Make your changes and add tests
3. Run the test suite
4. Submit a pull request.
Tests are run via mocha and nock. To run the tests, clone the repository and
then:

npm install
npm test
You can also run the tests against various node environments using the
Dockerfile.example file.
1. cp Dockerfile.example Dockerfile
2. edit Dockerfile and uncomment the node version that interests you
3. [sudo] docker build -t coinbase-node .
4. [sudo] docker run -it coinbase-node

More Documentation
You can generate html documentation by running the command:
npm install && npm run docs
Open generated html files in docs/ dir with a browser.

Making Bitcoin Paywall Middleware


Today's comic doesn't include a lot of built-in technology like Wednesday's did. Just a moth joke.
Or was that just a mistake? I'm not sure. Moving on...
Wednesday's comic had a Bitcoin paywall, and in Wednesday's blog I explained how I
processed a 402 response in the client to make it work. But the server played more than a bit
part in the whole operation. Get it? Bit part. Bitcoin. Moving on...

It's like regular money, but with more math.

To handle the Bitcoin payments and unlock the content, there are several pieces at work. I am
using the Express framework for my web application, so I have a middleware applied to each
non-free resource. There is also a Bitcoin address generator to create new payment addresses.
Another resource serves as the payment notification - when payment is made to an address, this
resource receives data about the transaction. Finally, there is a datastore that manages the
records to keep all the other pieces in sync.
This is how it works:
First, a resource is requested which requires payment. The middleware checks with
the datastore to see if the requesting client has an existing record for this resource.
If no existing record is found, it means the client has never attempted to access this
resource before. The middleware uses the address generator to create a new
payment address record and gives it to the datastore. The client is returned the 402

response along with the special payment instruction headers.


Alternatively, the datastore might find a record for this resource and client. That
means the client has been here before. The record returned by the datastore will
indicate whether or not the payment is complete. If the payment has been made, the
middleware allows normal access. If payment has not been made, the middleware
returns the 402 response to the client with the special payment instruction headers.
The data for those headers comes out of the payment record.
At any time, an external Bitcoin processing system can determine that payment has
been made to one of the addresses generated by the address generator. It sends
data on the payment transaction to the payment callback resource which looks up the
record in the datastore and marks it as paid.

I used the Coinbase Merchant API as the external Bitcoin processing system. When I create
addresses with Coinbase, I can specify a callback URL for each one and Coinbase will POST
some data to it when payment is made. Each address gets a unique URL so my system can look
up the payment record that matches it. I am using the official Coinbase Node module in my app.
Here is a basic outline of the app:
var express = require("express");
var app = express();
// mock purchase record
var demoRecord = {
recordId: "12345",
code: "product-code",
paid: false,
cost: 123.45,
address: "bitcoinaddress",
secret: "itsasecret"
};
// mock datastore object
var datastore = {
findRecord: function(req, productCode, callback) {
callback("12345");
},
checkPaidStatus: function(recordId, callback) {
callback(demoRecord);
},
newRecord: function(data) {
// store the record
},
findRecordBySecret: function(secret, callback) {

if (secret === demoRecord.secret) {


callback(demoRecord);
} else {
callback(null);
}
}
};
function newBitcoinAddress(productCode, callback) {
callback(null, demoRecord);
}
function send402(res, data) {
res.setHeader("X-Payment-Types-Accepted", "Bitcoin");
res.setHeader("X-Payment-Address-Bitcoin", data.address);
res.setHeader("X-Payment-Amount-Bitcoin", data.cost);
res.sendStatus(402);
}
function paywallMiddleware(req, res, next) {
// let's use the URL as the product code,
// since that's really what is being sold
var productCode = req.path;
datastore.findRecord(req, productCode, function(recordId) {
if (recordId) {
// found a record, which means that this client
// has a payment address and purchase record already.
// now check to see if it has been paid.
datastore.checkPaidStatus(recordId, function(data) {
if (data.paid) {
next(); // all paid, move along...
} else {
// respond with the payment address that already exists
send402(res, data);
}
});
} else {
// no record found, which means a new Bitcoin

// address and purchase record must be created.


newBitcoinAddress(productCode, function(err, data) {
if (err) {
next(err);
} else {
datastore.newRecord(data);
send402(res, data);
}
});
}
});
}
app.get("/free", function(req, res, next) {
res.send("free content");
});
app.get("/paid", paywallMiddleware, function(req, res, next) {
res.send("paid content");
});
app.get("/callback", function(req, res, next) {
var secretCode = req.query.secret;
datastore.findRecordBySecret(secretCode, function(record) {
if (record) {
record.paid = true;
}
});
res.sendStatus(200);
});
// ------------ start listening
var server = app.listen(3000, function() {
console.log("listening on port %d", server.address().port);
});
That looks like a lot of code, but it's not really that complicated. Near the top, you see I have
some mock objects for the demo. In a real scenario, your datastore object would access an
RDBMS or the file system to store and retrieve actual purchase records. Here, though, a single
fake record and some stub functions will suffice. The newBitcoinAddress function is also a stub in the real app, this is where I use the Coinbase API to create addresses and associated
purchase records each with their own unique secret code as part of the callback URL. That

secret code should never be returned to the user, but needs to be stored so the record can be
retrieved later in the callback handler. The send402 function is just a utility function that sets the
special response headers and sends the 402 code.
The paywallMiddleware function is the implementation of the algorithm I described above. It uses
the mock datastore and address generation function.
The routes at the bottom allow testing the system. Launch the app and point your browser
tohttp://localhost:3000/free. You should get the free content. Now try
http://localhost:3000/paid . You should get a 402 response. This is because the /paid route
includes the paywallMiddleware. To get access, you'll need to pay.
This demo doesn't require any real Bitcoin transactions to take place. To simulate the callback
coming from Coinbase, I included a /callback route that is a GET, which makes it easy to test
from your browser. In real life, this will be a POST. To simulate sending payment to the address,
you just have to go to http://localhost:3000/callback?secret=itsasecret. When you do, you
should get a simple OK response...but on the server side, the demo record was updated to paid
because the secret code matched. Now you can go back to http://localhost:3000/paid and get
the paid content. If you had used a different (incorrect) value for secret, the /paid resource would
not have been unlocked.
Next week I'll go into a little more detail about how I use the Coinbase API. My hope is that
someday more content creators such as myself can use functions like this for micropayments in
place of running advertisements on their sites.
But that's just a dream right now. How long will it take to become reality? A few moths? I mean,
months?

Using HTTP 402 for a Bitcoin Paywall

Bitcoin. Perfect for Microtransactions?

The punchline for today's comic is hidden behind a paywall. It is a literal wall, built by the frogs to
hide the last frame of the comic. However, if you have some Bitcoin to spare (it costs 0.001
coins, about $0.25 US at the present time) you can actually pay for the wall to be removed.
A fair amount of interesting work went in to this comic, but it all revolves around the concept of

using the HTTP 402 response code.


Response code 402 is officially "reserved for future use" but I felt that it was about time the future
showed up. It's 2015. Where is my moon colony?? Anyway, 402 means "Payment Required" and
was apparently intended to be a way for web servers to indicate to clients that the requested
resource had to be purchased. Unfortunately, a way to pay for those resources was never
worked out and the response code has languished in the realm of TBD for many years.
But these days we have Ajax, REST web services, and Bitcoin. It's all coming together. People
have kicked around the notion of integrating 402's with Bitcoin transactions for a few years now
but no significant implementation has emerged. With today's comic, sadly, nothing has changed.
I did, however, create a functional web content paywall for Bitcoin microtransactions. Here's how
it works...
When a client - be it a human-operated web browser or another computer program - accesses a
URL which does not dispense free content, the server will return a 402 response instead of the
content. That response also includes three special headers, examples of which are shown here:
X-Payment-Types-Accepted: Bitcoin
X-Payment-Address-Bitcoin: putarealbitcoinaddresshere
X-Payment-Amount-Bitcoin: 1.234

The first, X-Payment-Types-Accepted, should be a comma-separated list of acceptable


payment types. In my example and in my comic I am only accepting Bitcoin for now, although a
similar form of payment such as Litecoin would easily be possible in place of or in addition to
Bitcoin. Each item listed in this header should be used to check the other 2 headers. The XPayment-Address-XXXheader specifies an address to which the payment should be sent. The
X-Payment-Amount-XXXheader specifies how much this particular resource costs.
The key is that the last part of the address and amount headers should match an item in the list
of types accepted. If I wanted to accept either Bitcoin or Litecoin, my headers might look like this:
X-Payment-Types-Accepted: Bitcoin, Litecoin
X-Payment-Address-Bitcoin: putarealbitcoinaddresshere
X-Payment-Amount-Bitcoin: 1.234
X-Payment-Address-Litecoin: putareallitecoinaddresshere
X-Payment-Amount-Litecoin: 2.345

It's then up to the client to deal with this response. Today, browsers will silently ignore this extra

information and just tell you that the response code means "Payment Required" without letting
you know how to pay. In the future, browsers might prompt you to submit the payment (see this:
Zero Click Bitcoin Micropayments). Today, though, you have to do things manually.
In certain cases, the server could include the Bitcoin address and price in the HTML that
accompanies the 402 response. Since I am just requesting the paid resources via Ajax, I didn't
bother with that and don't include anything human-readable in the response. Here is how my
client-side code works when you view the comic:

function checkForPayment() {
$.ajax({
url: "/paidContent/paywall-comic",
dataType: "html",
success: function(data) {
$('#comicArea').html(data);
},
error: function(xhr, respText, et) {
if (xhr.status === 402) {
var addr = xhr.getResponseHeader("X-Payment-AddressBitcoin");

var cost = xhr.getResponseHeader("X-Payment-Amount-

Bitcoin");
var bcqr = encodeURIComponent("bitcoin:" + addr + "?
amount=" + cost);
if ($("#paydiv").html() === "") {
$("#paydiv").html("<p>Pay with Bitcoin!<br>" +
"<img src='/qrc?text=" + bcqr +
"'><br>" +

"Send " + cost + " BTC to<br>" +


addr + "</p>");
}
setTimeout(checkForPayment, 2000);
} else {
console.log("failed");
}

}
});

}
When the free version (missing the last frame) of the comic loads, checkForPayment() is called
and attempts to get the data for the complete comic from the URL /paidContent/paywall-comic.
Anything on my site with a path starting with /paidContent/ will require purchasing. On a
successful response, which you'll only get if you've paid, the unpaid version of the comic is
replaced with the data from the server.
The interesting part is the error response handling on line 11. A 402 response is an error
because it is in the 400 range - indicating a client-side error. It's not a very serious error - just
asking for something for which you have not paid! I am using jQuery so the first parameter
passed to the error handler function is the jqXHR object. There are many things you can do with
that object, but I only need to check the response status to see if it is a 402, and if so I read the
values of the X-Payment-Address-Bitcoin and X-Payment-Amount-Bitcoin headers. Yes, I
am ignoring my own X-Payment-Types-Accepted header because I happen to know that it
only contains Bitcoin (that's the only kind of coin I have right now). If I expected other types, the
right thing to do would be to read the X-Payment-Types-Accepted header and loop over the list
of values to get the names of the other headers.
I take the address and price and submit them to my QR Code image generation URL to make an
easy, scannable way to pay - but also just display the address and price to the user. Again, I'm
doing this on the client side because I'm requesting the data with Ajax. If the user navigated
directly to a URL which required payment, the server could have responded with that HTML as
part of the 402 page, much in the same way servers respond with custom (and sometimes
helpful) 404 pages today.
The last part is to check the /paidContent/paywall-comic URL again to see if a payment has gone
through. Since it can be a few seconds before Coinbase tells my server that payment has been
sent to the address, I took the quick and dirty route of setting a timeout and running the
wholecheckForPayment() function again. I could have connected a Websocket to wait for
payment confirmation from the server if I wanted to get fancy - a website that was expected to
get more traffic than my comic would probably want to go that route instead. A possible future
enhancement would be to include an additional header with a recommendation for the client specifying if it should refresh, wait, redirect so some other URL, etc.
In the future, I might put more special features on Amphibian.com on the /paidContent/ URL,
instead of it just being part of the joke. Maybe special comics that you can only access by paying
a few cents? I'm not sure yet, but I tried to develop a framework that robust enough to support
future expansion. At this point, I can easily make the server request payment for anything thanks
to the Express middleware that I wrote combined with the Coinbase Node module. But that's too
much for a single blog post so I'll talk about that on Friday!
I also hope that more web sites adopt and expand on this model now that I have it working in a
semi-legitimate application. In my opinion, it beats displaying ads for enabling content creators to
monetize. You can help me monetize by paying to get the whole comic today!

You might also like