mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
feat(Utxo.get()): Moving old function to getOld. New get() uses psf-slp-indexer
This commit is contained in:
@@ -132,6 +132,7 @@ class PsfSlpIndexer {
|
|||||||
*/
|
*/
|
||||||
async balance (address) {
|
async balance (address) {
|
||||||
try {
|
try {
|
||||||
|
console.log('balance() address: ', address)
|
||||||
// Handle single address.
|
// Handle single address.
|
||||||
if (typeof address === 'string') {
|
if (typeof address === 'string') {
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
|
|||||||
+150
-6
@@ -8,19 +8,21 @@
|
|||||||
// Local libraries
|
// Local libraries
|
||||||
const Electrumx = require('./electrumx')
|
const Electrumx = require('./electrumx')
|
||||||
const Slp = require('./slp/slp')
|
const Slp = require('./slp/slp')
|
||||||
|
const PsfSlpIndexer = require('./psf-slp-indexer')
|
||||||
|
|
||||||
class UTXO {
|
class UTXO {
|
||||||
constructor (config) {
|
constructor (config = {}) {
|
||||||
// Encapsulate dependencies for easier mocking.
|
// Encapsulate dependencies for easier mocking.
|
||||||
this.electrumx = new Electrumx(config)
|
this.electrumx = new Electrumx(config)
|
||||||
this.slp = new Slp(config)
|
this.slp = new Slp(config)
|
||||||
|
this.psfSlpIndexer = new PsfSlpIndexer(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api Utxo.get() get()
|
* @api Utxo.getOld() getOld()
|
||||||
* @apiName get
|
* @apiName getOld
|
||||||
* @apiGroup UTXO
|
* @apiGroup UTXO
|
||||||
* @apiDescription Get UTXOs for an address
|
* @apiDescription Get UTXOs for an address (from SLPDB)
|
||||||
*
|
*
|
||||||
* Given an address, this function will return an object with thre following
|
* Given an address, this function will return an object with thre following
|
||||||
* properties:
|
* properties:
|
||||||
@@ -45,7 +47,7 @@ class UTXO {
|
|||||||
* @apiExample Example usage:
|
* @apiExample Example usage:
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* try {
|
* try {
|
||||||
* let utxos = await bchjs.Utxo.get('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
* let utxos = await bchjs.Utxo.getOld('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
||||||
* console.log(utxos);
|
* console.log(utxos);
|
||||||
* } catch(error) {
|
* } catch(error) {
|
||||||
* console.error(error)
|
* console.error(error)
|
||||||
@@ -181,7 +183,7 @@ class UTXO {
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async get (address, useWhitelist = false) {
|
async getOld (address, useWhitelist = false) {
|
||||||
try {
|
try {
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new Error('Address must be an array or a string')
|
throw new Error('Address must be an array or a string')
|
||||||
@@ -286,6 +288,148 @@ class UTXO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api Utxo.get() get()
|
||||||
|
* @apiName get
|
||||||
|
* @apiGroup UTXO
|
||||||
|
* @apiDescription Get UTXOs for an address (from psf-slp-indexer)
|
||||||
|
*
|
||||||
|
* Given an address, this function will return an object with thre following
|
||||||
|
* properties:
|
||||||
|
* - address: "" - the address these UTXOs are associated with
|
||||||
|
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
|
||||||
|
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
|
||||||
|
* not spent, to be safe.
|
||||||
|
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
|
||||||
|
* - type1: {}
|
||||||
|
* - tokens: [] - SLP token Type 1 tokens.
|
||||||
|
* - mintBatons: [] - SLP token Type 1 mint batons.
|
||||||
|
* - nft: {}
|
||||||
|
* - tokens: [] - NFT tokens
|
||||||
|
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
|
||||||
|
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
|
||||||
|
*
|
||||||
|
* Note: You can pass in an optional second Boolean argument. The default
|
||||||
|
* `false` will use the normal waterfall validation method. Set to `true`,
|
||||||
|
* SLP UTXOs will be validated with the whitelist filtered SLPDB. This will
|
||||||
|
* result is many more UTXOs in the `nullUtxos` array.
|
||||||
|
*
|
||||||
|
* @apiExample Example usage:
|
||||||
|
* (async () => {
|
||||||
|
* try {
|
||||||
|
* let utxos = await bchjs.Utxo.get('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
||||||
|
* console.log(utxos);
|
||||||
|
* } catch(error) {
|
||||||
|
* console.error(error)
|
||||||
|
* }
|
||||||
|
* })()
|
||||||
|
*
|
||||||
|
* // returns
|
||||||
|
* [
|
||||||
|
* {
|
||||||
|
* "address": "bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv",
|
||||||
|
* "bchUtxos": [
|
||||||
|
* {
|
||||||
|
* "height": 674513,
|
||||||
|
* "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
||||||
|
* "tx_pos": 3,
|
||||||
|
* "value": 38134,
|
||||||
|
* "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
||||||
|
* "vout": 3,
|
||||||
|
* "isValid": false
|
||||||
|
* }
|
||||||
|
* ],
|
||||||
|
*/
|
||||||
|
// This version of get() uses the psf-slp-indexer. It will replace the older
|
||||||
|
// get() function that uses SLPDB.
|
||||||
|
// TODO: NFT UTXOs are identified as non-token UTXOs, which will cause a wallet
|
||||||
|
// to burn them. The psf-slp-indexer needs to be updated to mark these UTXOs.
|
||||||
|
async get (address) {
|
||||||
|
try {
|
||||||
|
// Convert address to an array if it is a string.
|
||||||
|
if (typeof address !== 'string') {
|
||||||
|
throw new Error('address input must be a string')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the address is a BCH address.
|
||||||
|
const addr = this.slp.Address.toCashAddress(address)
|
||||||
|
|
||||||
|
// Get the UTXOs associated with the address.
|
||||||
|
const utxoData = await this.electrumx.utxo(addr)
|
||||||
|
// console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`)
|
||||||
|
const utxos = utxoData.utxos
|
||||||
|
|
||||||
|
// Get SLP UTXOs from the psf-slp-indexer
|
||||||
|
const slpUtxoData = await this.psfSlpIndexer.balance(addr)
|
||||||
|
// console.log(`slpUtxoData: ${JSON.stringify(slpUtxoData, null, 2)}`)
|
||||||
|
const slpUtxos = slpUtxoData.balance.utxos
|
||||||
|
|
||||||
|
// Loop through the Fulcrum UTXOs.
|
||||||
|
for (let i = 0; i < utxos.length; i++) {
|
||||||
|
const thisUtxo = utxos[i]
|
||||||
|
|
||||||
|
// Loop through the UTXOs from psf-slp-indexer.
|
||||||
|
for (let j = 0; j < slpUtxos.length; j++) {
|
||||||
|
const thisSlpUtxo = slpUtxos[j]
|
||||||
|
|
||||||
|
// If the non-hydrated UTXO matches the SLP UTXO, then combine the data
|
||||||
|
// and mark the UTXO as an SLP token.
|
||||||
|
if (
|
||||||
|
thisUtxo.tx_hash === thisSlpUtxo.txid &&
|
||||||
|
thisUtxo.tx_pos === thisSlpUtxo.vout
|
||||||
|
) {
|
||||||
|
thisUtxo.txid = thisUtxo.tx_hash
|
||||||
|
thisUtxo.vout = thisUtxo.tx_pos
|
||||||
|
thisUtxo.isSlp = true
|
||||||
|
thisUtxo.type = thisSlpUtxo.type
|
||||||
|
thisUtxo.qty = thisSlpUtxo.qty
|
||||||
|
thisUtxo.tokenId = thisSlpUtxo.tokenId
|
||||||
|
thisUtxo.address = thisSlpUtxo.address
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there was no match, then this is a normal BCH UTXO. Mark it as such.
|
||||||
|
if (!thisUtxo.isSlp) {
|
||||||
|
thisUtxo.txid = thisUtxo.tx_hash
|
||||||
|
thisUtxo.vout = thisUtxo.tx_pos
|
||||||
|
thisUtxo.isSlp = false
|
||||||
|
thisUtxo.address = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bchUtxos = utxos.filter(x => x.isSlp === false)
|
||||||
|
const type1TokenUtxos = utxos.filter(
|
||||||
|
x => x.isSlp === true && x.type === 'token'
|
||||||
|
)
|
||||||
|
const type1BatonUtxos = utxos.filter(
|
||||||
|
x => x.isSlp === true && x.type === 'baton'
|
||||||
|
)
|
||||||
|
const nullUtxos = utxos.filter(x => x.isSlp === null)
|
||||||
|
|
||||||
|
const outObj = {
|
||||||
|
address: addr,
|
||||||
|
bchUtxos,
|
||||||
|
slpUtxos: {
|
||||||
|
type1: {
|
||||||
|
tokens: type1TokenUtxos,
|
||||||
|
mintBatons: type1BatonUtxos
|
||||||
|
},
|
||||||
|
nft: {} // Allocated for future support of NFT spec.
|
||||||
|
},
|
||||||
|
nullUtxos
|
||||||
|
}
|
||||||
|
|
||||||
|
return outObj
|
||||||
|
} catch (err) {
|
||||||
|
// console.error('Error in bchjs.utxo.get2(): ', err)
|
||||||
|
|
||||||
|
if (err.error) throw new Error(err.error)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api Utxo.findBiggestUtxo() findBiggestUtxo()
|
* @api Utxo.findBiggestUtxo() findBiggestUtxo()
|
||||||
* @apiName findBiggestUtxo
|
* @apiName findBiggestUtxo
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe('#UTXO', () => {
|
|||||||
|
|
||||||
if (process.env.IS_USING_FREE_TIER) await sleep(3000)
|
if (process.env.IS_USING_FREE_TIER) await sleep(3000)
|
||||||
})
|
})
|
||||||
|
/*
|
||||||
describe('#get', () => {
|
describe('#get', () => {
|
||||||
it('should get hydrated and filtered UTXOs for an address', async () => {
|
it('should get hydrated and filtered UTXOs for an address', async () => {
|
||||||
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
||||||
@@ -90,7 +90,40 @@ describe('#UTXO', () => {
|
|||||||
assert.isAbove(result[0].nullUtxos.length, 1)
|
assert.isAbove(result[0].nullUtxos.length, 1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
describe('#get', () => {
|
||||||
|
it('should hydrate address with BCH and SLP UTXOs', async () => {
|
||||||
|
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
||||||
|
|
||||||
|
const result = await bchjs.Utxo.get(addr)
|
||||||
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
|
// Assert expected properties exist.
|
||||||
|
assert.property(result, 'address')
|
||||||
|
assert.property(result, 'bchUtxos')
|
||||||
|
assert.property(result, 'slpUtxos')
|
||||||
|
assert.property(result.slpUtxos, 'type1')
|
||||||
|
assert.property(result.slpUtxos, 'nft')
|
||||||
|
assert.property(result, 'nullUtxos')
|
||||||
|
|
||||||
|
assert.isAbove(result.bchUtxos.length, 0)
|
||||||
|
assert.isAbove(result.slpUtxos.type1.tokens.length, 0)
|
||||||
|
assert.equal(result.slpUtxos.type1.mintBatons.length, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: NFTs are currently not identified as different than normal BCH UTXOs.
|
||||||
|
// The psf-slp-indexer needs to be updated to fix this issue.
|
||||||
|
it('should handle NFTs and minting batons', async () => {
|
||||||
|
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
||||||
|
|
||||||
|
const result = await bchjs.Utxo.get(addr)
|
||||||
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
|
// Assert that minting batons are correctly identified.
|
||||||
|
assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
/*
|
||||||
describe('#findBiggestUtxo', () => {
|
describe('#findBiggestUtxo', () => {
|
||||||
it('should sort UTXOs from Electrumx', async () => {
|
it('should sort UTXOs from Electrumx', async () => {
|
||||||
const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
|
const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
|
||||||
@@ -118,6 +151,7 @@ describe('#UTXO', () => {
|
|||||||
assert.equal(result.satoshis, 800)
|
assert.equal(result.satoshis, 800)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
})
|
})
|
||||||
|
|
||||||
function sleep (ms) {
|
function sleep (ms) {
|
||||||
|
|||||||
@@ -280,10 +280,100 @@ const electrumxUtxos = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fulcrumUtxos01 = {
|
||||||
|
success: true,
|
||||||
|
utxos: [
|
||||||
|
{
|
||||||
|
height: 674512,
|
||||||
|
tx_hash:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
tx_pos: 1,
|
||||||
|
value: 546
|
||||||
|
},
|
||||||
|
{
|
||||||
|
height: 674512,
|
||||||
|
tx_hash:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
tx_pos: 2,
|
||||||
|
value: 546
|
||||||
|
},
|
||||||
|
{
|
||||||
|
height: 674512,
|
||||||
|
tx_hash:
|
||||||
|
'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b',
|
||||||
|
tx_pos: 1,
|
||||||
|
value: 546
|
||||||
|
},
|
||||||
|
{
|
||||||
|
height: 674513,
|
||||||
|
tx_hash:
|
||||||
|
'705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
|
||||||
|
tx_pos: 1,
|
||||||
|
value: 546
|
||||||
|
},
|
||||||
|
{
|
||||||
|
height: 674513,
|
||||||
|
tx_hash:
|
||||||
|
'705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
|
||||||
|
tx_pos: 2,
|
||||||
|
value: 546
|
||||||
|
},
|
||||||
|
{
|
||||||
|
height: 674513,
|
||||||
|
tx_hash:
|
||||||
|
'705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
|
||||||
|
tx_pos: 3,
|
||||||
|
value: 38134
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const psfSlpIndexerUtxos01 = {
|
||||||
|
balance: {
|
||||||
|
utxos: [
|
||||||
|
{
|
||||||
|
txid:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
vout: 1,
|
||||||
|
type: 'token',
|
||||||
|
qty: '10000000000',
|
||||||
|
tokenId:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
address: 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
txid:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
vout: 2,
|
||||||
|
type: 'baton',
|
||||||
|
tokenId:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
address: 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
txs: [
|
||||||
|
{
|
||||||
|
txid:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
height: 674512
|
||||||
|
}
|
||||||
|
],
|
||||||
|
balances: [
|
||||||
|
{
|
||||||
|
tokenId:
|
||||||
|
'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
|
||||||
|
qty: '10000000000'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mockUtxoData,
|
mockUtxoData,
|
||||||
mockHydratedUtxos,
|
mockHydratedUtxos,
|
||||||
mockTwoHydratedAddrs,
|
mockTwoHydratedAddrs,
|
||||||
mockEveryUtxoType,
|
mockEveryUtxoType,
|
||||||
electrumxUtxos
|
electrumxUtxos,
|
||||||
|
fulcrumUtxos01,
|
||||||
|
psfSlpIndexerUtxos01
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-7
@@ -15,7 +15,7 @@ describe('#utxo', () => {
|
|||||||
beforeEach(() => (sandbox = sinon.createSandbox()))
|
beforeEach(() => (sandbox = sinon.createSandbox()))
|
||||||
afterEach(() => sandbox.restore())
|
afterEach(() => sandbox.restore())
|
||||||
|
|
||||||
describe('#get', () => {
|
describe('#getOld', () => {
|
||||||
it('should get hydrated and filtered UTXOs for an address', async () => {
|
it('should get hydrated and filtered UTXOs for an address', async () => {
|
||||||
// Mock dependencies.
|
// Mock dependencies.
|
||||||
sandbox.stub(bchjs.Utxo.electrumx, 'utxo').resolves(mockData.mockUtxoData)
|
sandbox.stub(bchjs.Utxo.electrumx, 'utxo').resolves(mockData.mockUtxoData)
|
||||||
@@ -25,7 +25,7 @@ describe('#utxo', () => {
|
|||||||
|
|
||||||
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
||||||
|
|
||||||
const result = await bchjs.Utxo.get(addr)
|
const result = await bchjs.Utxo.getOld(addr)
|
||||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
assert.isArray(result)
|
assert.isArray(result)
|
||||||
@@ -46,7 +46,7 @@ describe('#utxo', () => {
|
|||||||
|
|
||||||
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
||||||
|
|
||||||
await bchjs.Utxo.get(addr)
|
await bchjs.Utxo.getOld(addr)
|
||||||
|
|
||||||
assert.fail('Unexpected code path')
|
assert.fail('Unexpected code path')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -66,7 +66,7 @@ describe('#utxo', () => {
|
|||||||
'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
||||||
]
|
]
|
||||||
|
|
||||||
const result = await bchjs.Utxo.get(addr)
|
const result = await bchjs.Utxo.getOld(addr)
|
||||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
assert.isArray(result)
|
assert.isArray(result)
|
||||||
@@ -88,7 +88,7 @@ describe('#utxo', () => {
|
|||||||
addrs.push(addr)
|
addrs.push(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
await bchjs.Utxo.get(addrs)
|
await bchjs.Utxo.getOld(addrs)
|
||||||
|
|
||||||
assert.fail('Unexpected code path')
|
assert.fail('Unexpected code path')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -105,7 +105,7 @@ describe('#utxo', () => {
|
|||||||
|
|
||||||
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
||||||
|
|
||||||
const result = await bchjs.Utxo.get(addr)
|
const result = await bchjs.Utxo.getOld(addr)
|
||||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
assert.isArray(result)
|
assert.isArray(result)
|
||||||
@@ -133,7 +133,7 @@ describe('#utxo', () => {
|
|||||||
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
||||||
const useWhitelist = true
|
const useWhitelist = true
|
||||||
|
|
||||||
const result = await bchjs.Utxo.get(addr, useWhitelist)
|
const result = await bchjs.Utxo.getOld(addr, useWhitelist)
|
||||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
assert.isArray(result)
|
assert.isArray(result)
|
||||||
@@ -188,4 +188,48 @@ describe('#utxo', () => {
|
|||||||
assert.equal(result.satoshis, 800)
|
assert.equal(result.satoshis, 800)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#get', () => {
|
||||||
|
it('should throw an error if input is not a string', async () => {
|
||||||
|
try {
|
||||||
|
const addr = 123
|
||||||
|
|
||||||
|
await bchjs.Utxo.get(addr)
|
||||||
|
|
||||||
|
assert.fail('Unexpected code path')
|
||||||
|
} catch (err) {
|
||||||
|
assert.include(err.message, 'address input must be a string')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return UTXO information', async () => {
|
||||||
|
// mock dependencies
|
||||||
|
sandbox
|
||||||
|
.stub(bchjs.Utxo.electrumx, 'utxo')
|
||||||
|
.resolves(mockData.fulcrumUtxos01)
|
||||||
|
sandbox
|
||||||
|
.stub(bchjs.Utxo.psfSlpIndexer, 'balance')
|
||||||
|
.resolves(mockData.psfSlpIndexerUtxos01)
|
||||||
|
|
||||||
|
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
||||||
|
|
||||||
|
const result = await bchjs.Utxo.get(addr)
|
||||||
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
|
||||||
|
// Assert expected properties exist
|
||||||
|
assert.property(result, 'address')
|
||||||
|
assert.property(result, 'bchUtxos')
|
||||||
|
assert.property(result, 'slpUtxos')
|
||||||
|
assert.property(result.slpUtxos, 'type1')
|
||||||
|
assert.property(result.slpUtxos.type1, 'tokens')
|
||||||
|
assert.property(result.slpUtxos.type1, 'mintBatons')
|
||||||
|
assert.property(result.slpUtxos, 'nft')
|
||||||
|
assert.property(result, 'nullUtxos')
|
||||||
|
|
||||||
|
assert.equal(result.bchUtxos.length, 4)
|
||||||
|
assert.equal(result.slpUtxos.type1.tokens.length, 1)
|
||||||
|
assert.equal(result.slpUtxos.type1.mintBatons.length, 1)
|
||||||
|
assert.equal(result.nullUtxos.length, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user