Completed
Pull Request — master (#337)
by thomas
35:12
created

AddressFactory   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 13

Test Coverage

Coverage 84.62%

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 109
ccs 33
cts 39
cp 0.8462
rs 10
wmc 14
lcom 0
cbo 13

6 Methods

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