From 6d7056808203f705265d6f289447f8e89b69db3f Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Wed, 19 Jan 2022 14:46:00 -0800 Subject: [PATCH] fix(Utxo.get()): Properly handling addresses with no SLP utxos --- src/utxo.js | 18 ++++++++++--- .../chains/bchn/utxo-integration.js | 10 ++++++++ test/unit/fixtures/utxo-mocks.js | 23 ++++++++++++++++- test/unit/utxo-unit.js | 25 +++++++++++++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/utxo.js b/src/utxo.js index 500cc29..8bc61f1 100644 --- a/src/utxo.js +++ b/src/utxo.js @@ -357,10 +357,22 @@ class UTXO { // console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`) const utxos = utxoData.utxos + let slpUtxos = [] + // 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 + try { + const slpUtxoData = await this.psfSlpIndexer.balance(addr) + // console.log(`slpUtxoData: ${JSON.stringify(slpUtxoData, null, 2)}`) + + slpUtxos = slpUtxoData.balance.utxos + } catch (err) { + // console.log('err: ', err) + + // Exit quietly if address has no SLP UTXOs. Otherwise, throw the error. + if (err.error && !err.error.includes('Key not found in database')) { + throw err + } + } // Loop through the Fulcrum UTXOs. for (let i = 0; i < utxos.length; i++) { diff --git a/test/integration/chains/bchn/utxo-integration.js b/test/integration/chains/bchn/utxo-integration.js index f1dc876..9089900 100644 --- a/test/integration/chains/bchn/utxo-integration.js +++ b/test/integration/chains/bchn/utxo-integration.js @@ -208,6 +208,16 @@ describe('#UTXO', () => { // Assert that minting batons are correctly identified. assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0) }) + + it('should return UTXOs for address with no SLP tokens', async () => { + const addr = 'bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7' + + const result = await bchjs.Utxo.get(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isAbove(result.bchUtxos.length, 0) + assert.equal(result.slpUtxos.type1.tokens.length, 0) + }) }) }) diff --git a/test/unit/fixtures/utxo-mocks.js b/test/unit/fixtures/utxo-mocks.js index 06a7488..6d8d3e6 100644 --- a/test/unit/fixtures/utxo-mocks.js +++ b/test/unit/fixtures/utxo-mocks.js @@ -328,6 +328,19 @@ const fulcrumUtxos01 = { ] } +const fulcrumUtxos02 = { + success: true, + utxos: [ + { + height: 674513, + tx_hash: + '705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04', + tx_pos: 3, + value: 38134 + } + ] +} + const psfSlpIndexerUtxos01 = { balance: { utxos: [ @@ -457,6 +470,12 @@ const genesisData03 = { } } +const noUtxoErr = { + success: false, + error: + 'Key not found in database [bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7]' +} + module.exports = { mockUtxoData, mockHydratedUtxos, @@ -464,9 +483,11 @@ module.exports = { mockEveryUtxoType, electrumxUtxos, fulcrumUtxos01, + fulcrumUtxos02, psfSlpIndexerUtxos01, tokenUtxos01, genesisData01, genesisData02, - genesisData03 + genesisData03, + noUtxoErr } diff --git a/test/unit/utxo-unit.js b/test/unit/utxo-unit.js index 7253283..52ef883 100644 --- a/test/unit/utxo-unit.js +++ b/test/unit/utxo-unit.js @@ -272,5 +272,30 @@ describe('#utxo', () => { assert.equal(result.slpUtxos.type1.mintBatons.length, 1) assert.equal(result.nullUtxos.length, 0) }) + + it('should handle an address with no SLP UTXOs', async () => { + // mock dependencies + sandbox + .stub(bchjs.Utxo.electrumx, 'utxo') + .resolves(mockData.fulcrumUtxos02) + + // Force psf-slp-indexer to return no UTXOs + sandbox + .stub(bchjs.Utxo.psfSlpIndexer, 'balance') + .rejects(mockData.noUtxoErr) + + // Mock function to return the same input. Good enough for this test. + sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(() => []) + + const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj' + + const result = await bchjs.Utxo.get(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.equal(result.bchUtxos.length, 1) + assert.equal(result.slpUtxos.type1.tokens.length, 0) + assert.equal(result.slpUtxos.type1.mintBatons.length, 0) + assert.equal(result.nullUtxos.length, 0) + }) }) })