diff --git a/package.json b/package.json index 11f5d39..f4c04d6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "test:integration:nft": "export RESTURL=https://bchn.fullstack.cash/v5/ && 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/v5/ && 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/v5/ && 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/", + "test:integration:bchn:slpdb": "export TESTSLP=1 && export RESTURL=https://bchn.fullstack.cash/v5/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/", "test:integration:local:abc": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/", "test:integration:local:bchn": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/", "test:integration:local:testnet": "RESTURL=http://localhost:4000/v5/ mocha --timeout 30000 test/integration/chains/testnet", diff --git a/test/integration/chains/bchn/slp.js b/test/integration/chains/bchn/slp.js index 85aa848..a0fd795 100644 --- a/test/integration/chains/bchn/slp.js +++ b/test/integration/chains/bchn/slp.js @@ -30,265 +30,269 @@ describe('#SLP', () => { bchjs = new BCHJS() }) - describe('#util', () => { - describe('#decodeOpReturn', () => { - it('should decode a NFT Child transaction', async () => { - const txid = - 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b' + if (process.env.TESTSLP) { + describe('#util', () => { + describe('#decodeOpReturn', () => { + it('should decode a NFT Child transaction', async () => { + const txid = + 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b' - const data = await bchjs.SLP.Utils.decodeOpReturn(txid) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + const data = await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) - assert.property(data, 'tokenType') - assert.property(data, 'txType') - assert.property(data, 'ticker') - assert.property(data, 'name') - assert.property(data, 'tokenId') - assert.property(data, 'documentUri') - assert.property(data, 'documentHash') - assert.property(data, 'decimals') - assert.property(data, 'mintBatonVout') - assert.property(data, 'qty') + assert.property(data, 'tokenType') + assert.property(data, 'txType') + assert.property(data, 'ticker') + assert.property(data, 'name') + assert.property(data, 'tokenId') + assert.property(data, 'documentUri') + assert.property(data, 'documentHash') + assert.property(data, 'decimals') + assert.property(data, 'mintBatonVout') + assert.property(data, 'qty') - assert.equal(data.tokenType, 65) - assert.equal(data.mintBatonVout, 0) - assert.equal(data.qty, '1') + assert.equal(data.tokenType, 65) + assert.equal(data.mintBatonVout, 0) + assert.equal(data.qty, '1') + }) }) - }) - describe('#tokenUtxoDetails', () => { - it('should handle a range of UTXO types', async () => { - const utxos = [ + describe('#tokenUtxoDetails', () => { + it('should handle a range of UTXO types', async () => { + const utxos = [ + // Malformed SLP tx + { + note: 'Malformed SLP tx', + tx_hash: + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', + tx_pos: 1, + value: 546 + }, + // Normal TX (non-SLP) + { + note: 'Normal TX (non-SLP)', + tx_hash: + '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', + tx_pos: 0, + value: 400000 + }, + // Valid PSF SLP tx + { + note: 'Valid PSF SLP tx', + tx_hash: + 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', + tx_pos: 1, + value: 546 + }, + // Valid SLP token not in whitelist + { + note: 'Valid SLP token not in whitelist', + tx_hash: + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', + tx_pos: 1, + value: 546 + }, + // Token send on BCHN network. + { + note: 'Token send on BCHN network', + tx_hash: + '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019', + tx_pos: 1, + value: 546 + }, + // Token send on ABC network. + { + note: 'Token send on ABC network', + tx_hash: + '336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d', + tx_pos: 1, + value: 546 + }, + // Known invalid SLP token send of PSF tokens. + { + note: 'Known invalid SLP token send of PSF tokens', + tx_hash: + '2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74', + tx_pos: 1, + value: 546 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + // Malformed SLP tx - { - note: 'Malformed SLP tx', - tx_hash: - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', - tx_pos: 1, - value: 546 - }, + assert.equal(data[0].tx_hash, utxos[0].tx_hash) + assert.equal(data[0].isValid, false) + // Normal TX (non-SLP) - { - note: 'Normal TX (non-SLP)', - tx_hash: - '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', - tx_pos: 0, - value: 400000 - }, + assert.equal(data[1].tx_hash, utxos[1].tx_hash) + assert.equal(data[1].isValid, false) + // Valid PSF SLP tx - { - note: 'Valid PSF SLP tx', - tx_hash: - 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', - tx_pos: 1, - value: 546 - }, + assert.equal(data[2].tx_hash, utxos[2].tx_hash) + assert.equal(data[2].isValid, true) + // Valid SLP token not in whitelist - { - note: 'Valid SLP token not in whitelist', - tx_hash: - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', - tx_pos: 1, - value: 546 - }, - // Token send on BCHN network. - { - note: 'Token send on BCHN network', - tx_hash: - '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019', - tx_pos: 1, - value: 546 - }, - // Token send on ABC network. - { - note: 'Token send on ABC network', - tx_hash: - '336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d', - tx_pos: 1, - value: 546 - }, - // Known invalid SLP token send of PSF tokens. - { - note: 'Known invalid SLP token send of PSF tokens', - tx_hash: - '2bf691ad3679d928fef880b8a45b93b233f8fa0d0a92cf792313dbe77b1deb74', - tx_pos: 1, - value: 546 - } - ] + assert.equal(data[3].tx_hash, utxos[3].tx_hash) + assert.equal(data[3].isValid, true) - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + // Token send on BCHN network + assert.equal(data[4].tx_hash, utxos[4].tx_hash) + assert.equal(data[4].isValid, true) - // Malformed SLP tx - assert.equal(data[0].tx_hash, utxos[0].tx_hash) - assert.equal(data[0].isValid, false) + // Token send on ABC network + assert.equal(data[5].tx_hash, utxos[5].tx_hash) + assert.equal(data[5].isValid, null) - // Normal TX (non-SLP) - assert.equal(data[1].tx_hash, utxos[1].tx_hash) - assert.equal(data[1].isValid, false) + // Known invalid SLP token send of PSF tokens + assert.equal(data[6].tx_hash, utxos[6].tx_hash) + assert.equal(data[6].isValid, false) + }) + }) - // Valid PSF SLP tx - assert.equal(data[2].tx_hash, utxos[2].tx_hash) - assert.equal(data[2].isValid, true) + describe('#validateTxid3', () => { + it('should invalidate a known invalid TXID', async () => { + const txid = + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' - // Valid SLP token not in whitelist - assert.equal(data[3].tx_hash, utxos[3].tx_hash) - assert.equal(data[3].isValid, true) + const result = await bchjs.SLP.Utils.validateTxid3(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // Token send on BCHN network - assert.equal(data[4].tx_hash, utxos[4].tx_hash) - assert.equal(data[4].isValid, true) + assert.isArray(result) - // Token send on ABC network - assert.equal(data[5].tx_hash, utxos[5].tx_hash) - assert.equal(data[5].isValid, null) + assert.property(result[0], 'txid') + assert.equal(result[0].txid, txid) - // Known invalid SLP token send of PSF tokens - assert.equal(data[6].tx_hash, utxos[6].tx_hash) - assert.equal(data[6].isValid, false) + assert.property(result[0], 'valid') + assert.equal(result[0].valid, null) + }) + + it('should validate a known valid TXID', async () => { + const txid = + 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd' + + const result = await bchjs.SLP.Utils.validateTxid3(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + + assert.property(result[0], 'txid') + assert.equal(result[0].txid, txid) + + assert.property(result[0], 'valid') + assert.equal(result[0].valid, true) + }) + + it('should handle a mix of valid, invalid, and non-SLP txs', async () => { + const txids = [ + // Malformed SLP tx + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', + // Normal TX (non-SLP) + '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', + // Valid PSF SLP tx + 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', + // Valid SLP token not in whitelist + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', + // Unprocessed SLP TX + '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019' + ] + + const result = await bchjs.SLP.Utils.validateTxid3(txids) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + + assert.equal(result[0].txid, txids[0]) + assert.equal(result[0].valid, null) + + assert.equal(result[1].txid, txids[1]) + assert.equal(result[1].valid, null) + + assert.equal(result[2].txid, txids[2]) + assert.equal(result[2].valid, true) + + // True in validateTxid() but null in validateTxid3() + assert.equal(result[3].txid, txids[3]) + assert.equal(result[3].valid, null) + + // Note: This should change from null to true once SLPDB finishes indexing. + assert.equal(result[4].txid, txids[4]) + assert.equal(result[4].valid, null) + }) + }) + + describe('#validateTxid', () => { + it('should handle a mix of valid, invalid, and non-SLP txs', async () => { + const txids = [ + // Malformed SLP tx + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', + // Normal TX (non-SLP) + '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', + // Valid PSF SLP tx + 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', + // Valid SLP token not in whitelist + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', + // Token send on BCHN network. + '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019', + // Token send on ABC network. + '336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d' + ] + + const result = await bchjs.SLP.Utils.validateTxid(txids) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + + assert.equal(result[0].txid, txids[0]) + assert.equal(result[0].valid, null) + + assert.equal(result[1].txid, txids[1]) + assert.equal(result[1].valid, null) + + assert.equal(result[2].txid, txids[2]) + assert.equal(result[2].valid, true) + + // True in validateTxid() but null in validateTxid3() + assert.equal(result[3].txid, txids[3]) + assert.equal(result[3].valid, true) + + assert.equal(result[4].txid, txids[4]) + assert.equal(result[4].valid, true) + + assert.equal(result[5].txid, txids[5]) + assert.equal(result[5].valid, null) + }) }) }) - - describe('#validateTxid3', () => { - it('should invalidate a known invalid TXID', async () => { - const txid = - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' - - const result = await bchjs.SLP.Utils.validateTxid3(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - - assert.property(result[0], 'txid') - assert.equal(result[0].txid, txid) - - assert.property(result[0], 'valid') - assert.equal(result[0].valid, null) + describe('#nft1', () => { + describe('#listNFTGroupChildren', () => { + 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)}`) + assert.property(result, 'nftChildren') + assert.isArray(result.nftChildren) + }) }) - - it('should validate a known valid TXID', async () => { - const txid = - 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd' - - const result = await bchjs.SLP.Utils.validateTxid3(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - - assert.property(result[0], 'txid') - assert.equal(result[0].txid, txid) - - assert.property(result[0], 'valid') - assert.equal(result[0].valid, true) - }) - - it('should handle a mix of valid, invalid, and non-SLP txs', async () => { - const txids = [ - // Malformed SLP tx - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', - // Normal TX (non-SLP) - '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', - // Valid PSF SLP tx - 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', - // Valid SLP token not in whitelist - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', - // Unprocessed SLP TX - '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019' - ] - - const result = await bchjs.SLP.Utils.validateTxid3(txids) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - - assert.equal(result[0].txid, txids[0]) - assert.equal(result[0].valid, null) - - assert.equal(result[1].txid, txids[1]) - assert.equal(result[1].valid, null) - - assert.equal(result[2].txid, txids[2]) - assert.equal(result[2].valid, true) - - // True in validateTxid() but null in validateTxid3() - assert.equal(result[3].txid, txids[3]) - assert.equal(result[3].valid, null) - - // Note: This should change from null to true once SLPDB finishes indexing. - assert.equal(result[4].txid, txids[4]) - assert.equal(result[4].valid, null) + 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') + }) }) }) - - describe('#validateTxid', () => { - it('should handle a mix of valid, invalid, and non-SLP txs', async () => { - const txids = [ - // Malformed SLP tx - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', - // Normal TX (non-SLP) - '01cdaec2f8b311fc2d6ecc930247bd45fa696dc204ab684596e281fe1b06c1f0', - // Valid PSF SLP tx - 'daf4d8b8045e7a90b7af81bfe2370178f687da0e545511bce1c9ae539eba5ffd', - // Valid SLP token not in whitelist - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', - // Token send on BCHN network. - '402c663379d9699b6e2dd38737061e5888c5a49fca77c97ab98e79e08959e019', - // Token send on ABC network. - '336bfe2168aac4c3303508a9e8548a0d33797a83b85b76a12d845c8d6674f79d' - ] - - const result = await bchjs.SLP.Utils.validateTxid(txids) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - - assert.equal(result[0].txid, txids[0]) - assert.equal(result[0].valid, null) - - assert.equal(result[1].txid, txids[1]) - assert.equal(result[1].valid, null) - - assert.equal(result[2].txid, txids[2]) - assert.equal(result[2].valid, true) - - // True in validateTxid() but null in validateTxid3() - assert.equal(result[3].txid, txids[3]) - assert.equal(result[3].valid, true) - - assert.equal(result[4].txid, txids[4]) - assert.equal(result[4].valid, true) - - assert.equal(result[5].txid, txids[5]) - assert.equal(result[5].valid, null) - }) - }) - }) - describe('#nft1', () => { - describe('#listNFTGroupChildren', () => { - 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)}`) - assert.property(result, 'nftChildren') - 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') - }) - }) - }) + } }) // Promise-based sleep function diff --git a/test/integration/slp.js b/test/integration/slp.js index daacfeb..e44d919 100644 --- a/test/integration/slp.js +++ b/test/integration/slp.js @@ -30,965 +30,971 @@ describe('#SLP', () => { }) describe('#util', () => { - describe('#list', () => { - it('should get information on the Spice token', async () => { - const tokenId = - '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf' + if (process.env.TESTSLP) { + describe('#list', () => { + it('should get information on the Spice token', async () => { + const tokenId = + '4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf' - const result = await bchjs.SLP.Utils.list(tokenId) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAnyKeys(result, [ - 'decimals', - 'timestamp', - 'timestamp_unix', - 'versionType', - 'documentUri', - 'symbol', - 'name', - 'containsBaton', - 'id', - 'documentHash', - 'initialTokenQty', - 'blockCreated', - 'blockLastActiveSend', - 'blockLastActiveMint', - 'txnsSinceGenesis', - 'validAddress', - 'totalMinted', - 'totalBurned', - 'circulatingSupply', - 'mintingBatonStatus' - ]) - }) - }) - - // describe("#decodeOpReturn", () => { - // it("should decode the OP_RETURN for a SEND txid", async () => { - // const txid = - // "266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1" - // - // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // - // assert.hasAllKeys(result, [ - // "tokenType", - // "transactionType", - // "tokenId", - // "spendData" - // ]) - // }) - // - // it("should decode the OP_RETURN for a GENESIS txid", async () => { - // const txid = - // "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7" - // - // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // - // assert.hasAllKeys(result, [ - // "tokenType", - // "transactionType", - // "ticker", - // "name", - // "documentUrl", - // "documentHash", - // "decimals", - // "mintBatonVout", - // "initialQty", - // "tokensSentTo", - // "batonHolder" - // ]) - // }) - // - // it("should decode the OP_RETURN for a MINT txid", async () => { - // const txid = - // "65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4" - // - // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // - // assert.hasAllKeys(result, [ - // "tokenType", - // "transactionType", - // "tokenId", - // "mintBatonVout", - // "batonStillExists", - // "quantity", - // "tokensSentTo", - // "batonHolder" - // ]) - // }) - // - // it("should throw an error for a non-SLP transaction", async () => { - // try { - // const txid = - // "3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec" - // - // await bchjs.SLP.Utils.decodeOpReturn(txid) - // - // assert.equal(true, false, "Unexpected result") - // } catch (err) { - // // console.log(`err: `, err) - // assert.include(err.message, "Not an OP_RETURN") - // } - // }) - // }) - - describe('#decodeOpReturn', () => { - it('should decode the OP_RETURN for a SEND txid', async () => { - const txid = - '266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1' - - const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAllKeys(result, ['tokenType', 'txType', 'tokenId', 'amounts']) - assert.equal( - result.tokenId, - '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' - ) - - // Verify outputs - assert.equal(result.amounts.length, 2) - assert.equal(result.amounts[0], '100000000') - assert.equal(result.amounts[1], '99883300000000') - }) - - it('should decode the OP_RETURN for a GENESIS txid', async () => { - const txid = - '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' - - const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAllKeys(result, [ - 'tokenType', - 'txType', - 'tokenId', - 'ticker', - 'name', - 'documentUri', - 'documentHash', - 'decimals', - 'mintBatonVout', - 'qty' - ]) - assert.equal( - result.tokenId, - '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' - ) - assert.equal(result.txType, 'GENESIS') - assert.equal(result.ticker, 'TOK-CH') - assert.equal(result.name, 'TokyoCash') - }) - - it('should decode the OP_RETURN for a MINT txid', async () => { - const txid = - '65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4' - - const result = await bchjs.SLP.Utils.decodeOpReturn(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.hasAllKeys(result, [ - 'tokenType', - 'txType', - 'tokenId', - 'mintBatonVout', - 'qty' - ]) - }) - - it('should throw an error for a non-SLP transaction', async () => { - try { - const txid = - '3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec' - - await bchjs.SLP.Utils.decodeOpReturn(txid) - - assert.equal(true, false, 'Unexpected result') - } catch (err) { - // console.log(`err: `, err) - assert.include(err.message, 'scriptpubkey not op_return') - } - }) - - // Note: This TX is interpreted as valid by the original decodeOpReturn(). - // Fixing this issue and related issues was the reason for creating the - // decodeOpReturn2() method using the slp-parser library. - it('should throw error for invalid SLP transaction', async () => { - try { - const txid = - 'a60a522cc11ad7011b74e57fbabbd99296e4b9346bcb175dcf84efb737030415' - - await bchjs.SLP.Utils.decodeOpReturn(txid) + const result = await bchjs.SLP.Utils.list(tokenId) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - } catch (err) { - // console.log(`err: `, err) - assert.include(err.message, 'amount string size not 8 bytes') - } - }) - }) - describe('#tokenUtxoDetails', () => { - // // This captures an important corner-case. When an SLP token is created, the - // // change UTXO will contain the same SLP txid, but it is not an SLP UTXO. - it('should return details on minting baton from genesis transaction', async () => { - const utxos = [ - { - txid: - 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90', - vout: 3, - amount: 0.00002015, - satoshis: 2015, - height: 594892, - confirmations: 5 - }, - { - txid: - 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90', - vout: 2, - amount: 0.00000546, - satoshis: 546, - height: 594892, - confirmations: 5 + assert.hasAnyKeys(result, [ + 'decimals', + 'timestamp', + 'timestamp_unix', + 'versionType', + 'documentUri', + 'symbol', + 'name', + 'containsBaton', + 'id', + 'documentHash', + 'initialTokenQty', + 'blockCreated', + 'blockLastActiveSend', + 'blockLastActiveMint', + 'txnsSinceGenesis', + 'validAddress', + 'totalMinted', + 'totalBurned', + 'circulatingSupply', + 'mintingBatonStatus' + ]) + }) + }) + + // describe("#decodeOpReturn", () => { + // it("should decode the OP_RETURN for a SEND txid", async () => { + // const txid = + // "266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1" + // + // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // // console.log(`result: ${JSON.stringify(result, null, 2)}`) + // + // assert.hasAllKeys(result, [ + // "tokenType", + // "transactionType", + // "tokenId", + // "spendData" + // ]) + // }) + // + // it("should decode the OP_RETURN for a GENESIS txid", async () => { + // const txid = + // "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7" + // + // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // // console.log(`result: ${JSON.stringify(result, null, 2)}`) + // + // assert.hasAllKeys(result, [ + // "tokenType", + // "transactionType", + // "ticker", + // "name", + // "documentUrl", + // "documentHash", + // "decimals", + // "mintBatonVout", + // "initialQty", + // "tokensSentTo", + // "batonHolder" + // ]) + // }) + // + // it("should decode the OP_RETURN for a MINT txid", async () => { + // const txid = + // "65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4" + // + // const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // // console.log(`result: ${JSON.stringify(result, null, 2)}`) + // + // assert.hasAllKeys(result, [ + // "tokenType", + // "transactionType", + // "tokenId", + // "mintBatonVout", + // "batonStillExists", + // "quantity", + // "tokensSentTo", + // "batonHolder" + // ]) + // }) + // + // it("should throw an error for a non-SLP transaction", async () => { + // try { + // const txid = + // "3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec" + // + // await bchjs.SLP.Utils.decodeOpReturn(txid) + // + // assert.equal(true, false, "Unexpected result") + // } catch (err) { + // // console.log(`err: `, err) + // assert.include(err.message, "Not an OP_RETURN") + // } + // }) + // }) + + describe('#decodeOpReturn', () => { + it('should decode the OP_RETURN for a SEND txid', async () => { + const txid = + '266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1' + + const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.hasAllKeys(result, [ + 'tokenType', + 'txType', + 'tokenId', + 'amounts' + ]) + assert.equal( + result.tokenId, + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' + ) + + // Verify outputs + assert.equal(result.amounts.length, 2) + assert.equal(result.amounts[0], '100000000') + assert.equal(result.amounts[1], '99883300000000') + }) + + it('should decode the OP_RETURN for a GENESIS txid', async () => { + const txid = + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' + + const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.hasAllKeys(result, [ + 'tokenType', + 'txType', + 'tokenId', + 'ticker', + 'name', + 'documentUri', + 'documentHash', + 'decimals', + 'mintBatonVout', + 'qty' + ]) + assert.equal( + result.tokenId, + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' + ) + assert.equal(result.txType, 'GENESIS') + assert.equal(result.ticker, 'TOK-CH') + assert.equal(result.name, 'TokyoCash') + }) + + it('should decode the OP_RETURN for a MINT txid', async () => { + const txid = + '65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4' + + const result = await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.hasAllKeys(result, [ + 'tokenType', + 'txType', + 'tokenId', + 'mintBatonVout', + 'qty' + ]) + }) + + it('should throw an error for a non-SLP transaction', async () => { + try { + const txid = + '3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec' + + await bchjs.SLP.Utils.decodeOpReturn(txid) + + assert.equal(true, false, 'Unexpected result') + } catch (err) { + // console.log(`err: `, err) + assert.include(err.message, 'scriptpubkey not op_return') } - ] + }) - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + // Note: This TX is interpreted as valid by the original decodeOpReturn(). + // Fixing this issue and related issues was the reason for creating the + // decodeOpReturn2() method using the slp-parser library. + it('should throw error for invalid SLP transaction', async () => { + try { + const txid = + 'a60a522cc11ad7011b74e57fbabbd99296e4b9346bcb175dcf84efb737030415' - assert.equal(data[0].isValid, false, 'Change UTXO marked as false.') - - assert.property(data[1], 'txid') - assert.property(data[1], 'vout') - assert.property(data[1], 'amount') - assert.property(data[1], 'satoshis') - assert.property(data[1], 'height') - assert.property(data[1], 'confirmations') - assert.property(data[1], 'utxoType') - assert.property(data[1], 'tokenId') - assert.property(data[1], 'tokenTicker') - assert.property(data[1], 'tokenName') - assert.property(data[1], 'tokenDocumentUrl') - assert.property(data[1], 'tokenDocumentHash') - assert.property(data[1], 'decimals') - assert.property(data[1], 'isValid') - assert.equal(data[1].isValid, true) - }) - - it('should return details for a MINT token utxo', async () => { - // Mock the call to REST API - - const utxos = [ - { - txid: - 'cf4b922d1e1aa56b52d752d4206e1448ea76c3ebe69b3b97d8f8f65413bd5c76', - vout: 1, - amount: 0.00000546, - satoshis: 546, - height: 600297, - confirmations: 76 + await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + } catch (err) { + // console.log(`err: `, err) + assert.include(err.message, 'amount string size not 8 bytes') } - ] - - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.property(data[0], 'txid') - assert.property(data[0], 'vout') - assert.property(data[0], 'amount') - assert.property(data[0], 'satoshis') - assert.property(data[0], 'height') - assert.property(data[0], 'confirmations') - assert.property(data[0], 'utxoType') - assert.property(data[0], 'transactionType') - assert.property(data[0], 'tokenId') - assert.property(data[0], 'tokenTicker') - assert.property(data[0], 'tokenName') - assert.property(data[0], 'tokenDocumentUrl') - assert.property(data[0], 'tokenDocumentHash') - assert.property(data[0], 'decimals') - assert.property(data[0], 'mintBatonVout') - assert.property(data[0], 'tokenQty') - assert.property(data[0], 'isValid') - assert.equal(data[0].isValid, true) + }) }) - it('should return details for a simple SEND SLP token utxo', async () => { - const utxos = [ - { - txid: - 'fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb', - vout: 1, - amount: 0.00000546, - satoshis: 546, - height: 596089, - confirmations: 748 + describe('#tokenUtxoDetails', () => { + // // This captures an important corner-case. When an SLP token is created, the + // // change UTXO will contain the same SLP txid, but it is not an SLP UTXO. + it('should return details on minting baton from genesis transaction', async () => { + const utxos = [ + { + txid: + 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90', + vout: 3, + amount: 0.00002015, + satoshis: 2015, + height: 594892, + confirmations: 5 + }, + { + txid: + 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90', + vout: 2, + amount: 0.00000546, + satoshis: 546, + height: 594892, + confirmations: 5 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.equal(data[0].isValid, false, 'Change UTXO marked as false.') + + assert.property(data[1], 'txid') + assert.property(data[1], 'vout') + assert.property(data[1], 'amount') + assert.property(data[1], 'satoshis') + assert.property(data[1], 'height') + assert.property(data[1], 'confirmations') + assert.property(data[1], 'utxoType') + assert.property(data[1], 'tokenId') + assert.property(data[1], 'tokenTicker') + assert.property(data[1], 'tokenName') + assert.property(data[1], 'tokenDocumentUrl') + assert.property(data[1], 'tokenDocumentHash') + assert.property(data[1], 'decimals') + assert.property(data[1], 'isValid') + assert.equal(data[1].isValid, true) + }) + + it('should return details for a MINT token utxo', async () => { + // Mock the call to REST API + + const utxos = [ + { + txid: + 'cf4b922d1e1aa56b52d752d4206e1448ea76c3ebe69b3b97d8f8f65413bd5c76', + vout: 1, + amount: 0.00000546, + satoshis: 546, + height: 600297, + confirmations: 76 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.property(data[0], 'txid') + assert.property(data[0], 'vout') + assert.property(data[0], 'amount') + assert.property(data[0], 'satoshis') + assert.property(data[0], 'height') + assert.property(data[0], 'confirmations') + assert.property(data[0], 'utxoType') + assert.property(data[0], 'transactionType') + assert.property(data[0], 'tokenId') + assert.property(data[0], 'tokenTicker') + assert.property(data[0], 'tokenName') + assert.property(data[0], 'tokenDocumentUrl') + assert.property(data[0], 'tokenDocumentHash') + assert.property(data[0], 'decimals') + assert.property(data[0], 'mintBatonVout') + assert.property(data[0], 'tokenQty') + assert.property(data[0], 'isValid') + assert.equal(data[0].isValid, true) + }) + + it('should return details for a simple SEND SLP token utxo', async () => { + const utxos = [ + { + txid: + 'fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb', + vout: 1, + amount: 0.00000546, + satoshis: 546, + height: 596089, + confirmations: 748 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.property(data[0], 'txid') + assert.property(data[0], 'vout') + assert.property(data[0], 'amount') + assert.property(data[0], 'satoshis') + assert.property(data[0], 'height') + assert.property(data[0], 'confirmations') + assert.property(data[0], 'utxoType') + assert.property(data[0], 'tokenId') + assert.property(data[0], 'tokenTicker') + assert.property(data[0], 'tokenName') + assert.property(data[0], 'tokenDocumentUrl') + assert.property(data[0], 'tokenDocumentHash') + assert.property(data[0], 'decimals') + assert.property(data[0], 'tokenQty') + assert.property(data[0], 'isValid') + assert.equal(data[0].isValid, true) + }) + + it('should handle BCH and SLP utxos in the same TX', async () => { + const utxos = [ + { + txid: + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', + vout: 3, + value: '6816', + height: 606848, + confirmations: 13, + satoshis: 6816 + }, + { + txid: + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', + vout: 2, + value: '546', + height: 606848, + confirmations: 13, + satoshis: 546 + } + ] + + const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.equal(result.length, 2) + assert.equal(result[0].isValid, false) + assert.equal(result[1].isValid, true) + }) + + it('should handle problematic utxos', async () => { + const utxos = [ + { + txid: + '0e3a217fc22612002031d317b4cecd9b692b66b52951a67b23c43041aefa3959', + vout: 0, + amount: 0.00018362, + satoshis: 18362, + height: 613483, + confirmations: 124 + }, + { + txid: + '67fd3c7c3a6eb0fea9ab311b91039545086220f7eeeefa367fa28e6e43009f19', + vout: 1, + amount: 0.00000546, + satoshis: 546, + height: 612075, + confirmations: 1532 + } + ] + + const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.equal(result.length, 2) + assert.equal(result[0].isValid, false) + assert.equal(result[1].isValid, true) + }) + + it('should return false for BCH-only UTXOs', async () => { + const utxos = [ + { + txid: + 'a937f792c7c9eb23b4f344ce5c233d1ac0909217d0a504d71e6b1e4efb864a3b', + vout: 0, + amount: 0.00001, + satoshis: 1000, + confirmations: 0, + ts: 1578424704 + }, + { + txid: + '53fd141c2e999e080a5860887441a2c45e9cbe262027e2bd2ac998fc76e43c44', + vout: 0, + amount: 0.00001, + satoshis: 1000, + confirmations: 0, + ts: 1578424634 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data) + assert.equal(data[0].isValid, false) + assert.equal(data[1].isValid, false) + }) + + it('should handle a dust attack', async () => { + // it("#dustattack", async () => { + const utxos = [ + { + height: 655965, + tx_hash: + 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', + tx_pos: 151, + value: 547, + satoshis: 547, + txid: + 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', + vout: 151, + address: 'bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww', + hdIndex: 11 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.equal(data[0].isValid, false) + }) + + it('should handle null SLPDB validations', async () => { + const utxos = [ + { + height: 665577, + tx_hash: + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', + tx_pos: 1, + value: 546 + }, + { + height: 665577, + tx_hash: + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', + tx_pos: 1, + value: 546 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data) + // assert.equal(data[0].isValid, null) + }) + }) + + describe('#tokenUtxoDetailsWL', () => { + it('should return details for a simple SEND SLP token utxo', async () => { + const utxos = [ + { + height: 660554, + tx_hash: + '89b3f0c84efe8b01b24e2d7ac08636de5781f31dbb84478e3de868ca0a7ed93a', + tx_pos: 1, + value: 546 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.property(data[0], 'txid') + assert.property(data[0], 'vout') + assert.property(data[0], 'height') + assert.property(data[0], 'utxoType') + assert.property(data[0], 'tokenId') + assert.property(data[0], 'tokenTicker') + assert.property(data[0], 'tokenName') + assert.property(data[0], 'tokenDocumentUrl') + assert.property(data[0], 'tokenDocumentHash') + assert.property(data[0], 'decimals') + assert.property(data[0], 'tokenQty') + assert.property(data[0], 'isValid') + assert.equal(data[0].isValid, true) + }) + + it('should return false for BCH-only UTXOs', async () => { + const utxos = [ + { + txid: + 'a937f792c7c9eb23b4f344ce5c233d1ac0909217d0a504d71e6b1e4efb864a3b', + vout: 0, + amount: 0.00001, + satoshis: 1000, + confirmations: 0, + ts: 1578424704 + }, + { + txid: + '53fd141c2e999e080a5860887441a2c45e9cbe262027e2bd2ac998fc76e43c44', + vout: 0, + amount: 0.00001, + satoshis: 1000, + confirmations: 0, + ts: 1578424634 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data) + assert.equal(data[0].isValid, false) + assert.equal(data[1].isValid, false) + }) + + it('should handle a dust attack', async () => { + // it("#dustattack", async () => { + const utxos = [ + { + height: 655965, + tx_hash: + 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', + tx_pos: 151, + value: 547, + satoshis: 547, + txid: + 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', + vout: 151, + address: 'bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww', + hdIndex: 11 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.equal(data[0].isValid, false) + }) + + it('should handle null SLPDB validations', async () => { + const utxos = [ + { + height: 665577, + tx_hash: + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', + tx_pos: 1, + value: 546 + }, + { + height: 665577, + tx_hash: + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', + tx_pos: 1, + value: 546 + } + ] + + const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data) + // assert.equal(data[0].isValid, null) + }) + }) + + describe('#balancesForAddress', () => { + it('should fetch all balances for address: simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9', async () => { + const balances = await bchjs.SLP.Utils.balancesForAddress( + 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9' + ) + // console.log(`balances: ${JSON.stringify(balances, null, 2)}`) + + assert.isArray(balances) + assert.hasAllKeys(balances[0], [ + 'tokenId', + 'balanceString', + 'balance', + 'decimalCount', + 'slpAddress' + ]) + }) + + it('should fetch balances for multiple addresses', async () => { + const addresses = [ + 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9', + 'simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57' + ] + + const balances = await bchjs.SLP.Utils.balancesForAddress(addresses) + // console.log(`balances: ${JSON.stringify(balances, null, 2)}`) + + assert.isArray(balances) + assert.isArray(balances[0]) + assert.hasAllKeys(balances[0][0], [ + 'tokenId', + 'balanceString', + 'balance', + 'decimalCount', + 'slpAddress' + ]) + }) + }) + + describe('#hydrateUtxos-', () => { + it('should hydrate UTXOs', async () => { + const utxos = [ + { + utxos: [ + { + txid: + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', + vout: 3, + value: '6816', + height: 606848, + confirmations: 13, + satoshis: 6816 + }, + { + txid: + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', + vout: 2, + value: '546', + height: 606848, + confirmations: 13, + satoshis: 546 + } + ] + } + ] + + const result = await bchjs.SLP.Utils.hydrateUtxos(utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // Test the general structure of the output. + assert.isArray(result.slpUtxos) + assert.equal(result.slpUtxos.length, 1) + assert.equal(result.slpUtxos[0].utxos.length, 2) + + // Test the non-slp UTXO. + assert.property(result.slpUtxos[0].utxos[0], 'txid') + assert.property(result.slpUtxos[0].utxos[0], 'vout') + assert.property(result.slpUtxos[0].utxos[0], 'value') + assert.property(result.slpUtxos[0].utxos[0], 'height') + assert.property(result.slpUtxos[0].utxos[0], 'confirmations') + assert.property(result.slpUtxos[0].utxos[0], 'satoshis') + assert.property(result.slpUtxos[0].utxos[0], 'isValid') + assert.equal(result.slpUtxos[0].utxos[0].isValid, false) + + // Test the slp UTXO. + assert.property(result.slpUtxos[0].utxos[1], 'txid') + assert.property(result.slpUtxos[0].utxos[1], 'vout') + assert.property(result.slpUtxos[0].utxos[1], 'value') + assert.property(result.slpUtxos[0].utxos[1], 'height') + assert.property(result.slpUtxos[0].utxos[1], 'confirmations') + assert.property(result.slpUtxos[0].utxos[1], 'satoshis') + assert.property(result.slpUtxos[0].utxos[1], 'isValid') + assert.equal(result.slpUtxos[0].utxos[1].isValid, true) + assert.property(result.slpUtxos[0].utxos[1], 'transactionType') + assert.property(result.slpUtxos[0].utxos[1], 'tokenId') + assert.property(result.slpUtxos[0].utxos[1], 'tokenTicker') + assert.property(result.slpUtxos[0].utxos[1], 'tokenName') + assert.property(result.slpUtxos[0].utxos[1], 'tokenDocumentUrl') + assert.property(result.slpUtxos[0].utxos[1], 'tokenDocumentHash') + assert.property(result.slpUtxos[0].utxos[1], 'decimals') + assert.property(result.slpUtxos[0].utxos[1], 'tokenType') + assert.property(result.slpUtxos[0].utxos[1], 'tokenQty') + }) + + it('should process data directly from Electrumx', async () => { + const addrs = [ + 'bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp', + 'bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5', + 'bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495' + ] + + const utxos = await bchjs.Electrumx.utxo(addrs) + // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) + + const result = await bchjs.SLP.Utils.hydrateUtxos(utxos.utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // Test the general structure of the output. + assert.isArray(result.slpUtxos) + assert.equal(result.slpUtxos.length, 3) + assert.equal(result.slpUtxos[0].utxos.length, 1) + assert.equal(result.slpUtxos[1].utxos.length, 1) + assert.equal(result.slpUtxos[2].utxos.length, 2) + + try { + // Test the expected values. + assert.equal(result.slpUtxos[0].utxos[0].isValid, false) + assert.equal(result.slpUtxos[1].utxos[0].isValid, true) + assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, 'TROUT') + assert.equal(result.slpUtxos[2].utxos[0].isValid, false) + assert.equal(result.slpUtxos[2].utxos[1].isValid, true) + assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, 'VALENTINE') + } catch (err) { + console.error( + 'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"' + ) + console.log('Error: ', err) } - ] + }) - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + it('should handle null SLPDB validations', async () => { + const utxos = [ + { + height: 665577, + tx_hash: + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', + tx_pos: 1, + value: 546 + }, + { + height: 665577, + tx_hash: + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', + tx_pos: 1, + value: 546 + } + ] - assert.property(data[0], 'txid') - assert.property(data[0], 'vout') - assert.property(data[0], 'amount') - assert.property(data[0], 'satoshis') - assert.property(data[0], 'height') - assert.property(data[0], 'confirmations') - assert.property(data[0], 'utxoType') - assert.property(data[0], 'tokenId') - assert.property(data[0], 'tokenTicker') - assert.property(data[0], 'tokenName') - assert.property(data[0], 'tokenDocumentUrl') - assert.property(data[0], 'tokenDocumentHash') - assert.property(data[0], 'decimals') - assert.property(data[0], 'tokenQty') - assert.property(data[0], 'isValid') - assert.equal(data[0].isValid, true) + const data = await bchjs.SLP.Utils.hydrateUtxos([{ utxos: utxos }]) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data.slpUtxos) + assert.equal(data.slpUtxos[0].isValid, null) + }) }) - it('should handle BCH and SLP utxos in the same TX', async () => { - const utxos = [ - { - txid: - 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', - vout: 3, - value: '6816', - height: 606848, - confirmations: 13, - satoshis: 6816 - }, - { - txid: - 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', - vout: 2, - value: '546', - height: 606848, - confirmations: 13, - satoshis: 546 + describe('#hydrateUtxosWL', () => { + it('should hydrate UTXOs', async () => { + const utxos = [ + { + utxos: [ + { + txid: + '89b3f0c84efe8b01b24e2d7ac08636de5781f31dbb84478e3de868ca0a7ed93a', + vout: 1, + value: 546 + } + ] + } + ] + + const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // Test the general structure of the output. + assert.isArray(result.slpUtxos) + assert.equal(result.slpUtxos.length, 1) + assert.equal(result.slpUtxos[0].utxos.length, 1) + + // Test the non-slp UTXO. + assert.property(result.slpUtxos[0].utxos[0], 'txid') + assert.property(result.slpUtxos[0].utxos[0], 'vout') + assert.property(result.slpUtxos[0].utxos[0], 'value') + assert.property(result.slpUtxos[0].utxos[0], 'isValid') + assert.equal(result.slpUtxos[0].utxos[0].isValid, true) + }) + + it('should process data directly from Electrumx', async () => { + const addrs = [ + 'bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp', + 'bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5', + 'bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495' + ] + + const utxos = await bchjs.Electrumx.utxo(addrs) + // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) + + const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos.utxos) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // Test the general structure of the output. + assert.isArray(result.slpUtxos) + assert.equal(result.slpUtxos.length, 3) + assert.equal(result.slpUtxos[0].utxos.length, 1) + assert.equal(result.slpUtxos[1].utxos.length, 1) + assert.equal(result.slpUtxos[2].utxos.length, 2) + + try { + // Test the expected values. + assert.equal(result.slpUtxos[0].utxos[0].isValid, false) + assert.equal(result.slpUtxos[1].utxos[0].isValid, true) + assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, 'TROUT') + assert.equal(result.slpUtxos[2].utxos[0].isValid, false) + // assert.equal(result.slpUtxos[2].utxos[1].isValid, null) + assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, 'VALENTINE') + } catch (err) { + console.error( + 'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"' + ) + console.log('Error: ', err) } - ] + }) - const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) + it('should handle null SLPDB validations', async () => { + const utxos = [ + { + height: 665577, + tx_hash: + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', + tx_pos: 1, + value: 546 + }, + { + height: 665577, + tx_hash: + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', + tx_pos: 1, + value: 546 + } + ] - assert.isArray(result) - assert.equal(result.length, 2) - assert.equal(result[0].isValid, false) - assert.equal(result[1].isValid, true) + const data = await bchjs.SLP.Utils.hydrateUtxosWL([{ utxos: utxos }]) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.isArray(data.slpUtxos) + assert.equal(data.slpUtxos[0].isValid, null) + }) }) - it('should handle problematic utxos', async () => { - const utxos = [ - { - txid: - '0e3a217fc22612002031d317b4cecd9b692b66b52951a67b23c43041aefa3959', - vout: 0, - amount: 0.00018362, - satoshis: 18362, - height: 613483, - confirmations: 124 - }, - { - txid: - '67fd3c7c3a6eb0fea9ab311b91039545086220f7eeeefa367fa28e6e43009f19', - vout: 1, - amount: 0.00000546, - satoshis: 546, - height: 612075, - confirmations: 1532 - } - ] + describe('#validateTxid', () => { + // This test is not necessary. + it('should handle a null response from SLPDB', async () => { + const txid = + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419' - const result = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) + const result = await bchjs.SLP.Utils.validateTxid(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isArray(result) - assert.equal(result.length, 2) - assert.equal(result[0].isValid, false) - assert.equal(result[1].isValid, true) + assert.isArray(result) + assert.equal(result[0].txid, txid) + // assert.equal(result[0].valid, null) + }) + + it('should handle a null response from SLPDB', async () => { + const txid = [ + '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' + ] + + const result = await bchjs.SLP.Utils.validateTxid(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.isArray(result) + assert.equal(result[0].txid, txid[0]) + // assert.equal(result[0].valid, null) + }) }) - it('should return false for BCH-only UTXOs', async () => { - const utxos = [ - { - txid: - 'a937f792c7c9eb23b4f344ce5c233d1ac0909217d0a504d71e6b1e4efb864a3b', - vout: 0, - amount: 0.00001, - satoshis: 1000, - confirmations: 0, - ts: 1578424704 - }, - { - txid: - '53fd141c2e999e080a5860887441a2c45e9cbe262027e2bd2ac998fc76e43c44', - vout: 0, - amount: 0.00001, - satoshis: 1000, - confirmations: 0, - ts: 1578424634 - } - ] + describe('#validateTxid2', () => { + it('should invalidate a known invalid TXID', async () => { + const txid = + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + const result = await bchjs.SLP.Utils.validateTxid2(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isArray(data) - assert.equal(data[0].isValid, false) - assert.equal(data[1].isValid, false) + assert.property(result, 'txid') + assert.equal(result.txid, txid) + + assert.property(result, 'isValid') + assert.equal(result.isValid, false) + }) + + it('should validate a known valid TXID', async () => { + const txid = + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' + + const result = await bchjs.SLP.Utils.validateTxid2(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.property(result, 'txid') + assert.equal(result.txid, txid) + + assert.property(result, 'isValid') + assert.equal(result.isValid, true) + }) }) - it('should handle a dust attack', async () => { - // it("#dustattack", async () => { - const utxos = [ - { - height: 655965, - tx_hash: - 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', - tx_pos: 151, - value: 547, - satoshis: 547, - txid: - 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', - vout: 151, - address: 'bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww', - hdIndex: 11 - } - ] + describe('#getWhitelist', () => { + it('should get the whitelist', async () => { + const result = await bchjs.SLP.Utils.getWhitelist() + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.equal(data[0].isValid, false) + assert.isArray(result) + assert.property(result[0], 'name') + assert.property(result[1], 'tokenId') + }) }) - it('should handle null SLPDB validations', async () => { - const utxos = [ - { - height: 665577, - tx_hash: - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', - tx_pos: 1, - value: 546 - }, - { - height: 665577, - tx_hash: - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', - tx_pos: 1, - value: 546 - } - ] + describe('#getStatus', () => { + it('should return the current block height of the SLPDB indexer', async () => { + const result = await bchjs.SLP.Utils.getStatus() - const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isArray(data) - // assert.equal(data[0].isValid, null) - }) - }) - - describe('#tokenUtxoDetailsWL', () => { - it('should return details for a simple SEND SLP token utxo', async () => { - const utxos = [ - { - height: 660554, - tx_hash: - '89b3f0c84efe8b01b24e2d7ac08636de5781f31dbb84478e3de868ca0a7ed93a', - tx_pos: 1, - value: 546 - } - ] - - const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.property(data[0], 'txid') - assert.property(data[0], 'vout') - assert.property(data[0], 'height') - assert.property(data[0], 'utxoType') - assert.property(data[0], 'tokenId') - assert.property(data[0], 'tokenTicker') - assert.property(data[0], 'tokenName') - assert.property(data[0], 'tokenDocumentUrl') - assert.property(data[0], 'tokenDocumentHash') - assert.property(data[0], 'decimals') - assert.property(data[0], 'tokenQty') - assert.property(data[0], 'isValid') - assert.equal(data[0].isValid, true) + assert.property(result, 'bchBlockHeight') + assert.property(result, 'slpProcessedBlockHeight') + }) }) - it('should return false for BCH-only UTXOs', async () => { - const utxos = [ - { - txid: - 'a937f792c7c9eb23b4f344ce5c233d1ac0909217d0a504d71e6b1e4efb864a3b', - vout: 0, - amount: 0.00001, - satoshis: 1000, - confirmations: 0, - ts: 1578424704 - }, - { - txid: - '53fd141c2e999e080a5860887441a2c45e9cbe262027e2bd2ac998fc76e43c44', - vout: 0, - amount: 0.00001, - satoshis: 1000, - confirmations: 0, - ts: 1578424634 - } - ] + describe('#waterfallValidateTxid', () => { + it('should validate known good txid not in whitelist', async () => { + const txid = + '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' - const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) + const result = await bchjs.SLP.Utils.waterfallValidateTxid(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isArray(data) - assert.equal(data[0].isValid, false) - assert.equal(data[1].isValid, false) + assert.equal(result, true) + }) + + it('should invalidate a known invalid TXID', async () => { + const txid = + 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' + + const result = await bchjs.SLP.Utils.waterfallValidateTxid(txid) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + assert.equal(result, false) + }) }) - - it('should handle a dust attack', async () => { - // it("#dustattack", async () => { - const utxos = [ - { - height: 655965, - tx_hash: - 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', - tx_pos: 151, - value: 547, - satoshis: 547, - txid: - 'a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e', - vout: 151, - address: 'bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww', - hdIndex: 11 - } - ] - - const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.equal(data[0].isValid, false) - }) - - it('should handle null SLPDB validations', async () => { - const utxos = [ - { - height: 665577, - tx_hash: - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', - tx_pos: 1, - value: 546 - }, - { - height: 665577, - tx_hash: - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488', - tx_pos: 1, - value: 546 - } - ] - - const data = await bchjs.SLP.Utils.tokenUtxoDetailsWL(utxos) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.isArray(data) - // assert.equal(data[0].isValid, null) - }) - }) - - describe('#balancesForAddress', () => { - it('should fetch all balances for address: simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9', async () => { - const balances = await bchjs.SLP.Utils.balancesForAddress( - 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9' - ) - // console.log(`balances: ${JSON.stringify(balances, null, 2)}`) - - assert.isArray(balances) - assert.hasAllKeys(balances[0], [ - 'tokenId', - 'balanceString', - 'balance', - 'decimalCount', - 'slpAddress' - ]) - }) - - it('should fetch balances for multiple addresses', async () => { - const addresses = [ - 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9', - 'simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57' - ] - - const balances = await bchjs.SLP.Utils.balancesForAddress(addresses) - // console.log(`balances: ${JSON.stringify(balances, null, 2)}`) - - assert.isArray(balances) - assert.isArray(balances[0]) - assert.hasAllKeys(balances[0][0], [ - 'tokenId', - 'balanceString', - 'balance', - 'decimalCount', - 'slpAddress' - ]) - }) - }) - - describe('#hydrateUtxos-', () => { - it('should hydrate UTXOs', async () => { - const utxos = [ - { - utxos: [ + describe('#tokentype1', () => { + describe('#getHexOpReturn', () => { + it('should return OP_RETURN object ', async () => { + const tokenUtxos = [ { - txid: - 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', - vout: 3, - value: '6816', - height: 606848, - confirmations: 13, - satoshis: 6816 - }, - { - txid: - 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', - vout: 2, - value: '546', - height: 606848, - confirmations: 13, - satoshis: 546 + tokenId: + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + decimals: 8, + tokenQty: 2 } ] - } - ] + const sendQty = 1.5 - const result = await bchjs.SLP.Utils.hydrateUtxos(utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) + const result = await bchjs.SLP.TokenType1.getHexOpReturn( + tokenUtxos, + sendQty + ) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) - // Test the general structure of the output. - assert.isArray(result.slpUtxos) - assert.equal(result.slpUtxos.length, 1) - assert.equal(result.slpUtxos[0].utxos.length, 2) + assert.property(result, 'script') + assert.isString(result.script) - // Test the non-slp UTXO. - assert.property(result.slpUtxos[0].utxos[0], 'txid') - assert.property(result.slpUtxos[0].utxos[0], 'vout') - assert.property(result.slpUtxos[0].utxos[0], 'value') - assert.property(result.slpUtxos[0].utxos[0], 'height') - assert.property(result.slpUtxos[0].utxos[0], 'confirmations') - assert.property(result.slpUtxos[0].utxos[0], 'satoshis') - assert.property(result.slpUtxos[0].utxos[0], 'isValid') - assert.equal(result.slpUtxos[0].utxos[0].isValid, false) - - // Test the slp UTXO. - assert.property(result.slpUtxos[0].utxos[1], 'txid') - assert.property(result.slpUtxos[0].utxos[1], 'vout') - assert.property(result.slpUtxos[0].utxos[1], 'value') - assert.property(result.slpUtxos[0].utxos[1], 'height') - assert.property(result.slpUtxos[0].utxos[1], 'confirmations') - assert.property(result.slpUtxos[0].utxos[1], 'satoshis') - assert.property(result.slpUtxos[0].utxos[1], 'isValid') - assert.equal(result.slpUtxos[0].utxos[1].isValid, true) - assert.property(result.slpUtxos[0].utxos[1], 'transactionType') - assert.property(result.slpUtxos[0].utxos[1], 'tokenId') - assert.property(result.slpUtxos[0].utxos[1], 'tokenTicker') - assert.property(result.slpUtxos[0].utxos[1], 'tokenName') - assert.property(result.slpUtxos[0].utxos[1], 'tokenDocumentUrl') - assert.property(result.slpUtxos[0].utxos[1], 'tokenDocumentHash') - assert.property(result.slpUtxos[0].utxos[1], 'decimals') - assert.property(result.slpUtxos[0].utxos[1], 'tokenType') - assert.property(result.slpUtxos[0].utxos[1], 'tokenQty') + assert.property(result, 'outputs') + assert.isNumber(result.outputs) + }) + }) }) - - it('should process data directly from Electrumx', async () => { - const addrs = [ - 'bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp', - 'bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5', - 'bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495' - ] - - const utxos = await bchjs.Electrumx.utxo(addrs) - // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) - - const result = await bchjs.SLP.Utils.hydrateUtxos(utxos.utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - // Test the general structure of the output. - assert.isArray(result.slpUtxos) - assert.equal(result.slpUtxos.length, 3) - assert.equal(result.slpUtxos[0].utxos.length, 1) - assert.equal(result.slpUtxos[1].utxos.length, 1) - assert.equal(result.slpUtxos[2].utxos.length, 2) - - try { - // Test the expected values. - assert.equal(result.slpUtxos[0].utxos[0].isValid, false) - assert.equal(result.slpUtxos[1].utxos[0].isValid, true) - assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, 'TROUT') - assert.equal(result.slpUtxos[2].utxos[0].isValid, false) - assert.equal(result.slpUtxos[2].utxos[1].isValid, true) - assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, 'VALENTINE') - } catch (err) { - console.error( - 'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"' - ) - console.log('Error: ', err) - } - }) - - it('should handle null SLPDB validations', async () => { - const utxos = [ - { - height: 665577, - tx_hash: - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', - tx_pos: 1, - value: 546 - }, - { - height: 665577, - tx_hash: - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', - tx_pos: 1, - value: 546 - } - ] - - const data = await bchjs.SLP.Utils.hydrateUtxos([{ utxos: utxos }]) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.isArray(data.slpUtxos) - assert.equal(data.slpUtxos[0].isValid, null) - }) - }) - - describe('#hydrateUtxosWL', () => { - it('should hydrate UTXOs', async () => { - const utxos = [ - { - utxos: [ - { - txid: - '89b3f0c84efe8b01b24e2d7ac08636de5781f31dbb84478e3de868ca0a7ed93a', - vout: 1, - value: 546 - } - ] - } - ] - - const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - // Test the general structure of the output. - assert.isArray(result.slpUtxos) - assert.equal(result.slpUtxos.length, 1) - assert.equal(result.slpUtxos[0].utxos.length, 1) - - // Test the non-slp UTXO. - assert.property(result.slpUtxos[0].utxos[0], 'txid') - assert.property(result.slpUtxos[0].utxos[0], 'vout') - assert.property(result.slpUtxos[0].utxos[0], 'value') - assert.property(result.slpUtxos[0].utxos[0], 'isValid') - assert.equal(result.slpUtxos[0].utxos[0].isValid, true) - }) - - it('should process data directly from Electrumx', async () => { - const addrs = [ - 'bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp', - 'bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5', - 'bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495' - ] - - const utxos = await bchjs.Electrumx.utxo(addrs) - // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`) - - const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos.utxos) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - // Test the general structure of the output. - assert.isArray(result.slpUtxos) - assert.equal(result.slpUtxos.length, 3) - assert.equal(result.slpUtxos[0].utxos.length, 1) - assert.equal(result.slpUtxos[1].utxos.length, 1) - assert.equal(result.slpUtxos[2].utxos.length, 2) - - try { - // Test the expected values. - assert.equal(result.slpUtxos[0].utxos[0].isValid, false) - assert.equal(result.slpUtxos[1].utxos[0].isValid, true) - assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, 'TROUT') - assert.equal(result.slpUtxos[2].utxos[0].isValid, false) - // assert.equal(result.slpUtxos[2].utxos[1].isValid, null) - assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, 'VALENTINE') - } catch (err) { - console.error( - 'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"' - ) - console.log('Error: ', err) - } - }) - - it('should handle null SLPDB validations', async () => { - const utxos = [ - { - height: 665577, - tx_hash: - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', - tx_pos: 1, - value: 546 - }, - { - height: 665577, - tx_hash: - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a', - tx_pos: 1, - value: 546 - } - ] - - const data = await bchjs.SLP.Utils.hydrateUtxosWL([{ utxos: utxos }]) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - - assert.isArray(data.slpUtxos) - assert.equal(data.slpUtxos[0].isValid, null) - }) - }) - - describe('#validateTxid', () => { - // This test is not necessary. - it('should handle a null response from SLPDB', async () => { - const txid = - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419' - - const result = await bchjs.SLP.Utils.validateTxid(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.equal(result[0].txid, txid) - // assert.equal(result[0].valid, null) - }) - - it('should handle a null response from SLPDB', async () => { - const txid = [ - '4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419', - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' - ] - - const result = await bchjs.SLP.Utils.validateTxid(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.equal(result[0].txid, txid[0]) - // assert.equal(result[0].valid, null) - }) - }) - - describe('#validateTxid2', () => { - it('should invalidate a known invalid TXID', async () => { - const txid = - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' - - const result = await bchjs.SLP.Utils.validateTxid2(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.property(result, 'txid') - assert.equal(result.txid, txid) - - assert.property(result, 'isValid') - assert.equal(result.isValid, false) - }) - - it('should validate a known valid TXID', async () => { - const txid = - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' - - const result = await bchjs.SLP.Utils.validateTxid2(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.property(result, 'txid') - assert.equal(result.txid, txid) - - assert.property(result, 'isValid') - assert.equal(result.isValid, true) - }) - }) - - describe('#getWhitelist', () => { - it('should get the whitelist', async () => { - const result = await bchjs.SLP.Utils.getWhitelist() - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.isArray(result) - assert.property(result[0], 'name') - assert.property(result[1], 'tokenId') - }) - }) - - describe('#getStatus', () => { - it('should return the current block height of the SLPDB indexer', async () => { - const result = await bchjs.SLP.Utils.getStatus() - - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.property(result, 'bchBlockHeight') - assert.property(result, 'slpProcessedBlockHeight') - }) - }) - - describe('#waterfallValidateTxid', () => { - it('should validate known good txid not in whitelist', async () => { - const txid = - '3a4b628cbcc183ab376d44ce5252325f042268307ffa4a53443e92b6d24fb488' - - const result = await bchjs.SLP.Utils.waterfallValidateTxid(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.equal(result, true) - }) - - it('should invalidate a known invalid TXID', async () => { - const txid = - 'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a' - - const result = await bchjs.SLP.Utils.waterfallValidateTxid(txid) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.equal(result, false) - }) - }) - }) - - describe('#tokentype1', () => { - describe('#getHexOpReturn', () => { - it('should return OP_RETURN object ', async () => { - const tokenUtxos = [ - { - tokenId: - '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', - decimals: 8, - tokenQty: 2 - } - ] - const sendQty = 1.5 - - const result = await bchjs.SLP.TokenType1.getHexOpReturn( - tokenUtxos, - sendQty - ) - // console.log(`result: ${JSON.stringify(result, null, 2)}`) - - assert.property(result, 'script') - assert.isString(result.script) - - assert.property(result, 'outputs') - assert.isNumber(result.outputs) - }) - }) + } }) })