File Coverage

blib/lib/Finance/Crypto/Exchange/Kraken.pm
Criterion Covered Total %
statement 42 51 82.3
branch 2 6 33.3
condition n/a
subroutine 12 14 85.7
pod 1 1 100.0
total 57 72 79.1


line stmt bran cond sub pod time code
1 1     1   1355 use utf8;
  1         16  
  1         6  
2              
3             package Finance::Crypto::Exchange::Kraken;
4             our $VERSION = '0.002';
5 1     1   663 use Moose;
  1         499176  
  1         9  
6 1     1   8633 use namespace::autoclean;
  1         8520  
  1         3  
7 1     1   799 use LWP::UserAgent;
  1         17323  
  1         42  
8 1     1   468 use MooseX::Types::URI qw(Uri);
  1         207812  
  1         6  
9 1     1   2138 use JSON qw(decode_json);
  1         3  
  1         12  
10 1     1   164 use Try::Tiny;
  1         3  
  1         71  
11 1     1   6 use MIME::Base64 qw(decode_base64url);
  1         3  
  1         55  
12 1     1   718 use Time::HiRes qw(gettimeofday);
  1         1537  
  1         7  
13              
14             # ABSTRACT: A Perl implementation of the Kraken REST API
15              
16             has ua => (
17             is => 'ro',
18             isa => 'LWP::UserAgent',
19             lazy => 1,
20             builder => '_build_ua',
21             );
22              
23             sub _build_ua {
24 1     1   2 my $self = shift;
25 1         16 my $ua = LWP::UserAgent->new(
26             agent => sprintf("%s/%s", __PACKAGE__, $VERSION),
27             timeout => 10,
28             protocols_allowed => ['https'],
29             max_redirect => 0,
30             ssl_opts => { verify_hostname => 1 },
31             );
32 1         3346 return $ua;
33             }
34              
35             has _uri => (
36             is => 'ro',
37             isa => Uri,
38             coerce => 1,
39             default => 'https://api.kraken.com',
40             init_arg => 'base_uri',
41             );
42              
43             has key => (
44             is => 'ro',
45             isa => 'Str',
46             predicate => 'has_key',
47             );
48              
49             has secret => (
50             is => 'ro',
51             isa => 'Str',
52             predicate => 'has_secret',
53             );
54              
55             sub nonce {
56 0     0   0 my $self = shift;
57 0         0 return gettimeofday() * 100000;
58             }
59              
60             sub call {
61 42     42 1 99 my ($self, $req) = @_;
62              
63 42         113 foreach (qw(Content-Type Content-Length)) {
64 84         1021 $req->headers->remove_header($_);
65             }
66              
67 42         759 $req->headers->header(Accept => 'application/json');
68              
69 42         3357 my $response = $self->ua->request($req);
70              
71 42 50       19030 if ($response->is_success) {
72 42         357 my $data;
73             try {
74 42     42   4471 $data = decode_json($response->decoded_content);
75             }
76             catch {
77 0     0   0 die "Unable to decode JSON from Kraken!", $/;
78 42         284 };
79              
80 42 50       5396 if (@{$data->{error}}) {
  42         156  
81 0 0       0 if (@{$data->{error}} > 1) {
  0         0  
82             die "Multiple errors occurred: " .
83 0         0 join($/, @{$data->{error}})
  0         0  
84             , $/;
85             }
86             else {
87 0         0 die $data->{error}[0], $/;
88             }
89             }
90 42         334 return $data->{result};
91             }
92 0           die "Error calling Kraken: " . $response->status_line, $/;
93              
94             }
95              
96             around 'BUILDARGS' => sub {
97             my ($orig, $class, %args) = @_;
98             if (my $secret = delete $args{secret}) {
99             $args{secret} = decode_base64url($secret);
100             }
101             return $class->$orig(%args);
102             };
103              
104              
105             with qw(
106             Finance::Crypto::Exchange::Kraken::REST::Public
107             Finance::Crypto::Exchange::Kraken::REST::Private
108             );
109              
110             __PACKAGE__->meta->make_immutable;
111              
112             __END__
113              
114             =pod
115              
116             =encoding UTF-8
117              
118             =head1 NAME
119              
120             Finance::Crypto::Exchange::Kraken - A Perl implementation of the Kraken REST API
121              
122             =head1 VERSION
123              
124             version 0.002
125              
126             =head1 SYNOPSIS
127              
128             package Foo;
129             use Finance::Crypto::Exchange::Kraken;
130              
131             my $kraken = Finance::Crypto::Exchange::Kraken->new(
132             key => 'your very secret key',
133             secret => 'your very secret secret',
134             );
135              
136             # For all methods, please visit the documentation
137             $kraken->get_server_time;
138              
139             =head1 DESCRIPTION
140              
141             Talk to the Kraken REST API within Perl
142              
143             =head1 METHODS
144              
145             =head2 call
146              
147             my $req = HTTP::Request->new(GET, ...);
148             $self->call($req);
149              
150             A very simple API call function.
151             Decodes the JSON for you on success, otherwise dies a horrible death with the
152             error Kraken gives back to you.
153              
154             You should not be needing this method, this function is public because all the
155             roles use it.
156              
157             =head2 nonce
158              
159             Create a nonce
160              
161             =head1 SEE ALSO
162              
163             =over
164              
165             =item L<Finance::Crypto::Exchange::Kraken::REST::Public>
166              
167             =item L<Finance::Crypto::Exchange::Kraken::REST::Private>
168              
169             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Data>
170              
171             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Trading>
172              
173             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Funding>
174              
175             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::Websockets>
176              
177             =back
178              
179             There is another module that does more or less the same:
180             L<Finance::Bank::Kraken> but it requires a more hands on approach.
181              
182             =head1 AUTHOR
183              
184             Wesley Schwengle <waterkip@cpan.org>
185              
186             =head1 COPYRIGHT AND LICENSE
187              
188             This software is Copyright (c) 2020 by Wesley Schwengle.
189              
190             This is free software, licensed under:
191              
192             The (three-clause) BSD License
193              
194             =cut