File Coverage

blib/lib/Bitcoin/RPC/Client.pm
Criterion Covered Total %
statement 14 60 23.3
branch 0 28 0.0
condition 0 3 0.0
subroutine 5 9 55.5
pod 0 1 0.0
total 19 101 18.8


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