Compare commits

...
25 Commits
Author SHA1 Message Date
Chris Troutner 3c4051c3a5 Merge pull request #74 from Permissionless-Software-Foundation/ct-unstable
fix(tokenUtxoDetails): Updating to handle alternative output from SLPDB
2020-12-13 09:00:48 -08:00
Chris Troutner 0f3cc1e9e8 Merge branch 'master' into ct-unstable 2020-12-13 08:56:28 -08:00
Chris Troutner b9873f7ed8 Added additional corner case unit test for tokenUtxoDetails() 2020-12-13 08:56:09 -08:00
Chris Troutner 82cd9270fa fix(tokenUtxoDetails): Updating to handle alternative output from SLPDB 2020-12-13 08:51:58 -08:00
Chris Troutner ac6b45b162 Merge pull request #73 from Permissionless-Software-Foundation/ct-unstable
fix(debugging): Additional debugging
2020-12-13 07:26:07 -08:00
Chris Troutner 66a99c0560 Merge branch 'master' into ct-unstable 2020-12-13 07:20:08 -08:00
Chris Troutner 17e4a32ff4 fix(debugging): Additional debugging 2020-12-13 07:19:24 -08:00
Chris Troutner 6a430b4da6 Merge pull request #72 from Permissionless-Software-Foundation/ct-unstable
fix(debugging): Debugging problem with hydrateUtxos()
2020-12-13 06:55:48 -08:00
Chris Troutner 77ab090bc2 fix(debugging): Debugging problem with hydrateUtxos() 2020-12-13 06:51:07 -08:00
Chris Troutner fdff4a1afb Merge pull request #71 from Permissionless-Software-Foundation/ct-unstable
fix(tokenUtxoDetails): Fixing bug with fallback validators
2020-12-13 06:25:10 -08:00
Chris Troutner 12701cf3dc fix(tokenUtxoDetails): Fixing bug with fallback validators 2020-12-13 06:20:51 -08:00
Chris Troutner 1032625ac8 Merge pull request #70 from Permissionless-Software-Foundation/ct-unstable
blockbook: Removing blockbook support from testnet
2020-12-11 15:19:36 -08:00
Chris Troutner 586c2972da feat(blockbook): Removing blockbook support from testnet 2020-12-11 15:15:03 -08:00
Chris Troutner 3d41e41192 fix(testnet): Updating integration tests 2020-12-11 14:59:46 -08:00
Chris Troutner af8e0cdf45 Merge pull request #69 from Permissionless-Software-Foundation/ct-unstable
fix(testnet): Fixing testnet integration tests
2020-12-08 18:36:54 -08:00
Chris Troutner 10f6f58ec5 fix(testnet): Fixing testnet integration tests 2020-12-08 18:28:30 -08:00
Chris Troutner fd9f399f41 Merge pull request #68 from Permissionless-Software-Foundation/ct-unstable
Added test/integration/implementations/
2020-12-08 17:59:49 -08:00
Chris Troutner 98582edd0b Merge branch 'master' into ct-unstable 2020-12-08 17:56:03 -08:00
Chris Troutner 07b7cb0afd Added test/integration/implementations/ for customized integration tests for different implementations 2020-12-08 17:55:47 -08:00
Chris Troutner dda9658375 Merge pull request #67 from Permissionless-Software-Foundation/ct-unstable
Refactoring integration tests
2020-12-08 17:45:22 -08:00
Chris Troutner 358dad533d Removing old bchn integration tests 2020-12-08 17:42:31 -08:00
Chris Troutner 7a63573143 fix(integration): Refactored abc and bchn integration tests 2020-12-08 17:23:41 -08:00
Chris Troutner 333ced5c79 updating gitignore 2020-12-07 15:54:56 -08:00
Chris Troutner c6ceae1283 Merge pull request #65 from Permissionless-Software-Foundation/ct-unstable
fix(semantic-release): Updating to 17.3.0
2020-12-06 19:59:16 -08:00
Chris Troutner 4e8a376720 fix(semantic-release): Updating to 17.3.0 2020-12-06 19:54:44 -08:00
33 changed files with 1965 additions and 3499 deletions
+1
View File
@@ -2,6 +2,7 @@ node_modules/*
.nyc_output/*
wallet-info.txt
wallet.json
integration-test-sweet.sh
docs/
coverage/
+744 -662
View File
File diff suppressed because it is too large Load Diff
+7 -10
View File
@@ -9,18 +9,15 @@
"main": "src/bch-js",
"scripts": {
"test": "nyc mocha --trace-warnings --unhandled-rejections=strict --timeout 30000 test/unit/",
"test:integration": "bash test/integration/test-bchn-integration.sh",
"test:integration:bchn": "bash test/integration/test-bchn-integration.sh",
"test:integration:abc": "RESTURL=https://abc.fullstack.cash/v4/ IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/",
"test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/testnet/",
"test:integration": "npm run test:integration:bchn",
"test:integration:abc": "export RESTURL=https://abc.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:bchn": "export RESTURL=https://bchn.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/chains/testnet/",
"test:integration:local": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration",
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v4/ bash test/integration/test-bchn-integration.sh",
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v4/ mocha --timeout 30000 test/integration/testnet",
"test:integration:api": "RESTURL=https://api.fullstack.cash/v4/ mocha --timeout 30000 test/integration",
"test:temp": "RESTURL=https://bchn.fullstack.cash/v4/ mocha --timeout 30000 -g '#validateTxid' test/integration/bchn/",
"test:temp2": "RESTURL=https://abc.fullstack.cash/v4/ mocha --timeout 30000 -g '#validateTxid' test/integration/",
"test:temp3": "ISBCHN=true RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 -g '#validateTxid' test/integration/bchn/",
"test:temp4": "mocha --timeout=30000 -g '#tokenUtxoDetails' test/unit/",
"test:temp": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#validateTxid2' test/integration/",
"test:temp2": "mocha --timeout 30000 -g 'tokenUtxoDetails' test/unit/",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
"docs": "./node_modules/.bin/apidoc -i src/ -o docs"
@@ -91,7 +88,7 @@
"node-mocks-http": "^1.7.0",
"nyc": "^14.1.0",
"prettier": "^1.18.2",
"semantic-release": "^15.13.19",
"semantic-release": "^17.3.0",
"sinon": "^7.3.2"
},
"apidoc": {
+59 -11
View File
@@ -431,10 +431,14 @@ class Utils {
* '00ea27261196a411776f81029c0ebe34362936b4a9847deb1f7a40a02b3a1476',
* valid: true } ]
*/
// This function has two responses. If SLPDB is working correctly, the output
// will be like the examples above. If SLPDB has fallen behind real-time
// processing, it will return this output:
// [ null ]
async validateTxid(txid) {
const path = `${this.restURL}slp/validateTxid`
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
// Handle a single TXID or an array of TXIDs.
let txids
@@ -449,7 +453,9 @@ class Utils {
},
_this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
console.log(
`validateTxid response.data: ${JSON.stringify(response.data, null, 2)}`
)
const validatedTxids = response.data
@@ -1052,7 +1058,7 @@ class Utils {
// utxo list may have duplicate tx_hash, varying tx_pos
// only need to call decodeOpReturn once for those
const decodeOpReturnCache = {}
const cachedTxValidation = {}
// const cachedTxValidation = {}
// Throw error if input is not an array.
if (!Array.isArray(utxos)) throw new Error("Input must be an array.")
@@ -1288,19 +1294,52 @@ class Utils {
// property. i.e. it has been successfully hydrated with SLP
// information.
// CT 12/13/2020: Disabling the cache until I get processing of tokens
// to be more stable.
// If the value has been cached, use the cached version first.
let isValid = cachedTxValidation[utxo.txid]
// let isValid = cachedTxValidation[utxo.txid]
let isValid = null
// There are two possible responses from SLPDB. If SLPDB is functioning
// correctly, then validateTxid() will return this:
// isValid: [
// {
// "txid": "ff0c0354f8d3ddb34fa36f73494eb58ea24f8b8da6904aa8ed43b7a74886c583",
// "valid": true
// }
// ]
//
// If SLPDB has fallen behind real-time processing, it will return this:
// isValid: [
// null
// ]
//
// Note: validateTxid3() has the same output as validateTxid().
// validateTxid2() uses slp-validate, which has a different output format.
// If not in the cache, try the general SLPDB.
if (isValid == null) {
if (isValid === null) {
// console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`)
isValid = await this.validateTxid(utxo.txid)
// console.log(
// `validateTxid() isValid: ${JSON.stringify(isValid, null, 2)}`
// )
// Handle corner case where SLPDB returns an array with a null element.
if (isValid[0] === null)
isValid = [{ txid: utxo.txid, valid: null }]
isValid = isValid[0].valid
// Save the result to the local cache.
cachedTxValidation[utxo.txid] = isValid
// cachedTxValidation[utxo.txid] = isValid
}
// console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
// console.log(
// `pre-validateTxid3() isValid: ${JSON.stringify(isValid, null, 2)}`
// )
// If still null, check the whitelist SLPDB
if (isValid === null) {
// console.log(
@@ -1334,24 +1373,33 @@ class Utils {
// )}`
// )
isValid = isValid[0].valid
if (isValid[0] !== null) isValid = isValid[0].valid
// Save the result to the local cache.
cachedTxValidation[utxo.txid] = isValid
// cachedTxValidation[utxo.txid] = isValid
}
}
// console.log(
// `pre-validateTxid2() isValid: ${JSON.stringify(isValid, null, 2)}`
// )
// If still null, as a last resort, check it against slp-validate
if (isValid === null) {
isValid = await this.validateTxid2(utxo.txid)
try {
isValid = await this.validateTxid2(utxo.txid)
} catch (err) {
// Mark as invalid if validateTxid2() throws an error.
isValid = null
}
// console.log(
// `slp-validate isValid: ${JSON.stringify(isValid, null, 2)}`
// )
isValid = isValid.isValid
if (isValid !== null) isValid = isValid.isValid
// Save the result to the local cache.
cachedTxValidation[utxo.txid] = isValid
// cachedTxValidation[utxo.txid] = isValid
}
// console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
-331
View File
@@ -1,331 +0,0 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
TODO
- getMempoolEntry() only works on TXs in the mempool, so it needs to be part
of an e2e test to be properly tested.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe(`#blockchain`, () => {
describe(`#getBestBlockHash`, () => {
it(`should GET best block hash`, async () => {
const result = await bchjs.Blockchain.getBestBlockHash()
//console.log(`result: ${util.inspect(result)}`)
assert.isString(result)
assert.equal(result.length, 64, "Specific hash length")
})
})
describe("#getBlockHeader", () => {
it(`should GET block header for a single hash`, async () => {
const hash =
"000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201"
const result = await bchjs.Blockchain.getBlockHeader(hash)
assert.hasAllKeys(result, [
"hash",
"confirmations",
"height",
"version",
"versionHex",
"merkleroot",
"time",
"mediantime",
"nonce",
"bits",
"difficulty",
"chainwork",
"previousblockhash",
"nextblockhash",
"nTx"
])
})
it(`should GET block headers for an array of hashes`, async () => {
const hash = [
"000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201",
"00000000000000000568f0a96bf4348847bc84e455cbfec389f27311037a20f3"
]
const result = await bchjs.Blockchain.getBlockHeader(hash)
assert.isArray(result)
assert.hasAllKeys(result[0], [
"hash",
"confirmations",
"height",
"version",
"versionHex",
"merkleroot",
"time",
"mediantime",
"nonce",
"bits",
"difficulty",
"chainwork",
"previousblockhash",
"nextblockhash",
"nTx"
])
})
it(`should throw an error for improper input`, async () => {
try {
const hash = 12345
await bchjs.Blockchain.getBlockHeader(hash)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.include(
err.message,
`Input hash must be a string or array of strings`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const data = []
for (let i = 0; i < 25; i++) {
data.push(
"000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201"
)
}
const result = await bchjs.Blockchain.getBlockHeader(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe("#getMempoolEntry", () => {
/*
// To run this test, the txid must be unconfirmed.
const txid =
"defea04c38ee00cf73ad402984714ed22dc0dd99b2ae5cb50d791d94343ba79b"
it(`should GET single mempool entry`, async () => {
const result = await bchjs.Blockchain.getMempoolEntry(txid)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, [
"size",
"fee",
"modifiedfee",
"time",
"height",
"startingpriority",
"currentpriority",
"descendantcount",
"descendantsize",
"descendantfees",
"ancestorcount",
"ancestorsize",
"ancestorfees",
"depends"
])
})
it(`should get an array of mempool entries`, async () => {
const result = await bchjs.Blockchain.getMempoolEntry([txid, txid])
console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"size",
"fee",
"modifiedfee",
"time",
"height",
"startingpriority",
"currentpriority",
"descendantcount",
"descendantsize",
"descendantfees",
"ancestorcount",
"ancestorsize",
"ancestorfees",
"depends"
])
})
*/
it(`should throw an error if txid is not in mempool`, async () => {
try {
const txid =
"03f69502ca32e7927fd4f38c1d3f950bff650c1eea3d09a70e9df5a9d7f989f7"
await bchjs.Blockchain.getMempoolEntry(txid)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, `Transaction not in mempool`)
}
})
it(`should throw an error for improper single input`, async () => {
try {
const txid = 12345
await bchjs.Blockchain.getMempoolEntry(txid)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.include(
err.message,
`Input must be a string or array of strings`
)
}
})
})
describe(`#getTxOutProof`, () => {
it(`should get single tx out proof`, async () => {
const txid =
"03f69502ca32e7927fd4f38c1d3f950bff650c1eea3d09a70e9df5a9d7f989f7"
const result = await bchjs.Blockchain.getTxOutProof(txid)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isString(result)
})
it(`should get an array of tx out proofs`, async () => {
const txid = [
"03f69502ca32e7927fd4f38c1d3f950bff650c1eea3d09a70e9df5a9d7f989f7",
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"
]
const result = await bchjs.Blockchain.getTxOutProof(txid)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isString(result[0])
})
it(`should throw an error for improper single input`, async () => {
try {
const txid = 12345
await bchjs.Blockchain.getTxOutProof(txid)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.include(
err.message,
`Input must be a string or array of strings`
)
}
})
})
describe(`#verifyTxOutProof`, () => {
const mockTxOutProof =
"0000002086a4a3161f9ba2174883ec0b93acceac3b2f37b36ed1f90000000000000000009cb02406d1094ecf3e0b4c0ca7c585125e721147c39daf6b48c90b512741e13a12333e5cb38705180f441d8c7100000008fee9b60f1edb57e5712839186277ed39e0a004a32be9096ee47472efde8eae62f789f9d7a9f59d0ea7093dea1e0c65ff0b953f1d8cf3d47f92e732ca0295f603c272d5f4a63509f7a887f2549d78af7444aa0ecbb4f66d9cbe13bc6a89f59e05a199df8325d490818ffefe6b6321d32d7496a68580459836c0183f89082fc1b491cc91b23ecdcaa4c347bf599a62904d61f1c15b400ebbd5c90149010c139d9c1e31b774b796977393a238080ab477e1d240d0c4f155d36f519668f49bae6bd8cd5b8e40522edf76faa09cca6188d83ff13af6967cc6a569d1a5e9aeb1fdb7f531ddd2d0cbb81879741d5f38166ac1932136264366a4065cc96a42e41f96294f02df01"
it(`should verify a single proof`, async () => {
const result = await bchjs.Blockchain.verifyTxOutProof(mockTxOutProof)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isString(result[0])
assert.equal(
result[0],
"03f69502ca32e7927fd4f38c1d3f950bff650c1eea3d09a70e9df5a9d7f989f7"
)
})
it(`should verify an array of proofs`, async () => {
const proofs = [mockTxOutProof, mockTxOutProof]
const result = await bchjs.Blockchain.verifyTxOutProof(proofs)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isString(result[0])
assert.equal(
result[0],
"03f69502ca32e7927fd4f38c1d3f950bff650c1eea3d09a70e9df5a9d7f989f7"
)
})
it(`should throw an error for improper single input`, async () => {
try {
const txid = 12345
await bchjs.Blockchain.verifyTxOutProof(txid)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.include(
err.message,
`Input must be a string or array of strings`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const data = []
for (let i = 0; i < 25; i++) data.push(mockTxOutProof)
const result = await bchjs.Blockchain.verifyTxOutProof(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe("#getTxOut", () => {
it("should get information on an unspent tx", async () => {
const result = await bchjs.Blockchain.getTxOut(
"62a3ea958a463a372bc0caf2c374a7f60be9c624be63a0db8db78f05809df6d8",
0,
true
)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, [
"bestblock",
"confirmations",
"value",
"scriptPubKey",
"coinbase"
])
})
it("should get information on a spent tx", async () => {
const result = await bchjs.Blockchain.getTxOut(
"87380e52d151856b23173d6d8a3db01b984c6b50f77ea045a5a1cf4f54497871",
0,
true
)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.equal(result, null)
})
})
})
-19
View File
@@ -1,19 +0,0 @@
/*
Integration tests for bchjs control library.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
describe(`#control`, () => {
describe(`#getNetworkInfo`, () => {
it("should get info on the full node", async () => {
const result = await bchjs.Control.getNetworkInfo()
console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "version")
})
})
})
-356
View File
@@ -1,356 +0,0 @@
const chai = require("chai")
const assert = chai.assert
const sinon = require("sinon")
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
describe(`#ElectrumX`, () => {
let sandbox
beforeEach(() => (sandbox = sinon.createSandbox()))
afterEach(() => sandbox.restore())
describe(`#utxo`, () => {
it(`should GET utxos for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.Electrumx.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "height")
assert.property(result.utxos[0], "tx_hash")
assert.property(result.utxos[0], "tx_pos")
assert.property(result.utxos[0], "value")
})
it(`should POST request for UTXOs for an array of addresses`, async () => {
const addr = [
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
]
const result = await bchjs.Electrumx.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "utxos")
assert.isArray(result.utxos[0].utxos)
assert.property(result.utxos[0], "address")
assert.property(result.utxos[0].utxos[0], "height")
assert.property(result.utxos[0].utxos[0], "tx_hash")
assert.property(result.utxos[0].utxos[0], "tx_pos")
assert.property(result.utxos[0].utxos[0], "value")
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
const result = await bchjs.Electrumx.utxo(addr)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#balance`, () => {
it(`should GET balance for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.Electrumx.balance(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "balance")
assert.property(result.balance, "confirmed")
assert.property(result.balance, "unconfirmed")
})
it(`should POST request for balances for an array of addresses`, async () => {
const addr = [
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
]
const result = await bchjs.Electrumx.balance(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "balances")
assert.isArray(result.balances)
assert.property(result.balances[0], "address")
assert.property(result.balances[0], "balance")
assert.property(result.balances[0].balance, "confirmed")
assert.property(result.balances[0].balance, "unconfirmed")
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
const result = await bchjs.Electrumx.balance(addr)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#transactions`, () => {
it(`should GET transaction history for a single address`, async () => {
const addr = "bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
const result = await bchjs.Electrumx.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "transactions")
assert.isArray(result.transactions)
assert.property(result.transactions[0], "height")
assert.property(result.transactions[0], "tx_hash")
})
it(`should POST request for transaction history for an array of addresses`, async () => {
const addr = [
"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj",
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
]
const result = await bchjs.Electrumx.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "transactions")
assert.isArray(result.transactions)
assert.property(result.transactions[0], "address")
assert.property(result.transactions[0], "transactions")
assert.isArray(result.transactions[0].transactions)
assert.property(result.transactions[0].transactions[0], "height")
assert.property(result.transactions[0].transactions[0], "tx_hash")
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0")
const result = await bchjs.Electrumx.transactions(addr)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#unconfirmed`, () => {
// These tests won't work because unconfirmed transactions are transient in nature.
/*
it(`should GET unconfirmed UTXOs (mempool) for a single address`, async () => {
const addr = "bitcoincash:qqy6qwk3wpne95hhv8uzwr4cn8m7c06cqgchl77dnv"
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "height")
assert.property(result.utxos[0], "tx_hash")
assert.property(result.utxos[0], "fee")
})
it(`should POST request for unconfirmed UTXOs (mempool) for an array of addresses`, async () => {
const addr = [
"bitcoincash:qqy6qwk3wpne95hhv8uzwr4cn8m7c06cqgchl77dnv",
"bitcoincash:qpyrtsl9msdu2klgfpcmn2v5r22w9rk24g8pal74ts"
]
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "utxos")
assert.isArray(result.utxos[0].utxos)
assert.property(result.utxos[0], "address")
assert.property(result.utxos[0].utxos[0], "height")
assert.property(result.utxos[0].utxos[0], "tx_hash")
assert.property(result.utxos[0].utxos[0], "fee")
})
*/
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#blockHeader`, () => {
it(`should GET block headers for given height and count`, async () => {
const height = 42
const count = 2
const result = await bchjs.Electrumx.blockHeader(height, count)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "headers")
assert.isArray(result.headers)
assert.equal(result.headers.length, 2)
})
it(`should GET block headers for given height with default count = 1`, async () => {
const height = 42
const result = await bchjs.Electrumx.blockHeader(height)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "headers")
assert.isArray(result.headers)
assert.equal(result.headers.length, 1)
})
})
describe(`#txData`, () => {
it(`should GET details for a single transaction`, async () => {
const txid =
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
const result = await bchjs.Electrumx.txData(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "details")
assert.isObject(result.details)
assert.property(result.details, "blockhash")
assert.property(result.details, "hash")
assert.property(result.details, "hex")
assert.property(result.details, "vin")
assert.property(result.details, "vout")
assert.equal(result.details.hash, txid)
})
it(`should POST details for an array of transactions`, async () => {
const txids = [
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251",
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
]
const result = await bchjs.Electrumx.txData(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "transactions")
assert.isArray(result.transactions)
assert.property(result.transactions[0], "txid")
assert.property(result.transactions[0], "details")
assert.property(result.transactions[0].details, "blockhash")
assert.property(result.transactions[0].details, "hash")
assert.property(result.transactions[0].details, "hex")
assert.property(result.transactions[0].details, "vin")
assert.property(result.transactions[0].details, "vout")
})
it(`should throw error on array size rate limit`, async () => {
try {
const txids = []
for (let i = 0; i < 25; i++) {
txids.push(
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
)
}
await bchjs.Electrumx.txData(txids)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#broadcast`, () => {
it(`should broadcast a single transaction`, async () => {
const txHex =
"020000000265d13ef402840c8a51f39779afb7ae4d49e4b0a3c24a3d0e7742038f2c679667010000006441dd1dd72770cadede1a7fd0363574846c48468a398ddfa41a9677c74cac8d2652b682743725a3b08c6c2021a629011e11a264d9036e9d5311e35b5f4937ca7b4e4121020797d8fd4d2fa6fd7cdeabe2526bfea2b90525d6e8ad506ec4ee3c53885aa309ffffffff65d13ef402840c8a51f39779afb7ae4d49e4b0a3c24a3d0e7742038f2c679667000000006441347d7f218c11c04487c1ad8baac28928fb10e5054cd4494b94d078cfa04ccf68e064fb188127ff656c0b98e9ce87f036d183925d0d0860605877d61e90375f774121028a53f95eb631b460854fc836b2e5d31cad16364b4dc3d970babfbdcc3f2e4954ffffffff035ac355000000000017a914189ce02e332548f4804bac65cba68202c9dbf822878dfd0800000000001976a914285bb350881b21ac89724c6fb6dc914d096cd53b88acf9ef3100000000001976a91445f1f1c4a9b9419a5088a3e9c24a293d7a150e6488ac00000000"
try {
await bchjs.Electrumx.broadcast(txHex)
} catch (err) {
assert.property(err, "success")
assert.equal(err.success, false)
assert.include(
err.error,
"the transaction was rejected by network rules"
)
}
})
})
})
-31
View File
@@ -1,31 +0,0 @@
const assert = require("chai").assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
describe("#Encryption", () => {
describe("#getPubKey", () => {
it("should get a public key", async () => {
const addr = "bitcoincash:qpf8jv9hmqcda0502gjp7nm3g24y5h5s4unutghsxq"
const result = await bchjs.encryption.getPubKey(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "publicKey")
})
it("should report when public key can not be found", async () => {
const addr = "bitcoincash:qrgqqkky28jdkv3w0ctrah0mz3jcsnsklc34gtukrh"
const result = await bchjs.encryption.getPubKey(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, false)
assert.property(result, "publicKey")
assert.equal(result.publicKey, "not found")
})
})
})
-129
View File
@@ -1,129 +0,0 @@
const chai = require("chai")
const assert = chai.assert
const sinon = require("sinon")
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS({ ninsightURL: "https://rest.bitcoin.com/v2" })
describe(`#Ninsight`, () => {
let sandbox
beforeEach(() => (sandbox = sinon.createSandbox()))
afterEach(() => sandbox.restore())
describe(`#utxo`, () => {
it(`should GET utxos for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.Ninsight.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result[0], "utxos")
assert.property(result[0], "legacyAddress")
assert.property(result[0], "cashAddress")
assert.property(result[0], "slpAddress")
assert.property(result[0], "scriptPubKey")
assert.property(result[0], "asm")
assert.isArray(result[0].utxos)
assert.property(result[0].utxos[0], "txid")
assert.property(result[0].utxos[0], "vout")
assert.property(result[0].utxos[0], "amount")
assert.property(result[0].utxos[0], "satoshis")
assert.property(result[0].utxos[0], "height")
assert.property(result[0].utxos[0], "confirmations")
})
it(`should POST utxo details for an array of addresses`, async () => {
const addr = [
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
]
const result = await bchjs.Ninsight.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isArray(result[0].utxos)
assert.property(result[0], "utxos")
assert.property(result[0], "legacyAddress")
assert.property(result[0], "cashAddress")
assert.property(result[0], "slpAddress")
assert.property(result[0], "scriptPubKey")
assert.property(result[0], "asm")
})
})
describe(`#transactions`, () => {
it(`should POST transactions history for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.Ninsight.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "cashAddress")
assert.property(result[0], "legacyAddress")
assert.property(result[0], "txs")
assert.isArray(result[0].txs)
assert.property(result[0].txs[0], "txid")
assert.property(result[0].txs[0], "vin")
assert.property(result[0].txs[0], "vout")
})
it(`should POST transactions history for an array of addresses`, async () => {
const addr = [
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
]
const result = await bchjs.Ninsight.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "cashAddress")
assert.property(result[0], "legacyAddress")
assert.property(result[0], "txs")
assert.isArray(result[0].txs)
assert.property(result[0].txs[0], "txid")
assert.property(result[0].txs[0], "vin")
assert.property(result[0].txs[0], "vout")
})
})
describe(`#txDetails`, () => {
it(`should POST transactions details for a single address`, async () => {
const txid = "fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"
const result = await bchjs.Ninsight.txDetails(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.property(result[0], "version")
assert.property(result[0], "locktime")
assert.property(result[0], "vin")
assert.property(result[0], "vout")
assert.property(result[0], "blockhash")
assert.property(result[0], "blockheight")
assert.property(result[0], "confirmations")
assert.property(result[0], "time")
assert.property(result[0], "blocktime")
assert.property(result[0], "isCoinBase")
assert.property(result[0], "valueOut")
assert.property(result[0], "size")
})
it(`should POST transactions details for an array of addresses`, async () => {
const txid = [
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
"4db095f34d632a4daf942142c291f1f2abb5ba2e1ccac919d85bdc2f671fb251"
]
const result = await bchjs.Ninsight.txDetails(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.property(result[0], "vin")
assert.property(result[0], "vout")
})
})
})
-117
View File
@@ -1,117 +0,0 @@
/*
tests for OpenBazaar library.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
describe(`#OpenBazaar`, () => {
describe(`#Balance`, () => {
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.OpenBazaar.balance(addr)
// assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(err.message, `Input address must be a string`)
}
})
it(`should GET balance for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.OpenBazaar.balance(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, [
"page",
"totalPages",
"itemsOnPage",
"addrStr",
"balance",
"totalReceived",
"totalSent",
"unconfirmedBalance",
"unconfirmedTxApperances",
"txApperances",
"transactions"
])
assert.isArray(result.transactions)
})
})
describe(`#utxo`, () => {
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.OpenBazaar.utxo(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(err.message, `Input address must be a string`)
}
})
it(`should GET utxos for a single address`, async () => {
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.OpenBazaar.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAllKeys(result[0], [
"txid",
"vout",
"amount",
"height",
"confirmations",
"satoshis"
])
})
})
describe(`#tx`, () => {
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.OpenBazaar.tx(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(err.message, `Input txid must be a string`)
}
})
it(`should GET transactions for a single address`, async () => {
const addr =
"2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7"
const result = await bchjs.OpenBazaar.tx(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, [
"txid",
"version",
"vin",
"vout",
"blockhash",
"blockheight",
"confirmations",
"blocktime",
"valueOut",
"valueIn",
"fees",
"hex",
"time"
])
assert.isArray(result.vin)
assert.isArray(result.vout)
})
})
})
-42
View File
@@ -1,42 +0,0 @@
const assert = require("chai").assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
describe("#price", () => {
describe("#current", () => {
describe("#single currency", () => {
it("should get current price for single currency", async () => {
const result = await bchjs.Price.current("usd")
assert.notEqual(0, result)
})
})
})
describe("#getUsd", () => {
it("should get the USD price of BCH", async () => {
const result = await bchjs.Price.getUsd()
// console.log(result)
assert.isNumber(result)
})
})
describe("#getBchaUsd", () => {
it("should get the USD price of BCHA", async () => {
const result = await bchjs.Price.getBchaUsd()
console.log(result)
assert.isNumber(result)
})
})
describe("#rates", () => {
it("should get the price of BCH in several currencies", async () => {
const result = await bchjs.Price.rates()
// console.log(result)
assert.property(result, "USD")
assert.property(result, "CAD")
})
})
})
-329
View File
@@ -1,329 +0,0 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
TODO
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe("#rawtransaction", () => {
describe("#decodeRawTransaction", () => {
it("should decode tx for a single hex", async () => {
const hex =
"0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000"
const result = await bchjs.RawTransactions.decodeRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, [
"txid",
"hash",
"size",
"version",
"locktime",
"vin",
"vout"
])
assert.isArray(result.vin)
assert.isArray(result.vout)
})
it("should decode an array of tx hexes", async () => {
const hexes = [
"0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000",
"0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000"
]
const result = await bchjs.RawTransactions.decodeRawTransaction(hexes)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"txid",
"hash",
"size",
"version",
"locktime",
"vin",
"vout"
])
assert.isArray(result[0].vin)
assert.isArray(result[0].vout)
})
it(`should throw an error for improper single input`, async () => {
try {
const addr = 12345
await bchjs.RawTransactions.decodeRawTransaction(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input must be a string or array of strings.`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const data = []
for (let i = 0; i < 25; i++) {
data.push(
"0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000"
)
}
const result = await bchjs.RawTransactions.decodeRawTransaction(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe("#getRawTransaction", () => {
it("should decode a single txid, with concise output", async () => {
const txid =
"23213453b4642a73b4fc30d3112d72549ca153a8707255b14373b59e43558de1"
const verbose = false
const result = await bchjs.RawTransactions.getRawTransaction(
txid,
verbose
)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isString(result)
})
it("should decode a single txid, with verbose output", async () => {
const txid =
"23213453b4642a73b4fc30d3112d72549ca153a8707255b14373b59e43558de1"
const verbose = true
const result = await bchjs.RawTransactions.getRawTransaction(
txid,
verbose
)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, [
"hex",
"txid",
"hash",
"size",
"version",
"locktime",
"vin",
"vout",
"blockhash",
"confirmations",
"time",
"blocktime"
])
assert.isArray(result.vin)
assert.isArray(result.vout)
})
it("should decode an array of txids, with a concise output", async () => {
const txid = [
"23213453b4642a73b4fc30d3112d72549ca153a8707255b14373b59e43558de1",
"b25d24fbb42d84812ed2cb55797f10fdec41afc7906ab563d1ec8c8676a2037f"
]
const verbose = false
const result = await bchjs.RawTransactions.getRawTransaction(
txid,
verbose
)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isString(result[0])
})
it("should decode an array of txids, with a verbose output", async () => {
const txid = [
"23213453b4642a73b4fc30d3112d72549ca153a8707255b14373b59e43558de1",
"b25d24fbb42d84812ed2cb55797f10fdec41afc7906ab563d1ec8c8676a2037f"
]
const verbose = true
const result = await bchjs.RawTransactions.getRawTransaction(
txid,
verbose
)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"hex",
"txid",
"hash",
"size",
"version",
"locktime",
"vin",
"vout",
"blockhash",
"confirmations",
"time",
"blocktime"
])
assert.isArray(result[0].vin)
assert.isArray(result[0].vout)
})
it(`should throw error on array size rate limit`, async () => {
try {
const dataMock =
"23213453b4642a73b4fc30d3112d72549ca153a8707255b14373b59e43558de1"
const data = []
for (let i = 0; i < 25; i++) data.push(dataMock)
const result = await bchjs.RawTransactions.getRawTransaction(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe("#decodeScript", () => {
it("should decode script for a single hex", async () => {
const hex =
"4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16"
const result = await bchjs.RawTransactions.decodeScript(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, ["asm", "type", "p2sh"])
})
// CT 2/20/19 - Waiting for this PR to be merged complete the test:
// https://github.com/Bitcoin-com/rest.bitcoin.com/pull/312
/*
it("should decode an array of tx hexes", async () => {
const hexes = [
"4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16",
"4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16"
]
const result = await bchjs.RawTransactions.decodeScript(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
})
*/
/*
it(`should throw an error for improper single input`, async () => {
try {
const addr = 12345
await bchjs.RawTransactions.decodeRawTransaction(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input must be a string or array of strings.`
)
}
})
*/
})
/*
Testing sentRawTransaction isn't really possible with an integration test,
as the endpoint really needs an e2e test to be properly tested. The tests
below expect error messages returned from the server, but at least test
that the server is responding on those endpoints, and responds consistently.
*/
describe("sendRawTransaction", () => {
it("should send a single transaction hex", async () => {
try {
const hex =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
await bchjs.RawTransactions.sendRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.fail("Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
it("should send an array of tx hexes", async () => {
try {
const hexes = [
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000",
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
]
const result = await bchjs.RawTransactions.sendRawTransaction(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.fail("Unexpected result!")
} catch (err) {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
it(`should throw an error for improper single input`, async () => {
try {
const addr = 12345
await bchjs.RawTransactions.sendRawTransaction(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input hex must be a string or array of strings`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const dataMock =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
const data = []
for (let i = 0; i < 25; i++) data.push(dataMock)
const result = await bchjs.RawTransactions.sendRawTransaction(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
})
-964
View File
@@ -1,964 +0,0 @@
/*
Integration tests for the bchjs covering SLP tokens.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
let bchjs
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 1
}
describe(`#SLP`, () => {
// before(() => {
// console.log(`bchjs.SLP.restURL: ${bchjs.SLP.restURL}`)
// console.log(`bchjs.SLP.apiToken: ${bchjs.SLP.apiToken}`)
// })
beforeEach(async () => {
// Introduce a delay so that the BVT doesn't trip the rate limits.
await sleep(1000)
bchjs = new BCHJS()
})
describe("#util", () => {
describe("#list", () => {
it(`should get information on the Spice token`, async () => {
const tokenId = `4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf`
const result = await bchjs.SLP.Utils.list(tokenId)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, [
"decimals",
"timestamp",
"timestamp_unix",
"versionType",
"documentUri",
"symbol",
"name",
"containsBaton",
"id",
"documentHash",
"initialTokenQty",
"blockCreated",
"blockLastActiveSend",
"blockLastActiveMint",
"txnsSinceGenesis",
"validAddress",
"totalMinted",
"totalBurned",
"circulatingSupply",
"mintingBatonStatus"
])
})
it("should NOT get a list of all tokens in existence", async () => {
try {
await bchjs.SLP.Utils.list()
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.fail("Unexpected result!")
} catch (err) {
// console.log(err)
assert.include(err.message, "Not Found")
}
})
it("should get information on multiple tokens", async () => {
const tokenIds = [
// Spice
`4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf`,
// PSF
"38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0"
]
const result = await bchjs.SLP.Utils.list(tokenIds)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].symbol, "SPICE")
assert.equal(result[1].symbol, "PSF")
})
})
// describe("#decodeOpReturn", () => {
// it("should decode the OP_RETURN for a SEND txid", async () => {
// const txid =
// "266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1"
//
// const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.hasAllKeys(result, [
// "tokenType",
// "transactionType",
// "tokenId",
// "spendData"
// ])
// })
//
// it("should decode the OP_RETURN for a GENESIS txid", async () => {
// const txid =
// "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
//
// const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.hasAllKeys(result, [
// "tokenType",
// "transactionType",
// "ticker",
// "name",
// "documentUrl",
// "documentHash",
// "decimals",
// "mintBatonVout",
// "initialQty",
// "tokensSentTo",
// "batonHolder"
// ])
// })
//
// it("should decode the OP_RETURN for a MINT txid", async () => {
// const txid =
// "65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4"
//
// const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.hasAllKeys(result, [
// "tokenType",
// "transactionType",
// "tokenId",
// "mintBatonVout",
// "batonStillExists",
// "quantity",
// "tokensSentTo",
// "batonHolder"
// ])
// })
//
// it("should throw an error for a non-SLP transaction", async () => {
// try {
// const txid =
// "3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec"
//
// await bchjs.SLP.Utils.decodeOpReturn(txid)
//
// assert.equal(true, false, "Unexpected result")
// } catch (err) {
// // console.log(`err: `, err)
// assert.include(err.message, "Not an OP_RETURN")
// }
// })
// })
describe("#decodeOpReturn", () => {
it("should decode the OP_RETURN for a SEND txid", async () => {
const txid =
"266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1"
const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, ["tokenType", "txType", "tokenId", "amounts"])
assert.equal(
result.tokenId,
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
)
// Verify outputs
assert.equal(result.amounts.length, 2)
assert.equal(result.amounts[0], "100000000")
assert.equal(result.amounts[1], "99883300000000")
})
it("should decode the OP_RETURN for a GENESIS txid", async () => {
const txid =
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, [
"tokenType",
"txType",
"tokenId",
"ticker",
"name",
"documentUri",
"documentHash",
"decimals",
"mintBatonVout",
"qty"
])
assert.equal(
result.tokenId,
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
)
assert.equal(result.txType, "GENESIS")
assert.equal(result.ticker, "TOK-CH")
assert.equal(result.name, "TokyoCash")
})
it("should decode the OP_RETURN for a MINT txid", async () => {
const txid =
"65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4"
const result = await bchjs.SLP.Utils.decodeOpReturn(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, [
"tokenType",
"txType",
"tokenId",
"mintBatonVout",
"qty"
])
})
it("should throw an error for a non-SLP transaction", async () => {
try {
const txid =
"3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec"
await bchjs.SLP.Utils.decodeOpReturn(txid)
assert.equal(true, false, "Unexpected result")
} catch (err) {
// console.log(`err: `, err)
assert.include(err.message, "scriptpubkey not op_return")
}
})
// Note: This TX is interpreted as valid by the original decodeOpReturn().
// Fixing this issue and related issues was the reason for creating the
// decodeOpReturn2() method using the slp-parser library.
it("should throw error for invalid SLP transaction", async () => {
try {
const txid =
"a60a522cc11ad7011b74e57fbabbd99296e4b9346bcb175dcf84efb737030415"
await bchjs.SLP.Utils.decodeOpReturn(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
} catch (err) {
// console.log(`err: `, err)
assert.include(err.message, "amount string size not 8 bytes")
}
})
})
describe("#tokenUtxoDetails", () => {
// // This captures an important corner-case. When an SLP token is created, the
// // change UTXO will contain the same SLP txid, but it is not an SLP UTXO.
it("should return details on minting baton from genesis transaction", async () => {
const utxos = [
{
txid:
"bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90",
vout: 3,
amount: 0.00002015,
satoshis: 2015,
height: 594892,
confirmations: 5
},
{
txid:
"bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90",
vout: 2,
amount: 0.00000546,
satoshis: 546,
height: 594892,
confirmations: 5
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.equal(data[0].isValid, false, "Change UTXO marked as false.")
assert.property(data[1], "txid")
assert.property(data[1], "vout")
assert.property(data[1], "amount")
assert.property(data[1], "satoshis")
assert.property(data[1], "height")
assert.property(data[1], "confirmations")
assert.property(data[1], "utxoType")
assert.property(data[1], "tokenId")
assert.property(data[1], "tokenTicker")
assert.property(data[1], "tokenName")
assert.property(data[1], "tokenDocumentUrl")
assert.property(data[1], "tokenDocumentHash")
assert.property(data[1], "decimals")
assert.property(data[1], "isValid")
assert.equal(data[1].isValid, true)
})
it("should return details for a MINT token utxo", async () => {
// Mock the call to REST API
const utxos = [
{
txid:
"cf4b922d1e1aa56b52d752d4206e1448ea76c3ebe69b3b97d8f8f65413bd5c76",
vout: 1,
amount: 0.00000546,
satoshis: 546,
height: 600297,
confirmations: 76
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.property(data[0], "txid")
assert.property(data[0], "vout")
assert.property(data[0], "amount")
assert.property(data[0], "satoshis")
assert.property(data[0], "height")
assert.property(data[0], "confirmations")
assert.property(data[0], "utxoType")
assert.property(data[0], "transactionType")
assert.property(data[0], "tokenId")
assert.property(data[0], "tokenTicker")
assert.property(data[0], "tokenName")
assert.property(data[0], "tokenDocumentUrl")
assert.property(data[0], "tokenDocumentHash")
assert.property(data[0], "decimals")
assert.property(data[0], "mintBatonVout")
assert.property(data[0], "tokenQty")
assert.property(data[0], "isValid")
assert.equal(data[0].isValid, true)
})
it("should return details for a simple SEND SLP token utxo", async () => {
const utxos = [
{
txid:
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
vout: 1,
amount: 0.00000546,
satoshis: 546,
height: 596089,
confirmations: 748
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.property(data[0], "txid")
assert.property(data[0], "vout")
assert.property(data[0], "amount")
assert.property(data[0], "satoshis")
assert.property(data[0], "height")
assert.property(data[0], "confirmations")
assert.property(data[0], "utxoType")
assert.property(data[0], "tokenId")
assert.property(data[0], "tokenTicker")
assert.property(data[0], "tokenName")
assert.property(data[0], "tokenDocumentUrl")
assert.property(data[0], "tokenDocumentHash")
assert.property(data[0], "decimals")
assert.property(data[0], "tokenQty")
assert.property(data[0], "isValid")
assert.equal(data[0].isValid, true)
})
it("should handle BCH and SLP utxos in the same TX", async () => {
const utxos = [
{
txid:
"d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56",
vout: 3,
value: "6816",
height: 606848,
confirmations: 13,
satoshis: 6816
},
{
txid:
"d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56",
vout: 2,
value: "546",
height: 606848,
confirmations: 13,
satoshis: 546
}
]
const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result.length, 2)
assert.equal(result[0].isValid, false)
assert.equal(result[1].isValid, true)
})
it("should handle problematic utxos", async () => {
const utxos = [
{
txid:
"0e3a217fc22612002031d317b4cecd9b692b66b52951a67b23c43041aefa3959",
vout: 0,
amount: 0.00018362,
satoshis: 18362,
height: 613483,
confirmations: 124
},
{
txid:
"67fd3c7c3a6eb0fea9ab311b91039545086220f7eeeefa367fa28e6e43009f19",
vout: 1,
amount: 0.00000546,
satoshis: 546,
height: 612075,
confirmations: 1532
}
]
const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result.length, 2)
assert.equal(result[0].isValid, false)
assert.equal(result[1].isValid, true)
})
it("should return false for BCH-only UTXOs", async () => {
const utxos = [
{
txid:
"a937f792c7c9eb23b4f344ce5c233d1ac0909217d0a504d71e6b1e4efb864a3b",
vout: 0,
amount: 0.00001,
satoshis: 1000,
confirmations: 0,
ts: 1578424704
},
{
txid:
"53fd141c2e999e080a5860887441a2c45e9cbe262027e2bd2ac998fc76e43c44",
vout: 0,
amount: 0.00001,
satoshis: 1000,
confirmations: 0,
ts: 1578424634
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.isArray(data)
assert.equal(data[0].isValid, false)
assert.equal(data[1].isValid, false)
})
it("should handle a dust attack", async () => {
// it("#dustattack", async () => {
const utxos = [
{
height: 655965,
tx_hash:
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
tx_pos: 151,
value: 547,
satoshis: 547,
txid:
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
vout: 151,
address: "bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww",
hdIndex: 11
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.equal(data[0].isValid, false)
})
it("should handle a range of UTXO types", async () => {
const utxos = [
// Malformed SLP tx
{
note: "Malformed SLP tx",
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
tx_pos: 1,
value: 546
},
// Normal TX (non-SLP)
{
note: "Normal TX (non-SLP)",
tx_hash:
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
tx_pos: 0,
value: 400000
},
// Valid PSF SLP tx
{
note: "Valid PSF SLP tx",
tx_hash:
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
tx_pos: 1,
value: 546
},
// Valid SLP token not in whitelist
{
note: "Valid SLP token not in whitelist",
tx_hash:
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
tx_pos: 1,
value: 546
},
// Token send on BCHN network.
{
note: "Token send on BCHN network",
tx_hash:
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
tx_pos: 1,
value: 546
},
// Token send on ABC network.
{
note: "Token send on ABC network",
tx_hash:
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
tx_pos: 1,
value: 546
},
// Known invalid SLP token send of PSF tokens.
{
note: "Known invalid SLP token send of PSF tokens",
tx_hash:
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// Malformed SLP tx
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
assert.equal(data[0].isValid, false)
// Normal TX (non-SLP)
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
assert.equal(data[1].isValid, false)
// Valid PSF SLP tx
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
assert.equal(data[2].isValid, true)
// Valid SLP token not in whitelist
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
assert.equal(data[3].isValid, true)
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
assert.equal(data[4].isValid, true)
// Token send on ABC network
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
assert.equal(data[5].isValid, null)
// Known invalid SLP token send of PSF tokens
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
assert.equal(data[6].isValid, false)
})
})
describe("#balancesForAddress", () => {
it(`should throw an error if input is not a string or array of strings`, async () => {
try {
const address = 1234
await bchjs.SLP.Utils.balancesForAddress(address)
assert.equal(true, false, "Uh oh. Code path should not end here.")
} catch (err) {
//console.log(`Error: `, err)
assert.include(
err.message,
`Input address must be a string or array of strings`
)
}
})
it(`should fetch all balances for address: simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9`, async () => {
const balances = await bchjs.SLP.Utils.balancesForAddress(
"simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9"
)
// console.log(`balances: ${JSON.stringify(balances, null, 2)}`)
assert.isArray(balances)
assert.hasAllKeys(balances[0], [
"tokenId",
"balanceString",
"balance",
"decimalCount",
"slpAddress"
])
})
it(`should fetch balances for multiple addresses`, async () => {
const addresses = [
"simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9",
"simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57"
]
const balances = await bchjs.SLP.Utils.balancesForAddress(addresses)
// console.log(`balances: ${JSON.stringify(balances, null, 2)}`)
assert.isArray(balances)
assert.isArray(balances[0])
assert.hasAllKeys(balances[0][0], [
"tokenId",
"balanceString",
"balance",
"decimalCount",
"slpAddress"
])
})
})
describe("#hydrateUtxos", () => {
it("should throw an error if input is not an array", async () => {
try {
const utxos = 1234
await bchjs.SLP.Utils.hydrateUtxos(utxos)
assert.equal(true, false, "Uh oh. Code path should not end here.")
} catch (err) {
// console.log(`Error: `, err)
assert.include(err.message, `Input must be an array.`)
}
})
it("should hydrate UTXOs", async () => {
const utxos = [
{
utxos: [
{
txid:
"d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56",
vout: 3,
value: "6816",
height: 606848,
confirmations: 13,
satoshis: 6816
},
{
txid:
"d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56",
vout: 2,
value: "546",
height: 606848,
confirmations: 13,
satoshis: 546
}
]
}
]
const result = await bchjs.SLP.Utils.hydrateUtxos(utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 1)
assert.equal(result.slpUtxos[0].utxos.length, 2)
// Test the non-slp UTXO.
assert.property(result.slpUtxos[0].utxos[0], "txid")
assert.property(result.slpUtxos[0].utxos[0], "vout")
assert.property(result.slpUtxos[0].utxos[0], "value")
assert.property(result.slpUtxos[0].utxos[0], "height")
assert.property(result.slpUtxos[0].utxos[0], "confirmations")
assert.property(result.slpUtxos[0].utxos[0], "satoshis")
assert.property(result.slpUtxos[0].utxos[0], "isValid")
assert.equal(result.slpUtxos[0].utxos[0].isValid, false)
// Test the slp UTXO.
assert.property(result.slpUtxos[0].utxos[1], "txid")
assert.property(result.slpUtxos[0].utxos[1], "vout")
assert.property(result.slpUtxos[0].utxos[1], "value")
assert.property(result.slpUtxos[0].utxos[1], "height")
assert.property(result.slpUtxos[0].utxos[1], "confirmations")
assert.property(result.slpUtxos[0].utxos[1], "satoshis")
assert.property(result.slpUtxos[0].utxos[1], "isValid")
assert.equal(result.slpUtxos[0].utxos[1].isValid, true)
assert.property(result.slpUtxos[0].utxos[1], "transactionType")
assert.property(result.slpUtxos[0].utxos[1], "tokenId")
assert.property(result.slpUtxos[0].utxos[1], "tokenTicker")
assert.property(result.slpUtxos[0].utxos[1], "tokenName")
assert.property(result.slpUtxos[0].utxos[1], "tokenDocumentUrl")
assert.property(result.slpUtxos[0].utxos[1], "tokenDocumentHash")
assert.property(result.slpUtxos[0].utxos[1], "decimals")
assert.property(result.slpUtxos[0].utxos[1], "tokenType")
assert.property(result.slpUtxos[0].utxos[1], "tokenQty")
})
it("should process data directly from Electrumx", async () => {
const addrs = [
"bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp",
"bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5",
"bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495"
]
const utxos = await bchjs.Electrumx.utxo(addrs)
// console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
const result = await bchjs.SLP.Utils.hydrateUtxos(utxos.utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 3)
assert.equal(result.slpUtxos[0].utxos.length, 1)
assert.equal(result.slpUtxos[1].utxos.length, 1)
assert.equal(result.slpUtxos[2].utxos.length, 2)
try {
// Test the expected values.
assert.equal(result.slpUtxos[0].utxos[0].isValid, false)
assert.equal(result.slpUtxos[1].utxos[0].isValid, true)
assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, "TROUT")
assert.equal(result.slpUtxos[2].utxos[0].isValid, false)
assert.equal(result.slpUtxos[2].utxos[1].isValid, true)
assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, "VALENTINE")
} catch (err) {
console.error(
'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"'
)
console.log("Error: ", err)
}
})
})
describe("#validateTxid2", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid2(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "txid")
assert.equal(result.txid, txid)
assert.property(result, "isValid")
assert.equal(result.isValid, false)
})
it("should validate a known valid TXID", async () => {
const txid =
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488"
const result = await bchjs.SLP.Utils.validateTxid2(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "txid")
assert.equal(result.txid, txid)
assert.property(result, "isValid")
assert.equal(result.isValid, true)
})
})
describe("#getWhitelist", () => {
it("should get the whitelist", async () => {
const result = await bchjs.SLP.Utils.getWhitelist()
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "name")
assert.property(result[1], "tokenId")
})
})
describe("#validateTxid3", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should validate a known valid TXID", async () => {
const txid =
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
// Known invalid SLP token send of PSF tokens.
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74"
]
const result = await bchjs.SLP.Utils.validateTxid3(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid() but null in validateTxid3()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, null)
// Note: This should change from null to true once SLPDB finishes indexing.
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, null)
assert.equal(result[5].txid, txids[5])
assert.equal(result[5].valid, null)
assert.equal(result[6].txid, txids[6])
assert.equal(result[6].valid, false)
assert.include(
result[6].invalidReason,
"Token outputs are greater than valid token inputs"
)
})
})
describe("#validateTxid", () => {
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
// Known invalid SLP token send of PSF tokens.
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74"
]
const result = await bchjs.SLP.Utils.validateTxid(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid() but null in validateTxid3()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, true)
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, true)
assert.equal(result[5].txid, txids[5])
assert.equal(result[5].valid, null)
assert.equal(result[6].txid, txids[6])
assert.equal(result[6].valid, false)
assert.include(
result[6].invalidReason,
"Token outputs are greater than valid token inputs"
)
})
})
})
describe("#tokentype1", () => {
describe("#getHexOpReturn", () => {
it("should return OP_RETURN object ", async () => {
const tokenUtxos = [
{
tokenId:
"0a321bff9761f28e06a268b14711274bb77617410a16807bd0437ef234a072b1",
decimals: 0,
tokenQty: 2
}
]
const sendQty = 1.5
const result = await bchjs.SLP.TokenType1.getHexOpReturn(
tokenUtxos,
sendQty
)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "script")
assert.isString(result.script)
assert.property(result, "outputs")
assert.isNumber(result.outputs)
})
})
})
})
// Promise-based sleep function
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
-109
View File
@@ -1,109 +0,0 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe(`#util`, () => {
describe(`#validateAddress`, () => {
it(`should return false for testnet addr on mainnet`, async () => {
const address = `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y`
const result = await bchjs.Util.validateAddress(address)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, ["isvalid"])
assert.equal(result.isvalid, false)
})
it(`should return false for bad address`, async () => {
const address = `bitcoincash:qp4k8fjtgunhdr7yq30ha4peu`
const result = await bchjs.Util.validateAddress(address)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAllKeys(result, ["isvalid"])
assert.equal(result.isvalid, false)
})
it(`should validate valid address`, async () => {
const address = `bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z`
const result = await bchjs.Util.validateAddress(address)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, [
"isvalid",
"address",
"scriptPubKey",
//"ismine",
//"iswatchonly",
"isscript"
])
assert.equal(result.isvalid, true)
})
it(`should validate an array of addresses`, async () => {
const address = [
`bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z`,
`bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z`
]
const result = await bchjs.Util.validateAddress(address)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"isvalid",
"address",
"scriptPubKey",
//"ismine",
//"iswatchonly",
"isscript"
])
})
it(`should throw an error for improper single input`, async () => {
try {
const address = 15432
await bchjs.Util.validateAddress(address)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input must be a string or array of strings.`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const dataMock = `bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z`
const data = []
for (let i = 0; i < 25; i++) data.push(dataMock)
const result = await bchjs.Util.validateAddress(data)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
})
@@ -0,0 +1,71 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
TODO
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe("#rawtransaction", () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
})
/*
Testing sentRawTransaction isn't really possible with an integration test,
as the endpoint really needs an e2e test to be properly tested. The tests
below expect error messages returned from the server, but at least test
that the server is responding on those endpoints, and responds consistently.
*/
describe("sendRawTransaction", () => {
it("should send a single transaction hex", async () => {
try {
const hex =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
await bchjs.RawTransactions.sendRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent")
}
})
it("should send an array of tx hexes", async () => {
try {
const hexes = [
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000",
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
]
const result = await bchjs.RawTransactions.sendRawTransaction(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
} catch (err) {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent")
}
})
})
})
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
+223
View File
@@ -0,0 +1,223 @@
/*
Integration tests for the bchjs covering SLP tokens.
These tests are specific to the ABC chain.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
let bchjs
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 1
}
describe(`#SLP`, () => {
// before(() => {
// console.log(`bchjs.SLP.restURL: ${bchjs.SLP.restURL}`)
// console.log(`bchjs.SLP.apiToken: ${bchjs.SLP.apiToken}`)
// })
beforeEach(async () => {
// Introduce a delay so that the BVT doesn't trip the rate limits.
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
bchjs = new BCHJS()
})
describe("#util", () => {
describe("#tokenUtxoDetails", () => {
it("should handle a range of UTXO types", async () => {
const utxos = [
// Malformed SLP tx
{
note: "Malformed SLP tx",
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
tx_pos: 1,
value: 546
},
// Normal TX (non-SLP)
{
note: "Normal TX (non-SLP)",
tx_hash:
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
tx_pos: 0,
value: 400000
},
// Valid PSF SLP tx
{
note: "Valid PSF SLP tx",
tx_hash:
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
tx_pos: 1,
value: 546
},
// Valid SLP token not in whitelist
{
note: "Valid SLP token not in whitelist",
tx_hash:
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
tx_pos: 1,
value: 546
},
// Token send on BCHN network.
{
note: "Token send on BCHN network",
tx_hash:
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
tx_pos: 1,
value: 546
},
// Token send on ABC network.
{
note: "Token send on ABC network",
tx_hash:
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
tx_pos: 1,
value: 546
},
// Known invalid SLP token send of PSF tokens.
{
note: "Known invalid SLP token send of PSF tokens",
tx_hash:
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// Malformed SLP tx
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
assert.equal(data[0].isValid, false)
// Normal TX (non-SLP)
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
assert.equal(data[1].isValid, false)
// Valid PSF SLP tx
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
assert.equal(data[2].isValid, true)
// Valid SLP token not in whitelist
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
assert.equal(data[3].isValid, true)
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
assert.equal(data[4].isValid, null)
// Token send on ABC network
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
assert.equal(data[5].isValid, true)
// Known invalid SLP token send of PSF tokens
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
assert.equal(data[6].isValid, false)
})
})
describe("#validateTxid3", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should validate a known valid TXID", async () => {
const txid =
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Unprocessed SLP TX
// "a0d6406eecfd8634158efa9314ff15b4cbf451938e9dc7b5678c46b41eabc6ed" // Mint baton
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019"
]
const result = await bchjs.SLP.Utils.validateTxid3(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].valid, null)
assert.equal(result[1].valid, null)
assert.equal(result[2].valid, true)
assert.equal(result[3].valid, true)
assert.equal(result[4].valid, null)
})
})
describe("#validateTxid", () => {
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d"
]
const result = await bchjs.SLP.Utils.validateTxid(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].valid, null)
assert.equal(result[1].valid, null)
assert.equal(result[2].valid, true)
assert.equal(result[3].valid, true)
assert.equal(result[4].valid, null)
assert.equal(result[5].valid, true)
})
})
})
})
// Promise-based sleep function
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
@@ -0,0 +1,71 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
TODO
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe("#rawtransaction", () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
})
/*
Testing sentRawTransaction isn't really possible with an integration test,
as the endpoint really needs an e2e test to be properly tested. The tests
below expect error messages returned from the server, but at least test
that the server is responding on those endpoints, and responds consistently.
*/
describe("sendRawTransaction", () => {
it("should send a single transaction hex", async () => {
try {
const hex =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
await bchjs.RawTransactions.sendRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
it("should send an array of tx hexes", async () => {
try {
const hexes = [
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000",
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
]
const result = await bchjs.RawTransactions.sendRawTransaction(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
} catch (err) {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
})
})
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
+247
View File
@@ -0,0 +1,247 @@
/*
Integration tests for the bchjs covering SLP tokens.
These tests are specific to the ABC chain.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
let bchjs
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 1
}
describe(`#SLP`, () => {
// before(() => {
// console.log(`bchjs.SLP.restURL: ${bchjs.SLP.restURL}`)
// console.log(`bchjs.SLP.apiToken: ${bchjs.SLP.apiToken}`)
// })
beforeEach(async () => {
// Introduce a delay so that the BVT doesn't trip the rate limits.
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
bchjs = new BCHJS()
})
describe("#util", () => {
describe("#tokenUtxoDetails", () => {
it("should handle a range of UTXO types", async () => {
const utxos = [
// Malformed SLP tx
{
note: "Malformed SLP tx",
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
tx_pos: 1,
value: 546
},
// Normal TX (non-SLP)
{
note: "Normal TX (non-SLP)",
tx_hash:
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
tx_pos: 0,
value: 400000
},
// Valid PSF SLP tx
{
note: "Valid PSF SLP tx",
tx_hash:
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
tx_pos: 1,
value: 546
},
// Valid SLP token not in whitelist
{
note: "Valid SLP token not in whitelist",
tx_hash:
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
tx_pos: 1,
value: 546
},
// Token send on BCHN network.
{
note: "Token send on BCHN network",
tx_hash:
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
tx_pos: 1,
value: 546
},
// Token send on ABC network.
{
note: "Token send on ABC network",
tx_hash:
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
tx_pos: 1,
value: 546
},
// Known invalid SLP token send of PSF tokens.
{
note: "Known invalid SLP token send of PSF tokens",
tx_hash:
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// Malformed SLP tx
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
assert.equal(data[0].isValid, false)
// Normal TX (non-SLP)
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
assert.equal(data[1].isValid, false)
// Valid PSF SLP tx
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
assert.equal(data[2].isValid, true)
// Valid SLP token not in whitelist
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
assert.equal(data[3].isValid, true)
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
assert.equal(data[4].isValid, true)
// Token send on ABC network
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
assert.equal(data[5].isValid, null)
// Known invalid SLP token send of PSF tokens
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
assert.equal(data[6].isValid, false)
})
})
describe("#validateTxid3", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should validate a known valid TXID", async () => {
const txid =
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Unprocessed SLP TX
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019"
]
const result = await bchjs.SLP.Utils.validateTxid3(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid() but null in validateTxid3()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, null)
// Note: This should change from null to true once SLPDB finishes indexing.
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, null)
})
})
describe("#validateTxid", () => {
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d"
]
const result = await bchjs.SLP.Utils.validateTxid(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid() but null in validateTxid3()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, true)
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, true)
assert.equal(result[5].txid, txids[5])
assert.equal(result[5].valid, null)
})
})
})
})
// Promise-based sleep function
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
@@ -15,7 +15,7 @@ const RESTURL = process.env.RESTURL
: "https://testnet3.fullstack.cash/v4/"
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v4/` })
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
@@ -9,7 +9,7 @@ const RESTURL = process.env.RESTURL
? process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
describe(`#control`, () => {
@@ -6,7 +6,7 @@ const RESTURL = process.env.RESTURL
? process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
describe(`#ElectrumX`, () => {
@@ -2,7 +2,7 @@ const chai = require("chai")
const assert = chai.assert
const sinon = require("sinon")
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS({ ninsightURL: "https://trest.bitcoin.com/v2" })
describe(`#Ninsight`, () => {
@@ -105,7 +105,8 @@ describe(`#Ninsight`, () => {
})
describe(`#txDetails`, () => {
it(`should POST transactions details for a single address`, async () => {
const txid = "76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea"
const txid =
"76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea"
const result = await bchjs.Ninsight.txDetails(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
@@ -13,7 +13,7 @@ const RESTURL = process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v4/` })
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
@@ -251,7 +251,7 @@ describe("#rawtransaction", () => {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent (code 16)")
assert.include(err.error, "Missing inputs")
}
})
@@ -268,7 +268,7 @@ describe("#rawtransaction", () => {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent (code 16)")
assert.include(err.error, "Missing inputs")
}
})
@@ -10,7 +10,7 @@ const RESTURL = process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v4/` })
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
@@ -11,7 +11,7 @@ const RESTURL = process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
const BCHJS = require("../../../src/bch-js")
const BCHJS = require("../../../../src/bch-js")
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v4/` })
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
@@ -0,0 +1,71 @@
/*
Integration tests for the bchjs. Only covers calls made to
rest.bitcoin.com.
TODO
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
const bchjs = new BCHJS()
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe("#rawtransaction", () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
})
/*
Testing sentRawTransaction isn't really possible with an integration test,
as the endpoint really needs an e2e test to be properly tested. The tests
below expect error messages returned from the server, but at least test
that the server is responding on those endpoints, and responds consistently.
*/
describe("sendRawTransaction", () => {
it("should send a single transaction hex", async () => {
try {
const hex =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
await bchjs.RawTransactions.sendRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
it("should send an array of tx hexes", async () => {
try {
const hexes = [
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000",
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
]
const result = await bchjs.RawTransactions.sendRawTransaction(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
} catch (err) {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "Missing inputs")
}
})
})
})
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
@@ -0,0 +1,246 @@
/*
Integration tests for the bchjs covering SLP tokens.
These tests are specific to the ABC chain.
*/
const chai = require("chai")
const assert = chai.assert
const BCHJS = require("../../../../src/bch-js")
let bchjs
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 1
}
describe(`#SLP`, () => {
// before(() => {
// console.log(`bchjs.SLP.restURL: ${bchjs.SLP.restURL}`)
// console.log(`bchjs.SLP.apiToken: ${bchjs.SLP.apiToken}`)
// })
beforeEach(async () => {
// Introduce a delay so that the BVT doesn't trip the rate limits.
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
bchjs = new BCHJS()
})
describe("#util", () => {
describe("#tokenUtxoDetails", () => {
it("should handle a range of UTXO types", async () => {
const utxos = [
// Malformed SLP tx
{
note: "Malformed SLP tx",
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
tx_pos: 1,
value: 546
},
// Normal TX (non-SLP)
{
note: "Normal TX (non-SLP)",
tx_hash:
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
tx_pos: 0,
value: 400000
},
// Valid PSF SLP tx
{
note: "Valid PSF SLP tx",
tx_hash:
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
tx_pos: 1,
value: 546
},
// Valid SLP token not in whitelist
{
note: "Valid SLP token not in whitelist",
tx_hash:
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
tx_pos: 1,
value: 546
},
// Token send on BCHN network.
{
note: "Token send on BCHN network",
tx_hash:
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
tx_pos: 1,
value: 546
},
// Token send on ABC network.
{
note: "Token send on ABC network",
tx_hash:
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
tx_pos: 1,
value: 546
},
// Known invalid SLP token send of PSF tokens.
{
note: "Known invalid SLP token send of PSF tokens",
tx_hash:
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// Malformed SLP tx
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
assert.equal(data[0].isValid, false)
// Normal TX (non-SLP)
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
assert.equal(data[1].isValid, false)
// Valid PSF SLP tx
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
assert.equal(data[2].isValid, true)
// Valid SLP token not in whitelist
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
assert.equal(data[3].isValid, true)
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
assert.equal(data[4].isValid, true)
// Token send on ABC network
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
assert.equal(data[5].isValid, null)
// Known invalid SLP token send of PSF tokens
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
assert.equal(data[6].isValid, false)
})
})
describe("#validateTxid3", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should validate a known valid TXID", async () => {
const txid =
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Unprocessed SLP TX
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019"
]
const result = await bchjs.SLP.Utils.validateTxid3(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, true)
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, true)
})
})
describe("#validateTxid", () => {
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d"
]
const result = await bchjs.SLP.Utils.validateTxid(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.equal(result[0].txid, txids[0])
assert.equal(result[0].valid, null)
assert.equal(result[1].txid, txids[1])
assert.equal(result[1].valid, null)
assert.equal(result[2].txid, txids[2])
assert.equal(result[2].valid, true)
// True in validateTxid() but null in validateTxid3()
assert.equal(result[3].txid, txids[3])
assert.equal(result[3].valid, true)
assert.equal(result[4].txid, txids[4])
assert.equal(result[4].valid, true)
assert.equal(result[5].txid, txids[5])
assert.equal(result[5].valid, null)
})
})
})
})
// Promise-based sleep function
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
-34
View File
@@ -231,40 +231,6 @@ describe("#rawtransaction", () => {
that the server is responding on those endpoints, and responds consistently.
*/
describe("sendRawTransaction", () => {
it("should send a single transaction hex", async () => {
try {
const hex =
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
await bchjs.RawTransactions.sendRawTransaction(hex)
//console.log(`result ${JSON.stringify(result, null, 2)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent")
}
})
it("should send an array of tx hexes", async () => {
try {
const hexes = [
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000",
"01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"
]
const result = await bchjs.RawTransactions.sendRawTransaction(hexes)
console.log(`result ${JSON.stringify(result, null, 2)}`)
} catch (err) {
// console.log(`err: ${util.inspect(err)}`)
assert.hasAllKeys(err, ["error"])
assert.include(err.error, "bad-txns-inputs-missingorspent")
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const dataMock =
+156 -150
View File
@@ -464,96 +464,26 @@ describe(`#SLP`, () => {
assert.equal(data[0].isValid, false)
})
it("should handle a range of UTXO types", async () => {
it("should handle null SLPDB validations", async () => {
const utxos = [
// Malformed SLP tx
{
note: "Malformed SLP tx",
height: 665577,
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
"4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419",
tx_pos: 1,
value: 546
},
// Normal TX (non-SLP)
{
note: "Normal TX (non-SLP)",
tx_hash:
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
tx_pos: 0,
value: 400000
},
// Valid PSF SLP tx
{
note: "Valid PSF SLP tx",
tx_hash:
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
tx_pos: 1,
value: 546
},
// Valid SLP token not in whitelist
{
note: "Valid SLP token not in whitelist",
height: 665577,
tx_hash:
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
tx_pos: 1,
value: 546
},
// Token send on BCHN network.
{
note: "Token send on BCHN network",
tx_hash:
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
tx_pos: 1,
value: 546
},
// Token send on ABC network.
{
note: "Token send on ABC network",
tx_hash:
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d",
tx_pos: 1,
value: 546
},
// Known invalid SLP token send of PSF tokens.
{
note: "Known invalid SLP token send of PSF tokens",
tx_hash:
"2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// Malformed SLP tx
assert.equal(data[0].tx_hash, utxos[0].tx_hash)
assert.equal(data[0].isValid, false)
// Normal TX (non-SLP)
assert.equal(data[1].tx_hash, utxos[1].tx_hash)
assert.equal(data[1].isValid, false)
// Valid PSF SLP tx
assert.equal(data[2].tx_hash, utxos[2].tx_hash)
assert.equal(data[2].isValid, true)
// Valid SLP token not in whitelist
assert.equal(data[3].tx_hash, utxos[3].tx_hash)
assert.equal(data[3].isValid, true)
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
assert.equal(data[4].isValid, null)
// Token send on ABC network
assert.equal(data[5].tx_hash, utxos[5].tx_hash)
assert.equal(data[5].isValid, true)
// Known invalid SLP token send of PSF tokens
assert.equal(data[6].tx_hash, utxos[6].tx_hash)
assert.equal(data[6].isValid, false)
console.log(`data: ${JSON.stringify(data, null, 2)}`)
})
})
@@ -695,6 +625,82 @@ describe(`#SLP`, () => {
console.log("Error: ", err)
}
})
it("should handle null SLPDB validations", async () => {
const utxos = [
{
height: 665577,
tx_hash:
"4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419",
tx_pos: 1,
value: 546
},
{
height: 665577,
tx_hash:
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.hydrateUtxos([{ utxos: utxos }])
console.log(`data: ${JSON.stringify(data, null, 2)}`)
})
})
describe("#validateTxid", () => {
/*
it("should return null on a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
const result = await bchjs.SLP.Utils.validateTxid(txid)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should return true a known valid TXID", async () => {
const txid =
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488"
const result = await bchjs.SLP.Utils.validateTxid(txid)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
*/
// This test is not necessary.
it("should handle a null response from SLPDB", async () => {
const txid =
"4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419"
const result = await bchjs.SLP.Utils.validateTxid(txid)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
})
it("should handle a null response from SLPDB", async () => {
const txid = [
"4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419",
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488"
]
const result = await bchjs.SLP.Utils.validateTxid(txid)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
})
})
describe("#validateTxid2", () => {
@@ -738,82 +744,82 @@ describe(`#SLP`, () => {
})
})
describe("#validateTxid3", () => {
it("should invalidate a known invalid TXID", async () => {
const txid =
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
// describe("#validateTxid3", () => {
// it("should invalidate a known invalid TXID", async () => {
// const txid =
// "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a"
//
// const result = await bchjs.SLP.Utils.validateTxid3(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
//
// assert.property(result[0], "txid")
// assert.equal(result[0].txid, txid)
//
// assert.property(result[0], "valid")
// assert.equal(result[0].valid, null)
// })
//
// it("should validate a known valid TXID", async () => {
// const txid =
// "daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
//
// const result = await bchjs.SLP.Utils.validateTxid3(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
//
// assert.property(result[0], "txid")
// assert.equal(result[0].txid, txid)
//
// assert.property(result[0], "valid")
// assert.equal(result[0].valid, true)
// })
//
// it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
// const txids = [
// // Malformed SLP tx
// "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// // Normal TX (non-SLP)
// "01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// // Valid PSF SLP tx
// "daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// // Valid SLP token not in whitelist
// "3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// // Unprocessed SLP TX
// // "a0d6406eecfd8634158efa9314ff15b4cbf451938e9dc7b5678c46b41eabc6ed" // Mint baton
// "402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019"
// ]
//
// const result = await bchjs.SLP.Utils.validateTxid3(txids)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
// })
// })
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, null)
})
it("should validate a known valid TXID", async () => {
const txid =
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd"
const result = await bchjs.SLP.Utils.validateTxid3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], "txid")
assert.equal(result[0].txid, txid)
assert.property(result[0], "valid")
assert.equal(result[0].valid, true)
})
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Unprocessed SLP TX
// "a0d6406eecfd8634158efa9314ff15b4cbf451938e9dc7b5678c46b41eabc6ed" // Mint baton
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019"
]
const result = await bchjs.SLP.Utils.validateTxid3(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
})
describe("#validateTxid", () => {
it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
const txids = [
// Malformed SLP tx
"f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// Normal TX (non-SLP)
"01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// Valid PSF SLP tx
"daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// Valid SLP token not in whitelist
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// Unprocessed SLP TX
// "a0d6406eecfd8634158efa9314ff15b4cbf451938e9dc7b5678c46b41eabc6ed"
// Token send on BCHN network.
"402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// Token send on ABC network.
"336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d"
]
const result = await bchjs.SLP.Utils.validateTxid(txids)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
})
})
})
// describe("#validateTxid", () => {
// it("should handle a mix of valid, invalid, and non-SLP txs", async () => {
// const txids = [
// // Malformed SLP tx
// "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
// // Normal TX (non-SLP)
// "01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
// // Valid PSF SLP tx
// "daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
// // Valid SLP token not in whitelist
// "3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
// // Unprocessed SLP TX
// // "a0d6406eecfd8634158efa9314ff15b4cbf451938e9dc7b5678c46b41eabc6ed"
// // Token send on BCHN network.
// "402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019",
// // Token send on ABC network.
// "336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d"
// ]
//
// const result = await bchjs.SLP.Utils.validateTxid(txids)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// })
// })
})
describe("#tokentype1", () => {
@@ -1,9 +0,0 @@
#!/bin/bash
# export RESTURL=https://bchn.fullstack.cash/v4/
#export RESTURL=http://localhost:3000/v4/
#export IS_USING_FREE_TIER=true
cd test/integration/bchn/
mocha --timeout 30000 blockchain.js control.js encryption.js electrumx.js ninsight.js openbazaar.js price.js rawtransaction.js slp.js util.js
#mocha --timeout 30000 slp.js
-186
View File
@@ -1,186 +0,0 @@
/*
Integration tests for the Blockbook library.
*/
const chai = require("chai")
const assert = chai.assert
const RESTURL = process.env.RESTURL
? process.env.RESTURL
: `https://testnet3.fullstack.cash/v4/`
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
const BCHJS = require("../../../src/bch-js")
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v4/` })
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
// const bchjs = new BCHJS({ restURL: RESTURL })
//const axios = require("axios")
// Inspect utility used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true,
depth: 3
}
describe(`#Blockbook`, () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
})
describe(`#Balance`, () => {
it(`should GET balance for a single address`, async () => {
const addr = "bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2"
const result = await bchjs.Blockbook.balance(addr)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAnyKeys(result, [
"page",
"totalPages",
"itemsOnPage",
"address",
"balance",
"totalReceived",
"totalSent",
"unconfirmedBalance",
"unconfirmedTxs",
"txs",
"txids"
])
assert.isArray(result.txids)
})
it(`should POST request balances for an array of addresses`, async () => {
const addr = [
"bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2",
"bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2"
]
const result = await bchjs.Blockbook.balance(addr)
//console.log(`result: ${util.inspect(result)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"page",
"totalPages",
"itemsOnPage",
"address",
"balance",
"totalReceived",
"totalSent",
"unconfirmedBalance",
"unconfirmedTxs",
"txs",
"txids"
])
assert.isArray(result[0].txids)
})
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.Blockbook.balance(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input address must be a string or array of strings`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2")
const result = await bchjs.Blockbook.balance(addr)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
describe(`#utxo`, () => {
it(`should GET utxos for a single address`, async () => {
const addr = "bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2"
const result = await bchjs.Blockbook.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.hasAnyKeys(result[0], [
"txid",
"vout",
"value",
"height",
"confirmations"
])
})
it(`should POST utxo details for an array of addresses`, async () => {
const addr = [
"bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2",
"bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2"
]
const result = await bchjs.Blockbook.utxo(addr)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isArray(result[0])
assert.hasAnyKeys(result[0][0], [
"txid",
"vout",
"value",
"height",
"confirmations"
])
})
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.Blockbook.utxo(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err: `, err)
assert.include(
err.message,
`Input address must be a string or array of strings`
)
}
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2")
await bchjs.Blockbook.utxo(addr)
//console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
})
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
+58
View File
@@ -1771,6 +1771,64 @@ describe("#SLP Utils", () => {
// The UTXO should have been validated by the third validation source.
assert.equal(data[0].isValid, true)
})
it("should handle SLPDB returning null corner case", async () => {
// Mock the call to REST API
// Stub the calls to decodeOpReturn.
sandbox
.stub(uut.Utils, "decodeOpReturn")
.onCall(0)
.resolves({
tokenType: 1,
txType: "SEND",
tokenId:
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
amounts: ["200000000", "99887500000000"]
})
.onCall(1)
.resolves({
tokenType: 1,
txType: "GENESIS",
ticker: "TOK-CH",
name: "TokyoCash",
tokenId:
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
documentUri: "",
documentHash: "",
decimals: 8,
mintBatonVout: 0,
qty: "2100000000000000"
})
// Force default SLPDB to return 'null' corner case.
sandbox.stub(uut.Utils, "validateTxid").resolves([null])
// Mock the response from slp-api
sandbox.stub(uut.Utils, "validateTxid2").resolves({
txid:
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
isValid: true,
msg: ""
})
const utxos = [
{
txid:
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
vout: 1,
amount: 0.00000546,
satoshis: 546,
height: 596089,
confirmations: 748
}
]
const data = await uut.Utils.tokenUtxoDetails(utxos)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
// The UTXO should have been validated by the third validation source.
assert.equal(data[0].isValid, true)
})
})
describe("#txDetails", () => {