@exodus/bitcoinjs-lib-forks 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +207 -0
  4. package/package.json +67 -0
  5. package/src/address.js +97 -0
  6. package/src/block.js +177 -0
  7. package/src/bufferutils.js +56 -0
  8. package/src/crypto.js +29 -0
  9. package/src/ecdsa.js +161 -0
  10. package/src/ecpair.js +131 -0
  11. package/src/ecsignature.js +97 -0
  12. package/src/hdnode.js +316 -0
  13. package/src/index.js +23 -0
  14. package/src/networks.js +47 -0
  15. package/src/script.js +214 -0
  16. package/src/script_number.js +68 -0
  17. package/src/templates/index.js +74 -0
  18. package/src/templates/multisig/index.js +4 -0
  19. package/src/templates/multisig/input.js +71 -0
  20. package/src/templates/multisig/output.js +64 -0
  21. package/src/templates/nulldata.js +34 -0
  22. package/src/templates/pubkey/index.js +4 -0
  23. package/src/templates/pubkey/input.js +39 -0
  24. package/src/templates/pubkey/output.js +33 -0
  25. package/src/templates/pubkeyhash/index.js +4 -0
  26. package/src/templates/pubkeyhash/input.js +51 -0
  27. package/src/templates/pubkeyhash/output.js +42 -0
  28. package/src/templates/scripthash/index.js +4 -0
  29. package/src/templates/scripthash/input.js +84 -0
  30. package/src/templates/scripthash/output.js +34 -0
  31. package/src/templates/witnesscommitment/index.js +3 -0
  32. package/src/templates/witnesscommitment/output.js +42 -0
  33. package/src/templates/witnesspubkeyhash/index.js +4 -0
  34. package/src/templates/witnesspubkeyhash/input.js +44 -0
  35. package/src/templates/witnesspubkeyhash/output.js +33 -0
  36. package/src/templates/witnessscripthash/index.js +4 -0
  37. package/src/templates/witnessscripthash/input.js +63 -0
  38. package/src/templates/witnessscripthash/output.js +33 -0
  39. package/src/transaction.js +547 -0
  40. package/src/transaction_builder.js +825 -0
  41. package/src/types.js +53 -0
@@ -0,0 +1,547 @@
1
+ var Buffer = require('safe-buffer').Buffer
2
+ var bcrypto = require('./crypto')
3
+ var bscript = require('./script')
4
+ var bufferutils = require('./bufferutils')
5
+ var opcodes = require('bitcoin-ops')
6
+ var typeforce = require('typeforce')
7
+ var types = require('./types')
8
+ var varuint = require('varuint-bitcoin')
9
+
10
+ function varSliceSize (someScript) {
11
+ var length = someScript.length
12
+
13
+ return varuint.encodingLength(length) + length
14
+ }
15
+
16
+ function vectorSize (someVector) {
17
+ var length = someVector.length
18
+
19
+ return varuint.encodingLength(length) + someVector.reduce(function (sum, witness) {
20
+ return sum + varSliceSize(witness)
21
+ }, 0)
22
+ }
23
+
24
+ function Transaction () {
25
+ this.version = 1
26
+ this.locktime = 0
27
+ this.ins = []
28
+ this.outs = []
29
+ }
30
+
31
+ Transaction.DEFAULT_SEQUENCE = 0xffffffff
32
+ Transaction.SIGHASH_ALL = 0x01
33
+ Transaction.SIGHASH_NONE = 0x02
34
+ Transaction.SIGHASH_SINGLE = 0x03
35
+ Transaction.SIGHASH_ANYONECANPAY = 0x80
36
+ Transaction.SIGHASH_BITCOINCASHBIP143 = 0x40
37
+ Transaction.ADVANCED_TRANSACTION_MARKER = 0x00
38
+ Transaction.ADVANCED_TRANSACTION_FLAG = 0x01
39
+ Transaction.FORKID_BTG = 0x4F // 79
40
+ Transaction.FORKID_BCH = 0xFF0001
41
+
42
+ var EMPTY_SCRIPT = Buffer.allocUnsafe(0)
43
+ var EMPTY_WITNESS = []
44
+ var ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
45
+ var ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
46
+ var VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex')
47
+ var BLANK_OUTPUT = {
48
+ script: EMPTY_SCRIPT,
49
+ valueBuffer: VALUE_UINT64_MAX
50
+ }
51
+
52
+ Transaction.fromBuffer = function (buffer, __noStrict) {
53
+ var offset = 0
54
+ function readSlice (n) {
55
+ offset += n
56
+ return buffer.slice(offset - n, offset)
57
+ }
58
+
59
+ function readUInt32 () {
60
+ var i = buffer.readUInt32LE(offset)
61
+ offset += 4
62
+ return i
63
+ }
64
+
65
+ function readInt32 () {
66
+ var i = buffer.readInt32LE(offset)
67
+ offset += 4
68
+ return i
69
+ }
70
+
71
+ function readUInt64 () {
72
+ var i = bufferutils.readUInt64LE(buffer, offset)
73
+ offset += 8
74
+ return i
75
+ }
76
+
77
+ function readVarInt () {
78
+ var vi = varuint.decode(buffer, offset)
79
+ offset += varuint.decode.bytes
80
+ return vi
81
+ }
82
+
83
+ function readVarSlice () {
84
+ return readSlice(readVarInt())
85
+ }
86
+
87
+ function readVector () {
88
+ var count = readVarInt()
89
+ var vector = []
90
+ for (var i = 0; i < count; i++) vector.push(readVarSlice())
91
+ return vector
92
+ }
93
+
94
+ var tx = new Transaction()
95
+ tx.version = readInt32()
96
+
97
+ var marker = buffer.readUInt8(offset)
98
+ var flag = buffer.readUInt8(offset + 1)
99
+
100
+ var hasWitnesses = false
101
+ if (marker === Transaction.ADVANCED_TRANSACTION_MARKER &&
102
+ flag === Transaction.ADVANCED_TRANSACTION_FLAG) {
103
+ offset += 2
104
+ hasWitnesses = true
105
+ }
106
+
107
+ var vinLen = readVarInt()
108
+ for (var i = 0; i < vinLen; ++i) {
109
+ tx.ins.push({
110
+ hash: readSlice(32),
111
+ index: readUInt32(),
112
+ script: readVarSlice(),
113
+ sequence: readUInt32(),
114
+ witness: EMPTY_WITNESS
115
+ })
116
+ }
117
+
118
+ var voutLen = readVarInt()
119
+ for (i = 0; i < voutLen; ++i) {
120
+ tx.outs.push({
121
+ value: readUInt64(),
122
+ script: readVarSlice()
123
+ })
124
+ }
125
+
126
+ if (hasWitnesses) {
127
+ for (i = 0; i < vinLen; ++i) {
128
+ tx.ins[i].witness = readVector()
129
+ }
130
+
131
+ // was this pointless?
132
+ if (!tx.hasWitnesses()) throw new Error('Transaction has superfluous witness data')
133
+ }
134
+
135
+ tx.locktime = readUInt32()
136
+
137
+ if (__noStrict) return tx
138
+ if (offset !== buffer.length) throw new Error('Transaction has unexpected data')
139
+
140
+ return tx
141
+ }
142
+
143
+ Transaction.fromHex = function (hex) {
144
+ return Transaction.fromBuffer(Buffer.from(hex, 'hex'))
145
+ }
146
+
147
+ Transaction.isCoinbaseHash = function (buffer) {
148
+ typeforce(types.Hash256bit, buffer)
149
+ for (var i = 0; i < 32; ++i) {
150
+ if (buffer[i] !== 0) return false
151
+ }
152
+ return true
153
+ }
154
+
155
+ Transaction.prototype.isCoinbase = function () {
156
+ return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
157
+ }
158
+
159
+ Transaction.prototype.addInput = function (hash, index, sequence, scriptSig) {
160
+ typeforce(types.tuple(
161
+ types.Hash256bit,
162
+ types.UInt32,
163
+ types.maybe(types.UInt32),
164
+ types.maybe(types.Buffer)
165
+ ), arguments)
166
+
167
+ if (types.Null(sequence)) {
168
+ sequence = Transaction.DEFAULT_SEQUENCE
169
+ }
170
+
171
+ // Add the input and return the input's index
172
+ return (this.ins.push({
173
+ hash: hash,
174
+ index: index,
175
+ script: scriptSig || EMPTY_SCRIPT,
176
+ sequence: sequence,
177
+ witness: EMPTY_WITNESS
178
+ }) - 1)
179
+ }
180
+
181
+ Transaction.prototype.addOutput = function (scriptPubKey, value) {
182
+ typeforce(types.tuple(types.Buffer, types.Satoshi), arguments)
183
+
184
+ // Add the output and return the output's index
185
+ return (this.outs.push({
186
+ script: scriptPubKey,
187
+ value: value
188
+ }) - 1)
189
+ }
190
+
191
+ Transaction.prototype.hasWitnesses = function () {
192
+ return this.ins.some(function (x) {
193
+ return x.witness.length !== 0
194
+ })
195
+ }
196
+
197
+ Transaction.prototype.weight = function () {
198
+ var base = this.__byteLength(false)
199
+ var total = this.__byteLength(true)
200
+ return base * 3 + total
201
+ }
202
+
203
+ Transaction.prototype.virtualSize = function () {
204
+ return Math.ceil(this.weight() / 4)
205
+ }
206
+
207
+ Transaction.prototype.byteLength = function () {
208
+ return this.__byteLength(true)
209
+ }
210
+
211
+ Transaction.prototype.__byteLength = function (__allowWitness) {
212
+ var hasWitnesses = __allowWitness && this.hasWitnesses()
213
+
214
+ return (
215
+ (hasWitnesses ? 10 : 8) +
216
+ varuint.encodingLength(this.ins.length) +
217
+ varuint.encodingLength(this.outs.length) +
218
+ this.ins.reduce(function (sum, input) { return sum + 40 + varSliceSize(input.script) }, 0) +
219
+ this.outs.reduce(function (sum, output) { return sum + 8 + varSliceSize(output.script) }, 0) +
220
+ (hasWitnesses ? this.ins.reduce(function (sum, input) { return sum + vectorSize(input.witness) }, 0) : 0)
221
+ )
222
+ }
223
+
224
+ Transaction.prototype.clone = function () {
225
+ var newTx = new Transaction()
226
+ newTx.version = this.version
227
+ newTx.locktime = this.locktime
228
+
229
+ newTx.ins = this.ins.map(function (txIn) {
230
+ return {
231
+ hash: txIn.hash,
232
+ index: txIn.index,
233
+ script: txIn.script,
234
+ sequence: txIn.sequence,
235
+ witness: txIn.witness
236
+ }
237
+ })
238
+
239
+ newTx.outs = this.outs.map(function (txOut) {
240
+ return {
241
+ script: txOut.script,
242
+ value: txOut.value
243
+ }
244
+ })
245
+
246
+ return newTx
247
+ }
248
+
249
+ /**
250
+ * Hash transaction for signing a specific input.
251
+ *
252
+ * Bitcoin uses a different hash for each signed transaction input.
253
+ * This method copies the transaction, makes the necessary changes based on the
254
+ * hashType, and then hashes the result.
255
+ * This hash can then be used to sign the provided transaction input.
256
+ */
257
+ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashType) {
258
+ typeforce(types.tuple(types.UInt32, types.Buffer, /* types.UInt8 */ types.Number), arguments)
259
+
260
+ // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29
261
+ if (inIndex >= this.ins.length) return ONE
262
+
263
+ // ignore OP_CODESEPARATOR
264
+ var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
265
+ return x !== opcodes.OP_CODESEPARATOR
266
+ }))
267
+
268
+ var txTmp = this.clone()
269
+
270
+ // SIGHASH_NONE: ignore all outputs? (wildcard payee)
271
+ if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
272
+ txTmp.outs = []
273
+
274
+ // ignore sequence numbers (except at inIndex)
275
+ txTmp.ins.forEach(function (input, i) {
276
+ if (i === inIndex) return
277
+
278
+ input.sequence = 0
279
+ })
280
+
281
+ // SIGHASH_SINGLE: ignore all outputs, except at the same index?
282
+ } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
283
+ // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60
284
+ if (inIndex >= this.outs.length) return ONE
285
+
286
+ // truncate outputs after
287
+ txTmp.outs.length = inIndex + 1
288
+
289
+ // "blank" outputs before
290
+ for (var i = 0; i < inIndex; i++) {
291
+ txTmp.outs[i] = BLANK_OUTPUT
292
+ }
293
+
294
+ // ignore sequence numbers (except at inIndex)
295
+ txTmp.ins.forEach(function (input, y) {
296
+ if (y === inIndex) return
297
+
298
+ input.sequence = 0
299
+ })
300
+ }
301
+
302
+ // SIGHASH_ANYONECANPAY: ignore inputs entirely?
303
+ if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
304
+ txTmp.ins = [txTmp.ins[inIndex]]
305
+ txTmp.ins[0].script = ourScript
306
+
307
+ // SIGHASH_ALL: only ignore input scripts
308
+ } else {
309
+ // "blank" others input scripts
310
+ txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT })
311
+ txTmp.ins[inIndex].script = ourScript
312
+ }
313
+
314
+ // serialize and hash
315
+ var buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4)
316
+ buffer.writeInt32LE(hashType, buffer.length - 4)
317
+ txTmp.__toBuffer(buffer, 0, false)
318
+
319
+ return bcrypto.hash256(buffer)
320
+ }
321
+
322
+ Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value, hashType) {
323
+ typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), arguments)
324
+
325
+ var tbuffer, toffset
326
+ function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) }
327
+ function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) }
328
+ function writeUInt64 (i) { toffset = bufferutils.writeUInt64LE(tbuffer, i, toffset) }
329
+ function writeVarInt (i) {
330
+ varuint.encode(i, tbuffer, toffset)
331
+ toffset += varuint.encode.bytes
332
+ }
333
+ function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) }
334
+
335
+ var hashOutputs = ZERO
336
+ var hashPrevouts = ZERO
337
+ var hashSequence = ZERO
338
+
339
+ if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
340
+ tbuffer = Buffer.allocUnsafe(36 * this.ins.length)
341
+ toffset = 0
342
+
343
+ this.ins.forEach(function (txIn) {
344
+ writeSlice(txIn.hash)
345
+ writeUInt32(txIn.index)
346
+ })
347
+
348
+ hashPrevouts = bcrypto.hash256(tbuffer)
349
+ }
350
+
351
+ if (!(hashType & Transaction.SIGHASH_ANYONECANPAY) &&
352
+ (hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
353
+ (hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
354
+ tbuffer = Buffer.allocUnsafe(4 * this.ins.length)
355
+ toffset = 0
356
+
357
+ this.ins.forEach(function (txIn) {
358
+ writeUInt32(txIn.sequence)
359
+ })
360
+
361
+ hashSequence = bcrypto.hash256(tbuffer)
362
+ }
363
+
364
+ if ((hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
365
+ (hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
366
+ var txOutsSize = this.outs.reduce(function (sum, output) {
367
+ return sum + 8 + varSliceSize(output.script)
368
+ }, 0)
369
+
370
+ tbuffer = Buffer.allocUnsafe(txOutsSize)
371
+ toffset = 0
372
+
373
+ this.outs.forEach(function (out) {
374
+ writeUInt64(out.value)
375
+ writeVarSlice(out.script)
376
+ })
377
+
378
+ hashOutputs = bcrypto.hash256(tbuffer)
379
+ } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
380
+ var output = this.outs[inIndex]
381
+
382
+ tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script))
383
+ toffset = 0
384
+ writeUInt64(output.value)
385
+ writeVarSlice(output.script)
386
+
387
+ hashOutputs = bcrypto.hash256(tbuffer)
388
+ }
389
+
390
+ tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript))
391
+ toffset = 0
392
+
393
+ var input = this.ins[inIndex]
394
+ writeUInt32(this.version)
395
+ writeSlice(hashPrevouts)
396
+ writeSlice(hashSequence)
397
+ writeSlice(input.hash)
398
+ writeUInt32(input.index)
399
+ writeVarSlice(prevOutScript)
400
+ writeUInt64(value)
401
+ writeUInt32(input.sequence)
402
+ writeSlice(hashOutputs)
403
+ writeUInt32(this.locktime)
404
+ writeUInt32(hashType)
405
+ return bcrypto.hash256(tbuffer)
406
+ }
407
+
408
+ /**
409
+ * Hash transaction for signing a specific input for Bitcoin Cash.
410
+ */
411
+ Transaction.prototype.hashForCashSignature = function (inIndex, prevOutScript, inAmount, hashType) {
412
+ typeforce(types.tuple(types.UInt32, types.Buffer, /* types.UInt8 */ types.Number, types.maybe(types.UInt53)), arguments)
413
+
414
+ // This function works the way it does because Bitcoin Cash
415
+ // uses BIP143 as their replay protection, AND their algo
416
+ // includes `forkId | hashType`, AND since their forkId=0,
417
+ // this is a NOP, and has no difference to segwit. To support
418
+ // other forks, another parameter is required, and a new parameter
419
+ // would be required in the hashForWitnessV0 function, or
420
+ // it could be broken into two..
421
+
422
+ // BIP143 sighash activated in BitcoinCash via 0x40 bit
423
+ if (hashType & Transaction.SIGHASH_BITCOINCASHBIP143) {
424
+ if (types.Null(inAmount)) {
425
+ throw new Error('Bitcoin Cash sighash requires value of input to be signed.')
426
+ }
427
+ return this.hashForWitnessV0(inIndex, prevOutScript, inAmount, hashType)
428
+ } else {
429
+ return this.hashForSignature(inIndex, prevOutScript, hashType)
430
+ }
431
+ }
432
+
433
+ /**
434
+ * Hash transaction for signing a specific input for Bitcoin Gold.
435
+ */
436
+ Transaction.prototype.hashForGoldSignature = function (inIndex, prevOutScript, inAmount, hashType, sigVersion) {
437
+ typeforce(types.tuple(types.UInt32, types.Buffer, /* types.UInt8 */ types.Number, types.maybe(types.UInt53)), arguments)
438
+
439
+ // Bitcoin Gold also implements segregated witness
440
+ // therefore we can pull out the setting of nForkHashType
441
+ // and pass it into the functions.
442
+
443
+ var nForkHashType = hashType
444
+ var fUseForkId = (hashType & Transaction.SIGHASH_BITCOINCASHBIP143) > 0
445
+ if (fUseForkId) {
446
+ nForkHashType |= Transaction.FORKID_BTG << 8
447
+ }
448
+
449
+ // BIP143 sighash activated in BitcoinCash via 0x40 bit
450
+ if (sigVersion || fUseForkId) {
451
+ if (types.Null(inAmount)) {
452
+ throw new Error('Bitcoin Cash sighash requires value of input to be signed.')
453
+ }
454
+ return this.hashForWitnessV0(inIndex, prevOutScript, inAmount, nForkHashType)
455
+ } else {
456
+ return this.hashForSignature(inIndex, prevOutScript, nForkHashType)
457
+ }
458
+ }
459
+
460
+ Transaction.prototype.getHash = function () {
461
+ return bcrypto.hash256(this.__toBuffer(undefined, undefined, false))
462
+ }
463
+
464
+ Transaction.prototype.getId = function () {
465
+ // transaction hash's are displayed in reverse order
466
+ return this.getHash().reverse().toString('hex')
467
+ }
468
+
469
+ Transaction.prototype.toBuffer = function (buffer, initialOffset) {
470
+ return this.__toBuffer(buffer, initialOffset, true)
471
+ }
472
+
473
+ Transaction.prototype.__toBuffer = function (buffer, initialOffset, __allowWitness) {
474
+ if (!buffer) buffer = Buffer.allocUnsafe(this.__byteLength(__allowWitness))
475
+
476
+ var offset = initialOffset || 0
477
+ function writeSlice (slice) { offset += slice.copy(buffer, offset) }
478
+ function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) }
479
+ function writeUInt32 (i) { offset = buffer.writeUInt32LE(i, offset) }
480
+ function writeInt32 (i) { offset = buffer.writeInt32LE(i, offset) }
481
+ function writeUInt64 (i) { offset = bufferutils.writeUInt64LE(buffer, i, offset) }
482
+ function writeVarInt (i) {
483
+ varuint.encode(i, buffer, offset)
484
+ offset += varuint.encode.bytes
485
+ }
486
+ function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) }
487
+ function writeVector (vector) { writeVarInt(vector.length); vector.forEach(writeVarSlice) }
488
+
489
+ writeInt32(this.version)
490
+
491
+ var hasWitnesses = __allowWitness && this.hasWitnesses()
492
+
493
+ if (hasWitnesses) {
494
+ writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER)
495
+ writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG)
496
+ }
497
+
498
+ writeVarInt(this.ins.length)
499
+
500
+ this.ins.forEach(function (txIn) {
501
+ writeSlice(txIn.hash)
502
+ writeUInt32(txIn.index)
503
+ writeVarSlice(txIn.script)
504
+ writeUInt32(txIn.sequence)
505
+ })
506
+
507
+ writeVarInt(this.outs.length)
508
+ this.outs.forEach(function (txOut) {
509
+ if (!txOut.valueBuffer) {
510
+ writeUInt64(txOut.value)
511
+ } else {
512
+ writeSlice(txOut.valueBuffer)
513
+ }
514
+
515
+ writeVarSlice(txOut.script)
516
+ })
517
+
518
+ if (hasWitnesses) {
519
+ this.ins.forEach(function (input) {
520
+ writeVector(input.witness)
521
+ })
522
+ }
523
+
524
+ writeUInt32(this.locktime)
525
+
526
+ // avoid slicing unless necessary
527
+ if (initialOffset !== undefined) return buffer.slice(initialOffset, offset)
528
+ return buffer
529
+ }
530
+
531
+ Transaction.prototype.toHex = function () {
532
+ return this.toBuffer().toString('hex')
533
+ }
534
+
535
+ Transaction.prototype.setInputScript = function (index, scriptSig) {
536
+ typeforce(types.tuple(types.Number, types.Buffer), arguments)
537
+
538
+ this.ins[index].script = scriptSig
539
+ }
540
+
541
+ Transaction.prototype.setWitness = function (index, witness) {
542
+ typeforce(types.tuple(types.Number, [types.Buffer]), arguments)
543
+
544
+ this.ins[index].witness = witness
545
+ }
546
+
547
+ module.exports = Transaction