diff --git a/config/env/common.js b/config/env/common.js index 58f058c..448f1bf 100644 --- a/config/env/common.js +++ b/config/env/common.js @@ -47,8 +47,8 @@ export default { useFullStackCash: process.env.USE_FULLSTACKCASH ? true : false, consumerUrl: process.env.CONSUMER_URL ? process.env.CONSUMER_URL - // : 'https://free-bch.fullstack.cash', - : 'https://dev-consumer.psfoundation.info', + : 'https://free-bch.fullstack.cash', + // : 'https://dev-consumer.psfoundation.info', // : 'https://wa-usa-bch-consumer.fullstackcash.nl', // P2WDB URL that will accept API calls from the p2wdb npm library. diff --git a/src/adapters/localdb/models/offer.js b/src/adapters/localdb/models/offer.js index 823aae2..f36c7a7 100644 --- a/src/adapters/localdb/models/offer.js +++ b/src/adapters/localdb/models/offer.js @@ -47,6 +47,7 @@ const Offer = new mongoose.Schema({ tokenIconUrl: { type: String, default: null }, tokenCategories: { type: Array, default: [] }, tokenTags: { type: Array, default: [] }, + userDataStr: { type: String }, // Token user data lastUpdatedTokenData: { type: String, default: null } // ISO timestamp of the last time token data was updated. }) diff --git a/src/use-cases/offer/index.js b/src/use-cases/offer/index.js index c8a5e29..606a1bc 100644 --- a/src/use-cases/offer/index.js +++ b/src/use-cases/offer/index.js @@ -129,38 +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) { - offerEntity.tokenIconUrl = mutableData.tokenIcon - offerEntity.tokenCategories = mutableData.category - offerEntity.tokenTags = mutableData.tags - offerEntity.lastUpdatedTokenData = new Date().getTime() - } + 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) @@ -168,7 +187,7 @@ class OfferUseCases { return true } catch (err) { - console.error('Error in createOffer()', err.message) + 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 f9ad063..716f132 100644 --- a/test/unit/use-cases/offer.use-case.unit.js +++ b/test/unit/use-cases/offer.use-case.unit.js @@ -112,7 +112,7 @@ describe('#offer-use-case', () => { const tokenDataMock = mockData.nftTokenData01 const offerObj = mockData.offerMockData const mutableDataMock = mockData.mutableDataMock - console.log('mutableDataMock: ', mutableDataMock) + // Mock dependencies // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').resolves(false) sandbox.stub(uut, 'findOfferByTxid').throws(new Error('offer not found')) @@ -124,6 +124,57 @@ describe('#offer-use-case', () => { const result = await uut.createOffer(offerObj) assert.isTrue(result) }) + + it('should skip userData stringify error', 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).resolves(mutableDataMock) + + const result = await uut.createOffer(offerObj) + 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 @@ -801,27 +852,17 @@ describe('#offer-use-case', () => { assert.equal(result, 'N/A') }) - it('should return if utxo cant be validated', async () => { + it('should return if utxo can not be validated', async () => { // Mock dependencies const mock = Object.assign({}, mockData.offerMockData.data) sandbox.stub(uut.orderUseCase, 'findOrderByUtxo').resolves(mock) - sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').throws(new Error('test error')) + // sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').throws(new Error('test error')) + sandbox.stub(uut.retryQueue, 'addToQueue').throws(new Error('test error')) const result = await uut.acceptCounterOffer({ data: { /** .... */ } }) assert.equal(result, 'N/A') }) - it('should handle axios error', async () => { - // Mock dependencies - const mock = Object.assign({}, mockData.offerMockData.data) - const stubErr = new Error() - stubErr.isAxiosError = true - sandbox.stub(uut.orderUseCase, 'findOrderByUtxo').resolves(mock) - sandbox.stub(uut.adapters.wallet.bchWallet, 'utxoIsValid').throws(stubErr) - - const result = await uut.acceptCounterOffer({ data: { /** .... */ } }) - assert.equal(result, 'N/A') - }) it('should return if utxo is invalid', async () => { // Mock dependencies const mock = Object.assign({}, mockData.offerMockData.data)