@smartledger/bsv 5.4.2 → 5.5.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 (93) hide show
  1. package/.mocharc.json +5 -0
  2. package/CHANGELOG.md +66 -0
  3. package/README.md +28 -8
  4. package/bsv-covenant.min.js +8 -8
  5. package/bsv-gdaf.min.js +11 -11
  6. package/bsv-ltp.min.js +11 -11
  7. package/bsv-smartcontract.min.js +8 -8
  8. package/bsv.bundle.js +11 -11
  9. package/bsv.min.js +11 -11
  10. package/lib/smart_contract/authorizers.js +159 -0
  11. package/lib/smart_contract/covenant_helpers.js +3 -3
  12. package/lib/smart_contract/dsl.js +1 -1
  13. package/lib/smart_contract/index.js +9 -8
  14. package/lib/smart_contract/pels.js +1 -0
  15. package/lib/smart_contract/pushtx.js +51 -7
  16. package/lib/smart_contract/token.js +179 -35
  17. package/package.json +3 -1
  18. package/test/address.js +629 -0
  19. package/test/block/block.js +239 -0
  20. package/test/block/blockheader.js +270 -0
  21. package/test/block/merkleblock.js +207 -0
  22. package/test/cli/smoke.js +261 -0
  23. package/test/credentials-test.js +329 -0
  24. package/test/crypto/bn.js +168 -0
  25. package/test/crypto/ecdsa.js +328 -0
  26. package/test/crypto/elliptic-fixed.js +61 -0
  27. package/test/crypto/hash.browser.js +121 -0
  28. package/test/crypto/hash.js +122 -0
  29. package/test/crypto/point.js +193 -0
  30. package/test/crypto/random.js +32 -0
  31. package/test/crypto/security.js +127 -0
  32. package/test/crypto/shamir.js +169 -0
  33. package/test/crypto/signature.js +318 -0
  34. package/test/data/bip69.json +215 -0
  35. package/test/data/bitcoind/base58_keys_invalid.json +152 -0
  36. package/test/data/bitcoind/base58_keys_valid.json +452 -0
  37. package/test/data/bitcoind/blocks.json +27 -0
  38. package/test/data/bitcoind/script_tests.json +2244 -0
  39. package/test/data/bitcoind/sig_canonical.json +7 -0
  40. package/test/data/bitcoind/sig_noncanonical.json +22 -0
  41. package/test/data/bitcoind/tx_invalid.json +177 -0
  42. package/test/data/bitcoind/tx_valid.json +224 -0
  43. package/test/data/blk86756-testnet.dat +0 -0
  44. package/test/data/blk86756-testnet.js +12 -0
  45. package/test/data/blk86756-testnet.json +684 -0
  46. package/test/data/ecdsa.json +230 -0
  47. package/test/data/merkleblocks.js +486 -0
  48. package/test/data/messages.json +22 -0
  49. package/test/data/sighash.json +1004 -0
  50. package/test/data/tx_creation.json +85 -0
  51. package/test/ecies/bitcore-ecies.js +170 -0
  52. package/test/ecies/electrum-ecies.js +206 -0
  53. package/test/encoding/base58.js +131 -0
  54. package/test/encoding/base58check.js +136 -0
  55. package/test/encoding/bufferreader.js +328 -0
  56. package/test/encoding/bufferwriter.js +160 -0
  57. package/test/encoding/varint.js +104 -0
  58. package/test/gdaf/canonicalize.js +140 -0
  59. package/test/hdkeys.js +365 -0
  60. package/test/hdprivatekey.js +330 -0
  61. package/test/hdpublickey.js +293 -0
  62. package/test/index.js +16 -0
  63. package/test/ltp/right.js +198 -0
  64. package/test/message/message.js +190 -0
  65. package/test/mnemonic/data/fixtures.json +300 -0
  66. package/test/mnemonic/mnemonic.js +245 -0
  67. package/test/mnemonic/mocha.opts +1 -0
  68. package/test/mnemonic/pbkdf2.test.js +43 -0
  69. package/test/networks.js +162 -0
  70. package/test/opcode.js +161 -0
  71. package/test/privatekey.js +430 -0
  72. package/test/publickey.js +411 -0
  73. package/test/script/genesis_limits.js +80 -0
  74. package/test/script/interpreter.js +723 -0
  75. package/test/script/script.js +1256 -0
  76. package/test/script/string_ops.js +72 -0
  77. package/test/smart_contract/covenants.js +247 -0
  78. package/test/smart_contract/dsl_debugger.js +103 -0
  79. package/test/smart_contract/token_generalized.js +187 -0
  80. package/test/transaction/deserialize.js +33 -0
  81. package/test/transaction/input/input.js +92 -0
  82. package/test/transaction/input/multisig.js +174 -0
  83. package/test/transaction/input/multisigscripthash.js +111 -0
  84. package/test/transaction/input/publickey.js +68 -0
  85. package/test/transaction/input/publickeyhash.js +59 -0
  86. package/test/transaction/output.js +185 -0
  87. package/test/transaction/sighash.js +71 -0
  88. package/test/transaction/signature.js +127 -0
  89. package/test/transaction/transaction.js +1299 -0
  90. package/test/transaction/unspentoutput.js +92 -0
  91. package/test/util/js.js +76 -0
  92. package/test/util/preconditions.js +79 -0
  93. package/test/vcjwt/interop.js +126 -0
@@ -0,0 +1,270 @@
1
+ 'use strict'
2
+
3
+ var bsv = require('../..')
4
+ var BN = require('../../lib/crypto/bn')
5
+ var BufferReader = bsv.encoding.BufferReader
6
+ var BufferWriter = bsv.encoding.BufferWriter
7
+
8
+ var BlockHeader = bsv.BlockHeader
9
+ var fs = require('fs')
10
+ var should = require('chai').should()
11
+
12
+ // https://test-insight.bitpay.com/block/000000000b99b16390660d79fcc138d2ad0c89a0d044c4201a02bdf1f61ffa11
13
+ var dataRawBlockBuffer = fs.readFileSync('test/data/blk86756-testnet.dat')
14
+ var dataRawBlockBinary = fs.readFileSync('test/data/blk86756-testnet.dat', 'binary')
15
+ var dataRawId = '000000000b99b16390660d79fcc138d2ad0c89a0d044c4201a02bdf1f61ffa11'
16
+ var data = require('../data/blk86756-testnet')
17
+
18
+ describe('BlockHeader', function () {
19
+ var version = data.version
20
+ var prevblockidbuf = Buffer.from(data.prevblockidhex, 'hex')
21
+ var merklerootbuf = Buffer.from(data.merkleroothex, 'hex')
22
+ var time = data.time
23
+ var bits = data.bits
24
+ var nonce = data.nonce
25
+ var bh = new BlockHeader({
26
+ version: version,
27
+ prevHash: prevblockidbuf,
28
+ merkleRoot: merklerootbuf,
29
+ time: time,
30
+ bits: bits,
31
+ nonce: nonce
32
+ })
33
+ var bhhex = data.blockheaderhex
34
+ var bhbuf = Buffer.from(bhhex, 'hex')
35
+
36
+ it('should make a new blockheader', function () {
37
+ BlockHeader(bhbuf).toBuffer().toString('hex').should.equal(bhhex)
38
+ })
39
+
40
+ it('should not make an empty block', function () {
41
+ (function () {
42
+ BlockHeader()
43
+ }).should.throw('Unrecognized argument for BlockHeader')
44
+ })
45
+
46
+ describe('#constructor', function () {
47
+ it('should set all the variables', function () {
48
+ var bh = new BlockHeader({
49
+ version: version,
50
+ prevHash: prevblockidbuf,
51
+ merkleRoot: merklerootbuf,
52
+ time: time,
53
+ bits: bits,
54
+ nonce: nonce
55
+ })
56
+ should.exist(bh.version)
57
+ should.exist(bh.prevHash)
58
+ should.exist(bh.merkleRoot)
59
+ should.exist(bh.time)
60
+ should.exist(bh.bits)
61
+ should.exist(bh.nonce)
62
+ })
63
+
64
+ it('will throw an error if the argument object hash property doesn\'t match', function () {
65
+ (function () {
66
+ new BlockHeader({ //eslint-disable-line
67
+ hash: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
68
+ version: version,
69
+ prevHash: prevblockidbuf,
70
+ merkleRoot: merklerootbuf,
71
+ time: time,
72
+ bits: bits,
73
+ nonce: nonce
74
+ })
75
+ }).should.throw('Argument object hash property does not match block hash.')
76
+ })
77
+ })
78
+
79
+ describe('version', function () {
80
+ it('is interpreted as an int32le', function () {
81
+ var hex = 'ffffffff00000000000000000000000000000000000000000000000000000000000000004141414141414141414141414141414141414141414141414141414141414141010000000200000003000000'
82
+ var header = BlockHeader.fromBuffer(Buffer.from(hex, 'hex'))
83
+ header.version.should.equal(-1)
84
+ header.timestamp.should.equal(1)
85
+ })
86
+ })
87
+
88
+ describe('#fromObject', function () {
89
+ it('should set all the variables', function () {
90
+ var bh = BlockHeader.fromObject({
91
+ version: version,
92
+ prevHash: prevblockidbuf.toString('hex'),
93
+ merkleRoot: merklerootbuf.toString('hex'),
94
+ time: time,
95
+ bits: bits,
96
+ nonce: nonce
97
+ })
98
+ should.exist(bh.version)
99
+ should.exist(bh.prevHash)
100
+ should.exist(bh.merkleRoot)
101
+ should.exist(bh.time)
102
+ should.exist(bh.bits)
103
+ should.exist(bh.nonce)
104
+ })
105
+ })
106
+
107
+ describe('#toJSON', function () {
108
+ it('should set all the variables', function () {
109
+ var json = bh.toJSON()
110
+ should.exist(json.version)
111
+ should.exist(json.prevHash)
112
+ should.exist(json.merkleRoot)
113
+ should.exist(json.time)
114
+ should.exist(json.bits)
115
+ should.exist(json.nonce)
116
+ })
117
+ })
118
+
119
+ describe('#fromJSON', function () {
120
+ it('should parse this known json string', function () {
121
+ var jsonString = JSON.stringify({
122
+ version: version,
123
+ prevHash: prevblockidbuf,
124
+ merkleRoot: merklerootbuf,
125
+ time: time,
126
+ bits: bits,
127
+ nonce: nonce
128
+ })
129
+
130
+ var json = new BlockHeader(JSON.parse(jsonString))
131
+ should.exist(json.version)
132
+ should.exist(json.prevHash)
133
+ should.exist(json.merkleRoot)
134
+ should.exist(json.time)
135
+ should.exist(json.bits)
136
+ should.exist(json.nonce)
137
+ })
138
+ })
139
+
140
+ describe('#fromString/#toString', function () {
141
+ it('should output/input a block hex string', function () {
142
+ var b = BlockHeader.fromString(bhhex)
143
+ b.toString().should.equal(bhhex)
144
+ })
145
+ })
146
+
147
+ describe('#fromBuffer', function () {
148
+ it('should parse this known buffer', function () {
149
+ BlockHeader.fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex)
150
+ })
151
+ })
152
+
153
+ describe('#fromBufferReader', function () {
154
+ it('should parse this known buffer', function () {
155
+ BlockHeader.fromBufferReader(BufferReader(bhbuf)).toBuffer().toString('hex').should.equal(bhhex)
156
+ })
157
+ })
158
+
159
+ describe('#toBuffer', function () {
160
+ it('should output this known buffer', function () {
161
+ BlockHeader.fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex)
162
+ })
163
+ })
164
+
165
+ describe('#toBufferWriter', function () {
166
+ it('should output this known buffer', function () {
167
+ BlockHeader.fromBuffer(bhbuf).toBufferWriter().concat().toString('hex').should.equal(bhhex)
168
+ })
169
+
170
+ it('doesn\'t create a bufferWriter if one provided', function () {
171
+ var writer = new BufferWriter()
172
+ var blockHeader = BlockHeader.fromBuffer(bhbuf)
173
+ blockHeader.toBufferWriter(writer).should.equal(writer)
174
+ })
175
+ })
176
+
177
+ describe('#inspect', function () {
178
+ it('should return the correct inspect of the genesis block', function () {
179
+ var block = BlockHeader.fromRawBlock(dataRawBlockBinary)
180
+ block.inspect().should.equal('<BlockHeader ' + dataRawId + '>')
181
+ })
182
+ })
183
+
184
+ describe('#fromRawBlock', function () {
185
+ it('should instantiate from a raw block binary', function () {
186
+ var x = BlockHeader.fromRawBlock(dataRawBlockBinary)
187
+ x.version.should.equal(2)
188
+ new BN(x.bits).toString('hex').should.equal('1c3fffc0')
189
+ })
190
+
191
+ it('should instantiate from raw block buffer', function () {
192
+ var x = BlockHeader.fromRawBlock(dataRawBlockBuffer)
193
+ x.version.should.equal(2)
194
+ new BN(x.bits).toString('hex').should.equal('1c3fffc0')
195
+ })
196
+ })
197
+
198
+ describe('#validTimestamp', function () {
199
+ var x = BlockHeader.fromRawBlock(dataRawBlockBuffer)
200
+
201
+ it('should validate timpstamp as true', function () {
202
+ var valid = x.validTimestamp(x)
203
+ valid.should.equal(true)
204
+ })
205
+
206
+ it('should validate timestamp as false', function () {
207
+ x.time = Math.round(new Date().getTime() / 1000) + BlockHeader.Constants.MAX_TIME_OFFSET + 100
208
+ var valid = x.validTimestamp(x)
209
+ valid.should.equal(false)
210
+ })
211
+ })
212
+
213
+ describe('#validProofOfWork', function () {
214
+ it('should validate proof-of-work as true', function () {
215
+ var x = BlockHeader.fromRawBlock(dataRawBlockBuffer)
216
+ var valid = x.validProofOfWork(x)
217
+ valid.should.equal(true)
218
+ })
219
+
220
+ it('should validate proof of work as false because incorrect proof of work', function () {
221
+ var x = BlockHeader.fromRawBlock(dataRawBlockBuffer)
222
+ var nonce = x.nonce
223
+ x.nonce = 0
224
+ var valid = x.validProofOfWork(x)
225
+ valid.should.equal(false)
226
+ x.nonce = nonce
227
+ })
228
+ })
229
+
230
+ describe('#getDifficulty', function () {
231
+ it('should get the correct difficulty for block 86756', function () {
232
+ var x = BlockHeader.fromRawBlock(dataRawBlockBuffer)
233
+ x.bits.should.equal(0x1c3fffc0)
234
+ x.getDifficulty().should.equal(4)
235
+ })
236
+
237
+ it('should get the correct difficulty for testnet block 552065', function () {
238
+ var x = new BlockHeader({
239
+ bits: 0x1b00c2a8
240
+ })
241
+ x.getDifficulty().should.equal(86187.62562209)
242
+ })
243
+
244
+ it('should get the correct difficulty for livenet block 373043', function () {
245
+ var x = new BlockHeader({
246
+ bits: 0x18134dc1
247
+ })
248
+ x.getDifficulty().should.equal(56957648455.01001)
249
+ })
250
+
251
+ it('should get the correct difficulty for livenet block 340000', function () {
252
+ var x = new BlockHeader({
253
+ bits: 0x1819012f
254
+ })
255
+ x.getDifficulty().should.equal(43971662056.08958)
256
+ })
257
+
258
+ it('should use exponent notation if difficulty is larger than Javascript number', function () {
259
+ var x = new BlockHeader({
260
+ bits: 0x0900c2a8
261
+ })
262
+ x.getDifficulty().should.equal(1.9220482782645836 * 1e48)
263
+ })
264
+ })
265
+
266
+ it('coverage: caches the "_id" property', function () {
267
+ var blockHeader = BlockHeader.fromRawBlock(dataRawBlockBuffer)
268
+ blockHeader.id.should.equal(blockHeader.id)
269
+ })
270
+ })
@@ -0,0 +1,207 @@
1
+ 'use strict'
2
+
3
+ var should = require('chai').should()
4
+
5
+ var bsv = require('../..')
6
+ var MerkleBlock = bsv.MerkleBlock
7
+ var BufferReader = bsv.encoding.BufferReader
8
+ var BufferWriter = bsv.encoding.BufferWriter
9
+ var Transaction = bsv.Transaction
10
+ var data = require('../data/merkleblocks.js')
11
+ var transactionVector = require('../data/tx_creation')
12
+
13
+ describe('MerkleBlock', function () {
14
+ var blockhex = data.HEX[0]
15
+ var blockbuf = Buffer.from(blockhex, 'hex')
16
+ var blockJSON = JSON.stringify(data.JSON[0])
17
+ var blockObject = JSON.parse(JSON.stringify(data.JSON[0]))
18
+
19
+ describe('#constructor', function () {
20
+ it('should make a new merkleblock from buffer', function () {
21
+ var b = MerkleBlock(blockbuf)
22
+ b.toBuffer().toString('hex').should.equal(blockhex)
23
+ })
24
+
25
+ it('should make a new merkleblock from object', function () {
26
+ var b = MerkleBlock(blockObject)
27
+ b.toObject().should.deep.equal(blockObject)
28
+ })
29
+
30
+ it('should make a new merkleblock from JSON', function () {
31
+ var b = MerkleBlock(JSON.parse(blockJSON))
32
+ JSON.stringify(b).should.equal(blockJSON)
33
+ })
34
+
35
+ it('should not make an empty block', function () {
36
+ (function () {
37
+ return new MerkleBlock()
38
+ }).should.throw('Unrecognized argument for MerkleBlock')
39
+ })
40
+ })
41
+
42
+ describe('#fromObject', function () {
43
+ it('should set these known values', function () {
44
+ var block = MerkleBlock.fromObject(JSON.parse(blockJSON))
45
+ should.exist(block.header)
46
+ should.exist(block.numTransactions)
47
+ should.exist(block.hashes)
48
+ should.exist(block.flags)
49
+ })
50
+
51
+ it('should set these known values', function () {
52
+ var block = MerkleBlock(JSON.parse(blockJSON))
53
+ should.exist(block.header)
54
+ should.exist(block.numTransactions)
55
+ should.exist(block.hashes)
56
+ should.exist(block.flags)
57
+ })
58
+
59
+ it('accepts an object as argument', function () {
60
+ var block = MerkleBlock(blockbuf)
61
+ should.exist(MerkleBlock.fromObject(block.toObject()))
62
+ })
63
+ })
64
+
65
+ describe('#toJSON', function () {
66
+ it('should recover these known values', function () {
67
+ var block = new MerkleBlock(JSON.parse(blockJSON))
68
+ var b = JSON.parse(JSON.stringify(block))
69
+ should.exist(block.header)
70
+ should.exist(block.numTransactions)
71
+ should.exist(block.hashes)
72
+ should.exist(block.flags)
73
+ should.exist(b.header)
74
+ should.exist(b.numTransactions)
75
+ should.exist(b.hashes)
76
+ should.exist(b.flags)
77
+ })
78
+ })
79
+
80
+ describe('#fromBuffer', function () {
81
+ it('should make a block from this known buffer', function () {
82
+ var block = MerkleBlock.fromBuffer(blockbuf)
83
+ block.toBuffer().toString('hex').should.equal(blockhex)
84
+ })
85
+ })
86
+
87
+ describe('#fromBufferReader', function () {
88
+ it('should make a block from this known buffer', function () {
89
+ var block = MerkleBlock.fromBufferReader(BufferReader(blockbuf))
90
+ block.toBuffer().toString('hex').should.equal(blockhex)
91
+ })
92
+ })
93
+
94
+ describe('#toBuffer', function () {
95
+ it('should recover a block from this known buffer', function () {
96
+ var block = MerkleBlock.fromBuffer(blockbuf)
97
+ block.toBuffer().toString('hex').should.equal(blockhex)
98
+ })
99
+ })
100
+
101
+ describe('#toBufferWriter', function () {
102
+ it('should recover a block from this known buffer', function () {
103
+ var block = MerkleBlock.fromBuffer(blockbuf)
104
+ block.toBufferWriter().concat().toString('hex').should.equal(blockhex)
105
+ })
106
+
107
+ it('doesn\'t create a bufferWriter if one provided', function () {
108
+ var writer = new BufferWriter()
109
+ var block = MerkleBlock.fromBuffer(blockbuf)
110
+ block.toBufferWriter(writer).should.equal(writer)
111
+ })
112
+ })
113
+
114
+ describe('#validMerkleTree', function () {
115
+ it('should validate good merkleblocks', function () {
116
+ data.JSON.forEach(function (data) {
117
+ var b = MerkleBlock(data)
118
+ b.validMerkleTree().should.equal(true)
119
+ })
120
+ })
121
+
122
+ it('should not validate merkleblocks with too many hashes', function () {
123
+ var b = MerkleBlock(data.JSON[0])
124
+ // Add too many hashes
125
+ var i = 0
126
+ while (i <= b.numTransactions) {
127
+ b.hashes.push('bad' + i++)
128
+ }
129
+ b.validMerkleTree().should.equal(false)
130
+ })
131
+
132
+ it('should not validate merkleblocks with too few bit flags', function () {
133
+ var b = MerkleBlock(JSON.parse(blockJSON))
134
+ b.flags.pop()
135
+ b.validMerkleTree().should.equal(false)
136
+ })
137
+ })
138
+
139
+ describe('#filteredTxsHash', function () {
140
+ it('should validate good merkleblocks', function () {
141
+ var hashOfFilteredTx = '6f64fd5aa9dd01f74c03656d376625cf80328d83d9afebe60cc68b8f0e245bd9'
142
+ var b = MerkleBlock(data.JSON[3])
143
+ b.filteredTxsHash()[0].should.equal(hashOfFilteredTx)
144
+ })
145
+
146
+ it('should fail with merkleblocks with too many hashes', function () {
147
+ var b = MerkleBlock(data.JSON[0])
148
+ // Add too many hashes
149
+ var i = 0
150
+ while (i <= b.numTransactions) {
151
+ b.hashes.push('bad' + i++)
152
+ }
153
+ (function () {
154
+ b.filteredTxsHash()
155
+ }).should.throw('This MerkleBlock contain an invalid Merkle Tree')
156
+ })
157
+
158
+ it('should fail with merkleblocks with too few bit flags', function () {
159
+ var b = MerkleBlock(JSON.parse(blockJSON))
160
+ b.flags.pop();
161
+ (function () {
162
+ b.filteredTxsHash()
163
+ }).should.throw('This MerkleBlock contain an invalid Merkle Tree')
164
+ })
165
+ })
166
+
167
+ describe('#hasTransaction', function () {
168
+ it('should find transactions via hash string', function () {
169
+ var jsonData = data.JSON[0]
170
+ var txId = Buffer.from(jsonData.hashes[1], 'hex').toString('hex')
171
+ var b = MerkleBlock(jsonData)
172
+ b.hasTransaction(txId).should.equal(true)
173
+ b.hasTransaction(txId + 'abcd').should.equal(false)
174
+ })
175
+
176
+ it('should find transactions via Transaction object', function () {
177
+ var jsonData = data.JSON[0]
178
+ var txBuf = Buffer.from(data.TXHEX[0][0], 'hex')
179
+ var tx = new Transaction().fromBuffer(txBuf)
180
+ var b = MerkleBlock(jsonData)
181
+ b.hasTransaction(tx).should.equal(true)
182
+ })
183
+
184
+ it('should not find non-existant Transaction object', function () {
185
+ // Reuse another transaction already in data/ dir
186
+ var serialized = transactionVector[0][7]
187
+ var tx = new Transaction().fromBuffer(Buffer.from(serialized, 'hex'))
188
+ var b = MerkleBlock(data.JSON[0])
189
+ b.hasTransaction(tx).should.equal(false)
190
+ })
191
+
192
+ it('should not match with merkle nodes', function () {
193
+ var b = MerkleBlock(data.JSON[0])
194
+
195
+ var hashData = [
196
+ ['3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2', false],
197
+ ['019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b65', true],
198
+ ['41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068', false],
199
+ ['20d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf', false]
200
+ ]
201
+
202
+ hashData.forEach(function check (d) {
203
+ b.hasTransaction(d[0]).should.equal(d[1])
204
+ })
205
+ })
206
+ })
207
+ })