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

AddressFactory::fromString()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 6
nop 2
dl 0
loc 14
ccs 9
cts 9
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
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