Completed
Push — master ( 1989a1...e79d55 )
by thomas
37:47
created

TxBuilder::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 90
    public function __construct()
54
    {
55 90
        $this->reset();
56 90
    }
57
58
    /**
59
     * @return $this
60
     */
61 90
    public function reset()
62
    {
63 90
        $this->nVersion = 1;
64 90
        $this->inputs = [];
65 90
        $this->outputs = [];
66 90
        $this->witness = [];
67 90
        $this->nLockTime = 0;
68 90
        return $this;
69
    }
70
71
    /**
72
     * @return TransactionInterface
73
     */
74 87
    private function makeTransaction()
75
    {
76 87
        return new Transaction(
77 87
            $this->nVersion,
78 87
            new TransactionInputCollection($this->inputs),
79 87
            new TransactionOutputCollection($this->outputs),
80 87
            new TransactionWitnessCollection($this->witness),
81 87
            $this->nLockTime
82 58
        );
83
    }
84
85
    /**
86
     * @return TransactionInterface
87
     */
88 84
    public function get()
89
    {
90 84
        return $this->makeTransaction();
91
    }
92
93
    /**
94
     * @return TransactionInterface
95
     */
96 15
    public function getAndReset()
97
    {
98 15
        $transaction = $this->makeTransaction();
99 15
        $this->reset();
100 15
        return $transaction;
101
    }
102
103
    /**
104
     * @param int $nVersion
105
     * @return $this
106
     */
107 9
    public function version($nVersion)
108
    {
109 9
        $this->nVersion = $nVersion;
110 9
        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 45
    public function input($hashPrevOut, $nPrevOut, Script $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
121
    {
122 45
        $this->inputs[] = new TransactionInput(
123 45
            new OutPoint(
124 45
                $hashPrevOut instanceof BufferInterface ? $hashPrevOut : Buffer::hex($hashPrevOut, 32),
125
                $nPrevOut
126 30
            ),
127 45
            $script ?: new Script(),
128
            $nSequence
129 30
        );
130
131 45
        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 78
    public function output($value, ScriptInterface $script)
153 12
    {
154 78
        $this->outputs[] = new TransactionOutput($value, $script);
155 78
        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 12
    public function locktime($locktime)
189
    {
190 12
        $this->nLockTime = $locktime;
191 12
        return $this;
192
    }
193
194
    /**
195
     * @param Locktime $lockTime
196
     * @param int $nTimestamp
197
     * @return $this
198
     * @throws \Exception
199
     */
200 3
    public function lockToTimestamp(Locktime $lockTime, $nTimestamp)
201
    {
202 3
        $this->locktime($lockTime->fromTimestamp($nTimestamp));
203 3
        return $this;
204
    }
205
206
    /**
207
     * @param Locktime $lockTime
208
     * @param int $blockHeight
209
     * @return $this
210
     * @throws \Exception
211
     */
212 3
    public function lockToBlockHeight(Locktime $lockTime, $blockHeight)
213
    {
214 3
        $this->locktime($lockTime->fromBlockHeight($blockHeight));
215 3
        return $this;
216
    }
217
218
    /**
219
     * @param OutPointInterface $outpoint
220
     * @param ScriptInterface|null $script
221
     * @param int $nSequence
222
     * @return $this
223
     */
224 27
    public function spendOutPoint(OutPointInterface $outpoint, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
225
    {
226 27
        $this->inputs[] = new TransactionInput(
227 18
            $outpoint,
228 27
            $script ?: new Script(),
229
            $nSequence
230 18
        );
231
232 27
        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 18
    public function spendOutputFrom(TransactionInterface $transaction, $outputToSpend, ScriptInterface $script = null, $nSequence = TransactionInputInterface::SEQUENCE_FINAL)
243
    {
244
        // Check TransactionOutput exists in $tx
245 18
        $transaction->getOutput($outputToSpend);
246 18
        $this->input(
247 18
            $transaction->getTxId(),
248 12
            $outputToSpend,
249 12
            $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 12
        );
252
253 18
        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 42
    public function payToAddress($value, AddressInterface $address)
264
    {
265
        // Create Script from address, then create an output.
266 42
        $this->output(
267 28
            $value,
268 42
            ScriptFactory::scriptPubKey()->payToAddress($address)
269 28
        );
270
271 42
        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