AddressCreator   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Test Coverage

Coverage 97.14%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 97
ccs 34
cts 35
cp 0.9714
rs 10
wmc 17

4 Methods

Rating   Name   Duplication   Size   Complexity  
A readBase58Address() 0 16 4
A fromOutputScript() 0 22 6
A fromString() 0 13 4
A readSegwitAddress() 0 17 3
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\Buffertools\Buffer;
18
use BitWasp\Buffertools\BufferInterface;
19
20
class AddressCreator extends BaseAddressCreator
21
{
22
    /**
23
     * @param string $strAddress
24
     * @param NetworkInterface $network
25
     * @return Base58Address|null
26
     */
27 37
    protected function readBase58Address(string $strAddress, NetworkInterface $network)
28
    {
29
        try {
30 37
            $data = Base58::decodeCheck($strAddress);
31 31
            $prefixByte = $data->slice(0, $network->getP2shPrefixLength())->getHex();
32
33 31
            if ($prefixByte === $network->getP2shByte()) {
34 10
                return new ScriptHashAddress($data->slice(1));
35 21
            } else if ($prefixByte === $network->getAddressByte()) {
36 21
                return new PayToPubKeyHashAddress($data->slice($network->getAddressPrefixLength()));
37
            }
38 6
        } catch (\Exception $e) {
39
            // Just return null
40
        }
41
42 7
        return null;
43
    }
44
45
    /**
46
     * @param string $strAddress
47
     * @param NetworkInterface $network
48
     * @return SegwitAddress|null
49
     */
50 7
    protected function readSegwitAddress(string $strAddress, NetworkInterface $network)
51
    {
52
        try {
53 7
            list ($version, $program) = \BitWasp\Bech32\decodeSegwit($network->getSegwitBech32Prefix(), $strAddress);
54
55 6
            if (0 === $version) {
56 3
                $wp = WitnessProgram::v0(new Buffer($program));
57
            } else {
58 3
                $wp = new WitnessProgram($version, new Buffer($program));
59
            }
60
61 6
            return new SegwitAddress($wp);
62 1
        } catch (\Exception $e) {
63
            // Just return null
64
        }
65
66 1
        return null;
67
    }
68
69
    /**
70
     * @param ScriptInterface $outputScript
71
     * @return Address
72
     */
73 49
    public function fromOutputScript(ScriptInterface $outputScript): Address
74
    {
75 49
        if ($outputScript instanceof P2shScript || $outputScript instanceof WitnessScript) {
76
            throw new \RuntimeException("P2shScript & WitnessScript's are not accepted by fromOutputScript");
77
        }
78
79 49
        $wp = null;
80 49
        if ($outputScript->isWitness($wp)) {
81
            /** @var WitnessProgram $wp */
82 14
            return new SegwitAddress($wp);
83
        }
84
85 35
        $decode = (new OutputClassifier())->decode($outputScript);
86 35
        switch ($decode->getType()) {
87
            case ScriptType::P2PKH:
88
                /** @var BufferInterface $solution */
89 20
                return new PayToPubKeyHashAddress($decode->getSolution());
90
            case ScriptType::P2SH:
91
                /** @var BufferInterface $solution */
92 15
                return new ScriptHashAddress($decode->getSolution());
93
            default:
94 1
                throw new \RuntimeException('Script type is not associated with an address');
95
        }
96
    }
97
98
    /**
99
     * @param string $strAddress
100
     * @param NetworkInterface|null $network
101
     * @return Address
102
     * @throws UnrecognizedAddressException
103
     */
104 37
    public function fromString(string $strAddress, NetworkInterface $network = null): Address
105
    {
106 37
        $network = $network ?: Bitcoin::getNetwork();
107
108 37
        if (($base58Address = $this->readBase58Address($strAddress, $network))) {
109 30
            return $base58Address;
110
        }
111
112 7
        if (($bech32Address = $this->readSegwitAddress($strAddress, $network))) {
113 6
            return $bech32Address;
114
        }
115
116 1
        throw new UnrecognizedAddressException();
117
    }
118
}
119