File Coverage

blib/lib/WebService/Cryptsy.pm
Criterion Covered Total %
statement 86 99 86.8
branch 17 24 70.8
condition 8 14 57.1
subroutine 30 33 90.9
pod 21 21 100.0
total 162 191 84.8


line stmt bran cond sub pod time code
1             package WebService::Cryptsy;
2              
3 24     24   695325 use Moo;
  24         256117  
  24         114  
4              
5             our $VERSION = '1.008005'; # VERSION
6              
7 24     24   39607 use URI;
  24         85087  
  24         626  
8 24     24   10346 use JSON::MaybeXS;
  24         102733  
  24         1309  
9 24     24   13308 use LWP::UserAgent;
  24         662679  
  24         833  
10 24     24   11980 use Digest::SHA qw/hmac_sha512_hex/;
  24         65575  
  24         1979  
11 24     24   10825 use HTTP::Request::Common qw/POST/;
  24         37370  
  24         1324  
12              
13 24     24   178 use constant API_POST_URL => 'https://api.cryptsy.com/api';
  24         33  
  24         1456  
14 24     24   105 use constant API_GET_URL => 'http://pubapi.cryptsy.com/api.php';
  24         30  
  24         1315  
15 24     24   117 use overload '""' => sub { shift->error };
  24     3   244  
  24         246  
  3         449  
16              
17              
18             has public_key => ( is => 'ro', );
19             has private_key => ( is => 'ro', );
20             has error => ( is => 'rw', );
21             has timeout => ( is => 'rw', default => 60 );
22              
23             ########## API METHODS ##########
24 0     0 1 0 sub marketdata { return shift->_api_query('marketdata' ); }
25 0     0 1 0 sub marketdatav2 { return shift->_api_query('marketdatav2' ); }
26 1     1 1 1502 sub orderdata { return shift->_api_query('orderdata' ); }
27 1     1 1 2061 sub getinfo { return shift->_api_query('getinfo' ); }
28 1     1 1 1854 sub getmarkets { return shift->_api_query('getmarkets' ); }
29 1     1 1 1957 sub mytransactions { return shift->_api_query('mytransactions' ); }
30 1     1 1 2040 sub allmyorders { return shift->_api_query('allmyorders' ); }
31 1     1 1 1861 sub cancelallorders { return shift->_api_query('cancelallorders'); }
32 1     1 1 1923 sub allmytrades { return shift->_api_query('allmytrades' ); }
33              
34             sub singlemarketdata {
35 1     1 1 1851 my ( $self, $market_id ) = @_;
36 1         4 return $self->_api_query(
37             'singlemarketdata', marketid => $market_id,
38             );
39             }
40              
41             sub singleorderdata {
42 1     1 1 1848 my ( $self, $market_id ) = @_;
43 1         4 return $self->_api_query(
44             'singleorderdata', marketid => $market_id,
45             );
46             }
47              
48             sub markettrades {
49 1     1 1 1551 my ( $self, $market_id ) = @_;
50 1         5 return $self->_api_query(
51             'markettrades', marketid => $market_id,
52             );
53             }
54              
55             sub marketorders {
56 1     1 1 1530 my ( $self, $market_id ) = @_;
57 1         5 return $self->_api_query(
58             'marketorders', marketid => $market_id,
59             );
60             }
61              
62             sub mytrades {
63 1     1 1 1807 my ( $self, $market_id, $limit ) = @_;
64 1   50     4 $limit ||= 200;
65 1         5 return $self->_api_query(
66             'mytrades', marketid => $market_id, limit => $limit,
67             );
68             }
69              
70             sub myorders {
71 1     1 1 1493 my ( $self, $market_id ) = @_;
72 1         6 return $self->_api_query(
73             'myorders', marketid => $market_id,
74             );
75             }
76              
77             sub depth {
78 1     1 1 1866 my ( $self, $market_id ) = @_;
79 1         5 return $self->_api_query(
80             'depth', marketid => $market_id,
81             );
82             }
83              
84             sub createorder {
85 2     2 1 3421 my ( $self, $market_id, $order_type, $quantity, $price ) = @_;
86 2         11 return $self->_api_query(
87             'createorder',
88             marketid => $market_id,
89             ordertype => $order_type,
90             quantity => $quantity,
91             price => $price,
92             );
93             }
94              
95             sub cancelorder {
96 0     0 1 0 my ( $self, $order_id ) = @_;
97 0         0 return $self->_api_query(
98             'cancelorder', orderid => $order_id,
99             );
100             }
101              
102             sub cancelmarketorders {
103 1     1 1 1880 my ( $self, $market_id ) = @_;
104 1         4 return $self->_api_query(
105             'cancelmarketorders', marketid => $market_id,
106             );
107             }
108              
109             sub calculatefees {
110 1     1 1 1735 my ( $self, $order_type, $quantity, $price ) = @_;
111 1         5 return $self->_api_query(
112             'calculatefees',
113             ordertype => $order_type,
114             quantity => $quantity,
115             price => $price,
116             );
117             }
118              
119             sub generatenewaddress {
120 3     3 1 23951 my ( $self, $currency_id, $currency_code ) = @_;
121 3 100       36 return $self->_api_query(
    100          
122             'generatenewaddress',
123             ( defined $currency_id ? ( currencyid => $currency_id ) : () ),
124             ( defined $currency_code ? ( currencycode => $currency_code ) : () ),
125             );
126             }
127              
128              
129             ########## MODULE METHODS ##########
130             sub _decode {
131 21     21   12109 my ( $self, $json, $method ) = @_;
132              
133 21 50       106 unless ( $json ) {
134 0         0 $self->error('Network error: got no data');
135             return
136 0         0 }
137              
138 21         147 $self->error( undef );
139              
140 21         39 my $decoded = eval { decode_json( $json ); };
  21         89296  
141 21 50       589 if ( $@ ) {
142 0         0 $self->error('JSON parsing error: ' . $@);
143 0         0 return;
144             }
145              
146 21 100 66     276 unless ( $decoded and $decoded->{success} ) {
147 2 50 33     18 $self->error( $decoded && $decoded->{error}
148             ? $decoded->{error}
149             : 'Unknown JSON parsing error'
150             );
151 2         148 return;
152             }
153              
154             ## Seems to be a bug in API, as it returns a null instead of an
155             ## Empty array, as it does for other similar methods
156 19 50 66     112 $decoded->{return} = []
      66        
157             if not defined $decoded->{return}
158             and (
159             $method eq 'mytransactions'
160             or $method eq 'cancelmarketorders'
161             or $method eq 'cancelallorders'
162             );
163              
164 19 50       95 if ( $method eq 'cancelorder' ) {
165 0         0 $decoded->{return} = 1;
166             }
167              
168 19 50       792 unless ( $decoded->{return} ) {
169 0         0 $self->error('Return given by Cryptsy is empty');
170 0         0 return;
171             }
172              
173 19         2014 return $decoded->{return};
174             }
175              
176             sub _api_query {
177 21     21   74 my ( $self, $method, %req_args ) = @_;
178              
179              
180 21         419 my $ua = LWP::UserAgent->new( timeout => $self->timeout );
181 21         46221 my $res;
182 21         245 my %get_methods = map +( $_ => 1 ), qw/
183             marketdata marketdatav2 singlemarketdata
184             orderdata singleorderdata
185             /;
186 21 100       96 if ( $get_methods{ $method } ) {
187 3         17 my $url = URI->new( API_GET_URL );
188 3 100       20087 $url->query_form(
189             method => $method,
190             $method =~ /^single(market|order)data$/
191             ? ( marketid => $req_args{marketid} ) : ()
192             );
193              
194 3         530 $res = $ua->get( $url );
195             }
196             else {
197 18         225 my $req = POST(
198             API_POST_URL, [
199             %req_args,
200             method => $method,
201             nonce => time(),
202             ]
203             );
204              
205 18         122559 my $digest = hmac_sha512_hex( $req->content, $self->private_key );
206 18         753 $req->header( Sign => $digest, );
207 18         1049 $req->header( Key => $self->public_key, );
208              
209 18         922 $res = $ua->request( $req );
210             }
211              
212 21 50       28284947 unless ( $res->is_success ) {
213 0         0 $self->error('Network error: ' . $res->status_line );
214 0         0 return;
215             }
216 21         503 return $self->_decode( $res->decoded_content, $method );
217             }
218              
219              
220             1;
221              
222             __END__