diff --git a/src/slp/nft1.js b/src/slp/nft1.js index 1f52f9f..a41f1c6 100644 --- a/src/slp/nft1.js +++ b/src/slp/nft1.js @@ -147,7 +147,7 @@ class Nft1 { // Loop through the tokenUtxos array and find the minting baton. let mintBatonUtxo for (let i = 0; i < tokenUtxos.length; i++) { - if (tokenUtxos[i].utxoType === 'minting-baton') { + if (tokenUtxos[i].utxoType === 'minting-baton' || tokenUtxos[i].type === 'baton') { mintBatonUtxo = tokenUtxos[i] } } diff --git a/src/utxo.js b/src/utxo.js index f873407..a92acdb 100644 --- a/src/utxo.js +++ b/src/utxo.js @@ -125,6 +125,7 @@ class UTXO { thisUtxo.qty = thisSlpUtxo.qty thisUtxo.tokenId = thisSlpUtxo.tokenId thisUtxo.address = thisSlpUtxo.address + thisUtxo.tokenType = thisSlpUtxo.tokenType break } @@ -151,19 +152,37 @@ class UTXO { // Get token UTXOs let type1TokenUtxos = utxos.filter( - x => x.isSlp === true && x.type === 'token' + x => x.isSlp === true && x.type === 'token' && x.tokenType === 1 ) // Hydrate the UTXOs with additional token data. type1TokenUtxos = await this.hydrateTokenData(type1TokenUtxos) - // Collect and hydrate any baton UTXOs + // Collect and hydrate any type1 baton UTXOs const bchUtxos = utxos.filter(x => x.isSlp === false) let type1BatonUtxos = utxos.filter( - x => x.isSlp === true && x.type === 'baton' + x => x.isSlp === true && x.type === 'baton' && x.tokenType === 1 ) type1BatonUtxos = await this.hydrateTokenData(type1BatonUtxos) + // Collect and hydrate NFT Group tokens + let nftGroupTokenUtxos = utxos.filter( + x => x.isSlp === true && x.type === 'token' && x.tokenType === 129 + ) + nftGroupTokenUtxos = await this.hydrateTokenData(nftGroupTokenUtxos) + + // Collect and hydrate any Group baton UTXOs + let groupBatonUtxos = utxos.filter( + x => x.isSlp === true && x.type === 'baton' && x.tokenType === 129 + ) + groupBatonUtxos = await this.hydrateTokenData(groupBatonUtxos) + + // Collect and hydrate NFT child tokens + let nftChildTokenUtxos = utxos.filter( + x => x.isSlp === true && x.type === 'token' && x.tokenType === 65 + ) + nftChildTokenUtxos = await this.hydrateTokenData(nftChildTokenUtxos) + // Isolate any UTXOs that are marked null by the SLP indexer. const nullUtxos = utxos.filter(x => x.isSlp === null) @@ -175,7 +194,13 @@ class UTXO { tokens: type1TokenUtxos, mintBatons: type1BatonUtxos }, - nft: {} // Allocated for future support of NFT spec. + group: { + tokens: nftGroupTokenUtxos, + mintBatons: groupBatonUtxos + }, + nft: { + tokens: nftChildTokenUtxos + } }, nullUtxos } @@ -229,14 +254,16 @@ class UTXO { thisUtxo.documentHash = genData[0].tokenData.documentHash thisUtxo.decimals = genData[0].tokenData.decimals - // Calculate the real token quantity - const qty = new BigNumber(thisUtxo.qty).dividedBy( - 10 ** parseInt(thisUtxo.decimals) - ) - thisUtxo.qtyStr = qty.toString() + if (thisUtxo.type !== 'baton') { + // Calculate the real token quantity + const qty = new BigNumber(thisUtxo.qty).dividedBy( + 10 ** parseInt(thisUtxo.decimals) + ) + thisUtxo.qtyStr = qty.toString() - // tokenQty is property expected by SLP.tokentype1.js library - thisUtxo.tokenQty = thisUtxo.qtyStr + // tokenQty is property expected by SLP.tokentype1.js library + thisUtxo.tokenQty = thisUtxo.qtyStr + } } return utxoAry diff --git a/test/integration/chains/bchn/utxo-integration.js b/test/integration/chains/bchn/utxo-integration.js index 883619d..9bca943 100644 --- a/test/integration/chains/bchn/utxo-integration.js +++ b/test/integration/chains/bchn/utxo-integration.js @@ -83,10 +83,8 @@ describe('#UTXO', () => { 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 minting batons', async () => { - const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj' + it('should handle Type1 minting batons', async () => { + const addr = 'simpleledger:qz5l5yzz9r09hw9aadcz53elp2knx6gyg5qk3s8md7' const result = await bchjs.Utxo.get(addr) // console.log(`result: ${JSON.stringify(result, null, 2)}`) @@ -105,13 +103,23 @@ describe('#UTXO', () => { assert.equal(result.slpUtxos.type1.tokens.length, 0) }) - it('should handle Group NFTs', async () => { - const addr = 'bitcoincash:qrnghwrfgccf3s5e9wnglzxegcnhje9rkcwv2eka33' + it('should filter Group tokens and mint batons', async () => { + const addr = 'bitcoincash:qzeqcrpe5fcnslv8rfqjq4gh4gzdwytmdc4qmh0ztv' const result = await bchjs.Utxo.get(addr) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.equal(result.nullUtxos.length, 0) + assert.isAbove(result.slpUtxos.group.tokens.length, 0) + assert.isAbove(result.slpUtxos.group.mintBatons.length, 0) + }) + + it('should filter NFTs', async () => { + const addr = 'simpleledger:qq7vp2kvejsql898a2760kuq6xz00h0a5vuwu9lywu' + + const result = await bchjs.Utxo.get(addr) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isAbove(result.slpUtxos.nft.tokens.length, 0) }) }) })