Compare commits

...
23 Commits
Author SHA1 Message Date
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
10 changed files with 5365 additions and 8341 deletions
+4660 -8317
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -54,7 +54,7 @@
"bip66": "^1.1.5",
"bitcoinjs-message": "^2.0.0",
"bs58": "^4.0.1",
"cashaddrjs": "^0.3.3",
"ecashaddrjs": "^1.0.7",
"ini": "^1.3.8",
"randombytes": "^2.0.6",
"safe-buffer": "^5.1.2",
@@ -76,9 +76,9 @@
"eslint-plugin-standard": "^4.0.0",
"husky": "^4.3.6",
"lodash.clonedeep": "^4.5.0",
"mocha": "^6.1.4",
"mocha": "^9.1.3",
"node-mocks-http": "^1.7.0",
"nyc": "^14.1.0",
"nyc": "^15.1.0",
"prettier": "^1.18.2",
"semantic-release": "^17.3.9",
"sinon": "^7.3.2",
+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
+5 -5
View File
@@ -128,7 +128,7 @@ class Price {
* @apiGroup Price
* @apiDescription Return current price of BCHA in USD.
* 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
* denominated in BCHA comes from bch-api, so it has a better chance of
* working in Tor.
*
* @apiExample Example usage:
@@ -150,7 +150,7 @@ class Price {
this.axiosOptions
)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
const bchaPrice = response.data.usd * 1000000
// Convert XEC denomination to BCHA denomination
@@ -161,7 +161,7 @@ class Price {
}
}
/**
/**
* @api price.getXecUsd() getXecUsd()
* @apiName Price getXecUsd()
* @apiGroup Price
@@ -179,9 +179,9 @@ class Price {
* }
*})()
*
* // 0.00021234
* // 0.00021234
*/
async getXecUsd () {
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()
+1 -1
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) {
+65 -10
View File
@@ -4,6 +4,7 @@
const RawTransaction = require('./raw-transactions')
const SlpUtils = require('./slp/utils')
const BigNumber = require('bignumber.js')
class Transaction {
constructor (config) {
@@ -75,9 +76,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.
@@ -101,17 +111,62 @@ 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
} else {
thisVin.tokenQty = null
+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
}
+149
View File
@@ -115,5 +115,154 @@ 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)
})
})
})