File Coverage

blib/lib/Bitcoin/RPC/Client.pm
Criterion Covered Total %
statement 35 64 54.6
branch 10 30 33.3
condition 0 3 0.0
subroutine 6 9 66.6
pod 0 1 0.0
total 51 107 47.6


line stmt bran cond sub pod time code
1             package Bitcoin::RPC::Client;
2              
3 2     2   106684 use 5.008;
  2         13  
4              
5 2     2   9 use strict;
  2         3  
  2         32  
6 2     2   8 use warnings;
  2         3  
  2         61  
7              
8 2     2   868 use Moo;
  2         18142  
  2         8  
9 2     2   3122 use JSON::RPC::Legacy::Client;
  2         104770  
  2         1667  
10              
11             our $VERSION = '0.12';
12              
13             has jsonrpc => (is => "lazy", default => sub { "JSON::RPC::Legacy::Client"->new });
14             has user => (is => 'ro');
15             has password => (is => 'ro');
16             has cookie => (is => 'ro', isa => \&isa_cookie);
17             has host => (is => 'ro');
18             has wallet => (is => 'ro');
19             has port => (is => "lazy", default => 8332);
20             has timeout => (is => "lazy", default => 20);
21             has debug => (is => "lazy", default => 0);
22              
23             # SSL constructor options
24             # OpenSSL support has been removed from Bitcoin Core as of v0.12.0
25             # but should work with older versions
26             has ssl => (is => 'ro', default => 0);
27             has verify_hostname => (is => 'ro', default => 1);
28              
29             my $DEBUG_DUMPED = 0;
30              
31             sub AUTOLOAD {
32 2     2   2047 my $self = shift;
33 2         4 my $method = $Bitcoin::RPC::Client::AUTOLOAD;
34              
35 2         11 $method =~ s/.*:://;
36              
37 2 100       16 return if ($method eq 'DESTROY');
38              
39             # Build request URL
40 1         11 my $url = "";
41              
42             # Are we using SSL?
43 1         3 my $uri = "http://";
44 1 50       7 if ($self->ssl eq 1) {
45 0         0 $uri = "https://";
46             }
47              
48             # Cookie will take precedence over user/password
49 1 50       6 if ($self->cookie) {
    50          
50             # If cookie is defined its contents become user:password
51 0         0 $url = $uri . $self->cookie . "\@" . $self->host . ":" . $self->port;
52             } elsif ($self->user) {
53 1         26 $url = $uri . $self->user . ":" . $self->password . "\@" . $self->host . ":" . $self->port;
54             } else {
55 0         0 die "An RPC user or RPC cookie file must be defined\n";
56             }
57              
58             # Tack on a specific wallet name if given
59 1 50       12 if ($self->wallet) {
60 0         0 $url .= "/wallet/" . $self->wallet;
61             }
62              
63 1         16 my $client = $self->jsonrpc;
64              
65             # Set timeout because bitcoin is slow
66 1         2495 $client->ua->timeout($self->timeout);
67              
68             # Set Agent, let them know who we be
69 1         65 $client->ua->agent("Bitcoin::RPC::Client/" . $VERSION);
70              
71             # Turn on debugging for LWP::UserAgent
72 1 50       77 if ($self->debug) {
73 0 0       0 if (!$DEBUG_DUMPED) { # We only want to set this up once
74 0     0   0 $client->ua->add_handler("request_send", sub { shift->dump; return });
  0         0  
  0         0  
75 0     0   0 $client->ua->add_handler("response_done", sub { shift->dump; return });
  0         0  
  0         0  
76 0         0 $DEBUG_DUMPED = 1;
77             }
78             }
79              
80             # For self signed certs
81 1 50       14 if ($self->verify_hostname eq 0) {
82 0         0 $client->ua->ssl_opts( verify_hostname => 0,
83             SSL_verify_mode => 0 );
84             }
85              
86             # Build the RPC
87 1 50       5 my $obj = {
88             method => $method,
89             params => (ref $_[0] ? $_[0] : [@_]),
90             };
91 1         2 my $res;
92             eval {
93             # Attempt the RPC
94 1         6 $res = $client->call( $url, $obj );
95 1 50       2 } or do {
96             # Test the HTTP service and die with usable output if above RPC call fails
97 1         47872 my $tr = $client->ua->post($url);
98 1         1944 die $tr->status_line;
99             };
100 0 0         if($res) {
101 0 0         if ($res->is_error) {
102 0           my $content = $res->content;
103 0           die sprintf("error code: %d, error message: %s (%s)\n", $content->{error}->{code}, $content->{error}->{message}, $method);
104             }
105              
106 0           return $res->result;
107             }
108              
109 0           return;
110             }
111              
112             # function to setup cookie attrib
113             sub isa_cookie {
114              
115 0     0 0   my $failed = 0;
116              
117             # We only want to read this once (limit io).
118 0 0         open COOKIE, $_[0] or $failed = 1;
119              
120 0 0         if ($failed) {
121 0           die sprintf("Could not open RPC cookie file: %s\n", $_[0]);
122             }
123              
124 0           my $cookie = ;
125 0           close COOKIE;
126 0 0 0       if (!defined($cookie) or $cookie !~ /:/) {
127 0           die "Invalid RPC cookie file format\n";
128             }
129 0           $cookie =~ s/\s+//g;
130 0           $_[0] = $cookie;
131              
132             }
133              
134             1;
135              
136             =pod
137              
138             =head1 NAME
139              
140             Bitcoin::RPC::Client - Bitcoin Core JSON RPC Client
141              
142             =head1 SYNOPSIS
143              
144             use Bitcoin::RPC::Client;
145              
146             # Create Bitcoin::RPC::Client object
147             $btc = Bitcoin::RPC::Client->new(
148             user => "username",
149             password => "p4ssword",
150             host => "127.0.0.1",
151             );
152              
153             # Check the block height of bitcoin node
154             # https://developer.bitcoin.org/reference/rpc/getblockchaininfo.html
155             $chaininfo = $btc->getblockchaininfo;
156             $blocks = $chaininfo->{blocks};
157              
158             # Estimate a reasonable transaction fee
159             # https://developer.bitcoin.org/reference/rpc/estimatesmartfee.html
160             $fee = $btc->estimatesmartfee(6);
161             $feerate = $fee->{feerate};
162              
163             # Set the transaction fee
164             # https://developer.bitcoin.org/reference/rpc/settxfee.html
165             $settx = $btc->settxfee($feerate);
166              
167             # Check balance
168             # (JSON::Boolean objects must be passed as boolean parameters)
169             # https://developer.bitcoin.org/reference/rpc/getbalance.html
170             $balance = $btc->getbalance("*", 1, JSON::true);
171              
172             # Send to an address
173             # https://developer.bitcoin.org/reference/rpc/sendtoaddress.html
174             $transid = $btc->sendtoaddress("1DopyzQi9mX3huvGacfjpzCKFug2Dtvykp","0.01");
175              
176             # See ex/example.pl for more in depth JSON handling:
177             # https://github.com/whindsx/Bitcoin-RPC-Client/tree/master/ex
178              
179             =head1 DESCRIPTION
180              
181             This module implements in Perl the functions that are currently part of the
182             Bitcoin Core RPC client calls (bitcoin-cli). The function names and parameters
183             are identical between the L and this module.
184              
185             =head1 CONSTRUCTOR
186              
187             $btc = Bitcoin::RPC::Client->new( %options )
188              
189             This method creates a new C and returns it.
190              
191             Key Default
192             ----------- -----------
193             host undef (Required)
194             user undef (Required)
195             password undef (Required)
196             cookie undef
197             port 8332
198             wallet undef
199             timeout 20
200             ssl 0
201             verify_hostname 1
202             debug 0
203              
204             cookie - Absolute path to your RPC cookie file (.cookie). When cookie is
205             defined user and password will be ignored and the contents of cookie will
206             be used instead.
207              
208             wallet - Work against specific wallet.dat file when Multi-wallet support is
209             enabled (Bitcoin Core v0.15+ only)
210              
211             timeout - Set the timeout in seconds for individual RPC requests. Increase
212             this for slow bitcoind instances.
213              
214             ssl - OpenSSL support has been removed from the Bitcoin Core project as of
215             v0.12.0. However Bitcoin::RPC::Client will work over SSL with earlier versions
216             or with a reverse web proxy such as nginx.
217              
218             verify_hostname - Disable SSL certificate verification. Needed when
219             bitcoind is fronted by a proxy or when using a self-signed certificate.
220              
221             debug - Turns on raw HTTP request/response output from LWP::UserAgent.
222              
223             =head1 AUTHOR
224              
225             Wesley Hinds wesley.hinds@gmail.com
226              
227             =head1 AVAILABILITY
228              
229             The latest branch is avaiable from Github.
230              
231             https://github.com/whindsx/Bitcoin-RPC-Client.git
232              
233             =head1 DONATE
234              
235             1DopyzQi9mX3huvGacfjpzCKFug2Dtvykp
236              
237             =head1 LICENSE AND COPYRIGHT
238              
239             Copyright 2016 Wesley Hinds.
240              
241             This program is free software; you can redistribute it and/or modify it
242             under the terms of the the Artistic License (2.0). You may obtain a
243             copy of the full license at:
244              
245             L
246              
247             Any use, modification, and distribution of the Standard or Modified
248             Versions is governed by this Artistic License. By using, modifying or
249             distributing the Package, you accept this license. Do not use, modify,
250             or distribute the Package, if you do not accept this license.
251              
252             If your Modified Version has been derived from a Modified Version made
253             by someone other than you, you are nevertheless required to ensure that
254             your Modified Version complies with the requirements of this license.
255              
256             This license does not grant you the right to use any trademark, service
257             mark, tradename, or logo of the Copyright Holder.
258              
259             This license includes the non-exclusive, worldwide, free-of-charge
260             patent license to make, have made, use, offer to sell, sell, import and
261             otherwise transfer the Package with respect to any patent claims
262             licensable by the Copyright Holder that are necessarily infringed by the
263             Package. If you institute patent litigation (including a cross-claim or
264             counterclaim) against any party alleging that the Package constitutes
265             direct or contributory patent infringement, then this Artistic License
266             to you shall terminate on the date that such litigation is filed.
267              
268             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
269             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
270             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
271             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
272             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
273             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
274             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
275             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276              
277              
278             =cut