Completed
Push — 0.0.35 ( b2fc74...d8d049 )
by thomas
28:12 queued 09:10
created

AddressCreator::readBase58Address()   A

Complexity

Conditions 4
Paths 9

Size

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