Skip to content

Commit 537fd7b

Browse files
robsantinidmzoneill
authored andcommitted
Add support for testnet
1 parent 44944f9 commit 537fd7b

1 file changed

Lines changed: 40 additions & 13 deletions

File tree

php-binance-api.php

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@
2828
class API
2929
{
3030
protected $base = 'https://api.binance.com/api/'; // /< REST endpoint for the currency exchange
31+
protected $baseTestnet = 'https://testnet.binance.vision/api/'; // /< Testnet REST endpoint for the currency exchange
3132
protected $wapi = 'https://api.binance.com/wapi/'; // /< REST endpoint for the withdrawals
3233
protected $sapi = 'https://api.binance.com/sapi/'; // /< REST endpoint for the supporting network API
3334
protected $stream = 'wss://stream.binance.com:9443/ws/'; // /< Endpoint for establishing websocket connections
35+
protected $streamTestnet = 'wss://testnet.binance.vision/ws/'; // /< Testnet endpoint for establishing websocket connections
3436
protected $api_key; // /< API key that you created in the binance website member area
3537
protected $api_secret; // /< API secret that was given to you when you created the api key
38+
protected $useTestnet = false; // /< Enable/disable testnet (https://testnet.binance.vision/)
3639
protected $depthCache = []; // /< Websockets depth cache
3740
protected $depthQueue = []; // /< Websockets depth queue
3841
protected $chartQueue = []; // /< Websockets chart queue
@@ -65,6 +68,7 @@ class API
6568
* No arguments - use file setup
6669
* 1 argument - file to load config from
6770
* 2 arguments - api key and api secret
71+
* 3 arguments - api key, api secret and use testnet flag
6872
*
6973
* @return null
7074
*/
@@ -86,6 +90,11 @@ public function __construct()
8690
$this->api_key = $param[0];
8791
$this->api_secret = $param[1];
8892
break;
93+
case 3:
94+
$this->api_key = $param[0];
95+
$this->api_secret = $param[1];
96+
$this->useTestnet = (bool)$param[2];
97+
break;
8998
default:
9099
echo 'Please see valid constructors here: https://github.com/jaggedsoft/php-binance-api/blob/master/examples/constructor.php';
91100
}
@@ -139,6 +148,7 @@ protected function setupApiConfigFromFile(string $file = null)
139148
$contents = json_decode(file_get_contents($file), true);
140149
$this->api_key = isset($contents['api-key']) ? $contents['api-key'] : "";
141150
$this->api_secret = isset($contents['api-secret']) ? $contents['api-secret'] : "";
151+
$this->useTestnet = isset($contents['use-testnet']) ? (bool)$contents['use-testnet'] : false;
142152
}
143153

144154
/**
@@ -937,7 +947,7 @@ public function balances($priceData = false)
937947

938948
/**
939949
* coins get list coins
940-
*
950+
*
941951
* $coins = $api->coins();
942952
* @return array with error message or array containing coins
943953
* @throws \Exception
@@ -1052,15 +1062,21 @@ protected function httpRequest(string $url, string $method = "GET", array $param
10521062
throw new \Exception("signedRequest error: API Secret not set!");
10531063
}
10541064

1055-
$base = $this->base;
1065+
$base = $this->getRestEndpoint();
10561066
$ts = (microtime(true) * 1000) + $this->info['timeOffset'];
10571067
$params['timestamp'] = number_format($ts, 0, '.', '');
10581068
if (isset($params['wapi'])) {
1069+
if ($this->useTestnet) {
1070+
throw new \Exception("wapi endpoints are not available in testnet");
1071+
}
10591072
unset($params['wapi']);
10601073
$base = $this->wapi;
10611074
}
10621075

10631076
if (isset($params['sapi'])) {
1077+
if ($this->useTestnet) {
1078+
throw new \Exception("sapi endpoints are not available in testnet");
1079+
}
10641080
unset($params['sapi']);
10651081
$base = $this->sapi;
10661082
}
@@ -1082,11 +1098,11 @@ protected function httpRequest(string $url, string $method = "GET", array $param
10821098
}
10831099
// params so buildquery string and append to url
10841100
else if (count($params) > 0) {
1085-
curl_setopt($curl, CURLOPT_URL, $this->base . $url . '?' . $query);
1101+
curl_setopt($curl, CURLOPT_URL, $this->getRestEndpoint() . $url . '?' . $query);
10861102
}
10871103
// no params so just the base url
10881104
else {
1089-
curl_setopt($curl, CURLOPT_URL, $this->base . $url);
1105+
curl_setopt($curl, CURLOPT_URL, $this->getRestEndpoint() . $url);
10901106
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
10911107
'X-MBX-APIKEY: ' . $this->api_key,
10921108
));
@@ -1949,7 +1965,7 @@ public function depthCache($symbols, callable $callback)
19491965
$endpoint = strtolower($symbol) . '@depthCache';
19501966
$this->subscriptions[$endpoint] = true;
19511967

1952-
$connector($this->stream . strtolower($symbol) . '@depth')->then(function ($ws) use ($callback, $symbol, $loop, $endpoint) {
1968+
$connector($this->getWsEndpoint() . strtolower($symbol) . '@depth')->then(function ($ws) use ($callback, $symbol, $loop, $endpoint) {
19531969
$ws->on('message', function ($data) use ($ws, $callback, $loop, $endpoint) {
19541970
if ($this->subscriptions[$endpoint] === false) {
19551971
//$this->subscriptions[$endpoint] = null;
@@ -2019,7 +2035,7 @@ public function trades($symbols, callable $callback)
20192035
$endpoint = strtolower($symbol) . '@trades';
20202036
$this->subscriptions[$endpoint] = true;
20212037

2022-
$connector($this->stream . strtolower($symbol) . '@aggTrade')->then(function ($ws) use ($callback, $symbol, $loop, $endpoint) {
2038+
$connector($this->getWsEndpoint() . strtolower($symbol) . '@aggTrade')->then(function ($ws) use ($callback, $symbol, $loop, $endpoint) {
20232039
$ws->on('message', function ($data) use ($ws, $callback, $loop, $endpoint) {
20242040
if ($this->subscriptions[$endpoint] === false) {
20252041
//$this->subscriptions[$endpoint] = null;
@@ -2073,7 +2089,7 @@ public function ticker($symbol, callable $callback)
20732089

20742090
// @codeCoverageIgnoreStart
20752091
// phpunit can't cover async function
2076-
\Ratchet\Client\connect($this->stream . $endpoint)->then(function ($ws) use ($callback, $symbol, $endpoint) {
2092+
\Ratchet\Client\connect($this->getWsEndpoint() . $endpoint)->then(function ($ws) use ($callback, $symbol, $endpoint) {
20772093
$ws->on('message', function ($data) use ($ws, $callback, $symbol, $endpoint) {
20782094
if ($this->subscriptions[$endpoint] === false) {
20792095
//$this->subscriptions[$endpoint] = null;
@@ -2150,7 +2166,7 @@ public function chart($symbols, string $interval = "30m", callable $callback, $l
21502166
$this->info[$symbol][$interval]['firstOpen'] = 0;
21512167
$endpoint = strtolower($symbol) . '@kline_' . $interval;
21522168
$this->subscriptions[$endpoint] = true;
2153-
$connector($this->stream . $endpoint)->then(function ($ws) use ($callback, $symbol, $loop, $endpoint, $interval) {
2169+
$connector($this->getWsEndpoint() . $endpoint)->then(function ($ws) use ($callback, $symbol, $loop, $endpoint, $interval) {
21542170
$ws->on('message', function ($data) use ($ws, $loop, $callback, $endpoint) {
21552171
if ($this->subscriptions[$endpoint] === false) {
21562172
//$this->subscriptions[$endpoint] = null;
@@ -2212,7 +2228,7 @@ public function kline($symbols, string $interval = "30m", callable $callback)
22122228
foreach ($symbols as $symbol) {
22132229
$endpoint = strtolower($symbol) . '@kline_' . $interval;
22142230
$this->subscriptions[$endpoint] = true;
2215-
$connector($this->stream . $endpoint)->then(function ($ws) use ($callback, $symbol, $loop, $endpoint, $interval) {
2231+
$connector($this->getWsEndpoint() . $endpoint)->then(function ($ws) use ($callback, $symbol, $loop, $endpoint, $interval) {
22162232
$ws->on('message', function ($data) use ($ws, $loop, $callback, $endpoint) {
22172233
if ($this->subscriptions[$endpoint] === false) {
22182234
$loop->stop();
@@ -2324,7 +2340,7 @@ public function userData(&$balance_callback, &$execution_callback = false)
23242340

23252341
// @codeCoverageIgnoreStart
23262342
// phpunit can't cover async function
2327-
$connector($this->stream . $this->listenKey)->then(function ($ws) {
2343+
$connector($this->getWsEndpoint() . $this->listenKey)->then(function ($ws) {
23282344
$ws->on('message', function ($data) use ($ws) {
23292345
if ($this->subscriptions['@userdata'] === false) {
23302346
//$this->subscriptions[$endpoint] = null;
@@ -2372,7 +2388,7 @@ public function miniTicker(callable $callback)
23722388

23732389
// @codeCoverageIgnoreStart
23742390
// phpunit can't cover async function
2375-
\Ratchet\Client\connect($this->stream . '!miniTicker@arr')->then(function ($ws) use ($callback, $endpoint) {
2391+
\Ratchet\Client\connect($this->getWsEndpoint() . '!miniTicker@arr')->then(function ($ws) use ($callback, $endpoint) {
23762392
$ws->on('message', function ($data) use ($ws, $callback, $endpoint) {
23772393
if ($this->subscriptions[$endpoint] === false) {
23782394
//$this->subscriptions[$endpoint] = null;
@@ -2423,7 +2439,7 @@ public function bookTicker(callable $callback)
24232439

24242440
// @codeCoverageIgnoreStart
24252441
// phpunit can't cover async function
2426-
\Ratchet\Client\connect($this->stream . '!bookTicker')->then(function ($ws) use ($callback, $endpoint) {
2442+
\Ratchet\Client\connect($this->getWsEndpoint() . '!bookTicker')->then(function ($ws) use ($callback, $endpoint) {
24272443
$ws->on('message', function ($data) use ($ws, $callback, $endpoint) {
24282444
if ($this->subscriptions[$endpoint] === false) {
24292445
//$this->subscriptions[$endpoint] = null;
@@ -2523,5 +2539,16 @@ public function getXMbxUsedWeight () : int {
25232539
public function getXMbxUsedWeight1m () : int {
25242540
$this->xMbxUsedWeight1m;
25252541
}
2526-
2542+
2543+
private function getRestEndpoint() : string {
2544+
return $this->useTestnet ? $this->baseTestnet : $this->base;
2545+
}
2546+
2547+
private function getWsEndpoint() : string {
2548+
return $this->useTestnet ? $this->streamTestnet : $this->stream;
2549+
}
2550+
2551+
public function isOnTestnet() : bool {
2552+
return $this->useTestnet;
2553+
}
25272554
}

0 commit comments

Comments
 (0)