Completed
Push — 0.0.34 ( 61212b...2e9020 )
by thomas
20:55
created

TxBuilder   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 79.49%

Importance

Changes 0
Metric Value
dl 0
loc 260
ccs 62
cts 78
cp 0.7949
rs 10
c 0
b 0
f 0
wmc 21
lcom 1
cbo 11

18 Methods

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