File Coverage

blib/lib/Finance/Crypto/Exchange/Kraken.pm
Criterion Covered Total %
statement 39 48 81.2
branch 2 6 33.3
condition n/a
subroutine 12 14 85.7
pod 1 1 100.0
total 54 69 78.2


line stmt bran cond sub pod time code
1 1     1   1378 use utf8;
  1         16  
  1         5  
2              
3             package Finance::Crypto::Exchange::Kraken;
4             our $VERSION = '0.001';
5 1     1   605 use Moose;
  1         512638  
  1         10  
6 1     1   8723 use namespace::autoclean;
  1         8778  
  1         5  
7 1     1   789 use LWP::UserAgent;
  1         17868  
  1         43  
8 1     1   491 use MooseX::Types::URI qw(Uri);
  1         212958  
  1         9  
9 1     1   2176 use JSON qw(decode_json);
  1         3  
  1         12  
10 1     1   172 use Try::Tiny;
  1         2  
  1         77  
11 1     1   8 use MIME::Base64 qw(decode_base64url);
  1         2  
  1         56  
12 1     1   793 use Time::HiRes qw(gettimeofday);
  1         1724  
  1         4  
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   3 my $self = shift;
25 1         26 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         3336 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 116 my ($self, $req) = @_;
62              
63 42         1558 my $response = $self->ua->request($req);
64 42 50       19669 if ($response->is_success) {
65 42         442 my $data;
66             try {
67 42     42   4448 $data = decode_json($response->decoded_content);
68             }
69             catch {
70 0     0   0 die "Unable to decode JSON from Kraken!", $/;
71 42         318 };
72              
73 42 50       5564 if (@{$data->{error}}) {
  42         149  
74 0 0       0 if (@{$data->{error}} > 1) {
  0         0  
75             die "Multiple errors occurred: " .
76 0         0 join($/, @{$data->{error}})
  0         0  
77             , $/;
78             }
79             else {
80 0         0 die $data->{error}[0], $/;
81             }
82             }
83 42         335 return $data->{result};
84             }
85 0           die "Error calling Kraken: " . $response->status_line, $/;
86              
87             }
88              
89             around 'BUILDARGS' => sub {
90             my ($orig, $class, %args) = @_;
91             if (my $secret = delete $args{secret}) {
92             $args{secret} = decode_base64url($secret);
93             }
94             return $class->$orig(%args);
95             };
96              
97              
98             with qw(
99             Finance::Crypto::Exchange::Kraken::REST::Public
100             Finance::Crypto::Exchange::Kraken::REST::Private
101             );
102              
103             __PACKAGE__->meta->make_immutable;
104              
105             __END__
106              
107             =pod
108              
109             =encoding UTF-8
110              
111             =head1 NAME
112              
113             Finance::Crypto::Exchange::Kraken - A Perl implementation of the Kraken REST API
114              
115             =head1 VERSION
116              
117             version 0.001
118              
119             =head1 SYNOPSIS
120              
121             package Foo;
122             use Finance::Crypto::Exchange::Kraken;
123              
124             my $kraken = Finance::Crypto::Exchange::Kraken->new(
125             key => 'your very secret key',
126             secret => 'your very secret secret',
127             );
128              
129             # For all methods, please visit the documentation
130             $kraken->get_server_time;
131              
132             =head1 DESCRIPTION
133              
134             Talk to the Kraken REST API within Perl
135              
136             =head1 METHODS
137              
138             =head2 call
139              
140             my $req = HTTP::Request->new(GET, ...);
141             $self->call($req);
142              
143             A very simple API call function.
144             Decodes the JSON for you on success, otherwise dies a horrible death with the
145             error Kraken gives back to you.
146              
147             You should not be needing this method, this function is public because all the
148             roles use it.
149              
150             =head2 nonce
151              
152             Create a nonce
153              
154             =head1 SEE ALSO
155              
156             =over
157              
158             =item L<Finance::Crypto::Exchange::Kraken::REST::Public>
159              
160             =item L<Finance::Crypto::Exchange::Kraken::REST::Private>
161              
162             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Data>
163              
164             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Trading>
165              
166             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::User::Funding>
167              
168             =item L<Finance::Crypto::Exchange::Kraken::REST::Private::Websockets>
169              
170             =back
171              
172             There is another module that does more or less the same:
173             L<Finance::Bank::Kraken> but it requires a more hands on approach.
174              
175             =head1 AUTHOR
176              
177             Wesley Schwengle <waterkip@cpan.org>
178              
179             =head1 COPYRIGHT AND LICENSE
180              
181             This software is Copyright (c) 2020 by Wesley Schwengle.
182              
183             This is free software, licensed under:
184              
185             The (three-clause) BSD License
186              
187             =cut