Bitcoin-RPC-Client

 view release on metacpan or  search on metacpan

lib/Bitcoin/RPC/Client.pm  view on Meta::CPAN

package Bitcoin::RPC::Client;

use 5.008;

use strict;
use warnings;

use Moo;
use JSON::RPC::Legacy::Client;

our $VERSION  = '0.12';

has jsonrpc  => (is => "lazy", default => sub { "JSON::RPC::Legacy::Client"->new });
has user     => (is => 'ro');
has password => (is => 'ro');
has cookie   => (is => 'ro', isa => \&isa_cookie);
has host     => (is => 'ro');
has wallet   => (is => 'ro');
has port     => (is => "lazy", default => 8332);
has timeout  => (is => "lazy", default => 20);
has debug    => (is => "lazy", default => 0);

# SSL constructor options
#  OpenSSL support has been removed from Bitcoin Core as of v0.12.0
#  but should work with older versions
has ssl      => (is => 'ro', default => 0);
has verify_hostname => (is => 'ro', default => 1);

my $DEBUG_DUMPED = 0;

sub AUTOLOAD {
   my $self   = shift;
   my $method = $Bitcoin::RPC::Client::AUTOLOAD;

   $method =~ s/.*:://;

   return if ($method eq 'DESTROY');

   # Build request URL
   my $url = "";

   # Are we using SSL?
   my $uri = "http://";
   if ($self->ssl eq 1) {
      $uri = "https://";
   }

   # Cookie will take precedence over user/password
   if ($self->cookie) {
      # If cookie is defined its contents become user:password
      $url = $uri . $self->cookie . "\@" . $self->host . ":" . $self->port;
   } elsif ($self->user) {
      $url = $uri . $self->user . ":" . $self->password . "\@" . $self->host . ":" . $self->port;
   } else {
      die "An RPC user or RPC cookie file must be defined\n";
   }

   # Tack on a specific wallet name if given
   if ($self->wallet) {
      $url .= "/wallet/" . $self->wallet;
   }

   my $client = $self->jsonrpc;

   # Set timeout because bitcoin is slow
   $client->ua->timeout($self->timeout);

   # Set Agent, let them know who we be
   $client->ua->agent("Bitcoin::RPC::Client/" . $VERSION);

   # Turn on debugging for LWP::UserAgent
   if ($self->debug) {
      if (!$DEBUG_DUMPED) { # We only want to set this up once
         $client->ua->add_handler("request_send",  sub { shift->dump; return });
         $client->ua->add_handler("response_done", sub { shift->dump; return });
         $DEBUG_DUMPED = 1;
      }
   }

   # For self signed certs
   if ($self->verify_hostname eq 0) {
      $client->ua->ssl_opts( verify_hostname => 0,
                             SSL_verify_mode => 0 );
   }

   # Build the RPC
   my $obj = {
      method => $method,
      params => (ref $_[0] ? $_[0] : [@_]),
   };
   my $res;
   eval {
      # Attempt the RPC
      $res = $client->call( $url, $obj );
   } or do {
      # Test the HTTP service and die with usable output if above RPC call fails
      my $tr = $client->ua->post($url);
      die $tr->status_line;
   };
   if($res) {
      if ($res->is_error) {
          my $content = $res->content;
          die sprintf("error code: %d, error message: %s (%s)\n", $content->{error}->{code}, $content->{error}->{message}, $method);
      }

      return $res->result;
   }



( run in 0.764 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )