Compare commits

..
12 Commits
Author SHA1 Message Date
Chris Troutner 24e2c78d03 Merge pull request #148 from Permissionless-Software-Foundation/ct-unstable
fix(testnet): Removing testnet ninsight tests as they rarely pass
2021-05-22 07:58:39 -07:00
Chris Troutner eab02fdbc9 fix(testnet): Removing testnet ninsight tests as they rarely pass 2021-05-22 07:55:02 -07:00
Chris Troutner f7bd9c75db Merge pull request #147 from Permissionless-Software-Foundation/ct-unstable
fix(nft docs): Fixing a typo in docs
2021-05-21 15:54:07 -07:00
Chris Troutner 2a96f3a4f5 fix(nft docs): Fixing a typo in docs 2021-05-21 15:51:43 -07:00
Chris Troutner 3dc4a8ba6f Merge pull request #146 from Permissionless-Software-Foundation/ct-unstable
fix(dependencies): Updating dependencies. 0 npm vulns
2021-05-21 15:39:46 -07:00
Chris Troutner 65916f2c5c fix(dependencies): Updating dependencies. 0 npm vulns 2021-05-21 15:38:02 -07:00
Chris Troutner 18188bfdce Merge pull request #145 from Permissionless-Software-Foundation/nft-group-get-call
Return parent NFT group token information
2021-05-18 12:40:16 -07:00
Stoyan Zhekov 45acc2b0b7 Return parent NFT group token information 2021-05-16 14:22:33 +09:00
Chris Troutner 31913c3fb7 Merge pull request #144 from Permissionless-Software-Foundation/nft-children-get-call
NFT children get call
2021-05-15 08:54:58 -07:00
Stoyan Zhekov 2311643398 Example fixed 2021-05-14 21:58:52 +09:00
Stoyan Zhekov 7501aa0238 Lint fixes 2021-05-14 21:18:08 +09:00
Stoyan Zhekov 92a89a543d List NFT children per group 2021-05-14 21:17:07 +09:00
8 changed files with 16499 additions and 210 deletions
+16118 -76
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -4,12 +4,14 @@
"description": "The FullStack.cash JavaScript library for Bitcoin Cash and SLP Tokens",
"author": "Chris Troutner <chris.troutner@gmail.com>",
"contributors": [
"Gabriel Cardona <gabriel@bitcoin.com>"
"Gabriel Cardona <gabriel@bitcoin.com>",
"Stoyan Zhekov <zh@zhware.net>"
],
"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/",
+100 -2
View File
@@ -8,16 +8,21 @@
(Parent) token.
*/
// Public npm libraries
const axios = require('axios')
// Local libraries.
const Address = require('./address')
// const BigNumber = require('bignumber.js')
const slpMdm = require('slp-mdm')
let _this
// const addy = new Address()
let addy
const TransactionBuilder = require('../transaction-builder')
class TokenType1 {
class Nft1 {
constructor (config) {
this.restURL = config.restURL
@@ -25,6 +30,8 @@ class TokenType1 {
// Instantiate the transaction builder.
TransactionBuilder.setAddress(addy)
_this = this
}
/**
@@ -412,6 +419,97 @@ class TokenType1 {
throw err
}
}
/**
* @api SLP.NFT1.listNFTGroupChildren() listNFTGroupChildren()
* @apiName listNFTGroupChildren
* @apiGroup SLP NFT1
* @apiDescription Return list of NFT children tokens in a NFT Group.
* It's assumed provided groupId parameter is for an NFT Group token (type=129)
*
* Returns an Array with GENESIS transaction IDs of the children tokens.
*
* @apiExample Example usage:
*
* const groupId = '68cd33ecd909068fbea318ae5ff1d6207cf754e53b191327d6d73b6916424c0a'
* const children = await bchjs.SLP.Nft1.listNFTGroupChildren(groupId)
*
* children = {
* "nftChildren": [
* "45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9",
* "928ce61fe1006b1325a0ba0dce700bf83986a6f0691ba26e121c9ac035d12a55"
* ]
* }
*/
async listNFTGroupChildren (groupId) {
try {
if (typeof groupId === 'string') {
const response = await axios.get(
`${this.restURL}slp/nftChildren/${groupId}`,
_this.axiosOptions
)
return response.data
}
throw new Error('groupId must be a string.')
} catch (error) {
// console.log('Error in listNFTGroupChildren()')
if (error.response && error.response.data) throw error.response.data
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 = TokenType1
module.exports = Nft1
+1 -1
View File
@@ -41,7 +41,7 @@ class SLP {
this.Address = new Address(config)
this.ECPair = ECPair
this.TokenType1 = new TokenType1(config)
this.NFT1 = new NFT1(this.restURL)
this.NFT1 = new NFT1(config)
this.Utils = new Utils(config)
}
}
+25
View File
@@ -264,6 +264,31 @@ describe('#SLP', () => {
})
})
})
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
+130 -128
View File
@@ -1,9 +1,9 @@
const chai = require('chai')
const assert = chai.assert
// const chai = require('chai')
// const assert = chai.assert
const sinon = require('sinon')
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS({ ninsightURL: 'https://trest.bitcoin.com/v2' })
// const BCHJS = require('../../../../src/bch-js')
// const bchjs = new BCHJS({ ninsightURL: 'https://trest.bitcoin.com/v2' })
describe('#Ninsight', () => {
let sandbox
@@ -16,130 +16,132 @@ describe('#Ninsight', () => {
afterEach(() => sandbox.restore())
describe('#utxo', () => {
it('should GET utxos for a single address', async () => {
const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
const result = await bchjs.Ninsight.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result[0], 'utxos')
assert.property(result[0], 'legacyAddress')
assert.property(result[0], 'cashAddress')
assert.property(result[0], 'slpAddress')
assert.property(result[0], 'scriptPubKey')
assert.property(result[0], 'asm')
assert.isArray(result[0].utxos)
assert.property(result[0].utxos[0], 'txid')
assert.property(result[0].utxos[0], 'vout')
assert.property(result[0].utxos[0], 'amount')
assert.property(result[0].utxos[0], 'satoshis')
assert.property(result[0].utxos[0], 'height')
assert.property(result[0].utxos[0], 'confirmations')
})
it('should POST utxo details for an array of addresses', async () => {
const addr = [
'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
]
const result = await bchjs.Ninsight.utxo(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.isArray(result[0].utxos)
assert.property(result[0], 'utxos')
assert.property(result[0], 'legacyAddress')
assert.property(result[0], 'cashAddress')
assert.property(result[0], 'slpAddress')
assert.property(result[0], 'scriptPubKey')
assert.property(result[0], 'asm')
// assert.hasAnyKeys(result[0][0], [
// "txid",
// "vout",
// "value",
// "height",
// "confirmations"
// ])
})
})
describe('#transactions', () => {
it('should POST transactions history for a single address', async () => {
const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
const result = await bchjs.Ninsight.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], 'cashAddress')
assert.property(result[0], 'legacyAddress')
assert.property(result[0], 'txs')
assert.isArray(result[0].txs)
assert.property(result[0].txs[0], 'txid')
assert.property(result[0].txs[0], 'vin')
assert.property(result[0].txs[0], 'vout')
})
it('should POST transactions history for an array of addresses', async () => {
const addr = [
'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
]
const result = await bchjs.Ninsight.transactions(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], 'cashAddress')
assert.property(result[0], 'legacyAddress')
assert.property(result[0], 'txs')
assert.isArray(result[0].txs)
assert.property(result[0].txs[0], 'txid')
assert.property(result[0].txs[0], 'vin')
assert.property(result[0].txs[0], 'vout')
})
})
describe('#txDetails', () => {
it('should POST transactions details for a single address', async () => {
const txid =
'76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
const result = await bchjs.Ninsight.txDetails(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], 'txid')
assert.property(result[0], 'version')
assert.property(result[0], 'locktime')
assert.property(result[0], 'vin')
assert.property(result[0], 'vout')
assert.property(result[0], 'blockhash')
assert.property(result[0], 'blockheight')
assert.property(result[0], 'confirmations')
assert.property(result[0], 'time')
assert.property(result[0], 'blocktime')
assert.property(result[0], 'valueOut')
assert.property(result[0], 'size')
})
it('should POST transactions details for an array of addresses', async () => {
const txid = [
'f191d1062789d7071da6f2168ba306869a829294f6b1c09d03492db4ca3a8e77',
'76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
]
const result = await bchjs.Ninsight.txDetails(txid)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isArray(result)
assert.property(result[0], 'txid')
assert.property(result[0], 'vin')
assert.property(result[0], 'vout')
})
})
// describe('#utxo', () => {
// it('should GET utxos for a single address', async () => {
// const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
//
// const result = await bchjs.Ninsight.utxo(addr)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.property(result[0], 'utxos')
// assert.property(result[0], 'legacyAddress')
// assert.property(result[0], 'cashAddress')
// assert.property(result[0], 'slpAddress')
// assert.property(result[0], 'scriptPubKey')
// assert.property(result[0], 'asm')
//
// assert.isArray(result[0].utxos)
//
// assert.property(result[0].utxos[0], 'txid')
// assert.property(result[0].utxos[0], 'vout')
// assert.property(result[0].utxos[0], 'amount')
// assert.property(result[0].utxos[0], 'satoshis')
// assert.property(result[0].utxos[0], 'height')
// assert.property(result[0].utxos[0], 'confirmations')
// })
//
// it('should POST utxo details for an array of addresses', async () => {
// const addr = [
// 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
// 'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
// ]
//
// const result = await bchjs.Ninsight.utxo(addr)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
// assert.isArray(result[0].utxos)
//
// assert.property(result[0], 'utxos')
// assert.property(result[0], 'legacyAddress')
// assert.property(result[0], 'cashAddress')
// assert.property(result[0], 'slpAddress')
// assert.property(result[0], 'scriptPubKey')
// assert.property(result[0], 'asm')
//
// // assert.hasAnyKeys(result[0][0], [
// // "txid",
// // "vout",
// // "value",
// // "height",
// // "confirmations"
// // ])
// })
// })
//
// describe('#transactions', () => {
// it('should POST transactions history for a single address', async () => {
// const addr = 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr'
//
// const result = await bchjs.Ninsight.transactions(addr)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
// assert.property(result[0], 'cashAddress')
// assert.property(result[0], 'legacyAddress')
// assert.property(result[0], 'txs')
// assert.isArray(result[0].txs)
// assert.property(result[0].txs[0], 'txid')
// assert.property(result[0].txs[0], 'vin')
// assert.property(result[0].txs[0], 'vout')
// })
// it('should POST transactions history for an array of addresses', async () => {
// const addr = [
// 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr',
// 'bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul'
// ]
//
// const result = await bchjs.Ninsight.transactions(addr)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
// assert.property(result[0], 'cashAddress')
// assert.property(result[0], 'legacyAddress')
// assert.property(result[0], 'txs')
// assert.isArray(result[0].txs)
// assert.property(result[0].txs[0], 'txid')
// assert.property(result[0].txs[0], 'vin')
// assert.property(result[0].txs[0], 'vout')
// })
// })
//
// describe('#txDetails', () => {
// it('should POST transactions details for a single address', async () => {
// const txid =
// '76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
//
// const result = await bchjs.Ninsight.txDetails(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
// assert.property(result[0], 'txid')
// assert.property(result[0], 'version')
// assert.property(result[0], 'locktime')
// assert.property(result[0], 'vin')
// assert.property(result[0], 'vout')
// assert.property(result[0], 'blockhash')
// assert.property(result[0], 'blockheight')
// assert.property(result[0], 'confirmations')
// assert.property(result[0], 'time')
// assert.property(result[0], 'blocktime')
// assert.property(result[0], 'valueOut')
// assert.property(result[0], 'size')
// })
// it('should POST transactions details for an array of addresses', async () => {
// const txid = [
// 'f191d1062789d7071da6f2168ba306869a829294f6b1c09d03492db4ca3a8e77',
// '76856d82e00b2696acd8d989e1fa6c46b431005046a285ce905814cac0ff8fea'
// ]
//
// const result = await bchjs.Ninsight.txDetails(txid)
// // console.log(`result: ${JSON.stringify(result, null, 2)}`)
//
// assert.isArray(result)
// assert.property(result[0], 'txid')
// assert.property(result[0], 'vin')
// assert.property(result[0], 'vout')
// })
// })
})
function sleep (ms) {
+29
View File
@@ -119,6 +119,33 @@ const mockTokens = [
}
]
const mockNftChildrenList = {
nftChildren: [
'45a30085691d6ea586e3ec2aa9122e9b0e0d6c3c1fd357decccc15d8efde48a9',
'928ce61fe1006b1325a0ba0dce700bf83986a6f0691ba26e121c9ac035d12a55'
]
}
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',
@@ -1388,6 +1415,8 @@ module.exports = {
mockList,
mockToken,
mockTokens,
mockNftChildrenList,
mockNftGroup,
balancesForAddress,
balancesForAddresses,
mockRawTx,
+93 -2
View File
@@ -4,7 +4,7 @@
const assert = require('chai').assert
const sinon = require('sinon')
// const axios = require("axios")
const axios = require('axios')
// Default to unit tests unless some other value for TEST is passed.
if (!process.env.TEST) process.env.TEST = 'unit'
@@ -14,7 +14,7 @@ const BCHJS = require('../../src/bch-js')
const bchjs = new BCHJS()
// Mock data used for unit tests
// const mockData = require("./fixtures/slp/mock-utils")
const mockData = require('./fixtures/slp/mock-utils')
// Default to unit tests unless some other value for TEST is passed.
if (!process.env.TEST) process.env.TEST = 'unit'
@@ -253,4 +253,95 @@ describe('#SLP NFT1', () => {
assert.isNumber(result.outputs)
})
})
describe('#listNFTGroupChildren', () => {
it('should throw an error for improper input', async () => {
try {
const groupId = 12345
await bchjs.SLP.NFT1.listNFTGroupChildren(groupId)
assert.equal(true, false, 'Unexpected result!')
} catch (err) {
// console.log(`err: `, err)
assert.include(
err.message,
'groupId must be a string'
)
}
})
it('should handle API response error', async () => {
try {
const error = new Error()
error.response = {
error: 'NFT group does not exists'
}
sandbox.stub(axios, 'get').throws(error)
const groupId = 'non-exists'
await bchjs.SLP.NFT1.listNFTGroupChildren(groupId)
} catch (err) {
assert.include(
err.response,
{ error: 'NFT group does not exists' }
)
}
})
it('should return array of children GENESIS transactions IDs', async () => {
sandbox.stub(axios, 'get').resolves({ data: mockData.mockNftChildrenList })
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 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')
})
})
})