Finance-GDAX-Lite/lib/Finance/GDAX/Lite.pm
package Finance::GDAX::Lite;
our $DATE = '2018-06-14'; # DATE
our $VERSION = '0.003'; # VERSION
use 5.010001;
use strict;
use warnings;
use Log::ger;
use Digest::SHA qw(hmac_sha256_base64);
use MIME::Base64 qw(decode_base64);
use Time::HiRes qw(time);
my $url_prefix = "https://api.gdax.com";
sub new {
my ($class, %args) = @_;
my $self = {};
if (my $key = delete $args{key}) {
$self->{key} = $key;
}
if (my $secret = delete $args{secret}) {
$self->{secret} = $secret;
}
if (my $passphrase = delete $args{passphrase}) {
$self->{passphrase} = $passphrase;
}
if (keys %args) {
die "Unknown argument(s): ".join(", ", sort keys %args);
}
require HTTP::Tiny;
$self->{_http} = HTTP::Tiny->new;
require JSON::XS;
$self->{_json} = JSON::XS->new;
require URI::Encode;
$self->{_urienc} = URI::Encode->new;
bless $self, $class;
}
sub _request {
my ($self, $is_private, $method, $request_path, $params) = @_;
$params //= {};
if ($is_private) {
$self->{key} or die "Please supply API key in new()";
$self->{secret} or die "Please supply API secret in new()";
$self->{passphrase} or die "Please supply API passphrase in new()";
}
my $time = $ENV{FINANCE_GDAX_LITE_DEBUG_TIME} // sprintf "%.3f", time();
log_trace("API %s request [%s]: %s %s %s",
$is_private ? "private" : "public",
$time, $method, $request_path, $params);
my $url = "$url_prefix$request_path";
my $body;
my $encoded_body = '';
if ($method eq 'POST') {
$body = $encoded_body = $self->{_json}->encode($params);
} else {
if (keys %$params) {
my $qs = '?' . join(
"&",
map { $self->{_urienc}->encode($_ // ''). "=" .
$self->{_urienc}->encode($params->{$_} // '') }
sort keys(%$params),
);
$url .= $qs;
$encoded_body = $qs;
}
}
my $signature;
if ($is_private) {
my $what = $time . $method . $request_path . $encoded_body;
$signature = hmac_sha256_base64($what, decode_base64($self->{secret}));
while (length($signature) % 4) { $signature .= '=' }
}
my $options = {
headers => {
("CB-ACCESS-KEY" => $self->{key}) x !!$is_private,
("CB-ACCESS-SIGN" => $signature ) x !!$is_private,
("CB-ACCESS-TIMESTAMP" => $time ) x !!$is_private,
("CB-ACCESS-PASSPHRASE" => $self->{passphrase}) x !!$is_private,,
"Content-Type" => "application/json",
"Accept" => "application/json",
},
(content => $body) x !!defined($body),
};
my $res = $self->{_http}->request($method, $url, $options);
# HTTP::Tiny puts error message in content
if (!$res->{success} && $res->{status} == 599 &&
$res->{reason} eq 'Internal Exception') {
$res->{content} =~ s/\R/ /g;
$res->{reason} .= ": $res->{content}";
undef $res->{content};
}
if ($res->{headers}{'content-type'} =~ m!application/json!) {
$res->{content} = $self->{_json}->decode($res->{content});
log_trace("API response [%s]: JSON: %s", $time, $res->{content});
} else {
log_trace("API response [%s]: non-JSON: %s", $time, $res->{content});
}
my $reason = $res->{reason};
if ($res->{status} != 200 &&
ref($res->{content}) eq 'HASH' && $res->{content}{message}) {
$reason .= ": $res->{content}{message}";
}
[$res->{status}, $reason, $res->{content}];
}
sub public_request {
my $self = shift;
$self->_request(0, @_);
}
sub private_request {
my $self = shift;
$self->_request(1, @_);
}
1;
# ABSTRACT: Client API library for GDAX (lite edition)
__END__
=pod
=encoding UTF-8
=head1 NAME
Finance::GDAX::Lite - Client API library for GDAX (lite edition)
=head1 VERSION
This document describes version 0.003 of Finance::GDAX::Lite (from Perl distribution Finance-GDAX-Lite), released on 2018-06-14.
=head1 SYNOPSIS
use Finance::GDAX::Lite;
my $gdax = Finance::GDAX::Lite->new(
key => 'Your API key',
secret => 'Your API secret',
passphrase => 'Your API passphrase',
);
my $res = $gdax->public_request(GET => "/products");
# [
# 200,
# "OK",
# [
# {
# base_currency => "BCH",
# base_max_size => 200,
# ...
# },
# ...
# ]
# ]
my $res = $gdax->private_request(GET => "/coinbase-accounts");
# [
# 200,
# "OK",
# [
# {
# active => 1,
# balance => "0.00",
# currency => "USD",
# name => "USD wallet",
# ...
# },
# ...
# ]
# ]
my $res = $gdax->private_request(POST => "/reports", {
type => "fills",
start_date => "2018-02-01T00:00:00.000Z",
end_date => "2018-02-01T00:00:00.000Z",
});
=head1 DESCRIPTION
L<https://gdax.com> is a US cryptocurrency exchange. This module provides a Perl
wrapper for GDAX's API. This module is an alternative to L<Finance::GDAX::API>
and is more lightweight/barebones (no entity objects, Moose, etc). Please peruse
the GDAX API reference to see which API endpoints are available.
=head1 METHODS
=head2 new
Usage: new(%args)
Constructor. Known arguments:
=over
=item * key
=item * secret
=item * passphrase
=back
=head2 public_request
Usage: public_request($method, $request_path [, \%params ]) => [$status_code, $message, $content]
Will send HTTP request and decode the JSON body for you.
=head2 private_request
Usage: public_request($method, $request_path [, \%params ]) => [$status_code, $message, $content]
Will send and sign HTTP request and decode the JSON body for you.
=head1 HOMEPAGE
Please visit the project's homepage at L<https://metacpan.org/release/Finance-GDAX-Lite>.
=head1 SOURCE
Source repository is at L<https://github.com/perlancar/perl-Finance-GDAX-Lite>.
=head1 BUGS
Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Finance-GDAX-Lite>
When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.
=head1 SEE ALSO
GDAX API Reference, L<https://docs.gdax.com/>
L<Finance::GDAX::API>
=head1 AUTHOR
perlancar <perlancar@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2018 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut