Completed
Branch master (5ab745)
by
unknown
05:26
created

BIP32Path::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Blocktrail\SDK\Bitcoin;
4
5
/**
6
 * Class BIP32Path
7
 *
8
 * BIP32 path, does not mutate itself but returns new instance everytime
9
 *
10
 * @package Blocktrail\SDK
11
 */
12
class BIP32Path implements \ArrayAccess {
13
    protected $path;
14
15
    public function __construct($path) {
16
        $this->path = is_array($path) ? $path : explode("/", $path);
17
18
        if (strtolower($this->path[0]) != "m") {
19
            throw new \InvalidArgumentException("BIP32Path can only be used for absolute paths");
20
        }
21
    }
22
23
    /**
24
     * @return int
25
     */
26
    public function depth() {
27
        return count($this->path);
28
    }
29
30
    public function insert($insert, $offset) {
31
        $path = $this->path;
32
33
        array_splice($path, $offset+1, 0, [$insert]);
34
35
        return new static($path);
36
    }
37
38
    /**
39
     * increase the last level of the path by 1 and return the new path
40
     *
41
     * @return BIP32Path
42
     */
43
    public function next() {
44
        $path = $this->path;
45
46
        $last = array_pop($path);
47
48
        if ($hardened = (strpos($last, "'") !== false)) {
49
            $last = str_replace("'", "", $last);
50
        }
51
52
        $last = (int)$last;
53
        $last += 1;
54
55
        if ($hardened) {
56
            $last .= "'";
57
        }
58
59
        $path[] = $last;
60
61
        return new static($path);
62
    }
63
64
    /**
65
     * pop off one level of the path and return the new path
66
     *
67
     * @return BIP32Path
68
     */
69
    public function parent() {
70
        $path = $this->path;
71
72
        array_pop($path);
73
74
        if (empty($path)) {
75
            throw new \RuntimeException("Can't get parent of root path");
76
        }
77
78
        return new static($path);
79
    }
80
81
    /**
82
     * get child $child of the current path and return the new path
83
     *
84
     * @param $child
85
     * @return BIP32Path
86
     */
87
    public function child($child) {
88
        $path = $this->path;
89
90
        $path[] = $child;
91
92
        return new static($path);
93
    }
94
95
    /**
96
     * pop off one level of the path and add $last and return the new path
97
     *
98
     * @param $last
99
     * @return BIP32Path
100
     */
101
    public function last($last) {
102
        $path = $this->path;
103
104
        array_pop($path);
105
        $path[] = $last;
106
107
        return new static($path);
108
    }
109
110
    /**
111
     * harden the last level of the path and return the new path
112
     *
113
     * @return BIP32Path
114
     */
115 View Code Duplication
    public function hardened() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
        $path = $this->path;
117
118
        $last = array_pop($path);
119
120
        if (strpos($last, "'") !== false) {
121
            return $this;
122
        }
123
124
        $last .= "'";
125
126
        $path[] = $last;
127
128
        return new static($path);
129
    }
130
131
    /**
132
     * unharden the last level of the path and return the new path
133
     *
134
     * @return BIP32Path
135
     */
136 View Code Duplication
    public function unhardenedLast() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
        $path = $this->path;
138
139
        $last = array_pop($path);
140
141
        $last = str_replace("'", "", $last);
142
143
        $path[] = $last;
144
145
        return new static($path);
146
    }
147
148
    /**
149
     * unharden all levels of the path and return the new path
150
     *
151
     * @return BIP32Path
152
     */
153
    public function unhardenedPath() {
154
        $path = $this->path;
155
156
        foreach ($path as $i => $level) {
157
            $path[$i] = str_replace("'", "", $level);
158
        }
159
160
        return new static($path);
161
    }
162
163
    /**
164
     * change the path to be for the public key (starting with M/) and return the new path
165
     *
166
     * @return BIP32Path
167
     */
168 View Code Duplication
    public function publicPath() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
        $path = $this->path;
170
171
        if ($path[0] === "M") {
172
            return new static($path);
173
        } else {
174
            $path[0] = "M";
175
176
            return new static($path);
177
        }
178
    }
179
180
    /**
181
     * change the path to be for the private key (starting with m/) and return the new path
182
     *
183
     * @return BIP32Path
184
     */
185 View Code Duplication
    public function privatePath() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
        $path = $this->path;
187
188
        if ($path[0] === "m") {
189
            return new static($path);
190
        } else {
191
            $path[0] = "m";
192
193
            return new static($path);
194
        }
195
    }
196
197
    /**
198
     * get the string representation of the path
199
     *
200
     * @return string
201
     */
202
    public function getPath() {
203
        return implode("/", $this->path);
204
    }
205
206
    /**
207
     * get the last part of the path
208
     *
209
     * @return string
210
     */
211
    public function getLast() {
212
        return $this->path[count($this->path)-1];
213
    }
214
215
    /**
216
     * check if the last level of the path is hardened
217
     *
218
     * @return bool
219
     */
220
    public function isHardened() {
221
        $path = $this->path;
222
223
        $last = array_pop($path);
224
225
        return strpos($last, "'") !== false;
226
    }
227
228
    /**
229
     * check if the last level of the path is hardened
230
     *
231
     * @return bool
232
     */
233
    public function isPublicPath() {
234
        $path = $this->path;
235
236
        return $path[0] == "M";
237
    }
238
239
    /**
240
     * check if this path is parent path of the provided path
241
     *
242
     * @param string|BIP32Path $path
243
     * @return bool
244
     */
245
    public function isParentOf($path) {
246
        $path = BIP32Path::path($path);
247
248
        return strlen((string)$path) > strlen((string)$this) && strpos((string)$path, (string)$this) === 0;
249
    }
250
251
    /**
252
     * static method to initialize class
253
     *
254
     * @param $path
255
     * @return BIP32Path
256
     */
257
    public static function path($path) {
258
        if ($path instanceof static) {
259
            return $path;
260
        }
261
262
        return new static($path);
263
    }
264
265
    public function getKeyIndex() {
266
        return str_replace("'", "", $this->path[1]);
267
    }
268
269
    /**
270
     * count the levels in the path (including master)
271
     *
272
     * @return int
273
     */
274
    public function count() {
275
        return count($this->path);
276
    }
277
278
279
    public function offsetExists($offset) {
280
        return isset($this->path[$offset]);
281
    }
282
283
    public function offsetGet($offset) {
284
        return isset($this->path[$offset]) ? $this->path[$offset] : null;
285
    }
286
287
    public function offsetSet($offset, $value) {
288
        throw new \Exception("Not implemented");
289
    }
290
291
    public function offsetUnset($offset) {
292
        throw new \Exception("Not implemented");
293
    }
294
295
    /**
296
     * @return string
297
     */
298
    public function __toString() {
299
        return $this->getPath();
300
    }
301
}
302