1 | <?php |
||
2 | |||
3 | namespace sabramooz\binance; |
||
4 | |||
5 | use Exception; |
||
6 | |||
7 | class BinanceAPI |
||
8 | { |
||
9 | protected $key; // API key |
||
10 | protected $secret; // API secret |
||
11 | protected $url; // API base URL |
||
12 | protected $recvWindow; // API base URL |
||
13 | protected $version; // API version |
||
14 | protected $curl; // curl handle |
||
15 | |||
16 | /** |
||
17 | * Constructor for BinanceAPI |
||
18 | */ |
||
19 | function __construct() |
||
20 | { |
||
21 | $this->key = config('binance.auth.key'); |
||
22 | $this->secret = config('binance.auth.secret'); |
||
23 | $this->url = config('binance.urls.api'); |
||
24 | $this->wapi_url = config('binance.urls.wapi'); |
||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
25 | $this->recvWindow = config('binance.settings.timing'); |
||
26 | $this->curl = curl_init(); |
||
27 | |||
28 | $curl_options = [ |
||
29 | CURLOPT_SSL_VERIFYPEER => config('binance.settings.ssl'), |
||
30 | CURLOPT_SSL_VERIFYHOST => 2, |
||
31 | CURLOPT_USERAGENT => 'Binance PHP API Agent', |
||
32 | CURLOPT_RETURNTRANSFER => true, |
||
33 | CURLOPT_CONNECTTIMEOUT => 20, |
||
34 | CURLOPT_TIMEOUT => 300 |
||
35 | ]; |
||
36 | |||
37 | curl_setopt_array($this->curl, $curl_options); |
||
38 | |||
39 | } |
||
40 | |||
41 | /** |
||
42 | * Close CURL |
||
43 | */ |
||
44 | function __destruct() |
||
0 ignored issues
–
show
|
|||
45 | { |
||
46 | curl_close($this->curl); |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Key and Secret setter function. It's required for TRADE, USER_DATA, USER_STREAM, MARKET_DATA endpoints. |
||
51 | * https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#endpoint-security-type |
||
52 | * |
||
53 | * @param string $key API Key |
||
54 | * @param string $secret API Secret |
||
55 | */ |
||
56 | function setAPI($key, $secret) |
||
0 ignored issues
–
show
|
|||
57 | { |
||
58 | $this->key = $key; |
||
59 | $this->secret = $secret; |
||
60 | } |
||
61 | |||
62 | |||
63 | //------ PUBLIC API CALLS -------- |
||
64 | /* |
||
65 | * getTicker |
||
66 | * getCurrencies |
||
67 | * getMarkets |
||
68 | * getAvgPrice |
||
69 | */ |
||
70 | |||
71 | /** |
||
72 | * Get ticker |
||
73 | * |
||
74 | * @return mixed |
||
75 | * @throws Exception |
||
76 | */ |
||
77 | public function getTickers() |
||
78 | { |
||
79 | return $this->request('v3/ticker/price'); |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * Make public requests (Security Type: NONE) |
||
84 | * |
||
85 | * @param string $url URL Endpoint |
||
86 | * @param array $params Required and optional parameters |
||
87 | * @param string $method GET, POST, PUT, DELETE |
||
88 | * @return mixed |
||
89 | * @throws Exception |
||
90 | */ |
||
91 | private function request($url, $params = [], $method = 'GET') |
||
92 | { |
||
93 | // Set URL & Header |
||
94 | curl_setopt($this->curl, CURLOPT_URL, $this->url . $url); |
||
95 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, array()); |
||
96 | |||
97 | //Add post vars |
||
98 | if ($method == 'POST') { |
||
99 | curl_setopt($this->curl, CURLOPT_POST, count($params)); |
||
100 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, $params); |
||
101 | } |
||
102 | |||
103 | //Get result |
||
104 | $result = curl_exec($this->curl); |
||
105 | if ($result === false) |
||
106 | throw new Exception('CURL error: ' . curl_error($this->curl)); |
||
107 | |||
108 | // decode results |
||
109 | $result = json_decode($result, true); |
||
110 | |||
111 | if (!is_array($result) || json_last_error()) |
||
112 | throw new Exception('JSON decode error'); |
||
113 | |||
114 | return $result; |
||
115 | |||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Get ticker |
||
120 | * |
||
121 | * @return mixed |
||
122 | * @throws Exception |
||
123 | */ |
||
124 | public function getTicker($symbol) |
||
125 | { |
||
126 | $data = [ |
||
127 | 'symbol' => $symbol |
||
128 | ]; |
||
129 | return $this->request('v3/ticker/price?symbol=' . $symbol , $data); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Get ticker |
||
134 | * |
||
135 | * @param $symbol |
||
136 | * @return mixed |
||
137 | * @throws Exception |
||
138 | */ |
||
139 | public function getAvgPrice($symbol) |
||
140 | { |
||
141 | $data = [ |
||
142 | 'symbol' => $symbol |
||
143 | ]; |
||
144 | return $this->request('v3/avgPrice?symbol='.$symbol, $data); |
||
145 | } |
||
146 | |||
147 | public function getCurrencies() |
||
148 | { |
||
149 | //Seems to be no such functionality |
||
150 | return false; |
||
151 | } |
||
152 | |||
153 | |||
154 | //------ PRIVATE API CALLS ---------- |
||
155 | /* |
||
156 | * getBalances |
||
157 | * getRecentTrades |
||
158 | * getOpenOrders |
||
159 | * getAllOrders |
||
160 | * trade |
||
161 | * marketSell |
||
162 | * marketBuy |
||
163 | * limitSell |
||
164 | * limitBuy |
||
165 | * depositAddress |
||
166 | */ |
||
167 | |||
168 | /** |
||
169 | * Current exchange trading rules and symbol information |
||
170 | * |
||
171 | * @return mixed |
||
172 | * @throws Exception |
||
173 | */ |
||
174 | public function getMarkets() |
||
175 | { |
||
176 | $return = $this->request('v3/exchangeInfo'); |
||
177 | return $return['symbols']; |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Get current account information |
||
182 | * |
||
183 | * @return mixed |
||
184 | * @throws Exception |
||
185 | */ |
||
186 | public function getBalances() |
||
187 | { |
||
188 | $b = $this->privateRequest('v3/account'); |
||
189 | return $b['balances']; |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Make private requests (Security Type: TRADE, USER_DATA, USER_STREAM, MARKET_DATA) |
||
194 | * |
||
195 | * @param string $url URL Endpoint |
||
196 | * @param array $params Required and optional parameters |
||
197 | * @param string $method GET, POST, PUT, DELETE |
||
198 | * @return mixed |
||
199 | * @throws Exception |
||
200 | */ |
||
201 | private function privateRequest($url, $params = [], $method = 'GET') |
||
202 | { |
||
203 | // build the POST data string |
||
204 | $params['timestamp'] = number_format((microtime(true) * 1000), 0, '.', ''); |
||
205 | $params['recvWindow'] = $this->recvWindow; |
||
206 | |||
207 | $query = http_build_query($params, '', '&'); |
||
208 | |||
209 | // set API key and sign the message |
||
210 | $sign = hash_hmac('sha256', $query, $this->secret); |
||
211 | |||
212 | $headers = array( |
||
213 | 'X-MBX-APIKEY: ' . $this->key |
||
214 | ); |
||
215 | |||
216 | // make request |
||
217 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers); |
||
218 | |||
219 | // build the POST data string |
||
220 | $postdata = $params; |
||
221 | |||
222 | // Set URL & Header |
||
223 | curl_setopt($this->curl, CURLOPT_URL, $this->url . $url . "?{$query}&signature={$sign}"); |
||
224 | |||
225 | //Add post vars |
||
226 | if ($method == "POST") { |
||
227 | curl_setopt($this->curl, CURLOPT_POST, 1); |
||
228 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, array()); |
||
229 | } |
||
230 | |||
231 | //Get result |
||
232 | $result = curl_exec($this->curl); |
||
233 | if ($result === false) |
||
234 | throw new Exception('CURL error: ' . curl_error($this->curl)); |
||
235 | |||
236 | // decode results |
||
237 | $result = json_decode($result, true); |
||
238 | if (!is_array($result) || json_last_error()) |
||
239 | throw new Exception('JSON decode error'); |
||
240 | |||
241 | return $result; |
||
242 | |||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Get trades for a specific account and symbol |
||
247 | * |
||
248 | * @param string $symbol Currency pair |
||
249 | * @param int $limit Limit of trades. Max. 500 |
||
250 | * @return mixed |
||
251 | * @throws Exception |
||
252 | */ |
||
253 | public function getRecentTrades($symbol = 'BNBBTC', $limit = 500) |
||
254 | { |
||
255 | $data = [ |
||
256 | 'symbol' => $symbol, |
||
257 | 'limit' => $limit, |
||
258 | ]; |
||
259 | |||
260 | $b = $this->privateRequest('v3/myTrades', $data); |
||
261 | return $b; |
||
262 | |||
263 | } |
||
264 | |||
265 | public function getOpenOrders() |
||
266 | { |
||
267 | $b = $this->privateRequest('v3/openOrders'); |
||
268 | return $b; |
||
269 | } |
||
270 | |||
271 | public function getAllOrders($symbol) |
||
272 | { |
||
273 | $data = [ |
||
274 | 'symbol' => $symbol |
||
275 | ]; |
||
276 | $b = $this->privateRequest('v3/allOrders', $data); |
||
277 | return $b; |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Sell at market price |
||
282 | * |
||
283 | * @param string $symbol Asset pair to trade |
||
284 | * @param string $quantity Amount of trade asset |
||
285 | * @return mixed |
||
286 | * @throws Exception |
||
287 | */ |
||
288 | public function marketSell($symbol, $quantity) |
||
289 | { |
||
290 | return $this->trade($symbol, $quantity, 'SELL', 'MARKET'); |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * Base trade function |
||
295 | * |
||
296 | * @param string $symbol Asset pair to trade |
||
297 | * @param string $quantity Amount of trade asset |
||
298 | * @param string $side BUY, SELL |
||
299 | * @param string $type MARKET, LIMIT, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER |
||
300 | * @param bool $price Limit price |
||
301 | * @return mixed |
||
302 | * @throws Exception |
||
303 | */ |
||
304 | public function trade($symbol, $quantity, $side, $type = 'MARKET', $price = false) |
||
305 | { |
||
306 | $data = [ |
||
307 | 'symbol' => $symbol, |
||
308 | 'side' => $side, |
||
309 | 'type' => $type, |
||
310 | 'quantity' => $quantity |
||
311 | ]; |
||
312 | if ($price !== false) { |
||
313 | $data['price'] = $price; |
||
314 | } |
||
315 | |||
316 | $b = $this->privateRequest('v3/order', $data, 'POST'); |
||
317 | |||
318 | return $b; |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * Buy at market price |
||
323 | * |
||
324 | * @param string $symbol Asset pair to trade |
||
325 | * @param string $quantity Amount of trade asset |
||
326 | * @return mixed |
||
327 | * @throws Exception |
||
328 | */ |
||
329 | public function marketBuy($symbol, $quantity) |
||
330 | { |
||
331 | return $this->trade($symbol, $quantity, 'BUY', 'MARKET'); |
||
332 | } |
||
333 | |||
334 | /** |
||
335 | * Sell limit |
||
336 | * |
||
337 | * @param string $symbol Asset pair to trade |
||
338 | * @param string $quantity Amount of trade asset |
||
339 | * @param float $price Limit price to sell |
||
340 | * @return mixed |
||
341 | * @throws Exception |
||
342 | */ |
||
343 | public function limitSell($symbol, $quantity, $price) |
||
344 | { |
||
345 | return $this->trade($symbol, $quantity, 'SELL', 'LIMIT', $price); |
||
346 | } |
||
347 | |||
348 | //------ REQUESTS FUNCTIONS ------ |
||
349 | |||
350 | /** |
||
351 | * Buy limit |
||
352 | * |
||
353 | * @param string $symbol Asset pair to trade |
||
354 | * @param string $quantity Amount of trade asset |
||
355 | * @param float $price Limit price to buy |
||
356 | * @return mixed |
||
357 | * @throws Exception |
||
358 | */ |
||
359 | public function limitBuy($symbol, $quantity, $price) |
||
360 | { |
||
361 | return $this->trade($symbol, $quantity, 'BUY', 'LIMIT', $price); |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * Deposit Address |
||
366 | * @param string $symbol Asset symbol |
||
367 | * @return mixed |
||
368 | * |
||
369 | * @throws Exception |
||
370 | */ |
||
371 | public function depositAddress($symbol) |
||
372 | { |
||
373 | return $this->wapiRequest("v3/depositAddress.html", ['asset' => $symbol]); |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Make wapi requests |
||
378 | * |
||
379 | * @param string $url URL Endpoint |
||
380 | * @param array $params Required and optional parameters |
||
381 | * @param string $method GET, POST, PUT, DELETE |
||
382 | * @return mixed |
||
383 | * @throws Exception |
||
384 | */ |
||
385 | private function wapiRequest($url, $params = [], $method = 'GET') |
||
386 | { |
||
387 | // build the POST data string |
||
388 | $params['timestamp'] = number_format((microtime(true) * 1000), 0, '.', ''); |
||
389 | $params['recvWindow'] = $this->recvWindow; |
||
390 | |||
391 | $query = http_build_query($params, '', '&'); |
||
392 | |||
393 | // set API key and sign the message |
||
394 | $sign = hash_hmac('sha256', $query, $this->secret); |
||
395 | |||
396 | $headers = array( |
||
397 | 'X-MBX-APIKEY: ' . $this->key |
||
398 | ); |
||
399 | |||
400 | // make request |
||
401 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers); |
||
402 | |||
403 | // build the POST data string |
||
404 | $postdata = $params; |
||
405 | |||
406 | // Set URL & Header |
||
407 | curl_setopt($this->curl, CURLOPT_URL, $this->wapi_url . $url . "?{$query}&signature={$sign}"); |
||
408 | |||
409 | //Add post vars |
||
410 | if ($method == "POST") { |
||
411 | curl_setopt($this->curl, CURLOPT_POST, 1); |
||
412 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, array()); |
||
413 | } |
||
414 | |||
415 | //Get result |
||
416 | $result = curl_exec($this->curl); |
||
417 | if ($result === false) |
||
418 | throw new Exception('CURL error: ' . curl_error($this->curl)); |
||
419 | |||
420 | // decode results |
||
421 | $result = json_decode($result, true); |
||
422 | if (!is_array($result) || json_last_error()) |
||
423 | throw new Exception('JSON decode error'); |
||
424 | |||
425 | return $result; |
||
426 | |||
427 | } |
||
428 | |||
429 | } |
||
430 |