Skip to content

Commit

Permalink
Merge pull request #98 from nevermined-io/feature/balance
Browse files Browse the repository at this point in the history
Adding NFT balance command
  • Loading branch information
aaitor authored May 2, 2023
2 parents 8b595cc + a0e4855 commit 4c275e0
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 50 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ jobs:
yarn build
yarn start --help
- uses: nevermined-io/nvm-tools-actions@v0.9.0
- uses: nevermined-io/nvm-tools-actions@v0.10.0
with:
token: ${{ secrets.API_TOKEN_GITHUB }}
opengsn: "true"
estuary: "true"
contracts-version: "v3.0.0"
opengsn: 'true'
estuary: 'true'
contracts-version: 'v3.2.1'
- name: Check artifacts and circuits
run: |
nvm-tools copy-artifacts /tmp/.nevermined/artifacts
Expand All @@ -41,14 +41,14 @@ jobs:
- name: Run integration tests
env:
LOCAL_CONF_DIR: "/tmp/.nevermined"
LOCAL_CONF_DIR: '/tmp/.nevermined'
SEED_WORDS: ${{ secrets.TEST_MNEMONIC }}
TOKEN_ADDRESS: "0x0000000000000000000000000000000000000000"
WEB3_PROVIDER_URL: "http://contracts.nevermined.localnet"
NETWORK: "geth-localnet"
TOKEN_ADDRESS: '0x0000000000000000000000000000000000000000'
WEB3_PROVIDER_URL: 'http://contracts.nevermined.localnet'
NETWORK: 'geth-localnet'
IPFS_PROJECT_ID: ${{ secrets.IPFS_PROJECT_ID }}
IPFS_PROJECT_SECRET: ${{ secrets.IPFS_PROJECT_SECRET }}
NO_GRAPH: "true"
NO_GRAPH: 'true'
run: |
yarn test:integration
- name: Upload logs
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nevermined-io/cli",
"version": "1.1.1",
"version": "1.2.0",
"main": "index.js",
"repository": "[email protected]:nevermined-io/cli.git",
"author": "Nevermined",
Expand All @@ -24,8 +24,8 @@
"ncli": "./dist/src/index.js"
},
"dependencies": {
"@nevermined-io/sdk": "1.3.3",
"@nevermined-io/sdk-dtp": "0.4.4",
"@nevermined-io/sdk": "1.3.6",
"@nevermined-io/sdk-dtp": "0.4.7",
"@truffle/hdwallet-provider": "^2.0.9",
"chalk": "^4.1.2",
"cross-fetch": "~3.1.5",
Expand Down
57 changes: 55 additions & 2 deletions resources/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@
}, {
"name": "clone [nftAddress]",
"description": "It clones an existing NFT (ERC-721) contract",
"details": "Nevermined Smart Contracts are deployed in a blockchain, with this command it's possible to clone the implementation of an already deployed Smart Contract. The new contract clonned will be owned by the user doing that clonning action.",
"details": "Nevermined Smart Contracts are deployed in a blockchain, with this command it's possible to clone the implementation of an already deployed Smart Contract. The new contract cloned will be owned by the user doing that clonning action.",
"examples": ["ncli nfts721 clone 0x37BB53e3d293494DE59fBe1FF78500423dcFd43B --params 'Token Name' --params 'SYMBOL'"],
"commandHandler": "cloneNft",
"positionalArguments": [{
Expand Down Expand Up @@ -983,6 +983,31 @@
"description": "The NFT type"
}
]
}, {
"name": "balance [nftAddress]",
"description": "It gets the balance of a NFT",
"details": "This command allows to check if an address is a holder of a specific NFT wrapped by a Nevermined DID",
"examples": ["ncli nfts721 hold did:nv:afd733c23c41af948be7ec039c3fb2048d437e082a69ea3f336cdf452a49be7e"],
"commandHandler": "balanceNft",
"positionalArguments": [{
"name": "nftAddress",
"type": "string",
"description": "The NFT contract address"
}],
"optionalArguments": [{
"name": "address",
"type": "string",
"default": "",
"description": "The address of the account to get the balance"
},
{
"name": "nftType",
"type": "number",
"default": "721",
"hidden": true,
"description": "The NFT type"
}
]
}, {
"name": "mint [did]",
"description": "Mints a ERC-721 NFT",
Expand Down Expand Up @@ -1210,7 +1235,7 @@
}, {
"name": "clone [nftAddress]",
"description": "It clones an existing NFT (ERC-1155) contract",
"details": "Nevermined Smart Contracts are deployed in a blockchain, with this command it's possible to clone the implementation of an already deployed Smart Contract. The new contract clonned will be owned by the user doing that clonning action.",
"details": "Nevermined Smart Contracts are deployed in a blockchain, with this command it's possible to clone the implementation of an already deployed Smart Contract. The new contract cloned will be owned by the user doing that clonning action.",
"examples": ["ncli nfts1155 clone 0x37BB53e3d293494DE59fBe1FF78500423dcFd43B --params 'Token Name' --params 'SYMBOL'"],
"commandHandler": "cloneNft",
"positionalArguments": [{
Expand Down Expand Up @@ -1396,6 +1421,34 @@
"description": "The NFT type"
}
]
}, {
"name": "balance [nftAddress] [did]",
"description": "It gets the balance of a NFT",
"details": "This command allows to check if an address is a holder of a specific NFT wrapped by a Nevermined DID",
"examples": ["ncli nfts1155 balance 0xF841Ff2C8abF1751A83923755EbD2F66bBAa5BFE did:nv:afd733c23c41af948be7ec039c3fb2048d437e082a69ea3f336cdf452a49be7e"],
"commandHandler": "balanceNft",
"positionalArguments": [{
"name": "nftAddress",
"type": "string",
"description": "The NFT contract address"
}, {
"name": "did",
"type": "string",
"description": "The asset DID"
}],
"optionalArguments": [{
"name": "address",
"type": "string",
"default": "",
"description": "The address of the account to get the balance"
}, {
"name": "nftType",
"type": "number",
"default": "1155",
"hidden": true,
"description": "The NFT type"
}
]
}, {
"name": "mint [did]",
"description": "Mints a ERC-1155 NFT",
Expand Down
31 changes: 27 additions & 4 deletions resources/networks.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"nativeToken": "MATIC",
"networkId": "80001",
"networkName": "mumbai",
"contractsVersion": "3.0.0",
"contractsVersion": "3.2.1",
"tagName": "public",
"etherscanUrl": "https://mumbai.polygonscan.com",
"erc20TokenAddress": "0xe11A86849d99F524cAC3E7A0Ec1241828e332C62",
Expand Down Expand Up @@ -178,8 +178,8 @@
"externalNetwork": false
},
"oneMumbai": {
"envDescription": "Nevermined One testnet environment where users can interact with Nevermined protocol.",
"envUrl": "https://nevermined.io/",
"envDescription": "Nevermined One internal environment where Nevermined developers can integrate new versions of the application.",
"envUrl": "https://mumbai.nevermined.one/",
"isProduction": false,
"nvm": {
"web3ProviderUri": "https://matic-mumbai.chainstacklabs.com",
Expand All @@ -192,7 +192,30 @@
"nativeToken": "MATIC",
"networkId": "80001",
"networkName": "mumbai",
"contractsVersion": "3.0.0",
"contractsVersion": "3.2.1",
"tagName": "public",
"etherscanUrl": "https://mumbai.polygonscan.com",
"erc20TokenAddress": "0xe11A86849d99F524cAC3E7A0Ec1241828e332C62",
"gasMultiplier": 0,
"gasPriceMultiplier": 0,
"externalNetwork": false
},
"appMumbai": {
"envDescription": "Nevermined One testnet environment where users can interact with Nevermined protocol.",
"envUrl": "https://mumbai.nevermined.app/",
"isProduction": false,
"nvm": {
"web3ProviderUri": "https://matic-mumbai.chainstacklabs.com",
"marketplaceUri": "https://marketplace-api.mumbai.nevermined.app",
"graphHttpUri": "https://api.thegraph.com/subgraphs/name/nevermined-io/public",
"neverminedNodeUri": "https://node.mumbai.nevermined.app",
"neverminedNodeAddress": "0x5838B5512cF9f12FE9f2beccB20eb47211F9B0bc",
"verbose": true
},
"nativeToken": "MATIC",
"networkId": "80001",
"networkName": "mumbai",
"contractsVersion": "3.2.1",
"tagName": "public",
"etherscanUrl": "https://mumbai.polygonscan.com",
"erc20TokenAddress": "0xe11A86849d99F524cAC3E7A0Ec1241828e332C62",
Expand Down
1 change: 0 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ const cmdHandler = async (

try {
if (requiresAccount) {

nvm = await loadNevermined(config, network, verbose)
if (!nvm.keeper) process.exit(StatusCodes.FAILED_TO_CONNECT)

Expand Down
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './assets/retireDID'
export * from './nfts/cloneNft'
export * from './nfts/deployNft'
export * from './nfts/createNft'
export * from './nfts/balanceNft'
export * from './nfts/holdNft'
export * from './nfts/mintNft'
export * from './nfts/showNft'
Expand Down
43 changes: 43 additions & 0 deletions src/commands/nfts/balanceNft.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Account, didZeroX, Nevermined, zeroX } from '@nevermined-io/sdk'
import { StatusCodes } from '../../utils'
import { ExecutionOutput } from '../../models/ExecutionOutput'
import chalk from 'chalk'
import { Logger } from 'log4js'
import { ConfigEntry } from '../../models/ConfigDefinition'

export const balanceNft = async (
nvm: Nevermined,
consumerAccount: Account,
argv: any,
config: ConfigEntry,
logger: Logger
): Promise<ExecutionOutput> => {
const { nftAddress } = argv

const nftType = Number(argv.nftType)

let balance
const userAddress = argv.address ? argv.address : consumerAccount.getId()

logger.info(
chalk.dim(`Gets the balance of the account ${userAddress} for the NFT-${nftType} with address ${chalk.whiteBright(nftAddress)}`)
)

if (nftType === 721) {
const nft = await nvm.contracts.loadNft721(nftAddress)
balance = await nft.balanceOf(userAddress)
logger.info(`The user holds ${balance} token/s of the ERC-${nftType} NFT`)
} else {
const nft = await nvm.contracts.loadNft1155Contract(nftAddress)
balance = await nft.balance(userAddress, zeroX(didZeroX(argv.did)))
logger.info(`The user holds ${balance} edition/s of the ERC-${nftType} NFT`)
}

return {
status: StatusCodes.OK,
results: JSON.stringify({
balance
})
}

}
28 changes: 22 additions & 6 deletions src/commands/nfts/cloneNft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,38 @@ export const cloneNft = async (
logger: Logger
): Promise<ExecutionOutput> => {

const { nftAddress, nftType } = argv
const { nftAddress } = argv

logger.info(chalk.dim(`Clonning NFT contract from address ${nftAddress}...`))

const nftType = Number(argv.nftType) === 721 ? 721 : 1155

if (!ethers.utils.isAddress(nftAddress))
return {
status: StatusCodes.ERROR,
errorMessage: `Invalid contract address ${nftAddress}`
}

const operators: string[] = []

argv.operators.forEach((_operator: string) => {
if (ethers.utils.isAddress(_operator)) operators.push(_operator)
})

let clonnedAddress

if (nftType == 721) {
logger.debug(`Clonning NFT-${nftType} using params:`)
logger.debug(`\tName: ${argv.name}`)
logger.debug(`\tSymbol: ${argv.symbol}`)
logger.debug(`\tURI: ${argv.uri}`)
logger.debug(`\tCap: ${argv.cap}`)

if (nftType === 721) {
if (!operators.includes(nvm.keeper.conditions.transferNft721Condition.getAddress()))
operators.push(nvm.keeper.conditions.transferNft721Condition.getAddress())

logger.debug(`\tOperators: ${JSON.stringify(operators)}`)

await nvm.contracts.loadNft721(nftAddress)
clonnedAddress = await nvm.nfts721.getContract.createClone(
argv.name,
Expand All @@ -44,18 +58,20 @@ export const cloneNft = async (
creatorAccount
)
} else {
await nvm.contracts.loadNft721(nftAddress)
clonnedAddress = await nvm.nfts721.getContract.createClone(
if (!operators.includes(nvm.keeper.conditions.transferNftCondition.getAddress()))
operators.push(nvm.keeper.conditions.transferNftCondition.getAddress())

await nvm.contracts.loadNft1155(nftAddress)
clonnedAddress = await nvm.nfts1155.getContract.createClone(
argv.name,
argv.symbol,
argv.uri,
BigNumber.from(argv.cap),
operators,
creatorAccount
)
}

logger.info(`Contract clonned into address: ${clonnedAddress}\n`)
logger.info(`Contract cloned at address: ${clonnedAddress}\n`)

return {
status: StatusCodes.OK,
Expand Down
25 changes: 15 additions & 10 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,23 @@ export const loadNevermined = async (
network: string,
verbose = false
): Promise<Nevermined> => {

const nvm = await Nevermined.getInstance({
...config.nvm,
verbose: verbose ? verbose : config.nvm.verbose
})
if (!nvm.keeper) {
logger.error(
chalk.red(`ERROR: Nevermined could not connect to '${network}'\n`)
)
try {
logger.log(JSON.stringify(config.nvm.web3ProviderUri))
const nvm = await Nevermined.getInstance({
...config.nvm,
verbose: verbose ? verbose : config.nvm.verbose
})
if (!nvm.keeper) {
logger.error(
chalk.red(`ERROR: Nevermined could not connect to '${network}'\n`)
)
}
return nvm
} catch (error) {
logger.error(chalk.red(`ERROR: ${(error as Error).message}\n`))
process.exit(1)
}

return nvm
}

export const loginMarketplaceApi = async (
Expand Down
2 changes: 2 additions & 0 deletions test/helpers/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const baseCommands = {
show: `${BASE_COMMAND} ${VERBOSE} nfts721 show `,
mint: `${BASE_COMMAND} ${VERBOSE} nfts721 mint `,
hold: `${BASE_COMMAND} ${VERBOSE} nfts721 hold `,
balance: `${BASE_COMMAND} ${VERBOSE} nfts721 balance `,
burn: `${BASE_COMMAND} ${VERBOSE} nfts721 burn `,
order: `${BASE_COMMAND} ${VERBOSE} nfts721 order `,
claim: `${BASE_COMMAND} ${VERBOSE} nfts721 claim `,
Expand All @@ -84,6 +85,7 @@ export const baseCommands = {
create: `${BASE_COMMAND} ${VERBOSE} nfts1155 create `,
show: `${BASE_COMMAND} ${VERBOSE} nfts1155 show `,
hold: `${BASE_COMMAND} ${VERBOSE} nfts1155 hold `,
balance: `${BASE_COMMAND} ${VERBOSE} nfts721 balance `,
mint: `${BASE_COMMAND} ${VERBOSE} nfts1155 mint `,
burn: `${BASE_COMMAND} ${VERBOSE} nfts1155 burn `,
order: `${BASE_COMMAND} ${VERBOSE} nfts1155 order `,
Expand Down
9 changes: 9 additions & 0 deletions test/helpers/StdoutParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const commandRegex = {
},
nfts: {
deploy: new RegExp('.*Contract deployed into address: (.{42}).*', 'gm'),
clone: new RegExp('.*Contract cloned at address: (.{42}).*', 'gm'),
create: new RegExp('.*Created DID: (.{71}).*', 'gm'),
publishMetadata: new RegExp('.*NFT Metadata Created: (.*)', 'gm'),
order: new RegExp('.*NFT Agreement Created: (.{66})', 'g')
Expand Down Expand Up @@ -158,3 +159,11 @@ export const parseAddressOfContractDeployed = (stdout: string): string => {
}
return ''
}

export const parseAddressOfContractCloned = (stdout: string): string => {
const parsed = commandRegex.nfts.clone.exec(stdout)
if (parsed != null) {
return parsed[1]
}
return ''
}
Loading

0 comments on commit 4c275e0

Please sign in to comment.