File Coverage

blib/lib/Binance/API.pm
Criterion Covered Total %
statement 92 154 59.7
branch 29 50 58.0
condition 1 3 33.3
subroutine 22 34 64.7
pod 26 26 100.0
total 170 267 63.6


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