AJT
AJT

Reputation: 266

Coinbase API returning "product not found" for valid product ID

I'm using the sandbox API at the moment, and I can query the products, including individually, but if I try and place a buy order, the response I get is { message: 'Product not found' }.

Here's my code:

async function cb_request( method, path, headers = {}, body = ''){

  var apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
      apiSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
      apiPass = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';

  //get unix time in seconds
  var timestamp = Math.floor(Date.now() / 1000);

  // set the request message
  var message = timestamp + method + path + body;

  //create a hexedecimal encoded SHA256 signature of the message
  var key = Buffer.from(apiSecret, 'base64');
  var signature = crypto.createHmac('sha256', key).update(message).digest('base64');

  //create the request options object
  var baseUrl = 'https://api-public.sandbox.pro.coinbase.com';

  headers = Object.assign({},headers,{
      'CB-ACCESS-SIGN': signature,
      'CB-ACCESS-TIMESTAMP': timestamp,
      'CB-ACCESS-KEY': apiKey,
      'CB-ACCESS-PASSPHRASE': apiPass,
      'USER-AGENT': 'request'
  });

  // Logging the headers here to ensure they're sent properly
  console.log(headers);

  var options = {
      baseUrl: baseUrl,
      url: path,
      method: method,
      headers: headers
  };

  return new Promise((resolve,reject)=>{
    request( options, function(err, response, body){
      if (err) reject(err);
      resolve(JSON.parse(response.body));
    });
  });

}

async function main() {
  
  // This queries a product by id (successfully)
  try {
     console.log( await cb_request('GET','/products/BTC-USD') );
  }
  catch(e) {
     console.log(e);
  }

  // Trying to place a buy order here (using the same id as above) returns { message: 'Product not found' }
  var buyParams = {
    'type': 'market',
    'side': 'buy',
    'funds': '100',
    'product_id': 'BTC-USD'
  };

  try {
    var buy = await cb_request('POST','/orders',buyParams);
    console.log(buy);
  }
  catch(e) {
     console.log(e);
  }

}

main();

I've tried sending the params in the body, which responds with invalid signature, even when stringified. I've also tried using the params shown in the API docs, but that responds with product not found too.

Any ideas? TIA

Upvotes: 6

Views: 2409

Answers (3)

dev_al
dev_al

Reputation: 154

It's worth mentioning that the sandbox API has different results than the production API. Consider the following CURLs.

Sandbox API:

❯ curl --request GET \
     --url https://api-public.sandbox.exchange.coinbase.com/products/ETH-USD \
     --header 'Accept: application/json'
{"message":"NotFound"}%

Production API:

❯ curl --request GET \
     --url https://api.exchange.coinbase.com/products/ETH-USD \
     --header 'Accept: application/json'
{"id":"ETH-USD","base_currency":"ETH","quote_currency":"USD","base_min_size":"0.00029","base_max_size":"2800","quote_increment":"0.01","base_increment":"0.00000001","display_name":"ETH/USD","min_market_funds":"1","max_market_funds":"4000000","margin_enabled":false,"fx_stablecoin":false,"max_slippage_percentage":"0.02000000","post_only":false,"limit_only":false,"cancel_only":false,"trading_disabled":false,"status":"online","status_message":"","auction_mode":false}%

You'll notice that the paths are identical but you get different results so keep that in mind. For testing purposes BTC-USD can be used.

Upvotes: 0

maximus
maximus

Reputation: 746

As j-petty mentioned you need to send data as request body for POST operation as described in the API documentation so this is why you get "product not found".

Here is working code based on what your shared:

   var crypto = require('crypto');
    var request = require('request');
    
    async function cb_request( method, path, headers = {}, body = ''){
    
      var apiKey = 'xxxxxx',
          apiSecret = 'xxxxxxx',
          apiPass = 'xxxxxxx';
    
      //get unix time in seconds
      var timestamp = Math.floor(Date.now() / 1000);
    
      // set the request message
      var message = timestamp + method + path + body;
      console.log('######## message=' + message);
    
      //create a hexedecimal encoded SHA256 signature of the message
      var key = Buffer.from(apiSecret, 'base64');
      var signature = crypto.createHmac('sha256', key).update(message).digest('base64');
    
      //create the request options object
      var baseUrl = 'https://api-public.sandbox.pro.coinbase.com';
    
      headers = Object.assign({},headers,{
        'content-type': 'application/json; charset=UTF-8',
          'CB-ACCESS-SIGN': signature,
          'CB-ACCESS-TIMESTAMP': timestamp,
          'CB-ACCESS-KEY': apiKey,
          'CB-ACCESS-PASSPHRASE': apiPass,
          'USER-AGENT': 'request'
      });
    
      // Logging the headers here to ensure they're sent properly
      console.log(headers);
    
      var options = {
          'baseUrl': baseUrl,
          'url': path,
          'method': method,
          'headers': headers,
          'body': body
    
      };
    
      return new Promise((resolve,reject)=>{
        request( options, function(err, response, body){
          console.log(response.statusCode + "  " + response.statusMessage);
          if (err) reject(err);
          resolve(JSON.parse(response.body));
        });
      });
    
    }
    
    async function main() {
      
      // This queries a product by id (successfully)
      try {
        console.log('try to call product------->');
         console.log( await cb_request('GET','/products/BTC-USD') );
         console.log('product------------------->done');
      }
      catch(e) {
         console.log(e);
      }
    
      var buyParams = JSON.stringify({
        'type': 'market',
        'side': 'buy',
        'funds': '10',
        'product_id': 'BTC-USD'
      });
    
      try {
        console.log('try to call orders------->');
        var buy = await cb_request('POST','/orders', {}, buyParams);
        console.log(buy);
        console.log('orders----------------------->done');
    
      }
      catch(e) {
         console.log(e);
      }
    
    }
    
    main();

enter image description here

Upvotes: 2

j-petty
j-petty

Reputation: 3026

You need to send a POST request to the /orders endpoint and include the body in the request payload.

There are some example answers in this question.

var options = {
    baseUrl: baseUrl,
    url: path,
    method: method,
    headers: headers
    json: true,
    body: body
}

request.post(options, function(err, response, body){
  if (err) reject(err);
  resolve(JSON.parse(response.body));
});

Upvotes: 0

Related Questions