Finance-Indodax

 view release on metacpan or  search on metacpan

lib/Finance/Indodax.pm  view on Meta::CPAN

package Finance::Indodax;

our $DATE = '2018-06-13'; # DATE
our $VERSION = '0.011'; # VERSION

use 5.010001;
use strict;
use warnings;
use Log::ger;

use Digest::SHA qw(hmac_sha512_hex);
use Time::HiRes qw(time);

my $url_prefix = "https://indodax.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 (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 _get_json {
    my ($self, $url) = @_;

    log_trace("JSON API request: %s", $url);

    my $res = $self->{_http}->get($url);
    die "Can't retrieve $url: $res->{status} - $res->{reason}"
        unless $res->{success};
    my $decoded;
    eval { $decoded = $self->{_json}->decode($res->{content}) };
    die "Can't decode response from $url: $@" if $@;

    log_trace("JSON API response: %s", $decoded);

    $decoded;
}

sub tapi {
    my ($self, $method, %args) = @_;

    $self->{key} or die "Please supply API key in new()";
    $self->{secret} or die "Please supply API secret in new()";

    my $time = time();
    my $form = {
        %args,
        method => $method,
        # ms after 2015-01-01
        nonce => int(1000 * (time() - 1_420_045_200)),
    };

    log_trace("TAPI request: %s", $form);

    my $encoded_form = join(
        "&",
        map { $self->{_urienc}->encode($_ // ''). "=" .
                  $self->{_urienc}->encode($form->{$_} // '') }
            sort keys(%$form),
    );

    my $options = {
        headers => {
            Key => $self->{key},
            Sign => hmac_sha512_hex($encoded_form, $self->{secret}),

            # XXX why do i have to do this manually?
            "Content-Length" => length($encoded_form),
            "Content-Type" => "application/x-www-form-urlencoded",
        },
        content => $encoded_form,
    };

    my $url = "$url_prefix/tapi/";
    my $res = $self->{_http}->post($url, $options);
    die "Can't retrieve $url: $res->{status} - $res->{reason}"
        unless $res->{success};
    my $decoded;
    eval { $decoded = $self->{_json}->decode($res->{content}) };
    die "Can't decode response from $url: $@" if $@;

    log_trace("TAPI response: %s", $decoded);

    die "API response not a hash: $decoded" unless ref $decoded eq 'HASH';
    die "API response is not success: $decoded->{error}" unless $decoded->{success};
    $decoded;
}

sub _check_pair {
    my $pair = shift;
    $pair =~ /\A(\w{3,5})_(\w{3,5})\z/
        or die "Invalid pair: must be in the form of 'abc_xyz'";
}

sub get_ticker {
    my ($self, %args) = @_;
    $args{pair} //= "btc_idr";
    _check_pair($args{pair});
    $self->_get_json("$url_prefix/api/$args{pair}/ticker");
}

sub get_trades {
    my ($self, %args) = @_;
    $args{pair} //= "btc_idr";
    _check_pair($args{pair});

    $self->_get_json("$url_prefix/api/$args{pair}/trades");
}

sub get_depth {
    my ($self, %args) = @_;
    $args{pair} //= "btc_idr";
    _check_pair($args{pair});

    $self->_get_json("$url_prefix/api/$args{pair}/depth");
}

sub get_price_history {
    my ($self, %args) = @_;
    $args{pair} //= "btc_idr"; # note: pair other than btc_idr does not seem to be supported
    _check_pair($args{pair});
    $args{period} //= 'day';
    $args{period} =~ /\A(day|all)\z/
        or die "Invalid period: must be day|all";

    if ($args{period} eq 'all') {
        $self->_get_json("$url_prefix/api/$args{pair}/chartdata");
    } else {
        $self->_get_json("$url_prefix/api/$args{pair}/chart_1d");
    }
}

sub get_info {
    my ($self, %args) = @_;
    $self->tapi("getInfo");
}

sub get_tx_history {
    my ($self, %args) = @_;
    $self->tapi("transHistory");
}

sub get_trade_history {
    my ($self, %args) = @_;
    die "Please specify pair" unless $args{pair};
    $self->tapi(



( run in 0.477 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )