Completed
Pull Request — master (#596)
by thomas
37:15
created

AddressReader::fromString()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 6
nop 2
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Address;
6
7
use BitWasp\Bitcoin\Base58;
8
use BitWasp\Bitcoin\Bitcoin;
9
use BitWasp\Bitcoin\Exceptions\UnrecognizedAddressException;
10
use BitWasp\Bitcoin\Network\NetworkInterface;
11
use BitWasp\Bitcoin\Script\Classifier\OutputClassifier;
12
use BitWasp\Bitcoin\Script\P2shScript;
13
use BitWasp\Bitcoin\Script\ScriptInterface;
14
use BitWasp\Bitcoin\Script\ScriptType;
15
use BitWasp\Bitcoin\Script\WitnessProgram;
16
use BitWasp\Bitcoin\Script\WitnessScript;
17
use BitWasp\Bitcoin\SegwitBech32;
18
use BitWasp\Buffertools\BufferInterface;
19
20
class AddressReader extends BaseAddressEncoder
21
{
22
    /**
23
     * @param string $strAddress
24
     * @param NetworkInterface $network
25
     * @return Base58Address|null
26
     */
27
    protected function readBase58Address(string $strAddress, NetworkInterface $network)
28
    {
29
        try {
30
            $data = Base58::decodeCheck($strAddress);
31
            $prefixByte = $data->slice(0, 1)->getHex();
32
33
            if ($prefixByte === $network->getP2shByte()) {
34
                return new ScriptHashAddress($data->slice(1));
35
            } else if ($prefixByte === $network->getAddressByte()) {
36
                return new PayToPubKeyHashAddress($data->slice(1));
37
            }
38
        } catch (\Exception $e) {
39
            // Just return null
40
        }
41
42
        return null;
43
    }
44
45
    /**
46
     * @param string $strAddress
47
     * @param NetworkInterface $network
48
     * @return SegwitAddress|null
49
     */
50
    protected function readSegwitAddress(string $strAddress, NetworkInterface $network)
51
    {
52
        try {
53
            return new SegwitAddress(SegwitBech32::decode($strAddress, $network));
54
        } catch (\Exception $e) {
55
            // Just return null
56
        }
57
58
        return null;
59
    }
60
61
    /**
62
     * @param ScriptInterface $outputScript
63
     * @return Address
64
     */
65
    public function fromOutputScript(ScriptInterface $outputScript): Address
66
    {
67
        if ($outputScript instanceof P2shScript || $outputScript instanceof WitnessScript) {
68
            throw new \RuntimeException("P2shScript & WitnessScript's are not accepted by fromOutputScript");
69
        }
70
71
        $wp = null;
72
        if ($outputScript->isWitness($wp)) {
73
            /** @var WitnessProgram $wp */
74
            return new SegwitAddress($wp);
75
        }
76
77
        $decode = (new OutputClassifier())->decode($outputScript);
78
        switch ($decode->getType()) {
79
            case ScriptType::P2PKH:
80
                /** @var BufferInterface $solution */
81
                return new PayToPubKeyHashAddress($decode->getSolution());
82
            case ScriptType::P2SH:
83
                /** @var BufferInterface $solution */
84
                return new ScriptHashAddress($decode->getSolution());
85
            default:
86
                throw new \RuntimeException('Script type is not associated with an address');
87
        }
88
    }
89
90
    /**
91
     * @param string $strAddress
92
     * @param NetworkInterface|null $network
93
     * @return Address
94
     * @throws UnrecognizedAddressException
95
     */
96
    public function fromString(string $strAddress, NetworkInterface $network = null): Address
97
    {
98
        $network = $network ?: Bitcoin::getNetwork();
99
100
        if (($base58Address = $this->readBase58Address($strAddress, $network))) {
101
            return $base58Address;
102
        }
103
104
        if (($bech32Address = $this->readSegwitAddress($strAddress, $network))) {
105
            return $bech32Address;
106
        }
107
108
        throw new UnrecognizedAddressException();
109
    }
110
}
111