From 2f74b741101637ae480d496398c210276f238ba5 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 21 Oct 2025 12:44:48 -0700 Subject: [PATCH] fix(createOffer()): Handling API errors when token data can not be retrieved --- src/use-cases/offer/index.js | 85 +++++++++++++--------- test/unit/use-cases/offer.use-case.unit.js | 33 +++++++++ 2 files changed, 82 insertions(+), 36 deletions(-) diff --git a/src/use-cases/offer/index.js b/src/use-cases/offer/index.js index d0229fe..606a1bc 100644 --- a/src/use-cases/offer/index.js +++ b/src/use-cases/offer/index.js @@ -129,44 +129,57 @@ class OfferUseCases { // Get data about the token. const tokenId = offerEntity.tokenId - // const tokenData = await this.adapters.wallet.bchWallet.getTokenData(tokenId) - const tokenData = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.getTokenData, tokenId) - // console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`) - - // Store the mutable and immutable data cids. - const mutableDataCid = tokenData.mutableData - const immutableDataCid = tokenData.immutableData - offerEntity.mutableDataCid = mutableDataCid - offerEntity.immutableDataCid = immutableDataCid - // Get the mutable data from the cid if it exists. - if (mutableDataCid && typeof mutableDataCid === 'string') { - const mutableData = await this.retryQueue.addToQueue(this.adapters.wallet.cid2json, mutableDataCid) - console.log('mutableData: ', mutableData) - if (mutableData) { - try { - offerEntity.tokenIconUrl = mutableData.tokenIcon - offerEntity.tokenCategories = mutableData.category - offerEntity.tokenTags = mutableData.tags - offerEntity.lastUpdatedTokenData = new Date().getTime() - - offerEntity.userDataStr = JSON.stringify(mutableData.userData) - } catch (error) { - // skip error - } - } + let tokenData = null + try { + tokenData = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.getTokenData, tokenId) + } catch (err) { + console.error('Error in OfferUseCases/createOffer() getting token data: ', err.message) } - console.log('offerEntity: ', offerEntity) - // Generate a 'display category' for the token. This will allow the - // front end UI to figure out how to display the token. - const displayCategory = this.categorizeToken(offerEntity, tokenData) - console.log('displayCategory: ', displayCategory) - offerEntity.displayCategory = displayCategory + // Do additional data analysis if the token data was successfully retrieved. + if (tokenData) { + // Store the mutable and immutable data cids. + const mutableDataCid = tokenData.mutableData + const immutableDataCid = tokenData.immutableData + offerEntity.mutableDataCid = mutableDataCid + offerEntity.immutableDataCid = immutableDataCid - // Detect if user set the NSFW flag. - // const nsfw = false - // nsfw = await this.retryQueue.addToQueue(this.detectNsfw, tokenData) - // offerEntity.nsfw = nsfw + // Get the mutable data from the cid if it exists. + if (mutableDataCid && typeof mutableDataCid === 'string') { + let mutableData = null + try { + mutableData = await this.retryQueue.addToQueue(this.adapters.wallet.cid2json, mutableDataCid) + } catch (err) { + console.error('Error in OfferUseCases/createOffer() getting mutable data: ', err.message) + } + console.log('mutableData: ', mutableData) + + if (mutableData) { + try { + offerEntity.tokenIconUrl = mutableData.tokenIcon + offerEntity.tokenCategories = mutableData.category + offerEntity.tokenTags = mutableData.tags + offerEntity.lastUpdatedTokenData = new Date().getTime() + + offerEntity.userDataStr = JSON.stringify(mutableData.userData) + } catch (error) { + // skip error + } + } + } + console.log('offerEntity: ', offerEntity) + + // Generate a 'display category' for the token. This will allow the + // front end UI to figure out how to display the token. + const displayCategory = this.categorizeToken(offerEntity, tokenData) + console.log('displayCategory: ', displayCategory) + offerEntity.displayCategory = displayCategory + + // Detect if user set the NSFW flag. + // const nsfw = false + // nsfw = await this.retryQueue.addToQueue(this.detectNsfw, tokenData) + // offerEntity.nsfw = nsfw + } // Add offer to the local database. const offerModel = new this.OfferModel(offerEntity) @@ -174,7 +187,7 @@ class OfferUseCases { return true } catch (err) { - console.error('\n\nError in createOffer()', err.message, '\n\n') + console.error('\n\nError in createOffer()', err.message, '\n\n', err) throw err } } diff --git a/test/unit/use-cases/offer.use-case.unit.js b/test/unit/use-cases/offer.use-case.unit.js index 436bb97..716f132 100644 --- a/test/unit/use-cases/offer.use-case.unit.js +++ b/test/unit/use-cases/offer.use-case.unit.js @@ -142,6 +142,39 @@ describe('#offer-use-case', () => { assert.isTrue(result) }) + it('should handle error getting token data', async () => { + // const tokenDataMock = mockData.nftTokenData01 + const offerObj = mockData.offerMockData + const mutableDataMock = mockData.mutableDataMock + mutableDataMock.userData = { n: 10n } + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) + sandbox.stub(uut, 'findOfferByTxid').throws(new Error('offer not found')) + sandbox.stub(uut.retryQueue, 'addToQueue') + .onCall(0).resolves({}) // Utxo Status call + .onCall(1).throws(new Error('test error')) + + const result = await uut.createOffer(offerObj) + assert.isTrue(result) + }) + + it('should handle error getting mutable data', async () => { + const tokenDataMock = mockData.nftTokenData01 + const offerObj = mockData.offerMockData + const mutableDataMock = mockData.mutableDataMock + mutableDataMock.userData = { n: 10n } + // Mock dependencies + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) + sandbox.stub(uut, 'findOfferByTxid').throws(new Error('offer not found')) + sandbox.stub(uut.retryQueue, 'addToQueue') + .onCall(0).resolves({}) // Utxo Status call + .onCall(1).resolves(tokenDataMock) // Token Data call + .onCall(2).throws(new Error('test error')) // cid2json call + + const result = await uut.createOffer(offerObj) + assert.isTrue(result) + }) + it('should create offer', async () => { const tokenDataMock = mockData.simpleNftTokenData01 const offerObj = mockData.offerMockData