Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
3.85% covered (danger)
3.85%
1 / 26
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
BitWasp_API
3.85% covered (danger)
3.85%
1 / 26
50.00% covered (danger)
50.00%
1 / 2
38.00
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generate_address
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * The local PHP library for generating addresses.
4 *
5 * @see https://github.com/Bit-Wasp/bitcoin-php
6 * @see https://gist.github.com/mariodian/5b67a1f315a74a7753a6f23d0198ec48
7 *
8 * @package    brianhenryie/bh-wp-bitcoin-gateway
9 */
10
11namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Addresses;
12
13use BrianHenryIE\WP_Bitcoin_Gateway\API\Generate_Address_API_Interface;
14use Exception;
15use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Address\AddressCreator;
16use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Bitcoin;
17use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Key\Deterministic\HdPrefix\GlobalPrefixConfig;
18use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Key\Deterministic\HdPrefix\NetworkConfig;
19use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Key\Deterministic\Slip132\Slip132;
20use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Key\KeyToScript\KeyToScriptHelper;
21use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Network\NetworkFactory;
22use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Network\Slip132\BitcoinRegistry;
23use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Serializer\Key\HierarchicalKey\Base58ExtendedKeySerializer;
24use BrianHenryIE\WP_Bitcoin_Gateway\BitWasp\Bitcoin\Serializer\Key\HierarchicalKey\ExtendedKeySerializer;
25use Psr\Log\LoggerAwareTrait;
26use Psr\Log\LoggerInterface;
27
28/**
29 * Use Bitwasp API to generate public addresses.
30 */
31class BitWasp_API implements Generate_Address_API_Interface {
32    use LoggerAwareTrait;
33
34    /**
35     * Constructor.
36     *
37     * @param LoggerInterface $logger PSR Logger.
38     */
39    public function __construct( LoggerInterface $logger ) {
40        $this->setLogger( $logger );
41    }
42
43    /**
44     * Generate the nth address for the given xpub|ypub|zpub.
45     *
46     * @param string $public_address The wallet address.
47     * @param int    $nth Derive path nth address in sequence.
48     *
49     * @return string
50     * @throws Exception Failed to generate address.
51     */
52    public function generate_address( string $public_address, int $nth ): string {
53
54        $path = "0/$nth";
55
56        $adapter          = Bitcoin::getEcAdapter();
57        $helper           = new KeyToScriptHelper( $adapter );
58        $slip132          = new Slip132( $helper );
59        $bitcoin_prefixes = new BitcoinRegistry();
60
61        switch ( substr( $public_address, 0, 4 ) ) {
62            case 'xpub':
63                /**
64                 * Pay-to-Pubkey Hash.
65                 *
66                 * TODO: This also applies to 'tpub'?
67                 *
68                 * @see https://en.bitcoinwiki.org/wiki/Pay-to-Pubkey_Hash
69                 */
70                $pub_prefix = $slip132->p2pkh( $bitcoin_prefixes );
71                break;
72            case 'ypub':
73                /**
74                 * TODO: Pay To Script Hash - Pay to Witness Script Hash ?
75                 */
76                $pub_prefix = $slip132->p2shP2wpkh( $bitcoin_prefixes );
77                break;
78            case 'zpub':
79                /**
80                 * Pay to Witness Public Key Hash.
81                 *
82                 * TODO: This also applies to 'vpub'?
83                 *
84                 * @see https://programmingblockchain.gitbook.io/programmingblockchain/other_types_of_ownership/p2wpkh_pay_to_witness_public_key_hash
85                 */
86                $pub_prefix = $slip132->p2wpkh( $bitcoin_prefixes );
87                break;
88            default:
89                throw new Exception( 'Bad public key' );
90        }
91
92        $network = NetworkFactory::bitcoin();
93
94        $network_config = new NetworkConfig( $network, array( $pub_prefix ) );
95        $config         = new GlobalPrefixConfig( array( $network_config ) );
96
97        $serializer = new Base58ExtendedKeySerializer(
98            new ExtendedKeySerializer( $adapter, $config )
99        );
100
101        $key       = $serializer->parse( $network, $public_address );
102        $child_key = $key->derivePath( $path );
103
104        return $child_key->getAddress( new AddressCreator() )->getAddress();
105    }
106}