difftreelog
tests(eth): NFT, RFT, FT tests refactored for playgrounds
in: master
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';3031class EthGroupBase {32 helper: EthUniqueHelper;3334 constructor(helper: EthUniqueHelper) {35 this.helper = helper;36 }37}383940class ContractGroup extends EthGroupBase {41 async findImports(imports?: ContractImports[]){42 if(!imports) return function(path: string) {43 return {error: `File not found: ${path}`};44 };45 46 const knownImports = {} as any;47 for(const imp of imports) {48 knownImports[imp.solPath] = (await readFile(imp.fsPath)).toString();49 }50 51 return function(path: string) {52 if(knownImports.hasOwnPropertyDescriptor(path)) return {contents: knownImports[path]};53 return {error: `File not found: ${path}`};54 };55 }5657 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {58 const out = JSON.parse(solc.compile(JSON.stringify({59 language: 'Solidity',60 sources: {61 [`${name}.sol`]: {62 content: src,63 },64 },65 settings: {66 outputSelection: {67 '*': {68 '*': ['*'],69 },70 },71 },72 }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];73 74 return {75 abi: out.abi,76 object: '0x' + out.evm.bytecode.object,77 };78 }7980 async deployByCode(signer: string, name: string, src: string, imports?: ContractImports[]): Promise<Contract> {81 const compiledContract = await this.compile(name, src, imports);82 return this.deployByAbi(signer, compiledContract.abi, compiledContract.object);83 }8485 async deployByAbi(signer: string, abi: any, object: string): Promise<Contract> {86 const web3 = this.helper.getWeb3();87 const contract = new web3.eth.Contract(abi, undefined, {88 data: object,89 from: signer,90 gas: this.helper.eth.DEFAULT_GAS,91 });92 return await contract.deploy({data: object}).send({from: signer});93 }9495}96 97class NativeContractGroup extends EthGroupBase {9899 contractHelpers(caller: string): Contract {100 const web3 = this.helper.getWeb3();101 return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});102 }103104 collectionHelpers(caller: string) {105 const web3 = this.helper.getWeb3();106 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});107 }108109 collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {110 const abi = {111 'nft': nonFungibleAbi,112 'rft': refungibleAbi,113 'ft': fungibleAbi,114 }[mode];115 const web3 = this.helper.getWeb3();116 return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});117 }118119 rftTokenByAddress(address: string, caller?: string): Contract {120 const web3 = this.helper.getWeb3();121 return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});122 }123124 rftToken(collectionId: number, tokenId: number, caller?: string): Contract {125 return this.rftTokenByAddress(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);126 }127}128129 130class EthGroup extends EthGroupBase {131 DEFAULT_GAS = 2_500_000;132133 createAccount() {134 const web3 = this.helper.getWeb3();135 const account = web3.eth.accounts.create();136 web3.eth.accounts.wallet.add(account.privateKey);137 return account.address;138 }139140 async createAccountWithBalance(donor: IKeyringPair, amount=1000n) {141 const account = this.createAccount();142 await this.transferBalanceFromSubstrate(donor, account, amount);143 144 return account;145 }146147 async transferBalanceFromSubstrate(donor: IKeyringPair, recepient: string, amount=1000n, inTokens=true) {148 return await this.helper.balance.transferToSubstrate(donor, evmToAddress(recepient), amount * (inTokens ? this.helper.balance.getOneTokenNominal() : 1n));149 }150151 async callEVM(signer: IKeyringPair, contractAddress: string, abi: any, value: string, gasLimit?: number) {152 if(!gasLimit) gasLimit = this.DEFAULT_GAS;153 const web3 = this.helper.getWeb3();154 const gasPrice = await web3.eth.getGasPrice();155 // TODO: check execution status156 await this.helper.executeExtrinsic(157 signer,158 'api.tx.evm.call', [this.helper.address.substrateToEth(signer.address), contractAddress, abi, value, gasLimit, gasPrice, null, null, []],159 true,160 );161 }162163 async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {164 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);165 166 const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send();167168 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);169 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);170171 return {collectionId, collectionAddress};172 }173174 async deployCollectorContract(signer: string): Promise<Contract> {175 return await this.helper.ethContract.deployByCode(signer, 'Collector', `176 // SPDX-License-Identifier: UNLICENSED177 pragma solidity ^0.8.6;178179 contract Collector {180 uint256 collected;181 fallback() external payable {182 giveMoney();183 }184 function giveMoney() public payable {185 collected += msg.value;186 }187 function getCollected() public view returns (uint256) {188 return collected;189 }190 function getUnaccounted() public view returns (uint256) {191 return address(this).balance - collected;192 }193194 function withdraw(address payable target) public {195 target.transfer(collected);196 collected = 0;197 }198 }199 `);200 }201202 async deployFlipper(signer: string): Promise<Contract> {203 return await this.helper.ethContract.deployByCode(signer, 'Flipper', `204 // SPDX-License-Identifier: UNLICENSED205 pragma solidity ^0.8.6;206207 contract Flipper {208 bool value = false;209 function flip() public {210 value = !value;211 }212 function getValue() public view returns (bool) {213 return value;214 }215 }216 `);217 }218} 219 220class EthAddressGroup extends EthGroupBase {221 extractCollectionId(address: string): number {222 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');223 return parseInt(address.substr(address.length - 8), 16);224 }225226 fromCollectionId(collectionId: number): string {227 if (collectionId >= 0xffffffff || collectionId < 0) throw new Error('collectionId overflow');228 return Web3.utils.toChecksumAddress(`0x17c4e6453cc49aaaaeaca894e6d9683e${collectionId.toString(16).padStart(8,'0')}`);229 }230231 extractTokenId(address: string): {collectionId: number, tokenId: number} {232 if (!address.startsWith('0x'))233 throw 'address not starts with "0x"';234 if (address.length > 42)235 throw 'address length is more than 20 bytes';236 return {237 collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),238 tokenId: Number('0x' + address.substring(address.length - 8)),239 };240 }241242 fromTokenId(collectionId: number, tokenId: number): string {243 return this.helper.util.getTokenAddress({collectionId, tokenId});244 }245246 normalizeAddress(address: string): string {247 return '0x' + address.substring(address.length - 40);248 }249} 250 251252export class EthUniqueHelper extends DevUniqueHelper {253 web3: Web3 | null = null;254 web3Provider: WebsocketProvider | null = null;255256 eth: EthGroup;257 ethAddress: EthAddressGroup;258 ethNativeContract: NativeContractGroup;259 ethContract: ContractGroup;260261 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {262 super(logger);263 this.eth = new EthGroup(this);264 this.ethAddress = new EthAddressGroup(this);265 this.ethNativeContract = new NativeContractGroup(this);266 this.ethContract = new ContractGroup(this);267 }268269 getWeb3(): Web3 {270 if(this.web3 === null) throw Error('Web3 not connected');271 return this.web3;272 }273274 async connectWeb3(wsEndpoint: string) {275 if(this.web3 !== null) return;276 this.web3Provider = new Web3.providers.WebsocketProvider(wsEndpoint);277 this.web3 = new Web3(this.web3Provider);278 }279280 async disconnectWeb3() {281 if(this.web3 === null) return;282 this.web3Provider?.connection.close();283 this.web3 = null;284 }285}286 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';3031class EthGroupBase {32 helper: EthUniqueHelper;3334 constructor(helper: EthUniqueHelper) {35 this.helper = helper;36 }37}383940class ContractGroup extends EthGroupBase {41 async findImports(imports?: ContractImports[]){42 if(!imports) return function(path: string) {43 return {error: `File not found: ${path}`};44 };45 46 const knownImports = {} as any;47 for(const imp of imports) {48 knownImports[imp.solPath] = (await readFile(imp.fsPath)).toString();49 }50 51 return function(path: string) {52 if(knownImports.hasOwnPropertyDescriptor(path)) return {contents: knownImports[path]};53 return {error: `File not found: ${path}`};54 };55 }5657 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {58 const out = JSON.parse(solc.compile(JSON.stringify({59 language: 'Solidity',60 sources: {61 [`${name}.sol`]: {62 content: src,63 },64 },65 settings: {66 outputSelection: {67 '*': {68 '*': ['*'],69 },70 },71 },72 }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];73 74 return {75 abi: out.abi,76 object: '0x' + out.evm.bytecode.object,77 };78 }7980 async deployByCode(signer: string, name: string, src: string, imports?: ContractImports[]): Promise<Contract> {81 const compiledContract = await this.compile(name, src, imports);82 return this.deployByAbi(signer, compiledContract.abi, compiledContract.object);83 }8485 async deployByAbi(signer: string, abi: any, object: string): Promise<Contract> {86 const web3 = this.helper.getWeb3();87 const contract = new web3.eth.Contract(abi, undefined, {88 data: object,89 from: signer,90 gas: this.helper.eth.DEFAULT_GAS,91 });92 return await contract.deploy({data: object}).send({from: signer});93 }9495}96 97class NativeContractGroup extends EthGroupBase {9899 contractHelpers(caller: string): Contract {100 const web3 = this.helper.getWeb3();101 return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});102 }103104 collectionHelpers(caller: string) {105 const web3 = this.helper.getWeb3();106 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});107 }108109 collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {110 const abi = {111 'nft': nonFungibleAbi,112 'rft': refungibleAbi,113 'ft': fungibleAbi,114 }[mode];115 const web3 = this.helper.getWeb3();116 return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});117 }118119 collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {120 return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller);121 }122123 rftToken(address: string, caller?: string): Contract {124 const web3 = this.helper.getWeb3();125 return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});126 }127128 rftTokenById(collectionId: number, tokenId: number, caller?: string): Contract {129 return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);130 }131}132133 134class EthGroup extends EthGroupBase {135 DEFAULT_GAS = 2_500_000;136137 createAccount() {138 const web3 = this.helper.getWeb3();139 const account = web3.eth.accounts.create();140 web3.eth.accounts.wallet.add(account.privateKey);141 return account.address;142 }143144 async createAccountWithBalance(donor: IKeyringPair, amount=1000n) {145 const account = this.createAccount();146 await this.transferBalanceFromSubstrate(donor, account, amount);147 148 return account;149 }150151 async transferBalanceFromSubstrate(donor: IKeyringPair, recepient: string, amount=1000n, inTokens=true) {152 return await this.helper.balance.transferToSubstrate(donor, evmToAddress(recepient), amount * (inTokens ? this.helper.balance.getOneTokenNominal() : 1n));153 }154155 async callEVM(signer: IKeyringPair, contractAddress: string, abi: any, value: string, gasLimit?: number) {156 if(!gasLimit) gasLimit = this.DEFAULT_GAS;157 const web3 = this.helper.getWeb3();158 const gasPrice = await web3.eth.getGasPrice();159 // TODO: check execution status160 await this.helper.executeExtrinsic(161 signer,162 'api.tx.evm.call', [this.helper.address.substrateToEth(signer.address), contractAddress, abi, value, gasLimit, gasPrice, null, null, []],163 true,164 );165 }166167 async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {168 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);169 170 const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send();171172 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);173 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);174175 return {collectionId, collectionAddress};176 }177178 async createRefungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {179 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);180 181 const result = await collectionHelper.methods.createRFTCollection(name, description, tokenPrefix).send();182183 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);184 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);185186 return {collectionId, collectionAddress};187 }188189 async deployCollectorContract(signer: string): Promise<Contract> {190 return await this.helper.ethContract.deployByCode(signer, 'Collector', `191 // SPDX-License-Identifier: UNLICENSED192 pragma solidity ^0.8.6;193194 contract Collector {195 uint256 collected;196 fallback() external payable {197 giveMoney();198 }199 function giveMoney() public payable {200 collected += msg.value;201 }202 function getCollected() public view returns (uint256) {203 return collected;204 }205 function getUnaccounted() public view returns (uint256) {206 return address(this).balance - collected;207 }208209 function withdraw(address payable target) public {210 target.transfer(collected);211 collected = 0;212 }213 }214 `);215 }216217 async deployFlipper(signer: string): Promise<Contract> {218 return await this.helper.ethContract.deployByCode(signer, 'Flipper', `219 // SPDX-License-Identifier: UNLICENSED220 pragma solidity ^0.8.6;221222 contract Flipper {223 bool value = false;224 function flip() public {225 value = !value;226 }227 function getValue() public view returns (bool) {228 return value;229 }230 }231 `);232 }233234 async recordCallFee(user: string, call: () => Promise<any>): Promise<bigint> {235 const before = await this.helper.balance.getEthereum(user);236 await call();237 // In dev mode, the transaction might not finish processing in time238 await this.helper.wait.newBlocks(1);239 const after = await this.helper.balance.getEthereum(user);240241 return before - after;242 }243} 244 245class EthAddressGroup extends EthGroupBase {246 extractCollectionId(address: string): number {247 if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');248 return parseInt(address.substr(address.length - 8), 16);249 }250251 fromCollectionId(collectionId: number): string {252 if (collectionId >= 0xffffffff || collectionId < 0) throw new Error('collectionId overflow');253 return Web3.utils.toChecksumAddress(`0x17c4e6453cc49aaaaeaca894e6d9683e${collectionId.toString(16).padStart(8,'0')}`);254 }255256 extractTokenId(address: string): {collectionId: number, tokenId: number} {257 if (!address.startsWith('0x'))258 throw 'address not starts with "0x"';259 if (address.length > 42)260 throw 'address length is more than 20 bytes';261 return {262 collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),263 tokenId: Number('0x' + address.substring(address.length - 8)),264 };265 }266267 fromTokenId(collectionId: number, tokenId: number): string {268 return this.helper.util.getTokenAddress({collectionId, tokenId});269 }270271 normalizeAddress(address: string): string {272 return '0x' + address.substring(address.length - 40);273 }274} 275 276277export class EthUniqueHelper extends DevUniqueHelper {278 web3: Web3 | null = null;279 web3Provider: WebsocketProvider | null = null;280281 eth: EthGroup;282 ethAddress: EthAddressGroup;283 ethNativeContract: NativeContractGroup;284 ethContract: ContractGroup;285286 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {287 super(logger);288 this.eth = new EthGroup(this);289 this.ethAddress = new EthAddressGroup(this);290 this.ethNativeContract = new NativeContractGroup(this);291 this.ethContract = new ContractGroup(this);292 }293294 getWeb3(): Web3 {295 if(this.web3 === null) throw Error('Web3 not connected');296 return this.web3;297 }298299 async connectWeb3(wsEndpoint: string) {300 if(this.web3 !== null) return;301 this.web3Provider = new Web3.providers.WebsocketProvider(wsEndpoint);302 this.web3 = new Web3(this.web3Provider);303 }304305 async disconnectWeb3() {306 if(this.web3 === null) return;307 this.web3Provider?.connection.close();308 this.web3 = null;309 }310}311