Completed
Pull Request — master (#240)
by thomas
73:04
created

src/Transaction/Factory/TxBuilder.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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