Completed
Pull Request — master (#118)
by Ruben de
09:49 queued 04:39
created

WalletV1   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 61.11%

Importance

Changes 0
Metric Value
dl 0
loc 109
ccs 22
cts 36
cp 0.6111
rs 10
c 0
b 0
f 0
wmc 18
lcom 1
cbo 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A passwordChange() 0 3 1
A lock() 0 4 1
D unlock() 0 49 15
1
<?php
2
3
namespace Blocktrail\SDK;
4
5
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
6
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory;
7
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
8
use Blocktrail\SDK\Address\AddressReaderBase;
9
use Blocktrail\SDK\Bitcoin\BIP32Key;
10
use Blocktrail\SDK\Exceptions\BlocktrailSDKException;
11
use Blocktrail\SDK\Exceptions\NotImplementedException;
12
13
class WalletV1 extends Wallet {
14
15
    /**
16
     * BIP39 Mnemonic for the master primary private key
17
     *
18
     * @var string
19
     */
20
    protected $primaryMnemonic;
21
22
    /**
23
     * @param BlocktrailSDKInterface        $sdk                        SDK instance used to do requests
24
     * @param string                        $identifier                 identifier of the wallet
25
     * @param string                        $primaryMnemonic
26
     * @param BIP32Key[]                    $primaryPublicKeys
27
     * @param BIP32Key                      $backupPublicKey            should be BIP32 master public key M/
28
     * @param BIP32Key[]                    $blocktrailPublicKeys
29
     * @param int                           $keyIndex
30
     * @param string                        $network
31
     * @param bool                          $testnet
32
     * @param bool                          $segwit
33
     * @param AddressReaderBase             $addressReader
34
     * @param string                        $checksum
35
     * @throws                              BlocktrailSDKException
36
     */
37 3
    public function __construct(BlocktrailSDKInterface $sdk, $identifier, $primaryMnemonic, array $primaryPublicKeys, $backupPublicKey, array $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, AddressReaderBase $addressReader, $checksum) {
38 3
        $this->primaryMnemonic = $primaryMnemonic;
39
40 3
        parent::__construct($sdk, $identifier, $primaryPublicKeys, $backupPublicKey, $blocktrailPublicKeys, $keyIndex, $network, $testnet, $segwit, $addressReader, $checksum);
41 3
    }
42
43
    /**
44
     * unlock wallet so it can be used for payments
45
     *
46
     * @param          $options ['primary_private_key' => key] OR ['passphrase' => pass]
47
     * @param callable $fn
48
     * @return bool
49
     * @throws \Exception
50
     */
51 3
    public function unlock($options, callable $fn = null) {
52
        // explode the wallet data
53 3
        $password = isset($options['passphrase']) ? $options['passphrase'] : (isset($options['password']) ? $options['password'] : null);
54 3
        $primaryMnemonic = $this->primaryMnemonic;
55 3
        $primaryPrivateKey = isset($options['primary_private_key']) ? $options['primary_private_key'] : null;
56
57 3
        if ($primaryMnemonic && $primaryPrivateKey) {
58
            throw new \InvalidArgumentException("Can't specify Primary Mnemonic and Primary PrivateKey");
59
        }
60
61 3
        if (!$primaryMnemonic && !$primaryPrivateKey) {
62
            throw new \InvalidArgumentException("Can't init wallet without Primary Mnemonic or Primary PrivateKey");
63
        }
64
65 3
        if ($primaryMnemonic && !$password) {
66
            throw new \InvalidArgumentException("Can't init wallet with Primary Mnemonic without a passphrase");
67
        }
68
69 3
        if ($primaryPrivateKey) {
70
            if (!($primaryPrivateKey instanceof HierarchicalKey)) {
71
                $primaryPrivateKey = HierarchicalKeyFactory::fromExtended($primaryPrivateKey);
72
            }
73
        } else {
74
            // convert the mnemonic to a seed using BIP39 standard
75 3
            $primarySeed = (new Bip39SeedGenerator())->getSeed($primaryMnemonic, $password);
76
            // create BIP32 private key from the seed
77 3
            $primaryPrivateKey = HierarchicalKeyFactory::fromEntropy($primarySeed);
78
        }
79
80 3
        $this->primaryPrivateKey = BIP32Key::create($primaryPrivateKey, "m");
81
82
        // create checksum (address) of the primary privatekey to compare to the stored checksum
83 3
        $checksum = $this->primaryPrivateKey->key()->getPublicKey()->getAddress()->getAddress();
84 3
        if ($checksum != $this->checksum) {
85 1
            throw new \Exception("Checksum [{$checksum}] does not match [{$this->checksum}], most likely due to incorrect password");
86
        }
87
88 2
        $this->locked = false;
89
90
        // if the response suggests we should upgrade to a different blocktrail cosigning key then we should
91 2
        if (isset($data['upgrade_key_index'])) {
0 ignored issues
show
Bug introduced by
The variable $data seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
92
            $this->upgradeKeyIndex($data['upgrade_key_index']);
93
        }
94
95 2
        if ($fn) {
96
            $fn($this);
97
            $this->lock();
98
        }
99 2
    }
100
101
    /**
102
     * lock the wallet (unsets primary private key)
103
     *
104
     * @return void
105
     */
106
    public function lock() {
107
        $this->primaryPrivateKey = null;
108
        $this->locked = true;
109
    }
110
111
    /**
112
     * change password that is used to store data encrypted on server
113
     *
114
     * @param $newPassword
115
     * @return array backupInfo
116
     * @throws NotImplementedException
117
     */
118
    public function passwordChange($newPassword) {
119
        throw new NotImplementedException();
120
    }
121
}
122