From 45acc2b0b70e7c979f80d8cdb1c2c51bd53beb28 Mon Sep 17 00:00:00 2001 From: Stoyan Zhekov Date: Sun, 16 May 2021 14:22:33 +0900 Subject: [PATCH] Return parent NFT group token information --- package.json | 4 ++- src/slp/nft1.js | 52 ++++++++++++++++++++++++++++ test/integration/chains/bchn/slp.js | 16 ++++++++- test/unit/fixtures/slp/mock-utils.js | 21 +++++++++++ test/unit/slp-nft1.js | 48 +++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f8d2e07..8dc3119 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,14 @@ "description": "The FullStack.cash JavaScript library for Bitcoin Cash and SLP Tokens", "author": "Chris Troutner ", "contributors": [ - "Gabriel Cardona " + "Gabriel Cardona ", + "Stoyan Zhekov " ], "main": "src/bch-js", "scripts": { "test": "nyc mocha --trace-warnings --unhandled-rejections=strict --timeout 30000 test/unit/", "test:integration": "npm run test:integration:bchn", + "test:integration:nft": "export RESTURL=https://bchn.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 -g '#nft1' test/integration/chains/bchn/slp.js", "test:integration:abc": "export RESTURL=https://abc.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/abc/", "test:integration:bchn": "export RESTURL=https://bchn.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/", "test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/chains/testnet/", diff --git a/src/slp/nft1.js b/src/slp/nft1.js index 571b186..67e5c50 100644 --- a/src/slp/nft1.js +++ b/src/slp/nft1.js @@ -458,6 +458,58 @@ class Nft1 { else throw error } } + + /** + * @api SLP.Nft1.parentNFTGroup() parentNFTGroup() + * @apiName parentNFTGroup + * @apiGroup SLP Nft1 + * @apiDescription Return parent NFT Group information for a given NFT child token. + * It's assumed provided groupId parameter is for an NFT Child token (type=65) + * + * Returns a JSON with NFT group information. + * + * @apiExample Example usage: + * + * const tokenId = '45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9' + * const group = await bchjs.SLP.Nft1.parentNFTGroup(tokenId) + * + * group = { + * "nftGroup": { + * "decimals": 0, + * "timestamp": "2021-05-03 10:36:01", + * "timestamp_unix": 1620038161, + * "versionType": 129, + * "documentUri": "psfoundation.cash", + * "symbol": "PSF.TEST.GROUP", + * "name": "PSF Test NFT Group", + * "containsBaton": true, + * "id": "68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a", + * "documentHash": null, + * "initialTokenQty": 1000000, + * "blockCreated": 686117, + * "totalMinted": null, + * "totalBurned": null, + * "circulatingSupply": null + * } + * } + */ + async parentNFTGroup (tokenId) { + try { + if (typeof tokenId === 'string') { + const response = await axios.get( + `${this.restURL}slp/nftGroup/${tokenId}`, + _this.axiosOptions + ) + return response.data + } + + throw new Error('tokenId must be a string.') + } catch (error) { + // console.log('Error in parentNFTGroup()') + if (error.response && error.response.data) throw error.response.data + else throw error + } + } } module.exports = Nft1 diff --git a/test/integration/chains/bchn/slp.js b/test/integration/chains/bchn/slp.js index 884ce66..85aa848 100644 --- a/test/integration/chains/bchn/slp.js +++ b/test/integration/chains/bchn/slp.js @@ -266,7 +266,7 @@ describe('#SLP', () => { }) describe('#nft1', () => { describe('#listNFTGroupChildren', () => { - it.only('should return array of children GENESIS transactions IDs', async () => { + it('should return array of children GENESIS transactions IDs', async () => { const groupId = '68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a' const result = await bchjs.SLP.NFT1.listNFTGroupChildren(groupId) // console.log(`result: ${JSON.stringify(result, null, 2)}`) @@ -274,6 +274,20 @@ describe('#SLP', () => { assert.isArray(result.nftChildren) }) }) + describe('#parentNFTGroup', () => { + it('should return parent NFT group information', async () => { + const tokenId = '45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9' + const result = await bchjs.SLP.NFT1.parentNFTGroup(tokenId) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + assert.property(result, 'nftGroup') + assert.property(result.nftGroup, 'id') + assert.property(result.nftGroup, 'name') + assert.property(result.nftGroup, 'symbol') + assert.property(result.nftGroup, 'documentUri') + assert.property(result.nftGroup, 'versionType') + assert.property(result.nftGroup, 'initialTokenQty') + }) + }) }) }) diff --git a/test/unit/fixtures/slp/mock-utils.js b/test/unit/fixtures/slp/mock-utils.js index 881d8df..36e2c2d 100644 --- a/test/unit/fixtures/slp/mock-utils.js +++ b/test/unit/fixtures/slp/mock-utils.js @@ -126,6 +126,26 @@ const mockNftChildrenList = { ] } +const mockNftGroup = { + nftGroup: { + decimals: 0, + timestamp: '2021-05-03 10:36:01', + timestamp_unix: 1620038161, + versionType: 129, + documentUri: 'psfoundation.cash', + symbol: 'PSF.TEST.GROUP', + name: 'PSF Test NFT Group', + containsBaton: true, + id: '68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a', + documentHash: null, + initialTokenQty: 1000000, + blockCreated: 686117, + totalMinted: null, + totalBurned: null, + circulatingSupply: null + } +} + const balancesForAddress = [ { tokenId: 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', @@ -1396,6 +1416,7 @@ module.exports = { mockToken, mockTokens, mockNftChildrenList, + mockNftGroup, balancesForAddress, balancesForAddresses, mockRawTx, diff --git a/test/unit/slp-nft1.js b/test/unit/slp-nft1.js index 2d22557..763788f 100644 --- a/test/unit/slp-nft1.js +++ b/test/unit/slp-nft1.js @@ -296,4 +296,52 @@ describe('#SLP NFT1', () => { assert.isArray(result.nftChildren) }) }) + describe('#parentNFTGroup', () => { + it('should throw an error for improper input', async () => { + try { + const tokenId = 12345 + + await bchjs.SLP.NFT1.parentNFTGroup(tokenId) + assert.equal(true, false, 'Unexpected result!') + } catch (err) { + // console.log(`err: `, err) + assert.include( + err.message, + 'tokenId must be a string' + ) + } + }) + it('should handle API response error', async () => { + try { + const error = new Error() + error.response = { + error: 'NFT child does not exists' + } + sandbox.stub(axios, 'get').throws(error) + + const tokenId = 'non-exists' + await bchjs.SLP.NFT1.parentNFTGroup(tokenId) + } catch (err) { + assert.include( + err.response, + { error: 'NFT child does not exists' } + ) + } + }) + it('should return parent NFT group information', async () => { + sandbox.stub(axios, 'get').resolves({ data: mockData.mockNftGroup }) + + const tokenId = '45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9' + const result = await bchjs.SLP.NFT1.parentNFTGroup(tokenId) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, 'nftGroup') + assert.property(result.nftGroup, 'id') + assert.property(result.nftGroup, 'name') + assert.property(result.nftGroup, 'symbol') + assert.property(result.nftGroup, 'documentUri') + assert.property(result.nftGroup, 'versionType') + assert.property(result.nftGroup, 'initialTokenQty') + }) + }) })