Search code examples
google-apps-scriptgoogle-sheetscoinbase-api

Coinbase v2 with Google Sheets


I'm trying to use the Coinbase API v2 (NOT PRO) to simply pull the contents of my wallet in to my spreadsheet. I have the following:

    var url = 'https://api.coinbase.com/v2';
    var requestPath = '/accounts';
    var api_key = '********';
    var secret_key = '********';
    // var timestamp = new Date().getTime().toString().slice(0, -3);
    var timestamp = Math.floor(Date.now() / 1000).toString();
    var method = 'GET';

    var message = Utilities.base64Decode(Utilities.base64Encode(timestamp + method + requestPath));
    var decoded_secret = Utilities.base64Decode(secret_key);
    var signature = Utilities.base64Encode(Utilities.computeHmacSha256Signature(message, decoded_secret));
    
    //previous attempt
    /* var signature = Utilities.computeHmacSha256Signature(message, decoded_secret);
    signature = signature.map(function(e) {
      var v = (e < 0 ? e + 256 : e).toString(16);
      return v.length == 1 ? "0" + v : v;
    }).join("");*/

    var params = {
      'method': method,
      'headers': {
        'Content-Type':        'application/json',
        'CB-ACCESS-SIGN':      signature,
        'CB-ACCESS-TIMESTAMP': timestamp,
        'CB-ACCESS-KEY':       api_key,
        'CB-VERSION':          '2021-02-03'
      }
    };
    Logger.log(params);
    var res = await UrlFetchApp.fetch(url + requestPath, params);

Unfortunately I am getting the invalid signature error. I feel like I'm close. It could be that I don't have the url/request path going in to the signature correctly.


Solution

  • Creating a Coinbase signature with Apps Script is a bit tricky

    As you can see from the documentation for Coinbase API, in Python the signature is built with signature = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest().

    In other words, the signature needs to be hex-encoded.

    There is no 1:1 equivalent to hexdigest() in Apps Script, but you can build it manually.

    This works for me:

      var message = (timestamp + method +  requestPath + body);  
      var byteSignature = Utilities.computeHmacSha256Signature(message, secret);
      var signature = byteSignature.reduce(function(str,chr){
        chr = (chr < 0 ? chr + 256 : chr).toString(16);
        return str + (chr.length==1?'0':'') + chr;
      },'');  
    

    Thereby secret is your credential provided by Coinbase - no need to decode it.