Compare commits

...
49 Commits
Author SHA1 Message Date
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 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 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
31 changed files with 8725 additions and 12925 deletions
+2 -4
View File
@@ -33,9 +33,6 @@ 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/v5/' })
```
This library is intended to be paired with
@@ -43,7 +40,6 @@ the [bch-api](https://github.com/Permissionless-Software-Foundation/bch-api) RES
- BCHN Mainnet REST API server: https://bchn.fullstack.cash/v5/
- ABC Mainnet REST API server: https://abc.fullstack.cash/v5/
- Testnet3 REST API server: https://testnet3.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
+7406 -12530
View File
File diff suppressed because it is too large Load Diff
+43 -43
View File
@@ -36,53 +36,53 @@
"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": "^8.1.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.8",
"lodash.clonedeep": "4.5.0",
"mocha": "9.1.3",
"node-mocks-http": "1.7.0",
"nyc": "15.1.0",
"prettier": "1.18.2",
"semantic-release": "18.0.0",
"sinon": "7.3.2",
"standard": "^16.0.4"
},
"apidoc": {
"title": "bch-js",
+74 -1
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)
@@ -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
+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(
+42 -3
View File
@@ -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 () => {
@@ -140,9 +141,47 @@ class Price {
* }
*})()
*
* // 18.81
* // 212.34
*/
async getBchaUsd () {
try {
const response = await this.axios.get(
`${this.restURL}price/bchausd`,
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
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.err(err)
* }
*})()
*
* // 0.00021234
*/
async getXecUsd () {
try {
const response = await this.axios.get(
`${this.restURL}price/bchausd`,
+3
View File
@@ -319,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)
+9 -3
View File
@@ -287,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()
+17 -23
View File
@@ -921,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) {
@@ -1588,31 +1588,25 @@ class Utils {
// Note: validateTxid3() has the same output as validateTxid().
// validateTxid2() uses slp-validate, which has a different output format.
// If the whitelist SLPDB is having issues, the try/catch will skip it
// and continue execution.
try {
// Validate against the whitelist SLPDB first.
const whitelistResult = await this.validateTxid3(txid, usrObj)
// console.log(
// `whitelist-SLPDB for ${txid}: ${JSON.stringify(
// whitelistResult,
// null,
// 2
// )}`
// )
// Validate against the whitelist SLPDB first.
const whitelistResult = await this.validateTxid3(txid, usrObj)
// console.log(
// `whitelist-SLPDB for ${txid}: ${JSON.stringify(
// whitelistResult,
// null,
// 2
// )}`
// )
// Safely retrieve the returned value.
if (whitelistResult[0] !== null) isValid = whitelistResult[0].valid
// Safely retrieve the returned value.
if (whitelistResult[0] !== null) isValid = whitelistResult[0].valid
// Exit if isValid is not null.
if (isValid !== null) {
// Save to the cache.
cachedTxValidation[txid] = isValid
// Exit if isValid is not null.
if (isValid !== null) {
// Save to the cache.
cachedTxValidation[txid] = isValid
return isValid
}
} catch {
/* exit quietly */
return isValid
}
// Try the general SLPDB, if the whitelist returned null.
+272 -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,6 +194,202 @@ 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
}
return txDetails
} 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.get2() get2()
* @apiName get2
* @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 get2 (txid) {
try {
if (typeof txid !== 'string') {
throw new Error(
'Input to Transaction.get() must be a string containing a TXID.'
)
}
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
// First get the token information for the output. If that fails, then
// this is not an SLP transaction, and this method can return false.
let outTokenData
try {
outTokenData = await this.slpUtils.decodeOpReturn(txid)
// console.log(`outTokenData: ${JSON.stringify(outTokenData, null, 2)}`)
// Get Genesis data for this token.
const genesisData = await this.slpUtils.decodeOpReturn(
outTokenData.tokenId
// decodeOpReturnCache
// usrObj // pass user data when making an internal call.
)
// console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`)
// Add token information to the tx details object.
txDetails.tokenTxType = outTokenData.txType
txDetails.tokenId = outTokenData.tokenId
txDetails.tokenTicker = genesisData.ticker
txDetails.tokenName = genesisData.name
txDetails.tokenDecimals = genesisData.decimals
txDetails.tokenUri = genesisData.documentUri
txDetails.tokenDocHash = genesisData.documentHash
// 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)
// 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.
for (let i = 0; i < txDetails.vout.length; i++) {
const thisVout = txDetails.vout[i]
if (!thisVout.tokenQty && thisVout.tokenQty !== 0) {
thisVout.tokenQty = null
}
}
// 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
// from an SLP transaction and can be ignored.
const inTokenData = await this.slpUtils.decodeOpReturn(thisVin.txid)
// console.log(
// `vin[${i}] tokenData: ${JSON.stringify(inTokenData, null, 2)}`
// )
let tokenQty = 0
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.get2(). What is the txType?'
)
console.log(inTokenData)
throw new Error('Unexpected code path')
}
if (tokenQty) {
// 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
thisVin.tokenQtyStr = null
}
} catch (err) {
// If decodeOpReturn() throws an error, then this input is not
// from an SLP transaction and can be ignored.
// thisVin.tokenQty = null
thisVin.tokenQty = null
thisVin.tokenQtyStr = null
continue
}
}
} catch (err) {
// console.log('Error: ', err)
+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', () => {
@@ -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)
})
})
})
+1 -1
View File
@@ -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', () => {
+396 -1
View File
@@ -175,10 +175,405 @@ 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'
]
}
module.exports = {
nonSlpTxDetails,
slpTxDetails,
mockOpReturnData01,
mockOpReturnData02,
mockOpReturnData03
mockOpReturnData03,
genesisTestInputTx,
mintTestInputTx,
genesisTestOpReturnData01,
genesisTestOpReturnData02,
mintTestOpReturnData01,
mintTestOpReturnData02,
mintTestOpReturnData03,
sendTestInputTx01,
sendTestOpReturnData01,
sendTestOpReturnData02,
sendTestOpReturnData03,
sendTestOpReturnData04
}
+419
View File
@@ -115,5 +115,424 @@ 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('#get2', () => {
it('should throw an error if txid is not specified', async () => {
try {
await bchjs.Transaction.get2()
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 })
const result = await bchjs.Transaction.get2(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.property(result, 'isValidSLPTx')
assert.equal(result.isValidSLPTx, false)
// Assert blockheight is added
assert.equal(result.blockheight, 602405)
})
it('should get details about a SLP transaction', 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.get2(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 that tokenIds and tokenQty are included in inputs.
assert.property(result.vin[0], 'tokenId')
assert.equal(result.vin[0].tokenQtyStr, '998834')
// Assert blockheight is added
assert.equal(result.blockheight, 603424)
})
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.get(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 input details when input is a genesis tx', 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.get2(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 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)
// Assert that tokenIds and tokenQty are included in inputs.
assert.property(result.vin[0], 'tokenId')
assert.equal(result.vin[0].tokenQtyStr, '10000000')
assert.equal(result.vin[1].tokenQty, null)
assert.equal(result.vin[1].tokenQtyStr, null)
// Assert blockheight is added
assert.equal(result.blockheight, 543409)
})
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.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.get2(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 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)
// Assert blockheight is added
assert.equal(result.blockheight, 543614)
})
// 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.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.get2(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 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)
// Assert blockheight is added
assert.equal(result.blockheight, 543957)
})
})
})