File Coverage

blib/lib/Business/Bitcoin.pm
Criterion Covered Total %
statement 49 53 92.4
branch 15 30 50.0
condition 3 7 42.8
subroutine 10 11 90.9
pod 3 3 100.0
total 80 104 76.9


line stmt bran cond sub pod time code
1             # -*-cperl-*-
2             #
3             # Business::Bitcoin - Easy and secure way to accept Bitcoin payments online
4             # Copyright (c) 2016 Ashish Gulhati
5             #
6             # $Id: lib/Business/Bitcoin.pm v1.10 Thu Dec 29 13:32:18 2016 -0500 $
7              
8 2     2   25590 use strict;
  2         2  
  2         56  
9              
10             package Business::Bitcoin;
11              
12 2     2   29 use 5.008001;
  2         4  
13 2     2   6 use warnings;
  2         5  
  2         50  
14 2     2   6 use strict;
  2         2  
  2         25  
15              
16 2     2   2671 use DBI;
  2         23232  
  2         103  
17 2     2   816 use Business::Bitcoin::Request;
  2         5  
  2         81  
18              
19 2     2   9 use vars qw( $VERSION $AUTOLOAD );
  2         1  
  2         935  
20              
21             our ( $VERSION ) = '$Revision: 1.10 $' =~ /\s+([\d\.]+)/;
22              
23             sub new {
24 1     1 1 73603 my $class = shift;
25 1         5 my %args = @_;
26 1 50       5 return undef unless $args{XPUB};
27 1 50 33     4 return undef if $args{StartIndex} and $args{StartIndex} =~ /\D/;
28 1 50       76 unlink $args{DB} if $args{Clobber};
29 1         12 my $db = DBI->connect("dbi:SQLite:dbname=$args{DB}","","");
30 1         8496 my @tables = $db->tables('%','%','requests','TABLE');
31 1 50       1014 unless ($tables[0]) {
32 1 50       4 if ($args{Create}) {
33 1 50       5 return undef unless $db->do('CREATE TABLE requests (
34             reqid INTEGER PRIMARY KEY AUTOINCREMENT,
35             amount int NOT NULL,
36             address text,
37             refid text UNIQUE,
38             created int NOT NULL
39             );');
40 1 50       6143022 return undef unless $db->do('CREATE INDEX idx_requests_address ON requests(address);');
41 1 50       34760 return undef unless $db->do('CREATE INDEX idx_requests_refid ON requests(refid);');
42 1   50     11111 my $startindex = $args{StartIndex} || 0;
43 1         4 $startindex--;
44 1 50       18 return unless $db->do("INSERT INTO SQLITE_SEQUENCE values ('requests',$startindex);");
45             }
46             else {
47 0         0 return undef;
48             }
49             }
50 1   50     5324 bless { XPUB => $args{XPUB}, DB => $db, KUCMD => $args{kucmd} || '/usr/local/bin/ku' }, $class;
51             }
52              
53             sub request { # Create a Bitcoin payment request
54 1     1 1 15 my ($self, %args) = @_;
55 1 50       10 return undef if $args{Amount} !~ /^\d+$/;
56              
57             # Workaround for SQLite not starting sequence from 0 when asked to in new()
58 1         15 my $startindex = $self->db->selectcol_arrayref("SELECT seq from SQLITE_SEQUENCE WHERE name='requests';")->[0];
59 1 50       329 my %forcezero; %forcezero = ( StartIndex => 0 ) if $startindex == -1;
  1         8  
60              
61 1         19 my $req = new Business::Bitcoin::Request (_BizBTC => $self, %args, %forcezero);
62             }
63              
64             sub findreq { # Retrieve a previously created request
65 0     0 1 0 my ($self, %args) = @_;
66 0         0 my $req = _find Business::Bitcoin::Request (_BizBTC => $self, %args);
67             }
68              
69             sub AUTOLOAD {
70 5     5   8 my $self = shift; (my $auto = $AUTOLOAD) =~ s/.*:://;
  5         29  
71 5 50       18 return if $auto eq 'DESTROY';
72 5 50       24 if ($auto =~ /^(xpub|db|kucmd)$/x) {
73 5 50       11 $self->{"\U$auto"} = shift if (defined $_[0]);
74             }
75 5 50       18 if ($auto =~ /^(xpub|db|version|kucmd)$/x) {
76 5         102 return $self->{"\U$auto"};
77             }
78             else {
79 0           die "Could not AUTOLOAD method $auto.";
80             }
81             }
82              
83             1; # End of Business::Bitcoin
84              
85             =head1 NAME
86              
87             Business::Bitcoin - Easy and secure way to accept Bitcoin payments online
88              
89             =head1 VERSION
90              
91             $Revision: 1.10 $
92             $Date: Thu Dec 29 13:32:18 2016 -0500 $
93              
94             =head1 SYNOPSIS
95              
96             An easy and secure way to accept Bitcoin payments online using an HD
97             wallet, generating new receiving addresses on demand and keeping the
98             wallet private key offline.
99              
100             use Business::Bitcoin;
101              
102             my $bizbtc = new Business::Bitcoin (DB => '/tmp/bizbtc.db',
103             XPUB => 'xpub...',
104             Create => 1);
105              
106             my $req = $bizbtc->request(Amount => 4200);
107              
108             print 'Please pay ' . $req->amount . ' Satoshi ' .
109             'to Bitcoin address ' . $req->address . ".\n" .
110             'Once the payment has ' . $req->confirmations , ' confirmations, ' .
111             "press to continue.\n";
112             readline(*STDIN);
113              
114             print ($req->verify ? "Verified\n" : "Verification failed\n");
115              
116             print "Enter a request address to verify a payment.\n";
117             my $address = ; chomp $address;
118              
119             my $req2 = $bizbtc->findreq(Address => $address);
120             print ($req2->verify ? "Verified\n" : "Verification failed\n");
121              
122             =head1 HOW TO USE
123              
124             To start receiving Bitcoin payments online, create an HD wallet using
125             any HD wallet app (e.g. Electrum, Bitcoin Armory), get the
126             "Master Public Key" for the wallet (a string beginning with "xpub")
127             and plug it into the constructor's XPUB argument).
128              
129             Now you can receive online payments as outlined above, while keeping
130             your private key secure offline. You should still take all precautions
131             to ensure that your XPUB key on the server is also safe, as its
132             compromise can weaken your security, though it can't in itself lead to
133             the loss of any Bitcoin.
134              
135             =head1 METHODS
136              
137             =head2 new
138              
139             Create a new Business::Bitcoin object and open (or create) the
140             requests database. The following named arguments are required:
141              
142             =over
143              
144             DB - The filename of the requests database
145              
146             XPUB - The master public key for the wallet receiving payments
147              
148             =back
149              
150             The following optional named arguments can be provided:
151              
152             =over
153              
154             Create - Create the requests table if it doesn't exist. If the table
155             doesn't exist and Create is not true, the constructor will return
156             undef. Unset by default.
157              
158             Clobber - Wipe out any existing database file first. Unset by default.
159              
160             StartIndex - Start generating receiving keys from the specified index
161             rather than from 0. Useful if you've already used some receiving
162             addresses before starting to receive payments using this
163             module. Only relevant when Create is true and a new
164             requests table is being created. Ignored when an existing
165             requests table is being used; in that case the index is generated by the
166             database. By default, receiving addresses will be generaed starting
167             from the first one, at index 0.
168              
169             kucmd - The filename of the "ku" command from pycoin. Default is '/usr/local/bin/ku'.
170              
171             =back
172              
173             =head2 request
174              
175             Create a new payment request and generate a new receiving
176             address. Returns a Business::Bitcoin::Request object if successful, or
177             undef on error. The following named argument is required:
178              
179             =over
180              
181             Amount - The amount of the payment requested, in Satoshi.
182              
183             =back
184              
185             The following optional named arguments can be provided:
186              
187             =over
188              
189             Confirmations - The number of confirmations needed to verify payment
190             of this request. The default is 5.
191              
192             Reference - Optional reference ID to be associated with the requst, to
193             facilitate integration with existing ordering systems. If you provide
194             a reference ID it should be unique for each request.
195              
196             =head2 findreq
197              
198             Find a previously created payment request, by either Address or
199             Reference. Returns a Business::Bitcoin::Request object if successful,
200             or undef on error. Exactly one of the following named arguments is
201             required:
202              
203             =over
204              
205             Address - The receiving address associated with the payment request
206              
207             Reference - The reference ID associated with the payment request
208              
209             =back
210              
211             The following optional named argument can be provided:
212              
213             =over
214              
215             Confirmations - The number of confirmations needed to verify payment
216             of this request. The default is 5.
217              
218             =back
219              
220             =head1 ACCESSORS
221              
222             Accessors can be called with no arguments to query the value of an
223             object property, or with a single argument, to set the property to a
224             specific value (unless the property is read only).
225              
226             =head2 db
227              
228             The filename of the requests DB file.
229              
230             =head2 xpub
231              
232             The master public key from which all receiving keys are generated.
233              
234             =head2 kucmd
235              
236             The pathname of the "ku" command from pycoin.
237              
238             =head2 version
239              
240             The version number of this module. Read only.
241              
242             =head1 PREREQUISITES
243              
244             =head2 pycoin
245              
246             The "ku" command from pycoin is used to generate new receiving
247             addresses. You can get pycoin from:
248              
249             https://github.com/richardkiss/pycoin
250              
251             =head2 DBD::SQLite
252              
253             Used to keep track of payment requests.
254              
255             =head2 LWP and an Internet connection
256              
257             Required to verify payments. Currently this is done via the
258             blockchain.info API.
259              
260             =head1 AUTHOR
261              
262             Ashish Gulhati, C<< >>
263              
264             =head1 BUGS
265              
266             Please report any bugs or feature requests to C, or through
267             the web interface at L. I will be notified, and then you'll
268             automatically be notified of progress on your bug as I make changes.
269              
270             =head1 SUPPORT
271              
272             You can find documentation for this module with the perldoc command.
273              
274             perldoc Business::Bitcoin
275              
276             You can also look for information at:
277              
278             =over 4
279              
280             =item * RT: CPAN's request tracker
281              
282             L
283              
284             =item * AnnoCPAN: Annotated CPAN documentation
285              
286             L
287              
288             =item * CPAN Ratings
289              
290             L
291              
292             =item * Search CPAN
293              
294             L
295              
296             =back
297              
298             =head1 LICENSE AND COPYRIGHT
299              
300             Copyright (c) 2016 Ashish Gulhati. All rights reserved.
301              
302             This program is free software; you can redistribute it and/or modify it
303             under the terms of either: the GNU General Public License as published
304             by the Free Software Foundation; or the Artistic License.
305              
306             See http://dev.perl.org/licenses/ for more information.