Merge pull request #14 from zh/add-electrumx-unconfirmed-utxo

Access to unconfirmed UTXOs API endpoints
This commit is contained in:
Chris Troutner
2020-08-05 08:42:14 -07:00
committed by GitHub
5 changed files with 316 additions and 1 deletions
+92
View File
@@ -299,6 +299,98 @@ class ElectrumX {
else throw error
}
}
/**
* @api Electrumx.unconfirmed() unconfirmed() - Get a list of unconfirmed uxtos (mempool) for an address.
* @apiName ElectrumX Unconfirmed
* @apiGroup ElectrumX
* @apiDescription Return a list of unconfirmed uxtos (mempool) for an address.
*
* @apiExample Example usage:
* (async () => {
* try {
* let mempool = await bchjs.Electrumx.unconfirmed('bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9');
* console.log(mempool);
* } catch(error) {
* console.error(error)
* }
* })()
*
* mempool = {
* "success": true,
* "utxos": [
* {
* "height": 602405,
* "tx_hash": "2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7",
* "fee": 24310
* }
* ]
* }
*
* (async () => {
* try {
* let mempool = await bchjs.Electrumx.unconfirmed(['bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf', 'bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v']);
* console.log(mempool);
* } catch(error) {
* console.error(error)
* }
* })()
*
* mempool = {
* "success": true,
* "utxos": [
* {
* "utxos": [
* {
* "height": 604392,
* "tx_hash": "7774e449c5a3065144cefbc4c0c21e6b69c987f095856778ef9f45ddd8ae1a41",
* "fee": 24310
* },
* {
* "height": 630834,
* "tx_hash": "4fe60a51e0d8f5134bfd8e5f872d6e502d7f01b28a6afebb27f4438a4f638d53",
* "fee": 3000
* }
* ],
* "address": "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
* },
* {
* "utxos": [],
* "address": "bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
* }
* ]
* }
*
*/
async unconfirmed(address) {
try {
// Handle single address.
if (typeof address === "string") {
const response = await axios.get(
`${this.restURL}electrumx/unconfirmed/${address}`,
_this.axiosOptions
)
return response.data
// Handle array of addresses.
} else if (Array.isArray(address)) {
const response = await axios.post(
`${this.restURL}electrumx/unconfirmed`,
{
addresses: address
},
_this.axiosOptions
)
return response.data
}
throw new Error(`Input address must be a string or array of strings.`)
} catch (error) {
if (error.response && error.response.data) throw error.response.data
else throw error
}
}
}
module.exports = ElectrumX
+59
View File
@@ -178,4 +178,63 @@ describe(`#ElectrumX`, () => {
}
})
})
describe(`#unconfirmed`, () => {
it(`should GET unconfirmed UTXOs (mempool) for a single address`, async () => {
const addr = "bitcoincash:qqy6qwk3wpne95hhv8uzwr4cn8m7c06cqgchl77dnv"
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "height")
assert.property(result.utxos[0], "tx_hash")
assert.property(result.utxos[0], "fee")
})
it(`should POST request for unconfirmed UTXOs (mempool) for an array of addresses`, async () => {
const addr = [
"bitcoincash:qqy6qwk3wpne95hhv8uzwr4cn8m7c06cqgchl77dnv",
"bitcoincash:qpyrtsl9msdu2klgfpcmn2v5r22w9rk24g8pal74ts"
]
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "utxos")
assert.isArray(result.utxos[0].utxos)
assert.property(result.utxos[0], "address")
assert.property(result.utxos[0].utxos[0], "height")
assert.property(result.utxos[0].utxos[0], "tx_hash")
assert.property(result.utxos[0].utxos[0], "fee")
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf")
const result = await bchjs.Electrumx.unconfirmed(addr)
console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
})
+59
View File
@@ -182,4 +182,63 @@ describe(`#ElectrumX`, () => {
}
})
})
describe(`#unconfirmed`, () => {
it(`should GET unconfirmed UTXOs (mempool) for a single address`, async () => {
const addr = "bchtest:qp25k20dgcljrz4hkdz43partam3j5httyprjp23qd"
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "height")
assert.property(result.utxos[0], "tx_hash")
assert.property(result.utxos[0], "fee")
})
it(`should POST unconfirmed UTXO details for an array of addresses`, async () => {
const addr = [
"bchtest:qp25k20dgcljrz4hkdz43partam3j5httyprjp23qd",
"bchtest:qpkl3xylrjx4jup6m66e7zg7whlaucsxeudxeqawdj"
]
const result = await bchjs.Electrumx.unconfirmed(addr)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "utxos")
assert.isArray(result.utxos[0].utxos)
assert.property(result.utxos[0], "address")
assert.property(result.utxos[0].utxos[0], "height")
assert.property(result.utxos[0].utxos[0], "tx_hash")
assert.property(result.utxos[0].utxos[0], "fee")
})
it(`should throw error on array size rate limit`, async () => {
try {
const addr = []
for (let i = 0; i < 25; i++)
addr.push("bchtest:qrvn2n228aa39xupcw9jw0d3fj8axxky656e4j62z2")
const result = await bchjs.Electrumx.unconfirmed(addr)
//console.log(`result: ${util.inspect(result)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
assert.hasAnyKeys(err, ["error"])
assert.include(err.error, "Array too large")
}
})
})
})
+64
View File
@@ -196,4 +196,68 @@ describe(`#ElectrumX`, () => {
assert.property(result.transactions[0].transactions[0], "tx_hash")
})
})
describe(`#unconfirmed`, () => {
it(`should throw an error for improper input`, async () => {
try {
const addr = 12345
await bchjs.Electrumx.unconfirmed(addr)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
// console.log(`err: `, err)
assert.include(
err.message,
`Input address must be a string or array of strings`
)
}
})
it(`should GET unconfirmed utxos for a single address`, async () => {
// Stub the network call.
sandbox.stub(axios, "get").resolves({ data: mockData.unconfirmed })
const addr = "bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9"
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "height")
assert.property(result.utxos[0], "tx_hash")
assert.property(result.utxos[0], "fee")
})
it(`should POST unconfirmed utxo details for an array of addresses`, async () => {
// Stub the network call.
sandbox.stub(axios, "post").resolves({ data: mockData.unconfirmedArray })
const addr = [
"bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf",
"bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
]
const result = await bchjs.Electrumx.unconfirmed(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, "success")
assert.equal(result.success, true)
assert.property(result, "utxos")
assert.isArray(result.utxos)
assert.property(result.utxos[0], "utxos")
assert.isArray(result.utxos[0].utxos)
assert.property(result.utxos[0], "address")
assert.property(result.utxos[0].utxos[0], "height")
assert.property(result.utxos[0].utxos[0], "tx_hash")
assert.property(result.utxos[0].utxos[0], "fee")
})
})
})
+42 -1
View File
@@ -119,11 +119,52 @@ const transactions = {
]
}
const unconfirmed = {
success: true,
utxos: [
{
height: 602405,
tx_hash:
"2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7",
fee: 34100
}
]
}
const unconfirmedArray = {
success: true,
utxos: [
{
utxos: [
{
height: 604392,
tx_hash:
"7774e449c5a3065144cefbc4c0c21e6b69c987f095856778ef9f45ddd8ae1a41",
fee: 34210
},
{
height: 630834,
tx_hash:
"4fe60a51e0d8f5134bfd8e5f872d6e502d7f01b28a6afebb27f4438a4f638d53",
value: 3000
}
],
address: "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"
},
{
utxos: [],
address: "bitcoincash:qpdh9s677ya8tnx7zdhfrn8qfyvy22wj4qa7nwqa5v"
}
]
}
module.exports = {
utxo,
utxos,
balance,
balances,
transaction,
transactions
transactions,
unconfirmed,
unconfirmedArray
}