2

I'm working with the Coinbase Pro API and while it's working well for GET requests I'm getting an "Invalid signature" when I try a POST request to place an order. I suspect that this may be something related to the "body" of the message since this is the only difference with the GET where "body" is empty.

I'm wondering if someone can help me on this.

function SellMarket (product,amount) {
  var requestPath = '/orders';
  var method = 'POST';
  var body = JSON.stringify({
    "type": "market",
    "side": "buy",
    "product_id": product,
    //"size": amount,
    'size': '1.0'
  });
  
  Logger.log('Sell - Body = '+body); 

  var responseJson = SignAndCallAPI(method, requestPath, body);
  Logger.log('Sell Executed = '+responseJson); 
}  


function SignAndCallAPI(method, requestPath, body) {

  var timestamp = Math.floor(Date.now() / 1000).toString();
  var what = Utilities.base64Decode(Utilities.base64Encode(timestamp + method + requestPath + body));
  var decodedsecret = Utilities.base64Decode(globalvars_CB.secret);
  
  var hmac = Utilities.base64Encode(Utilities.computeHmacSha256Signature(what, decodedsecret));
     
  var options = {
    'method' : method,
    'muteHttpExceptions' : true,     
    'headers' : {
      'Content-Type': 'application/json',
      'CB-ACCESS-KEY' : globalvars_CB.apikey,
      'CB-ACCESS-SIGN' : hmac,
      'CB-ACCESS-TIMESTAMP' : timestamp,
      'CB-ACCESS-PASSPHRASE' :  globalvars_CB.passphrase,
     }
  }  
      
  var responseJson = UrlFetchApp.fetch(globalvars_CB.uri+requestPath, options);
  
  return(responseJson);  

}
  • If [your previous question](https://stackoverflow.com/q/63575840/7108653), had been resolved, I think that the authorization script of your this script is correct. In this case, can you confirm whether each value of `body` is correct, again? – Tanaike Sep 06 '20 at 00:59
  • Thanks @Tanaike. Yes, I think that all the values in body are correct but still not working :-( – Albert Sampietro Sep 06 '20 at 06:59
  • Thank you for replying. I apologize that my comment was not useful for your situation. – Tanaike Sep 06 '20 at 07:46
  • @AlbertSampietro could you update the code to the working version. I'm running into the same error. Thanks – Lenny Cunningham Feb 20 '21 at 13:23

1 Answers1

2

Untested suggestion, I recommend changing this bit in your code (in SignAndCallAPI function):

var options = {
  'method' : method,
  'muteHttpExceptions' : true,     
  'headers' : {
    'Content-Type': 'application/json',
    'CB-ACCESS-KEY' : globalvars_CB.apikey,
    'CB-ACCESS-SIGN' : hmac,
    'CB-ACCESS-TIMESTAMP' : timestamp,
    'CB-ACCESS-PASSPHRASE' :  globalvars_CB.passphrase,
  }
}

to:

const options = {
  method: method,
  payload: body,
  contentType: 'application/json',
  muteHttpExceptions: true,     
  headers: {
    'CB-ACCESS-KEY': globalvars_CB.apikey,
    'CB-ACCESS-SIGN': hmac,
    'CB-ACCESS-TIMESTAMP': timestamp,
    'CB-ACCESS-PASSPHRASE':  globalvars_CB.passphrase,
  },
}; 

due to the reasons below:

  1. Although you pass body to SignAndCallAPI function and use body in HMAC computation, you don't appear to actually include body in the POST request sent to the server. I was expecting to see it as the value to a payload property of your options object.

  2. UrlFetchApp documentation (https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl,-params) seems to indicate that Content-Type should be specified in the contentType property of your options object (as opposed to explicitly including a Content-Type header).

  3. I've not looked at the Coinbase API documentation in detail (https://docs.pro.coinbase.com/#place-a-new-order), but body seems okay. You'll also want to make sure the HMAC computation for the CB-ACCESS-SIGN request header is as described in the documentation (https://docs.pro.coinbase.com/#signing-a-message).

chillin
  • 4,391
  • 1
  • 8
  • 8