I have created a fully functional Coinbase API system in PHP for my own purposes. However, there is one part of the system that I cannot get to function properly: Market Orders.
The code that appears below is a reproduction of the steps that occur in the Object Oriented system. I thought linear code would be easier to troubleshoot in this forum than digging through layers of inheritance.
The Coinbase API returns error messages as shown in the comment text at the base of the code here. The 'price' parameter is not required for the 'market' order API, which is described here: Coinbase Exchange API Documentation. When I respond to the error messages by adding the requested fields, the order eventually succeeds, but the order is processed as a 'limit' order instead of a 'market' order as indicated by the type.
Can you spot the mistake I am making?
<?php
$settings = \parse_ini_file("API.ini", true);
$apiSecret = $settings['trader_sandbox']['API Secret'];
$apiKey = $settings['trader_sandbox']['API Key'];
$apiPassPhrase = $settings['trader_sandbox']['Passphrase'];
$urlBase = "https://api-public.sandbox.exchange.coinbase.com";
//get timestamp
$date = new \DateTime("now", new \DateTimeZone("America/Los_Angeles"));
$timestamp = $date->getTimestamp();
//API url
$relUrl = "/orders";
//set the method type GET|POST|DELETE|PUT
$method = "POST";
$params = [
"type" => "market",
"side" => "sell",
"product_id" => "BTC-USD",
"stp" => "dc",
"size" => "0.10000000"
];
//copied from coinbase's documentation added apiSecret
function signature($request_path = '', $body = '', $timestamp = false, $method = 'GET', $apiSecret=null) {
/**
* Modified $body assignment to exclude empty bodies
* @author Jared Clemence <[email protected]>
* @ref https://community.coinbase.com/t/get-fills-invalid-signature-error-php-example-included/911
*/
$body = is_array($body) ? ( \count($body) > 0 ? json_encode($body) : null ) : $body;
$timestamp = $timestamp ? time() : $timestamp;
$what = $timestamp . $method . $request_path . $body;
return base64_encode(hash_hmac("sha256", $what, base64_decode($apiSecret), true));
}
$url = $urlBase . $relUrl;
$ch = curl_init($url);
$output = \json_encode($params);
$signature = \signature($relUrl, $output, $timestamp, $method, $apiSecret);
$headers = [
"User-Agent" => "Traderbot/v1.0",
"CB-ACCESS-KEY" => $apiKey,
"CB-ACCESS-SIGN" => $signature,
"CB-ACCESS-TIMESTAMP" => $timestamp,
"CB-ACCESS-PASSPHRASE" => $apiPassPhrase,
"Content-Type" => "application/json"
];
\curl_setopt($ch, CURLOPT_POST, true);
\curl_setopt($ch, CURLOPT_POSTFIELDS, $output);
foreach ($headers as $key => &$header) {
//this I found is necessary. Before I added this, the headers lacked the field data and only had the content values
$header = "{$key}:$header";
}
\curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
\curl_close($ch);
try {
$newResult = \json_decode($result);
$result = $newResult;
} catch (Exception $ex) {
}
var_dump( $result );
/**
*
* Output:
class stdClass#2 (1) {
public $message =>
string(13) "Invalid price"
}
*/
I would guess the only thing causing this to fail is lack of support currently for market orders via the Exchange API. From the docs:
Documentation for the upcoming market order feature is for reference only. The feature is not yet available. You should however update your feed handlers in preparation of the new message types.