WebService-Cryptsy

 view release on metacpan or  search on metacpan

lib/WebService/Cryptsy.pm  view on Meta::CPAN

package WebService::Cryptsy;

use Moo;

our $VERSION = '1.008007'; # VERSION

use URI;
use JSON::MaybeXS;
use LWP::UserAgent;
use Digest::SHA qw/hmac_sha512_hex/;
use HTTP::Request::Common qw/POST/;

use constant API_POST_URL => 'https://api.cryptsy.com/api';
use constant API_GET_URL  => 'http://pubapi.cryptsy.com/api.php';
use overload '""' => sub { shift->error };


has public_key  => ( is => 'ro', );
has private_key => ( is => 'ro', );
has error       => ( is => 'rw', );
has timeout     => ( is => 'rw', default => 60 );

########## API METHODS ##########
sub marketdata      { return shift->_api_query('marketdata'     ); }
sub marketdatav2    { return shift->_api_query('marketdatav2'   ); }
sub orderdata       { return shift->_api_query('orderdata'      ); }
sub getinfo         { return shift->_api_query('getinfo'        ); }
sub getmarkets      { return shift->_api_query('getmarkets'     ); }
sub mytransactions  { return shift->_api_query('mytransactions' ); }
sub allmyorders     { return shift->_api_query('allmyorders'    ); }
sub cancelallorders { return shift->_api_query('cancelallorders'); }
sub allmytrades     { return shift->_api_query('allmytrades'    ); }

sub singlemarketdata {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(
        'singlemarketdata', marketid => $market_id,
    );
}

sub singleorderdata {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(
        'singleorderdata', marketid => $market_id,
    );
}

sub markettrades {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(
        'markettrades', marketid => $market_id,
    );
}

sub marketorders {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(
        'marketorders', marketid => $market_id,
    );
}

sub mytrades {
    my ( $self, $market_id, $limit ) = @_;
    $limit ||= 200;
    return $self->_api_query(
        'mytrades', marketid => $market_id, limit => $limit,
    );
}

sub myorders {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(
        'myorders', marketid => $market_id,
    );
}

sub depth {
    my ( $self, $market_id ) = @_;
    return $self->_api_query(

lib/WebService/Cryptsy.pm  view on Meta::CPAN


    unless ( $decoded and $decoded->{success} ) {
        $self->error( $decoded && $decoded->{error}
            ? $decoded->{error}
            : 'Unknown JSON parsing error'
        );
        return;
    }

    ## Seems to be a bug in API, as it returns a null instead of an
    ## Empty array, as it does for other similar methods
    $decoded->{return} = []
        if not defined $decoded->{return}
            and (
                   $method eq 'mytransactions'
                or $method eq 'cancelmarketorders'
                or $method eq 'cancelallorders'
            );

    if ( $method eq 'cancelorder' ) {
        $decoded->{return} = 1;
    }

    unless ( $decoded->{return} ) {
        $self->error('Return given by Cryptsy is empty');
        return;
    }

    return $decoded->{return};
}

sub _api_query {
    my ( $self, $method, %req_args ) = @_;


    my $ua = LWP::UserAgent->new( timeout => $self->timeout );
    my $res;
    my %get_methods = map +( $_ => 1 ), qw/
        marketdata  marketdatav2     singlemarketdata
        orderdata   singleorderdata
    /;
    if ( $get_methods{ $method } ) {
        my $url = URI->new( API_GET_URL );
        $url->query_form(
            method  => $method,
            $method =~ /^single(market|order)data$/
            ? ( marketid => $req_args{marketid} ) : ()
        );

        $res = $ua->get( $url );
    }
    else {
        my $req = POST(
            API_POST_URL, [
                %req_args,
                method => $method,
                nonce  => time(),
            ]
        );

        my $digest = hmac_sha512_hex( $req->content, $self->private_key );
        $req->header( Sign => $digest,           );
        $req->header( Key  => $self->public_key, );

        $res = $ua->request( $req );
    }

    unless ( $res->is_success ) {
        $self->error('Network error: ' . $res->status_line );
        return;
    }
    return $self->_decode( $res->decoded_content, $method );
}


1;

__END__

=encoding utf8

=for stopwords EST Orderbook buyorders com cryptsy sellorders tradeprice www www.cryptsy.com www.cryptsy.com. marketdatav marketdatav2

=head1 NAME

WebService::Cryptsy - implementation of www.cryptsy.com API

=head1 SYNOPSIS

    use WebService::Cryptsy;
    use Data::Dumper;

    my $cryp = WebService::Cryptsy->new(
        public_key  => 'YOUR PUBLICE KEY',
        private_key => 'YOUR PRIVATE KEY',
    );

    print Dumper( $cryp->getinfo      || $cryp->error ) . "\n";
    print Dumper( $cryp->marketdatav2 || $cryp->error ) . "\n";

    my ( $currency_id, $currency_code ) = ( 3, 'BTC' );
    my $generated_address
    = $cryp->generatenewaddress( $currency_id, $currency_code )
        or die "Error: " . $cryp->error;


    $cryp = WebService::Cryptsy->new; # no need for keys for some methods
    my $data = $cryp->marketdatav2
        or die "Error: $cryp";  # error checking and using interpolation
                                # to get the error message

    printf "%s: %f\n", @{ $data->{markets}{$_} }{qw/label  lasttradeprice/}
        for sort keys %{ $data->{markets} };

=head1 MAINTENANCE NOTE

B<NOTE: this module has not been keeping up with Cryptsy's API updates
since Feb 4, 2014. Reason being is that I don't personally use this
module and the person I wrote it for might not be using it any more
either. But if you do use this module and need it updated, just
submit a bug report (patches are also welcome!).>

=head1 DESCRIPTION

This module implements the L<www.cryptsy.com API|https://www.cryptsy.com/pages/api> whose description is available here:
L<https://www.cryptsy.com/pages/api|https://www.cryptsy.com/pages/api>

=head1 INSTALLATION NOTES

Depending on your configuration, you might need to install

    cpan LWP::Protocol::https  Net::SSLeay

Or some such, to make L<LWP::UserAgent> work over HTTPS, as that's what
Cryptsy's API requires.

=head1 GETTING API KEY

To use this module, you'll need to obtain the API key from
L<www.cryptsy.com|https://www.cryptsy.com/>. Once logged in,
go to L<account settings page|https://www.cryptsy.com/users/settings>
and scroll all the way to the bottom. Click the I<Generate New Key> button
to generate new key.

B<IMPORTANT!!! Ensure to toggle the "API Disabled"
button into the "on" position, otherwise your API will be off and this
module will give a confusing error message.>

=head1 CONSTRUCTOR

=head2 C<new>

    my $cryp = WebService::Cryptsy->new(
        public_key  => 'YOUR PUBLIC  KEY',
        private_key => 'YOUR PRIVATE KEY',
        timeout     => 30,
    );

    # or if you're only going to use the public methods:
    my $cryp = WebService::Cryptsy->new;

Creates and returns a new C<WebService::Cryptsy> object. B<Takes>
three optional arguments as key/value pairs. The
C<public_key> and C<private_key> are optional only for the
I<Public Methods> of the API. They both are required for calling the
I<Authenticated Methods>. To obtain your keys, see the L<GETTING API KEY>
section above.

=head3 C<public_key>

    my $cryp = WebService::Cryptsy->new(
        public_key  => '479c5eee116f8f5972bdaf12dd0a3f82562c8a7c',
        private_key => 'b408e899526142eee13304669a657c8782435ccda2f65dbea05270fe8dfa5d3d2ef7eb4812ce1c35',
    );

This is the key from the I<Public Key> box on
L<Cryptsy's settings page|https://www.cryptsy.com/users/settings>.

=head3 C<private_key>

    my $cryp = WebService::Cryptsy->new(
        public_key  => '479c5eee116f8f5972bdaf12dd0a3f82562c8a7c',
        private_key => 'b408e899526142eee13304669a657c8782435ccda2f65dbea05270fe8dfa5d3d2ef7eb4812ce1c35',
    );

This is the key from the I<Private Key> box on
L<Cryptsy's settings page|https://www.cryptsy.com/users/settings>.

=head3 C<timeout>

    my $cryp = WebService::Cryptsy->new(
        timeout => 30,
    );

B<Optional>. Specifies the timeout, in seconds, of the API requests.
B<Default:> C<60>

=head1 MODULE METHODS / OVERLOADS

=head2 C<error>

    # these two are equivalent
    my $data = $cryp->marketdata
        or die "Error: $cryp";


    my $data = $cryp->marketdata
        or die "Error: " . $cryp->error;

The API methods will return C<undef> or an empty list,
depending on the context, and the human-readable error will be available
using the C<< ->error >> method. This method is overloaded for object
interpolation, thus you can simply interpolate the object in a string
to get the error message.

=head2 C<timeout>

    printf "Current API request timeout is %d\n", $cryp->timeout;

    $cryp->timeout( 30 );

Gets/sets the C<timeout> constructor's argument. B<Takes> one optional
argument that specifies the new timeout in seconds. B<Returns> the
current timeout in seconds.

=head1 GENERAL CONVENTION FOR API METHODS

All methods are named exactly the same as in
L<Cryptsy's API|https://www.cryptsy.com/pages/api>. If the API method
takes any arguments, you'd supply them to the method, in the same order
(e.g. C<< $cryp->mytrades( $market_id,  $limit ); >>)

=head1 PUBLIC API METHODS

These methods do not require API keys.

=head2 C<marketdata>

    my $data = $cryp->marketdata
        or die "Error: $cryp";

B<NOTE: this API call doesn't seem to be listed on Cryptsy's site
any more. You're likely supposed to use marketdatav2 instead.>



( run in 0.622 second using v1.01-cache-2.11-cpan-39bf76dae61 )