Completed
Pull Request — master (#270)
by thomas
70:22
created

AddressFactory   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 13

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 15
c 4
b 0
f 1
lcom 0
cbo 13
dl 0
loc 109
ccs 34
cts 34
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A fromKey() 0 4 1
A fromScript() 0 4 1
A fromString() 0 14 4
A fromOutputScript() 0 18 3
A isValidAddress() 0 11 2
A getAssociatedAddress() 0 16 4
1
<?php
2
3
namespace BitWasp\Bitcoin\Address;
4
5
use BitWasp\Bitcoin\Base58;
6
use BitWasp\Bitcoin\Bitcoin;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\KeyInterface;
8
use BitWasp\Bitcoin\Network\NetworkInterface;
9
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
10
use BitWasp\Bitcoin\Script\ScriptInterface;
11
12
use BitWasp\Bitcoin\Key\PublicKeyFactory;
13
use BitWasp\Buffertools\Buffer;
14
15
class AddressFactory
16
{
17
    /**
18
     * Returns a pay-to-pubkey-hash address for the given public key
19
     *
20
     * @param KeyInterface $key
21
     * @return PayToPubKeyHashAddress
22
     */
23 210
    public static function fromKey(KeyInterface $key)
24
    {
25 210
        return new PayToPubKeyHashAddress($key->getPubKeyHash());
26
    }
27
28
    /**
29
     * Takes the $p2shScript and generates the scriptHash address.
30
     *
31
     * @param ScriptInterface $p2shScript
32
     * @return ScriptHashAddress
33
     */
34 90
    public static function fromScript(ScriptInterface $p2shScript)
35
    {
36 90
        return new ScriptHashAddress($p2shScript->getScriptHash());
37
    }
38
39
    /**
40
     * @param ScriptInterface $outputScript
41
     * @return PayToPubKeyHashAddress|ScriptHashAddress
42
     */
43 18
    public static function fromOutputScript(ScriptInterface $outputScript)
44
    {
45 18
        $classifier = new OutputClassifier($outputScript);
46 18
        $type = $classifier->classify();
47 18
        $parsed = $outputScript->getScriptParser()->decode();
48
49 18
        if ($type === OutputClassifier::PAYTOPUBKEYHASH) {
50
            /** @var \BitWasp\Buffertools\BufferInterface $hash */
51 12
            $hash = $parsed[2]->getData();
52 12
            return new PayToPubKeyHashAddress($hash);
53 12
        } else if ($type === OutputClassifier::PAYTOSCRIPTHASH) {
54
            /** @var \BitWasp\Buffertools\BufferInterface $hash */
55 6
            $hash = $parsed[1]->getData();
56 6
            return new ScriptHashAddress($hash);
57
        }
58
59 12
        throw new \RuntimeException('Script type is not associated with an address');
60
    }
61
62
    /**
63
     * @param string $address
64
     * @param NetworkInterface $network
65
     * @return AddressInterface
66
     * @throws \BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure
67
     */
68 162
    public static function fromString($address, NetworkInterface $network = null)
69
    {
70 162
        $network = $network ?: Bitcoin::getNetwork();
71 162
        $data = Base58::decodeCheck($address);
72 162
        $prefixByte = $data->slice(0, 1)->getHex();
73
74 162
        if ($prefixByte === $network->getP2shByte()) {
75 24
            return new ScriptHashAddress($data->slice(1));
76 138
        } else if ($prefixByte === $network->getAddressByte()) {
77 132
            return new PayToPubKeyHashAddress($data->slice(1));
78
        } else {
79 6
            throw new \InvalidArgumentException("Invalid prefix [{$prefixByte}]");
80
        }
81
    }
82
83
    /**
84
     * @param string $address
85
     * @param NetworkInterface $network
86
     * @return AddressInterface
87
     * @throws \BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure
88
     */
89 12
    public static function isValidAddress($address, NetworkInterface $network = null)
90
    {
91 12
        try {
92 12
            self::fromString($address, $network);
93
            $is_valid = true;
94 12
        } catch (\Exception $e) {
95 6
            $is_valid = false;
96 6
        }
97 12
98
        return $is_valid;
99
    }
100 6
101 6
    /**
102 6
     * @param ScriptInterface $script
103
     * @param NetworkInterface $network
104
     * @return String
105
     * @throws \RuntimeException
106
     */
107
    public static function getAssociatedAddress(ScriptInterface $script, NetworkInterface $network = null)
108
    {
109
        $classifier = new OutputClassifier($script);
110
        $network = $network ?: Bitcoin::getNetwork();
111
        try {
112
            if ($classifier->isPayToPublicKey()) {
113
                $address = PublicKeyFactory::fromHex($script->getScriptParser()->decode()[0]->getData())->getAddress();
114
            } else {
115
                $address = self::fromOutputScript($script);
116
            }
117
118
            return Base58::encodeCheck(Buffer::hex($network->getAddressByte() . $address->getHash(), 21));
119
        } catch (\Exception $e) {
120
            throw new \RuntimeException('No address associated with this script type');
121
        }
122
    }
123
}
124