Compare commits

...
78 Commits
Author SHA1 Message Date
Chris Troutner c74b675bc9 Merge branch 'master' into nft-docs-fixes 2021-11-13 06:47:17 -08:00
Chris Troutner d0129c01f3 Merge pull request #196 from Permissionless-Software-Foundation/temp-documentation
Temp documentation
2021-11-13 06:46:59 -08:00
Chris Troutner ad40607e5b Merge pull request #186 from mr-zwets/documentation-fix
small fixes documentation
2021-11-13 06:43:55 -08:00
Chris Troutner a4f0ee6e42 Merge branch 'master' into documentation-fix 2021-11-13 06:42:57 -08:00
Chris Troutner 0b70ea108b Merge pull request #195 from Permissionless-Software-Foundation/temp-documentation
Temp documentation
2021-11-13 06:42:05 -08:00
Chris Troutner cef9a3cf52 Merge pull request #194 from mr-zwets/documentation
clarified some of the documentation
2021-11-13 06:38:04 -08:00
mathi c216f6c075 clarified some of the documentation 2021-11-13 11:37:56 +01:00
Chris Troutner b53f6bcfc6 Merge pull request #193 from Permissionless-Software-Foundation/ct-unstable
fix(tests): Moving util.js integration tests to bchn specific folder
2021-11-10 18:16:45 -08:00
Chris Troutner cbc834cc1a fix(tests): Moving util.js integration tests to bchn specific folder 2021-11-10 17:32:17 -08:00
Chris Troutner 1cb5fe069b Merge pull request #192 from Permissionless-Software-Foundation/ct-unstable
Created Transaction.get3() to help with SLP indexer
2021-11-03 10:21:21 -07:00
Chris Troutner 425e2cbbc1 fix(Transaction.get3()): Created Transaction.get3() 2021-11-03 10:16:38 -07:00
Chris Troutner 9e92f77523 Making progress on Transaction.get3() 2021-11-03 07:53:56 -07:00
Chris Troutner dc85bb4cfe Making progress on Transaction.get3() 2021-11-03 07:53:42 -07:00
Chris Troutner 92960b6957 Merge branch 'master' into ct-unstable 2021-11-02 20:37:07 -07:00
Chris Troutner 6f34ea286a Merge pull request #191 from Permissionless-Software-Foundation/fix-bip32
fix(bip32-util): Moving to @chris.troutner/bip32-util
2021-11-01 06:21:49 -07:00
Chris Troutner 26f39023c4 fix(bip32-util): Moving to @chris.troutner/bip32-util 2021-11-01 06:18:55 -07:00
Chris Troutner 4a3baca72d Messing around with different variations of transaction.get2() 2021-11-01 06:12:14 -07:00
Chris Troutner fe37c3ca43 Merge pull request #190 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get2()): Improvement to vin token inputs
2021-10-31 18:56:09 -07:00
Chris Troutner ff4ffab670 fix(Transaction.get2()): Improvement to vin token inputs 2021-10-31 18:50:47 -07:00
Chris Troutner 400e7b31a8 Merge pull request #189 from Permissionless-Software-Foundation/ct-unstable
Adding Transaction.get2()
2021-10-31 17:02:14 -07:00
Chris Troutner 360fca0475 fix(Transaction.get2()): Added block height to tx data 2021-10-31 16:58:40 -07:00
Chris Troutner ef7056ee7a fix(Transaction.get2()): Added non-validating tx get 2021-10-31 16:29:50 -07:00
Chris Troutner d221077786 Merge pull request #188 from Permissionless-Software-Foundation/ct-unstable
fix(Jenkins): Attempting to fix CI/CD
2021-10-31 14:52:22 -07:00
Chris Troutner 046ab78c6a fix(Jenkins): Attempting to fix CI/CD 2021-10-31 14:44:07 -07:00
Chris Troutner 29e90915e7 Merge pull request #187 from Permissionless-Software-Foundation/ct-unstable
fix(bip-32): Updated bip-32 library to improve vulns
2021-10-31 14:31:52 -07:00
Chris Troutner 3d85dbfb22 Updating depds 2021-10-31 14:26:43 -07:00
Chris Troutner 2c0fa9dfbd Switched to exact dependency versions 2021-10-31 14:22:36 -07:00
Chris Troutner 6ca1d729dc fix(bip-32): Updated bip-32 library to improve vulns 2021-10-31 14:14:13 -07:00
Chris Troutner c095af8a29 Merge branch 'master' into documentation-fix 2021-10-30 09:07:46 -07:00
mathi 89e4ea1635 small fixes documentation 2021-10-30 17:06:46 +02:00
Chris Troutner 85a34a8305 Merge pull request #185 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get()): Adding token ID to tx token inputs
2021-10-28 16:58:56 -07:00
Chris Troutner ef6cfe4409 fix(Transaction.get()): Adding token ID to tx token inputs 2021-10-28 16:56:35 -07:00
Chris Troutner a29d6ed26a Merge pull request #184 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get()): Validating SLP inputs
2021-10-21 21:07:15 -07:00
Chris Troutner fa58a0764c fix(Transaction.get()): Validating SLP inputs 2021-10-21 21:04:11 -07:00
Chris Troutner 2c2fbeaa46 Merge pull request #183 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get()): Fixing another bug in MINT input handling
2021-10-21 20:47:03 -07:00
Chris Troutner 1e4cd5f99e fix(Transaction.get()): Fixing another bug in MINT input handling 2021-10-21 20:44:47 -07:00
Chris Troutner 52c1ebdafe Merge pull request #182 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get()): Fixing bug in previous PR
2021-10-21 19:45:36 -07:00
Chris Troutner 2e56d66f48 fix(Transaction.get()): Fixing bug in previous PR 2021-10-21 19:42:12 -07:00
Chris Troutner 9cf6c7e7a7 Merge pull request #181 from Permissionless-Software-Foundation/ct-unstable
fix(Transaction.get()): Adding support for MINT corner-case
2021-10-21 19:15:08 -07:00
Chris Troutner 43043672c6 linting 2021-10-21 19:12:10 -07:00
Chris Troutner 4f4b2c864d fix(Transaction.get()): Adding support for MINT corner-case 2021-10-21 19:11:55 -07:00
Chris Troutner 951fea8f9b Merge pull request #180 from Permissionless-Software-Foundation/ct-unstable
fix(npm): Ran npm audit fix, to fix vulns
2021-10-16 09:49:50 -07:00
Chris Troutner 6d75dceffb fix(npm): Ran npm audit fix, to fix vulns 2021-10-16 09:46:55 -07:00
Chris Troutner 3a491c7aba Merge pull request #178 from Permissionless-Software-Foundation/ct-unstable
fix(generateGenesisOpReturn): Fixing bug when 0 decimal
2021-10-14 13:08:31 -07:00
Chris Troutner f03c020e4f fix(generateGenesisOpReturn): Fixing bug when 0 decimal 2021-10-14 13:06:15 -07:00
Chris Troutner 4aeb1148e5 Merge pull request #177 from Permissionless-Software-Foundation/review01
added toEcashAddress() & ecashtoCashAddress() for ecash format support
2021-10-04 07:55:41 -07:00
Chris Troutner f03ee13a1e Merge pull request #175 from mr-zwets/master
conversion between bitcoincash: and ecash:
2021-10-04 06:55:48 -07:00
mr-zwets cb98773d6a Merge branch 'Permissionless-Software-Foundation:master' into master 2021-09-23 07:43:07 +02:00
Chris Troutner c593d68ee5 Merge pull request #176 from Permissionless-Software-Foundation/ct-unstable
Improvements to Transaction.get()
2021-09-22 17:36:30 -07:00
Chris Troutner dc7d3a9339 fix(Transaction.get): Using BigNumber for better tokenqty calc 2021-09-22 17:33:27 -07:00
Chris Troutner 6f4cc0f439 fix(Transaction.get): Fixed bug when Genesis TX was input to queried TX 2021-09-22 16:58:14 -07:00
Chris Troutner 7aa0fa865e fix(decodeOpReturn): Fixed api docs 2021-09-22 15:40:23 -07:00
mathi e8b6d7fb36 added toEcashAddress() & ecashtoCashAddress() for ecash format support 2021-09-22 14:38:54 +02:00
Chris Troutner b13ef94ea3 Merge pull request #174 from Permissionless-Software-Foundation/ct-unstable
fix(npm): Ran npm audit fix, 0 vulns
2021-09-20 16:07:18 -07:00
Chris Troutner 912f899f4e fix(npm): Ran npm audit fix, 0 vulns 2021-09-20 16:04:14 -07:00
Chris Troutner 9063d8da0b Merge pull request #173 from Permissionless-Software-Foundation/feat/ecash-price
Feat/ecash price
2021-09-20 16:00:32 -07:00
Chris Troutner f4e2bd96f0 fix(XEC price): Fixing BCHA XEC price feeds 2021-09-20 15:56:42 -07:00
Chris Troutner 1c898a4ad3 Removing ninsight from integration tests 2021-09-20 15:54:54 -07:00
Chris Troutner c4db813f76 Merge pull request #172 from mr-zwets/master
changed getBchaUsd which returns the price for the BCHA denomination, added getXecUsd for the XEC denomination
2021-09-20 15:33:30 -07:00
mathi 38b96b441f changed getBchaUsd so it returns the BCHA denomination, added getXecUsd 2021-09-20 22:13:24 +02:00
Chris Troutner c94f78f510 Merge pull request #170 from Permissionless-Software-Foundation/ct-unstable
fix(minimal-slp-wallet): Fixed code that was breaking minimal-slp-wal…
2021-08-12 09:16:52 -07:00
Chris Troutner 6de2b712ec fix(minimal-slp-wallet): Fixed code that was breaking minimal-slp-wallet build 2021-08-12 09:14:29 -07:00
Chris Troutner 6f681fd7b0 Merge pull request #169 from Permissionless-Software-Foundation/ct-unstable
fix(npm): Ran npm audit fix. 0 vulns
2021-08-09 17:59:43 -07:00
Chris Troutner 9a82effb2b fix(npm): Ran npm audit fix. 0 vulns 2021-08-09 17:41:38 -07:00
Chris Troutner 955a5e428e Merge pull request #168 from Permissionless-Software-Foundation/ct-unstable
fix(getRawTransaction): Fixing integration test
2021-08-09 14:56:52 -07:00
Chris Troutner 44c3bf44f9 fix(getRawTransaction): Fixing integration test 2021-08-09 14:54:49 -07:00
Chris Troutner 31ce84abb0 Merge pull request #167 from Permissionless-Software-Foundation/ct-unstable
fix(waterfallValidateTxid): Skipping validateTxid3() if it throws an error
2021-08-09 10:39:18 -07:00
Chris Troutner 40fa4b6bc1 linting 2021-08-09 10:36:07 -07:00
Chris Troutner 8c5e111d60 fix(waterfallValidateTxid): Skipping validateTxid3() if it throws an error 2021-08-09 10:35:51 -07:00
Chris Troutner 8965dfc57f Merge pull request #166 from Permissionless-Software-Foundation/ct-unstable
fix(apiToken): Changed _this.axiosOptions to this.axiosOptions
2021-08-08 20:06:05 -07:00
Chris Troutner 93904a632f fix(apiToken): Changed _this.axiosOptions to this.axiosOptions 2021-08-08 20:01:38 -07:00
Chris Troutner 851d4c404c fix(rate limits): Fixing more bugs with rate limit handling axios.options 2021-08-08 19:51:01 -07:00
Chris Troutner 44bac45c32 Updating README 2021-08-08 18:42:04 -07:00
Chris Troutner 95ee8054be Merge pull request #165 from Permissionless-Software-Foundation/ct-unstable
fix(Transactions.get()): Adding extra error handling for rate limits
2021-08-08 18:40:43 -07:00
Chris Troutner 547b28cac8 fix(Transactions.get()): Adding extra error handling for rate limits 2021-08-08 18:38:46 -07:00
Chris Troutner 40ba334a41 Merge pull request #163 from Permissionless-Software-Foundation/ct-unstable
fix(validateTxid3): Throwing an error when rate limit encountered.
2021-08-08 18:06:52 -07:00
Chris Troutner ffd8ccaf2b fix(validateTxid3): Throwing an error when rate limit encountered. 2021-08-08 18:04:39 -07:00
Stoyan Zhekov ee7ab54d26 Some NFT-related calls sample usage fixes 2021-07-21 11:26:35 +09:00
43 changed files with 9311 additions and 13413 deletions
+4 -6
View File
@@ -33,17 +33,13 @@ Here are two YouTube walk-through videos to help you get started:
```
const BCHJS = require("@psf/bch-js")
let bchjs = new BCHJS() // Defaults to BCHN network.
// testnet
bchjs = new BCHJS({ restURL: 'https://testnet3.fullstack.cash/v4/' })
```
This library is intended to be paired with
the [bch-api](https://github.com/Permissionless-Software-Foundation/bch-api) REST API, and the infrastructure provided by [FullStack.cash](https://fullstack.cash). The `restURL` property can be changed to work with different Bitcoin Cash networks:
- BCHN Mainnet REST API server: https://bchn.fullstack.cash/v4/
- ABC Mainnet REST API server: https://abc.fullstack.cash/v4/
- Testnet3 REST API server: https://testnet3.fullstack.cash/v4/
- BCHN Mainnet REST API server: https://bchn.fullstack.cash/v5/
- ABC Mainnet REST API server: https://abc.fullstack.cash/v5/
- Check server status: https://metrics.fullstack.cash
### API Key
@@ -122,3 +118,5 @@ Copies of this repository are also published on [IPFS](https://ipfs.io).
## License
[MIT](LICENSE.md)
test
+7312 -12890
View File
File diff suppressed because it is too large Load Diff
+44 -44
View File
@@ -18,7 +18,8 @@
"test:integration:local:abc": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:local:bchn": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v5/ mocha --timeout 30000 test/integration/chains/testnet",
"test:integration:decatur:bchn": "export RESTURL=http://192.168.0.36:3000/v5/ && mocha --timeout 30000 test/integration/",
"test:integration:decatur:bchn": "export RESTURL=http://192.168.0.36:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:decatur:abc": "export RESTURL=http://192.168.0.38:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:temp:bchn": "export RESTURL=http://157.90.174.219:3000/v5/ && mocha --timeout 30000 test/integration/",
"test:temp": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 -g '#Encryption' test/integration/",
"test:temp2": "mocha --timeout=30000 -g '#TransactionLib' test/unit/",
@@ -36,53 +37,52 @@
"url": "git+https://github.com/Permissionless-Software-Foundation/bch-js.git"
},
"dependencies": {
"@psf/bip21": "^2.0.1",
"@psf/bip32-utils": "^1.0.0",
"@psf/bitcoincash-ops": "^2.0.0",
"@psf/bitcoincashjs-lib": "^4.0.2",
"@psf/coininfo": "^4.0.0",
"@uppy/core": "^1.10.4",
"@uppy/tus": "^1.5.12",
"axios": "^0.21.1",
"bc-bip68": "^1.0.5",
"bchaddrjs-slp": "^0.2.5",
"bigi": "^1.4.2",
"bignumber.js": "^9.0.0",
"bip-schnorr": "^0.3.0",
"bip38": "^2.0.2",
"bip39": "^3.0.2",
"bip66": "^1.1.5",
"bitcoinjs-message": "^2.0.0",
"bs58": "^4.0.1",
"cashaddrjs": "^0.3.3",
"ini": "^1.3.8",
"randombytes": "^2.0.6",
"safe-buffer": "^5.1.2",
"satoshi-bitcoin": "^1.0.4",
"@psf/bip21": "2.0.1",
"@chris.troutner/bip32-utils": "1.0.5",
"@psf/bitcoincash-ops": "2.0.0",
"@psf/bitcoincashjs-lib": "4.0.2",
"@psf/coininfo": "4.0.0",
"@uppy/core": "1.10.4",
"@uppy/tus": "1.5.12",
"axios": "^0.21.4",
"bc-bip68": "1.0.5",
"bchaddrjs-slp": "0.2.5",
"bigi": "1.4.2",
"bignumber.js": "9.0.0",
"bip-schnorr": "0.3.0",
"bip38": "2.0.2",
"bip39": "3.0.2",
"bip66": "1.1.5",
"bitcoinjs-message": "2.0.0",
"bs58": "4.0.1",
"ecashaddrjs": "1.0.7",
"ini": "1.3.8",
"randombytes": "2.0.6",
"safe-buffer": "5.1.2",
"satoshi-bitcoin": "1.0.4",
"slp-mdm": "0.0.6",
"slp-parser": "0.0.4",
"wif": "^2.0.6"
"wif": "2.0.6"
},
"devDependencies": {
"apidoc": "^0.17.7",
"assert": "^2.0.0",
"chai": "^4.1.2",
"coveralls": "^3.0.2",
"eslint": "5.16.0",
"eslint-config-prettier": "^6.0.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-standard": "^4.0.0",
"husky": "^4.3.6",
"lodash.clonedeep": "^4.5.0",
"mocha": "^6.1.4",
"node-mocks-http": "^1.7.0",
"nyc": "^14.1.0",
"prettier": "^1.18.2",
"semantic-release": "^17.3.9",
"sinon": "^7.3.2",
"standard": "^16.0.3"
"apidoc": "0.17.7",
"assert": "2.0.0",
"chai": "4.1.2",
"coveralls": "3.0.2",
"eslint": "7.17.0",
"eslint-config-prettier": "7.1.0",
"eslint-config-standard": "16.0.3",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-standard": "4.0.0",
"husky": "^4.3.8",
"lodash.clonedeep": "4.5.0",
"mocha": "9.1.3",
"node-mocks-http": "1.7.0",
"nyc": "15.1.0",
"semantic-release": "18.0.0",
"sinon": "9.2.2",
"standard": "^16.0.4"
},
"apidoc": {
"title": "bch-js",
+77 -4
View File
@@ -1,6 +1,6 @@
// const axios = require("axios")
const Bitcoin = require('@psf/bitcoincashjs-lib')
const cashaddr = require('cashaddrjs')
const cashaddr = require('ecashaddrjs')
const coininfo = require('@psf/coininfo')
class Address {
@@ -129,6 +129,63 @@ class Address {
return cashAddress.split(':')[1]
}
/**
* @api Address.toEcashAddress() toEcashAddress()
* @apiName toEcashAddress
* @apiGroup Address
* @apiDescription Convert legacy to cashAddress format
*
* @apiExample Example usage:
* // mainnet
* bchjs.Address.toEcashAddress('bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2')
* // ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da
*
* // mainnet no prefix
* bchjs.Address.toEcashAddress('bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2', false)
* // qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da
*
*/
toEcashAddress (address, prefix = true) {
const decoded = this._decode(address)
const ecashAddress = cashaddr.encode(
'ecash',
decoded.type,
decoded.hash
)
if (prefix) return ecashAddress
return ecashAddress.split(':')[1]
}
/**
* @api Address.ecashtoCashAddress() ecashtoCashAddress()
* @apiName ecashtoCashAddress
* @apiGroup Address
* @apiDescription Convert legacy to cashAddress format
*
* @apiExample Example usage:
* // mainnet
* bchjs.Address.ecashtoCashAddress('ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da')
* // bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2
*
* // mainnet no prefix
* bchjs.Address.ecashtoCashAddress('ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da', false)
* // qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2
*/
ecashtoCashAddress (address, prefix = true) {
const decoded = this._decodeEcashAddress(address)
const cashAddress = cashaddr.encode(
'bitcoincash',
decoded.type,
decoded.hash
)
if (prefix) return cashAddress
return cashAddress.split(':')[1]
}
// Converts any address format to hash160
toHash160 (address) {
const legacyAddress = this.toLegacyAddress(address)
@@ -166,7 +223,7 @@ class Address {
* @api Address.hash160ToCash() hash160ToCash()
* @apiName hash160ToCash
* @apiGroup Address
* @apiDescription Convert hash160 to cash address.
* @apiDescription Convert hash160 to cash address. Accepts either hexadecimal or buffer.
*
* @apiExample Example usage:
* bchjs.Address.hash160ToCash("573d93b475be4f1925f3b74ed951201b0147eac1")
@@ -271,6 +328,22 @@ class Address {
throw new Error(`Invalid format : ${address}`)
}
_decodeEcashAddress (address) {
if (address.indexOf(':') !== -1) {
const decoded = cashaddr.decode(address)
decoded.format = 'cashaddr'
return decoded
}
try {
const decoded = cashaddr.decode(`ecash:${address}`)
decoded.format = 'cashaddr'
return decoded
} catch (error) {}
throw new Error(`Invalid format : ${address}`)
}
/**
* @api Address.isLegacyAddress() isLegacyAddress()
* @apiName isLegacyAddress
@@ -721,13 +794,13 @@ class Address {
* @apiDescription Detect an addess from an OutputScript..
*
* @apiExample Example usage:
* const script = bchjs.Script.encode([
* const scriptBuffer = bchjs.Script.encode([
* Buffer.from("BOX", "ascii"),
* bchjs.Script.opcodes.OP_CAT,
* Buffer.from("BITBOX", "ascii"),
* bchjs.Script.opcodes.OP_EQUAL
* ]);
* const p2sh_hash160 = bchjs.Crypto.hash160(script);
* const p2sh_hash160 = bchjs.Crypto.hash160(scriptBuffer);
* const scriptPubKey = bchjs.Script.scriptHash.output.encode(p2sh_hash160);
*
* // mainnet address from output script
+26 -26
View File
@@ -5,7 +5,7 @@
const axios = require('axios')
let _this
// let _this
class Blockchain {
constructor (config) {
@@ -29,7 +29,7 @@ class Blockchain {
}
}
_this = this
// _this = this
}
/**
@@ -54,7 +54,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getBestBlockHash`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -112,7 +112,7 @@ class Blockchain {
blockhash,
verbosity
},
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -162,7 +162,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getBlockchainInfo`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -193,7 +193,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getBlockCount`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -226,7 +226,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getBlockHash/${height}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -273,7 +273,7 @@ class Blockchain {
if (typeof hash === 'string') {
const response = await axios.get(
`${this.restURL}blockchain/getBlockHeader/${hash}?verbose=${verbose}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -287,7 +287,7 @@ class Blockchain {
hashes: hash,
verbose: verbose
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -334,7 +334,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getChainTips`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -366,7 +366,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getDifficulty`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -382,7 +382,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getMempoolAncestors/${txid}?verbose=${verbose}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -397,7 +397,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getMempoolDescendants/${txid}?verbose=${verbose}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -494,7 +494,7 @@ class Blockchain {
if (typeof txid === 'string') {
const response = await axios.get(
`${this.restURL}blockchain/getMempoolEntry/${txid}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -505,7 +505,7 @@ class Blockchain {
{
txids: txid
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -545,7 +545,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getMempoolInfo`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -592,7 +592,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/getRawMempool?vebose=${verbose}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -636,7 +636,7 @@ class Blockchain {
// Send the request to the REST API.
// const response = await axios.get(
// `${this.restURL}blockchain/getTxOut/${txid}/${n}?includeMempool=${includeMempool}`,
// _this.axiosOptions
// this.axiosOptions
// )
const response = await axios.post(
`${this.restURL}blockchain/getTxOut`,
@@ -645,7 +645,7 @@ class Blockchain {
vout: n,
mempool: includeMempool
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -698,7 +698,7 @@ class Blockchain {
const path = `${this.restURL}blockchain/getTxOutProof/${txids}`
// if (blockhash) path = `${path}?blockhash=${blockhash}`
const response = await axios.get(path, _this.axiosOptions)
const response = await axios.get(path, this.axiosOptions)
return response.data
// Array of txids.
@@ -709,7 +709,7 @@ class Blockchain {
{
txids: txids
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -726,7 +726,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/preciousBlock/${blockhash}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -739,7 +739,7 @@ class Blockchain {
try {
const response = await axios.post(
`${this.restURL}blockchain/pruneBlockchain/${height}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -752,7 +752,7 @@ class Blockchain {
try {
const response = await axios.get(
`${this.restURL}blockchain/verifyChain?checklevel=${checklevel}&nblocks=${nblocks}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -804,7 +804,7 @@ class Blockchain {
if (typeof proof === 'string') {
const response = await axios.get(
`${this.restURL}blockchain/verifyTxOutProof/${proof}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -816,7 +816,7 @@ class Blockchain {
{
proofs: proof
},
_this.axiosOptions
this.axiosOptions
)
return response.data
+4 -4
View File
@@ -4,7 +4,7 @@
const axios = require('axios')
let _this // Global reference to the instance of this class.
// let _this // Global reference to the instance of this class.
class Control {
constructor (config) {
@@ -28,7 +28,7 @@ class Control {
}
}
_this = this
// _this = this
}
/**
@@ -81,7 +81,7 @@ class Control {
try {
const response = await axios.get(
`${this.restURL}control/getNetworkInfo`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -94,7 +94,7 @@ class Control {
try {
const response = await axios.get(
`${this.restURL}control/getMemoryInfo`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
+2 -2
View File
@@ -60,7 +60,7 @@ class Crypto {
* @api Crypto.hash256() hash256()
* @apiName hash256
* @apiGroup Crypto
* @apiDescription Utility for creating double sha256 hash digests of data.
* @apiDescription Utility for creating double sha256 hash digests of buffer encoded data.
*
* @apiExample Example usage:
* // buffer from hex
@@ -86,7 +86,7 @@ class Crypto {
* @api Crypto.hash160() hash160()
* @apiName hash160
* @apiGroup Crypto
* @apiDescription Utility for creating ripemd160(sha256()) hash digests of data.
* @apiDescription Utility for creating ripemd160(sha256()) hash digests of buffer encoded data.
*
* @apiExample Example usage:
* // buffer from hex
+1 -1
View File
@@ -68,7 +68,7 @@ class DSProof {
}
const response = await _this.axios.get(
`${this.restURL}dsproof/getdsproof/${txid}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
+16 -16
View File
@@ -8,7 +8,7 @@ const axios = require('axios')
// Local libraries.
const Blockchain = require('./blockchain')
let _this
// let _this
class ElectrumX {
constructor (config) {
@@ -34,7 +34,7 @@ class ElectrumX {
this.blockchain = new Blockchain(config)
_this = this
// _this = this
}
/**
@@ -108,7 +108,7 @@ class ElectrumX {
if (typeof address === 'string') {
const response = await axios.get(
`${this.restURL}electrumx/utxos/${address}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -119,7 +119,7 @@ class ElectrumX {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -142,7 +142,7 @@ class ElectrumX {
* (async () => {
* try {
* let balance = await bchjs.Electrumx.balance('bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf');
* console.log(utxo);
* console.log(balance);
* } catch(error) {
* console.error(error)
* }
@@ -159,7 +159,7 @@ class ElectrumX {
* (async () => {
* try {
* let balance = await bchjs.Electrumx.balance(['bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf', 'bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v']);
* console.log(utxo);
* console.log(balance);
* } catch(error) {
* console.error(error)
* }
@@ -192,7 +192,7 @@ class ElectrumX {
if (typeof address === 'string') {
const response = await axios.get(
`${this.restURL}electrumx/balance/${address}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -203,7 +203,7 @@ class ElectrumX {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -290,7 +290,7 @@ class ElectrumX {
if (typeof address === 'string') {
const response = await axios.get(
`${this.restURL}electrumx/transactions/${address}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -302,7 +302,7 @@ class ElectrumX {
addresses: address,
usrObj // pass user data when making an internal call.
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -383,7 +383,7 @@ class ElectrumX {
if (typeof address === 'string') {
const response = await axios.get(
`${this.restURL}electrumx/unconfirmed/${address}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -394,7 +394,7 @@ class ElectrumX {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -452,7 +452,7 @@ class ElectrumX {
try {
const response = await axios.get(
`${this.restURL}electrumx/block/headers/${height}?count=${count}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -543,7 +543,7 @@ class ElectrumX {
if (typeof txid === 'string') {
const response = await axios.get(
`${this.restURL}electrumx/tx/data/${txid}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} else if (Array.isArray(txid)) {
@@ -552,7 +552,7 @@ class ElectrumX {
{
txids: txid
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -592,7 +592,7 @@ class ElectrumX {
const response = await axios.post(
`${this.restURL}electrumx/tx/broadcast`,
{ txHex },
_this.axiosOptions
this.axiosOptions
)
return response.data
+4 -2
View File
@@ -35,11 +35,13 @@ class Encryption {
// Search the blockchain for a public key associated with a BCH address.
async getPubKey (addr) {
try {
if (!addr || typeof addr !== 'string') { throw new Error('Input must be a valid Bitcoin Cash address.') }
if (!addr || typeof addr !== 'string') {
throw new Error('Input must be a valid Bitcoin Cash address.')
}
const response = await _this.axios.get(
`${this.restURL}encryption/publickey/${addr}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
+3 -3
View File
@@ -1,6 +1,6 @@
const axios = require('axios')
let _this
// let _this
class Generating {
constructor (config) {
@@ -24,14 +24,14 @@ class Generating {
}
}
_this = this
// _this = this
}
async generateToAddress (blocks, address, maxtries = 1000000) {
try {
const response = await axios.post(
`${this.restURL}generating/generateToAddress/${blocks}/${address}?maxtries=${maxtries}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
+4 -2
View File
@@ -1,6 +1,6 @@
const Bitcoin = require('@psf/bitcoincashjs-lib')
const coininfo = require('@psf/coininfo')
const bip32utils = require('@psf/bip32-utils')
const bip32utils = require('@chris.troutner/bip32-utils')
const bchaddrjs = require('bchaddrjs-slp')
class HDNode {
@@ -34,7 +34,9 @@ class HDNode {
*/
fromSeed (rootSeedBuffer, network = 'mainnet') {
let bitcoincash
if (network === 'bitcoincash' || network === 'mainnet') { bitcoincash = coininfo.bitcoincash.main } else bitcoincash = coininfo.bitcoincash.test
if (network === 'bitcoincash' || network === 'mainnet') {
bitcoincash = coininfo.bitcoincash.main
} else bitcoincash = coininfo.bitcoincash.test
const bitcoincashBitcoinJSLib = bitcoincash.toBitcoinJS()
return Bitcoin.HDNode.fromSeedBuffer(
+6 -6
View File
@@ -1,6 +1,6 @@
const axios = require('axios')
let _this
// let _this
class Mining {
constructor (config) {
@@ -24,14 +24,14 @@ class Mining {
}
}
_this = this
// _this = this
}
async getBlockTemplate (templateRequest) {
try {
const response = await axios.get(
`${this.restURL}mining/getBlockTemplate/${templateRequest}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -44,7 +44,7 @@ class Mining {
try {
const response = await axios.get(
`${this.restURL}mining/getMiningInfo`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -57,7 +57,7 @@ class Mining {
try {
const response = await axios.get(
`${this.restURL}mining/getNetworkHashps?nblocks=${nblocks}&height=${height}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
@@ -71,7 +71,7 @@ class Mining {
if (parameters) path = `${path}?parameters=${parameters}`
try {
const response = await axios.post(path, _this.axiosOptions)
const response = await axios.post(path, this.axiosOptions)
return response.data
} catch (error) {
if (error.response && error.response.data) throw error.response.data
+10 -10
View File
@@ -5,7 +5,7 @@
const axios = require('axios')
let _this
// let _this
class Ninsight {
constructor (config) {
@@ -27,7 +27,7 @@ class Ninsight {
}
}
_this = this
// _this = this
}
/**
@@ -75,7 +75,7 @@ class Ninsight {
{
addresses: [address]
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -86,7 +86,7 @@ class Ninsight {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -143,7 +143,7 @@ class Ninsight {
{
addresses: [address]
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -153,7 +153,7 @@ class Ninsight {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -219,7 +219,7 @@ class Ninsight {
{
addresses: [address]
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -229,7 +229,7 @@ class Ninsight {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -292,7 +292,7 @@ class Ninsight {
{
txids: [txid]
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -302,7 +302,7 @@ class Ninsight {
{
txids: txid
},
_this.axiosOptions
this.axiosOptions
)
return response.data
+52 -13
View File
@@ -1,10 +1,10 @@
const axios = require('axios')
let _this
// let _this
class Price {
constructor (config) {
_this = this
// _this = this
this.restURL = config.restURL
this.apiToken = config.apiToken
@@ -58,7 +58,7 @@ class Price {
* let current = await bchjs.Price.getUsd();
* console.log(current);
* } catch(err) {
* console.err(err)
* console.error(err)
* }
*})()
*
@@ -68,7 +68,7 @@ class Price {
try {
const response = await this.axios.get(
`${this.restURL}price/usd`,
_this.axiosOptions
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
@@ -94,7 +94,7 @@ class Price {
* let current = await bchjs.Price.rates();
* console.log(current);
* } catch(err) {
* console.err(err)
* console.error(err)
* }
*})()
*
@@ -111,7 +111,7 @@ class Price {
try {
const response = await this.axios.get(
`${this.restURL}price/rates`,
_this.axiosOptions
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
@@ -127,8 +127,9 @@ class Price {
* @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.
* This endpoint gets the USD price of XEC from the Coinex API. The price
* denominated in BCHA comes from bch-api, so it has a better chance of
* working in Tor.
*
* @apiExample Example usage:
*(async () => {
@@ -136,17 +137,55 @@ class Price {
* let current = await bchjs.Price.getBchaUsd();
* console.log(current);
* } catch(err) {
* console.err(err)
* console.error(err)
* }
*})()
*
* // 18.81
* // 212.34
*/
async getBchaUsd () {
try {
const response = await this.axios.get(
`${this.restURL}price/bchausd`,
_this.axiosOptions
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
const bchaPrice = response.data.usd * 1000000
// Convert XEC denomination to BCHA denomination
return bchaPrice
} catch (err) {
if (err.response && err.response.data) throw err.response.data
else throw err
}
}
/**
* @api price.getXecUsd() getXecUsd()
* @apiName Price getXecUsd()
* @apiGroup Price
* @apiDescription Return current price of XEC in USD.
* This endpoint gets the USD price of XEC 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.getXecUsd();
* console.log(current);
* } catch(err) {
* console.error(err)
* }
*})()
*
* // 0.00021234
*/
async getXecUsd () {
try {
const response = await this.axios.get(
`${this.restURL}price/bchausd`,
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
@@ -171,7 +210,7 @@ class Price {
* let current = await bchjs.Price.getBchUsd();
* console.log(current);
* } catch(err) {
* console.err(err)
* console.error(err)
* }
*})()
*
@@ -181,7 +220,7 @@ class Price {
try {
const response = await this.axios.get(
`${this.restURL}price/bchusd`,
_this.axiosOptions
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
+28 -6
View File
@@ -259,6 +259,10 @@ class RawTransactions {
async getRawTransaction (txid, verbose = false, usrObj = null) {
try {
if (typeof txid === 'string') {
// console.log(
// 'getRawTransaction() this.axiosOptions: ',
// this.axiosOptions
// )
const response = await axios.get(
`${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=${verbose}`,
this.axiosOptions
@@ -284,8 +288,13 @@ class RawTransactions {
throw new Error('Input must be a string or array of strings.')
} catch (error) {
if (error.error) throw new Error(error.error)
else if (error.response && error.response.data) throw error.response.data
else throw error
// This case handles rate limit errors.
if (error.response && error.response.data && error.response.data.error) {
throw new Error(error.response.data.error)
} else if (error.response && error.response.data) {
throw error.response.data
} else throw error
}
}
@@ -310,6 +319,9 @@ class RawTransactions {
const inputTxid = vin.txid
const inputVout = vin.vout
// TODO: Coinbase TXs have no input transaction. Figure out how to
// handle this corner case.
// Get the TX details for the input, in order to retrieve the address of
// the sender.
const txDetailsParent = await this.getRawTransaction(inputTxid, true)
@@ -330,8 +342,13 @@ class RawTransactions {
return retArray
} catch (error) {
if (error.error) throw new Error(error.error)
else if (error.response && error.response.data) throw error.response.data
else throw error
// This case handles rate limit errors.
if (error.response && error.response.data && error.response.data.error) {
throw new Error(error.response.data.error)
} else if (error.response && error.response.data) {
throw error.response.data
} else throw error
}
}
@@ -386,8 +403,13 @@ class RawTransactions {
return txDetails
} catch (error) {
if (error.error) throw new Error(error.error)
else if (error.response && error.response.data) throw error.response.data
else throw error
// This case handles rate limit errors.
if (error.response && error.response.data && error.response.data.error) {
throw new Error(error.response.data.error)
} else if (error.response && error.response.data) {
throw error.response.data
} else throw error
}
}
+6 -6
View File
@@ -17,7 +17,7 @@ const Address = require('./address')
// const BigNumber = require('bignumber.js')
const slpMdm = require('slp-mdm')
let _this
// let _this
// const addy = new Address()
let addy
const TransactionBuilder = require('../transaction-builder')
@@ -31,7 +31,7 @@ class Nft1 {
// Instantiate the transaction builder.
TransactionBuilder.setAddress(addy)
_this = this
// _this = this
}
/**
@@ -432,7 +432,7 @@ class Nft1 {
* @apiExample Example usage:
*
* const groupId = '68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a'
* const children = await bchjs.SLP.Nft1.listNFTGroupChildren(groupId)
* const children = await bchjs.SLP.NFT1.listNFTGroupChildren(groupId)
*
* children = {
* "nftChildren": [
@@ -446,7 +446,7 @@ class Nft1 {
if (typeof groupId === 'string') {
const response = await axios.get(
`${this.restURL}slp/nftChildren/${groupId}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
}
@@ -471,7 +471,7 @@ class Nft1 {
* @apiExample Example usage:
*
* const tokenId = '45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9'
* const group = await bchjs.SLP.Nft1.parentNFTGroup(tokenId)
* const group = await bchjs.SLP.NFT1.parentNFTGroup(tokenId)
*
* group = {
* "nftGroup": {
@@ -498,7 +498,7 @@ class Nft1 {
if (typeof tokenId === 'string') {
const response = await axios.get(
`${this.restURL}slp/nftGroup/${tokenId}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
}
+18 -12
View File
@@ -125,13 +125,13 @@ class TokenType1 {
// console.log('baseChange: ', baseChange)
// Check for potential burns
const outputQty = new BigNumber(baseChange).plus(
new BigNumber(baseQty)
)
const outputQty = new BigNumber(baseChange).plus(new BigNumber(baseQty))
const inputQty = new BigNumber(totalTokens)
const tokenOutputDelta = outputQty.minus(inputQty).toString() !== '0'
if (tokenOutputDelta) {
throw new Error('Token transaction inputs do not match outputs, cannot send transaction')
throw new Error(
'Token transaction inputs do not match outputs, cannot send transaction'
)
}
// Generate the OP_RETURN as a Buffer.
@@ -152,7 +152,9 @@ class TokenType1 {
const tokenSingleOutputError =
noChangeOutputQty.minus(noChangeInputQty).toString() !== '0'
if (tokenSingleOutputError) {
throw new Error('Token transaction inputs do not match outputs, cannot send transaction')
throw new Error(
'Token transaction inputs do not match outputs, cannot send transaction'
)
}
// Generate the OP_RETURN as a Buffer.
@@ -285,9 +287,15 @@ class TokenType1 {
try {
// TODO: Add input validation.
let baseQty = new BigNumber(configObj.initialQty).times(
10 ** configObj.decimals
)
let baseQty
if (configObj.decimals !== 0) {
baseQty = new BigNumber(configObj.initialQty).times(
10 ** configObj.decimals
)
} else {
baseQty = new BigNumber(configObj.initialQty)
}
baseQty = baseQty.absoluteValue()
baseQty = Math.floor(baseQty)
baseQty = baseQty.toString()
@@ -378,9 +386,7 @@ class TokenType1 {
// Throw an error if the minting baton could not be found.
if (!mintBatonUtxo) {
throw new Error(
'Minting baton could not be found in tokenUtxos array.'
)
throw new Error('Minting baton could not be found in tokenUtxos array.')
}
const tokenId = mintBatonUtxo.tokenId
@@ -454,7 +460,7 @@ class TokenType1 {
const result = await _this.axios.post(
`${this.restURL}slp/generatesendopreturn`,
data,
_this.axiosOptions
this.axiosOptions
)
const slpSendObj = result.data
+38 -19
View File
@@ -217,14 +217,14 @@ class Utils {
try {
let response
if (method === 'get') {
response = await _this.axios.get(path, _this.axiosOptions)
response = await _this.axios.get(path, this.axiosOptions)
} else {
response = await _this.axios.post(
path,
{
tokenIds: id
},
_this.axiosOptions
this.axiosOptions
)
}
return response.data
@@ -315,7 +315,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 _this.axios.get(path, this.axiosOptions)
return response.data
// Array of addresses.
@@ -328,7 +328,7 @@ class Utils {
{
addresses: address
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -380,7 +380,7 @@ class Utils {
try {
const path = `${this.restURL}slp/balancesForToken/${tokenId}`
const response = await _this.axios.get(path, _this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
if (error.response && error.response.data) throw error.response.data
@@ -450,13 +450,14 @@ class Utils {
else txids = txid
try {
// console.log('validateTxid() this.axiosOptions: ', this.axiosOptions)
const response = await _this.axios.post(
path,
{
txids: txids,
usrObj // pass user data when making an internal call.
},
_this.axiosOptions
this.axiosOptions
)
// console.log(
// `validateTxid response.data: ${JSON.stringify(response.data, null, 2)}`
@@ -520,7 +521,8 @@ class Utils {
const path = `${this.restURL}slp/validateTxid2/${txid}`
const response = await _this.axios.get(path, _this.axiosOptions)
// console.log('validateTxid2() this.axiosOptions: ', this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
if (error.response && error.response.data) throw error.response.data
@@ -589,7 +591,7 @@ class Utils {
// 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)
const response = await _this.axios.get(path, this.axiosOptions)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
this.whitelist = response.data
@@ -666,13 +668,14 @@ class Utils {
else txids = txid
try {
// console.log('validateTxid3() this.axiosOptions: ', this.axiosOptions)
const response = await _this.axios.post(
path,
{
txids: txids,
usrObj // pass user data when making an internal call.
},
_this.axiosOptions
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
@@ -680,6 +683,14 @@ class Utils {
return validatedTxids
} catch (error) {
// console.log('validateTxid3 error: ', error)
// This case handles rate limit errors.
if (error.response && error.response.data && error.response.data.error) {
throw new Error(error.response.data.error)
}
// Not sure if this can be safely deprecated?
if (error.response && error.response.data) throw error.response.data
throw error
}
@@ -724,7 +735,7 @@ class Utils {
try {
const path = `${this.restURL}slp/tokenStats/${tokenId}`
const response = await _this.axios.get(path, _this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
@@ -795,7 +806,7 @@ class Utils {
try {
const path = `${this.restURL}slp/transactions/${tokenId}/${address}`
const response = await _this.axios.get(path, _this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
@@ -835,7 +846,7 @@ class Utils {
try {
const path = `${this.restURL}slp/burnTotal/${transactionId}`
const response = await _this.axios.get(path, _this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
@@ -879,7 +890,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 _this.axios.get(path, this.axiosOptions)
return response.data
} catch (error) {
if (error.response && error.response.data) throw error.response.data
@@ -910,7 +921,7 @@ class Utils {
* const txid =
* "266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1"
*
* const data = await slp.Utils.decodeOpReturn2(txid)
* const data = await bchjs.SLP.Utils.decodeOpReturn(txid)
*
* console.log(`Decoded OP_RETURN data: ${JSON.stringify(data,null,2)}`)
* } catch (error) {
@@ -959,14 +970,15 @@ class Utils {
// CT: 2/24/21 Deprected GET in favor of POST, to pass IP address.
// Retrieve the transaction object from the full node.
const path = `${this.restURL}rawtransactions/getRawTransaction`
const response = await _this.axios.post(
// console.log('decodeOpReturn() this.axiosOptions: ', this.axiosOptions)
const response = await this.axios.post(
path,
{
verbose: true,
txids: [txid],
usrObj // pass user data when making an internal call.
},
_this.axiosOptions
this.axiosOptions
)
const txDetails = response.data[0]
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
@@ -1639,6 +1651,11 @@ class Utils {
// could not be validated.
return isValid
} catch (error) {
// This case handles rate limit errors.
if (error.response && error.response.data && error.response.data.error) {
throw new Error(error.response.data.error)
}
// console.log('Error in waterfallValidateTxid()')
if (error.response && error.response.data) throw error.response.data
throw error
@@ -1836,11 +1853,13 @@ class Utils {
utxos: utxos,
usrObj
},
_this.axiosOptions
this.axiosOptions
)
return response.data
} catch (error) {
console.log('Error in hydrateUtxos(): ', error)
if (error.response && error.response.data) {
throw new Error(JSON.stringify(error.response.data, null, 2))
}
@@ -1874,7 +1893,7 @@ class Utils {
{
utxos: utxos
},
_this.axiosOptions
this.axiosOptions
)
return response.data
@@ -1914,7 +1933,7 @@ class Utils {
const path = `${this.restURL}slp/status`
try {
const response = await _this.axios.get(path, _this.axiosOptions)
const response = await _this.axios.get(path, this.axiosOptions)
// console.log(
// `getStatus response.data: ${JSON.stringify(response.data, null, 2)}`
// )
+389 -10
View File
@@ -2,14 +2,18 @@
High-level functions for working with Transactions
*/
const BigNumber = require('bignumber.js')
const RawTransaction = require('./raw-transactions')
const SlpUtils = require('./slp/utils')
const Blockchain = require('./blockchain')
class Transaction {
constructor (config) {
// Encapsulate dependencies
this.slpUtils = new SlpUtils(config)
this.rawTransaction = new RawTransaction(config)
this.blockchain = new Blockchain(config)
}
/**
@@ -34,6 +38,10 @@ class Transaction {
* }
* })()
*/
// CT 10/31/21: TODO: this function should be refactored to use get2(), but
// add waterfall validation of the TX and its inputs.
async get (txid) {
try {
if (typeof txid !== 'string') {
@@ -75,9 +83,18 @@ class Transaction {
// Add the token quantity to each output.
for (let i = 0; i < outTokenData.amounts.length; i++) {
const rawQty = outTokenData.amounts[i]
const realQty = Number(rawQty) / Math.pow(10, txDetails.tokenDecimals)
// const realQty = Number(rawQty) / Math.pow(10, txDetails.tokenDecimals)
txDetails.vout[i + 1].tokenQty = realQty
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(rawQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
txDetails.vout[i + 1].tokenQtyStr = realQty
txDetails.vout[i + 1].tokenQty = parseFloat(realQty)
}
// Add tokenQty = null to any outputs that don't have a value.
@@ -92,6 +109,7 @@ class Transaction {
// Loop through each input and retrieve the token data.
for (let i = 0; i < txDetails.vin.length; i++) {
const thisVin = txDetails.vin[i]
// console.log(`thisVin: ${JSON.stringify(thisVin, null, 2)}`)
try {
// If decodeOpReturn() throws an error, then this input is not
@@ -101,18 +119,66 @@ class Transaction {
// `vin[${i}] tokenData: ${JSON.stringify(inTokenData, null, 2)}`
// )
// Get the appropriate vout token amount. This may throw an error,
// which means this Vin is not actually a token UTXO, it was just
// associated with a previous token TX.
const tokenQty = inTokenData.amounts[thisVin.vout - 1]
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
let tokenQty = 0
// Validate the input. Mark qty as null if not valid.
const vinIsValid = await this.slpUtils.waterfallValidateTxid(
thisVin.txid
)
if (!vinIsValid) {
// If the input is not a valid, then set qty as null.
tokenQty = null
} else if (inTokenData.txType === 'SEND') {
// Get the appropriate vout token amount. This may throw an error,
// which means this Vin is not actually a token UTXO, it was just
// associated with a previous token TX.
tokenQty = inTokenData.amounts[thisVin.vout - 1]
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
//
} else if (inTokenData.txType === 'GENESIS') {
// Only vout[1] of a Genesis transaction represents the tokens.
// Any other outputs in that transaction are normal BCH UTXOs.
if (thisVin.vout === 1) {
tokenQty = inTokenData.qty
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
}
} else if (inTokenData.txType === 'MINT') {
// vout=1 (second output) recieves the newly minted tokens.
if (thisVin.vout === 1) {
tokenQty = inTokenData.qty
} else {
tokenQty = null
}
//
} else {
console.log(
'Unexpected code path in Transaction.get(). What is the txType?'
)
console.log(inTokenData)
throw new Error('Unexpected code path')
}
if (tokenQty) {
const realQty =
Number(tokenQty) / Math.pow(10, txDetails.tokenDecimals)
// const realQty =
// Number(tokenQty) / Math.pow(10, txDetails.tokenDecimals)
thisVin.tokenQty = realQty
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(tokenQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
thisVin.tokenQtyStr = realQty
thisVin.tokenQty = parseFloat(realQty)
// txDetails.vin[i].tokenQty = tokenQty
// Add token ID to input
thisVin.tokenId = inTokenData.tokenId
} else {
thisVin.tokenQty = null
}
@@ -128,9 +194,17 @@ class Transaction {
// Finally, validate the SLP TX.
// this.slpUtils.waterfallValidateTxid(txid, usrObj)
txDetails.isValidSLPTx = await this.slpUtils.waterfallValidateTxid(txid)
// TODO: Convert the block hash to a block height. Add block height
// value to the transaction.
} catch (err) {
// console.log('Error: ', err)
// This case handles rate limit errors.
if (err.response && err.response.data && err.response.data.error) {
throw new Error(err.response.data.error)
}
// If decoding the op_return fails, then it's not an SLP transaction,
// and the non-hyrated TX details can be returned.
return txDetails
@@ -140,10 +214,315 @@ class Transaction {
} catch (err) {
// console.error('Error in transactions.js/get(): ', err)
// This case handles rate limit errors.
if (err.response && err.response.data && err.response.data.error) {
throw new Error(err.response.data.error)
}
if (err.error) throw new Error(err.error)
throw err
}
}
/**
* @api Transaction.get3() get3()
* @apiName get3
* @apiGroup Transaction
* @apiDescription
* Returns an object of transaction data, including addresses for input UTXOs.
* If it is a SLP token transaction, the token information for inputs and
* outputs will also be included.
*
* This is an API heavy call. This function will only work with a single txid.
* It does not yet support an array of TXIDs.
*
* This is the same as get(), except it omits DAG validation of the TXID.
*
* @apiExample Example usage:
* (async () => {
* try {
* let txData = await bchjs.Transaction.get2("0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098");
* console.log(txData);
* } catch(error) {
* console.error(error)
* }
* })()
*/
async get3 (txid) {
try {
if (typeof txid !== 'string') {
throw new Error(
'Input to Transaction.get() must be a string containing a TXID.'
)
}
// Get TX data
const txDetails = await this.rawTransaction.getTxData(txid)
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
// Get the block height the transaction was mined in.
const blockHeader = await this.blockchain.getBlockHeader(
txDetails.blockhash
)
txDetails.blockheight = blockHeader.height
// console.log(`blockHeader: ${JSON.stringify(blockHeader, null, 2)}`)
// Set default as not an SLP tx
txDetails.isSlpTx = false
// Get Token Data
const txTokenData = await this.getTokenInfo(txid)
// console.log(`txTokenData: ${JSON.stringify(txTokenData, null, 2)}`)
// If not a token, return the tx data. Processing is complete.
if (!txTokenData) return txDetails
// Mark TX as an SLP tx. This does not mean it's valid, it just means
// the OP_RETURN passes a basic check.
txDetails.isSlpTx = true
// Get Genesis data
const genesisData = await this.getTokenInfo(txTokenData.tokenId)
// console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`)
// Add token information to the tx details object.
txDetails.tokenTxType = txTokenData.txType
txDetails.tokenId = txTokenData.tokenId
txDetails.tokenTicker = genesisData.ticker
txDetails.tokenName = genesisData.name
txDetails.tokenDecimals = genesisData.decimals
txDetails.tokenUri = genesisData.documentUri
txDetails.tokenDocHash = genesisData.documentHash
// console.log(`txDetails before processing input and outputs: ${JSON.stringify(txDetails, null, 2)}`)
// Process TX Outputs
// Add the token quantity to each output.
// 'i' starts at 1, because vout[0] is the OP_RETURN
for (let i = 0; i < txDetails.vout.length; i++) {
const thisVout = txDetails.vout[i]
if (txTokenData.txType === 'SEND') {
// console.log(
// `output txTokenData: ${JSON.stringify(txTokenData, null, 2)}`
// )
// First output is OP_RETURN, so tokenQty is null.
if (i === 0) {
thisVout.tokenQty = null
thisVout.tokenQtyStr = null
continue
}
// Non SLP outputs.
if (i > txTokenData.amounts.length) {
thisVout.tokenQty = null
thisVout.tokenQtyStr = null
continue
}
const rawQty = txTokenData.amounts[i - 1]
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(rawQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
txDetails.vout[i].tokenQtyStr = realQty
txDetails.vout[i].tokenQty = parseFloat(realQty)
// console.log(
// `thisVout ${i}: ${JSON.stringify(txDetails.vout[i], null, 2)}`
// )
} else if (
txTokenData.txType === 'GENESIS' ||
txTokenData.txType === 'MINT'
) {
// console.log(
// `output txTokenData: ${JSON.stringify(txTokenData, null, 2)}`
// )
let tokenQty = 0 // Default value
// Only vout[1] of a Genesis or Mint transaction represents the tokens.
// Any other outputs in that transaction are normal BCH UTXOs.
if (i === 1) {
tokenQty = txTokenData.qty
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(tokenQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
thisVout.tokenQtyStr = realQty
thisVout.tokenQty = parseFloat(realQty)
// console.log(`thisVout[${i}]: ${JSON.stringify(thisVout, null, 2)}`)
} else if (i === txTokenData.mintBatonVout) {
// Optional Mint baton
thisVout.tokenQtyStr = '0'
thisVout.tokenQty = 0
thisVout.isMintBaton = true
} else {
thisVout.tokenQtyStr = '0'
thisVout.tokenQty = 0
}
} else {
throw new Error('Unknown SLP TX type for TX')
}
}
// Process TX inputs
for (let i = 0; i < txDetails.vin.length; i++) {
const thisVin = txDetails.vin[i]
// console.log(`thisVin[${i}]: ${JSON.stringify(thisVin, null, 2)}`)
const vinTokenData = await this.getTokenInfo(thisVin.txid)
// console.log(
// `vinTokenData ${i}: ${JSON.stringify(vinTokenData, null, 2)}`
// )
// Corner case: Ensure the token ID is the same.
const vinTokenIdIsTheSame = vinTokenData.tokenId === txDetails.tokenId
// If the input is not a token input, or if the tokenID is not the same,
// then mark the token output as null.
if (!vinTokenData || !vinTokenIdIsTheSame) {
thisVin.tokenQty = 0
thisVin.tokenQtyStr = '0'
thisVin.tokenId = null
continue
}
if (vinTokenData.txType === 'SEND') {
// console.log(
// `SEND vinTokenData ${i}: ${JSON.stringify(vinTokenData, null, 2)}`
// )
const tokenQty = vinTokenData.amounts[thisVin.vout - 1]
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(tokenQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
thisVin.tokenQtyStr = realQty
thisVin.tokenQty = parseFloat(realQty)
thisVin.tokenId = vinTokenData.tokenId
} else if (vinTokenData.txType === 'MINT') {
// console.log(
// `MINT vinTokenData ${i}: ${JSON.stringify(vinTokenData, null, 2)}`
// )
let tokenQty = 0 // Default value
// Only vout[1] of a Genesis transaction represents the tokens.
// Any other outputs in that transaction are normal BCH UTXOs.
if (thisVin.vout === 1) {
tokenQty = vinTokenData.qty
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(tokenQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
thisVin.tokenQtyStr = realQty
thisVin.tokenQty = parseFloat(realQty)
thisVin.tokenId = vinTokenData.tokenId
} else if (thisVin.vout === vinTokenData.mintBatonVout) {
// Optional Mint baton
thisVin.tokenQtyStr = '0'
thisVin.tokenQty = 0
thisVin.tokenId = vinTokenData.tokenId
thisVin.isMintBaton = true
} else {
thisVin.tokenQtyStr = '0'
thisVin.tokenQty = 0
thisVin.tokenId = null
}
} else if (vinTokenData.txType === 'GENESIS') {
// console.log(
// `GENESIS vinTokenData ${i}: ${JSON.stringify(
// vinTokenData,
// null,
// 2
// )}`
// )
let tokenQty = 0 // Default value
// Only vout[1] of a Genesis transaction represents the tokens.
// Any other outputs in that transaction are normal BCH UTXOs.
if (thisVin.vout === 1) {
tokenQty = vinTokenData.qty
// console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
// Calculate the real quantity using a BigNumber, then convert it to a
// floating point number.
let realQty = new BigNumber(tokenQty).dividedBy(
10 ** parseInt(txDetails.tokenDecimals)
)
realQty = realQty.toString()
// realQty = parseFloat(realQty)
thisVin.tokenQtyStr = realQty
thisVin.tokenQty = parseFloat(realQty)
thisVin.tokenId = vinTokenData.tokenId
} else if (thisVin.vout === vinTokenData.mintBatonVout) {
// Optional Mint baton
thisVin.tokenQtyStr = '0'
thisVin.tokenQty = 0
thisVin.tokenId = vinTokenData.tokenId
thisVin.isMintBaton = true
} else {
thisVin.tokenQtyStr = '0'
thisVin.tokenQty = 0
thisVin.tokenId = null
}
} else {
console.log(
`Unknown vinTokenData: ${JSON.stringify(vinTokenData, null, 2)}`
)
throw new Error('Unknown token type in input')
}
}
return txDetails
} catch (err) {
console.error('Error in get3()')
// This case handles rate limit errors.
if (err.response && err.response.data && err.response.data.error) {
throw new Error(err.response.data.error)
}
if (err.error) throw new Error(err.error)
throw err
}
}
// A wrapper for decodeOpReturn(). Returns false if txid is not an SLP tx.
// Returns the token data if the txid is an SLP tx.
async getTokenInfo (txid) {
try {
const tokenData = await this.slpUtils.decodeOpReturn(txid)
return tokenData
} catch (err) {
return false
}
}
}
module.exports = Transaction
+3 -3
View File
@@ -1,6 +1,6 @@
const axios = require('axios')
let _this
// let _this
class Util {
constructor (config) {
@@ -24,7 +24,7 @@ class Util {
}
}
_this = this
// _this = this
}
/**
@@ -225,7 +225,7 @@ class Util {
if (typeof address === 'string') {
const response = await axios.get(
`${this.restURL}util/validateAddress/${address}`,
_this.axiosOptions
this.axiosOptions
)
return response.data
+1 -1
View File
@@ -22,7 +22,7 @@ util.inspect.defaultOptions = {
describe('#blockchain', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#getBestBlockHash', () => {
@@ -20,7 +20,7 @@ util.inspect.defaultOptions = {
describe('#rawtransaction', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
/*
+1 -1
View File
@@ -25,7 +25,7 @@ describe('#SLP', () => {
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)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
bchjs = new BCHJS({ restURL: process.env.RESTURL })
})
@@ -11,7 +11,7 @@ describe('#UTXO', () => {
beforeEach(async () => {
// sandbox = sinon.createSandbox()
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#get', () => {
@@ -5,7 +5,7 @@
const chai = require('chai')
const assert = chai.assert
const BCHJS = require('../../src/bch-js')
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS()
// Inspect utility used for debugging.
@@ -18,7 +18,7 @@ util.inspect.defaultOptions = {
describe('#util', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#validateAddress', () => {
@@ -81,7 +81,8 @@ describe('#util', () => {
it('should throw error on array size rate limit', async () => {
try {
const dataMock = 'bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z'
const dataMock =
'bitcoincash:qp4k8fjtgunhdr7yq30ha4peuwupzan2vcnwrmpy0z'
const data = []
for (let i = 0; i < 25; i++) data.push(dataMock)
@@ -29,7 +29,7 @@ util.inspect.defaultOptions = {
describe('#blockchain', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#getBestBlockHash', () => {
+1 -1
View File
@@ -14,7 +14,7 @@ const bchjs = new BCHJS({ restURL: RESTURL, apiToken: process.env.BCHJSTOKEN })
describe('#control', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#getNetworkInfo', () => {
+1 -1
View File
@@ -16,7 +16,7 @@ describe('#ElectrumX', () => {
beforeEach(async () => {
sandbox = sinon.createSandbox()
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
afterEach(() => sandbox.restore())
-149
View File
@@ -1,149 +0,0 @@
// const chai = require('chai')
// const assert = chai.assert
const sinon = require('sinon')
// const BCHJS = require('../../../../src/bch-js')
// const bchjs = new BCHJS({ ninsightURL: 'https://trest.bitcoin.com/v2' })
describe('#Ninsight', () => {
let sandbox
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
sandbox = sinon.createSandbox()
})
afterEach(() => sandbox.restore())
// describe('#utxo', () => {
// it('should GET utxos for a single address', async () => {
// const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
//
// 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 = [
// 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
// 'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
// ]
//
// 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')
//
// // assert.hasAnyKeys(result[0][0], [
// // "txid",
// // "vout",
// // "value",
// // "height",
// // "confirmations"
// // ])
// })
// })
//
// describe('#transactions', () => {
// it('should POST transactions history for a single address', async () => {
// const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
//
// 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 = [
// 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
// 'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
// ]
//
// 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 =
// '76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
//
// 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], 'valueOut')
// assert.property(result[0], 'size')
// })
// it('should POST transactions details for an array of addresses', async () => {
// const txid = [
// 'f191d1062789d7071da6f2168ba306869a829294f6b1c09d03492db4ca3a8e77',
// '76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
// ]
//
// 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')
// })
// })
})
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
@@ -27,7 +27,7 @@ util.inspect.defaultOptions = {
describe('#rawtransaction', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#decodeRawTransaction', () => {
+1 -1
View File
@@ -25,7 +25,7 @@ util.inspect.defaultOptions = {
describe('#SLP', () => {
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)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#util', () => {
+1 -1
View File
@@ -25,7 +25,7 @@ util.inspect.defaultOptions = {
describe('#util', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#validateAddress', () => {
+1 -1
View File
@@ -9,7 +9,7 @@ const bchjs = new BCHJS()
describe('#control', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#getNetworkInfo', () => {
+1 -1
View File
@@ -11,7 +11,7 @@ describe('#ElectrumX', () => {
beforeEach(async () => {
sandbox = sinon.createSandbox()
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
afterEach(() => sandbox.restore())
+1 -1
View File
@@ -5,7 +5,7 @@ const bchjs = new BCHJS()
describe('#Encryption', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#getPubKey', () => {
-138
View File
@@ -1,138 +0,0 @@
const chai = require('chai')
const assert = chai.assert
const sinon = require('sinon')
const BCHJS = require('../../src/bch-js')
const bchjs = new BCHJS({ ninsightURL: 'https://rest.bitcoin.com/v2' })
describe('#Ninsight', () => {
let sandbox
beforeEach(async () => {
sandbox = sinon.createSandbox()
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
})
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], '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')
})
})
})
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
+1 -1
View File
@@ -4,7 +4,7 @@ const bchjs = new BCHJS()
describe('#price', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#current', () => {
+2 -3
View File
@@ -19,7 +19,7 @@ util.inspect.defaultOptions = {
describe('#rawtransaction', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
describe('#decodeRawTransaction', () => {
@@ -191,8 +191,7 @@ describe('#rawtransaction', () => {
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')
assert.include(err.message, 'Array too large')
}
})
})
@@ -56,5 +56,26 @@ describe('#Transaction', () => {
assert.property(result, 'isValidSLPTx')
assert.equal(result.isValidSLPTx, true)
})
// it('should get problematic transaction', async () => {
// const txid = 'a55515de32577e296c512840bcaabed5823bb773fb4f8fd8e5197cc96cbc54d1'
//
// const result = await bchjs.Transaction.get(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// })
// TX a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe has
// an input TXID (bd84bc1dd5ecd976165892306992401272f6bedeb37d7b2cdbf74fc4a55967a6)
// that is also a valid SLP tx, but is unrelated. Both TXs pass DAG validation,
// but for separate tokens.
it('should get problematic transaction', async () => {
const txid = 'a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe'
const result = await bchjs.Transaction.get(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// The token ID should equal the txid for this Vin.
assert.equal(result.vin[2].txid, result.vin[2].tokenId)
})
})
})
+612 -1
View File
@@ -175,10 +175,621 @@ const mockOpReturnData03 = {
amounts: ['1000000000', '99883400000000']
}
const genesisTestInputTx = {
txid: '874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e',
hash: '874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e',
version: 1,
size: 480,
locktime: 543408,
vin: [
{
txid: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
vout: 1,
scriptSig: {
asm:
'30440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f55[ALL|FORKID] 028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11',
hex:
'4730440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f554121028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11'
},
sequence: 4294967294,
address: 'bitcoincash:qp2jesd06k8ycj4wvkpl9lcwaemtr04f5yphjsa07v',
value: 0.00000546
},
{
txid: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
vout: 3,
scriptSig: {
asm:
'3045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519[ALL|FORKID] 02cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bc',
hex:
'483045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519412102cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bc'
},
sequence: 4294967294,
address: 'bitcoincash:qppj3euc36x5u6twr5cxrrea2rca53vsfu3dxwr86j',
value: 0.00172192
}
],
vout: [
{
value: 0,
n: 0,
scriptPubKey: {
asm:
'OP_RETURN 5262419 1 1145980243 323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35 00000000004c4b40 00000000004c4b40',
hex:
'6a04534c500001010453454e4420323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d350800000000004c4b400800000000004c4b40',
type: 'nulldata'
}
},
{
value: 0.00000546,
n: 1,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 0a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e0 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a9140a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e088ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qq98fnuup7eldhtzc067ang76mss29pguqh7qv9eac']
}
},
{
value: 0.00000546,
n: 2,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 d4548261e1be0de7e50b7511597799ec4af2b173 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914d4548261e1be0de7e50b7511597799ec4af2b17388ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qr29fqnpuxlqmel9pd63zkthn8ky4u43wv0v7pg5mn']
}
},
{
value: 0.00171165,
n: 3,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 d4548261e1be0de7e50b7511597799ec4af2b173 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914d4548261e1be0de7e50b7511597799ec4af2b17388ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qr29fqnpuxlqmel9pd63zkthn8ky4u43wv0v7pg5mn']
}
}
],
hex:
'0100000002359dab0d9c8ddc788b14c0b51493d195c9fbd9f2203d091663350bae351e3a32010000006a4730440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f554121028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11feffffff359dab0d9c8ddc788b14c0b51493d195c9fbd9f2203d091663350bae351e3a32030000006b483045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519412102cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bcfeffffff040000000000000000406a04534c500001010453454e4420323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d350800000000004c4b400800000000004c4b4022020000000000001976a9140a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e088ac22020000000000001976a914d4548261e1be0de7e50b7511597799ec4af2b17388ac9d9c0200000000001976a914d4548261e1be0de7e50b7511597799ec4af2b17388acb04a0800',
blockhash: '000000000000000000292a9c6150fce48e2edd8df346948494fe6249e6e7f63b',
confirmations: 163095,
time: 1534271330,
blocktime: 1534271330
}
const mintTestInputTx = {
txid: '4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa',
hash: '4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa',
version: 1,
size: 585,
locktime: 543613,
vin: [
{
txid: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
vout: 1,
scriptSig: {
asm:
'3045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2[ALL|FORKID] 02056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74',
hex:
'483045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2412102056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74'
},
sequence: 4294967294,
address: 'bitcoincash:qpaf9wltgmpjlg2vxwwu7zdw5y4z7m277ckxn8cufl',
value: 0.00000546,
tokenQtyStr: '43545.34534',
tokenQty: 43545.34534
},
{
txid: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
vout: 1,
scriptSig: {
asm:
'3045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a[ALL|FORKID] 024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2',
hex:
'483045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a4121024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2'
},
sequence: 4294967294,
address: 'bitcoincash:qqf89zzwd0fqc3npkks997r5l7dpfjf9kgx2rqu500',
value: 0.00000546,
tokenQtyStr: '2.34123',
tokenQty: 2.34123
},
{
txid: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
vout: 3,
scriptSig: {
asm:
'3044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae[ALL|FORKID] 02eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56',
hex:
'473044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae412102eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56'
},
sequence: 4294967294,
address: 'bitcoincash:qqt30r33k0jx3sxe34tmupaujpaljnglmvqgrrfp2x',
value: 0.00054848,
tokenQtyStr: '2.34123',
tokenQty: 2.34123
}
],
vout: [
{
value: 0,
n: 0,
scriptPubKey: {
asm:
'OP_RETURN 5262419 1 1145980243 938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8 0000000103907f11',
hex:
'6a04534c500001010453454e4420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8080000000103907f11',
type: 'nulldata'
},
tokenQty: null
},
{
value: 0.00000546,
n: 1,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 059775ff94f65c04e8a6847e74eb9809d8cd779b OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914059775ff94f65c04e8a6847e74eb9809d8cd779b88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qqzewa0ljnm9cp8g56z8ua8tnqya3nthnvhv5hpu8y']
},
tokenQtyStr: '43547.68657',
tokenQty: 43547.68657
},
{
value: 0.00054808,
n: 2,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 0e330dc9009e1e07831f5a22d4ade8977ab674c8 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a9140e330dc9009e1e07831f5a22d4ade8977ab674c888ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qq8rxrwfqz0pupurradz949dazth4dn5eqs3mhrucv']
},
tokenQty: null
}
],
hex:
'0100000003f8cda53b43b0ea49991a9bc6c74eb901d2a8b964bc7b8987d76789618ec18c93010000006b483045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2412102056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74feffffff34dbf62a45295ae11c2a45f44368218ec64498ac3f7e1434c1993515f53c9dee010000006b483045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a4121024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2feffffff34dbf62a45295ae11c2a45f44368218ec64498ac3f7e1434c1993515f53c9dee030000006a473044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae412102eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56feffffff030000000000000000376a04534c500001010453454e4420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8080000000103907f1122020000000000001976a914059775ff94f65c04e8a6847e74eb9809d8cd779b88ac18d60000000000001976a9140e330dc9009e1e07831f5a22d4ade8977ab674c888ac7d4b0800',
blockhash: '00000000000000000140f0d813052da59c811a936494a8d8b2d60b215d19e3dc',
confirmations: 167007,
time: 1534391953,
blocktime: 1534391953,
isValidSLPTx: true,
tokenTxType: 'SEND',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
tokenTicker: 'Bubb2',
tokenName: 'the new bubbles!',
tokenDecimals: 5,
tokenUri: '',
tokenDocHash: ''
}
const genesisTestOpReturnData01 = {
tokenType: 1,
txType: 'SEND',
tokenId: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
amounts: ['5000000', '5000000']
}
const genesisTestOpReturnData02 = {
tokenType: 1,
txType: 'GENESIS',
ticker: '',
name: '',
tokenId: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
documentUri: '',
documentHash: '',
decimals: 0,
mintBatonVout: 2,
qty: '10000000'
}
const mintTestOpReturnData01 = {
tokenType: 1,
txType: 'SEND',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
amounts: ['4354768657']
}
const mintTestOpReturnData02 = {
tokenType: 1,
txType: 'GENESIS',
ticker: 'Bubb2',
name: 'the new bubbles!',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
documentUri: '',
documentHash: '',
decimals: 5,
mintBatonVout: 2,
qty: '4354534534'
}
const mintTestOpReturnData03 = {
tokenType: 1,
txType: 'MINT',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
mintBatonVout: 2,
qty: '234123'
}
const sendTestInputTx01 = {
txid: '6bc111fbf5b118021d68355ca19a0e77fa358dd931f284b2550f79a51ab4792a',
hash: '6bc111fbf5b118021d68355ca19a0e77fa358dd931f284b2550f79a51ab4792a',
version: 1,
size: 627,
locktime: 543956,
vin: [
{
txid: 'b36b0c7485ad569b98cc9b9614dc68a5208495f22ec3b00effcf963b135a5215',
vout: 1,
scriptSig: {
asm:
'3045022100934ca9732bf6c1b146f09e6198142a79a80788b576c6b94e2052df5bcdc86ad902205ef6205192200ea93f6c97f966b838ee785529b694eb61e576e3452470613847[ALL|FORKID] 02b23484341cf36ec00184e045d54e6ffca97da7a8f8a6fd719cead192132306b1',
hex:
'483045022100934ca9732bf6c1b146f09e6198142a79a80788b576c6b94e2052df5bcdc86ad902205ef6205192200ea93f6c97f966b838ee785529b694eb61e576e3452470613847412102b23484341cf36ec00184e045d54e6ffca97da7a8f8a6fd719cead192132306b1'
},
sequence: 4294967294,
address: 'bitcoincash:qqxj7p2jatt8h3tcpadyxw8a2mr7myqk2qm57u4rdf',
value: 0.00000546
},
{
txid: 'b36b0c7485ad569b98cc9b9614dc68a5208495f22ec3b00effcf963b135a5215',
vout: 3,
scriptSig: {
asm:
'3044022004d4a95658ef140561ae3a936fb01511778a5376a499bcd6f47b64074a6ca4430220273a4bf553ca17c7e10f393582f980e17a6a98ada867633faad9dbcc595dfd23[ALL|FORKID] 0324fe3b895cfa09523e8ec529eb15c681e3a20f96df85175c54a952b68ac018df',
hex:
'473044022004d4a95658ef140561ae3a936fb01511778a5376a499bcd6f47b64074a6ca4430220273a4bf553ca17c7e10f393582f980e17a6a98ada867633faad9dbcc595dfd2341210324fe3b895cfa09523e8ec529eb15c681e3a20f96df85175c54a952b68ac018df'
},
sequence: 4294967294,
address: 'bitcoincash:qrcdncgpnv3s8lekcamv4yekp8sghnk37qtsxdyzla',
value: 0.00153976
},
{
txid: '95d460512143b636bbc5780d8b27b04fca3bfd2f22003ab48da594e2bab9cfc1',
vout: 2,
scriptSig: {
asm:
'3044022079f239216f8d806a084221e841227e55d23a1b90aaf5b5ab54d6f865fbeacf8b022053568f10afc00459af083e4c77d0b85229eb8973a1de406aaa699557f05c7fed[ALL|FORKID] 02035f98ff79d6f3a8ec5a2738c103bbb7796e94fcaffdfaae8f5b7a7fae5d93e3',
hex:
'473044022079f239216f8d806a084221e841227e55d23a1b90aaf5b5ab54d6f865fbeacf8b022053568f10afc00459af083e4c77d0b85229eb8973a1de406aaa699557f05c7fed412102035f98ff79d6f3a8ec5a2738c103bbb7796e94fcaffdfaae8f5b7a7fae5d93e3'
},
sequence: 4294967294,
address: 'bitcoincash:qrcukahsm53lsywcdarehh73vqazpdu8zv547nym9g',
value: 0.00000546
}
],
vout: [
{
value: 0,
n: 0,
scriptPubKey: {
asm:
'OP_RETURN 5262419 1 1145980243 550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35 00005af3107a4000 004657febe8d8000',
hex:
'6a04534c500001010453454e4420550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b350800005af3107a400008004657febe8d8000',
type: 'nulldata'
}
},
{
value: 0.00000546,
n: 1,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 268dadd7c7becc11782ad3d956342442d8eae92a OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914268dadd7c7becc11782ad3d956342442d8eae92a88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qqngmtwhc7lvcytc9tfaj435y3pd36hf9gtdq8nsuu']
}
},
{
value: 0.00000546,
n: 2,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 9fb45b370f9ff38a775ee95cabcad7615817924e OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a9149fb45b370f9ff38a775ee95cabcad7615817924e88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qz0mgkehp70l8znhtm54e2726as4s9ujfc9s2szctr']
}
},
{
value: 0.00153347,
n: 3,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 9fb45b370f9ff38a775ee95cabcad7615817924e OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a9149fb45b370f9ff38a775ee95cabcad7615817924e88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qz0mgkehp70l8znhtm54e2726as4s9ujfc9s2szctr']
}
}
],
hex:
'010000000315525a133b96cfff0eb0c32ef2958420a568dc14969bcc989b56ad85740c6bb3010000006b483045022100934ca9732bf6c1b146f09e6198142a79a80788b576c6b94e2052df5bcdc86ad902205ef6205192200ea93f6c97f966b838ee785529b694eb61e576e3452470613847412102b23484341cf36ec00184e045d54e6ffca97da7a8f8a6fd719cead192132306b1feffffff15525a133b96cfff0eb0c32ef2958420a568dc14969bcc989b56ad85740c6bb3030000006a473044022004d4a95658ef140561ae3a936fb01511778a5376a499bcd6f47b64074a6ca4430220273a4bf553ca17c7e10f393582f980e17a6a98ada867633faad9dbcc595dfd2341210324fe3b895cfa09523e8ec529eb15c681e3a20f96df85175c54a952b68ac018dffeffffffc1cfb9bae294a58db43a00222ffd3bca4fb0278b0d78c5bb36b643215160d495020000006a473044022079f239216f8d806a084221e841227e55d23a1b90aaf5b5ab54d6f865fbeacf8b022053568f10afc00459af083e4c77d0b85229eb8973a1de406aaa699557f05c7fed412102035f98ff79d6f3a8ec5a2738c103bbb7796e94fcaffdfaae8f5b7a7fae5d93e3feffffff040000000000000000406a04534c500001010453454e4420550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b350800005af3107a400008004657febe8d800022020000000000001976a914268dadd7c7becc11782ad3d956342442d8eae92a88ac22020000000000001976a9149fb45b370f9ff38a775ee95cabcad7615817924e88ac03570200000000001976a9149fb45b370f9ff38a775ee95cabcad7615817924e88acd44c0800',
blockhash: '000000000000000001882548bbd9a41bc53a039634f2afa4a12d653434347d04',
confirmations: 166670,
time: 1534593905,
blocktime: 1534593905
}
const sendTestOpReturnData01 = {
tokenType: 1,
txType: 'SEND',
tokenId: '550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35',
amounts: ['100000000000000', '19800000000000000']
}
const sendTestOpReturnData02 = {
tokenType: 1,
txType: 'GENESIS',
ticker: 'USDT',
name: 'Tether Ltd. US dollar backed tokens',
tokenId: '550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35',
documentUri:
'https://tether.to/wp-content/uploads/2016/06/TetherWhitePaper.pdf',
documentHash:
'DQ\u001e3\u0006ppM\u0001\u0017pW(;\u0003,wy19\u0016',
decimals: 8,
mintBatonVout: 2,
qty: '10000000000000000'
}
const sendTestOpReturnData03 = {
tokenType: 1,
txType: 'MINT',
tokenId: '550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35',
mintBatonVout: 2,
qty: '10000000000000000'
}
const sendTestOpReturnData04 = {
tokenType: 1,
txType: 'SEND',
tokenId: '550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35',
amounts: ['100000000000000', '9900000000000000']
}
const mintTestInputTx02 = {
txid: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
hash: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
version: 1,
size: 473,
locktime: 543613,
vin: [
{
txid: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
vout: 3,
scriptSig: {
asm:
'3045022100ac43a871e0f84787001db745e4801b789fd9cd7efa247727ebb5c0c7b66d597302205316328b6501759e9a15ec65202219a433172d153f9f1b68f65f3a63494ba6f0[ALL|FORKID] 0345a5f5dd11c987b346c18c245f0df6d305369984b9b3c7ba465c29875466e374',
hex:
'483045022100ac43a871e0f84787001db745e4801b789fd9cd7efa247727ebb5c0c7b66d597302205316328b6501759e9a15ec65202219a433172d153f9f1b68f65f3a63494ba6f041210345a5f5dd11c987b346c18c245f0df6d305369984b9b3c7ba465c29875466e374'
},
sequence: 4294967294,
address: 'bitcoincash:qqj0durd4qzdddvl2u6sen8n8h6mljtywugqctt9km',
value: 0.00056266
},
{
txid: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
vout: 2,
scriptSig: {
asm:
'304402202ce2d9d63bc6ab7765d267540fd3429bf7a8d1b50e975391fff3a4506289461a02205daf3f761a9b02d141f22136a6fe019062182c9da1b1d3a5245ff745f1236e45[ALL|FORKID] 02c00b05bc633a48e074bc54dd195b19a470ad6252ac8d306c82a2bd729c1c4c69',
hex:
'47304402202ce2d9d63bc6ab7765d267540fd3429bf7a8d1b50e975391fff3a4506289461a02205daf3f761a9b02d141f22136a6fe019062182c9da1b1d3a5245ff745f1236e45412102c00b05bc633a48e074bc54dd195b19a470ad6252ac8d306c82a2bd729c1c4c69'
},
sequence: 4294967294,
address: 'bitcoincash:qzf72qccdgjrpjpewq8dazlze6jyxzku8q3cauna4t',
value: 0.00000546
}
],
vout: [
{
value: 0,
n: 0,
scriptPubKey: {
asm:
'OP_RETURN 5262419 1 1414416717 938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8 2 000000000003928b',
hex:
'6a04534c50000101044d494e5420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8010208000000000003928b',
type: 'nulldata'
}
},
{
value: 0.00000546,
n: 1,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 1272884e6bd20c4661b5a052f874ff9a14c925b2 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a9141272884e6bd20c4661b5a052f874ff9a14c925b288ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qqf89zzwd0fqc3npkks997r5l7dpfjf9kgx2rqu500']
}
},
{
value: 0.00000546,
n: 2,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 d1eaebf8d1face5bd866e36bd94f43e2ffceef71 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914d1eaebf8d1face5bd866e36bd94f43e2ffceef7188ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qrg746lc68avuk7cvm3khk20g030lnh0wy5h2k2fqr']
}
},
{
value: 0.00054848,
n: 3,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 17178e31b3e468c0d98d57be07bc907bf94d1fdb OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a91417178e31b3e468c0d98d57be07bc907bf94d1fdb88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qqt30r33k0jx3sxe34tmupaujpaljnglmvqgrrfp2x']
}
}
],
hex:
'0100000002f8cda53b43b0ea49991a9bc6c74eb901d2a8b964bc7b8987d76789618ec18c93030000006b483045022100ac43a871e0f84787001db745e4801b789fd9cd7efa247727ebb5c0c7b66d597302205316328b6501759e9a15ec65202219a433172d153f9f1b68f65f3a63494ba6f041210345a5f5dd11c987b346c18c245f0df6d305369984b9b3c7ba465c29875466e374fefffffff8cda53b43b0ea49991a9bc6c74eb901d2a8b964bc7b8987d76789618ec18c93020000006a47304402202ce2d9d63bc6ab7765d267540fd3429bf7a8d1b50e975391fff3a4506289461a02205daf3f761a9b02d141f22136a6fe019062182c9da1b1d3a5245ff745f1236e45412102c00b05bc633a48e074bc54dd195b19a470ad6252ac8d306c82a2bd729c1c4c69feffffff040000000000000000396a04534c50000101044d494e5420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8010208000000000003928b22020000000000001976a9141272884e6bd20c4661b5a052f874ff9a14c925b288ac22020000000000001976a914d1eaebf8d1face5bd866e36bd94f43e2ffceef7188ac40d60000000000001976a91417178e31b3e468c0d98d57be07bc907bf94d1fdb88ac7d4b0800',
blockhash: '00000000000000000140f0d813052da59c811a936494a8d8b2d60b215d19e3dc',
confirmations: 168436,
time: 1534391953,
blocktime: 1534391953
}
const mintTestOpReturnData04 = {
tokenType: 1,
txType: 'MINT',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
mintBatonVout: 2,
qty: '234123'
}
const mintTestOpReturnData05 = {
tokenType: 1,
txType: 'GENESIS',
ticker: 'Bubb2',
name: 'the new bubbles!',
tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
documentUri: '',
documentHash: '',
decimals: 5,
mintBatonVout: 2,
qty: '4354534534'
}
const genesisTestInputTx02 = {
txid: '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
hash: '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
version: 1,
size: 444,
locktime: 571211,
vin: [
{
txid: 'f3e056874846b6f491a1ccac3da81a3411c61d8466835446a52efa68c0d11804',
vout: 0,
scriptSig: {
asm:
'3044022022fb67bd9b35810db3fa04da4014cc93063c5ed15e8febeca09d32c03397068502206fbb86498919ca8a9be6940c904c944cd923691391a4a7d92e0c841605d46b2e[ALL|FORKID] 03fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bf',
hex:
'473044022022fb67bd9b35810db3fa04da4014cc93063c5ed15e8febeca09d32c03397068502206fbb86498919ca8a9be6940c904c944cd923691391a4a7d92e0c841605d46b2e412103fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bf'
},
sequence: 4294967294,
address: 'bitcoincash:qz6rcxjw34yuy5fngu7fngnyy55t0v802cmsmjvsp2',
value: 0.00001111
},
{
txid: '87bf0efc1630f5179b73496f9f885b141cb4c8366432a91ba678298432b197ea',
vout: 0,
scriptSig: {
asm:
'3045022100d5fbab461c19c7b56245287eb15510c86872ceb405ede7322f5266efa6cc32ea022074b557bcef9a129fb31cb2e7c2ada9fe51d5cf924ae55d1d2a29368ca1f15ef2[ALL|FORKID] 03fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bf',
hex:
'483045022100d5fbab461c19c7b56245287eb15510c86872ceb405ede7322f5266efa6cc32ea022074b557bcef9a129fb31cb2e7c2ada9fe51d5cf924ae55d1d2a29368ca1f15ef2412103fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bf'
},
sequence: 4294967294,
address: 'bitcoincash:qz6rcxjw34yuy5fngu7fngnyy55t0v802cmsmjvsp2',
value: 0.007
}
],
vout: [
{
value: 0,
n: 0,
scriptPubKey: {
asm:
'OP_RETURN 5262419 1 47454e45534953 5350494345 5370696365 7370696365736c7040676d61696c2e636f6d 0 8 0 016345785d8a0000',
hex:
'6a04534c500001010747454e45534953055350494345055370696365127370696365736c7040676d61696c2e636f6d4c0001084c0008016345785d8a0000',
type: 'nulldata'
}
},
{
value: 0.00000546,
n: 1,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 70e5c384ae563b4fd6cfc5f7f8df43ea427d9e10 OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a91470e5c384ae563b4fd6cfc5f7f8df43ea427d9e1088ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qpcwtsuy4etrkn7kelzl07xlg04yylv7zqru2cqwvm']
}
},
{
value: 0.0070012,
n: 2,
scriptPubKey: {
asm:
'OP_DUP OP_HASH160 df305a87d98cd64e1bee825d2167a16445ecdfdd OP_EQUALVERIFY OP_CHECKSIG',
hex: '76a914df305a87d98cd64e1bee825d2167a16445ecdfdd88ac',
reqSigs: 1,
type: 'pubkeyhash',
addresses: ['bitcoincash:qr0nqk58mxxdvnsma6p96gt859jytmxlm5t0v7de4q']
}
}
],
hex:
'01000000020418d1c068fa2ea546548366841dc611341aa83daccca191f4b646488756e0f3000000006a473044022022fb67bd9b35810db3fa04da4014cc93063c5ed15e8febeca09d32c03397068502206fbb86498919ca8a9be6940c904c944cd923691391a4a7d92e0c841605d46b2e412103fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bffeffffffea97b132842978a61ba9326436c8b41c145b889f6f49739b17f53016fc0ebf87000000006b483045022100d5fbab461c19c7b56245287eb15510c86872ceb405ede7322f5266efa6cc32ea022074b557bcef9a129fb31cb2e7c2ada9fe51d5cf924ae55d1d2a29368ca1f15ef2412103fbe2c56094dc336f6244eac2e45d3d25a8e97059f2cc7de31cbf179e73dcc9bffeffffff0300000000000000003e6a04534c500001010747454e45534953055350494345055370696365127370696365736c7040676d61696c2e636f6d4c0001084c0008016345785d8a000022020000000000001976a91470e5c384ae563b4fd6cfc5f7f8df43ea427d9e1088acd8ae0a00000000001976a914df305a87d98cd64e1bee825d2167a16445ecdfdd88ac4bb70800',
blockhash: '000000000000000002278c188c52b536d4ed84a1970d8ff59043e082cef7748a',
confirmations: 141226,
time: 1551042875,
blocktime: 1551042875
}
const genesisTestOpReturn03 = {
tokenType: 1,
txType: 'GENESIS',
ticker: 'SPICE',
name: 'Spice',
tokenId: '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf',
documentUri: 'spiceslp@gmail.com',
documentHash: '',
decimals: 8,
mintBatonVout: 0,
qty: '100000000000000000'
}
module.exports = {
nonSlpTxDetails,
slpTxDetails,
mockOpReturnData01,
mockOpReturnData02,
mockOpReturnData03
mockOpReturnData03,
genesisTestInputTx,
mintTestInputTx,
genesisTestOpReturnData01,
genesisTestOpReturnData02,
mintTestOpReturnData01,
mintTestOpReturnData02,
mintTestOpReturnData03,
sendTestInputTx01,
sendTestOpReturnData01,
sendTestOpReturnData02,
sendTestOpReturnData03,
sendTestOpReturnData04,
mintTestInputTx02,
mintTestOpReturnData04,
mintTestOpReturnData05,
genesisTestInputTx02,
genesisTestOpReturn03
}
+19 -17
View File
@@ -2281,23 +2281,25 @@ describe('#SLP Utils', () => {
assert.equal(result, true)
})
it('catches and throws an error', async () => {
try {
const txid = 'fakeTxid'
// Force an error
sandbox
.stub(uut.Utils, 'validateTxid3')
.rejects(new Error('fake error'))
await await uut.Utils.waterfallValidateTxid(txid)
assert.fail('Unexpected result')
} catch (err) {
// console.log(`err.message: ${err.message}`)
assert.include(err.message, 'fake error')
}
})
// CT 08-09-21 Changed behavior. validateTxid3() is now wrapped in a
// try/catch statement that exits quietly if there is an error.
// it('catches and throws an error', async () => {
// try {
// const txid = 'fakeTxid'
//
// // Force an error
// sandbox
// .stub(uut.Utils, 'validateTxid3')
// .rejects(new Error('fake error'))
//
// await await uut.Utils.waterfallValidateTxid(txid)
//
// assert.fail('Unexpected result')
// } catch (err) {
// // console.log(`err.message: ${err.message}`)
// assert.include(err.message, 'fake error')
// }
// })
})
describe('#getWhitelist', () => {
+592 -3
View File
@@ -5,15 +5,21 @@
// Public npm libraries
const assert = require('chai').assert
const sinon = require('sinon')
const cloneDeep = require('lodash.clonedeep')
const BCHJS = require('../../src/bch-js')
const bchjs = new BCHJS()
const mockData = require('./fixtures/transaction-mock.js')
const mockDataLib = require('./fixtures/transaction-mock.js')
describe('#TransactionLib', () => {
let sandbox
beforeEach(() => (sandbox = sinon.createSandbox()))
let sandbox, mockData
beforeEach(() => {
sandbox = sinon.createSandbox()
mockData = cloneDeep(mockDataLib)
})
afterEach(() => sandbox.restore())
describe('#get', () => {
@@ -115,5 +121,588 @@ describe('#TransactionLib', () => {
assert.include(err.message, 'test error')
}
})
// This test case was created in response to a bug. When the input TX
// was a Genesis SLP transaction, the inputs of the transaction were not
// being hydrated properly.
it('should get input details when input is a genesis tx', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.genesisTestInputTx)
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.genesisTestOpReturnData01)
.onCall(1)
.resolves(mockData.genesisTestOpReturnData02)
.onCall(2)
.resolves(mockData.genesisTestOpReturnData02)
.onCall(3)
.resolves(mockData.genesisTestOpReturnData02)
sandbox
.stub(bchjs.Transaction.slpUtils, 'waterfallValidateTxid')
.resolves(true)
const txid =
'874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e'
const result = await bchjs.Transaction.get(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert that added properties exist.
assert.property(result.vout[0], 'tokenQty')
assert.equal(result.vout[0].tokenQty, null)
assert.property(result.vin[0], 'address')
assert.property(result.vin[0], 'value')
assert.property(result.vin[0], 'tokenQty')
assert.property(result, 'isValidSLPTx')
assert.equal(result.isValidSLPTx, true)
// Assert inputs values unique to a Genesis input have the proper values.
assert.equal(result.vin[0].tokenQty, 10000000)
assert.equal(result.vin[1].tokenQty, null)
})
it('should get input details when input is a mint tx', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.mintTestInputTx)
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.mintTestOpReturnData01)
.onCall(1)
.resolves(mockData.mintTestOpReturnData02)
.onCall(2)
.resolves(mockData.mintTestOpReturnData02)
.onCall(3)
.resolves(mockData.mintTestOpReturnData03)
.onCall(4)
.resolves(mockData.mintTestOpReturnData03)
sandbox
.stub(bchjs.Transaction.slpUtils, 'waterfallValidateTxid')
.resolves(true)
const txid =
'4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa'
const result = await bchjs.Transaction.get(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert that added properties exist.
assert.property(result.vout[0], 'tokenQty')
assert.equal(result.vout[0].tokenQty, null)
assert.property(result.vin[0], 'address')
assert.property(result.vin[0], 'value')
assert.property(result.vin[0], 'tokenQty')
assert.property(result, 'isValidSLPTx')
assert.equal(result.isValidSLPTx, true)
// Assert inputs values unique to a Mint input have the proper values.
assert.equal(result.vin[0].tokenQty, 43545.34534)
assert.equal(result.vin[1].tokenQty, 2.34123)
assert.equal(result.vin[2].tokenQty, null)
})
// This test case was generated from the problematic transaction that
// used inputs in a 'non-standard' way.
it('should correctly assign quantities to mixed mint inputs', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.sendTestInputTx01)
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.sendTestOpReturnData01)
.onCall(1)
.resolves(mockData.sendTestOpReturnData02)
.onCall(2)
.resolves(mockData.sendTestOpReturnData03)
.onCall(3)
.resolves(mockData.sendTestOpReturnData03)
.onCall(4)
.resolves(mockData.sendTestOpReturnData04)
sandbox
.stub(bchjs.Transaction.slpUtils, 'waterfallValidateTxid')
.resolves(true)
const txid =
'6bc111fbf5b118021d68355ca19a0e77fa358dd931f284b2550f79a51ab4792a'
const result = await bchjs.Transaction.get(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert that added properties exist.
assert.property(result.vout[0], 'tokenQty')
assert.equal(result.vout[0].tokenQty, null)
assert.property(result.vin[0], 'address')
assert.property(result.vin[0], 'value')
assert.property(result.vin[0], 'tokenQty')
assert.property(result, 'isValidSLPTx')
assert.equal(result.isValidSLPTx, true)
// Assert inputs values unique to a Mint input have the proper values.
assert.equal(result.vin[0].tokenQty, 100000000)
assert.equal(result.vin[1].tokenQty, null)
assert.equal(result.vin[2].tokenQty, 99000000)
})
})
describe('#get3', () => {
it('should throw an error if txid is not specified', async () => {
try {
await bchjs.Transaction.get3()
assert.fail('Unexpected code path!')
} catch (err) {
assert.include(
err.message,
'Input to Transaction.get() must be a string containing a TXID.'
)
}
})
it('should get details about a non-SLP transaction', async () => {
const txid =
'2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.nonSlpTxDetails)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 602405 })
sandbox.stub(bchjs.Transaction, 'getTokenInfo').resolves(false)
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[0].scriptPubKey, 'addresses')
// Assert that added properties exist.
assert.property(result.vin[0], 'address')
assert.property(result.vin[0], 'value')
// Assert blockheight is added
assert.equal(result.blockheight, 602405)
assert.equal(result.isSlpTx, false)
})
it('should get details about a SLP SEND tx with SEND input', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.slpTxDetails)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 603424 })
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.mockOpReturnData01)
.onCall(1)
.resolves(mockData.mockOpReturnData02)
.onCall(2)
.resolves(mockData.mockOpReturnData03)
.onCall(3)
.rejects(new Error('No OP_RETURN'))
const txid =
'266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert outputs have expected properties
assert.equal(result.vout[0].tokenQty, null)
assert.equal(result.vout[0].tokenQtyStr, null)
assert.equal(result.vout[1].tokenQty, 1)
assert.equal(result.vout[1].tokenQtyStr, '1')
assert.equal(result.vout[2].tokenQty, 998833)
assert.equal(result.vout[2].tokenQtyStr, '998833')
assert.equal(result.vout[3].tokenQty, null)
assert.equal(result.vout[3].tokenQtyStr, null)
// Assert that inputs have expected properties
assert.equal(result.vin[0].tokenQtyStr, '998834')
assert.equal(result.vin[0].tokenQty, 998834)
assert.equal(
result.vin[0].tokenId,
'497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7'
)
assert.equal(result.vin[1].tokenQtyStr, '0')
assert.equal(result.vin[1].tokenQty, 0)
assert.equal(result.vin[1].tokenId, null)
// Assert blockheight is added
assert.equal(result.blockheight, 603424)
assert.equal(result.isSlpTx, true)
})
it('should catch and throw error on network error', async () => {
try {
const txid =
'2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
// Force an error
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.rejects(new Error('test error'))
await bchjs.Transaction.get3(txid)
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
// This test case was created in response to a bug. When the input TX
// was a Genesis SLP transaction, the inputs of the transaction were not
// being hydrated properly.
it('should get details about a SLP SEND tx with GENSIS input', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.genesisTestInputTx)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 543409 })
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.genesisTestOpReturnData01)
.onCall(1)
.resolves(mockData.genesisTestOpReturnData02)
.onCall(2)
.resolves(mockData.genesisTestOpReturnData02)
.onCall(3)
.resolves(mockData.genesisTestOpReturnData02)
const txid =
'874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert outputs have expected properties and values
assert.equal(result.vout[0].tokenQty, null)
assert.equal(result.vout[0].tokenQtyStr, null)
assert.equal(result.vout[1].tokenQty, 5000000)
assert.equal(result.vout[1].tokenQtyStr, '5000000')
assert.equal(result.vout[2].tokenQty, 5000000)
assert.equal(result.vout[2].tokenQtyStr, '5000000')
assert.equal(result.vout[3].tokenQty, null)
assert.equal(result.vout[3].tokenQtyStr, null)
// Assert inputs have expected properties and values
assert.equal(result.vin[0].tokenQty, 10000000)
assert.equal(result.vin[0].tokenQtyStr, '10000000')
assert.equal(
result.vin[0].tokenId,
'323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35'
)
assert.equal(result.vin[1].tokenQty, 0)
assert.equal(result.vin[1].tokenQtyStr, '0')
assert.equal(result.vin[1].tokenId, null)
// Assert blockheight is added
assert.equal(result.blockheight, 543409)
assert.equal(result.isSlpTx, true)
})
it('should get details about a SLP SEND tx with MINT (and GENESIS) input', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.mintTestInputTx)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 543614 })
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.mintTestOpReturnData01)
.onCall(1)
.resolves(mockData.mintTestOpReturnData02)
.onCall(2)
.resolves(mockData.mintTestOpReturnData02)
.onCall(3)
.resolves(mockData.mintTestOpReturnData03)
.onCall(4)
.resolves(mockData.mintTestOpReturnData03)
const txid =
'4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert expected output properties and values exist.
assert.equal(result.vout[0].tokenQty, null)
assert.equal(result.vout[1].tokenQty, 43547.68657)
assert.equal(result.vout[1].tokenQtyStr, '43547.68657')
assert.equal(result.vout[2].tokenQty, null)
// Assert expected input properties and values exist.
assert.equal(result.vin[0].tokenQty, 43545.34534)
assert.equal(result.vin[0].tokenQtyStr, '43545.34534')
assert.equal(
result.vin[0].tokenId,
'938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8'
)
assert.equal(result.vin[1].tokenQty, 2.34123)
assert.equal(result.vin[1].tokenQtyStr, '2.34123')
assert.equal(
result.vin[1].tokenId,
'938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8'
)
assert.equal(result.vin[2].tokenQty, 0)
assert.equal(result.vin[2].tokenQtyStr, '0')
assert.equal(result.vin[2].tokenId, null)
// Assert blockheight is added
assert.equal(result.blockheight, 543614)
assert.equal(result.isSlpTx, true)
})
// This test case was generated from the problematic transaction that
// used inputs in a 'non-standard' way.
it('should get details about a SLP SEND tx with MINT (and SEND) input', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.sendTestInputTx01)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 543957 })
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.sendTestOpReturnData01)
.onCall(1)
.resolves(mockData.sendTestOpReturnData02)
.onCall(2)
.resolves(mockData.sendTestOpReturnData03)
.onCall(3)
.resolves(mockData.sendTestOpReturnData03)
.onCall(4)
.resolves(mockData.sendTestOpReturnData04)
const txid =
'6bc111fbf5b118021d68355ca19a0e77fa358dd931f284b2550f79a51ab4792a'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert the outputs have expected properties and values.
assert.equal(result.vout[0].tokenQty, null)
assert.equal(result.vout[1].tokenQty, 1000000)
assert.equal(result.vout[1].tokenQtyStr, '1000000')
assert.equal(result.vout[2].tokenQty, 198000000)
assert.equal(result.vout[2].tokenQtyStr, '198000000')
assert.equal(result.vout[3].tokenQty, null)
// Assert the inputs have expected properties and values.
assert.equal(result.vin[0].tokenQty, 100000000)
assert.equal(result.vin[0].tokenQtyStr, '100000000')
assert.equal(
result.vin[0].tokenId,
'550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35'
)
assert.equal(result.vin[1].tokenQty, 0)
assert.equal(result.vin[1].tokenQtyStr, 0)
assert.equal(result.vin[1].tokenId, null)
assert.equal(result.vin[2].tokenQty, 99000000)
assert.equal(result.vin[2].tokenQtyStr, '99000000')
assert.equal(
result.vin[2].tokenId,
'550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35'
)
// Assert blockheight is added
assert.equal(result.blockheight, 543957)
assert.equal(result.isSlpTx, true)
})
// This was a problematic TX
it('should process MINT TX with GENESIS input', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.mintTestInputTx02)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 543614 })
sandbox
.stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
.onCall(0)
.resolves(mockData.mintTestOpReturnData04)
.onCall(1)
.resolves(mockData.mintTestOpReturnData05)
.onCall(2)
.resolves(mockData.mintTestOpReturnData05)
.onCall(3)
.resolves(mockData.mintTestOpReturnData05)
.onCall(4)
.resolves(mockData.mintTestOpReturnData05)
.onCall(5)
.resolves(mockData.mintTestOpReturnData05)
const txid =
'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert outputs have expected properties and values
assert.equal(result.vout[0].tokenQty, 0)
assert.equal(result.vout[0].tokenQty, '0')
assert.equal(result.vout[1].tokenQty, 2.34123)
assert.equal(result.vout[1].tokenQty, '2.34123')
assert.equal(result.vout[2].tokenQty, 0)
assert.equal(result.vout[2].tokenQty, '0')
assert.equal(result.vout[2].isMintBaton, true)
assert.equal(result.vout[3].tokenQty, 0)
assert.equal(result.vout[3].tokenQty, '0')
// Assert inputs have expected properties and values
assert.equal(result.vin[0].tokenQty, 0)
assert.equal(result.vin[0].tokenQtyStr, '0')
assert.equal(result.vin[0].tokenId, null)
assert.equal(result.vin[1].tokenQty, 0)
assert.equal(result.vin[1].tokenQtyStr, '0')
assert.equal(
result.vin[1].tokenId,
'938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8'
)
assert.equal(result.vin[1].isMintBaton, true)
// Assert added TX data exists.
assert.equal(result.blockheight, 543614)
assert.equal(result.isSlpTx, true)
})
// It should process a GENESIS tx
it('should process a GENESIS tx', async () => {
// Mock dependencies
sandbox
.stub(bchjs.Transaction.rawTransaction, 'getTxData')
.resolves(mockData.genesisTestInputTx02)
sandbox
.stub(bchjs.Transaction.blockchain, 'getBlockHeader')
.resolves({ height: 571212 })
sandbox
.stub(bchjs.Transaction, 'getTokenInfo')
.onCall(0)
.resolves(mockData.genesisTestOpReturn03)
.onCall(1)
.resolves(mockData.genesisTestOpReturn03)
.onCall(2)
.resolves(false)
.onCall(3)
.resolves(false)
.onCall(4)
.resolves(false)
const txid =
'4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf'
const result = await bchjs.Transaction.get3(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Assert that there are stanardized properties.
assert.property(result, 'txid')
assert.property(result, 'vin')
assert.property(result, 'vout')
assert.property(result.vout[0], 'value')
assert.property(result.vout[1].scriptPubKey, 'addresses')
// Assert output have expected properties and values
assert.equal(result.vout[0].tokenQty, 0)
assert.equal(result.vout[0].tokenQtyStr, '0')
assert.equal(result.vout[0].isMintBaton, true)
assert.equal(result.vout[1].tokenQty, 1000000000)
assert.equal(result.vout[1].tokenQtyStr, '1000000000')
assert.equal(result.vout[2].tokenQty, 0)
assert.equal(result.vout[2].tokenQtyStr, '0')
// Assert input have expected properties and values
assert.equal(result.vin[0].tokenQty, 0)
assert.equal(result.vin[0].tokenQtyStr, '0')
assert.equal(result.vin[0].tokenId, null)
assert.equal(result.vin[1].tokenQty, 0)
assert.equal(result.vin[1].tokenQtyStr, '0')
assert.equal(result.vin[1].tokenId, null)
// Assert added TX data exists.
assert.equal(result.blockheight, 571212)
assert.equal(result.isSlpTx, true)
})
})
})