2828class 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