Completed
Pull Request — master (#296)
by thomas
50:18 queued 47:04
created

TxBuilder   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 266
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Test Coverage

Coverage 78.82%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 266
ccs 67
cts 85
cp 0.7882
rs 10
c 3
b 0
f 0
wmc 21
lcom 1
cbo 14

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A get() 0 4 1
A getAndReset() 0 6 1
A version() 0 5 1
A output() 0 5 1
A locktime() 0 5 1
A lockToTimestamp() 0 5 1
A lockToBlockHeight() 0 5 1
A payToAddress() 0 10 1
A bip69() 0 10 1
A input() 0 13 3
A spendOutPoint() 0 10 2
A spendOutputFrom() 0 13 1
A reset() 0 9 1
A makeTransaction() 0 10 1
A inputs() 0 8 1
A outputs() 0 8 1
A witnesses() 0 8 1
1
<?php
2
3
namespace BitWasp\Bitcoin\Transaction\Factory;
4
5
use BitWasp\Bitcoin\Address\AddressInterface;
6
use BitWasp\Bitcoin\Collection\Transaction\TransactionInputCollection;
7
use BitWasp\Bitcoin\Collection\Transaction\TransactionOutputCollection;
8
use BitWasp\Bitcoin\Collection\Transaction\TransactionWitnessCollection;
9
use BitWasp\Bitcoin\Locktime;
10
use BitWasp\Bitcoin\Script\Script;
11
use BitWasp\Bitcoin\Script\ScriptFactory;
12
use BitWasp\Bitcoin\Script\ScriptInterface;
13
use BitWasp\Bitcoin\Script\ScriptWitnessInterface;
14
use BitWasp\Bitcoin\Transaction\Bip69\Bip69;
15
use BitWasp\Bitcoin\Transaction\OutPoint;
16
use BitWasp\Bitcoin\Transaction\OutPointInterface;
17
use BitWasp\Bitcoin\Transaction\Transaction;
18
use BitWasp\Bitcoin\Transaction\TransactionInput;
19
use BitWasp\Bitcoin\Transaction\TransactionInputInterface;
20
use BitWasp\Bitcoin\Transaction\TransactionInterface;
21
use BitWasp\Bitcoin\Transaction\TransactionOutput;
22
use BitWasp\Bitcoin\Transaction\TransactionOutputInterface;
23
use BitWasp\Buffertools\Buffer;
24
use BitWasp\Buffertools\BufferInterface;
25
26
class TxBuilder
27
{
28
    /**
29
     * @var int
30
     */
31
    private $nVersion;
32
33
    /**
34
     * @var array
35
     */
36
    private $inputs;
37
38
    /**
39
     * @var array
40
     */
41
    private $outputs;
42
43
    /**
44
     * @var array
45
     */
46
    private $witness;
47
48
    /**
49
     * @var int
50
     */
51
    private $nLockTime;
52
53 864
    public function __construct()
54
    {
55 864
        $this->reset();
56 864
    }
57
58
    /**
59
     * @return $this
60
     */
61 864
    public function reset()
62
    {
63 864
        $this->nVersion = 1;
64 864
        $this->inputs = [];
65 864
        $this->outputs = [];
66 864
        $this->witness = [];
67 864
        $this->nLockTime = 0;
68 864
        return $this;
69
    }
70
71
    /**
72
     * @return TransactionInterface
73
     */
74 858
    private function makeTransaction()
75
    {
76 858
        return new Transaction(
77 858
            $this->nVersion,
78 858
            new TransactionInputCollection($this->inputs),
79 858
            new TransactionOutputCollection($this->outputs),
80 858
            new TransactionWitnessCollection($this->witness),
81 858
            $this->nLockTime
82 858
        );
83
    }
84
85
    /**
86
     * @return TransactionInterface
87
     */
88 852
    public function get()
89
    {
90 852
        return $this->makeTransaction();
91
    }
92
93
    /**
94
     * @return TransactionInterface
95
     */
96 30
    public function getAndReset()
97
    {
98 30
        $transaction = $this->makeTransaction();
99 30
        $this->reset();
100 30
        return $transaction;
101
    }
102
103
    /**
104
     * @param int $nVersion
105
     * @return $this
106
     */
107 18
    public function version($nVersion)
108
    {
109 18
        $this->nVersion = $nVersion;
110 18
        return $this;
111
    }
112
113
    /**
114
     * @param BufferInterface|string $hashPrevOut - hex or BufferInterface
115
     * @param int $nPrevOut
116
     * @param Script|null $script
117
     * @param int $nSequence
118
     * @return $this
119
     */
120 774
    public function input($hashPrevOut, $nPrevOut, Script $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
121
    {
122 774
        $this->inputs[] = new TransactionInput(
123 774
            new OutPoint(
124 774
                $hashPrevOut instanceof BufferInterface ? $hashPrevOut : Buffer::hex($hashPrevOut, 32),
125
                $nPrevOut
126 774
            ),
127 774
            $script ?: new Script(),
128
            $nSequence
129 774
        );
130
131 774
        return $this;
132
    }
133
134
    /**
135
     * @param TransactionInputInterface[] $inputs
136
     * @return $this
137
     */
138
    public function inputs(array $inputs)
139
    {
140
        array_walk($inputs, function (TransactionInputInterface $input) {
141
            $this->inputs[] = $input;
142
        });
143
144
        return $this;
145
    }
146
147
    /**
148
     * @param integer $value
149
     * @param ScriptInterface $script
150
     * @return $this
151
     */
152 150
    public function output($value, ScriptInterface $script)
153
    {
154 150
        $this->outputs[] = new TransactionOutput($value, $script);
155 150
        return $this;
156
    }
157
158
    /**
159
     * @param TransactionOutputInterface[] $outputs
160
     * @return $this
161
     */
162
    public function outputs(array $outputs)
163
    {
164
        array_walk($outputs, function (TransactionOutputInterface $output) {
165
            $this->outputs[] = $output;
166
        });
167
168
        return $this;
169
    }
170
171
    /**
172
     * @param ScriptWitnessInterface[] $witness
173
     * @return $this
174
     */
175
    public function witnesses(array $witness)
176
    {
177
        array_walk($witness, function (ScriptWitnessInterface $witness) {
178
            $this->witness[] = $witness;
179
        });
180
181
        return $this;
182
    }
183
184
    /**
185
     * @param int $locktime
186
     * @return $this
187
     */
188 24
    public function locktime($locktime)
189
    {
190 24
        $this->nLockTime = $locktime;
191 24
        return $this;
192
    }
193
194
    /**
195
     * @param Locktime $lockTime
196
     * @param int $nTimestamp
197
     * @return $this
198
     * @throws \Exception
199
     */
200 6
    public function lockToTimestamp(Locktime $lockTime, $nTimestamp)
201
    {
202 6
        $this->locktime($lockTime->fromTimestamp($nTimestamp));
203 6
        return $this;
204
    }
205
206
    /**
207
     * @param Locktime $lockTime
208
     * @param int $blockHeight
209
     * @return $this
210
     * @throws \Exception
211
     */
212 6
    public function lockToBlockHeight(Locktime $lockTime, $blockHeight)
213
    {
214 6
        $this->locktime($lockTime->fromBlockHeight($blockHeight));
215 6
        return $this;
216
    }
217
218
    /**
219
     * @param OutPointInterface $outpoint
220
     * @param ScriptInterface|null $script
221
     * @param int $nSequence
222
     * @return $this
223
     */
224 54
    public function spendOutPoint(OutPointInterface $outpoint, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
225
    {
226 54
        $this->inputs[] = new TransactionInput(
227 54
            $outpoint,
228 54
            $script ?: new Script(),
229
            $nSequence
230 54
        );
231
232 54
        return $this;
233
    }
234
235
    /**
236
     * @param TransactionInterface $transaction
237
     * @param int $outputToSpend
238
     * @param ScriptInterface|null $script
239
     * @param int $nSequence
240
     * @return $this
241
     */
242 36
    public function spendOutputFrom(TransactionInterface $transaction, $outputToSpend, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
243
    {
244
        // Check TransactionOutput exists in $tx
245 36
        $transaction->getOutput($outputToSpend);
246 36
        $this->input(
247 36
            $transaction->getTxId(),
248 36
            $outputToSpend,
249 36
            $script,
0 ignored issues
show
Bug introduced by
It seems like $script defined by parameter $script on line 242 can also be of type object<BitWasp\Bitcoin\Script\ScriptInterface>; however, BitWasp\Bitcoin\Transact...tory\TxBuilder::input() does only seem to accept null|object<BitWasp\Bitcoin\Script\Script>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
250
            $nSequence
251 36
        );
252
253 36
        return $this;
254
    }
255
256
    /**
257
     * Create an output paying $value to an Address.
258
     *
259
     * @param int $value
260
     * @param AddressInterface $address
261
     * @return $this
262
     */
263 84
    public function payToAddress($value, AddressInterface $address)
264
    {
265
        // Create Script from address, then create an output.
266 84
        $this->output(
267 84
            $value,
268 84
            ScriptFactory::scriptPubKey()->payToAddress($address)
269 84
        );
270
271 84
        return $this;
272
    }
273
274
    /**
275
     * Sorts the transaction inputs and outputs lexicographically,
276
     * according to BIP69
277
     *
278
     * @param Bip69 $bip69
279
     * @return $this
280
     */
281
    public function bip69(Bip69 $bip69)
282
    {
283
        list ($inputs, $witness) = $bip69->sortInputsAndWitness($this->inputs, $this->witness);
284
285
        $this->inputs = $inputs;
286
        $this->outputs = $bip69->sortOutputs($this->outputs);
287
        $this->witness = $witness;
288
289
        return $this;
290
    }
291
}
292