mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-22 00:52:01 -07:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bcbd7bfd8 | ||
|
|
788b07914e | ||
|
|
9aefdbf6be | ||
|
|
481c254061 | ||
|
|
bc62510b28 | ||
|
|
a71192257e | ||
|
|
0fd9f9ec89 | ||
|
|
97361b8edd | ||
|
|
263ee1b6e1 |
@@ -2,7 +2,6 @@ node_modules/*
|
||||
.nyc_output/*
|
||||
wallet-info.txt
|
||||
wallet.json
|
||||
integration-test-sweet.sh
|
||||
|
||||
docs/
|
||||
coverage/
|
||||
|
||||
Generated
+714
-812
File diff suppressed because it is too large
Load Diff
+13
-14
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@psf/bch-js",
|
||||
"version": "4.0.0",
|
||||
"version": "3.4.0",
|
||||
"description": "The FullStack.cash JavaScript library for Bitcoin Cash and SLP Tokens",
|
||||
"author": "Chris Troutner <chris.troutner@gmail.com>",
|
||||
"contributors": [
|
||||
@@ -8,16 +8,16 @@
|
||||
],
|
||||
"main": "src/bch-js",
|
||||
"scripts": {
|
||||
"test": "nyc mocha --trace-warnings --unhandled-rejections=strict --timeout 30000 test/unit/",
|
||||
"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:temp": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#getStatus' test/integration/",
|
||||
"test:temp2": "mocha --timeout 30000 -g '#getStatus' test/unit/",
|
||||
"test": "nyc mocha --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/v3/ 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:local": "RESTURL=http://localhost:3000/v3/ mocha --timeout 30000 test/integration",
|
||||
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v3/ bash test/integration/test-free-tier-bchn.sh",
|
||||
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v3/ mocha --timeout 30000 test/integration/testnet",
|
||||
"test:temp": "mocha --timeout 30000 -g '#Encryption' test/integration/",
|
||||
"test:integration:api": "RESTURL=https://api.fullstack.cash/v3/ mocha --timeout 30000 test/integration",
|
||||
"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"
|
||||
@@ -59,7 +59,7 @@
|
||||
"ecurve": "^1.0.6",
|
||||
"figlet": "^1.2.0",
|
||||
"git-clone": "^0.1.0",
|
||||
"ini": "^1.3.8",
|
||||
"ini": "^1.3.5",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-cmd": "^3.0.0",
|
||||
"node-emoji": "^1.8.1",
|
||||
@@ -82,13 +82,12 @@
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-plugin-node": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"mocha": "^6.1.4",
|
||||
"nock": "^10.0.6",
|
||||
"node-mocks-http": "^1.7.0",
|
||||
"nyc": "^14.1.0",
|
||||
"prettier": "^1.18.2",
|
||||
"semantic-release": "^17.3.0",
|
||||
"semantic-release": "^15.13.19",
|
||||
"sinon": "^7.3.2"
|
||||
},
|
||||
"apidoc": {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ const coininfo = require("coininfo")
|
||||
class Address {
|
||||
constructor(config) {
|
||||
const tmp = {}
|
||||
if (!config || !config.restURL) tmp.restURL = `https://api.bchjs.cash/v4/`
|
||||
if (!config || !config.restURL) tmp.restURL = `https://api.bchjs.cash/v3/`
|
||||
else tmp.restURL = config.restURL
|
||||
|
||||
this.restURL = tmp.restURL
|
||||
|
||||
+9
-2
@@ -7,8 +7,8 @@
|
||||
*/
|
||||
|
||||
// bch-api mainnet.
|
||||
const DEFAULT_REST_API = "https://api.fullstack.cash/v4/"
|
||||
// const DEFAULT_REST_API = "http://localhost:3000/v4/"
|
||||
// const DEFAULT_REST_API = "https://api.bchjs.cash/v3/"
|
||||
const DEFAULT_REST_API = "https://api.fullstack.cash/v3/"
|
||||
|
||||
// local deps
|
||||
const BitcoinCash = require("./bitcoincash")
|
||||
@@ -34,6 +34,7 @@ const IPFS = require("./ipfs")
|
||||
const Encryption = require("./encryption")
|
||||
|
||||
// Indexers
|
||||
const Blockbook = require("./blockbook")
|
||||
const OpenBazaar = require("./openbazaar")
|
||||
const Ninsight = require("./ninsight")
|
||||
const Electrumx = require("./electrumx")
|
||||
@@ -79,6 +80,9 @@ class BCHJS {
|
||||
|
||||
// console.log(`apiToken: ${this.apiToken}`)
|
||||
|
||||
// Populate Blockbook endpoints.
|
||||
this.Blockbook = new Blockbook(libConfig)
|
||||
|
||||
// Populate OpenBazaar endpoints
|
||||
this.OpenBazaar = new OpenBazaar(libConfig)
|
||||
|
||||
@@ -190,6 +194,9 @@ class BitboxShim {
|
||||
this.Mining = new Mining(libConfig)
|
||||
this.RawTransactions = new RawTransactions(libConfig)
|
||||
|
||||
// Populate Blockbook endpoints.
|
||||
this.Blockbook = new Blockbook(libConfig)
|
||||
|
||||
// Populate OpenBazaar endpoints
|
||||
this.OpenBazaar = new OpenBazaar(libConfig)
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
This library interacts with the REST API endpoints in bch-api that communicate
|
||||
with the Blockbook API.
|
||||
|
||||
CT 11/10/20
|
||||
These endpoints will be soon be deprecated. Blockbook is being fazed out in
|
||||
favor of Fulcrum.
|
||||
*/
|
||||
|
||||
const axios = require("axios")
|
||||
|
||||
let _this
|
||||
|
||||
class Blockbook {
|
||||
constructor(config) {
|
||||
this.restURL = config.restURL
|
||||
this.apiToken = config.apiToken
|
||||
this.authToken = config.authToken
|
||||
// console.log(`Blockbook apiToken: ${this.apiToken}`)
|
||||
|
||||
if (this.authToken) {
|
||||
// Add Basic Authentication token to the authorization header.
|
||||
this.axiosOptions = {
|
||||
headers: {
|
||||
authorization: this.authToken
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Add JWT token to the authorization header.
|
||||
this.axiosOptions = {
|
||||
headers: {
|
||||
authorization: `Token ${this.apiToken}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_this = this
|
||||
}
|
||||
|
||||
async balance(address) {
|
||||
try {
|
||||
// Handle single address.
|
||||
if (typeof address === "string") {
|
||||
const response = await axios.get(
|
||||
`${this.restURL}blockbook/balance/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
|
||||
// Handle array of addresses.
|
||||
} else if (Array.isArray(address)) {
|
||||
const response = await axios.post(
|
||||
`${this.restURL}blockbook/balance`,
|
||||
{
|
||||
addresses: address
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
async utxo(address) {
|
||||
try {
|
||||
// Handle single address.
|
||||
if (typeof address === "string") {
|
||||
const response = await axios.get(
|
||||
`${this.restURL}blockbook/utxos/${address}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
return response.data
|
||||
|
||||
// Handle array of addresses.
|
||||
} else if (Array.isArray(address)) {
|
||||
const response = await axios.post(
|
||||
`${this.restURL}blockbook/utxos`,
|
||||
{
|
||||
addresses: address
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
async tx(txid) {
|
||||
try {
|
||||
// Handle single txid.
|
||||
if (typeof txid === "string") {
|
||||
const response = await axios.get(
|
||||
`${this.restURL}blockbook/tx/${txid}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
return response.data
|
||||
|
||||
// Handle array of addresses.
|
||||
} else if (Array.isArray(txid)) {
|
||||
const response = await axios.post(
|
||||
`${this.restURL}blockbook/tx`,
|
||||
{
|
||||
txids: txid
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input txid must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Blockbook
|
||||
+84
-82
@@ -68,34 +68,10 @@ class Ninsight {
|
||||
*/
|
||||
async utxo(address) {
|
||||
try {
|
||||
// Handle single address.
|
||||
if (typeof address === "string") {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/utxo`,
|
||||
{
|
||||
addresses: [address]
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
return response.data
|
||||
|
||||
// Handle array of addresses.
|
||||
} else if (Array.isArray(address)) {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/utxo`,
|
||||
{
|
||||
addresses: address
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
_this._validateParam(address)
|
||||
return _this._callAxios(address, 'utxo')
|
||||
} catch (e) {
|
||||
_this._handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,32 +113,10 @@ class Ninsight {
|
||||
*/
|
||||
async unconfirmed(address) {
|
||||
try {
|
||||
if (typeof address === "string") {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/unconfirmed`,
|
||||
{
|
||||
addresses: [address]
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
} else if (Array.isArray(address)) {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/unconfirmed`,
|
||||
{
|
||||
addresses: address
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
_this._validateParam(address)
|
||||
return _this._callAxios(address, 'unconfirmed')
|
||||
} catch (e) {
|
||||
_this._handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,32 +167,10 @@ class Ninsight {
|
||||
*/
|
||||
async transactions(address) {
|
||||
try {
|
||||
if (typeof address === "string") {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/transactions`,
|
||||
{
|
||||
addresses: [address]
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
} else if (Array.isArray(address)) {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/address/transactions`,
|
||||
{
|
||||
addresses: address
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
_this._validateParam(address)
|
||||
return _this._callAxios(address, 'transactions')
|
||||
} catch (e) {
|
||||
_this._handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +220,7 @@ class Ninsight {
|
||||
try {
|
||||
if (typeof txid === "string") {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/transaction/details`,
|
||||
`${_this.ninsightURL}/transaction/details`,
|
||||
{
|
||||
txids: [txid]
|
||||
},
|
||||
@@ -298,7 +230,7 @@ class Ninsight {
|
||||
return response.data
|
||||
} else if (Array.isArray(txid)) {
|
||||
const response = await axios.post(
|
||||
`${this.ninsightURL}/transaction/details`,
|
||||
`${_this.ninsightURL}/transaction/details`,
|
||||
{
|
||||
txids: txid
|
||||
},
|
||||
@@ -314,6 +246,76 @@ class Ninsight {
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @api Ninsight.details() details()
|
||||
* @apiName Ninsight Details
|
||||
* @apiGroup Ninsight
|
||||
* @apiDescription Return details of address.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* (async () => {
|
||||
* try {
|
||||
* let details = await bchjs.Ninsight.details('bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c');
|
||||
* let details = await bchjs.Ninsight.details(['bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c','bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c']);
|
||||
* console.log(details);
|
||||
* } catch(error) {
|
||||
* console.error(error)
|
||||
* }
|
||||
* })()
|
||||
*
|
||||
* // [
|
||||
* // {
|
||||
* //"balance": 0.00001,
|
||||
* //"balanceSat": 1000,
|
||||
* //"totalReceived": 0.00001,
|
||||
* //"totalReceivedSat": 1000,
|
||||
* //"totalSent": 0,
|
||||
* //"totalSentSat": 0,
|
||||
* //"unconfirmedBalance": 0,
|
||||
* //"unconfirmedBalanceSat": 0,
|
||||
* //"unconfirmedTxApperances": 0,
|
||||
* //"txApperances": 1,
|
||||
* //"transactions": [
|
||||
* //"5f09d317e24c5d376f737a2711f3bd1d381abdb41743fff3819b4f76382e1eac" ],
|
||||
* //"legacyAddress": "1FZrK8HohEKyKCTM24NkAzPnX9WD9Ujhw7",
|
||||
* //"cashAddress": "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr",
|
||||
* //"slpAddress": "simpleledger:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ylynt40sa",
|
||||
* //"currentPage": 0,
|
||||
* //"pagesTotal": 1
|
||||
* // }
|
||||
* // ]
|
||||
*
|
||||
*/
|
||||
async details(address) {
|
||||
try {
|
||||
_this._validateParam(address)
|
||||
return _this._callAxios(address, 'details')
|
||||
} catch (e) {
|
||||
_this._handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
_validateParam(address) {
|
||||
if (typeof address !== "string" && !Array.isArray(address))
|
||||
throw new Error(`Input address must be a string or array of strings.`)
|
||||
}
|
||||
|
||||
_handleError(error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
|
||||
async _callAxios(address, type) {
|
||||
const response = await axios.post(
|
||||
`${_this.ninsightURL}/address/${type}`,
|
||||
{
|
||||
addresses: Array.isArray(address) ? address : [address]
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
//console.log(`SAMPLE: ${response.data}`);
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ninsight
|
||||
|
||||
+20
-36
@@ -29,7 +29,26 @@ class Price {
|
||||
this.axios = axios
|
||||
}
|
||||
|
||||
// This endpoint is deprecated. Documentation removed.
|
||||
/**
|
||||
* @api price.current() current()
|
||||
* @apiName Price.
|
||||
* @apiGroup Price
|
||||
* @apiDescription Return current price of BCH in multiple currencies.
|
||||
* This endpoint will be deprecated in favor of getUSD. It uses the Bitcoin.com
|
||||
* price feed.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*(async () => {
|
||||
* try {
|
||||
* let current = await bchjs.Price.current('usd');
|
||||
* console.log(current);
|
||||
* } catch(err) {
|
||||
* console.err(err)
|
||||
* }
|
||||
*})()
|
||||
*
|
||||
* // 26681
|
||||
*/
|
||||
async current(currency = "usd") {
|
||||
try {
|
||||
const response = await this.axios.get(
|
||||
@@ -121,41 +140,6 @@ class Price {
|
||||
else throw err
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api price.getBchaUsd() getBchaUsd()
|
||||
* @apiName Price getBchaUsd()
|
||||
* @apiGroup Price
|
||||
* @apiDescription Return current price of BCHA in USD.
|
||||
* This endpoint gets the USD price of BCHA from the Coinex API. The price
|
||||
* comes from bch-api, so it has a better chance of working in Tor.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*(async () => {
|
||||
* try {
|
||||
* let current = await bchjs.Price.getBchaUsd();
|
||||
* console.log(current);
|
||||
* } catch(err) {
|
||||
* console.err(err)
|
||||
* }
|
||||
*})()
|
||||
*
|
||||
* // 18.81
|
||||
*/
|
||||
async getBchaUsd() {
|
||||
try {
|
||||
const response = await this.axios.get(
|
||||
`${this.restURL}price/bchausd`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
|
||||
|
||||
return response.data.usd
|
||||
} catch (err) {
|
||||
if (err.response && err.response.data) throw err.response.data
|
||||
else throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Price
|
||||
|
||||
@@ -24,9 +24,6 @@ class RawTransactions {
|
||||
}
|
||||
}
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.axios = axios
|
||||
|
||||
_this = this
|
||||
}
|
||||
|
||||
@@ -325,7 +322,7 @@ class RawTransactions {
|
||||
try {
|
||||
// Single tx hex.
|
||||
if (typeof hex === "string") {
|
||||
const response = await this.axios.get(
|
||||
const response = await axios.get(
|
||||
`${this.restURL}rawtransactions/sendRawTransaction/${hex}`,
|
||||
_this.axiosOptions
|
||||
)
|
||||
@@ -350,7 +347,7 @@ class RawTransactions {
|
||||
},
|
||||
headers: _this.axiosOptions.headers
|
||||
}
|
||||
const response = await _this.axios(options)
|
||||
const response = await axios(options)
|
||||
|
||||
return response.data
|
||||
}
|
||||
|
||||
+17
-29
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
This library handles the OP_RETURN of SLP TokenType1 transactions.
|
||||
*/
|
||||
|
||||
//const BCHJS = require("../bch-js")
|
||||
//const bchjs = new BCHJS()
|
||||
|
||||
@@ -97,16 +93,12 @@ class TokenType1 {
|
||||
const tokenId = tokenUtxos[0].tokenId
|
||||
const decimals = tokenUtxos[0].decimals
|
||||
|
||||
const sendQtyBig = new BigNumber(sendQty).times(10 ** decimals)
|
||||
|
||||
// Calculate the total amount of tokens owned by the wallet.
|
||||
const totalTokens = tokenUtxos.reduce(
|
||||
(tot, txo) =>
|
||||
tot.plus(new BigNumber(txo.tokenQty).times(10 ** decimals)),
|
||||
new BigNumber(0)
|
||||
)
|
||||
let totalTokens = 0
|
||||
for (let i = 0; i < tokenUtxos.length; i++)
|
||||
totalTokens += tokenUtxos[i].tokenQty
|
||||
|
||||
const change = totalTokens.minus(sendQtyBig)
|
||||
const change = totalTokens - sendQty
|
||||
// console.log(`change: ${change}`)
|
||||
|
||||
let script
|
||||
@@ -117,20 +109,19 @@ class TokenType1 {
|
||||
outputs = 2
|
||||
|
||||
// Convert the send quantity to the format expected by slp-mdm.
|
||||
const baseQty = sendQtyBig.toString()
|
||||
let baseQty = new BigNumber(sendQty).times(10 ** decimals)
|
||||
baseQty = baseQty.absoluteValue()
|
||||
baseQty = Math.floor(baseQty)
|
||||
baseQty = baseQty.toString()
|
||||
// console.log(`baseQty: `, baseQty)
|
||||
|
||||
// Convert the change quantity to the format expected by slp-mdm.
|
||||
const baseChange = change.toString()
|
||||
let baseChange = new BigNumber(change).times(10 ** decimals)
|
||||
baseChange = baseChange.absoluteValue()
|
||||
baseChange = Math.floor(baseChange)
|
||||
baseChange = baseChange.toString()
|
||||
// console.log(`baseChange: `, baseChange)
|
||||
|
||||
// Check for potential burns
|
||||
const outputQty = new BigNumber(baseChange).plus(new BigNumber(baseQty))
|
||||
const inputQty = new BigNumber(totalTokens)
|
||||
const tokenOutputDelta = outputQty.minus(inputQty).toString() !== "0"
|
||||
if (tokenOutputDelta)
|
||||
throw "Token transaction inputs do not match outputs, cannot send transaction"
|
||||
|
||||
// Generate the OP_RETURN as a Buffer.
|
||||
script = slpMdm.TokenType1.send(tokenId, [
|
||||
new slpMdm.BN(baseQty),
|
||||
@@ -140,16 +131,13 @@ class TokenType1 {
|
||||
|
||||
// Corner case, when there is no token change to send back.
|
||||
} else {
|
||||
const baseQty = sendQtyBig.toString()
|
||||
let baseQty = new BigNumber(sendQty).times(10 ** decimals)
|
||||
baseQty = baseQty.absoluteValue()
|
||||
baseQty = Math.floor(baseQty)
|
||||
baseQty = baseQty.toString()
|
||||
// console.log(`baseQty: `, baseQty)
|
||||
|
||||
// Check for potential burns
|
||||
const noChangeOutputQty = new BigNumber(baseQty)
|
||||
const noChangeInputQty = new BigNumber(totalTokens)
|
||||
const tokenSingleOutputError =
|
||||
noChangeOutputQty.minus(noChangeInputQty).toString() !== "0"
|
||||
if (tokenSingleOutputError)
|
||||
throw "Token transaction inputs do not match outputs, cannot send transaction"
|
||||
// console.log(`baseQty: ${baseQty.toString()}`)
|
||||
|
||||
// Generate the OP_RETURN as a Buffer.
|
||||
script = slpMdm.TokenType1.send(tokenId, [new slpMdm.BN(baseQty)])
|
||||
|
||||
+43
-364
@@ -1,7 +1,5 @@
|
||||
// Public npm libraries
|
||||
const axios = require("axios")
|
||||
const slpParser = require("slp-parser")
|
||||
const BigNumber = require("bignumber.js")
|
||||
|
||||
// const Script = require("../script")
|
||||
// const scriptLib = new Script()
|
||||
@@ -16,7 +14,6 @@ class Utils {
|
||||
this.apiToken = config.apiToken
|
||||
this.slpParser = slpParser
|
||||
this.authToken = config.authToken
|
||||
this.axios = axios
|
||||
|
||||
if (this.authToken) {
|
||||
// Add Basic Authentication token to the authorization header.
|
||||
@@ -35,8 +32,6 @@ class Utils {
|
||||
}
|
||||
|
||||
_this = this
|
||||
|
||||
this.whitelist = []
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +193,6 @@ class Utils {
|
||||
async list(id) {
|
||||
let path
|
||||
let method
|
||||
|
||||
if (!id) {
|
||||
method = "get"
|
||||
path = `${this.restURL}slp/list`
|
||||
@@ -215,9 +209,9 @@ class Utils {
|
||||
try {
|
||||
let response
|
||||
if (method === "get") {
|
||||
response = await _this.axios.get(path, _this.axiosOptions)
|
||||
response = await axios.get(path, _this.axiosOptions)
|
||||
} else {
|
||||
response = await _this.axios.post(
|
||||
response = await axios.post(
|
||||
path,
|
||||
{
|
||||
tokenIds: id
|
||||
@@ -313,7 +307,7 @@ class Utils {
|
||||
if (typeof address === "string") {
|
||||
const path = `${this.restURL}slp/balancesForAddress/${address}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
|
||||
// Array of addresses.
|
||||
@@ -321,7 +315,7 @@ class Utils {
|
||||
const path = `${this.restURL}slp/balancesForAddress`
|
||||
|
||||
// Dev note: must use axios.post for unit test stubbing.
|
||||
const response = await _this.axios.post(
|
||||
const response = await axios.post(
|
||||
path,
|
||||
{
|
||||
addresses: address
|
||||
@@ -375,10 +369,10 @@ class Utils {
|
||||
*/
|
||||
// Retrieve token balances for a given tokenId.
|
||||
async balancesForToken(tokenId) {
|
||||
try {
|
||||
const path = `${this.restURL}slp/balancesForToken/${tokenId}`
|
||||
const path = `${this.restURL}slp/balancesForToken/${tokenId}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
try {
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -432,10 +426,6 @@ 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`
|
||||
|
||||
@@ -447,19 +437,27 @@ class Utils {
|
||||
else txids = txid
|
||||
|
||||
try {
|
||||
const response = await _this.axios.post(
|
||||
const response = await axios.post(
|
||||
path,
|
||||
{
|
||||
txids: txids
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
// console.log(
|
||||
// `validateTxid response.data: ${JSON.stringify(response.data, null, 2)}`
|
||||
// )
|
||||
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
|
||||
|
||||
const validatedTxids = response.data
|
||||
|
||||
// Handle any null values
|
||||
for (let i = 0; i < validatedTxids.length; i++) {
|
||||
if (validatedTxids[i] === null) {
|
||||
validatedTxids[i] = {
|
||||
txid: txids[i],
|
||||
valid: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validatedTxids
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -487,7 +485,7 @@ class Utils {
|
||||
* // validate single SLP txid
|
||||
* (async () => {
|
||||
* try {
|
||||
* let validated = await bchjs.SLP.Utils.validateTxid2(
|
||||
* let validated = await bchjs.SLP.Utils.validateTxid(
|
||||
* "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb"
|
||||
* );
|
||||
* console.log(validated);
|
||||
@@ -515,7 +513,7 @@ class Utils {
|
||||
|
||||
const path = `${this.restURL}slp/validateTxid2/${txid}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -527,154 +525,6 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api SLP.Utils.whitelist() whitelist()
|
||||
* @apiName whitelist
|
||||
* @apiGroup SLP Utils
|
||||
* @apiDescription Get SLP tokens in whitelist
|
||||
* Retrieves a list of the SLP tokens that in the whitelist. Tokens in the
|
||||
* whitelist can be validated with the validateTxid3() function. validateTxid3()
|
||||
* will still work when the SLP network is under stress.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*
|
||||
* // validate single SLP txid
|
||||
* (async () => {
|
||||
* try {
|
||||
* let list = await bchjs.SLP.Utils.whitelit();
|
||||
* console.log(list);
|
||||
* } catch (error) {
|
||||
* console.error(error);
|
||||
* }
|
||||
* })();
|
||||
*
|
||||
* // returns
|
||||
* [
|
||||
* {
|
||||
* name: 'USDH',
|
||||
* tokenId:
|
||||
* 'c4b0d62156b3fa5c8f3436079b5394f7edc1bef5dc1cd2f9d0c4d46f82cca479'
|
||||
* },
|
||||
* {
|
||||
* name: 'SPICE',
|
||||
* tokenId:
|
||||
* '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf'
|
||||
* },
|
||||
* {
|
||||
* name: 'PSF',
|
||||
* tokenId:
|
||||
* '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0'
|
||||
* },
|
||||
* {
|
||||
* name: 'TROUT',
|
||||
* tokenId:
|
||||
* 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2'
|
||||
* },
|
||||
* {
|
||||
* name: 'PSFTEST',
|
||||
* tokenId:
|
||||
* 'd0ef4de95b78222bfee2326ab11382f4439aa0855936e2fe6ac129a8d778baa0'
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
async getWhitelist() {
|
||||
try {
|
||||
const path = `${this.restURL}slp/whitelist`
|
||||
|
||||
// Retrieve the whitelist from the REST API if we haven't gotten it yet.
|
||||
if (this.whitelist.length === 0) {
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
|
||||
|
||||
this.whitelist = response.data
|
||||
}
|
||||
|
||||
return this.whitelist
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api SLP.Utils.validateTxid3() validateTxid3()
|
||||
* @apiName validateTxid3
|
||||
* @apiGroup SLP Utils
|
||||
* @apiDescription Validate that txid is an SLP transaction using the SLPDB whitelist server.
|
||||
* Same exact functionality as the validateTxid() function, but this function
|
||||
* calls the whitelist SLPDB. It will only validate SLP tokens that are in the
|
||||
* whitelist. You can retrieve the whitelist with the SLP.Utils.whitelist()
|
||||
* function.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*
|
||||
* // validate single SLP txid
|
||||
* (async () => {
|
||||
* try {
|
||||
* let validated = await bchjs.SLP.Utils.validateTxid3(
|
||||
* "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb"
|
||||
* );
|
||||
* console.log(validated);
|
||||
* } catch (error) {
|
||||
* console.error(error);
|
||||
* }
|
||||
* })();
|
||||
*
|
||||
* // returns
|
||||
* [ { txid:
|
||||
* 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
|
||||
* valid: true } ]
|
||||
*
|
||||
* // validate multiple SLP txids
|
||||
* (async () => {
|
||||
* try {
|
||||
* let validated = await bchjs.SLP.Utils.validateTxid3([
|
||||
* "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb",
|
||||
* "00ea27261196a411776f81029c0ebe34362936b4a9847deb1f7a40a02b3a1476"
|
||||
* ]);
|
||||
* console.log(validated);
|
||||
* } catch (error) {
|
||||
* console.error(error);
|
||||
* }
|
||||
* })();
|
||||
*
|
||||
* // returns
|
||||
* [ { txid:
|
||||
* 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
|
||||
* valid: true },
|
||||
* { txid:
|
||||
* '00ea27261196a411776f81029c0ebe34362936b4a9847deb1f7a40a02b3a1476',
|
||||
* valid: true } ]
|
||||
*/
|
||||
async validateTxid3(txid) {
|
||||
const path = `${this.restURL}slp/validateTxid3`
|
||||
|
||||
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
||||
|
||||
// Handle a single TXID or an array of TXIDs.
|
||||
let txids
|
||||
if (typeof txid === "string") txids = [txid]
|
||||
else txids = txid
|
||||
|
||||
try {
|
||||
const response = await _this.axios.post(
|
||||
path,
|
||||
{
|
||||
txids: txids
|
||||
},
|
||||
_this.axiosOptions
|
||||
)
|
||||
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
|
||||
|
||||
const validatedTxids = response.data
|
||||
|
||||
return validatedTxids
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api SLP.Utils.tokenStats() tokenStats()
|
||||
* @apiName tokenStats
|
||||
@@ -711,11 +561,10 @@ class Utils {
|
||||
* }
|
||||
*/
|
||||
async tokenStats(tokenId) {
|
||||
const path = `${this.restURL}slp/tokenStats/${tokenId}`
|
||||
|
||||
try {
|
||||
const path = `${this.restURL}slp/tokenStats/${tokenId}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -782,11 +631,10 @@ class Utils {
|
||||
*/
|
||||
// Retrieve token transactions for a given tokenId and address.
|
||||
async transactions(tokenId, address) {
|
||||
const path = `${this.restURL}slp/transactions/${tokenId}/${address}`
|
||||
|
||||
try {
|
||||
const path = `${this.restURL}slp/transactions/${tokenId}/${address}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -822,11 +670,10 @@ class Utils {
|
||||
* }
|
||||
*/
|
||||
async burnTotal(transactionId) {
|
||||
const path = `${this.restURL}slp/burnTotal/${transactionId}`
|
||||
|
||||
try {
|
||||
const path = `${this.restURL}slp/burnTotal/${transactionId}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -868,7 +715,7 @@ class Utils {
|
||||
// console.log(`this.restURL: ${this.restURL}`)
|
||||
const path = `${this.restURL}slp/txDetails/${txid}`
|
||||
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
@@ -943,7 +790,7 @@ class Utils {
|
||||
|
||||
// Retrieve the transaction object from the full node.
|
||||
const path = `${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=true`
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
const response = await axios.get(path, _this.axiosOptions)
|
||||
const txDetails = response.data
|
||||
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
||||
|
||||
@@ -1094,7 +941,6 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the UTXO has a vout or tx_pos property.
|
||||
if (!Number.isInteger(utxo.vout)) {
|
||||
if (Number.isInteger(utxo.tx_pos)) {
|
||||
utxo.vout = utxo.tx_pos
|
||||
@@ -1129,13 +975,9 @@ class Utils {
|
||||
if (
|
||||
!err.message ||
|
||||
(err.message.indexOf("scriptpubkey not op_return") === -1 &&
|
||||
err.message.indexOf("lokad id") === -1 &&
|
||||
err.message.indexOf("trailing data") === -1)
|
||||
err.message.indexOf("lokad id") === -1)
|
||||
) {
|
||||
// console.log(
|
||||
// `unknown error from decodeOpReturn(). Marking as 'null'`,
|
||||
// err
|
||||
// )
|
||||
// console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
|
||||
|
||||
utxo.isValid = null
|
||||
outAry.push(utxo)
|
||||
@@ -1144,7 +986,6 @@ class Utils {
|
||||
// an SLP UTXO.
|
||||
// Mark as false and continue the loop.
|
||||
} else {
|
||||
// console.log("marking as invalid")
|
||||
utxo.isValid = false
|
||||
outAry.push(utxo)
|
||||
}
|
||||
@@ -1179,9 +1020,7 @@ class Utils {
|
||||
// Tokens
|
||||
else {
|
||||
utxo.utxoType = "token"
|
||||
utxo.tokenQty = new BigNumber(slpData.qty)
|
||||
.div(Math.pow(10, slpData.decimals))
|
||||
.toString()
|
||||
utxo.tokenQty = slpData.qty / Math.pow(10, slpData.decimals)
|
||||
}
|
||||
|
||||
utxo.tokenId = utxo.txid
|
||||
@@ -1224,9 +1063,7 @@ class Utils {
|
||||
// Tokens
|
||||
else {
|
||||
utxo.utxoType = "token"
|
||||
utxo.tokenQty = new BigNumber(slpData.qty)
|
||||
.div(Math.pow(10, genesisData.decimals))
|
||||
.toString()
|
||||
utxo.tokenQty = slpData.qty / Math.pow(10, genesisData.decimals)
|
||||
}
|
||||
|
||||
// Hydrate the UTXO object with information about the SLP token.
|
||||
@@ -1284,12 +1121,7 @@ class Utils {
|
||||
utxo.tokenType = slpData.tokenType
|
||||
|
||||
// Calculate the real token quantity.
|
||||
|
||||
const tokenQtyBig = new BigNumber(tokenQty).div(
|
||||
Math.pow(10, genesisData.decimals)
|
||||
)
|
||||
//console.log(`tokenQtyBig`, tokenQtyBig.toString())
|
||||
utxo.tokenQty = tokenQtyBig.toString()
|
||||
utxo.tokenQty = tokenQty / Math.pow(10, genesisData.decimals)
|
||||
|
||||
// console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`)
|
||||
|
||||
@@ -1297,127 +1129,16 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
// *After* the UTXO has been hydrated with SLP data,
|
||||
// validate the TXID with SLPDB.
|
||||
// Finally, validate the SLP txid with SLPDB.
|
||||
if (outAry[i].tokenType) {
|
||||
// Only execute this block if the current UTXO has a 'tokenType'
|
||||
// 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]
|
||||
if (!isValid) isValid = null
|
||||
// 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) {
|
||||
// console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`)
|
||||
var isValid = cachedTxValidation[utxo.txid]
|
||||
if (isValid == null) {
|
||||
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(
|
||||
// `checking against whitelist SLPDB. outAry[${i}]: ${JSON.stringify(
|
||||
// outAry[i],
|
||||
// null,
|
||||
// 2
|
||||
// )}`
|
||||
// )
|
||||
|
||||
// Figure out if the token UTXO is in the whitelist.
|
||||
let utxoInWhitelist = false
|
||||
for (let j = 0; j < this.whitelist.length; j++) {
|
||||
if (outAry[i].tokenId === this.whitelist[j].tokenId) {
|
||||
utxoInWhitelist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If the utxo.tokenId is in the whitelist, check the validity with
|
||||
// the whitelist SLPDB. This should still be functioning properly
|
||||
// if the general SLPDB is not.
|
||||
if (utxoInWhitelist) {
|
||||
isValid = await this.validateTxid3(utxo.txid)
|
||||
|
||||
// console.log(
|
||||
// `whitelist-SLPDB for ${utxo.txid}: ${JSON.stringify(
|
||||
// isValid,
|
||||
// null,
|
||||
// 2
|
||||
// )}`
|
||||
// )
|
||||
|
||||
if (isValid[0] !== null) isValid = isValid[0].valid
|
||||
|
||||
// Save the result to the local cache.
|
||||
// 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) {
|
||||
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)}`
|
||||
// )
|
||||
|
||||
if (isValid !== null) isValid = isValid.isValid
|
||||
|
||||
// Save the result to the local cache.
|
||||
// cachedTxValidation[utxo.txid] = isValid
|
||||
}
|
||||
|
||||
// console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
|
||||
outAry[i].isValid = isValid
|
||||
|
||||
// Save the txid to the local cache to reduce API calls.
|
||||
cachedTxValidation[utxo.txid] = isValid
|
||||
outAry[i].isValid = isValid[0].valid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1598,7 +1319,7 @@ class Utils {
|
||||
// Throw error if input is not an array.
|
||||
if (!Array.isArray(utxos)) throw new Error("Input must be an array.")
|
||||
|
||||
const response = await _this.axios.post(
|
||||
const response = await axios.post(
|
||||
`${this.restURL}slp/hydrateUtxos`,
|
||||
{
|
||||
utxos: utxos
|
||||
@@ -1612,48 +1333,6 @@ class Utils {
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api SLP.Utils.getStatus() getStatus()
|
||||
* @apiName getStatus
|
||||
* @apiGroup SLP Utils
|
||||
* @apiDescription Get the status and health of the SLPDB connected to bch-api.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*
|
||||
* // Get the current blockheight of the SLPDB indexer.
|
||||
* (async () => {
|
||||
* try {
|
||||
* let validated = await bchjs.SLP.Utils.validateTxid(
|
||||
* "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb"
|
||||
* );
|
||||
* console.log(validated);
|
||||
* } catch (error) {
|
||||
* console.error(error);
|
||||
* }
|
||||
* })();
|
||||
*
|
||||
* // returns
|
||||
* [ { txid:
|
||||
* 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
|
||||
* valid: true } ]
|
||||
*
|
||||
*/
|
||||
async getStatus(txid) {
|
||||
const path = `${this.restURL}slp/status`
|
||||
|
||||
try {
|
||||
const response = await _this.axios.get(path, _this.axiosOptions)
|
||||
// console.log(
|
||||
// `getStatus response.data: ${JSON.stringify(response.data, null, 2)}`
|
||||
// )
|
||||
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Utils
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
const assert = require("chai").assert
|
||||
|
||||
// const RESTURL = `https://abc.fullstack.cash/v4/`
|
||||
const RESTURL = `https://bchn.fullstack.cash/v4/`
|
||||
// const RESTURL = `http://localhost:3000/v4/`
|
||||
// const RESTURL = `https://abc.fullstack.cash/v3/`
|
||||
const RESTURL = `https://bchn.fullstack.cash/v3/`
|
||||
// const RESTURL = `http://localhost:3000/v3/`
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({ restURL: RESTURL })
|
||||
|
||||
@@ -13,9 +13,9 @@ const PRO_PASS = "testpassword"
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({
|
||||
// restURL: `https://bchn.fullstack.cash/v4/`,
|
||||
restURL: `https://abc.fullstack.cash/v4/`,
|
||||
// restURL: `http://localhost:3000/v4/`,
|
||||
// restURL: `https://bchn.fullstack.cash/v3/`,
|
||||
restURL: `https://abc.fullstack.cash/v3/`,
|
||||
// restURL: `http://localhost:3000/v3/`,
|
||||
authPass: PRO_PASS
|
||||
})
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ const JWT_TOKEN =
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({
|
||||
restURL: `https://api.fullstack.cash/v4/`,
|
||||
// restURL: `http://localhost:3000/v4/`,
|
||||
restURL: `https://api.fullstack.cash/v3/`,
|
||||
// restURL: `http://localhost:3000/v3/`,
|
||||
apiToken: JWT_TOKEN
|
||||
})
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ const JWT_TOKEN =
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({
|
||||
// restURL: `https://bchn.fullstack.cash/v4/`,
|
||||
restURL: `https:/abc.fullstack.cash/v4/`,
|
||||
// restURL: `http://localhost:3000/v4/`,
|
||||
// restURL: `https://bchn.fullstack.cash/v3/`,
|
||||
restURL: `https:/abc.fullstack.cash/v3/`,
|
||||
// restURL: `http://localhost:3000/v3/`,
|
||||
apiToken: JWT_TOKEN
|
||||
})
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ const JWT_TOKEN =
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({
|
||||
// restURL: `https://bchn.fullstack.cash/v4/`,
|
||||
restURL: `https://abc.fullstack.cash/v4/`,
|
||||
// restURL: `http://localhost:3000/v4/`,
|
||||
// restURL: `https://bchn.fullstack.cash/v3/`,
|
||||
restURL: `https://abc.fullstack.cash/v3/`,
|
||||
// restURL: `http://localhost:3000/v3/`,
|
||||
apiToken: JWT_TOKEN
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
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")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,356 @@
|
||||
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"
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
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")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,216 @@
|
||||
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")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#detailsAddress`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.details(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 POST address details for a single address`, async () => {
|
||||
const addr = "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7"
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "currentPage")
|
||||
assert.property(result[0], "pagesTotal")
|
||||
})
|
||||
|
||||
it(`should POST address details for an array of addresses`, async () => {
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[1], "cashAddress")
|
||||
assert.property(result[1], "slpAddress")
|
||||
assert.property(result[1], "currentPage")
|
||||
assert.property(result[1], "pagesTotal")
|
||||
|
||||
/*
|
||||
If in any way possible, I would like to refactor this test
|
||||
according to the DRY principle to share it with the integration tests too
|
||||
Would that make sense or does that implicate anything unwanted?
|
||||
|
||||
assertDetails(result[0])
|
||||
|
||||
assertDetails(data) {
|
||||
assert.property(data, "balance")
|
||||
assert.property(data, "balanceSat")
|
||||
assert.property(data, "totalReceived")
|
||||
assert.property(data, "totalReceivedSat")
|
||||
assert.property(data, "totalSent")
|
||||
assert.property(data, "totalSentSat")
|
||||
}
|
||||
*/
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
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("#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")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
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")
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,700 @@
|
||||
/*
|
||||
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"
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
// 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)
|
||||
})
|
||||
})
|
||||
|
||||
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("#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))
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
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,148 @@
|
||||
/*
|
||||
Integration tests for the Blockbook library.
|
||||
|
||||
*/
|
||||
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
//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 = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
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 = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
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 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.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 = "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7"
|
||||
|
||||
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 = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
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 error on array size rate limit`, async () => {
|
||||
try {
|
||||
const addr = []
|
||||
for (let i = 0; i < 25; i++)
|
||||
addr.push("bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr")
|
||||
|
||||
const result = 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))
|
||||
}
|
||||
@@ -1,71 +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", () => {
|
||||
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))
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
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))
|
||||
}
|
||||
@@ -1,71 +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", () => {
|
||||
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))
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
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))
|
||||
}
|
||||
@@ -1,71 +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", () => {
|
||||
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))
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
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))
|
||||
}
|
||||
@@ -3,7 +3,9 @@ const assert = chai.assert
|
||||
const sinon = require("sinon")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS({ ninsightURL: "https://rest.bitcoin.com/v2" })
|
||||
const bchjs = new BCHJS({
|
||||
ninsightURL: "https://rest.bitcoin.com/v2"
|
||||
})
|
||||
|
||||
describe(`#Ninsight`, () => {
|
||||
let sandbox
|
||||
@@ -131,6 +133,91 @@ describe(`#Ninsight`, () => {
|
||||
assert.property(result[0], "vout")
|
||||
})
|
||||
})
|
||||
describe(`#detailsAddress`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.details(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 POST address details for a single address`, async () => {
|
||||
const addr = "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7"
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "currentPage")
|
||||
assert.property(result[0], "pagesTotal")
|
||||
})
|
||||
|
||||
it(`should POST address details for an array of addresses`, async () => {
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[1], "cashAddress")
|
||||
assert.property(result[1], "slpAddress")
|
||||
assert.property(result[1], "currentPage")
|
||||
assert.property(result[1], "pagesTotal")
|
||||
|
||||
/*
|
||||
If in any way possible, I would like to refactor this test
|
||||
according to the DRY principle to share it with the integration tests too
|
||||
Would that make sense or does that implicate anything unwanted?
|
||||
|
||||
assertDetails(result[0])
|
||||
|
||||
assertDetails(data) {
|
||||
assert.property(data, "balance")
|
||||
assert.property(data, "balanceSat")
|
||||
assert.property(data, "totalReceived")
|
||||
assert.property(data, "totalReceivedSat")
|
||||
assert.property(data, "totalSent")
|
||||
assert.property(data, "totalSentSat")
|
||||
}
|
||||
*/
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function sleep(ms) {
|
||||
|
||||
@@ -25,15 +25,6 @@ describe("#price", () => {
|
||||
})
|
||||
})
|
||||
|
||||
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()
|
||||
|
||||
@@ -231,6 +231,40 @@ 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 (code 16)")
|
||||
}
|
||||
})
|
||||
|
||||
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 (code 16)")
|
||||
}
|
||||
})
|
||||
|
||||
it(`should throw error on array size rate limit`, async () => {
|
||||
try {
|
||||
const dataMock =
|
||||
|
||||
@@ -463,31 +463,6 @@ describe(`#SLP`, () => {
|
||||
|
||||
assert.equal(data[0].isValid, false)
|
||||
})
|
||||
|
||||
it("should handle null SLPDB validations", async () => {
|
||||
const utxos = [
|
||||
{
|
||||
height: 665577,
|
||||
tx_hash:
|
||||
"4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419",
|
||||
tx_pos: 1,
|
||||
value: 546
|
||||
},
|
||||
{
|
||||
height: 665577,
|
||||
tx_hash:
|
||||
"3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
|
||||
tx_pos: 1,
|
||||
value: 546
|
||||
}
|
||||
]
|
||||
|
||||
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
|
||||
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||
|
||||
assert.isArray(data)
|
||||
// assert.equal(data[0].isValid, null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#balancesForAddress", () => {
|
||||
@@ -628,60 +603,6 @@ 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)}`)
|
||||
|
||||
assert.isArray(data.slpUtxos)
|
||||
assert.equal(data.slpUtxos[0].isValid, null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#validateTxid", () => {
|
||||
// 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)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.equal(result[0].txid, txid)
|
||||
// assert.equal(result[0].valid, null)
|
||||
})
|
||||
|
||||
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)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.equal(result[0].txid, txid[0])
|
||||
// assert.equal(result[0].valid, null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#validateTxid2", () => {
|
||||
@@ -713,28 +634,6 @@ describe(`#SLP`, () => {
|
||||
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("#getStatus", () => {
|
||||
it("should return the current block height of the SLPDB indexer", async () => {
|
||||
const result = await bchjs.SLP.Utils.getStatus()
|
||||
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, "bchBlockHeight")
|
||||
assert.property(result, "slpProcessedBlockHeight")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#tokentype1", () => {
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
export RESTURL=https://bchn.fullstack.cash/v3/
|
||||
#export RESTURL=http://localhost:3000/v3/
|
||||
#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
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
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/v3/`
|
||||
// if (process.env.RESTURL) RESTURL = process.env.RESTURL
|
||||
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v3/` })
|
||||
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))
|
||||
}
|
||||
+3
-3
@@ -12,11 +12,11 @@ const assert = chai.assert
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: "https://testnet3.fullstack.cash/v4/"
|
||||
: "https://testnet3.fullstack.cash/v3/"
|
||||
// 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 = require("../../../src/bch-js")
|
||||
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v3/` })
|
||||
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
|
||||
|
||||
// Inspect utility used for debugging.
|
||||
@@ -7,9 +7,9 @@ const assert = chai.assert
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: `https://testnet3.fullstack.cash/v4/`
|
||||
: `https://testnet3.fullstack.cash/v3/`
|
||||
|
||||
const BCHJS = require("../../../../src/bch-js")
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
|
||||
|
||||
describe(`#control`, () => {
|
||||
+2
-2
@@ -4,9 +4,9 @@ const sinon = require("sinon")
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: `https://testnet3.fullstack.cash/v4/`
|
||||
: `https://testnet3.fullstack.cash/v3/`
|
||||
|
||||
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,8 +2,10 @@ const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const sinon = require("sinon")
|
||||
|
||||
const BCHJS = require("../../../../src/bch-js")
|
||||
const bchjs = new BCHJS({ ninsightURL: "https://trest.bitcoin.com/v2" })
|
||||
const BCHJS = require("../../../src/bch-js")
|
||||
const bchjs = new BCHJS({
|
||||
ninsightURL: "https://trest.bitcoin.com/v2"
|
||||
})
|
||||
|
||||
describe(`#Ninsight`, () => {
|
||||
let sandbox
|
||||
@@ -105,8 +107,7 @@ 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)}`)
|
||||
@@ -140,6 +141,92 @@ describe(`#Ninsight`, () => {
|
||||
assert.property(result[0], "vout")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#detailsAddress`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.details(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 POST address details for a single address`, async () => {
|
||||
const addr = "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr"
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "currentPage")
|
||||
assert.property(result[0], "pagesTotal")
|
||||
})
|
||||
|
||||
it(`should POST address details for an array of addresses`, async () => {
|
||||
const addr = [
|
||||
"bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr",
|
||||
"bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[1], "cashAddress")
|
||||
assert.property(result[1], "slpAddress")
|
||||
assert.property(result[1], "currentPage")
|
||||
assert.property(result[1], "pagesTotal")
|
||||
|
||||
/*
|
||||
If in any way possible, I would like to refactor this test
|
||||
according to the DRY principle to share it with the integration tests too
|
||||
Would that make sense or does that implicate anything unwanted?
|
||||
|
||||
assertDetails(result[0])
|
||||
|
||||
assertDetails(data) {
|
||||
assert.property(data, "balance")
|
||||
assert.property(data, "balanceSat")
|
||||
assert.property(data, "totalReceived")
|
||||
assert.property(data, "totalReceivedSat")
|
||||
assert.property(data, "totalSent")
|
||||
assert.property(data, "totalSentSat")
|
||||
}
|
||||
*/
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function sleep(ms) {
|
||||
+5
-5
@@ -10,11 +10,11 @@ const assert = chai.assert
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: `https://testnet3.fullstack.cash/v4/`
|
||||
: `https://testnet3.fullstack.cash/v3/`
|
||||
// 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 = require("../../../src/bch-js")
|
||||
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v3/` })
|
||||
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
|
||||
|
||||
// Inspect utility used for debugging.
|
||||
@@ -251,7 +251,7 @@ describe("#rawtransaction", () => {
|
||||
//console.log(`err: ${util.inspect(err)}`)
|
||||
|
||||
assert.hasAllKeys(err, ["error"])
|
||||
assert.include(err.error, "Missing inputs")
|
||||
assert.include(err.error, "bad-txns-inputs-missingorspent (code 16)")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -268,7 +268,7 @@ describe("#rawtransaction", () => {
|
||||
// console.log(`err: ${util.inspect(err)}`)
|
||||
|
||||
assert.hasAllKeys(err, ["error"])
|
||||
assert.include(err.error, "Missing inputs")
|
||||
assert.include(err.error, "bad-txns-inputs-missingorspent (code 16)")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -7,11 +7,11 @@ const assert = chai.assert
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: `https://testnet3.fullstack.cash/v4/`
|
||||
: `https://testnet3.fullstack.cash/v3/`
|
||||
// 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 = require("../../../src/bch-js")
|
||||
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v3/` })
|
||||
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
|
||||
|
||||
// Inspect utility used for debugging.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
export RESTURL=https://free-test.fullstack.cash/v4/
|
||||
export RESTURL=https://free-test.fullstack.cash/v3/
|
||||
export NETWORK=testnet
|
||||
export IS_USING_FREE_TIER=true
|
||||
|
||||
@@ -8,11 +8,11 @@ const assert = chai.assert
|
||||
|
||||
const RESTURL = process.env.RESTURL
|
||||
? process.env.RESTURL
|
||||
: `https://testnet3.fullstack.cash/v4/`
|
||||
: `https://testnet3.fullstack.cash/v3/`
|
||||
// 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 = require("../../../src/bch-js")
|
||||
// const bchjs = new BCHJS({ restURL: `https://testnet.bchjs.cash/v3/` })
|
||||
const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
|
||||
|
||||
// Inspect utility used for debugging.
|
||||
+773
-803
File diff suppressed because it is too large
Load Diff
+37
-37
@@ -1,13 +1,7 @@
|
||||
// Public npm libraries
|
||||
const assert = require("assert")
|
||||
|
||||
// Mocks
|
||||
const fixtures = require("./fixtures/bitcoincash.json")
|
||||
|
||||
// Unit under test (uut)
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const bchjs = new BCHJS()
|
||||
let bchjs
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
// TODO
|
||||
// 1. generate testnet p2sh
|
||||
@@ -26,26 +20,28 @@ let bchjs
|
||||
// 6. More error test cases.
|
||||
|
||||
describe("#BitcoinCash", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("price conversion", () => {
|
||||
it("should exercise toBitcoinCash", () => {
|
||||
describe("#toBitcoinCash", () => {
|
||||
fixtures.conversion.toBCH.satoshis.forEach(satoshi => {
|
||||
it(`should convert ${satoshi[0]} Satoshis to ${satoshi[1]} $BCH`, () => {
|
||||
it(`should convert ${satoshi[0]} Satoshis to ${
|
||||
satoshi[1]
|
||||
} $BCH`, () => {
|
||||
assert.equal(bchjs.BitcoinCash.toBitcoinCash(satoshi[0]), satoshi[1])
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.conversion.toBCH.strings.forEach(satoshi => {
|
||||
it(`should convert "${satoshi[0]}" Satoshis as a string to ${satoshi[1]} $BCH`, () => {
|
||||
it(`should convert "${satoshi[0]}" Satoshis as a string to ${
|
||||
satoshi[1]
|
||||
} $BCH`, () => {
|
||||
assert.equal(bchjs.BitcoinCash.toBitcoinCash(satoshi[0]), satoshi[1])
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.conversion.toBCH.not.forEach(bch => {
|
||||
it(`converts ${bch[0]} to Bitcoin Cash, not to ${bch[1]} Satoshi`, () => {
|
||||
it(`converts ${bch[0]} to Bitcoin Cash, not to ${
|
||||
bch[1]
|
||||
} Satoshi`, () => {
|
||||
assert.notEqual(bchjs.BitcoinCash.toBitcoinCash(bch[0]), bch[1])
|
||||
})
|
||||
})
|
||||
@@ -57,7 +53,7 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("should exercise toSatoshi", () => {
|
||||
describe("#toSatoshi", () => {
|
||||
fixtures.conversion.toSatoshi.bch.forEach(bch => {
|
||||
it(`should convert ${bch[0]} $BCH to ${bch[1]} Satoshis`, () => {
|
||||
assert.equal(bchjs.BitcoinCash.toSatoshi(bch[0]), bch[1])
|
||||
@@ -65,13 +61,17 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
|
||||
fixtures.conversion.toSatoshi.strings.forEach(bch => {
|
||||
it(`should convert "${bch[0]}" $BCH as a string to ${bch[1]} Satoshis`, () => {
|
||||
it(`should convert "${bch[0]}" $BCH as a string to ${
|
||||
bch[1]
|
||||
} Satoshis`, () => {
|
||||
assert.equal(bchjs.BitcoinCash.toSatoshi(bch[0]), bch[1])
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.conversion.toSatoshi.not.forEach(satoshi => {
|
||||
it(`converts ${satoshi[0]} to Satoshi, not to ${satoshi[1]} Bitcoin Cash`, () => {
|
||||
it(`converts ${satoshi[0]} to Satoshi, not to ${
|
||||
satoshi[1]
|
||||
} Bitcoin Cash`, () => {
|
||||
assert.notEqual(bchjs.BitcoinCash.toSatoshi(satoshi[0]), satoshi[1])
|
||||
})
|
||||
})
|
||||
@@ -83,7 +83,7 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("should exercise satsToBits", () => {
|
||||
describe("#satsToBits", () => {
|
||||
fixtures.conversion.satsToBits.bch.forEach(bch => {
|
||||
it(`should convert ${bch[0]} BCH to ${bch[1]} bits`, () => {
|
||||
assert.equal(
|
||||
@@ -94,7 +94,9 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
|
||||
fixtures.conversion.satsToBits.strings.forEach(bch => {
|
||||
it(`should convert "${bch[0]}" BCH as a string to ${bch[1]} bits`, () => {
|
||||
it(`should convert "${bch[0]}" BCH as a string to ${
|
||||
bch[1]
|
||||
} bits`, () => {
|
||||
assert.equal(
|
||||
bchjs.BitcoinCash.satsToBits(bchjs.BitcoinCash.toSatoshi(bch[0])),
|
||||
bch[1]
|
||||
@@ -119,7 +121,7 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
|
||||
describe("sign and verify messages", () => {
|
||||
it("should exercise signMessageWithPrivKey", () => {
|
||||
describe("#signMessageWithPrivKey", () => {
|
||||
fixtures.signatures.sign.forEach(sign => {
|
||||
it(`should sign a message w/ ${sign.network} ${sign.privateKeyWIF}`, () => {
|
||||
const privateKeyWIF = sign.privateKeyWIF
|
||||
@@ -133,7 +135,7 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("shoudl exercise verifyMessage", () => {
|
||||
describe("#verifyMessage", () => {
|
||||
fixtures.signatures.verify.forEach(sign => {
|
||||
it(`should verify a valid signed message from ${sign.network} cashaddr address ${sign.address}`, () => {
|
||||
assert.equal(
|
||||
@@ -147,24 +149,22 @@ describe("#BitcoinCash", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("should verify legacy addresses", () => {
|
||||
fixtures.signatures.verify.forEach(sign => {
|
||||
const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
|
||||
it(`should verify a valid signed message from ${sign.network} legacy address ${legacyAddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.BitcoinCash.verifyMessage(
|
||||
legacyAddress,
|
||||
sign.signature,
|
||||
sign.message
|
||||
),
|
||||
true
|
||||
)
|
||||
})
|
||||
fixtures.signatures.verify.forEach(sign => {
|
||||
const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
|
||||
it(`should verify a valid signed message from ${sign.network} legacy address ${legacyAddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.BitcoinCash.verifyMessage(
|
||||
legacyAddress,
|
||||
sign.signature,
|
||||
sign.message
|
||||
),
|
||||
true
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.signatures.verify.forEach(sign => {
|
||||
// const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
|
||||
const legacyAddress = bchjs.Address.toLegacyAddress(sign.address)
|
||||
it(`should not verify an invalid signed message from ${sign.network} cashaddr address ${sign.address}`, () => {
|
||||
assert.equal(
|
||||
bchjs.BitcoinCash.verifyMessage(
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
const chai = require("chai")
|
||||
const assert = chai.assert
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
|
||||
const mockData = require("./fixtures/blockbook-mock")
|
||||
|
||||
describe(`#Blockbook`, () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
afterEach(() => sandbox.restore())
|
||||
|
||||
describe(`#Balance`, () => {
|
||||
it(`should GET balance for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.balance })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
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 () => {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.resolves({ data: [mockData.balance, mockData.balance] })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
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 {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.throws(`Input address must be a string or array of strings`)
|
||||
|
||||
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 {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").throws(`Array too large`)
|
||||
|
||||
const addr = []
|
||||
for (let i = 0; i < 25; i++)
|
||||
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
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 () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
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 () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxos })
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
]
|
||||
|
||||
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 {
|
||||
// Stub the network call.
|
||||
sandbox
|
||||
.stub(axios, "post")
|
||||
.throws(`Input address must be a string or array of strings`)
|
||||
|
||||
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("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
const result = 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")
|
||||
}
|
||||
})
|
||||
*/
|
||||
})
|
||||
|
||||
describe(`#tx`, () => {
|
||||
it(`should GET tx details for a single txid`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "get").resolves({ data: mockData.utxo })
|
||||
|
||||
const addr = "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
|
||||
|
||||
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 () => {
|
||||
// // Stub the network call.
|
||||
// sandbox.stub(axios, "post").resolves({ data: mockData.utxos })
|
||||
//
|
||||
// const addr = [
|
||||
// "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
// "bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
|
||||
// ]
|
||||
//
|
||||
// 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 {
|
||||
// // Stub the network call.
|
||||
// sandbox
|
||||
// .stub(axios, "post")
|
||||
// .throws(`Input address must be a string or array of strings`)
|
||||
//
|
||||
// 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("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
|
||||
|
||||
const result = 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")
|
||||
}
|
||||
})
|
||||
*/
|
||||
})
|
||||
})
|
||||
+4
-11
@@ -1,20 +1,13 @@
|
||||
// Public npm libraries.
|
||||
const assert = require("assert")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
// Mocks
|
||||
const fixtures = require("./fixtures/ecpair.json")
|
||||
|
||||
// Unit under test (uut)
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const bchjs = new BCHJS()
|
||||
let bchjs
|
||||
|
||||
describe("#ECPair", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#fromWIF", () => {
|
||||
fixtures.fromWIF.forEach(fixture => {
|
||||
it(`should create ECPair from WIF ${fixture.privateKeyWIF}`, () => {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Unit test mocks for Blockbook endpoints.
|
||||
*/
|
||||
|
||||
const balance = {
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
itemsOnPage: 1000,
|
||||
address: "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
|
||||
balance: "230000",
|
||||
totalReceived: "6194528752",
|
||||
totalSent: "6194298752",
|
||||
unconfirmedBalance: "0",
|
||||
unconfirmedTxs: 0,
|
||||
txs: 3,
|
||||
txids: [
|
||||
"27ec8512c1a9ee9e9ae9b98eb60375f1d2bd60e2e76a1eff5a45afdbc517cf9c",
|
||||
"6e1ae1bf7db6de799ec1c05ab2816ac65549bd80141567af088e6f291385b07d",
|
||||
"5d95f4e6047901fc1502a9758bbdb14ce73f24662b1784d13e0217b3d37bb7a2"
|
||||
]
|
||||
}
|
||||
|
||||
const utxo = [
|
||||
{
|
||||
txid: "27ec8512c1a9ee9e9ae9b98eb60375f1d2bd60e2e76a1eff5a45afdbc517cf9c",
|
||||
vout: 0,
|
||||
value: "100000",
|
||||
height: 560430,
|
||||
confirmations: 29321
|
||||
},
|
||||
{
|
||||
txid: "6e1ae1bf7db6de799ec1c05ab2816ac65549bd80141567af088e6f291385b07d",
|
||||
vout: 0,
|
||||
value: "130000",
|
||||
height: 560039,
|
||||
confirmations: 29712
|
||||
}
|
||||
]
|
||||
|
||||
const utxos = [
|
||||
[
|
||||
{
|
||||
txid: "27ec8512c1a9ee9e9ae9b98eb60375f1d2bd60e2e76a1eff5a45afdbc517cf9c",
|
||||
vout: 0,
|
||||
value: "100000",
|
||||
height: 560430,
|
||||
confirmations: 29868
|
||||
},
|
||||
{
|
||||
txid: "6e1ae1bf7db6de799ec1c05ab2816ac65549bd80141567af088e6f291385b07d",
|
||||
vout: 0,
|
||||
value: "130000",
|
||||
height: 560039,
|
||||
confirmations: 30259
|
||||
}
|
||||
],
|
||||
[]
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
balance,
|
||||
utxo,
|
||||
utxos
|
||||
}
|
||||
@@ -158,6 +158,30 @@ const details = {
|
||||
|
||||
const detailsPost = [details, details]
|
||||
|
||||
const addrDetail =
|
||||
{
|
||||
"balance": 0.00001,
|
||||
"balanceSat": 1000,
|
||||
"totalReceived": 0.00001,
|
||||
"totalReceivedSat": 1000,
|
||||
"totalSent": 0,
|
||||
"totalSentSat": 0,
|
||||
"unconfirmedBalance": 0,
|
||||
"unconfirmedBalanceSat": 0,
|
||||
"unconfirmedTxApperances": 0,
|
||||
"txApperances": 1,
|
||||
"transactions": [
|
||||
"5f09d317e24c5d376f737a2711f3bd1d381abdb41743fff3819b4f76382e1eac"
|
||||
],
|
||||
"legacyAddress": "1FZrK8HohEKyKCTM24NkAzPnX9WD9Ujhw7",
|
||||
"cashAddress": "bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr",
|
||||
"slpAddress": "simpleledger:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ylynt40sa",
|
||||
"currentPage": 0,
|
||||
"pagesTotal": 1
|
||||
}
|
||||
|
||||
const addrDetailArray = [addrDetail, addrDetail]
|
||||
|
||||
module.exports = {
|
||||
utxo,
|
||||
utxoPost,
|
||||
@@ -166,5 +190,7 @@ module.exports = {
|
||||
transactions,
|
||||
transactionsPost,
|
||||
details,
|
||||
detailsPost
|
||||
detailsPost,
|
||||
addrDetail,
|
||||
addrDetailArray
|
||||
}
|
||||
|
||||
@@ -1107,189 +1107,6 @@ const txDetailsSLPNftGenesis = {
|
||||
blocktime: 1591329189
|
||||
}
|
||||
|
||||
const mockWhitelist = [
|
||||
{
|
||||
name: "USDH",
|
||||
tokenId: "c4b0d62156b3fa5c8f3436079b5394f7edc1bef5dc1cd2f9d0c4d46f82cca479"
|
||||
},
|
||||
{
|
||||
name: "SPICE",
|
||||
tokenId: "4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf"
|
||||
},
|
||||
{
|
||||
name: "PSF",
|
||||
tokenId: "38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0"
|
||||
},
|
||||
{
|
||||
name: "TROUT",
|
||||
tokenId: "a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2"
|
||||
},
|
||||
{
|
||||
name: "PSFTEST",
|
||||
tokenId: "d0ef4de95b78222bfee2326ab11382f4439aa0855936e2fe6ac129a8d778baa0"
|
||||
}
|
||||
]
|
||||
|
||||
const mockValidateTxid3Valid = [
|
||||
{
|
||||
txid: "daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
|
||||
valid: true
|
||||
}
|
||||
]
|
||||
|
||||
const mockValidateTxid3Invalid = [
|
||||
{
|
||||
txid: "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
|
||||
valid: null
|
||||
}
|
||||
]
|
||||
|
||||
const mockValidateTxidArray = [
|
||||
{
|
||||
txid: "daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd",
|
||||
valid: true
|
||||
},
|
||||
{
|
||||
txid: "3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488",
|
||||
valid: true
|
||||
},
|
||||
{
|
||||
txid: "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
|
||||
valid: false
|
||||
},
|
||||
{
|
||||
txid: "01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0",
|
||||
valid: false
|
||||
}
|
||||
]
|
||||
|
||||
const whitelist = [
|
||||
{
|
||||
name: "USDH",
|
||||
tokenId: "c4b0d62156b3fa5c8f3436079b5394f7edc1bef5dc1cd2f9d0c4d46f82cca479"
|
||||
},
|
||||
{
|
||||
name: "SPICE",
|
||||
tokenId: "4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf"
|
||||
},
|
||||
{
|
||||
name: "PSF",
|
||||
tokenId: "38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0"
|
||||
},
|
||||
{
|
||||
name: "TROUT",
|
||||
tokenId: "a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2"
|
||||
},
|
||||
{
|
||||
name: "PSFTEST",
|
||||
tokenId: "d0ef4de95b78222bfee2326ab11382f4439aa0855936e2fe6ac129a8d778baa0"
|
||||
},
|
||||
{
|
||||
name: "TOK-CH",
|
||||
tokenId: "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
|
||||
}
|
||||
]
|
||||
|
||||
const slpdbStatus = {
|
||||
_id: "5fe4cd90cd2bd2000f7fe46c",
|
||||
version: "1.0.0-beta-rc13",
|
||||
versionHash: "bb4a805610b9e4d67c1595b716df36190c75e8b1",
|
||||
deplVersionHash: null,
|
||||
startCmd: "node index run",
|
||||
context: "SLPDB",
|
||||
lastStatusUpdate: {
|
||||
utc: "Thu, 24 Dec 2020 17:19:12 GMT",
|
||||
unix: 1608830352
|
||||
},
|
||||
lastIncomingTxnZmq: {
|
||||
utc: "Thu, 24 Dec 2020 17:19:12 GMT",
|
||||
unix: 1608830352
|
||||
},
|
||||
lastIncomingBlockZmq: {
|
||||
utc: "Thu, 24 Dec 2020 16:43:38 GMT",
|
||||
unix: 1608828218
|
||||
},
|
||||
lastOutgoingTxnZmq: null,
|
||||
lastOutgoingBlockZmq: null,
|
||||
state: "RUNNING",
|
||||
stateHistory: [
|
||||
{
|
||||
utc: "Mon, 07 Dec 2020 15:26:23 GMT",
|
||||
state: "STARTUP_BLOCK_SYNC"
|
||||
},
|
||||
{
|
||||
utc: "Tue, 08 Dec 2020 19:53:04 GMT",
|
||||
state: "RUNNING"
|
||||
}
|
||||
],
|
||||
network: "mainnet",
|
||||
bchBlockHeight: 667270,
|
||||
bchBlockHash:
|
||||
"000000000000000003d57b35b1b6b8073c8311974e2b9a473e1bd6daa98fde53",
|
||||
slpProcessedBlockHeight: 667270,
|
||||
mempoolInfoBch: {
|
||||
loaded: true,
|
||||
size: 534,
|
||||
bytes: 320552,
|
||||
usage: 956384,
|
||||
maxmempool: 300000000,
|
||||
mempoolminfee: 0.00001,
|
||||
minrelaytxfee: 0.00001
|
||||
},
|
||||
mempoolSizeSlp: 78,
|
||||
tokensCount: 77976,
|
||||
pastStackTraces: [
|
||||
"[Tue, 08 Dec 2020 19:35:36 GMT] MongoServerSelectionError: connection <monitor> to 172.17.0.1:12301 timed out\n at Timeout._onTimeout (/home/safeuser/SLPDB/node_modules/mongodb/lib/core/sdam/topology.js:438:30)\n at listOnTimeout (internal/timers.js:554:17)\n at processTimers (internal/timers.js:497:7)",
|
||||
"[Tue, 08 Dec 2020 19:35:36 GMT] MongoServerSelectionError: connection <monitor> to 172.17.0.1:12301 timed out\n at Timeout._onTimeout (/home/safeuser/SLPDB/node_modules/mongodb/lib/core/sdam/topology.js:438:30)\n at listOnTimeout (internal/timers.js:554:17)\n at processTimers (internal/timers.js:497:7)"
|
||||
],
|
||||
doubleSpends: [
|
||||
{
|
||||
txo:
|
||||
"3e377f67e9d065f02e47633d847cdb04b0679d51baccdc0feea5297529e330b5:820",
|
||||
details: {
|
||||
originalTxid:
|
||||
"dc148149d25a546fffe0b207c62b192811c288481df5f43f1f76f67b6004f98c",
|
||||
current:
|
||||
"de12db60e253c378eeebb1df85153168a998db8267ec54b38589cc31348b2b8d",
|
||||
time: {
|
||||
utc: "Sat, 19 Dec 2020 02:25:37 GMT",
|
||||
unix: 1608344737
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
reorgs: [],
|
||||
mongoDbStats: {
|
||||
db: "slpdb",
|
||||
collections: 5,
|
||||
views: 0,
|
||||
objects: 2497140,
|
||||
avgObjSize: 3188.778575890819,
|
||||
dataSize: 7593.943150520325,
|
||||
storageSize: 3357.74609375,
|
||||
indexes: 71,
|
||||
indexSize: 1490.14453125,
|
||||
totalSize: 4847.890625,
|
||||
scaleFactor: 1048576,
|
||||
fsUsedSize: 74424.46484375,
|
||||
fsTotalSize: 153676.98046875,
|
||||
ok: 1
|
||||
},
|
||||
publicUrl: "fullstack--bchn-02",
|
||||
telemetryHash: null,
|
||||
system: {
|
||||
loadAvg1: 0.16,
|
||||
loadAvg5: 0.11,
|
||||
loadAvg15: 0.04,
|
||||
platform: "linux",
|
||||
cpuCount: 8,
|
||||
freeMem: 5780.51953125,
|
||||
totalMem: 31360.8828125,
|
||||
uptime: 1654085,
|
||||
processUptime: 1374204.613560816
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mockList,
|
||||
mockToken,
|
||||
@@ -1314,10 +1131,5 @@ module.exports = {
|
||||
mockTxDetails,
|
||||
mockDualValidation,
|
||||
mockDualOpData,
|
||||
mockInvalidSlpSend,
|
||||
mockWhitelist,
|
||||
mockValidateTxid3Valid,
|
||||
mockValidateTxid3Invalid,
|
||||
whitelist,
|
||||
slpdbStatus
|
||||
mockInvalidSlpSend
|
||||
}
|
||||
|
||||
+2
-10
@@ -1,18 +1,10 @@
|
||||
// Public npm libraries
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
// Unit under test (uut)
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const bchjs = new BCHJS()
|
||||
let bchjs
|
||||
|
||||
describe("#Generating", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#generateToAddress", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
|
||||
+48
-61
@@ -1,20 +1,11 @@
|
||||
// Public npm libraries
|
||||
const assert = require("assert")
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
// Mocks
|
||||
const fixtures = require("./fixtures/hdnode.json")
|
||||
const slpFixtures = require("./fixtures/slp/address.json")
|
||||
|
||||
// Unit under test (uut)
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
let bchjs
|
||||
const bchjs = new BCHJS()
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
describe("#HDNode", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#fromSeed", () => {
|
||||
fixtures.fromSeed.forEach(mnemonic => {
|
||||
it(`should create an HDNode from root seed buffer`, async () => {
|
||||
@@ -187,75 +178,71 @@ describe("#HDNode", () => {
|
||||
})
|
||||
|
||||
describe("#fromXPriv", () => {
|
||||
it("should exercise fromXPriv", () => {
|
||||
fixtures.fromXPriv.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
it(`should create HDNode from xpriv ${fixture.xpriv}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
fixtures.fromXPriv.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
it(`should create HDNode from xpriv ${fixture.xpriv}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
|
||||
it(`should export xpriv ${fixture.xpriv}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPriv(hdNode), fixture.xpriv)
|
||||
})
|
||||
it(`should export xpriv ${fixture.xpriv}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPriv(hdNode), fixture.xpriv)
|
||||
})
|
||||
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
|
||||
it(`should export privateKeyWIF ${fixture.privateKeyWIF}`, () => {
|
||||
assert.equal(bchjs.HDNode.toWIF(hdNode), fixture.privateKeyWIF)
|
||||
})
|
||||
it(`should export privateKeyWIF ${fixture.privateKeyWIF}`, () => {
|
||||
assert.equal(bchjs.HDNode.toWIF(hdNode), fixture.privateKeyWIF)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#fromXPub", () => {
|
||||
it("should exercise fromXPub", () => {
|
||||
fixtures.fromXPub.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPub(fixture.xpub)
|
||||
it(`should create HDNode from xpub ${fixture.xpub}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
fixtures.fromXPub.forEach(fixture => {
|
||||
const hdNode = bchjs.HDNode.fromXPub(fixture.xpub)
|
||||
it(`should create HDNode from xpub ${fixture.xpub}`, () => {
|
||||
assert.notEqual(hdNode, null)
|
||||
})
|
||||
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
it(`should export xpub ${fixture.xpub}`, () => {
|
||||
assert.equal(bchjs.HDNode.toXPub(hdNode), fixture.xpub)
|
||||
})
|
||||
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
it(`should export legacy address ${fixture.legacy}`, () => {
|
||||
assert.equal(bchjs.HDNode.toLegacyAddress(hdNode), fixture.legacy)
|
||||
})
|
||||
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
it(`should export cashaddress ${fixture.cashaddress}`, () => {
|
||||
assert.equal(bchjs.HDNode.toCashAddress(hdNode), fixture.cashaddress)
|
||||
})
|
||||
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
it(`should export regtest cashaddress ${fixture.regtestaddress}`, () => {
|
||||
assert.equal(
|
||||
bchjs.HDNode.toCashAddress(hdNode, true),
|
||||
fixture.regtestaddress
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("#bip32", () => {
|
||||
it("should create accounts and addresses", () => {
|
||||
describe("create accounts and addresses", () => {
|
||||
fixtures.accounts.forEach(async fixture => {
|
||||
const seedBuffer = await bchjs.Mnemonic.toSeed(fixture.mnemonic)
|
||||
console.log(`seedBuffer: ${seedBuffer.toString()}`)
|
||||
|
||||
+2
-9
@@ -1,17 +1,10 @@
|
||||
// Public npm libraries
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const sinon = require("sinon")
|
||||
|
||||
// Unit under test (uut)
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
let bchjs
|
||||
|
||||
describe("#Mining", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#getBlockTemplate", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
|
||||
+125
-8
@@ -31,7 +31,9 @@ describe(`#Ninsight`, () => {
|
||||
|
||||
it(`should GET utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxo })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.utxo
|
||||
})
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
@@ -57,7 +59,9 @@ describe(`#Ninsight`, () => {
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.utxoPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.utxoPost
|
||||
})
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
@@ -96,7 +100,9 @@ describe(`#Ninsight`, () => {
|
||||
|
||||
it(`should POST utxos for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmed })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.unconfirmed
|
||||
})
|
||||
|
||||
const addr = "bitcoincash:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rku6usknlh5"
|
||||
|
||||
@@ -121,7 +127,9 @@ describe(`#Ninsight`, () => {
|
||||
|
||||
it(`should POST utxo details for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmedPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.unconfirmedPost
|
||||
})
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qpkkjkhe29mqhqmu3evtq3dsnruuzl3rku6usknlh5",
|
||||
@@ -159,7 +167,9 @@ describe(`#Ninsight`, () => {
|
||||
})
|
||||
it(`should POST transaction history for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.transactionsPost
|
||||
})
|
||||
|
||||
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
|
||||
|
||||
@@ -177,7 +187,9 @@ describe(`#Ninsight`, () => {
|
||||
})
|
||||
it(`should POST transaction history for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.transactionsPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.transactionsPost
|
||||
})
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
@@ -212,7 +224,9 @@ describe(`#Ninsight`, () => {
|
||||
})
|
||||
it(`should POST transaction details for a single TxID`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.detailsPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.detailsPost
|
||||
})
|
||||
|
||||
const txid = "fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33"
|
||||
|
||||
@@ -236,7 +250,9 @@ describe(`#Ninsight`, () => {
|
||||
})
|
||||
it(`should POST transaction details for an array of TxIDs`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({ data: mockData.detailsPost })
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.detailsPost
|
||||
})
|
||||
|
||||
const txid = [
|
||||
"fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33",
|
||||
@@ -252,4 +268,105 @@ describe(`#Ninsight`, () => {
|
||||
assert.property(result[0], "vout")
|
||||
})
|
||||
})
|
||||
|
||||
describe(`#addrDetails`, () => {
|
||||
it(`should throw an error for improper input`, async () => {
|
||||
try {
|
||||
const addr = 12345
|
||||
|
||||
await bchjs.Ninsight.details(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 POST address details for a single address`, async () => {
|
||||
// Stub the network call.
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.addrDetailArray
|
||||
})
|
||||
|
||||
const result = await bchjs.Ninsight.details("addr")
|
||||
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[0], "cashAddress")
|
||||
assert.property(result[0], "slpAddress")
|
||||
assert.property(result[0], "currentPage")
|
||||
assert.property(result[0], "pagesTotal")
|
||||
})
|
||||
|
||||
it(`should call constructor with null args`, async () => {
|
||||
new bchjs.Ninsight.constructor({})
|
||||
})
|
||||
|
||||
it(`should POST address details for an array of addresses`, async () => {
|
||||
// Mock the network call.
|
||||
sandbox.stub(axios, "post").resolves({
|
||||
data: mockData.addrDetailArray
|
||||
})
|
||||
|
||||
const addr = [
|
||||
"bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7",
|
||||
"bitcoincash:qz0us0z6ucpqt07jgpad0shgh7xmwxyr3ynlcsq0wr"
|
||||
]
|
||||
|
||||
const result = await bchjs.Ninsight.details(addr)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
|
||||
assert.property(result[0], "balance")
|
||||
assert.property(result[0], "balanceSat")
|
||||
assert.property(result[0], "totalReceived")
|
||||
assert.property(result[0], "totalReceivedSat")
|
||||
assert.property(result[0], "totalSent")
|
||||
assert.property(result[0], "totalSentSat")
|
||||
assert.property(result[0], "unconfirmedBalance")
|
||||
assert.property(result[0], "unconfirmedBalanceSat")
|
||||
assert.property(result[0], "unconfirmedTxApperances")
|
||||
assert.property(result[0], "txApperances")
|
||||
assert.property(result[0], "transactions")
|
||||
assert.property(result[0], "legacyAddress")
|
||||
assert.property(result[1], "cashAddress")
|
||||
assert.property(result[1], "slpAddress")
|
||||
assert.property(result[1], "currentPage")
|
||||
assert.property(result[1], "pagesTotal")
|
||||
|
||||
/*
|
||||
If in any way possible, I would like to refactor this test
|
||||
according to the DRY principle to share it with the integration tests too
|
||||
Would that make sense or does that implicate anything unwanted?
|
||||
|
||||
assertDetails(result[0])
|
||||
|
||||
assertDetails(data) {
|
||||
assert.property(data, "satoshis")
|
||||
assert.property(data, "height")
|
||||
assert.property(data, "confirmations")
|
||||
assert.property(data, "timestamp")
|
||||
assert.property(data, "fees")
|
||||
assert.property(data, "outputIndexes")
|
||||
assert.property(data, "inputIndexes")
|
||||
assert.property(data, "tx")
|
||||
}
|
||||
*/
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+1
-12
@@ -5,7 +5,7 @@ const sinon = require("sinon")
|
||||
const mockDataLib = require("./fixtures/price-mocks")
|
||||
let mockData
|
||||
|
||||
describe("#price", () => {
|
||||
describe("#Price", () => {
|
||||
let sandbox
|
||||
let bchjs
|
||||
|
||||
@@ -56,15 +56,4 @@ describe("#price", () => {
|
||||
assert.property(result, "CAD")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getBchaUsd", () => {
|
||||
it("should get the USD price of BCHA", async () => {
|
||||
sandbox.stub(bchjs.Price.axios, "get").resolves({ data: { usd: 18.87 } })
|
||||
|
||||
const result = await bchjs.Price.getBchaUsd()
|
||||
// console.log(result)
|
||||
|
||||
assert.isNumber(result)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
/*
|
||||
TODO:
|
||||
-Replace old unit tests mocking axios with the more generalized nock library.
|
||||
See the sendRawTransaction test for an example.
|
||||
-Create a mocking library of data to compare unit and integration tests.
|
||||
*/
|
||||
|
||||
// Public npm libraries
|
||||
const assert = require("assert")
|
||||
const axios = require("axios")
|
||||
const sinon = require("sinon")
|
||||
// const nock = require("nock") // HTTP mocking
|
||||
|
||||
// Unit under test (uut)
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const bchjs = new BCHJS()
|
||||
let bchjs
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
const sinon = require("sinon")
|
||||
const nock = require("nock") // HTTP mocking
|
||||
|
||||
// Used for debugging
|
||||
// const util = require("util")
|
||||
// util.inspect.defaultOptions = { depth: 1 }
|
||||
const util = require("util")
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
describe("#RawTransactions", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#decodeRawTransaction", () => {
|
||||
let sandbox
|
||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||
@@ -116,20 +111,19 @@ describe("#RawTransactions", () => {
|
||||
assert.equal(data, result)
|
||||
})
|
||||
|
||||
// it("should send an array of raw transactions", async () => {
|
||||
// const data = "Error: transaction already in block chain"
|
||||
//
|
||||
// // Mock the http call to rest.bitcoin.com
|
||||
// // nock(`${bchjs.RawTransactions.restURL}`)
|
||||
// // .post(uri => uri.includes(`/`))
|
||||
// // .reply(200, { data: data })
|
||||
// sandbox.stub(bchjs, "axios").resolves({ data: data })
|
||||
//
|
||||
// const result = await bchjs.RawTransactions.sendRawTransaction([
|
||||
// "020000000160d663961c63c7f0a07f22ec07b8f55b3935bfdbed8b1d8454916e8932fbf109010000006b4830450221008479fab4cfdcb111833d250a43f98ac26d43272b7a29cb1b9a0491eae5c44b3502203448b17253632395c29a7d62058bbfe93efb20fc8636ba6837002d464195aec04121029123258f7cdcd45b864066bcaa9b71f24d5ed1fa1dd36eaf107d8432b5014658ffffffff016d180000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac00000000"
|
||||
// ])
|
||||
//
|
||||
// assert.equal(data, result.data)
|
||||
// })
|
||||
it("should send an array of raw transactions", async () => {
|
||||
const data = "Error: transaction already in block chain"
|
||||
|
||||
// Mock the http call to rest.bitcoin.com
|
||||
nock(`${bchjs.RawTransactions.restURL}`)
|
||||
.post(uri => uri.includes(`/`))
|
||||
.reply(200, { data: data })
|
||||
|
||||
const result = await bchjs.RawTransactions.sendRawTransaction([
|
||||
"020000000160d663961c63c7f0a07f22ec07b8f55b3935bfdbed8b1d8454916e8932fbf109010000006b4830450221008479fab4cfdcb111833d250a43f98ac26d43272b7a29cb1b9a0491eae5c44b3502203448b17253632395c29a7d62058bbfe93efb20fc8636ba6837002d464195aec04121029123258f7cdcd45b864066bcaa9b71f24d5ed1fa1dd36eaf107d8432b5014658ffffffff016d180000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac00000000"
|
||||
])
|
||||
|
||||
assert.equal(data, result.data)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+20
-31
@@ -1,19 +1,10 @@
|
||||
// Public npm libraries
|
||||
const fixtures = require("./fixtures/script.json")
|
||||
const assert = require("assert")
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
const bchjs = new BCHJS()
|
||||
const Buffer = require("safe-buffer").Buffer
|
||||
|
||||
// Mocks
|
||||
const fixtures = require("./fixtures/script.json")
|
||||
|
||||
// Unit under test (uut)
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
let bchjs
|
||||
|
||||
describe("#Script", () => {
|
||||
beforeEach(() => {
|
||||
bchjs = new BCHJS()
|
||||
})
|
||||
|
||||
describe("#decode", () => {
|
||||
describe("P2PKH scriptSig", () => {
|
||||
fixtures.decodeScriptSig.forEach(fixture => {
|
||||
@@ -330,27 +321,25 @@ describe("#Script", () => {
|
||||
})
|
||||
|
||||
describe("#pubKeyHashOutputTemplate", () => {
|
||||
it("should exercise pubKeyHashOutputTemplate", () => {
|
||||
fixtures.pubKeyHashOutputTemplate.forEach(fixture => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
const identifier = bchjs.HDNode.toIdentifier(node)
|
||||
it(`should encode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
fixtures.pubKeyHashOutputTemplate.forEach(fixture => {
|
||||
const node = bchjs.HDNode.fromXPriv(fixture.xpriv)
|
||||
const identifier = bchjs.HDNode.toIdentifier(node)
|
||||
it(`should encode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
assert.equal(buf.toString("hex"), fixture.hex)
|
||||
})
|
||||
|
||||
it(`should decode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), identifier.toString("hex"))
|
||||
})
|
||||
it(`should decode pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.decode(
|
||||
Buffer.from(`${fixture.hex}`, "hex")
|
||||
)
|
||||
assert.equal(buf.toString("hex"), identifier.toString("hex"))
|
||||
})
|
||||
|
||||
it(`should confirm correctly formatted pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
const valid = bchjs.Script.pubKeyHash.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
it(`should confirm correctly formatted pubKeyHash output`, () => {
|
||||
const buf = bchjs.Script.pubKeyHash.output.encode(identifier)
|
||||
const valid = bchjs.Script.pubKeyHash.output.check(buf)
|
||||
assert.equal(valid, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+74
-82
@@ -1,9 +1,7 @@
|
||||
const assert = require("assert")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
// const SLP = require("../../src/slp/slp")
|
||||
// const SLP = new slp({ restURL: "http://fakeurl.com/" })
|
||||
let slp
|
||||
const slp = require("../../src/slp/slp")
|
||||
const SLP = new slp({ restURL: "http://fakeurl.com/" })
|
||||
|
||||
const fixtures = require("./fixtures/slp/address.json")
|
||||
//const axios = require("axios")
|
||||
@@ -88,18 +86,12 @@ const SLP_TESTNET_ADDRESSES_NO_PREFIX = SLP_TESTNET_ADDRESSES.map(address => {
|
||||
})
|
||||
*/
|
||||
describe("#SLP Address", () => {
|
||||
beforeEach(() => {
|
||||
const bchjs = new BCHJS()
|
||||
// console.log(`bchjs.restURL: ${bchjs.restURL}`)
|
||||
slp = bchjs.SLP
|
||||
})
|
||||
|
||||
describe("#mainnet", () => {
|
||||
describe("#toLegacyAddress", () => {
|
||||
it("should convert mainnet legacy address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -108,7 +100,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert cashAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -117,7 +109,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert slpAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -128,7 +120,7 @@ describe("#SLP Address", () => {
|
||||
it("should convert mainnet cash address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -137,7 +129,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert legacyAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -146,7 +138,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert slpAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -157,7 +149,7 @@ describe("#SLP Address", () => {
|
||||
it("should convert mainnet slp address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
SLP_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -166,7 +158,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert legacyAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -175,7 +167,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert cashAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_MAINNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_MAINNET_ADDRESSES
|
||||
)
|
||||
@@ -186,7 +178,7 @@ describe("#SLP Address", () => {
|
||||
describe("is legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -195,7 +187,7 @@ describe("#SLP Address", () => {
|
||||
describe("cashaddr is not legacy addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -204,7 +196,7 @@ describe("#SLP Address", () => {
|
||||
describe("slpaddr is not legacy addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -215,7 +207,7 @@ describe("#SLP Address", () => {
|
||||
describe("is cashaddr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cashaddr address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -224,7 +216,7 @@ describe("#SLP Address", () => {
|
||||
describe("legacy is not cash addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -233,7 +225,7 @@ describe("#SLP Address", () => {
|
||||
describe("slpaddr is not cash addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -244,7 +236,7 @@ describe("#SLP Address", () => {
|
||||
describe("is slpaddr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -253,7 +245,7 @@ describe("#SLP Address", () => {
|
||||
describe("legacy is not slp addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -262,7 +254,7 @@ describe("#SLP Address", () => {
|
||||
describe("cash is not slp addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -273,7 +265,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -282,7 +274,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet cash addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -291,7 +283,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet slp addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -300,7 +292,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -309,7 +301,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet cash addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -318,7 +310,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet slp addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a mainnet address`, () => {
|
||||
const isMainnetaddr = slp.Address.isMainnetAddress(address)
|
||||
const isMainnetaddr = SLP.Address.isMainnetAddress(address)
|
||||
assert.equal(isMainnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -329,7 +321,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
MAINNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2PKH address`, () => {
|
||||
const isP2PKHaddr = slp.Address.isP2PKHAddress(address)
|
||||
const isP2PKHaddr = SLP.Address.isP2PKHAddress(address)
|
||||
assert.equal(isP2PKHaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -340,7 +332,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
MAINNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2SH address`, () => {
|
||||
const isP2SHaddr = slp.Address.isP2SHAddress(address)
|
||||
const isP2SHaddr = SLP.Address.isP2SHAddress(address)
|
||||
assert.equal(isP2SHaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -350,21 +342,21 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressFormat", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacy = slp.Address.detectAddressFormat(address)
|
||||
const isLegacy = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isLegacy, "legacy")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cash address`, () => {
|
||||
const isCashaddr = slp.Address.detectAddressFormat(address)
|
||||
const isCashaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isCashaddr, "cashaddr")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSlpaddr = slp.Address.detectAddressFormat(address)
|
||||
const isSlpaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isSlpaddr, "slpaddr")
|
||||
})
|
||||
})
|
||||
@@ -373,21 +365,21 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressNetwork", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = slp.Address.detectAddressNetwork(address)
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = slp.Address.detectAddressNetwork(address)
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a mainnet address`, () => {
|
||||
const isMainnet = slp.Address.detectAddressNetwork(address)
|
||||
const isMainnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isMainnet, "mainnet")
|
||||
})
|
||||
})
|
||||
@@ -396,14 +388,14 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressType", () => {
|
||||
MAINNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2pkh address`, () => {
|
||||
const isp2pkh = slp.Address.detectAddressType(address)
|
||||
const isp2pkh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2pkh, "p2pkh")
|
||||
})
|
||||
})
|
||||
|
||||
MAINNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2sh address`, () => {
|
||||
const isp2sh = slp.Address.detectAddressType(address)
|
||||
const isp2sh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2sh, "p2sh")
|
||||
})
|
||||
})
|
||||
@@ -415,7 +407,7 @@ describe("#SLP Address", () => {
|
||||
it("should convert testnet legacy address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -424,7 +416,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert cashAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -433,7 +425,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert slpAddr to legacyAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toLegacyAddress(address)
|
||||
SLP.Address.toLegacyAddress(address)
|
||||
),
|
||||
LEGACY_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -444,7 +436,7 @@ describe("#SLP Address", () => {
|
||||
it("should convert testnet cash address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -453,7 +445,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert legacyAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -462,7 +454,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert slpAddr to cashAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toCashAddress(address)
|
||||
SLP.Address.toCashAddress(address)
|
||||
),
|
||||
CASH_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -473,7 +465,7 @@ describe("#SLP Address", () => {
|
||||
it("should convert testnet slp address format to itself correctly", () => {
|
||||
assert.deepEqual(
|
||||
SLP_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -482,7 +474,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert legacyAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
LEGACY_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -491,7 +483,7 @@ describe("#SLP Address", () => {
|
||||
it(`should convert cashAddr to slpAddr`, async () => {
|
||||
assert.deepEqual(
|
||||
CASH_TESTNET_ADDRESSES.map(address =>
|
||||
slp.Address.toSLPAddress(address)
|
||||
SLP.Address.toSLPAddress(address)
|
||||
),
|
||||
SLP_TESTNET_ADDRESSES
|
||||
)
|
||||
@@ -502,7 +494,7 @@ describe("#SLP Address", () => {
|
||||
describe("is legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -511,7 +503,7 @@ describe("#SLP Address", () => {
|
||||
describe("cashaddr is not legacy addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -520,7 +512,7 @@ describe("#SLP Address", () => {
|
||||
describe("slpaddr is not legacy addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a legacy address`, () => {
|
||||
const isLegacyaddr = slp.Address.isLegacyAddress(address)
|
||||
const isLegacyaddr = SLP.Address.isLegacyAddress(address)
|
||||
assert.equal(isLegacyaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -531,7 +523,7 @@ describe("#SLP Address", () => {
|
||||
describe("is cashaddr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cashaddr address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -540,7 +532,7 @@ describe("#SLP Address", () => {
|
||||
describe("legacy is not cash addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -549,7 +541,7 @@ describe("#SLP Address", () => {
|
||||
describe("slpaddr is not cash addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a cash address`, () => {
|
||||
const isCashaddr = slp.Address.isCashAddress(address)
|
||||
const isCashaddr = SLP.Address.isCashAddress(address)
|
||||
assert.equal(isCashaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -560,7 +552,7 @@ describe("#SLP Address", () => {
|
||||
describe("is slpaddr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -569,7 +561,7 @@ describe("#SLP Address", () => {
|
||||
describe("legacy is not slp addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -578,7 +570,7 @@ describe("#SLP Address", () => {
|
||||
describe("cash is not slp addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not an slp address`, () => {
|
||||
const isSLPaddr = slp.Address.isSLPAddress(address)
|
||||
const isSLPaddr = SLP.Address.isSLPAddress(address)
|
||||
assert.equal(isSLPaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -589,7 +581,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -598,7 +590,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet cash addr", () => {
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -607,7 +599,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet slp addr", () => {
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -616,7 +608,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet legacy addr", () => {
|
||||
LEGACY_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -625,7 +617,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet cash addr", () => {
|
||||
CASH_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -634,7 +626,7 @@ describe("#SLP Address", () => {
|
||||
describe("mainnet slp addr", () => {
|
||||
SLP_MAINNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is not a testnet address`, () => {
|
||||
const isTestnetaddr = slp.Address.isTestnetAddress(address)
|
||||
const isTestnetaddr = SLP.Address.isTestnetAddress(address)
|
||||
assert.equal(isTestnetaddr, false)
|
||||
})
|
||||
})
|
||||
@@ -645,7 +637,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
TESTNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2PKH address`, () => {
|
||||
const isP2PKHaddr = slp.Address.isP2PKHAddress(address)
|
||||
const isP2PKHaddr = SLP.Address.isP2PKHAddress(address)
|
||||
assert.equal(isP2PKHaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -656,7 +648,7 @@ describe("#SLP Address", () => {
|
||||
describe("testnet legacy addr", () => {
|
||||
TESTNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a P2SH address`, () => {
|
||||
const isP2SHaddr = slp.Address.isP2SHAddress(address)
|
||||
const isP2SHaddr = SLP.Address.isP2SHAddress(address)
|
||||
assert.equal(isP2SHaddr, true)
|
||||
})
|
||||
})
|
||||
@@ -666,21 +658,21 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressFormat", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a legacy address`, () => {
|
||||
const isLegacy = slp.Address.detectAddressFormat(address)
|
||||
const isLegacy = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isLegacy, "legacy")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a cash address`, () => {
|
||||
const isCashaddr = slp.Address.detectAddressFormat(address)
|
||||
const isCashaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isCashaddr, "cashaddr")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is an slp address`, () => {
|
||||
const isSlpaddr = slp.Address.detectAddressFormat(address)
|
||||
const isSlpaddr = SLP.Address.detectAddressFormat(address)
|
||||
assert.equal(isSlpaddr, "slpaddr")
|
||||
})
|
||||
})
|
||||
@@ -689,21 +681,21 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressNetwork", () => {
|
||||
LEGACY_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = slp.Address.detectAddressNetwork(address)
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
|
||||
CASH_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = slp.Address.detectAddressNetwork(address)
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
|
||||
SLP_TESTNET_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a testnet address`, () => {
|
||||
const isTestnet = slp.Address.detectAddressNetwork(address)
|
||||
const isTestnet = SLP.Address.detectAddressNetwork(address)
|
||||
assert.equal(isTestnet, "testnet")
|
||||
})
|
||||
})
|
||||
@@ -712,7 +704,7 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressType", () => {
|
||||
TESTNET_P2PKH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2pkh address`, () => {
|
||||
const isp2pkh = slp.Address.detectAddressType(address)
|
||||
const isp2pkh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2pkh, "p2pkh")
|
||||
})
|
||||
})
|
||||
@@ -721,7 +713,7 @@ describe("#SLP Address", () => {
|
||||
describe("#detectAddressType", () => {
|
||||
TESTNET_P2SH_ADDRESSES.forEach(address => {
|
||||
it(`should detect ${address} is a p2sh address`, () => {
|
||||
const isp2sh = slp.Address.detectAddressType(address)
|
||||
const isp2sh = SLP.Address.detectAddressType(address)
|
||||
assert.equal(isp2sh, "p2sh")
|
||||
})
|
||||
})
|
||||
@@ -761,7 +753,7 @@ describe("#details", () => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
slp.Address.details(
|
||||
SLP.Address.details(
|
||||
"simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
)
|
||||
.then(result => {
|
||||
@@ -796,7 +788,7 @@ describe("#utxo", () => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
slp.Address.utxo("simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6")
|
||||
SLP.Address.utxo("simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6")
|
||||
.then(result => {
|
||||
assert.deepEqual(
|
||||
"467969e067f5612863d0bf2daaa70dede2c6be03abb6fd401c5ef6e1e1f1f5c5",
|
||||
@@ -823,7 +815,7 @@ describe("#unconfirmed", () => {
|
||||
const resolved = new Promise(r => r({ data: data }))
|
||||
sandbox.stub(axios, "get").returns(resolved)
|
||||
|
||||
slp.Address.unconfirmed(
|
||||
SLP.Address.unconfirmed(
|
||||
"simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
)
|
||||
.then(result => {
|
||||
@@ -836,7 +828,7 @@ describe("#unconfirmed", () => {
|
||||
|
||||
// (async () => {
|
||||
// try {
|
||||
// const details = await slp.Address.unconfirmed(
|
||||
// const details = await SLP.Address.unconfirmed(
|
||||
// "simpleledger:qr4zg7xth86yzq94gl8jvnf5z4wuupzt3gev5wtnm6"
|
||||
// )
|
||||
// console.log(details)
|
||||
|
||||
+3
-12
@@ -1,19 +1,10 @@
|
||||
const fixtures = require("./fixtures/slp/ecpair.json")
|
||||
const assert = require("assert")
|
||||
|
||||
const fixtures = require("./fixtures/slp/ecpair.json")
|
||||
|
||||
const BCHJS = require("../../src/bch-js")
|
||||
let slp
|
||||
|
||||
// const SLP = require("../../src/slp/slp")
|
||||
// const slp = new SLP({ restURL: "http://fakeurl.com/" })
|
||||
const SLP = require("../../src/slp/slp")
|
||||
const slp = new SLP({ restURL: "http://fakeurl.com/" })
|
||||
|
||||
describe("#SLP ECPair", () => {
|
||||
beforeEach(() => {
|
||||
const bchjs = new BCHJS()
|
||||
slp = bchjs.SLP
|
||||
})
|
||||
|
||||
describe("#toSLPAddress", () => {
|
||||
it(`should return slp address for ecpair`, async () => {
|
||||
fixtures.wif.forEach((wif, index) => {
|
||||
|
||||
+1
-1117
File diff suppressed because it is too large
Load Diff
+484
-716
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user