File Coverage

blib/lib/Zcash/RPC/Client.pm
Criterion Covered Total %
statement 14 73 19.1
branch 0 30 0.0
condition 0 3 0.0
subroutine 5 10 50.0
pod 0 1 0.0
total 19 117 16.2


line stmt bran cond sub pod time code
1             package Zcash::RPC::Client;
2              
3 1     1   58229 use 5.008;
  1         3  
4              
5 1     1   4 use strict;
  1         2  
  1         17  
6 1     1   3 use warnings;
  1         2  
  1         32  
7              
8 1     1   495 use Moo;
  1         9668  
  1         4  
9 1     1   1684 use JSON::RPC::Legacy::Client;
  1         53830  
  1         851  
10              
11             our $VERSION = '1.01';
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 => "lazy", default => '127.0.0.1');
18             has wallet => (is => 'ro');
19             has port => (is => "lazy", default => 8232);
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 and Zcash
25             # but should work with older versions and connections via a proxy.
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 = $Zcash::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";
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("Zcash::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             } else {# Don't print error message when debug is on.
79             # We want to handle broken responses ourself
80             $client->ua->add_handler("response_data",
81             sub {
82 0     0     my ($response, $ua, $h, $data) = @_;
83              
84 0 0         if ($response->is_error) {
85 0           my $content = JSON->new->utf8->decode($data);
86 0           print STDERR "error code: ";
87 0           print STDERR $content->{error}->{code};
88 0           print STDERR ", error message: ";
89 0           print STDERR $content->{error}->{message} . " ($method)\n";
90 0           exit(1);
91             } else {
92             # If no error then ditch the handler
93             # otherwise things that did not error will get handled too
94 0           $ua->remove_handler();
95             }
96              
97 0           return;
98             }
99 0           );
100             }
101              
102             # For self signed certs
103 0 0         if ($self->verify_hostname eq 0) {
104 0           $client->ua->ssl_opts( verify_hostname => 0,
105             SSL_verify_mode => 'SSL_VERIFY_NONE' );
106             }
107              
108 0 0         my $obj = {
109             method => $method,
110             params => (ref $_[0] ? $_[0] : [@_]),
111             };
112              
113 0           my $res = $client->call( $url, $obj );
114 0 0         if($res) {
115 0 0         if ($res->is_error) {
116 0           return $res->error_message;
117             }
118              
119 0           return $res->result;
120             }
121              
122 0           return;
123             }
124              
125             # function to setup cookie attrib
126             sub isa_cookie {
127              
128 0     0 0   my $failed = 0;
129              
130             # We only want to read this once (limit io).
131 0 0         open COOKIE, $_[0] or $failed = 1;
132              
133 0 0         if ($failed) {
134 0           print STDERR "Could not open RPC cookie file: " . $_[0];
135 0           print STDERR "\n";
136 0           exit(1);
137             }
138              
139 0           my $cookie = ;
140 0           close COOKIE;
141 0 0 0       if (!defined($cookie) or $cookie !~ /:/) {
142 0           print STDERR "Invalid RPC cookie file format\n";
143 0           exit(1);
144             }
145 0           $cookie =~ s/\s+//g;
146 0           $_[0] = $cookie;
147              
148             }
149              
150             1;
151              
152             =pod
153              
154             =head1 NAME
155              
156             Zcash::RPC::Client - Zcash Payment API Client
157              
158             =head1 SYNOPSIS
159              
160             use Zcash::RPC::Client;
161              
162             # Create Zcash::RPC::Client object
163             $zec = Zcash::RPC::Client->new(
164             user => "username",
165             password => "p4ssword",
166             );
167              
168             # Zcash supports all commands in the Bitcoin Core API
169             # Check the block height of our Zcash node
170             # https://bitcoin.org/en/developer-reference#getblockchaininfo
171             $getinfo = $zec->getinfo;
172             $blocks = $getinfo->{blocks};
173              
174             # Return the total value of funds stored in the node's wallet
175             # https://github.com/zcash/zcash/blob/master/doc/payment-api.md
176             $z_gettotalbalance = $zec->z_gettotalbalance;
177             # Output:
178             #{
179             # "transparent" : 1.23,
180             # "private" : 4.56,
181             # "total" : 5.79
182             #}
183             print $z_gettotalbalance->{total};
184             # 5.79
185              
186             # See ex/example.pl for more in depth JSON handling:
187             # https://github.com/Cyclenerd/Zcash-RPC-Client/tree/master/ex
188              
189             =head1 DESCRIPTION
190              
191             This module is a pure Perl implementation of the methods that are currently
192             part of the Zcash Payment API client calls. The method names and parameters are
193             identical between the Zcash Payment API reference and this module. This is
194             done for consistency so that a developer only has to reference one manual:
195             L
196              
197             =head1 CONSTRUCTOR
198              
199             $zec = Zcash::RPC::Client->new( %options )
200              
201             This method creates a new C and returns it.
202              
203             Key Default
204             ----------- -----------
205             host 127.0.0.1
206             user undef (Required)
207             password undef (Required)
208             cookie undef
209             port 8232
210             wallet undef
211             timeout 20
212             ssl 0
213             verify_hostname 1
214             debug 0
215              
216             B - Address listens for JSON-RPC connections
217              
218             B and B - User and Password for JSON-RPC api commands
219              
220             B - Absolute path to your RPC cookie file (.cookie). When cookie is
221             defined user and password will be ignored and the contents of cookie will
222             be used instead.
223              
224             B - TCP port for JSON-RPC connections
225              
226             B - Work against specific wallet.dat file when Multi-wallet support is
227             enabled
228              
229             B - Set the timeout in seconds for individual RPC requests. Increase
230             this for slow zcashd instances.
231              
232             B - OpenSSL support has been removed from the Bitcoin Core and Zcash project.
233             However Zcash::RPC::Client will work over SSL with earlier versions
234             or with a reverse web proxy such as nginx.
235              
236             B - Disable SSL certificate verification. Needed when
237             bitcoind is fronted by a proxy or when using a self-signed certificate.
238              
239             B - Turns on raw HTTP request/response output from LWP::UserAgent.
240              
241             =head1 AVAILABILITY
242              
243             The latest branch is avaiable from GitHub:
244             L
245              
246             =head1 CAVEATS
247              
248             Boolean parameters must be passed as JSON::Boolean objects E.g. JSON::true
249              
250             =head1 AUTHOR
251              
252             Zcash is based on Bitcoin. Zcash supports all commands in the Bitcoin
253             Core API (as of version 0.11.2).
254              
255             This module is a fork of C.
256              
257             C is developed by Wesley Hinds. This Zcash fork is
258             mantained by Nils Knieling.
259              
260             =head1 LICENSE AND COPYRIGHT
261              
262             Copyright (c) 2018 Nils Knieling
263             Copyright (c) 2016-2018 Wesley Hinds
264              
265             This program is free software; you can redistribute it and/or modify it
266             under the terms of the the Artistic License (2.0). You may obtain a
267             copy of the full license at:
268              
269             L
270              
271             Any use, modification, and distribution of the Standard or Modified
272             Versions is governed by this Artistic License. By using, modifying or
273             distributing the Package, you accept this license. Do not use, modify,
274             or distribute the Package, if you do not accept this license.
275              
276             If your Modified Version has been derived from a Modified Version made
277             by someone other than you, you are nevertheless required to ensure that
278             your Modified Version complies with the requirements of this license.
279              
280             This license does not grant you the right to use any trademark, service
281             mark, tradename, or logo of the Copyright Holder.
282              
283             This license includes the non-exclusive, worldwide, free-of-charge
284             patent license to make, have made, use, offer to sell, sell, import and
285             otherwise transfer the Package with respect to any patent claims
286             licensable by the Copyright Holder that are necessarily infringed by the
287             Package. If you institute patent litigation (including a cross-claim or
288             counterclaim) against any party alleging that the Package constitutes
289             direct or contributory patent infringement, then this Artistic License
290             to you shall terminate on the date that such litigation is filed.
291              
292             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
293             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
294             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
295             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
296             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
297             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
298             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
299             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300              
301              
302             =cut