@psf/bch-js 4.21.0 → 5.2.0
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.
- package/package.json +3 -3
- package/src/bch-js.js +3 -4
- package/src/psf-slp-indexer.js +370 -0
- package/src/slp/utils.js +1 -1
- package/src/transaction.js +11 -2
- package/src/utxo.js +150 -6
- package/test/integration/chains/bchn/psf-slp-indexer.integration.js +121 -0
- package/test/integration/chains/bchn/slp.js +229 -225
- package/test/integration/chains/bchn/utxo-integration.js +35 -1
- package/test/integration/slp.js +907 -901
- package/test/integration/transaction-integration.js +58 -55
- package/test/unit/fixtures/psf-slp-indexer-mock.js +153 -0
- package/test/unit/fixtures/utxo-mocks.js +91 -1
- package/test/unit/psf-slp-indexer.js +339 -0
- package/test/unit/transaction-unit.js +19 -8
- package/test/unit/utxo-unit.js +51 -7
- package/src/ninsight.js +0 -319
- package/test/unit/fixtures/ninsight-mock.js +0 -170
- package/test/unit/ninsight.js +0 -255
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Integration tests for the psf-slp-indexer.js library
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const assert = require('chai').assert
|
|
6
|
+
|
|
7
|
+
const BCHJS = require('../../../../src/bch-js')
|
|
8
|
+
let bchjs
|
|
9
|
+
|
|
10
|
+
describe('#psf-slp-indexer', () => {
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
// Introduce a delay so that the BVT doesn't trip the rate limits.
|
|
13
|
+
if (process.env.IS_USING_FREE_TIER) await sleep(3000)
|
|
14
|
+
|
|
15
|
+
bchjs = new BCHJS()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('#status', () => {
|
|
19
|
+
it('should return the status of the indexer.', async () => {
|
|
20
|
+
const result = await bchjs.PsfSlpIndexer.status()
|
|
21
|
+
// console.log('result: ', result)
|
|
22
|
+
|
|
23
|
+
assert.property(result.status, 'startBlockHeight')
|
|
24
|
+
assert.property(result.status, 'syncedBlockHeight')
|
|
25
|
+
assert.property(result.status, 'chainBlockHeight')
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('#balance', () => {
|
|
30
|
+
it('should get balance data for an address.', async () => {
|
|
31
|
+
const addr = 'bitcoincash:qzmd5vxgh9m22m6fgvm57yd6kjnjl9qnwywsf3583n'
|
|
32
|
+
|
|
33
|
+
const result = await bchjs.PsfSlpIndexer.balance(addr)
|
|
34
|
+
// console.log('result: ', result)
|
|
35
|
+
|
|
36
|
+
assert.property(result.balance, 'utxos')
|
|
37
|
+
assert.property(result.balance, 'txs')
|
|
38
|
+
assert.property(result.balance, 'balances')
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('#tokenStats', () => {
|
|
43
|
+
it('should get stats on a token', async () => {
|
|
44
|
+
const tokenId =
|
|
45
|
+
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0'
|
|
46
|
+
|
|
47
|
+
const result = await bchjs.PsfSlpIndexer.tokenStats(tokenId)
|
|
48
|
+
// console.log('result: ', result)
|
|
49
|
+
|
|
50
|
+
assert.property(result.tokenData, 'documentUri')
|
|
51
|
+
assert.property(result.tokenData, 'txs')
|
|
52
|
+
assert.property(result.tokenData, 'totalBurned')
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('#tx', () => {
|
|
57
|
+
it('should get hydrated tx data for an SLP transaction', async () => {
|
|
58
|
+
const txid =
|
|
59
|
+
'947ccb2a0d62ca287bc4b0993874ab0f9f6afd454193e631e2bf84dca66731fc'
|
|
60
|
+
|
|
61
|
+
const result = await bchjs.PsfSlpIndexer.tx(txid)
|
|
62
|
+
// console.log('result: ', result)
|
|
63
|
+
|
|
64
|
+
assert.property(result.txData, 'vin')
|
|
65
|
+
assert.property(result.txData, 'vout')
|
|
66
|
+
assert.property(result.txData, 'isValidSlp')
|
|
67
|
+
assert.equal(result.txData.isValidSlp, true)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should mark non-SLP transaction as false', async () => {
|
|
71
|
+
const txid =
|
|
72
|
+
'03d6e6b63647ce7b02ecc73dc6d41b485be14a3e20eed4474b8a840358ddf14e'
|
|
73
|
+
|
|
74
|
+
const result = await bchjs.PsfSlpIndexer.tx(txid)
|
|
75
|
+
// console.log('result: ', result)
|
|
76
|
+
|
|
77
|
+
assert.property(result.txData, 'vin')
|
|
78
|
+
assert.property(result.txData, 'vout')
|
|
79
|
+
assert.property(result.txData, 'isValidSlp')
|
|
80
|
+
assert.equal(result.txData.isValidSlp, false)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// FlexUSD transactions
|
|
84
|
+
// Currently FlexUSD UTXOs are reported as invalid SLP UTXOs, which means
|
|
85
|
+
// the wallet will burn them. There is a TODO in the code. This test will
|
|
86
|
+
// need to be changed when it is done.
|
|
87
|
+
it('should mark blacklisted token as null', async () => {
|
|
88
|
+
const txid =
|
|
89
|
+
'302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85f'
|
|
90
|
+
|
|
91
|
+
const result = await bchjs.PsfSlpIndexer.tx(txid)
|
|
92
|
+
// console.log('result: ', result)
|
|
93
|
+
|
|
94
|
+
assert.property(result.txData, 'vin')
|
|
95
|
+
assert.property(result.txData, 'vout')
|
|
96
|
+
assert.property(result.txData, 'isValidSlp')
|
|
97
|
+
assert.equal(result.txData.isValidSlp, null)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should throw error for non-existent txid', async () => {
|
|
101
|
+
try {
|
|
102
|
+
const txid =
|
|
103
|
+
'302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85e'
|
|
104
|
+
|
|
105
|
+
await bchjs.PsfSlpIndexer.tx(txid)
|
|
106
|
+
// console.log('result: ', result)
|
|
107
|
+
|
|
108
|
+
assert.fail('Unexpected code path')
|
|
109
|
+
} catch (err) {
|
|
110
|
+
// console.log(err)
|
|
111
|
+
|
|
112
|
+
assert.include(err.message, 'No such mempool or blockchain transaction')
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Promise-based sleep function
|
|
119
|
+
function sleep (ms) {
|
|
120
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
121
|
+
}
|
|
@@ -30,265 +30,269 @@ describe('#SLP', () => {
|
|
|
30
30
|
bchjs = new BCHJS()
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
describe('#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
33
|
+
if (process.env.TESTSLP) {
|
|
34
|
+
describe('#util', () => {
|
|
35
|
+
describe('#decodeOpReturn', () => {
|
|
36
|
+
it('should decode a NFT Child transaction', async () => {
|
|
37
|
+
const txid =
|
|
38
|
+
'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b'
|
|
39
|
+
|
|
40
|
+
const data = await bchjs.SLP.Utils.decodeOpReturn(txid)
|
|
41
|
+
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
|
42
|
+
|
|
43
|
+
assert.property(data, 'tokenType')
|
|
44
|
+
assert.property(data, 'txType')
|
|
45
|
+
assert.property(data, 'ticker')
|
|
46
|
+
assert.property(data, 'name')
|
|
47
|
+
assert.property(data, 'tokenId')
|
|
48
|
+
assert.property(data, 'documentUri')
|
|
49
|
+
assert.property(data, 'documentHash')
|
|
50
|
+
assert.property(data, 'decimals')
|
|
51
|
+
assert.property(data, 'mintBatonVout')
|
|
52
|
+
assert.property(data, 'qty')
|
|
53
|
+
|
|
54
|
+
assert.equal(data.tokenType, 65)
|
|
55
|
+
assert.equal(data.mintBatonVout, 0)
|
|
56
|
+
assert.equal(data.qty, '1')
|
|
57
|
+
})
|
|
56
58
|
})
|
|
57
|
-
})
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
describe('#tokenUtxoDetails', () => {
|
|
61
|
+
it('should handle a range of UTXO types', async () => {
|
|
62
|
+
const utxos = [
|
|
63
|
+
// Malformed SLP tx
|
|
64
|
+
{
|
|
65
|
+
note: 'Malformed SLP tx',
|
|
66
|
+
tx_hash:
|
|
67
|
+
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
68
|
+
tx_pos: 1,
|
|
69
|
+
value: 546
|
|
70
|
+
},
|
|
71
|
+
// Normal TX (non-SLP)
|
|
72
|
+
{
|
|
73
|
+
note: 'Normal TX (non-SLP)',
|
|
74
|
+
tx_hash:
|
|
75
|
+
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
76
|
+
tx_pos: 0,
|
|
77
|
+
value: 400000
|
|
78
|
+
},
|
|
79
|
+
// Valid PSF SLP tx
|
|
80
|
+
{
|
|
81
|
+
note: 'Valid PSF SLP tx',
|
|
82
|
+
tx_hash:
|
|
83
|
+
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
84
|
+
tx_pos: 1,
|
|
85
|
+
value: 546
|
|
86
|
+
},
|
|
87
|
+
// Valid SLP token not in whitelist
|
|
88
|
+
{
|
|
89
|
+
note: 'Valid SLP token not in whitelist',
|
|
90
|
+
tx_hash:
|
|
91
|
+
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
92
|
+
tx_pos: 1,
|
|
93
|
+
value: 546
|
|
94
|
+
},
|
|
95
|
+
// Token send on BCHN network.
|
|
96
|
+
{
|
|
97
|
+
note: 'Token send on BCHN network',
|
|
98
|
+
tx_hash:
|
|
99
|
+
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019',
|
|
100
|
+
tx_pos: 1,
|
|
101
|
+
value: 546
|
|
102
|
+
},
|
|
103
|
+
// Token send on ABC network.
|
|
104
|
+
{
|
|
105
|
+
note: 'Token send on ABC network',
|
|
106
|
+
tx_hash:
|
|
107
|
+
'336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d',
|
|
108
|
+
tx_pos: 1,
|
|
109
|
+
value: 546
|
|
110
|
+
},
|
|
111
|
+
// Known invalid SLP token send of PSF tokens.
|
|
112
|
+
{
|
|
113
|
+
note: 'Known invalid SLP token send of PSF tokens',
|
|
114
|
+
tx_hash:
|
|
115
|
+
'2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74',
|
|
116
|
+
tx_pos: 1,
|
|
117
|
+
value: 546
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
|
|
122
|
+
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
|
123
|
+
|
|
62
124
|
// Malformed SLP tx
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
67
|
-
tx_pos: 1,
|
|
68
|
-
value: 546
|
|
69
|
-
},
|
|
125
|
+
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
|
|
126
|
+
assert.equal(data[0].isValid, false)
|
|
127
|
+
|
|
70
128
|
// Normal TX (non-SLP)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
tx_hash:
|
|
74
|
-
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
75
|
-
tx_pos: 0,
|
|
76
|
-
value: 400000
|
|
77
|
-
},
|
|
78
|
-
// Valid PSF SLP tx
|
|
79
|
-
{
|
|
80
|
-
note: 'Valid PSF SLP tx',
|
|
81
|
-
tx_hash:
|
|
82
|
-
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
83
|
-
tx_pos: 1,
|
|
84
|
-
value: 546
|
|
85
|
-
},
|
|
86
|
-
// Valid SLP token not in whitelist
|
|
87
|
-
{
|
|
88
|
-
note: 'Valid SLP token not in whitelist',
|
|
89
|
-
tx_hash:
|
|
90
|
-
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
91
|
-
tx_pos: 1,
|
|
92
|
-
value: 546
|
|
93
|
-
},
|
|
94
|
-
// Token send on BCHN network.
|
|
95
|
-
{
|
|
96
|
-
note: 'Token send on BCHN network',
|
|
97
|
-
tx_hash:
|
|
98
|
-
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019',
|
|
99
|
-
tx_pos: 1,
|
|
100
|
-
value: 546
|
|
101
|
-
},
|
|
102
|
-
// Token send on ABC network.
|
|
103
|
-
{
|
|
104
|
-
note: 'Token send on ABC network',
|
|
105
|
-
tx_hash:
|
|
106
|
-
'336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d',
|
|
107
|
-
tx_pos: 1,
|
|
108
|
-
value: 546
|
|
109
|
-
},
|
|
110
|
-
// Known invalid SLP token send of PSF tokens.
|
|
111
|
-
{
|
|
112
|
-
note: 'Known invalid SLP token send of PSF tokens',
|
|
113
|
-
tx_hash:
|
|
114
|
-
'2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74',
|
|
115
|
-
tx_pos: 1,
|
|
116
|
-
value: 546
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
|
|
121
|
-
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
|
122
|
-
|
|
123
|
-
// Malformed SLP tx
|
|
124
|
-
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
|
|
125
|
-
assert.equal(data[0].isValid, false)
|
|
126
|
-
|
|
127
|
-
// Normal TX (non-SLP)
|
|
128
|
-
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
|
|
129
|
-
assert.equal(data[1].isValid, false)
|
|
130
|
-
|
|
131
|
-
// Valid PSF SLP tx
|
|
132
|
-
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
|
|
133
|
-
assert.equal(data[2].isValid, true)
|
|
134
|
-
|
|
135
|
-
// Valid SLP token not in whitelist
|
|
136
|
-
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
|
|
137
|
-
assert.equal(data[3].isValid, true)
|
|
138
|
-
|
|
139
|
-
// Token send on BCHN network
|
|
140
|
-
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
|
|
141
|
-
assert.equal(data[4].isValid, true)
|
|
142
|
-
|
|
143
|
-
// Token send on ABC network
|
|
144
|
-
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
|
|
145
|
-
assert.equal(data[5].isValid, null)
|
|
146
|
-
|
|
147
|
-
// Known invalid SLP token send of PSF tokens
|
|
148
|
-
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
|
|
149
|
-
assert.equal(data[6].isValid, false)
|
|
150
|
-
})
|
|
151
|
-
})
|
|
129
|
+
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
|
|
130
|
+
assert.equal(data[1].isValid, false)
|
|
152
131
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a'
|
|
132
|
+
// Valid PSF SLP tx
|
|
133
|
+
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
|
|
134
|
+
assert.equal(data[2].isValid, true)
|
|
157
135
|
|
|
158
|
-
|
|
159
|
-
|
|
136
|
+
// Valid SLP token not in whitelist
|
|
137
|
+
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
|
|
138
|
+
assert.equal(data[3].isValid, true)
|
|
160
139
|
|
|
161
|
-
|
|
140
|
+
// Token send on BCHN network
|
|
141
|
+
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
|
|
142
|
+
assert.equal(data[4].isValid, true)
|
|
162
143
|
|
|
163
|
-
|
|
164
|
-
|
|
144
|
+
// Token send on ABC network
|
|
145
|
+
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
|
|
146
|
+
assert.equal(data[5].isValid, null)
|
|
165
147
|
|
|
166
|
-
|
|
167
|
-
|
|
148
|
+
// Known invalid SLP token send of PSF tokens
|
|
149
|
+
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
|
|
150
|
+
assert.equal(data[6].isValid, false)
|
|
151
|
+
})
|
|
168
152
|
})
|
|
169
153
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
154
|
+
describe('#validateTxid3', () => {
|
|
155
|
+
it('should invalidate a known invalid TXID', async () => {
|
|
156
|
+
const txid =
|
|
157
|
+
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a'
|
|
173
158
|
|
|
174
|
-
|
|
175
|
-
|
|
159
|
+
const result = await bchjs.SLP.Utils.validateTxid3(txid)
|
|
160
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
176
161
|
|
|
177
|
-
|
|
162
|
+
assert.isArray(result)
|
|
178
163
|
|
|
179
|
-
|
|
180
|
-
|
|
164
|
+
assert.property(result[0], 'txid')
|
|
165
|
+
assert.equal(result[0].txid, txid)
|
|
181
166
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
167
|
+
assert.property(result[0], 'valid')
|
|
168
|
+
assert.equal(result[0].valid, null)
|
|
169
|
+
})
|
|
185
170
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
190
|
-
// Normal TX (non-SLP)
|
|
191
|
-
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
192
|
-
// Valid PSF SLP tx
|
|
193
|
-
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
194
|
-
// Valid SLP token not in whitelist
|
|
195
|
-
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
196
|
-
// Unprocessed SLP TX
|
|
197
|
-
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019'
|
|
198
|
-
]
|
|
171
|
+
it('should validate a known valid TXID', async () => {
|
|
172
|
+
const txid =
|
|
173
|
+
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd'
|
|
199
174
|
|
|
200
|
-
|
|
201
|
-
|
|
175
|
+
const result = await bchjs.SLP.Utils.validateTxid3(txid)
|
|
176
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
202
177
|
|
|
203
|
-
|
|
178
|
+
assert.isArray(result)
|
|
204
179
|
|
|
205
|
-
|
|
206
|
-
|
|
180
|
+
assert.property(result[0], 'txid')
|
|
181
|
+
assert.equal(result[0].txid, txid)
|
|
207
182
|
|
|
208
|
-
|
|
209
|
-
|
|
183
|
+
assert.property(result[0], 'valid')
|
|
184
|
+
assert.equal(result[0].valid, true)
|
|
185
|
+
})
|
|
210
186
|
|
|
211
|
-
|
|
212
|
-
|
|
187
|
+
it('should handle a mix of valid, invalid, and non-SLP txs', async () => {
|
|
188
|
+
const txids = [
|
|
189
|
+
// Malformed SLP tx
|
|
190
|
+
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
191
|
+
// Normal TX (non-SLP)
|
|
192
|
+
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
193
|
+
// Valid PSF SLP tx
|
|
194
|
+
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
195
|
+
// Valid SLP token not in whitelist
|
|
196
|
+
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
197
|
+
// Unprocessed SLP TX
|
|
198
|
+
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019'
|
|
199
|
+
]
|
|
213
200
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
assert.equal(result[3].valid, null)
|
|
201
|
+
const result = await bchjs.SLP.Utils.validateTxid3(txids)
|
|
202
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
217
203
|
|
|
218
|
-
|
|
219
|
-
assert.equal(result[4].txid, txids[4])
|
|
220
|
-
assert.equal(result[4].valid, null)
|
|
221
|
-
})
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
describe('#validateTxid', () => {
|
|
225
|
-
it('should handle a mix of valid, invalid, and non-SLP txs', async () => {
|
|
226
|
-
const txids = [
|
|
227
|
-
// Malformed SLP tx
|
|
228
|
-
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
229
|
-
// Normal TX (non-SLP)
|
|
230
|
-
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
231
|
-
// Valid PSF SLP tx
|
|
232
|
-
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
233
|
-
// Valid SLP token not in whitelist
|
|
234
|
-
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
235
|
-
// Token send on BCHN network.
|
|
236
|
-
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019',
|
|
237
|
-
// Token send on ABC network.
|
|
238
|
-
'336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d'
|
|
239
|
-
]
|
|
204
|
+
assert.isArray(result)
|
|
240
205
|
|
|
241
|
-
|
|
242
|
-
|
|
206
|
+
assert.equal(result[0].txid, txids[0])
|
|
207
|
+
assert.equal(result[0].valid, null)
|
|
243
208
|
|
|
244
|
-
|
|
209
|
+
assert.equal(result[1].txid, txids[1])
|
|
210
|
+
assert.equal(result[1].valid, null)
|
|
245
211
|
|
|
246
|
-
|
|
247
|
-
|
|
212
|
+
assert.equal(result[2].txid, txids[2])
|
|
213
|
+
assert.equal(result[2].valid, true)
|
|
248
214
|
|
|
249
|
-
|
|
250
|
-
|
|
215
|
+
// True in validateTxid() but null in validateTxid3()
|
|
216
|
+
assert.equal(result[3].txid, txids[3])
|
|
217
|
+
assert.equal(result[3].valid, null)
|
|
251
218
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
assert.equal(result[3].valid, true)
|
|
258
|
-
|
|
259
|
-
assert.equal(result[4].txid, txids[4])
|
|
260
|
-
assert.equal(result[4].valid, true)
|
|
219
|
+
// Note: This should change from null to true once SLPDB finishes indexing.
|
|
220
|
+
assert.equal(result[4].txid, txids[4])
|
|
221
|
+
assert.equal(result[4].valid, null)
|
|
222
|
+
})
|
|
223
|
+
})
|
|
261
224
|
|
|
262
|
-
|
|
263
|
-
|
|
225
|
+
describe('#validateTxid', () => {
|
|
226
|
+
it('should handle a mix of valid, invalid, and non-SLP txs', async () => {
|
|
227
|
+
const txids = [
|
|
228
|
+
// Malformed SLP tx
|
|
229
|
+
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
|
|
230
|
+
// Normal TX (non-SLP)
|
|
231
|
+
'01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0',
|
|
232
|
+
// Valid PSF SLP tx
|
|
233
|
+
'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd',
|
|
234
|
+
// Valid SLP token not in whitelist
|
|
235
|
+
'3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488',
|
|
236
|
+
// Token send on BCHN network.
|
|
237
|
+
'402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019',
|
|
238
|
+
// Token send on ABC network.
|
|
239
|
+
'336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d'
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
const result = await bchjs.SLP.Utils.validateTxid(txids)
|
|
243
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
244
|
+
|
|
245
|
+
assert.isArray(result)
|
|
246
|
+
|
|
247
|
+
assert.equal(result[0].txid, txids[0])
|
|
248
|
+
assert.equal(result[0].valid, null)
|
|
249
|
+
|
|
250
|
+
assert.equal(result[1].txid, txids[1])
|
|
251
|
+
assert.equal(result[1].valid, null)
|
|
252
|
+
|
|
253
|
+
assert.equal(result[2].txid, txids[2])
|
|
254
|
+
assert.equal(result[2].valid, true)
|
|
255
|
+
|
|
256
|
+
// True in validateTxid() but null in validateTxid3()
|
|
257
|
+
assert.equal(result[3].txid, txids[3])
|
|
258
|
+
assert.equal(result[3].valid, true)
|
|
259
|
+
|
|
260
|
+
assert.equal(result[4].txid, txids[4])
|
|
261
|
+
assert.equal(result[4].valid, true)
|
|
262
|
+
|
|
263
|
+
assert.equal(result[5].txid, txids[5])
|
|
264
|
+
assert.equal(result[5].valid, null)
|
|
265
|
+
})
|
|
264
266
|
})
|
|
265
267
|
})
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
describe('#nft1', () => {
|
|
269
|
+
describe('#listNFTGroupChildren', () => {
|
|
270
|
+
it('should return array of children GENESIS transactions IDs', async () => {
|
|
271
|
+
const groupId =
|
|
272
|
+
'68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a'
|
|
273
|
+
const result = await bchjs.SLP.NFT1.listNFTGroupChildren(groupId)
|
|
274
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
275
|
+
assert.property(result, 'nftChildren')
|
|
276
|
+
assert.isArray(result.nftChildren)
|
|
277
|
+
})
|
|
275
278
|
})
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
279
|
+
describe('#parentNFTGroup', () => {
|
|
280
|
+
it('should return parent NFT group information', async () => {
|
|
281
|
+
const tokenId =
|
|
282
|
+
'45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9'
|
|
283
|
+
const result = await bchjs.SLP.NFT1.parentNFTGroup(tokenId)
|
|
284
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
285
|
+
assert.property(result, 'nftGroup')
|
|
286
|
+
assert.property(result.nftGroup, 'id')
|
|
287
|
+
assert.property(result.nftGroup, 'name')
|
|
288
|
+
assert.property(result.nftGroup, 'symbol')
|
|
289
|
+
assert.property(result.nftGroup, 'documentUri')
|
|
290
|
+
assert.property(result.nftGroup, 'versionType')
|
|
291
|
+
assert.property(result.nftGroup, 'initialTokenQty')
|
|
292
|
+
})
|
|
289
293
|
})
|
|
290
294
|
})
|
|
291
|
-
}
|
|
295
|
+
}
|
|
292
296
|
})
|
|
293
297
|
|
|
294
298
|
// Promise-based sleep function
|
|
@@ -13,7 +13,7 @@ describe('#UTXO', () => {
|
|
|
13
13
|
|
|
14
14
|
if (process.env.IS_USING_FREE_TIER) await sleep(3000)
|
|
15
15
|
})
|
|
16
|
-
|
|
16
|
+
/*
|
|
17
17
|
describe('#get', () => {
|
|
18
18
|
it('should get hydrated and filtered UTXOs for an address', async () => {
|
|
19
19
|
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
|
@@ -90,7 +90,40 @@ describe('#UTXO', () => {
|
|
|
90
90
|
assert.isAbove(result[0].nullUtxos.length, 1)
|
|
91
91
|
})
|
|
92
92
|
})
|
|
93
|
+
*/
|
|
94
|
+
describe('#get', () => {
|
|
95
|
+
it('should hydrate address with BCH and SLP UTXOs', async () => {
|
|
96
|
+
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
|
97
|
+
|
|
98
|
+
const result = await bchjs.Utxo.get(addr)
|
|
99
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
100
|
+
|
|
101
|
+
// Assert expected properties exist.
|
|
102
|
+
assert.property(result, 'address')
|
|
103
|
+
assert.property(result, 'bchUtxos')
|
|
104
|
+
assert.property(result, 'slpUtxos')
|
|
105
|
+
assert.property(result.slpUtxos, 'type1')
|
|
106
|
+
assert.property(result.slpUtxos, 'nft')
|
|
107
|
+
assert.property(result, 'nullUtxos')
|
|
108
|
+
|
|
109
|
+
assert.isAbove(result.bchUtxos.length, 0)
|
|
110
|
+
assert.isAbove(result.slpUtxos.type1.tokens.length, 0)
|
|
111
|
+
assert.equal(result.slpUtxos.type1.mintBatons.length, 0)
|
|
112
|
+
})
|
|
93
113
|
|
|
114
|
+
// TODO: NFTs are currently not identified as different than normal BCH UTXOs.
|
|
115
|
+
// The psf-slp-indexer needs to be updated to fix this issue.
|
|
116
|
+
it('should handle NFTs and minting batons', async () => {
|
|
117
|
+
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
|
118
|
+
|
|
119
|
+
const result = await bchjs.Utxo.get(addr)
|
|
120
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
121
|
+
|
|
122
|
+
// Assert that minting batons are correctly identified.
|
|
123
|
+
assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
/*
|
|
94
127
|
describe('#findBiggestUtxo', () => {
|
|
95
128
|
it('should sort UTXOs from Electrumx', async () => {
|
|
96
129
|
const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
|
|
@@ -118,6 +151,7 @@ describe('#UTXO', () => {
|
|
|
118
151
|
assert.equal(result.satoshis, 800)
|
|
119
152
|
})
|
|
120
153
|
})
|
|
154
|
+
*/
|
|
121
155
|
})
|
|
122
156
|
|
|
123
157
|
function sleep (ms) {
|