@psf/bch-js 4.22.1 → 5.1.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 +2 -2
- package/src/psf-slp-indexer.js +42 -2
- package/src/transaction.js +11 -2
- package/test/integration/chains/bchn/psf-slp-indexer.integration.js +32 -1
- package/test/integration/transaction-integration.js +6 -5
- package/test/unit/psf-slp-indexer.js +18 -12
- package/test/unit/transaction-unit.js +19 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psf/bch-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "The FullStack.cash JavaScript library for Bitcoin Cash and SLP Tokens",
|
|
5
5
|
"author": "Chris Troutner <chris.troutner@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"test:integration:local:abc": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
|
|
19
19
|
"test:integration:local:bchn": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
|
20
20
|
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v5/ mocha --timeout 30000 test/integration/chains/testnet",
|
|
21
|
-
"test:integration:decatur:bchn": "export RESTURL=http://192.168.2.
|
|
21
|
+
"test:integration:decatur:bchn": "export RESTURL=http://192.168.2.139:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
|
22
22
|
"test:integration:decatur:abc": "export RESTURL=http://192.168.2.141:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
|
|
23
23
|
"test:integration:temp:bchn": "export RESTURL=http://157.90.174.219:3000/v5/ && mocha --timeout 30000 test/integration/",
|
|
24
24
|
"test:temp": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 -g '#Encryption' test/integration/",
|
package/src/psf-slp-indexer.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/*
|
|
2
2
|
This library interacts with the PSF slp indexer REST API endpoints operated
|
|
3
3
|
by FullStack.cash
|
|
4
|
+
|
|
5
|
+
TODO:
|
|
6
|
+
- detect TXs from tokens in the blacklist.
|
|
4
7
|
*/
|
|
8
|
+
|
|
5
9
|
// Public npm libraries
|
|
6
10
|
const axios = require('axios')
|
|
7
11
|
|
|
12
|
+
// Local libraries
|
|
13
|
+
const RawTransaction = require('./raw-transactions')
|
|
14
|
+
|
|
8
15
|
// let _this
|
|
9
16
|
|
|
10
17
|
class PsfSlpIndexer {
|
|
@@ -29,6 +36,9 @@ class PsfSlpIndexer {
|
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
|
|
39
|
+
// Encapsulate dependencies
|
|
40
|
+
this.rawTransaction = new RawTransaction(config)
|
|
41
|
+
|
|
32
42
|
// _this = this
|
|
33
43
|
}
|
|
34
44
|
|
|
@@ -283,8 +293,38 @@ class PsfSlpIndexer {
|
|
|
283
293
|
}
|
|
284
294
|
throw new Error('Input txid must be a string.')
|
|
285
295
|
} catch (error) {
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
// console.log('error: ', error)
|
|
297
|
+
|
|
298
|
+
// Case: txid is not stored in the psf-slp-indexer tx database.
|
|
299
|
+
// Response: If it's not in the database, then it can be assumed the TX
|
|
300
|
+
// is not a token TX?
|
|
301
|
+
if (
|
|
302
|
+
error.response &&
|
|
303
|
+
error.response.data &&
|
|
304
|
+
error.response.data.error &&
|
|
305
|
+
error.response.data.error.includes('Key not found in database')
|
|
306
|
+
) {
|
|
307
|
+
// console.log(
|
|
308
|
+
// 'TX not found in psf-slp-indexer. Retrieving from full node.'
|
|
309
|
+
// )
|
|
310
|
+
|
|
311
|
+
// Get the TX Details from the full node.
|
|
312
|
+
const txDetails = await this.rawTransaction.getTxData(txid)
|
|
313
|
+
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
|
314
|
+
|
|
315
|
+
// TODO: Run the TX through decodeOpReturn() to see if it has a tokenID
|
|
316
|
+
// that is in the blacklist. If it is, then set isValidSlp = null to
|
|
317
|
+
// signal that it's state can not be determined.
|
|
318
|
+
|
|
319
|
+
// Assumption: transaction is not a valid SLP UTXO.
|
|
320
|
+
txDetails.isValidSlp = false
|
|
321
|
+
|
|
322
|
+
const outObj = {
|
|
323
|
+
txData: txDetails
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return outObj
|
|
327
|
+
} else throw error
|
|
288
328
|
}
|
|
289
329
|
}
|
|
290
330
|
}
|
package/src/transaction.js
CHANGED
|
@@ -2,18 +2,27 @@
|
|
|
2
2
|
High-level functions for working with Transactions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
// Global npm libraries
|
|
5
6
|
const BigNumber = require('bignumber.js')
|
|
6
7
|
|
|
8
|
+
// Local libraries
|
|
7
9
|
const RawTransaction = require('./raw-transactions')
|
|
8
10
|
const SlpUtils = require('./slp/utils')
|
|
9
11
|
const Blockchain = require('./blockchain')
|
|
12
|
+
const PsfSlpIndexer = require('./psf-slp-indexer')
|
|
10
13
|
|
|
11
14
|
class Transaction {
|
|
12
|
-
constructor (config) {
|
|
15
|
+
constructor (config = {}) {
|
|
13
16
|
// Encapsulate dependencies
|
|
14
17
|
this.slpUtils = new SlpUtils(config)
|
|
15
18
|
this.rawTransaction = new RawTransaction(config)
|
|
16
19
|
this.blockchain = new Blockchain(config)
|
|
20
|
+
this.psfSlpIndexer = new PsfSlpIndexer(config)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Proxy the call to the psf-slp-indexer.
|
|
24
|
+
async get (txid) {
|
|
25
|
+
return await this.psfSlpIndexer.tx(txid)
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
/**
|
|
@@ -42,7 +51,7 @@ class Transaction {
|
|
|
42
51
|
// CT 10/31/21: TODO: this function should be refactored to use get2(), but
|
|
43
52
|
// add waterfall validation of the TX and its inputs.
|
|
44
53
|
|
|
45
|
-
async
|
|
54
|
+
async getOld (txid) {
|
|
46
55
|
try {
|
|
47
56
|
if (typeof txid !== 'string') {
|
|
48
57
|
throw new Error(
|
|
@@ -54,7 +54,7 @@ describe('#psf-slp-indexer', () => {
|
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
describe('#tx', () => {
|
|
57
|
-
it('should get hydrated tx data', async () => {
|
|
57
|
+
it('should get hydrated tx data for an SLP transaction', async () => {
|
|
58
58
|
const txid =
|
|
59
59
|
'83361c34cac2ea7f9ca287fca57a96cc0763719f0cdf4850f9696c1e68eb635c'
|
|
60
60
|
|
|
@@ -64,6 +64,37 @@ describe('#psf-slp-indexer', () => {
|
|
|
64
64
|
assert.property(result.txData, 'vin')
|
|
65
65
|
assert.property(result.txData, 'vout')
|
|
66
66
|
assert.property(result.txData, 'isValidSlp')
|
|
67
|
+
assert.equal(result.txData.isValidSlp, true)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should handle non-SLP transaction', 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 handle a blacklisted token', 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, false)
|
|
67
98
|
})
|
|
68
99
|
})
|
|
69
100
|
})
|
|
@@ -11,12 +11,12 @@ describe('#Transaction', () => {
|
|
|
11
11
|
if (process.env.IS_USING_FREE_TIER) await bchjs.Util.sleep(1000)
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
describe('#
|
|
14
|
+
describe('#getOld', () => {
|
|
15
15
|
it('should get details about a non-SLP transaction', async () => {
|
|
16
16
|
const txid =
|
|
17
17
|
'2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
|
|
18
18
|
|
|
19
|
-
const result = await bchjs.Transaction.
|
|
19
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
20
20
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
21
21
|
|
|
22
22
|
// Assert that there are stanardized properties.
|
|
@@ -37,7 +37,7 @@ describe('#Transaction', () => {
|
|
|
37
37
|
const txid =
|
|
38
38
|
'266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
|
|
39
39
|
|
|
40
|
-
const result = await bchjs.Transaction.
|
|
40
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
41
41
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
42
42
|
|
|
43
43
|
// Assert that there are stanardized properties.
|
|
@@ -69,9 +69,10 @@ describe('#Transaction', () => {
|
|
|
69
69
|
// that is also a valid SLP tx, but is unrelated. Both TXs pass DAG validation,
|
|
70
70
|
// but for separate tokens.
|
|
71
71
|
it('should get problematic transaction', async () => {
|
|
72
|
-
const txid =
|
|
72
|
+
const txid =
|
|
73
|
+
'a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe'
|
|
73
74
|
|
|
74
|
-
const result = await bchjs.Transaction.
|
|
75
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
75
76
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
76
77
|
|
|
77
78
|
// The token ID should equal the txid for this Vin.
|
|
@@ -38,6 +38,7 @@ describe('#PsfSlpIndexer', () => {
|
|
|
38
38
|
assert.include(err.message, 'test error')
|
|
39
39
|
}
|
|
40
40
|
})
|
|
41
|
+
|
|
41
42
|
it('should handle request error', async () => {
|
|
42
43
|
try {
|
|
43
44
|
// Stub the network call.
|
|
@@ -239,20 +240,25 @@ describe('#PsfSlpIndexer', () => {
|
|
|
239
240
|
assert.include(err.message, 'test error')
|
|
240
241
|
}
|
|
241
242
|
})
|
|
242
|
-
it('should handle request error', async () => {
|
|
243
|
-
try {
|
|
244
|
-
// Stub the network call.
|
|
245
|
-
const testErr = new Error()
|
|
246
|
-
testErr.response = { data: { status: 422 } }
|
|
247
|
-
sandbox.stub(axios, 'post').throws(testErr)
|
|
248
243
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
} catch (err) {
|
|
254
|
-
assert.equal(err.status, 422)
|
|
244
|
+
it('should get tx from full node if not available from slp indexer', async () => {
|
|
245
|
+
// Stub the call to the SLP indexer.
|
|
246
|
+
const testErr = {
|
|
247
|
+
response: { data: { error: 'Key not found in database' } }
|
|
255
248
|
}
|
|
249
|
+
sandbox.stub(axios, 'post').rejects(testErr)
|
|
250
|
+
|
|
251
|
+
// Stub the call to the full node
|
|
252
|
+
sandbox
|
|
253
|
+
.stub(bchjs.PsfSlpIndexer.rawTransaction, 'getTxData')
|
|
254
|
+
.resolves({ txid: 'fakeTxid' })
|
|
255
|
+
|
|
256
|
+
const txid =
|
|
257
|
+
'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2'
|
|
258
|
+
const result = await bchjs.PsfSlpIndexer.tx(txid)
|
|
259
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
260
|
+
|
|
261
|
+
assert.equal(result.txData.txid, 'fakeTxid')
|
|
256
262
|
})
|
|
257
263
|
})
|
|
258
264
|
})
|
|
@@ -22,10 +22,10 @@ describe('#TransactionLib', () => {
|
|
|
22
22
|
})
|
|
23
23
|
afterEach(() => sandbox.restore())
|
|
24
24
|
|
|
25
|
-
describe('#
|
|
25
|
+
describe('#getOld', () => {
|
|
26
26
|
it('should throw an error if txid is not specified', async () => {
|
|
27
27
|
try {
|
|
28
|
-
await bchjs.Transaction.
|
|
28
|
+
await bchjs.Transaction.getOld()
|
|
29
29
|
|
|
30
30
|
assert.fail('Unexpected code path!')
|
|
31
31
|
} catch (err) {
|
|
@@ -45,7 +45,7 @@ describe('#TransactionLib', () => {
|
|
|
45
45
|
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
|
|
46
46
|
.resolves(mockData.nonSlpTxDetails)
|
|
47
47
|
|
|
48
|
-
const result = await bchjs.Transaction.
|
|
48
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
49
49
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
50
50
|
|
|
51
51
|
// Assert that there are stanardized properties.
|
|
@@ -84,7 +84,7 @@ describe('#TransactionLib', () => {
|
|
|
84
84
|
const txid =
|
|
85
85
|
'266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
|
|
86
86
|
|
|
87
|
-
const result = await bchjs.Transaction.
|
|
87
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
88
88
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
89
89
|
|
|
90
90
|
// Assert that there are stanardized properties.
|
|
@@ -114,7 +114,7 @@ describe('#TransactionLib', () => {
|
|
|
114
114
|
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
|
|
115
115
|
.rejects(new Error('test error'))
|
|
116
116
|
|
|
117
|
-
await bchjs.Transaction.
|
|
117
|
+
await bchjs.Transaction.getOld(txid)
|
|
118
118
|
|
|
119
119
|
assert.fail('Unexpected code path')
|
|
120
120
|
} catch (err) {
|
|
@@ -147,7 +147,7 @@ describe('#TransactionLib', () => {
|
|
|
147
147
|
const txid =
|
|
148
148
|
'874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e'
|
|
149
149
|
|
|
150
|
-
const result = await bchjs.Transaction.
|
|
150
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
151
151
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
152
152
|
|
|
153
153
|
// Assert that there are stanardized properties.
|
|
@@ -195,7 +195,7 @@ describe('#TransactionLib', () => {
|
|
|
195
195
|
const txid =
|
|
196
196
|
'4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa'
|
|
197
197
|
|
|
198
|
-
const result = await bchjs.Transaction.
|
|
198
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
199
199
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
200
200
|
|
|
201
201
|
// Assert that there are stanardized properties.
|
|
@@ -246,7 +246,7 @@ describe('#TransactionLib', () => {
|
|
|
246
246
|
const txid =
|
|
247
247
|
'6bc111fbf5b118021d68355ca19a0e77fa358dd931f284b2550f79a51ab4792a'
|
|
248
248
|
|
|
249
|
-
const result = await bchjs.Transaction.
|
|
249
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
250
250
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
251
251
|
|
|
252
252
|
// Assert that there are stanardized properties.
|
|
@@ -705,4 +705,15 @@ describe('#TransactionLib', () => {
|
|
|
705
705
|
assert.equal(result.isSlpTx, true)
|
|
706
706
|
})
|
|
707
707
|
})
|
|
708
|
+
|
|
709
|
+
describe('#get', () => {
|
|
710
|
+
it('should proxy psf-slp-indexer', async () => {
|
|
711
|
+
// console.log('bchjs.Transaction: ', bchjs.Transaction)
|
|
712
|
+
sandbox.stub(bchjs.Transaction.psfSlpIndexer, 'tx').resolves('test data')
|
|
713
|
+
|
|
714
|
+
const result = await bchjs.Transaction.get()
|
|
715
|
+
|
|
716
|
+
assert.equal(result, 'test data')
|
|
717
|
+
})
|
|
718
|
+
})
|
|
708
719
|
})
|