--- /dev/null +++ b/tests/src/eth/collections/callMethodsERC20.test.ts @@ -0,0 +1,91 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {Pallets, requirePalletsOrSkip} from '../../util'; +import {expect, itEth, usingEthPlaygrounds} from '../util'; +import {IKeyringPair} from '@polkadot/types/types'; + +[ + {mode: 'ft' as const, requiredPallets: []}, + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, +].map(testCase => { + describe(`${testCase.mode.toUpperCase()}: ERC-20 call methods`, () => { + let donor: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, testCase.requiredPallets); + donor = await privateKey({filename: __filename}); + }); + }); + + itEth('totalSupply', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const mintingParams = testCase.mode === 'ft' ? [caller, 200n] : [caller]; + + const {collection, collectionId} = await helper.eth.createCollection(testCase.mode, caller, 'TotalSupply', '6', '6'); + if (testCase.mode === 'rft') await collection.methods.mint(caller).send({from: caller}); + + // Use collection contract for FT or token contract for RFT: + const contract = testCase.mode === 'ft' + ? collection + : await helper.ethNativeContract.rftTokenById(collectionId, 1, caller); + + // Mint tokens: + testCase.mode === 'ft' + ? await contract.methods.mint(...mintingParams).send({from: caller}) + : await contract.methods.repartition(200).send({from: caller}); + + const totalSupply = await contract.methods.totalSupply().call(); + expect(totalSupply).to.equal('200'); + }); + + itEth('balanceOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const mintingParams = testCase.mode === 'ft' ? [caller, 200n] : [caller]; + + const {collection, collectionId} = await helper.eth.createCollection(testCase.mode, caller, 'BalanceOf', 'Descroption', 'Prefix'); + if (testCase.mode === 'rft') await collection.methods.mint(caller).send({from: caller}); + + // Use collection contract for FT or token contract for RFT: + const contract = testCase.mode === 'ft' + ? collection + : await helper.ethNativeContract.rftTokenById(collectionId, 1, caller); + + // Mint tokens: + testCase.mode === 'ft' + ? await contract.methods.mint(...mintingParams).send({from: caller}) + : await contract.methods.repartition(200).send({from: caller}); + + const balance = await contract.methods.balanceOf(caller).call(); + expect(balance).to.equal('200'); + }); + + itEth('decimals', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collection, collectionId} = await helper.eth.createCollection(testCase.mode, caller, 'BalanceOf', 'Descroption', 'Prefix'); + if (testCase.mode === 'rft') await collection.methods.mint(caller).send({from: caller}); + + // Use collection contract for FT or token contract for RFT: + const contract = testCase.mode === 'ft' + ? collection + : await helper.ethNativeContract.rftTokenById(collectionId, 1, caller); + + const decimals = await contract.methods.decimals().call(); + expect(decimals).to.equal(testCase.mode === 'rft' ? '0' : '18'); + }); + }); +}); \ No newline at end of file --- /dev/null +++ b/tests/src/eth/collections/callMethodsERC721.test.ts @@ -0,0 +1,127 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {Pallets, requirePalletsOrSkip} from '../../util'; +import {expect, itEth, usingEthPlaygrounds} from '../util'; +import {IKeyringPair} from '@polkadot/types/types'; + +[ + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, + {mode: 'nft' as const, requiredPallets: []}, +].map(testCase => { + describe(`${testCase.mode.toUpperCase()}: ERC-721 call methods`, () => { + let donor: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, testCase.requiredPallets); + + donor = await privateKey({filename: __filename}); + }); + }); + + itEth('name/symbol/description', async ({helper}) => { + const callerEth = await helper.eth.createAccountWithBalance(donor); + const [callerSub] = await helper.arrange.createAccounts([100n], donor); + const [name, description, tokenPrefix] = ['Name', 'Description', 'Symbol']; + + const {collection: collectionEth} = await helper.eth.createCollection(testCase.mode, callerEth, name, description, tokenPrefix); + await collectionEth.methods.mint(callerEth).send({from: callerEth}); + const {collectionId} = await helper[testCase.mode].mintCollection(callerSub, {name, description, tokenPrefix}); + const collectionSub = await helper.ethNativeContract.collectionById(collectionId, testCase.mode, callerEth); + + // Can get name/symbol/description for Eth collection + expect(await collectionEth.methods.name().call()).to.eq(name); + expect(await collectionEth.methods.symbol().call()).to.eq(tokenPrefix); + expect(await collectionEth.methods.description().call()).to.eq(description); + // Can get name/symbol/description for Sub collection + expect(await collectionSub.methods.name().call()).to.eq(name); + expect(await collectionSub.methods.symbol().call()).to.eq(tokenPrefix); + expect(await collectionSub.methods.description().call()).to.eq(description); + }); + + itEth('totalSupply', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + + const {collection} = await helper.eth.createCollection(testCase.mode, caller, 'TotalSupply', '6', '6'); + await collection.methods.mint(caller).send({from: caller}); + + const totalSupply = await collection.methods.totalSupply().call(); + expect(totalSupply).to.equal('1'); + }); + + itEth('balanceOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + + const {collection} = await helper.eth.createCollection(testCase.mode, caller, 'BalanceOf', 'Descroption', 'Prefix'); + await collection.methods.mint(caller).send({from: caller}); + await collection.methods.mint(caller).send({from: caller}); + await collection.methods.mint(caller).send({from: caller}); + + const balance = await collection.methods.balanceOf(caller).call(); + expect(balance).to.equal('3'); + }); + + itEth('ownerOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collection} = await helper.eth.createCollection(testCase.mode, caller, 'OwnerOf', '6', '6'); + + const result = await collection.methods.mint(caller).send(); + const tokenId = result.events.Transfer.returnValues.tokenId; + + const owner = await collection.methods.ownerOf(tokenId).call(); + expect(owner).to.equal(caller); + }); + + // TODO move to rft tests: + // itEth('ownerOf after burn', async ({helper}) => { + // const caller = await helper.eth.createAccountWithBalance(donor); + // const receiver = helper.eth.createAccount(); + // const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6'); + // const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + + // const result = await contract.methods.mint(caller).send(); + // const tokenId = result.events.Transfer.returnValues.tokenId; + // const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + + // await tokenContract.methods.repartition(2).send(); + // await tokenContract.methods.transfer(receiver, 1).send(); + + // await tokenContract.methods.burnFrom(caller, 1).send(); + + // const owner = await contract.methods.ownerOf(tokenId).call(); + // expect(owner).to.equal(receiver); + // }); + + // TODO move to rft tests: + // itEth('ownerOf for partial ownership', async ({helper}) => { + // const caller = await helper.eth.createAccountWithBalance(donor); + // const receiver = helper.eth.createAccount(); + // const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6'); + // const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + + // const result = await contract.methods.mint(caller).send(); + // const tokenId = result.events.Transfer.returnValues.tokenId; + // const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + + // await tokenContract.methods.repartition(2).send(); + // await tokenContract.methods.transfer(receiver, 1).send(); + + // const owner = await contract.methods.ownerOf(tokenId).call(); + // expect(owner).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); + // }); + }); +}); --- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -17,38 +17,6 @@ import {expect, itEth, usingEthPlaygrounds} from './util'; import {IKeyringPair} from '@polkadot/types/types'; -describe('Fungible: Information getting', () => { - let donor: IKeyringPair; - let alice: IKeyringPair; - - before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { - donor = await privateKey({filename: __filename}); - [alice] = await helper.arrange.createAccounts([20n], donor); - }); - }); - - itEth('totalSupply', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const collection = await helper.ft.mintCollection(alice); - await collection.mint(alice, 200n); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); - const totalSupply = await contract.methods.totalSupply().call(); - expect(totalSupply).to.equal('200'); - }); - - itEth('balanceOf', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const collection = await helper.ft.mintCollection(alice); - await collection.mint(alice, 200n, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); - const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('200'); - }); -}); - describe('Fungible: Plain calls', () => { let donor: IKeyringPair; let alice: IKeyringPair; --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -19,68 +19,6 @@ import {Contract} from 'web3-eth-contract'; import {ITokenPropertyPermission} from '../util/playgrounds/types'; - -describe('NFT: Information getting', () => { - let donor: IKeyringPair; - let alice: IKeyringPair; - - before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { - donor = await privateKey({filename: __filename}); - [alice] = await helper.arrange.createAccounts([10n], donor); - }); - }); - - itEth('totalSupply', async ({helper}) => { - const collection = await helper.nft.mintCollection(alice, {}); - await collection.mintToken(alice); - - const caller = await helper.eth.createAccountWithBalance(donor); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); - const totalSupply = await contract.methods.totalSupply().call(); - - expect(totalSupply).to.equal('1'); - }); - - itEth('balanceOf', async ({helper}) => { - const collection = await helper.nft.mintCollection(alice, {}); - const caller = await helper.eth.createAccountWithBalance(donor); - - await collection.mintToken(alice, {Ethereum: caller}); - await collection.mintToken(alice, {Ethereum: caller}); - await collection.mintToken(alice, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); - const balance = await contract.methods.balanceOf(caller).call(); - - expect(balance).to.equal('3'); - }); - - itEth('ownerOf', async ({helper}) => { - const collection = await helper.nft.mintCollection(alice, {}); - const caller = await helper.eth.createAccountWithBalance(donor); - - const token = await collection.mintToken(alice, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); - - const owner = await contract.methods.ownerOf(token.tokenId).call(); - - expect(owner).to.equal(caller); - }); - - itEth('name/symbol is available regardless of ERC721Metadata support', async ({helper}) => { - const collection = await helper.nft.mintCollection(alice, {name: 'test', tokenPrefix: 'TEST'}); - const caller = helper.eth.createAccount(); - - const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); - - expect(await contract.methods.name().call()).to.equal('test'); - expect(await contract.methods.symbol().call()).to.equal('TEST'); - }); -}); - describe('Check ERC721 token URI for NFT', () => { let donor: IKeyringPair; --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -19,90 +19,6 @@ import {IKeyringPair} from '@polkadot/types/types'; import {ITokenPropertyPermission} from '../util/playgrounds/types'; -describe('Refungible: Information getting', () => { - let donor: IKeyringPair; - - before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { - requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - - donor = await privateKey({filename: __filename}); - }); - }); - - itEth('totalSupply', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'TotalSupply', '6', '6'); - const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); - - await contract.methods.mint(caller).send(); - - const totalSupply = await contract.methods.totalSupply().call(); - expect(totalSupply).to.equal('1'); - }); - - itEth('balanceOf', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'BalanceOf', '6', '6'); - const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); - - await contract.methods.mint(caller).send(); - await contract.methods.mint(caller).send(); - await contract.methods.mint(caller).send(); - - const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('3'); - }); - - itEth('ownerOf', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf', '6', '6'); - const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); - - const result = await contract.methods.mint(caller).send(); - const tokenId = result.events.Transfer.returnValues.tokenId; - - const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal(caller); - }); - - itEth('ownerOf after burn', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const receiver = helper.eth.createAccount(); - const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6'); - const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); - - const result = await contract.methods.mint(caller).send(); - const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); - - await tokenContract.methods.repartition(2).send(); - await tokenContract.methods.transfer(receiver, 1).send(); - - await tokenContract.methods.burnFrom(caller, 1).send(); - - const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal(receiver); - }); - - itEth('ownerOf for partial ownership', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const receiver = helper.eth.createAccount(); - const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6'); - const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); - - const result = await contract.methods.mint(caller).send(); - const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); - - await tokenContract.methods.repartition(2).send(); - await tokenContract.methods.transfer(receiver, 1).send(); - - const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); - }); -}); - describe('Refungible: Plain calls', () => { let donor: IKeyringPair; let minter: IKeyringPair; --- a/tests/src/eth/reFungibleToken.test.ts +++ b/tests/src/eth/reFungibleToken.test.ts @@ -19,51 +19,6 @@ import {IKeyringPair} from '@polkadot/types/types'; import {Contract} from 'web3-eth-contract'; - -describe('Refungible token: Information getting', () => { - let donor: IKeyringPair; - let alice: IKeyringPair; - - before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { - requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - - donor = await privateKey({filename: __filename}); - [alice] = await helper.arrange.createAccounts([20n], donor); - }); - }); - - itEth('totalSupply', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); - const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); - const totalSupply = await contract.methods.totalSupply().call(); - expect(totalSupply).to.equal('200'); - }); - - itEth('balanceOf', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); - const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); - const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('200'); - }); - - itEth('decimals', async ({helper}) => { - const caller = await helper.eth.createAccountWithBalance(donor); - const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); - const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - - const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); - const decimals = await contract.methods.decimals().call(); - expect(decimals).to.equal('0'); - }); -}); - // FIXME: Need erc721 for ReFubgible. describe('Check ERC721 token URI for ReFungible', () => { let donor: IKeyringPair; --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -255,7 +255,7 @@ } } - async createCollection(mode: TCollectionMode, signer: string, name: string, description: string, tokenPrefix: string, decimals = 18): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { + async createCollection(mode: TCollectionMode, signer: string, name: string, description: string, tokenPrefix: string, decimals = 18, mergeDeprecated = false): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[], collection: Contract }> { const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice(); const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(signer); const functionName: string = this.createCollectionMethodName(mode); @@ -266,8 +266,9 @@ const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress); const events = this.helper.eth.normalizeEvents(result.events); + const collection = await this.helper.ethNativeContract.collectionById(collectionId, mode, signer, mergeDeprecated); - return {collectionId, collectionAddress, events}; + return {collectionId, collectionAddress, events, collection}; } createNFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {