difftreelog
Merge pull request #612 from UniqueNetwork/tests/eth-tokens
in: master
Tests (Eth): NFT, RFT & FT tests refactored for Playgrounds
6 files changed
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -87,8 +87,11 @@
"testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts",
"testEthCreateNFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createNFTCollection.test.ts",
"testEthCreateRFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createRFTCollection.test.ts",
+ "testEthNFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/nonFungible.test.ts",
"testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts",
+ "testEthRFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/reFungible.test.ts ./**/eth/reFungibleToken.test.ts",
"testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts",
+ "testEthFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/fungible.test.ts",
"testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts",
"testPromotion": "mocha --timeout 9999999 -r ts-node/register ./**/app-promotion.test.ts",
"polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json",
tests/src/eth/fungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -14,204 +14,132 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {approveExpectSuccess, createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
-import fungibleAbi from './fungibleAbi.json';
-import {expect} from 'chai';
-import {submitTransactionAsync} from '../substrate/substrate-api';
+import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
+import {IKeyringPair} from '@polkadot/types/types';
describe('Fungible: Information getting', () => {
- itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const alice = privateKeyWrapper('//Alice');
+ });
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ itEth('totalSupply', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n);
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller);
const totalSupply = await contract.methods.totalSupply().call();
-
expect(totalSupply).to.equal('200');
});
- itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
+ 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 caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller);
const balance = await contract.methods.balanceOf(caller).call();
-
expect(balance).to.equal('200');
});
});
describe('Fungible: Plain calls', () => {
- itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
- const collection = await createCollection(api, alice, {
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
+ });
- const receiver = createEthAccount(web3);
+ itEth('Can perform mint()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.addAdmin(alice, {Ethereum: owner});
- const collectionIdAddress = collectionIdToAddress(collection.collectionId);
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
- await submitTransactionAsync(alice, changeAdminTx);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
- const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
- const result = await collectionContract.methods.mint(receiver, 100).send();
- const events = normalizeEvents(result.events);
+ const result = await contract.methods.mint(receiver, 100).send();
- expect(events).to.be.deep.equal([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- value: '100',
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.value).to.equal('100');
});
-
- itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
- const collection = await createCollection(api, alice, {
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver1 = createEthAccount(web3);
- const receiver2 = createEthAccount(web3);
- const receiver3 = createEthAccount(web3);
-
- const collectionIdAddress = collectionIdToAddress(collection.collectionId);
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
- await submitTransactionAsync(alice, changeAdminTx);
+ itEth('Can perform mintBulk()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const bulkSize = 3;
+ const receivers = [...new Array(bulkSize)].map(() => helper.eth.createAccount());
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.addAdmin(alice, {Ethereum: owner});
- const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
- const result = await collectionContract.methods.mintBulk([
- [receiver1, 10],
- [receiver2, 20],
- [receiver3, 30],
- ]).send();
- const events = normalizeEvents(result.events);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
- expect(events).to.be.deep.contain({
- address:collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver1,
- value: '10',
- },
- });
-
- expect(events).to.be.deep.contain({
- address:collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver2,
- value: '20',
- },
- });
-
- expect(events).to.be.deep.contain({
- address:collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver3,
- value: '30',
- },
- });
+ const result = await contract.methods.mintBulk(Array.from({length: bulkSize}, (_, i) => (
+ [receivers[i], (i + 1) * 10]
+ ))).send();
+ const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.value - b.returnValues.value);
+ for (let i = 0; i < bulkSize; i++) {
+ const event = events[i];
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal(receivers[i]);
+ expect(event.returnValues.value).to.equal(String(10 * (i + 1)));
+ }
});
- itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
- const collection = await createCollection(api, alice, {
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
-
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
- await submitTransactionAsync(alice, changeAdminTx);
- const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ itEth('Can perform burn()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.addAdmin(alice, {Ethereum: owner});
- const collectionIdAddress = collectionIdToAddress(collection.collectionId);
- const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
- await collectionContract.methods.mint(receiver, 100).send();
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
+ await contract.methods.mint(receiver, 100).send();
- const result = await collectionContract.methods.burnFrom(receiver, 49).send({from: receiver});
+ const result = await contract.methods.burnFrom(receiver, 49).send({from: receiver});
- const events = normalizeEvents(result.events);
-
- expect(events).to.be.deep.equal([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: receiver,
- to: '0x0000000000000000000000000000000000000000',
- value: '49',
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(receiver);
+ expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.value).to.equal('49');
- const balance = await collectionContract.methods.balanceOf(receiver).call();
+ const balance = await contract.methods.balanceOf(receiver).call();
expect(balance).to.equal('51');
});
- itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('Can perform approve()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
-
- const spender = createEthAccount(web3);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
{
const result = await contract.methods.approve(spender, 100).send({from: owner});
- const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner,
- spender,
- value: '100',
- },
- },
- ]);
+ const event = result.events.Approval;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(owner);
+ expect(event.returnValues.spender).to.be.equal(spender);
+ expect(event.returnValues.value).to.be.equal('100');
}
{
@@ -220,51 +148,32 @@
}
});
- itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
-
- const spender = createEthAccount(web3);
- await transferBalanceToEth(api, alice, spender);
-
- const receiver = createEthAccount(web3);
+ itEth('Can perform transferFrom()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
await contract.methods.approve(spender, 100).send();
{
const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});
- const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- value: '49',
- },
- },
- {
- address,
- event: 'Approval',
- args: {
- owner,
- spender,
- value: '51',
- },
- },
- ]);
+
+ let event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('49');
+
+ event = result.events.Approval;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(owner);
+ expect(event.returnValues.spender).to.be.equal(spender);
+ expect(event.returnValues.value).to.be.equal('51');
}
{
@@ -278,38 +187,23 @@
}
});
- itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
-
- const receiver = createEthAccount(web3);
- await transferBalanceToEth(api, alice, receiver);
+ itEth('Can perform transfer()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
{
const result = await contract.methods.transfer(receiver, 50).send({from: owner});
- const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- value: '50',
- },
- },
- ]);
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('50');
}
{
@@ -325,162 +219,141 @@
});
describe('Fungible: Fees', () => {
- itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const alice = privateKeyWrapper('//Alice');
+ });
+
+ itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = createEthAccount(web3);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
- const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
- itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
+ itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
await contract.methods.approve(spender, 100).send({from: owner});
- const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
-
- itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
-
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
+ itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
- const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
});
describe('Fungible: Substrate calls', () => {
- itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const alice = privateKeyWrapper('//Alice');
+ });
- const receiver = createEthAccount(web3);
+ itEth('Events emitted for approve()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n);
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address);
-
- const events = await recordEvents(contract, async () => {
- await approveExpectSuccess(collection, 0, alice, {Ethereum: receiver}, 100);
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
+ await collection.approveTokens(alice, {Ethereum: receiver}, 100n);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner: subToEth(alice.address),
- spender: receiver,
- value: '100',
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Approval');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.spender).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('100');
});
- itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
+ itEth('Events emitted for transferFrom()', async ({helper}) => {
+ const [bob] = await helper.arrange.createAccounts([10n], donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n);
+ await collection.approveTokens(alice, {Substrate: bob.address}, 100n);
- const receiver = createEthAccount(web3);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});
- await approveExpectSuccess(collection, 0, alice, bob.address, 100);
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
+ await collection.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}, 51n);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address);
+ let event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('51');
- const events = await recordEvents(contract, async () => {
- await transferFromExpectSuccess(collection, 0, bob, alice, {Ethereum: receiver}, 51, 'Fungible');
- });
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- value: '51',
- },
- },
- {
- address,
- event: 'Approval',
- args: {
- owner: subToEth(alice.address),
- spender: subToEth(bob.address),
- value: '49',
- },
- },
- ]);
+ event = events[1];
+ expect(event.event).to.be.equal('Approval');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address));
+ expect(event.returnValues.value).to.be.equal('49');
});
- itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'Fungible', decimalPoints: 0},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('Events emitted for transfer()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n);
- const receiver = createEthAccount(web3);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');
- await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(fungibleAbi as any, address);
-
- const events = await recordEvents(contract, async () => {
- await transferExpectSuccess(collection, 0, alice, {Ethereum:receiver}, 51, 'Fungible');
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
+ await collection.transfer(alice, {Ethereum:receiver}, 51n);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- value: '51',
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('51');
});
});
tests/src/eth/nonFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -14,72 +14,78 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
-import nonFungibleAbi from './nonFungibleAbi.json';
-import {expect} from 'chai';
-import {submitTransactionAsync} from '../substrate/substrate-api';
+import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util/playgrounds';
+import {IKeyringPair} from '@polkadot/types/types';
+import {Contract} from 'web3-eth-contract';
describe('NFT: Information getting', () => {
- itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
});
- const alice = privateKeyWrapper('//Alice');
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ });
+
+ itEth('totalSupply', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.mintToken(alice);
- await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
+ const caller = await helper.eth.createAccountWithBalance(donor);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
const totalSupply = await contract.methods.totalSupply().call();
expect(totalSupply).to.equal('1');
});
- itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('balanceOf', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ const caller = await helper.eth.createAccountWithBalance(donor);
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});
- await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
- await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
+ await collection.mintToken(alice, {Ethereum: caller});
+ await collection.mintToken(alice, {Ethereum: caller});
+ await collection.mintToken(alice, {Ethereum: caller});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
const balance = await contract.methods.balanceOf(caller).call();
expect(balance).to.equal('3');
});
- itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('ownerOf', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ const caller = await helper.eth.createAccountWithBalance(donor);
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
+ const token = await collection.mintToken(alice, {Ethereum: caller});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
- const owner = await contract.methods.ownerOf(tokenId).call();
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
+
+ const owner = await contract.methods.ownerOf(token.tokenId).call();
expect(owner).to.equal(caller);
});
});
describe('Check ERC721 token URI for NFT', () => {
- itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress);
+ let donor: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (_helper, privateKey) => {
+ donor = privateKey('//Alice');
+ });
+ });
+
+ async function setup(helper: EthUniqueHelper, tokenPrefix: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
+ let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send();
+ const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
@@ -88,162 +94,73 @@
nextTokenId,
).send();
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
+ if (propertyKey && propertyValue) {
+ // Set URL or suffix
+ await contract.methods.setProperty(nextTokenId, propertyKey, Buffer.from(propertyValue)).send();
+ }
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(nextTokenId);
+ return {contract, nextTokenId};
+ }
+
+ itEth('Empty tokenURI', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, '');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');
});
- itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress);
-
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- // Set URL
- await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ itEth('TokenURI from url', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'url', 'Token URI');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');
});
- itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress);
-
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ itEth('TokenURI from baseURI + tokenId', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId);
});
- itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress);
-
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- // Set suffix
+ itEth('TokenURI from baseURI + suffix', async ({helper}) => {
const suffix = '/some/suffix';
- await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'suffix', suffix);
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);
});
});
describe('NFT: Plain calls', () => {
- itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress);
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
+ });
+ });
+
+ itEth('Can perform mint()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+
+ const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Minty', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mintWithTokenURI(
+ const result = await contract.methods.mintWithTokenURI(
receiver,
nextTokenId,
'Test URI',
).send();
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(nextTokenId);
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
@@ -254,7 +171,8 @@
});
//TODO: CORE-302 add eth methods
- itWeb3.skip('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {
+ /* todo:playgrounds skipped test!
+ itWeb3.skip('Can perform mintBulk()', async ({helper}) => {
const collection = await createCollectionExpectSuccess({
mode: {type: 'NFT'},
});
@@ -316,107 +234,70 @@
expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');
}
});
-
- itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ */
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ itEth('Can perform burn()', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: caller});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);
{
- const result = await contract.methods.burn(tokenId).send({from: owner});
- const events = normalizeEvents(result.events);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: '0x0000000000000000000000000000000000000000',
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const result = await contract.methods.burn(tokenId).send({from: caller});
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(caller);
+ expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
}
});
- itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ itEth('Can perform approve()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
- const spender = createEthAccount(web3);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
{
- const result = await contract.methods.approve(spender, tokenId).send({from: owner, ...GAS_ARGS});
- const events = normalizeEvents(result.events);
+ const result = await contract.methods.approve(spender, tokenId).send({from: owner});
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner,
- approved: spender,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const event = result.events.Approval;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(owner);
+ expect(event.returnValues.approved).to.be.equal(spender);
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
}
});
- itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
+ itEth('Can perform transferFrom()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
-
- const spender = createEthAccount(web3);
- await transferBalanceToEth(api, alice, spender);
-
- const receiver = createEthAccount(web3);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
await contract.methods.approve(spender, tokenId).send({from: owner});
{
const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender});
- const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
}
{
@@ -430,37 +311,24 @@
}
});
- itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ itEth('Can perform transfer()', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
- const receiver = createEthAccount(web3);
- await transferBalanceToEth(api, alice, receiver);
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
{
const result = await contract.methods.transfer(receiver, tokenId).send({from: owner});
- const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
}
{
@@ -476,237 +344,209 @@
});
describe('NFT: Fees', () => {
- itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
});
- const alice = privateKeyWrapper('//Alice');
+ });
+
+ itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = createEthAccount(web3);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
- const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
- itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
-
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);
await contract.methods.approve(spender, tokenId).send({from: owner});
- const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
- itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
- const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
});
describe('NFT: Substrate calls', () => {
- itWeb3('Events emitted for mint()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const alice = privateKeyWrapper('//Alice');
+ });
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ itEth('Events emitted for mint()', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
- let tokenId: number;
- const events = await recordEvents(contract, async () => {
- tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
+ const {tokenId} = await collection.mintToken(alice);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: subToEth(alice.address),
- tokenId: tokenId!.toString(),
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.tokenId).to.be.equal(tokenId.toString());
});
- itWeb3('Events emitted for burn()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
+ itEth('Events emitted for burn()', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice);
+
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
+
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
- const alice = privateKeyWrapper('//Alice');
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ await token.burn(alice);
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
- const events = await recordEvents(contract, async () => {
- await burnItemExpectSuccess(alice, collection, tokenId);
- });
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: '0x0000000000000000000000000000000000000000',
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());
});
- itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('Events emitted for approve()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
- const receiver = createEthAccount(web3);
-
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice);
- const events = await recordEvents(contract, async () => {
- await approveExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1);
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
+
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner: subToEth(alice.address),
- approved: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ await token.approve(alice, {Ethereum: receiver});
+
+ const event = events[0];
+ expect(event.event).to.be.equal('Approval');
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.approved).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());
});
- itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
+ itEth('Events emitted for transferFrom()', async ({helper}) => {
+ const [bob] = await helper.arrange.createAccounts([10n], donor);
+ const receiver = helper.eth.createAccount();
- const receiver = createEthAccount(web3);
-
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
- await approveExpectSuccess(collection, tokenId, alice, bob.address, 1);
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice);
+ await token.approve(alice, {Substrate: bob.address});
- const events = await recordEvents(contract, async () => {
- await transferFromExpectSuccess(collection, tokenId, bob, alice, {Ethereum: receiver}, 1, 'NFT');
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
+
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver});
+
+ const event = events[0];
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);
});
- itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- mode: {type: 'NFT'},
- });
- const alice = privateKeyWrapper('//Alice');
+ itEth('Events emitted for transfer()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
- const receiver = createEthAccount(web3);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice);
- const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
-
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
-
- const events = await recordEvents(contract, async () => {
- await transferExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1, 'NFT');
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
+
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ await token.transfer(alice, {Ethereum: receiver});
+
+ const event = events[0];
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);
});
});
describe('Common metadata', () => {
- itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'NFT'},
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ });
+
+ itEth('Returns collection name', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.nft.mintCollection(alice, {name: 'oh River', tokenPrefix: 'CHANGE'});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
const name = await contract.methods.name().call();
-
- expect(name).to.equal('token name');
+ expect(name).to.equal('oh River');
});
- itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- tokenPrefix: 'TOK',
- mode: {type: 'NFT'},
- });
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ itEth('Returns symbol name', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.nft.mintCollection(alice, {name: 'oh River', tokenPrefix: 'CHANGE'});
- const address = collectionIdToAddress(collection);
- const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
const symbol = await contract.methods.symbol().call();
-
- expect(symbol).to.equal('TOK');
+ expect(symbol).to.equal('CHANGE');
});
});
\ No newline at end of file
tests/src/eth/reFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -14,33 +14,35 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress, uniqueRefungibleToken} from './util/helpers';
-import {expect} from 'chai';
+import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';
+import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
+import {IKeyringPair} from '@polkadot/types/types';
describe('Refungible: Information getting', () => {
+ let donor: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ });
});
- itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('totalSupply', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TotalSupply', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const nextTokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, nextTokenId).send();
const totalSupply = await contract.methods.totalSupply().call();
expect(totalSupply).to.equal('1');
});
- itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('balanceOf', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'BalanceOf', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
{
const nextTokenId = await contract.methods.nextTokenId().call();
@@ -56,38 +58,30 @@
}
const balance = await contract.methods.balanceOf(caller).call();
-
expect(balance).to.equal('3');
});
- itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('ownerOf', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
const owner = await contract.methods.ownerOf(tokenId).call();
-
expect(owner).to.equal(caller);
});
- itWeb3('ownerOf after burn', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('ownerOf after burn', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf-AfterBurn', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
-
- const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
+ const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
@@ -95,80 +89,67 @@
await tokenContract.methods.burnFrom(caller, 1).send();
const owner = await contract.methods.ownerOf(tokenId).call();
-
expect(owner).to.equal(receiver);
});
- itWeb3('ownerOf for partial ownership', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ 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.createRefungibleCollection(caller, 'Partial-OwnerOf', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
-
- const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
+ const tokenContract = 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;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ });
});
- itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
+ itEth('Can perform mint()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Minty', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
const nextTokenId = await contract.methods.nextTokenId().call();
-
expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mintWithTokenURI(
+ const result = await contract.methods.mintWithTokenURI(
receiver,
nextTokenId,
'Test URI',
).send();
- const events = normalizeEvents(result.events);
-
- expect(events).to.include.deep.members([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(nextTokenId);
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
});
- itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('Can perform mintBulk()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'MintBulky', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
- const receiver = createEthAccount(web3);
-
{
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
@@ -180,37 +161,15 @@
[+nextTokenId + 2, 'Test URI 2'],
],
).send();
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: String(+nextTokenId + 1),
- },
- },
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: String(+nextTokenId + 2),
- },
- },
- ]);
+ const events = result.events.Transfer;
+ for (let i = 0; i < 2; i++) {
+ const event = events[i];
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(String(+nextTokenId + i));
+ }
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');
expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');
@@ -218,76 +177,54 @@
}
});
- itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('Can perform burn()', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Burny', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
{
const result = await contract.methods.burn(tokenId).send();
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: caller,
- to: '0x0000000000000000000000000000000000000000',
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
}
});
- itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
-
- const receiver = createEthAccount(web3);
+ itEth('Can perform transferFrom()', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TransferFromy', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
+ const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);
await contract.methods.mint(caller, tokenId).send();
- const address = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = uniqueRefungibleToken(web3, address, caller);
+ const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller);
await tokenContract.methods.repartition(15).send();
{
- const erc20Events = await recordEvents(tokenContract, async () => {
- const result = await contract.methods.transferFrom(caller, receiver, tokenId).send();
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: caller,
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const tokenEvents: any = [];
+ tokenContract.events.allEvents((_: any, event: any) => {
+ tokenEvents.push(event);
});
+ const result = await contract.methods.transferFrom(caller, receiver, tokenId).send();
+
+ let event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
- expect(erc20Events).to.include.deep.members([
- {
- address,
- event: 'Transfer',
- args: {
- from: caller,
- to: receiver,
- value: '15',
- },
- },
- ]);
+ event = tokenEvents[0];
+ expect(event.address).to.equal(tokenAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.value).to.equal('15');
}
{
@@ -301,32 +238,23 @@
}
});
- itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
-
- const receiver = createEthAccount(web3);
+ itEth('Can perform transfer()', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
{
const result = await contract.methods.transfer(receiver, tokenId).send();
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: caller,
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
}
{
@@ -340,141 +268,127 @@
}
});
- itWeb3('transfer event on transfer from partial ownership to full ownership', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Partial-to-Full', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
- const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
+ const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
- const events = await recordEvents(contract, async () =>
- await tokenContract.methods.transfer(receiver, 1).send());
- expect(events).to.deep.equal([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF',
- to: receiver,
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
+ await tokenContract.methods.transfer(receiver, 1).send();
+
+ const event = events[0];
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
});
- itWeb3('transfer event on transfer from full ownership to partial ownership', async ({api, web3, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Full-to-Partial', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
- const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
+ const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller);
await tokenContract.methods.repartition(2).send();
- const events = await recordEvents(contract, async () =>
- await tokenContract.methods.transfer(receiver, 1).send());
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
+ await tokenContract.methods.transfer(receiver, 1).send();
- expect(events).to.deep.equal([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: caller,
- to: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF',
- tokenId: tokenId.toString(),
- },
- },
- ]);
+ const event = events[0];
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
});
});
describe('RFT: Fees', () => {
+ let donor: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ });
});
- itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
-
- const receiver = createEthAccount(web3);
+ itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer-From', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
- const cost = await recordEthFee(api, caller, () => contract.methods.transferFrom(caller, receiver, tokenId).send());
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transferFrom(caller, receiver, tokenId).send());
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
expect(cost > 0n);
});
- itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
-
- const receiver = createEthAccount(web3);
+ itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
- const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send());
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transfer(receiver, tokenId).send());
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
expect(cost > 0n);
});
});
describe('Common metadata', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- });
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- name: 'token name',
- mode: {type: 'ReFungible'},
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
});
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ });
- const address = collectionIdToAddress(collection);
- const contract = evmCollection(web3, caller, address, {type: 'ReFungible'});
+ itEth('Returns collection name', async ({helper}) => {
+ const caller = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice, {name: 'Leviathan', tokenPrefix: '11'});
+
+ const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'rft', caller);
const name = await contract.methods.name().call();
-
- expect(name).to.equal('token name');
+ expect(name).to.equal('Leviathan');
});
- itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => {
- const collection = await createCollectionExpectSuccess({
- tokenPrefix: 'TOK',
- mode: {type: 'ReFungible'},
- });
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- const address = collectionIdToAddress(collection);
- const contract = evmCollection(web3, caller, address, {type: 'ReFungible'});
+ itEth('Returns symbol name', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Leviathan', '', '12');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const symbol = await contract.methods.symbol().call();
-
- expect(symbol).to.equal('TOK');
+ expect(symbol).to.equal('12');
});
});
tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -14,82 +14,76 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRFTCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
+import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';
+import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
+import {IKeyringPair} from '@polkadot/types/types';
+import {Contract} from 'web3-eth-contract';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+describe('Refungible token: Information getting', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
-describe('Refungible token: Information getting', () => {
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- });
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([20n], donor);
+ });
+ });
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
+ 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 address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, caller);
+ const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller);
const totalSupply = await contract.methods.totalSupply().call();
-
expect(totalSupply).to.equal('200');
});
- itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
+ 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 caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, caller);
+ const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller);
const balance = await contract.methods.balanceOf(caller).call();
-
expect(balance).to.equal('200');
});
- itWeb3('decimals', async ({api, web3, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ 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 collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, caller);
+ const contract = 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;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ });
});
- itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
+ async function setup(helper: EthUniqueHelper, tokenPrefix: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
+ let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send();
+ const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
result = await contract.methods.mint(
@@ -97,166 +91,71 @@
nextTokenId,
).send();
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
+ if (propertyKey && propertyValue) {
+ // Set URL or suffix
+ await contract.methods.setProperty(nextTokenId, propertyKey, Buffer.from(propertyValue)).send();
+ }
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(nextTokenId);
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
+ return {contract, nextTokenId};
+ }
+ itEth('Empty tokenURI', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, '');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');
});
-
- itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- // Set URL
- await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ itEth('TokenURI from url', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'url', 'Token URI');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');
});
-
- itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ itEth('TokenURI from baseURI + tokenId', async ({helper}) => {
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_');
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId);
});
- itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const receiver = createEthAccount(web3);
- const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
-
- const nextTokenId = await contract.methods.nextTokenId().call();
- expect(nextTokenId).to.be.equal('1');
- result = await contract.methods.mint(
- receiver,
- nextTokenId,
- ).send();
-
- // Set suffix
+ itEth('TokenURI from baseURI + suffix', async ({helper}) => {
const suffix = '/some/suffix';
- await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();
-
- const events = normalizeEvents(result.events);
- const address = collectionIdToAddress(collectionId);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: receiver,
- tokenId: nextTokenId,
- },
- },
- ]);
-
+ const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'suffix', suffix);
expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);
});
});
describe('Refungible: Plain calls', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([50n], donor);
+ });
});
- itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('Can perform approve()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const spender = createEthAccount(web3);
-
- const contract = uniqueRefungibleToken(web3, address, owner);
-
{
const result = await contract.methods.approve(spender, 100).send({from: owner});
- const events = normalizeEvents(result.events);
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner,
- spender,
- value: '100',
- },
- },
- ]);
+ const event = result.events.Approval;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.owner).to.be.equal(owner);
+ expect(event.returnValues.spender).to.be.equal(spender);
+ expect(event.returnValues.value).to.be.equal('100');
}
{
@@ -265,49 +164,31 @@
}
});
- itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
+ itEth('Can perform transferFrom()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
-
- const spender = createEthAccount(web3);
- await transferBalanceToEth(api, alice, spender);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const receiver = createEthAccount(web3);
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
-
await contract.methods.approve(spender, 100).send();
{
const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- value: '49',
- },
- },
- {
- address,
- event: 'Approval',
- args: {
- owner,
- spender,
- value: '51',
- },
- },
- ]);
+ let event = result.events.Transfer;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('49');
+
+ event = result.events.Approval;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.owner).to.be.equal(owner);
+ expect(event.returnValues.spender).to.be.equal(spender);
+ expect(event.returnValues.value).to.be.equal('51');
}
{
@@ -321,36 +202,22 @@
}
});
- itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('Can perform transfer()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
-
- const receiver = createEthAccount(web3);
- await transferBalanceToEth(api, alice, receiver);
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
{
const result = await contract.methods.transfer(receiver, 50).send({from: owner});
- const events = normalizeEvents(result.events);
- expect(events).to.include.deep.members([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: receiver,
- value: '50',
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('50');
}
{
@@ -364,311 +231,262 @@
}
});
- itWeb3('Can perform repartition()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
+ itEth('Can perform repartition()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const receiver = createEthAccount(web3);
- await transferBalanceToEth(api, alice, receiver);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
-
await contract.methods.repartition(200).send({from: owner});
expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);
await contract.methods.transfer(receiver, 110).send({from: owner});
expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);
expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);
- await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;
+ await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected; // Transaction is reverted
await contract.methods.transfer(receiver, 90).send({from: owner});
expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0);
expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200);
await contract.methods.repartition(150).send({from: receiver});
- await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected;
+ await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected; // Transaction is reverted
expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150);
});
- itWeb3('Can repartition with increased amount', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
+ itEth('Can repartition with increased amount', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
const result = await contract.methods.repartition(200).send();
- const events = normalizeEvents(result.events);
- expect(events).to.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: owner,
- value: '100',
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.to).to.be.equal(owner);
+ expect(event.returnValues.value).to.be.equal('100');
});
- itWeb3('Can repartition with decreased amount', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('Can repartition with decreased amount', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});
- const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;
-
- const owner = createEthAccount(web3);
- await transferBalanceToEth(api, alice, owner);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
const result = await contract.methods.repartition(50).send();
- const events = normalizeEvents(result.events);
- expect(events).to.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: owner,
- to: '0x0000000000000000000000000000000000000000',
- value: '50',
- },
- },
- ]);
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');
+ expect(event.returnValues.value).to.be.equal('50');
});
- itWeb3('Receiving Transfer event on burning into full ownership', async ({web3, api, privateKeyWrapper}) => {
- const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
- const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
+ itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Devastation', '6', '6');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
const tokenId = await contract.methods.nextTokenId().call();
await contract.methods.mint(caller, tokenId).send();
+ const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);
+ const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller);
- const address = tokenIdToAddress(collectionId, tokenId);
-
- const tokenContract = uniqueRefungibleToken(web3, address, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
- const events = await recordEvents(contract, async () =>
- await tokenContract.methods.burnFrom(caller, 1).send());
- expect(events).to.deep.equal([
- {
- address: collectionIdAddress,
- event: 'Transfer',
- args: {
- from: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF',
- to: receiver,
- tokenId,
- },
- },
- ]);
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
+ await tokenContract.methods.burnFrom(caller, 1).send();
+
+ const event = events[0];
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(tokenId);
});
});
describe('Refungible: Fees', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([50n], donor);
+ });
});
- itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = createEthAccount(web3);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
-
- const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
- itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
-
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
+ itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const spender = await helper.eth.createAccountWithBalance(donor);
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
await contract.methods.approve(spender, 100).send({from: owner});
- const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
- itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const receiver = createEthAccount(web3);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
-
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address, owner);
-
- const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
});
});
describe('Refungible: Substrate calls', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- });
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
-
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
-
- const receiver = createEthAccount(web3);
+ donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([50n], donor);
+ });
+ });
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;
+ itEth('Events emitted for approve()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const token = await collection.mintToken(alice, 200n);
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address);
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress);
- const events = await recordEvents(contract, async () => {
- expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true;
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
});
+ expect(await token.approve(alice, {Ethereum: receiver}, 100n)).to.be.true;
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Approval',
- args: {
- owner: subToEth(alice.address),
- spender: receiver,
- value: '100',
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Approval');
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.spender).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('100');
});
- itWeb3('Events emitted for transferFrom()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('Events emitted for transferFrom()', async ({helper}) => {
+ const [bob] = await helper.arrange.createAccounts([10n], donor);
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const token = await collection.mintToken(alice, 200n);
+ await token.approve(alice, {Substrate: bob.address}, 100n);
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const bob = privateKeyWrapper('//Bob');
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress);
- const receiver = createEthAccount(web3);
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;
- expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true;
+ expect(await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}, 51n)).to.be.true;
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address);
+ let event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('51');
- const events = await recordEvents(contract, async () => {
- expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver}, 51n)).to.be.true;
- });
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- value: '51',
- },
- },
- {
- address,
- event: 'Approval',
- args: {
- owner: subToEth(alice.address),
- spender: subToEth(bob.address),
- value: '49',
- },
- },
- ]);
+ event = events[1];
+ expect(event.event).to.be.equal('Approval');
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address));
+ expect(event.returnValues.value).to.be.equal('49');
});
- itWeb3('Events emitted for transfer()', async ({web3, api, privateKeyWrapper}) => {
- const alice = privateKeyWrapper('//Alice');
+ itEth('Events emitted for transfer()', async ({helper}) => {
+ const receiver = helper.eth.createAccount();
+ const collection = await helper.rft.mintCollection(alice);
+ const token = await collection.mintToken(alice, 200n);
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
+ const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);
+ const contract = helper.ethNativeContract.rftToken(tokenAddress);
- const receiver = createEthAccount(web3);
-
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;
+ const events: any = [];
+ contract.events.allEvents((_: any, event: any) => {
+ events.push(event);
+ });
- const address = tokenIdToAddress(collectionId, tokenId);
- const contract = uniqueRefungibleToken(web3, address);
+ expect(await token.transfer(alice, {Ethereum: receiver}, 51n)).to.be.true;
- const events = await recordEvents(contract, async () => {
- expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver}, 51n)).to.be.true;
- });
-
- expect(events).to.be.deep.equal([
- {
- address,
- event: 'Transfer',
- args: {
- from: subToEth(alice.address),
- to: receiver,
- value: '51',
- },
- },
- ]);
+ const event = events[0];
+ expect(event.event).to.be.equal('Transfer');
+ expect(event.address).to.be.equal(tokenAddress);
+ expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('51');
});
});
describe('ERC 1633 implementation', () => {
+ let donor: IKeyringPair;
+
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- });
+ await usingEthPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => {
- const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ donor = privateKey('//Alice');
+ });
+ });
- const {collectionIdAddress, collectionId} = await createRFTCollection(api, web3, owner);
- const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
- const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();
- await refungibleContract.methods.mint(owner, refungibleTokenId).send();
+ itEth('Default parent token address and id', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
- const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId);
- const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+ const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sands', '', 'GRAIN');
+ const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ const tokenId = await collectionContract.methods.nextTokenId().call();
+ await collectionContract.methods.mint(owner, tokenId).send();
+ const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);
+ const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner);
- const tokenAddress = await refungibleTokenContract.methods.parentToken().call();
- const tokenId = await refungibleTokenContract.methods.parentTokenId().call();
- expect(tokenAddress).to.be.equal(collectionIdAddress);
- expect(tokenId).to.be.equal(refungibleTokenId);
+ expect(await tokenContract.methods.parentToken().call()).to.be.equal(collectionAddress);
+ expect(await tokenContract.methods.parentTokenId().call()).to.be.equal(tokenId);
});
});
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034/* eslint-disable function-call-argument-newline */5// eslint-disable-next-line @typescript-eslint/triple-slash-reference6/// <reference path="unique.dev.d.ts" />78import {readFile} from 'fs/promises';910import Web3 from 'web3';11import {WebsocketProvider} from 'web3-core';12import {Contract} from 'web3-eth-contract';1314import * as solc from 'solc';1516import {evmToAddress} from '@polkadot/util-crypto';17import {IKeyringPair} from '@polkadot/types/types';1819import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';2021import {ContractImports, CompiledContract} from './types';2223// Native contracts ABI24import collectionHelpersAbi from '../../collectionHelpersAbi.json';25import fungibleAbi from '../../fungibleAbi.json';26import nonFungibleAbi from '../../nonFungibleAbi.json';27import refungibleAbi from '../../reFungibleAbi.json';28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';29import contractHelpersAbi from './../contractHelpersAbi.json';30import {TEthereumAccount} from '../../../util/playgrounds/types';3132class EthGroupBase {33 helper: EthUniqueHelper;3435 constructor(helper: EthUniqueHelper) {36 this.helper = helper;37 }38}394041class ContractGroup extends EthGroupBase {42 async findImports(imports?: ContractImports[]){43 if(!imports) return function(path: string) {44 return {error: `File not found: ${path}`};45 };46 47 const knownImports = {} as {[key: string]: string};48 for(const imp of imports) {49 knownImports[imp.solPath] = (await readFile(imp.fsPath)).toString();50 }51 52 return function(path: string) {53 if(path in knownImports) return {contents: knownImports[path]};54 return {error: `File not found: ${path}`};55 };56 }5758 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {59 const out = JSON.parse(solc.compile(JSON.stringify({60 language: 'Solidity',61 sources: {62 [`${name}.sol`]: {63 content: src,64 },65 },66 settings: {67 outputSelection: {68 '*': {69 '*': ['*'],70 },71 },72 },73 }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];74 75 return {76 abi: out.abi,77 object: '0x' + out.evm.bytecode.object,78 };79 }8081 async deployByCode(signer: string, name: string, src: string, imports?: ContractImports[]): Promise<Contract> {82 const compiledContract = await this.compile(name, src, imports);83 return this.deployByAbi(signer, compiledContract.abi, compiledContract.object);84 }8586 async deployByAbi(signer: string, abi: any, object: string): Promise<Contract> {87 const web3 = this.helper.getWeb3();88 const contract = new web3.eth.Contract(abi, undefined, {89 data: object,90 from: signer,91 gas: this.helper.eth.DEFAULT_GAS,92 });93 return await contract.deploy({data: object}).send({from: signer});94 }9596}97 98class NativeContractGroup extends EthGroupBase {99100 contractHelpers(caller: string): Contract {101 const web3 = this.helper.getWeb3();102 return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});103 }104105 collectionHelpers(caller: string) {106 const web3 = this.helper.getWeb3();107 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});108 }109110 collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {111 const abi = {112 'nft': nonFungibleAbi,113 'rft': refungibleAbi,114 'ft': fungibleAbi,115 }[mode];116 const web3 = this.helper.getWeb3();117 return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});118 }119120 rftTokenByAddress(address: string, caller?: string): Contract {121 const web3 = this.helper.getWeb3();122 return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});123 }124125 rftToken(collectionId: number, tokenId: number, caller?: string): Contract {126 return this.rftTokenByAddress(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);127 }128}129130 131class EthGroup extends EthGroupBase {132 DEFAULT_GAS = 2_500_000;133134 createAccount() {135 const web3 = this.helper.getWeb3();136 const account = web3.eth.accounts.create();137 web3.eth.accounts.wallet.add(account.privateKey);138 return account.address;139 }140141 async createAccountWithBalance(donor: IKeyringPair, amount=1000n) {142 const account = this.createAccount();143 await this.transferBalanceFromSubstrate(donor, account, amount);144 145 return account;146 }147148 async transferBalanceFromSubstrate(donor: IKeyringPair, recepient: string, amount=1000n, inTokens=true) {149 return await this.helper.balance.transferToSubstrate(donor, evmToAddress(recepient), amount * (inTokens ? this.helper.balance.getOneTokenNominal() : 1n));150 }151152 async sendEVM(signer: IKeyringPair, contractAddress: string, abi: string, value: string, gasLimit?: number) {153 if(!gasLimit) gasLimit = this.DEFAULT_GAS;154 const web3 = this.helper.getWeb3();155 const gasPrice = await web3.eth.getGasPrice();156 // TODO: check execution status157 await this.helper.executeExtrinsic(158 signer,159 'api.tx.evm.call', [this.helper.address.substrateToEth(signer.address), contractAddress, abi, value, gasLimit, gasPrice, null, null, []],160 true,161 );162 }163 164 async callEVM(signer: TEthereumAccount, contractAddress: string, abi: string) {165 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);166 }167168 async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {169 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);170 171 const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send();172173 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);174 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);175176 return {collectionId, collectionAddress};177 }178179 async deployCollectorContract(signer: string): Promise<Contract> {180 return await this.helper.ethContract.deployByCode(signer, 'Collector', `181 // SPDX-License-Identifier: UNLICENSED182 pragma solidity ^0.8.6;183184 contract Collector {185 uint256 collected;186 fallback() external payable {187 giveMoney();188 }189 function giveMoney() public payable {190 collected += msg.value;191 }192 function getCollected() public view returns (uint256) {193 return collected;194 }195 function getUnaccounted() public view returns (uint256) {196 return address(this).balance - collected;197 }198199 function withdraw(address payable target) public {200 target.transfer(collected);201 collected = 0;202 }203 }204 `);205 }206207 async deployFlipper(signer: string): Promise<Contract> {208 return await this.helper.ethContract.deployByCode(signer, 'Flipper', `209 // SPDX-License-Identifier: UNLICENSED210 pragma solidity ^0.8.6;211212 contract Flipper {213 bool value = false;214 function flip() public {215 value = !value;216 }217 function getValue() public view returns (bool) {218 return value;219 }220 }221 `);222 }223} 224 225class EthAddressGroup extends EthGroupBase {226 extractCollectionId(address: string): number {227 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');228 return parseInt(address.substr(address.length - 8), 16);229 }230231 fromCollectionId(collectionId: number): string {232 if (collectionId >= 0xffffffff || collectionId < 0) throw new Error('collectionId overflow');233 return Web3.utils.toChecksumAddress(`0x17c4e6453cc49aaaaeaca894e6d9683e${collectionId.toString(16).padStart(8,'0')}`);234 }235236 extractTokenId(address: string): {collectionId: number, tokenId: number} {237 if (!address.startsWith('0x'))238 throw 'address not starts with "0x"';239 if (address.length > 42)240 throw 'address length is more than 20 bytes';241 return {242 collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),243 tokenId: Number('0x' + address.substring(address.length - 8)),244 };245 }246247 fromTokenId(collectionId: number, tokenId: number): string {248 return this.helper.util.getTokenAddress({collectionId, tokenId});249 }250251 normalizeAddress(address: string): string {252 return '0x' + address.substring(address.length - 40);253 }254} 255 256257export class EthUniqueHelper extends DevUniqueHelper {258 web3: Web3 | null = null;259 web3Provider: WebsocketProvider | null = null;260261 eth: EthGroup;262 ethAddress: EthAddressGroup;263 ethNativeContract: NativeContractGroup;264 ethContract: ContractGroup;265266 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {267 super(logger);268 this.eth = new EthGroup(this);269 this.ethAddress = new EthAddressGroup(this);270 this.ethNativeContract = new NativeContractGroup(this);271 this.ethContract = new ContractGroup(this);272 }273274 getWeb3(): Web3 {275 if(this.web3 === null) throw Error('Web3 not connected');276 return this.web3;277 }278279 async connectWeb3(wsEndpoint: string) {280 if(this.web3 !== null) return;281 this.web3Provider = new Web3.providers.WebsocketProvider(wsEndpoint);282 this.web3 = new Web3(this.web3Provider);283 }284285 async disconnectWeb3() {286 if(this.web3 === null) return;287 this.web3Provider?.connection.close();288 this.web3 = null;289 }290}291 1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034/* eslint-disable function-call-argument-newline */5// eslint-disable-next-line @typescript-eslint/triple-slash-reference6/// <reference path="unique.dev.d.ts" />78import {readFile} from 'fs/promises';910import Web3 from 'web3';11import {WebsocketProvider} from 'web3-core';12import {Contract} from 'web3-eth-contract';1314import * as solc from 'solc';1516import {evmToAddress} from '@polkadot/util-crypto';17import {IKeyringPair} from '@polkadot/types/types';1819import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';2021import {ContractImports, CompiledContract} from './types';2223// Native contracts ABI24import collectionHelpersAbi from '../../collectionHelpersAbi.json';25import fungibleAbi from '../../fungibleAbi.json';26import nonFungibleAbi from '../../nonFungibleAbi.json';27import refungibleAbi from '../../reFungibleAbi.json';28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';29import contractHelpersAbi from './../contractHelpersAbi.json';30import {TEthereumAccount} from '../../../util/playgrounds/types';3132class EthGroupBase {33 helper: EthUniqueHelper;3435 constructor(helper: EthUniqueHelper) {36 this.helper = helper;37 }38}394041class ContractGroup extends EthGroupBase {42 async findImports(imports?: ContractImports[]){43 if(!imports) return function(path: string) {44 return {error: `File not found: ${path}`};45 };46 47 const knownImports = {} as {[key: string]: string};48 for(const imp of imports) {49 knownImports[imp.solPath] = (await readFile(imp.fsPath)).toString();50 }51 52 return function(path: string) {53 if(path in knownImports) return {contents: knownImports[path]};54 return {error: `File not found: ${path}`};55 };56 }5758 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {59 const out = JSON.parse(solc.compile(JSON.stringify({60 language: 'Solidity',61 sources: {62 [`${name}.sol`]: {63 content: src,64 },65 },66 settings: {67 outputSelection: {68 '*': {69 '*': ['*'],70 },71 },72 },73 }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];74 75 return {76 abi: out.abi,77 object: '0x' + out.evm.bytecode.object,78 };79 }8081 async deployByCode(signer: string, name: string, src: string, imports?: ContractImports[]): Promise<Contract> {82 const compiledContract = await this.compile(name, src, imports);83 return this.deployByAbi(signer, compiledContract.abi, compiledContract.object);84 }8586 async deployByAbi(signer: string, abi: any, object: string): Promise<Contract> {87 const web3 = this.helper.getWeb3();88 const contract = new web3.eth.Contract(abi, undefined, {89 data: object,90 from: signer,91 gas: this.helper.eth.DEFAULT_GAS,92 });93 return await contract.deploy({data: object}).send({from: signer});94 }9596}97 98class NativeContractGroup extends EthGroupBase {99100 contractHelpers(caller: string): Contract {101 const web3 = this.helper.getWeb3();102 return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});103 }104105 collectionHelpers(caller: string) {106 const web3 = this.helper.getWeb3();107 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});108 }109110 collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {111 const abi = {112 'nft': nonFungibleAbi,113 'rft': refungibleAbi,114 'ft': fungibleAbi,115 }[mode];116 const web3 = this.helper.getWeb3();117 return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});118 }119120 collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {121 return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller);122 }123124 rftToken(address: string, caller?: string): Contract {125 const web3 = this.helper.getWeb3();126 return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});127 }128129 rftTokenById(collectionId: number, tokenId: number, caller?: string): Contract {130 return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);131 }132}133134 135class EthGroup extends EthGroupBase {136 DEFAULT_GAS = 2_500_000;137138 createAccount() {139 const web3 = this.helper.getWeb3();140 const account = web3.eth.accounts.create();141 web3.eth.accounts.wallet.add(account.privateKey);142 return account.address;143 }144145 async createAccountWithBalance(donor: IKeyringPair, amount=1000n) {146 const account = this.createAccount();147 await this.transferBalanceFromSubstrate(donor, account, amount);148 149 return account;150 }151152 async transferBalanceFromSubstrate(donor: IKeyringPair, recepient: string, amount=1000n, inTokens=true) {153 return await this.helper.balance.transferToSubstrate(donor, evmToAddress(recepient), amount * (inTokens ? this.helper.balance.getOneTokenNominal() : 1n));154 }155156 async sendEVM(signer: IKeyringPair, contractAddress: string, abi: string, value: string, gasLimit?: number) {157 if(!gasLimit) gasLimit = this.DEFAULT_GAS;158 const web3 = this.helper.getWeb3();159 const gasPrice = await web3.eth.getGasPrice();160 // TODO: check execution status161 await this.helper.executeExtrinsic(162 signer,163 'api.tx.evm.call', [this.helper.address.substrateToEth(signer.address), contractAddress, abi, value, gasLimit, gasPrice, null, null, []],164 true,165 );166 }167 168 async callEVM(signer: TEthereumAccount, contractAddress: string, abi: string) {169 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);170 }171172 async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {173 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);174 175 const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send();176177 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);178 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);179180 return {collectionId, collectionAddress};181 }182183 async createRefungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {184 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);185 186 const result = await collectionHelper.methods.createRFTCollection(name, description, tokenPrefix).send();187188 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);189 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);190191 return {collectionId, collectionAddress};192 }193194 async deployCollectorContract(signer: string): Promise<Contract> {195 return await this.helper.ethContract.deployByCode(signer, 'Collector', `196 // SPDX-License-Identifier: UNLICENSED197 pragma solidity ^0.8.6;198199 contract Collector {200 uint256 collected;201 fallback() external payable {202 giveMoney();203 }204 function giveMoney() public payable {205 collected += msg.value;206 }207 function getCollected() public view returns (uint256) {208 return collected;209 }210 function getUnaccounted() public view returns (uint256) {211 return address(this).balance - collected;212 }213214 function withdraw(address payable target) public {215 target.transfer(collected);216 collected = 0;217 }218 }219 `);220 }221222 async deployFlipper(signer: string): Promise<Contract> {223 return await this.helper.ethContract.deployByCode(signer, 'Flipper', `224 // SPDX-License-Identifier: UNLICENSED225 pragma solidity ^0.8.6;226227 contract Flipper {228 bool value = false;229 function flip() public {230 value = !value;231 }232 function getValue() public view returns (bool) {233 return value;234 }235 }236 `);237 }238239 async recordCallFee(user: string, call: () => Promise<any>): Promise<bigint> {240 const before = await this.helper.balance.getEthereum(user);241 await call();242 // In dev mode, the transaction might not finish processing in time243 await this.helper.wait.newBlocks(1);244 const after = await this.helper.balance.getEthereum(user);245246 return before - after;247 }248} 249 250class EthAddressGroup extends EthGroupBase {251 extractCollectionId(address: string): number {252 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');253 return parseInt(address.substr(address.length - 8), 16);254 }255256 fromCollectionId(collectionId: number): string {257 if (collectionId >= 0xffffffff || collectionId < 0) throw new Error('collectionId overflow');258 return Web3.utils.toChecksumAddress(`0x17c4e6453cc49aaaaeaca894e6d9683e${collectionId.toString(16).padStart(8,'0')}`);259 }260261 extractTokenId(address: string): {collectionId: number, tokenId: number} {262 if (!address.startsWith('0x'))263 throw 'address not starts with "0x"';264 if (address.length > 42)265 throw 'address length is more than 20 bytes';266 return {267 collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),268 tokenId: Number('0x' + address.substring(address.length - 8)),269 };270 }271272 fromTokenId(collectionId: number, tokenId: number): string {273 return this.helper.util.getTokenAddress({collectionId, tokenId});274 }275276 normalizeAddress(address: string): string {277 return '0x' + address.substring(address.length - 40);278 }279} 280 281282export class EthUniqueHelper extends DevUniqueHelper {283 web3: Web3 | null = null;284 web3Provider: WebsocketProvider | null = null;285286 eth: EthGroup;287 ethAddress: EthAddressGroup;288 ethNativeContract: NativeContractGroup;289 ethContract: ContractGroup;290291 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {292 super(logger);293 this.eth = new EthGroup(this);294 this.ethAddress = new EthAddressGroup(this);295 this.ethNativeContract = new NativeContractGroup(this);296 this.ethContract = new ContractGroup(this);297 }298299 getWeb3(): Web3 {300 if(this.web3 === null) throw Error('Web3 not connected');301 return this.web3;302 }303304 async connectWeb3(wsEndpoint: string) {305 if(this.web3 !== null) return;306 this.web3Provider = new Web3.providers.WebsocketProvider(wsEndpoint);307 this.web3 = new Web3(this.web3Provider);308 }309310 async disconnectWeb3() {311 if(this.web3 === null) return;312 this.web3Provider?.connection.close();313 this.web3 = null;314 }315}316