Reputation: 266
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
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
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();
Upvotes: 2
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