File Coverage

blib/lib/Binance/API.pm
Criterion Covered Total %
statement 92 148 62.1
branch 29 48 60.4
condition 1 3 33.3
subroutine 22 33 66.6
pod 25 25 100.0
total 169 257 65.7


line stmt bran cond sub pod time code
1             package Binance::API;
2              
3             # MIT License
4             #
5             # Copyright (c) 2018
6             # Lari Taskula
7             # Filip La Gre
8             #
9             # Permission is hereby granted, free of charge, to any person obtaining a copy
10             # of this software and associated documentation files (the "Software"), to deal
11             # in the Software without restriction, including without limitation the rights
12             # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13             # copies of the Software, and to permit persons to whom the Software is
14             # furnished to do so, subject to the following conditions:
15             #
16             # The above copyright notice and this permission notice shall be included in all
17             # copies or substantial portions of the Software.
18             #
19             # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20             # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21             # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22             # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23             # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24             # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25             # SOFTWARE.
26              
27 2     2   90333 use strict;
  2         14  
  2         73  
28 2     2   10 use warnings;
  2         4  
  2         64  
29              
30 2     2   10 use Carp;
  2         4  
  2         136  
31 2     2   11 use Scalar::Util qw( blessed );
  2         4  
  2         87  
32              
33 2     2   896 use Binance::API::Logger;
  2         7  
  2         66  
34 2     2   1014 use Binance::API::Request;
  2         9  
  2         103  
35              
36 2     2   1157 use Binance::Exception::Parameter::BadValue;
  2         6  
  2         69  
37 2     2   15 use Binance::Exception::Parameter::Required;
  2         3  
  2         4946  
38              
39             our $VERSION = '1.07';
40              
41             =head1 NAME
42              
43             Binance::API -- Perl implementation for Binance API
44              
45             =head1 DESCRIPTION
46              
47             This module provides a Perl implementation for Binance API
48              
49             Binance API documentation: C.
50              
51             ENUM definitions:
52             https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#enum-definitions
53              
54             =head1 SYNOPSIS
55              
56             use Binance::API;
57              
58             my $api = Binance::API->new(
59             apiKey => 'my_api_key',
60             secretKey => 'my_secret_key',
61             );
62              
63             my $ticker = $api->ticker( symbol => 'ETHBTC' );
64              
65             =head1 METHODS
66              
67             =cut
68              
69             =head2 new
70              
71             my $api = Binance::API->new(
72             apiKey => 'my_api_key',
73             secretKey => 'my_secret_key',
74             );
75              
76             Instantiates a new C object
77              
78             B
79              
80             =over
81              
82             =item apiKey
83              
84             [OPTIONAL] Your Binance API key.
85              
86             =item secretKey
87              
88             [OPTIONAL] Your Binance API secret key.
89              
90             =item recvWindow
91              
92             [OPTIONAL] Number of milliseconds the request is valid for. Applies only in
93             signed requests.
94              
95             =item logger
96              
97             [OPTIONAL] See L
98              
99             =back
100              
101             B
102              
103             A C object.
104              
105             =cut
106              
107             sub new {
108 3     3 1 3319 my ($class, %params) = @_;
109              
110 3         23 my $logger = Binance::API::Logger->new($params{logger});
111              
112             my $ua = Binance::API::Request->new(
113             apiKey => $params{apiKey},
114             secretKey => $params{secretKey},
115             recvWindow => $params{recvWindow},
116 3         25 logger => $logger,
117             );
118              
119 3         11 my $self = {
120             ua => $ua,
121             logger => $logger,
122             };
123              
124 3         29 bless $self, $class;
125             }
126              
127             =head2 ping
128              
129             $api->ping();
130              
131             Test connectivity to the Rest API
132              
133             B
134              
135             =over
136              
137             =item Takes no parameters.
138              
139             =back
140              
141              
142             B
143             1 if successful, otherwise 0
144              
145             =cut
146              
147             sub ping {
148 1 50   1 1 7590 return keys %{$_[0]->ua->get('/api/v3/ping')} == 0 ? 1 : 0;
  1         6  
149             }
150              
151             =head2 time
152              
153             $api->time();
154              
155             Test connectivity to the Rest API and get the current server time.
156              
157             B
158              
159             =over
160              
161             =item Takes no parameters.
162              
163             =back
164              
165             B
166             Server (epoch) time in milliseconds
167              
168             =cut
169              
170             sub time {
171 1     1 1 3886 my $self = shift;
172              
173 1         6 my $time = $self->ua->get('/api/v3/time');
174 1 50       10 return exists $time->{serverTime} ? $time->{serverTime} : 0;
175             }
176              
177             =head2 exchange_info
178              
179             $api->exchange_info();
180              
181             Current exchange trading rules and symbol information.
182              
183             B
184              
185             =over
186              
187             =item Takes no parameters.
188              
189             =back
190              
191             B
192             A HASHref
193              
194             {
195             "timezone": "UTC",
196             "serverTime": 1508631584636,
197             "rateLimits": [{
198             "rateLimitType": "REQUESTS",
199             "interval": "MINUTE",
200             "limit": 1200
201             },
202             {
203             "rateLimitType": "ORDERS",
204             "interval": "SECOND",
205             "limit": 10
206             },
207             {
208             "rateLimitType": "ORDERS",
209             "interval": "DAY",
210             "limit": 100000
211             }
212             ],
213             "exchangeFilters": [],
214             "symbols": [{
215             "symbol": "ETHBTC",
216             "status": "TRADING",
217             "baseAsset": "ETH",
218             "baseAssetPrecision": 8,
219             "quoteAsset": "BTC",
220             "quotePrecision": 8,
221             "orderTypes": ["LIMIT", "MARKET"],
222             "icebergAllowed": false,
223             "filters": [{
224             "filterType": "PRICE_FILTER",
225             "minPrice": "0.00000100",
226             "maxPrice": "100000.00000000",
227             "tickSize": "0.00000100"
228             }, {
229             "filterType": "LOT_SIZE",
230             "minQty": "0.00100000",
231             "maxQty": "100000.00000000",
232             "stepSize": "0.00100000"
233             }, {
234             "filterType": "MIN_NOTIONAL",
235             "minNotional": "0.00100000"
236             }]
237             }]
238             }
239              
240             =cut
241              
242             sub exchange_info {
243 0     0 1 0 return $_[0]->ua->get('/api/v3/exchangeInfo');
244             }
245              
246             =head2 depth
247              
248             $api->depth( symbol => 'ETHBTC' );
249              
250             B
251              
252             =over
253              
254             =item symbol
255              
256             [REQUIRED] Symbol, for example C.
257              
258             =item limit
259              
260             [OPTIONAL] Default 100; max 5000. Valid limits: 5, 10, 20, 50, 100, 500, 1000, 5000.
261              
262             =back
263              
264             B
265             A HASHref
266              
267             {
268             "lastUpdateId": 1027024,
269             "bids": [
270             [
271             "4.00000000", // PRICE
272             "431.00000000", // QTY
273             [] // Can be ignored
274             ]
275             ],
276             "asks": [
277             [
278             "4.00000200",
279             "12.00000000",
280             []
281             ]
282             ]
283             }
284              
285             =cut
286              
287             sub depth {
288 2     2 1 6777 my ($self, %params) = @_;
289              
290 2 100       15 unless ($params{'symbol'}) {
291 1         5 $self->log->error('Parameter "symbol" required');
292 1         17 Binance::Exception::Parameter::Required->throw(
293             error => 'Parameter "symbol" required',
294             parameters => ['symbol']
295             );
296             }
297              
298             my $query = {
299             symbol => $params{'symbol'},
300 1         5 limit => $params{'limit'},
301             };
302              
303 1         5 return $self->ua->get('/api/v3/depth', { query => $query } );
304             }
305              
306             =head2 trades
307              
308             $api->trades();
309              
310             Get recent trades (up to last 1000).
311              
312             B
313              
314             =over
315              
316             =item symbol
317              
318             [REQUIRED] Symbol, for example C.
319              
320             =item limit
321              
322             [OPTIONAL] Default 500; max 1000.
323              
324             =back
325              
326             B
327             An ARRAYref of HASHrefs
328              
329             [
330             {
331             "id": 28457,
332             "price": "4.00000100",
333             "qty": "12.00000000",
334             "time": 1499865549590,
335             "isBuyerMaker": true,
336             "isBestMatch": true
337             }
338             ]
339              
340             =cut
341              
342             sub trades {
343 0     0 1 0 my ($self, %params) = @_;
344              
345 0 0       0 unless ($params{'symbol'}) {
346 0         0 $self->log->error('Parameter "symbol" required');
347 0         0 Binance::Exception::Parameter::Required->throw(
348             error => 'Parameter "symbol" required',
349             parameters => ['symbol']
350             );
351             }
352              
353             my $query = {
354             symbol => $params{'symbol'},
355 0         0 limit => $params{'limit'},
356             };
357              
358 0         0 return $self->ua->get('/api/v3/trades', { query => $query } );
359             }
360              
361             =head2 historical_trades
362              
363             $api->historical_trades();
364              
365             Get older trades.
366              
367             B
368              
369             =over
370              
371             =item symbol
372              
373             [REQUIRED] Symbol, for example C.
374              
375             =item limit
376              
377             [OPTIONAL] Default 500; max 1000.
378              
379             =item fromId
380              
381             [OPTIONAL] TradeId to fetch from. Default gets most recent trades.
382              
383             =back
384              
385             B
386             An ARRAYref of HASHrefs
387              
388             [
389             {
390             "id": 28457,
391             "price": "4.00000100",
392             "qty": "12.00000000",
393             "time": 1499865549590,
394             "isBuyerMaker": true,
395             "isBestMatch": true
396             }
397             ]
398              
399             =cut
400              
401             sub historical_trades {
402 0     0 1 0 my ($self, %params) = @_;
403              
404 0 0       0 unless ($params{'symbol'}) {
405 0         0 $self->log->error('Parameter "symbol" required');
406 0         0 Binance::Exception::Parameter::Required->throw(
407             error => 'Parameter "symbol" required',
408             parameters => ['symbol']
409             );
410             }
411              
412             my $query = {
413             symbol => $params{'symbol'},
414             limit => $params{'limit'},
415 0         0 fromId => $params{'fromId'},
416             };
417              
418 0         0 return $self->ua->get('/api/v3/historicalTrades', { query => $query } );
419             }
420              
421             =head2 aggregate_trades
422              
423             $api->aggregate_trades( symbol => 'ETHBTC' );
424              
425             Gets compressed, aggregate trades. Trades that fill at the time, from the same
426             order, with the same price will have the quantity aggregated.
427              
428             B
429              
430             =over
431              
432             =item symbol
433              
434             [REQUIRED] Symbol, for example C.
435              
436             =item fromId
437              
438             [OPTIONAL] ID to get aggregate trades from INCLUSIVE.
439              
440             =item startTime
441              
442             [OPTIONAL] timestamp in ms to get aggregate trades from INCLUSIVE.
443              
444             =item endTime
445              
446             [OPTIONAL] timestamp in ms to get aggregate trades until INCLUSIVE.
447              
448             =item limit
449              
450             [OPTIONAL] Default 500; max 1000.
451              
452             =back
453              
454             B
455             An ARRAYref of HASHrefs
456              
457             [
458             {
459             "a": 26129, // Aggregate tradeId
460             "p": "0.01633102", // Price
461             "q": "4.70443515", // Quantity
462             "f": 27781, // First tradeId
463             "l": 27781, // Last tradeId
464             "T": 1498793709153, // Timestamp
465             "m": true, // Was the buyer the maker?
466             "M": true // Was the trade the best price match?
467             }
468             ]
469              
470             =cut
471              
472             sub aggregate_trades {
473 2     2 1 6008 my ($self, %params) = @_;
474              
475 2 100       12 unless ($params{'symbol'}) {
476 1         4 $self->log->error('Parameter "symbol" required');
477 1         23 Binance::Exception::Parameter::Required->throw(
478             error => 'Parameter "symbol" required',
479             parameters => ['symbol']
480             );
481             }
482              
483             my $query = {
484             symbol => $params{'symbol'},
485             fromId => $params{'fromId'},
486             startTime => $params{'startTime'},
487             endTime => $params{'endTime'},
488 1         8 limit => $params{'limit'},
489             };
490              
491 1         6 return $self->ua->get('/api/v3/aggTrades', { query => $query } );
492             }
493              
494             =head2 klines
495              
496             $api->klines( symbol => 'ETHBTC', interval => '1M' );
497              
498             Kline/candlestick bars for a symbol. Klines are uniquely identified by their
499             open time.
500              
501             B
502              
503             =over
504              
505             =item symbol
506              
507             [REQUIRED] Symbol, for example C.
508              
509             =item interval
510              
511             [REQUIRED] ENUM (kline intervals), for example 1m, 1h, 1d or 1M.
512              
513             =item limit
514              
515             [OPTIONAL] Default 500; max 1000.
516              
517             =item startTime
518              
519             [OPTIONAL] timestamp in ms
520              
521             =item endTime
522              
523             [OPTIONAL] timestamp in ms
524              
525             =back
526              
527             B
528             An array of ARRAYrefs
529              
530             [
531             [
532             1499040000000, // Open time
533             "0.01634790", // Open
534             "0.80000000", // High
535             "0.01575800", // Low
536             "0.01577100", // Close
537             "148976.11427815", // Volume
538             1499644799999, // Close time
539             "2434.19055334", // Quote asset volume
540             308, // Number of trades
541             "1756.87402397", // Taker buy base asset volume
542             "28.46694368", // Taker buy quote asset volume
543             "17928899.62484339" // Can be ignored
544             ]
545             ]
546              
547             =cut
548              
549             sub klines {
550 4     4 1 12320 my ($self, %params) = @_;
551              
552 4 100       58 unless ($params{'symbol'}) {
553 2         10 $self->log->error('Parameter "symbol" required');
554 2         60 Binance::Exception::Parameter::Required->throw(
555             error => 'Parameter "symbol" required',
556             parameters => ['symbol']
557             );
558             }
559              
560 2 100       10 unless ($params{'interval'}) {
561 1         4 $self->log->error('Parameter "interval" required');
562 1         11 Binance::Exception::Parameter::Required->throw(
563             error => 'Parameter "interval" required',
564             parameters => ['interval']
565             );
566             }
567              
568             my $query = {
569             symbol => $params{'symbol'},
570             interval => $params{'interval'},
571             startTime => $params{'startTime'},
572             endTime => $params{'endTime'},
573 1         8 limit => $params{'limit'},
574             };
575              
576 1         6 return $self->ua->get('/api/v3/klines', { query => $query } );
577             }
578              
579             =head2 ticker
580              
581             $api->ticker( symbol => 'ETHBTC', interval => '1M' );
582              
583             24 hour price change statistics.
584              
585             B
586              
587             =over
588              
589             =item symbol
590              
591             [OPTIONAL] Symbol, for example C.
592             Warning: Careful when accessing this with no symbol.
593              
594             =back
595              
596             B
597             A HASHref or an Array of HASHrefs if no symbol given
598              
599             {
600             "priceChange": "-94.99999800",
601             "priceChangePercent": "-95.960",
602             "weightedAvgPrice": "0.29628482",
603             "prevClosePrice": "0.10002000",
604             "lastPrice": "4.00000200",
605             "bidPrice": "4.00000000",
606             "askPrice": "4.00000200",
607             "openPrice": "99.00000000",
608             "highPrice": "100.00000000",
609             "lowPrice": "0.10000000",
610             "volume": "8913.30000000",
611             "openTime": 1499783499040,
612             "closeTime": 1499869899040,
613             "fristId": 28385, // First tradeId
614             "lastId": 28460, // Last tradeId
615             "count": 76 // Trade count
616             }
617              
618             =cut
619              
620             sub ticker {
621 1     1 1 2516 my ($self, %params) = @_;
622              
623             my $query = {
624 1         4 symbol => $params{'symbol'},
625             };
626              
627 1         4 return $self->ua->get('/api/v3/ticker/24hr', { query => $query } );
628             }
629              
630             =head2 ticker_price
631              
632             $api->ticker_price();
633              
634             Latest price for a symbol or symbols.
635              
636             B
637              
638             =over
639              
640             =item symbol
641              
642             [OPTIONAL] Symbol, for example C. If not given, returns prices of all
643             symbols.
644              
645             =back
646              
647             B
648             A HASHref
649              
650             {
651             "symbol": "LTCBTC",
652             "price": "4.00000200"
653             }
654              
655             OR an ARRAY of HASHrefs
656              
657             [
658             {
659             "symbol": "LTCBTC",
660             "price": "4.00000200"
661             },
662             {
663             "symbol": "ETHBTC",
664             "price": "0.07946600"
665             }
666             ]
667              
668             =cut
669              
670             sub ticker_price {
671 2     2 1 4898 my ($self, %params) = @_;
672              
673             my $query = {
674 2         7 symbol => $params{'symbol'},
675             };
676              
677 2         7 return $self->ua->get('/api/v3/ticker/price', { query => $query } );
678             }
679              
680             =head2 book_ticker
681              
682             $api->book_ticker();
683              
684             Best price/qty on the order book for all symbols.
685              
686             B
687              
688             =over
689              
690             =item symbol
691              
692             [OPTIONAL] Symbol, for example C. If not given, returns best price/qty of all
693             symbols.
694              
695             =back
696              
697             B
698              
699             A HASHref
700             {
701             "symbol": "LTCBTC",
702             "bidPrice": "4.00000000",
703             "bidQty": "431.00000000",
704             "askPrice": "4.00000200",
705             "askQty": "9.00000000"
706             }
707              
708             OR an ARRAY of HASHrefs
709              
710             [
711             {
712             "symbol": "LTCBTC",
713             "bidPrice": "4.00000000",
714             "bidQty": "431.00000000",
715             "askPrice": "4.00000200",
716             "askQty": "9.00000000"
717             },
718             {
719             "symbol": "ETHBTC",
720             "bidPrice": "0.07946700",
721             "bidQty": "9.00000000",
722             "askPrice": "100000.00000000",
723             "askQty": "1000.00000000"
724             }
725             ]
726              
727             =cut
728              
729             sub book_ticker {
730 1     1 1 4 my ($self, %params) = @_;
731              
732             my $query = {
733 1         3 symbol => $params{'symbol'},
734             };
735              
736 1         6 return $_[0]->ua->get('/api/v3/ticker/bookTicker', { query => $query } );
737             }
738              
739             =head2 all_book_tickers
740              
741             $api->all_book_tickers();
742              
743             DEPRECATED: use book_ticker instead.
744              
745             =cut
746              
747             sub all_book_tickers {
748 1     1 1 4238 my $self = shift;
749              
750 1         6 return $self->book_ticker(@_);
751             }
752              
753             =head2 order
754              
755             $api->order(
756             symbol => 'ETHBTC',
757             side => 'BUY',
758             type => 'LIMIT',
759             timeInForce => 'GTC',
760             quantity => 1
761             price => 0.1
762             );
763              
764             Send in a new order.
765              
766             B
767              
768             =over
769              
770             =item symbol
771              
772             [REQUIRED] Symbol, for example C.
773              
774             =item side
775              
776             [REQUIRED] BUY or SELL.
777              
778             =item type
779              
780             [REQUIRED] LIMIT|STOP_LOSS|STOP_LOSS_LIMIT|TAKE_PROFIT|TAKE_PROFIT_LIMIT|LIMIT_MAKER|MARKET.
781              
782             =item timeInForce
783              
784             [OPTIONAL] GTC or IOC.
785              
786             =item quantity
787              
788             [OPTIONAL] Quantity (of symbols) in order.
789              
790             =item quoteOrderQty
791              
792             [OPTIONAL] MARKET orders using quoteOrderQty specifies the amount the user wants
793             to spend (when buying) or receive (when selling) the quote asset; the correct
794             quantity will be determined based on the market liquidity and quoteOrderQty.
795              
796             E.g. Using the symbol BTCUSDT:
797             BUY side, the order will buy as many BTC as quoteOrderQty USDT can.
798             SELL side, the order will sell as much BTC needed to receive quoteOrderQty USDT.
799              
800             =item price
801              
802             [OPTIONAL] Price (of symbol) in order.
803              
804             =item newClientOrderId
805              
806             [OPTIONAL] A unique id for the order. Automatically generated
807             if not sent.
808              
809             =item stopPrice
810              
811             [OPTIONAL] Used with stop orders.
812              
813             =item icebergQty
814              
815             [OPTIONAL] Used with iceberg orders.
816              
817             =item newOrderRespType
818              
819             [OPTIONAL] Set the response JSON. ACK, RESULT, or FULL; MARKET and LIMIT order
820             types default to FULL, all other orders default to ACK.
821              
822             =item test
823              
824             [OPTIONAL] Test new order creation and signature/recvWindow long. Creates and
825             validates a new order but does not send it into the matching engine.
826              
827             =back
828              
829             B
830             A HASHref
831              
832             {
833             "symbol":"LTCBTC",
834             "orderId": 1,
835             "clientOrderId": "myOrder1" // Will be newClientOrderId
836             "transactTime": 1499827319559
837             }
838              
839             =cut
840              
841             sub order {
842 32     32 1 137 my ($self, %params) = @_;
843              
844 32 100       140 unless (defined $params{'type'}) {
845 1         6 $self->log->error('Parameter "type" required');
846 1         11 Binance::Exception::Parameter::Required->throw(
847             error => 'Parameter "type" required',
848             parameters => ['type']
849             );
850             }
851              
852 31         104 my @required = (
853             'symbol', 'side',
854             );
855              
856 31 100       277 if ($params{'type'} eq 'LIMIT') {
    100          
    100          
    100          
    100          
    100          
    100          
857 5         14 push @required, ('timeInForce', 'quantity', 'price');
858             }
859             elsif ($params{'type'} eq 'STOP_LOSS') {
860 4         12 push @required, ('quantity', 'stopPrice');
861             }
862             elsif ($params{'type'} eq 'STOP_LOSS_LIMIT') {
863 6         21 push @required, ('timeInForce', 'quantity', 'price', 'stopPrice');
864             }
865             elsif ($params{'type'} eq 'TAKE_PROFIT') {
866 4         12 push @required, ('quantity', 'stopPrice');
867             }
868             elsif ($params{'type'} eq 'TAKE_PROFIT_LIMIT') {
869 6         17 push @required, ('timeInForce', 'quantity', 'price', 'stopPrice');
870             }
871             elsif ($params{'type'} eq 'LIMIT_MAKER') {
872 4         14 push @required, ('quantity', 'price');
873             }
874             elsif ($params{'type'} eq 'MARKET') {
875 1 50 33     10 if (!defined $params{'quantity'} && !defined $params{'quoteOrderQty'}) {
876 1         5 $self->log->error('One of parameters "quantity" or "quoteOrderQty" is required');
877 1         11 Binance::Exception::Parameter::Required->throw(
878             error => 'One of parameters "quantity" or "quoteOrderQty" is required',
879             parameters => ["quantity", "quoteOrderQty"]
880             );
881             }
882             } else {
883 1         4 $self->log->error('Invalid value for parameter "type"');
884 1         22 Binance::Exception::Parameter::BadValue->throw(
885             error => 'Invalid value for parameter "type"',
886             parameters => ["type"],
887             format => '(LIMIT|STOP_LOSS|STOP_LOSS_LIMIT|TAKE_PROFIT|TAKE_PROFIT_LIMIT|LIMIT_MAKER|MARKET)'
888             );
889             }
890              
891 29         84 foreach my $param (@required) {
892 87 100       204 unless (defined ($params{$param})) {
893 29         112 $self->log->error('Parameter "'.$param.'" required');
894 29         281 Binance::Exception::Parameter::Required->throw(
895             error => 'Parameter "'.$param.'" required',
896             parameters => [$param]
897             );
898             }
899             }
900              
901             my $body = {
902             symbol => $params{'symbol'},
903             side => $params{'side'},
904             type => $params{'type'},
905             timeInForce => $params{'timeInForce'},
906             quantity => $params{'quantity'},
907             quoteOrderQty => $params{'quoteOrderQty'},
908             price => $params{'price'},
909             newClientOrderId => $params{'newClientOrderId'},
910             stopPrice => $params{'stopPrice'},
911             icebergQty => $params{'icebergQty'},
912 0         0 newOrderRespType => $params{'newOrderRespType'},
913             };
914              
915             # Enable dry mode
916 0         0 my $url = '/api/v3/order';
917              
918 0 0       0 if ($params{'test'}) {
919 0         0 $self->{logger}->debug('Test flag enabled - using order_test() instead of order()');
920 0         0 $url .= '/test'
921             }
922              
923 0         0 return $self->ua->post($url, { signed => 1, body => $body } );
924             }
925              
926             =head2 order_test
927              
928             $api->order_test();
929              
930             Test new order creation and signature/recvWindow long. Creates and validates
931             a new order but does not send it into the matching engine.
932              
933             B
934              
935             Same as C.
936              
937             B
938             An empty HASHref
939              
940             {}
941              
942             =cut
943              
944             sub order_test {
945 32     32 1 108844 my ($self, %params) = @_;
946              
947 32         111 $params{'test'} = 1;
948              
949 32         164 return $self->order(%params);
950             }
951              
952             =head2 cancel_order
953              
954             $api->cancel_order();
955              
956             Cancel an active order.
957              
958             B
959              
960             =over
961              
962             =item symbol
963              
964             [REQUIRED] Symbol, for example C.
965              
966             =item orderId
967              
968             [OPTIONAL]
969              
970             =item origClientOrderId
971              
972             [OPTIONAL]
973              
974             =item newClientOrderId
975              
976             [OPTIONAL] Used to uniquely identify this cancel.
977             Automatically generated by default.
978              
979             =item recvWindow
980              
981             [OPTIONAL]
982              
983             =back
984              
985             B
986             A HASHref
987              
988             {
989             "symbol": "LTCBTC",
990             "origClientOrderId": "myOrder1",
991             "orderId": 1,
992             "clientOrderId": "cancelMyOrder1"
993             }
994              
995             =cut
996              
997             sub cancel_order {
998 0     0 1 0 my ($self, %params) = @_;
999              
1000 0 0       0 unless ($params{'symbol'}) {
1001 0         0 $self->log->error('Parameter "symbol" required');
1002 0         0 Binance::Exception::Parameter::Required->throw(
1003             error => 'Parameter "symbol" required',
1004             parameters => ['symbol']
1005             );
1006             }
1007              
1008             my $body = {
1009             symbol => $params{'symbol'},
1010             orderId => $params{'orderId'},
1011             origClientOrderId => $params{'origClientOrderId'},
1012             newClientOrderId => $params{'newClientOrderId'},
1013 0         0 recvWindow => $params{'recvWindow'},
1014             };
1015              
1016 0         0 return $self->ua->delete('/api/v3/order', { signed => 1, body => $body } );
1017             }
1018              
1019             =head2 open_orders
1020              
1021             $api->open_orders();
1022              
1023             Get all open orders on a symbol. Careful when accessing this with no symbol.
1024              
1025             B
1026              
1027             =over
1028              
1029             =item symbol
1030              
1031             OPTIONAL] Symbol, for example C.
1032              
1033             =item recvWindow
1034              
1035             [OPTIONAL]
1036              
1037             =back
1038              
1039             B
1040             An ARRAYref of HASHrefs
1041              
1042             [
1043             {
1044             "symbol": "LTCBTC",
1045             "orderId": 1,
1046             "clientOrderId": "myOrder1",
1047             "price": "0.1",
1048             "origQty": "1.0",
1049             "executedQty": "0.0",
1050             "status": "NEW",
1051             "timeInForce": "GTC",
1052             "type": "LIMIT",
1053             "side": "BUY",
1054             "stopPrice": "0.0",
1055             "icebergQty": "0.0",
1056             "time": 1499827319559,
1057             "isWorking": trueO
1058             }
1059             ]
1060              
1061             =cut
1062              
1063             sub open_orders {
1064 0     0 1 0 my ($self, %params) = @_;
1065              
1066             my $query = {
1067             symbol => $params{'symbol'},
1068 0         0 recvWindow => $params{'recvWindow'},
1069             };
1070 0         0 return $self->ua->get(
1071             '/api/v3/openOrders', { signed => 1, query => $query }
1072             );
1073             }
1074              
1075             =head2 all_orders
1076              
1077             $api->all_orders();
1078              
1079             Get all account orders; active, canceled, or filled.
1080              
1081             B
1082              
1083             =over
1084              
1085             =item symbol
1086              
1087             [REQUIRED] Symbol, for example C.
1088              
1089             =item orderId
1090              
1091             [OPTIONAL]
1092              
1093             =item startTime
1094              
1095             [OPTIONAL] Start time
1096              
1097             =item endTime
1098              
1099             [OPTIONAL] End time
1100              
1101             =item limit
1102              
1103             [OPTIONAL] Default 500; max 1000.
1104              
1105             =item recvWindow
1106              
1107             [OPTIONAL] The value cannot be greater than 60000.
1108              
1109             =back
1110              
1111             B
1112             An ARRAYref of HASHrefs
1113              
1114             [
1115             {
1116             "symbol": "LTCBTC",
1117             "orderId": 1,
1118             "clientOrderId": "myOrder1",
1119             "price": "0.1",
1120             "origQty": "1.0",
1121             "executedQty": "0.0",
1122             "status": "NEW",
1123             "timeInForce": "GTC",
1124             "type": "LIMIT",
1125             "side": "BUY",
1126             "stopPrice": "0.0",
1127             "icebergQty": "0.0",
1128             "time": 1499827319559,
1129             "isWorking": true
1130             }
1131             ]
1132              
1133             =cut
1134              
1135             sub all_orders {
1136 0     0 1 0 my ($self, %params) = @_;
1137 0 0       0 unless ($params{'symbol'}) {
1138 0         0 $self->log->error('Parameter "symbol" required');
1139 0         0 Binance::Exception::Parameter::Required->throw(
1140             error => 'Parameter "symbol" required',
1141             parameters => ['symbol']
1142             );
1143             }
1144             my $query = {
1145             symbol => $params{'symbol'},
1146             orderId => $params{'orderId'},
1147             startTime => $params{'startTime'},
1148             endTime => $params{'endTime'},
1149             limit => $params{'limit'},
1150 0         0 recvWindow => $params{'recvWindow'},
1151             };
1152 0         0 return $self->ua->get('/api/v3/allOrders',
1153             { signed => 1, query => $query }
1154             );
1155             }
1156              
1157             =head2 account
1158              
1159             $api->account();
1160              
1161             Get current account information.
1162              
1163             B
1164              
1165             =over
1166              
1167             =item recvWindow
1168              
1169             [OPTIONAL]
1170              
1171             =back
1172              
1173             B
1174             A HASHref
1175              
1176             {
1177             "makerCommission": 15,
1178             "takerCommission": 15,
1179             "buyerCommission": 0,
1180             "sellerCommission": 0,
1181             "canTrade": true,
1182             "canWithdraw": true,
1183             "canDeposit": true,
1184             "updateTime": 123456789,
1185             "balances": [
1186             {
1187             "asset": "BTC",
1188             "free": "4723846.89208129",
1189             "locked": "0.00000000"
1190             },
1191             {
1192             "asset": "LTC",
1193             "free": "4763368.68006011",
1194             "locked": "0.00000000"
1195             }
1196             ]
1197             }
1198              
1199             =cut
1200              
1201             sub account {
1202 0     0 1 0 my ($self, %params) = @_;
1203              
1204             my $query = {
1205 0         0 recvWindow => $params{'recvWindow'},
1206             };
1207 0         0 return $self->ua->get('/api/v3/account', { signed => 1, query => $query } );
1208             }
1209              
1210             =head2 my_trades
1211              
1212             $api->my_trades();
1213              
1214             Get trades for a specific account and symbol.
1215              
1216             B
1217              
1218             =over
1219              
1220             =item symbol
1221              
1222             [REQUIRED] Symbol, for example C.
1223              
1224             =item limit
1225              
1226             [OPTIONAL] Default 500; max 500.
1227              
1228             =item fromId
1229              
1230             [OPTIONAL] TradeId to fetch from. Default gets most recent
1231             trades.
1232              
1233             =item recvWindow
1234              
1235             [OPTIONAL]
1236              
1237             =back
1238              
1239             B
1240             An ARRAYref of HASHrefs
1241              
1242             [
1243             {
1244             "id": 28457,
1245             "orderId": 100234,
1246             "price": "4.00000100",
1247             "qty": "12.00000000",
1248             "commission": "10.10000000",
1249             "commissionAsset": "BNB",
1250             "time": 1499865549590,
1251             "isBuyer": true,
1252             "isMaker": false,
1253             "isBestMatch": true
1254             }
1255             ]
1256              
1257             =cut
1258              
1259             sub my_trades {
1260 0     0 1 0 my ($self, %params) = @_;
1261 0 0       0 unless ($params{'symbol'}) {
1262 0         0 $self->log->error('Parameter "symbol" required');
1263 0         0 Binance::Exception::Parameter::Required->throw(
1264             error => 'Parameter "symbol" required',
1265             parameters => ['symbol']
1266             );
1267             }
1268             my $query = {
1269             symbol => $params{'symbol'},
1270             limit => $params{'limit'},
1271             fromId => $params{'fromId'},
1272 0         0 recvWindow => $params{'recvWindow'},
1273             };
1274 0         0 return $self->ua->get(
1275             '/api/v3/myTrades', { signed => 1, query => $query }
1276             );
1277             }
1278              
1279             =head2 start_user_data_stream
1280              
1281             $api->start_user_data_stream();
1282              
1283             Start a new user data stream. The stream will close after 60 minutes unless
1284             a keepalive is sent.
1285              
1286             B
1287              
1288             =over
1289              
1290             =item Takes no parameters.
1291              
1292             =back
1293              
1294             B
1295             A HASHref
1296              
1297             {
1298             "listenKey": "pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a65a1"
1299             }
1300              
1301             =cut
1302              
1303             sub start_user_data_stream {
1304 0     0 1 0 return $_[0]->ua->post('/api/v3/userDataStream');
1305             }
1306              
1307             =head2 keep_alive_user_data_stream
1308              
1309             $api->keep_alive_user_data_stream();
1310              
1311             Keepalive a user data stream to prevent a time out. User data streams will close
1312             after 60 minutes. It's recommended to send a ping about every 30 minutes.
1313              
1314             B
1315              
1316             =over
1317              
1318             =item listenKey
1319              
1320             [REQUIRED]
1321              
1322             =back
1323              
1324             B
1325             An empty HASHref
1326              
1327             {}
1328              
1329             =cut
1330              
1331             sub keep_alive_user_data_stream {
1332 0     0 1 0 my ($self, %params) = @_;
1333 0 0       0 unless ($params{'listenKey'}) {
1334 0         0 $self->log->error('Parameter "listenKey" required');
1335 0         0 Binance::Exception::Parameter::Required->throw(
1336             error => 'Parameter "listenKey" required',
1337             parameters => ['listenKey']
1338             );
1339             }
1340             my $query = {
1341 0         0 listenKey => $params{'listenKey'},
1342             };
1343 0         0 return $self->ua->put('/api/v3/userDataStream', { query => $query } );
1344             }
1345              
1346             =head2 delete_user_data_stream
1347              
1348             $api->delete_user_data_stream();
1349              
1350             Close out a user data stream.
1351              
1352             B
1353              
1354             =over
1355              
1356             =item listenKey
1357              
1358             [REQUIRED]
1359              
1360             =back
1361              
1362             B
1363             An empty HASHref
1364              
1365             {}
1366              
1367             =cut
1368              
1369             sub delete_user_data_stream {
1370 0     0 1 0 my ($self, %params) = @_;
1371 0 0       0 unless ($params{'listenKey'}) {
1372 0         0 $self->log->error('Parameter "listenKey" required');
1373 0         0 Binance::Exception::Parameter::Required->throw(
1374             error => 'Parameter "listenKey" required',
1375             parameters => ['listenKey']
1376             );
1377             }
1378             my $query = {
1379 0         0 listenKey => $params{'listenKey'},
1380             };
1381 0         0 return $self->ua->delete('/api/v3/userDataStream', { query => $query } );
1382             }
1383              
1384             =head2 log
1385              
1386             $api->log->warn("This is a warning");
1387              
1388             B
1389              
1390             =over
1391              
1392             =item Takes no parameters.
1393              
1394             =back
1395              
1396             B
1397              
1398             An instance of L.
1399              
1400             =cut
1401              
1402 37     37 1 452 sub log { return $_[0]->{logger}; }
1403              
1404             =head2 ua
1405              
1406             $api->ua->get('/binance/endpoint');
1407              
1408             B
1409              
1410             =over
1411              
1412             =item Takes no parameters.
1413              
1414             =back
1415              
1416             B
1417              
1418             An instance of L.
1419              
1420             =cut
1421              
1422 9     9 1 78 sub ua { return $_[0]->{ua}; }
1423              
1424             1;