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   673402 use Moo;
  24         221231  
  24         110  
4              
5             our $VERSION = '1.008006'; # VERSION
6              
7 24     24   35090 use URI;
  24         82030  
  24         631  
8 24     24   11186 use JSON::MaybeXS;
  24         87538  
  24         1212  
9 24     24   11622 use LWP::UserAgent;
  24         597913  
  24         734  
10 24     24   11871 use Digest::SHA qw/hmac_sha512_hex/;
  24         57616  
  24         1809  
11 24     24   9484 use HTTP::Request::Common qw/POST/;
  24         33303  
  24         1253  
12              
13 24     24   265 use constant API_POST_URL => 'https://api.cryptsy.com/api';
  24         28  
  24         1412  
14 24     24   92 use constant API_GET_URL => 'http://pubapi.cryptsy.com/api.php';
  24         27  
  24         1032  
15 24     24   96 use overload '""' => sub { shift->error };
  24     3   218  
  24         214  
  3         1105  
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 1311 sub orderdata { return shift->_api_query('orderdata' ); }
27 1     1 1 2874 sub getinfo { return shift->_api_query('getinfo' ); }
28 1     1 1 1540 sub getmarkets { return shift->_api_query('getmarkets' ); }
29 1     1 1 1247 sub mytransactions { return shift->_api_query('mytransactions' ); }
30 1     1 1 2157 sub allmyorders { return shift->_api_query('allmyorders' ); }
31 1     1 1 1625 sub cancelallorders { return shift->_api_query('cancelallorders'); }
32 1     1 1 1562 sub allmytrades { return shift->_api_query('allmytrades' ); }
33              
34             sub singlemarketdata {
35 1     1 1 1234 my ( $self, $market_id ) = @_;
36 1         5 return $self->_api_query(
37             'singlemarketdata', marketid => $market_id,
38             );
39             }
40              
41             sub singleorderdata {
42 1     1 1 2090 my ( $self, $market_id ) = @_;
43 1         7 return $self->_api_query(
44             'singleorderdata', marketid => $market_id,
45             );
46             }
47              
48             sub markettrades {
49 1     1 1 1778 my ( $self, $market_id ) = @_;
50 1         6 return $self->_api_query(
51             'markettrades', marketid => $market_id,
52             );
53             }
54              
55             sub marketorders {
56 1     1 1 1437 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 1504 my ( $self, $market_id, $limit ) = @_;
64 1   50     4 $limit ||= 200;
65 1         3 return $self->_api_query(
66             'mytrades', marketid => $market_id, limit => $limit,
67             );
68             }
69              
70             sub myorders {
71 1     1 1 1278 my ( $self, $market_id ) = @_;
72 1         4 return $self->_api_query(
73             'myorders', marketid => $market_id,
74             );
75             }
76              
77             sub depth {
78 1     1 1 1312 my ( $self, $market_id ) = @_;
79 1         4 return $self->_api_query(
80             'depth', marketid => $market_id,
81             );
82             }
83              
84             sub createorder {
85 2     2 1 3164 my ( $self, $market_id, $order_type, $quantity, $price ) = @_;
86 2         10 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 1757 my ( $self, $market_id ) = @_;
104 1         5 return $self->_api_query(
105             'cancelmarketorders', marketid => $market_id,
106             );
107             }
108              
109             sub calculatefees {
110 1     1 1 1334 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 15953 my ( $self, $currency_id, $currency_code ) = @_;
121 3 100       21 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   8662 my ( $self, $json, $method ) = @_;
132              
133 21 50       100 unless ( $json ) {
134 0         0 $self->error('Network error: got no data');
135             return
136 0         0 }
137              
138 21         142 $self->error( undef );
139              
140 21         37 my $decoded = eval { decode_json( $json ); };
  21         88338  
141 21 50       592 if ( $@ ) {
142 0         0 $self->error('JSON parsing error: ' . $@);
143 0         0 return;
144             }
145              
146 21 100 66     178 unless ( $decoded and $decoded->{success} ) {
147 2 50 33     24 $self->error( $decoded && $decoded->{error}
148             ? $decoded->{error}
149             : 'Unknown JSON parsing error'
150             );
151 2         158 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     98 $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       1110 if ( $method eq 'cancelorder' ) {
165 0         0 $decoded->{return} = 1;
166             }
167              
168 19 50       1550 unless ( $decoded->{return} ) {
169 0         0 $self->error('Return given by Cryptsy is empty');
170 0         0 return;
171             }
172              
173 19         4289 return $decoded->{return};
174             }
175              
176             sub _api_query {
177 21     21   74 my ( $self, $method, %req_args ) = @_;
178              
179              
180 21         404 my $ua = LWP::UserAgent->new( timeout => $self->timeout );
181 21         43385 my $res;
182 21         173 my %get_methods = map +( $_ => 1 ), qw/
183             marketdata marketdatav2 singlemarketdata
184             orderdata singleorderdata
185             /;
186 21 100       89 if ( $get_methods{ $method } ) {
187 3         16 my $url = URI->new( API_GET_URL );
188 3 100       18201 $url->query_form(
189             method => $method,
190             $method =~ /^single(market|order)data$/
191             ? ( marketid => $req_args{marketid} ) : ()
192             );
193              
194 3         517 $res = $ua->get( $url );
195             }
196             else {
197 18         254 my $req = POST(
198             API_POST_URL, [
199             %req_args,
200             method => $method,
201             nonce => time(),
202             ]
203             );
204              
205 18         115384 my $digest = hmac_sha512_hex( $req->content, $self->private_key );
206 18         887 $req->header( Sign => $digest, );
207 18         909 $req->header( Key => $self->public_key, );
208              
209 18         722 $res = $ua->request( $req );
210             }
211              
212 21 50       40635119 unless ( $res->is_success ) {
213 0         0 $self->error('Network error: ' . $res->status_line );
214 0         0 return;
215             }
216 21         459 return $self->_decode( $res->decoded_content, $method );
217             }
218              
219              
220             1;
221              
222             __END__