mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-22 17:12:01 -07:00
feat(getTxData): RawTransactions.getTxData() returns tx info with vin addresses
This commit is contained in:
+1
-1
@@ -17,7 +17,7 @@
|
||||
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
||||
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v4/ mocha --timeout 30000 test/integration/testnet",
|
||||
"test:temp": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#rawtransaction' test/integration/",
|
||||
"test:temp2": "mocha --timeout=30000 -g '#_getInputAddrs' test/unit/",
|
||||
"test:temp2": "mocha --timeout=30000 -g '#getTxData' test/unit/",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
|
||||
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
|
||||
|
||||
+62
-9
@@ -289,20 +289,19 @@ class RawTransactions {
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the parent TX (pTX) for the given TXID in order to retrieve the BCH
|
||||
// address of the inputs for the given TXID.
|
||||
// Assumes a single TXID. Does not yet work with an array of TXIDs.
|
||||
// Given verbose transaction details, this function retrieves the transaction
|
||||
// data for the inputs (the parent transactions). It returns an array of
|
||||
// objects. Each object corresponds to a transaction input, and contains
|
||||
// the address that generated that input UTXO.
|
||||
//
|
||||
// Assumes a single TX. Does not yet work with an array of TXs.
|
||||
// This function returns an array of objects, each object if formated as follows:
|
||||
// {
|
||||
// vin: 0, // The position of the input for the given txid
|
||||
// address: bitcoincash:qzhrpmu7nruyfcemeanqh5leuqcnf6zkjq4qm9nqh0
|
||||
// }
|
||||
async _getInputAddrs (txid) {
|
||||
async _getInputAddrs (txDetails) {
|
||||
try {
|
||||
// Get the TX details for the transaction under consideration.
|
||||
const txDetails = await this.getRawTransaction(txid, true)
|
||||
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
||||
|
||||
const retArray = [] // Return array
|
||||
|
||||
for (let i = 0; i < txDetails.vin.length; i++) {
|
||||
@@ -314,7 +313,9 @@ class RawTransactions {
|
||||
// Get the TX details for the input, in order to retrieve the address of
|
||||
// the sender.
|
||||
const txDetailsParent = await this.getRawTransaction(inputTxid, true)
|
||||
console.log(`txDetailsParent: ${JSON.stringify(txDetailsParent, null, 2)}`)
|
||||
// console.log(
|
||||
// `txDetailsParent: ${JSON.stringify(txDetailsParent, null, 2)}`
|
||||
// )
|
||||
|
||||
// The vout from the previous tx that represents the sender.
|
||||
const voutSender = txDetailsParent.vout[inputVout]
|
||||
@@ -332,6 +333,58 @@ class RawTransactions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api RawTransactions.getTxData() getTxData()
|
||||
* @apiName getTxData
|
||||
* @apiGroup RawTransactions
|
||||
* @apiDescription
|
||||
* Returns an object of transaction data, including addresses for input UTXOs.
|
||||
*
|
||||
* This function is equivalent to running `getRawTransaction (txid, true)`,
|
||||
* execept the `vin` array will be populated with an `address` property that
|
||||
* contains the `bitcoincash:` address of the sender for each input.
|
||||
*
|
||||
* This function will only work with a single txid. It does not yet support an
|
||||
* array of TXIDs.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* (async () => {
|
||||
* try {
|
||||
* let txData = await bchjs.RawTransactions.getTxData("0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098");
|
||||
* console.log(txData);
|
||||
* } catch(error) {
|
||||
* console.error(error)
|
||||
* }
|
||||
* })()
|
||||
*/
|
||||
// Equivalent to running: async getRawTransaction (txid, verbose = true)
|
||||
// Only handles a single TXID (not arrays).
|
||||
// Appends the BCH address to the inputs of the transaction.
|
||||
async getTxData (txid) {
|
||||
try {
|
||||
if (typeof txid !== 'string') {
|
||||
throw new Error('Input must be a string or array of strings.')
|
||||
}
|
||||
|
||||
// Get the TX details for the transaction under consideration.
|
||||
const txDetails = await this.getRawTransaction(txid, true)
|
||||
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
||||
|
||||
const inAddrs = await this._getInputAddrs(txDetails)
|
||||
// console.log(`inAddrs: ${JSON.stringify(inAddrs, null, 2)}`)
|
||||
|
||||
// Add the input address to the transaction data.
|
||||
for (let i = 0; i < inAddrs.length; i++) {
|
||||
txDetails.vin[i].address = inAddrs[i].address
|
||||
}
|
||||
|
||||
return txDetails
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
else throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api RawTransactions.sendRawTransaction() sendRawTransaction()
|
||||
* @apiName sendRawTransaction
|
||||
|
||||
@@ -254,7 +254,9 @@ describe('#rawtransaction', () => {
|
||||
// const txid = '32233db13f2ae6d82b6262f335643dccf09fc0bcfcef4bc3fbe023355f02e112'
|
||||
const txid = '05f7d4a4e25f53d63a360434eb54f221abf159112b7fffc91da1072a079cded3'
|
||||
|
||||
const result = await bchjs.RawTransactions._getInputAddrs(txid)
|
||||
const txDetails = await bchjs.RawTransactions.getRawTransaction(txid, true)
|
||||
|
||||
const result = await bchjs.RawTransactions._getInputAddrs(txDetails)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.isArray(result)
|
||||
@@ -263,6 +265,17 @@ describe('#rawtransaction', () => {
|
||||
assert.property(result[0], 'address')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTxData', () => {
|
||||
it('should return tx data with input addresses', async () => {
|
||||
const txid = '05f7d4a4e25f53d63a360434eb54f221abf159112b7fffc91da1072a079cded3'
|
||||
|
||||
const result = await bchjs.RawTransactions.getTxData(txid)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result.vin[0], 'address')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function sleep (ms) {
|
||||
|
||||
@@ -48,7 +48,15 @@ const mockParentTx1 = {
|
||||
]
|
||||
}
|
||||
|
||||
const mockGetInputAddrsOutput = [
|
||||
{
|
||||
vin: 0,
|
||||
address: 'bitcoincash:qr2jtznnkhy0jnynn4l7jmmce6teqcyrhc8herhlgt'
|
||||
}
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
mockTx,
|
||||
mockParentTx1
|
||||
mockParentTx1,
|
||||
mockGetInputAddrsOutput
|
||||
}
|
||||
|
||||
@@ -141,15 +141,9 @@ describe('#RawTransactions', () => {
|
||||
it('should return an array of input addresses', async () => {
|
||||
sandbox
|
||||
.stub(bchjs.RawTransactions, 'getRawTransaction')
|
||||
.onCall(0)
|
||||
.resolves(mockData.mockTx)
|
||||
.onCall(1)
|
||||
.resolves(mockData.mockParentTx1)
|
||||
|
||||
const txid =
|
||||
'32233db13f2ae6d82b6262f335643dccf09fc0bcfcef4bc3fbe023355f02e112'
|
||||
|
||||
const result = await bchjs.RawTransactions._getInputAddrs(txid)
|
||||
const result = await bchjs.RawTransactions._getInputAddrs(mockData.mockTx)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert2.isArray(result)
|
||||
@@ -164,7 +158,53 @@ describe('#RawTransactions', () => {
|
||||
.stub(bchjs.RawTransactions, 'getRawTransaction')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
await bchjs.RawTransactions._getInputAddrs('fake txid')
|
||||
await bchjs.RawTransactions._getInputAddrs(mockData.mockTx)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
|
||||
assert2.equal(err.message, 'test error')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getTxData', () => {
|
||||
it('should return tx data with input addresses', async () => {
|
||||
// Mock dependencies
|
||||
sandbox.stub(bchjs.RawTransactions, 'getRawTransaction').resolves(mockData.mockTx)
|
||||
sandbox.stub(bchjs.RawTransactions, '_getInputAddrs').resolves(mockData.mockGetInputAddrsOutput)
|
||||
|
||||
const txid = '05f7d4a4e25f53d63a360434eb54f221abf159112b7fffc91da1072a079cded3'
|
||||
|
||||
const result = await bchjs.RawTransactions.getTxData(txid)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert2.property(result.vin[0], 'address')
|
||||
})
|
||||
|
||||
it('should throw an error for a non-txid input', async () => {
|
||||
try {
|
||||
await bchjs.RawTransactions.getTxData(1234)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
|
||||
assert2.include(err.message, 'Input must be a string or array of strings')
|
||||
}
|
||||
})
|
||||
|
||||
it('should catch and throw an error', async () => {
|
||||
try {
|
||||
// Force a network error.
|
||||
sandbox
|
||||
.stub(bchjs.RawTransactions, 'getRawTransaction')
|
||||
.rejects(new Error('test error'))
|
||||
|
||||
const txid = '05f7d4a4e25f53d63a360434eb54f221abf159112b7fffc91da1072a079cded3'
|
||||
|
||||
await bchjs.RawTransactions.getTxData(txid)
|
||||
|
||||
assert.fail('Unexpected result')
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user