git.delta.rocks / unique-network / refs/commits / d4443286d44f

difftreelog

tests(eth): more small tests refactored to playgrounds

Fahrrader2022-09-30parent: #e15be01.patch.diff
in: master

8 files changed

modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';
18import {expect} from 'chai';18import {IKeyringPair} from '@polkadot/types/types';
19import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';
20import {19import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
21 evmCollectionHelpers,
22 collectionIdToAddress,
23 createEthAccount,
24 createEthAccountWithBalance,
25 evmCollection,
26 itWeb3,
27 getCollectionAddressFromResult,
28} from './util/helpers';
2920
30describe('Create NFT collection from EVM', () => {21describe('Create NFT collection from EVM', () => {
31 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {22 let donor: IKeyringPair;
23
24 before(async function() {
25 await usingEthPlaygrounds(async (_helper, privateKey) => {
32 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);26 donor = privateKey('//Alice');
27 });
28 });
29
30 itEth('Create collection', async ({helper}) => {
33 const collectionHelper = evmCollectionHelpers(web3, owner);31 const owner = await helper.eth.createAccountWithBalance(donor);
32
34 const collectionName = 'CollectionEVM';33 const name = 'CollectionEVM';
35 const description = 'Some description';34 const description = 'Some description';
36 const tokenPrefix = 'token prefix';35 const prefix = 'token prefix';
36
37 37 // todo:playgrounds this might fail when in async environment.
38 const collectionCountBefore = await getCreatedCollectionCount(api);38 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
39 const result = await collectionHelper.methods39 const {collectionId} = await helper.eth.createNonfungibleCollection(owner, name, description, prefix);
40 .createNonfungibleCollection(collectionName, description, tokenPrefix)
41 .send();40 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
41
42 const collectionCountAfter = await getCreatedCollectionCount(api);42 const collection = helper.nft.getCollectionObject(collectionId);
43 43 const data = (await collection.getData())!;
44 const {collectionId, collection} = await getCollectionAddressFromResult(api, result);44
45 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);45 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
46 expect(collectionId).to.be.eq(collectionCountAfter);46 expect(collectionId).to.be.eq(collectionCountAfter);
47 expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);47 expect(data.name).to.be.eq(name);
48 expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);48 expect(data.description).to.be.eq(description);
49 expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);49 expect(data.raw.tokenPrefix).to.be.eq(prefix);
50 expect(collection.mode.isNft).to.be.true;50 expect(data.raw.mode).to.be.eq('NFT');
51 });51 });
5252
53 itWeb3('Check collection address exist', async ({api, web3, privateKeyWrapper}) => {53 // todo:playgrounds this test will fail when in async environment.
54 itEth('Check collection address exist', async ({helper}) => {
54 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);55 const owner = await helper.eth.createAccountWithBalance(donor);
56
55 const collectionHelpers = evmCollectionHelpers(web3, owner);57 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
56
57 const expectedCollectionId = await getCreatedCollectionCount(api) + 1;58 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
58 const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);59 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
60
59 expect(await collectionHelpers.methods61 expect(await collectionHelpers.methods
60 .isCollectionExist(expectedCollectionAddress)62 .isCollectionExist(expectedCollectionAddress)
69 .call()).to.be.true;71 .call()).to.be.true;
70 });72 });
71 73
72 itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {74 itEth('Set sponsorship', async ({helper}) => {
73 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);75 const owner = await helper.eth.createAccountWithBalance(donor);
74 const collectionHelpers = evmCollectionHelpers(web3, owner);76 const sponsor = await helper.eth.createAccountWithBalance(donor);
75 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();77 const ss58Format = helper.chain.getChainProperties().ss58Format;
76 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);78 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');
77 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);79
78 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);80 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
79 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();81 await collection.methods.setCollectionSponsor(sponsor).send();
82
80 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;83 let data = (await helper.nft.getData(collectionId))!;
81 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
82 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
83 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));84 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
85
84 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');86 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
87
85 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);88 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
86 await sponsorCollection.methods.confirmCollectionSponsorship().send();89 await sponsorCollection.methods.confirmCollectionSponsorship().send();
90
87 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;91 data = (await helper.nft.getData(collectionId))!;
88 expect(collectionSub.sponsorship.isConfirmed).to.be.true;92 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
89 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
90 });93 });
9194
92 itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {95 itEth('Set limits', async ({helper}) => {
93 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);96 const owner = await helper.eth.createAccountWithBalance(donor);
94 const collectionHelpers = evmCollectionHelpers(web3, owner);97 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'FLO');
95 const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send();
96 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
97 const limits = {98 const limits = {
98 accountTokenOwnershipLimit: 1000,99 accountTokenOwnershipLimit: 1000,
99 sponsoredDataSize: 1024,100 sponsoredDataSize: 1024,
106 transfersEnabled: false,107 transfersEnabled: false,
107 };108 };
108109
109 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);110 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
110 await collectionEvm.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();111 await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
111 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();112 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
112 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();113 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
113 await collectionEvm.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();114 await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
114 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();115 await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
115 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();116 await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
116 await collectionEvm.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();117 await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
117 await collectionEvm.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();118 await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
118 await collectionEvm.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();119 await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
119 120
120 const collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;121 const data = (await helper.nft.getData(collectionId))!;
121 expect(collectionSub.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.eq(limits.accountTokenOwnershipLimit);122 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);
122 expect(collectionSub.limits.sponsoredDataSize.unwrap().toNumber()).to.be.eq(limits.sponsoredDataSize);123 expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);
123 expect(collectionSub.limits.sponsoredDataRateLimit.unwrap().asBlocks.toNumber()).to.be.eq(limits.sponsoredDataRateLimit);124 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);
124 expect(collectionSub.limits.tokenLimit.unwrap().toNumber()).to.be.eq(limits.tokenLimit);125 expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);
125 expect(collectionSub.limits.sponsorTransferTimeout.unwrap().toNumber()).to.be.eq(limits.sponsorTransferTimeout);126 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);
126 expect(collectionSub.limits.sponsorApproveTimeout.unwrap().toNumber()).to.be.eq(limits.sponsorApproveTimeout);127 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);
127 expect(collectionSub.limits.ownerCanTransfer.toHuman()).to.be.eq(limits.ownerCanTransfer);128 expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);
128 expect(collectionSub.limits.ownerCanDestroy.toHuman()).to.be.eq(limits.ownerCanDestroy);129 expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);
129 expect(collectionSub.limits.transfersEnabled.toHuman()).to.be.eq(limits.transfersEnabled);130 expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);
130 });131 });
131132
132 itWeb3('Collection address exist', async ({api, web3, privateKeyWrapper}) => {133 itEth('Collection address exist', async ({helper}) => {
133 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);134 const owner = await helper.eth.createAccountWithBalance(donor);
134 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';135 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
135 const collectionHelpers = evmCollectionHelpers(web3, owner);136 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)
136 expect(await collectionHelpers.methods
137 .isCollectionExist(collectionAddressForNonexistentCollection).call())137 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
138 .to.be.false;138 .to.be.false;
139 139
140 const result = await collectionHelpers.methods.createNonfungibleCollection('Collection address exist', '7', '7').send();140 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Exister', 'absolutely anything', 'EVC');
141 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);141 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)
142 expect(await collectionHelpers.methods
143 .isCollectionExist(collectionIdAddress).call())142 .methods.isCollectionExist(collectionAddress).call())
144 .to.be.true;143 .to.be.true;
145 });144 });
146});145});
147146
148describe('(!negative tests!) Create NFT collection from EVM', () => {147describe('(!negative tests!) Create NFT collection from EVM', () => {
149 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {148 let donor: IKeyringPair;
149
150 before(async function() {
151 await usingEthPlaygrounds(async (_helper, privateKey) => {
152 donor = privateKey('//Alice');
153 });
154 });
155
156 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);157 const owner = await helper.eth.createAccountWithBalance(donor);
151 const helper = evmCollectionHelpers(web3, owner);158 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
152 {159 {
153 const MAX_NAME_LENGHT = 64;160 const MAX_NAME_LENGTH = 64;
154 const collectionName = 'A'.repeat(MAX_NAME_LENGHT + 1);161 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
155 const description = 'A';162 const description = 'A';
156 const tokenPrefix = 'A';163 const tokenPrefix = 'A';
157 164
158 await expect(helper.methods165 await expect(collectionHelper.methods
159 .createNonfungibleCollection(collectionName, description, tokenPrefix)166 .createNonfungibleCollection(collectionName, description, tokenPrefix)
160 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);167 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);
161 168
162 }169 }
163 { 170 {
164 const MAX_DESCRIPTION_LENGHT = 256;171 const MAX_DESCRIPTION_LENGTH = 256;
165 const collectionName = 'A';172 const collectionName = 'A';
166 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);173 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);
167 const tokenPrefix = 'A';174 const tokenPrefix = 'A';
168 await expect(helper.methods175 await expect(collectionHelper.methods
169 .createNonfungibleCollection(collectionName, description, tokenPrefix)176 .createNonfungibleCollection(collectionName, description, tokenPrefix)
170 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);177 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);
171 }178 }
172 { 179 {
173 const MAX_TOKEN_PREFIX_LENGHT = 16;180 const MAX_TOKEN_PREFIX_LENGTH = 16;
174 const collectionName = 'A';181 const collectionName = 'A';
175 const description = 'A';182 const description = 'A';
176 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);183 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);
177 await expect(helper.methods184 await expect(collectionHelper.methods
178 .createNonfungibleCollection(collectionName, description, tokenPrefix)185 .createNonfungibleCollection(collectionName, description, tokenPrefix)
179 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);186 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);
180 }187 }
181 });188 });
182 189
183 itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {190 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {
184 const owner = createEthAccount(web3);191 const owner = helper.eth.createAccount();
185 const helper = evmCollectionHelpers(web3, owner);192 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
186 const collectionName = 'A';193 await expect(collectionHelper.methods
187 const description = 'A';
188 const tokenPrefix = 'A';
189
190 await expect(helper.methods
191 .createNonfungibleCollection(collectionName, description, tokenPrefix)194 .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')
192 .call()).to.be.rejectedWith('NotSufficientFounds');195 .call()).to.be.rejectedWith('NotSufficientFounds');
193 });196 });
194197
195 itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {198 itEth('(!negative test!) Check owner', async ({helper}) => {
196 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);199 const owner = await helper.eth.createAccountWithBalance(donor);
197 const notOwner = createEthAccount(web3);200 const malfeasant = helper.eth.createAccount();
198 const collectionHelpers = evmCollectionHelpers(web3, owner);201 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Transgressed', 'absolutely anything', 'COR');
199 const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
200 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);202 const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);
201 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);
202 const EXPECTED_ERROR = 'NoPermission';203 const EXPECTED_ERROR = 'NoPermission';
203 {204 {
204 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);205 const sponsor = await helper.eth.createAccountWithBalance(donor);
205 await expect(contractEvmFromNotOwner.methods206 await expect(malfeasantCollection.methods
206 .setCollectionSponsor(sponsor)207 .setCollectionSponsor(sponsor)
207 .call()).to.be.rejectedWith(EXPECTED_ERROR);208 .call()).to.be.rejectedWith(EXPECTED_ERROR);
208 209
209 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);210 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
210 await expect(sponsorCollection.methods211 await expect(sponsorCollection.methods
211 .confirmCollectionSponsorship()212 .confirmCollectionSponsorship()
212 .call()).to.be.rejectedWith('caller is not set as sponsor');213 .call()).to.be.rejectedWith('caller is not set as sponsor');
213 }214 }
214 {215 {
215 await expect(contractEvmFromNotOwner.methods216 await expect(malfeasantCollection.methods
216 .setCollectionLimit('account_token_ownership_limit', '1000')217 .setCollectionLimit('account_token_ownership_limit', '1000')
217 .call()).to.be.rejectedWith(EXPECTED_ERROR);218 .call()).to.be.rejectedWith(EXPECTED_ERROR);
218 }219 }
219 });220 });
220221
221 itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {222 itEth('(!negative test!) Set limits', async ({helper}) => {
222 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);223 const owner = await helper.eth.createAccountWithBalance(donor);
223 const collectionHelpers = evmCollectionHelpers(web3, owner);224 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'OLF');
224 const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send();
225 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);225 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
226 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
227 await expect(collectionEvm.methods226 await expect(collectionEvm.methods
228 .setCollectionLimit('badLimit', 'true')227 .setCollectionLimit('badLimit', 'true')
229 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');228 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';
18import {expect} from 'chai';18import {IKeyringPair} from '@polkadot/types/types';
19import {getCreatedCollectionCount, getDetailedCollectionInfo, requirePallets, Pallets} from '../util/helpers';19import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';
20import {20import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
21 evmCollectionHelpers,
22 collectionIdToAddress,
23 createEthAccount,
24 createEthAccountWithBalance,
25 evmCollection,
26 itWeb3,
27 getCollectionAddressFromResult,
28} from './util/helpers';
2921
30describe('Create RFT collection from EVM', () => {22describe('Create RFT collection from EVM', () => {
23 let donor: IKeyringPair;
24
31 before(async function() {25 before(async function() {
32 await requirePallets(this, [Pallets.ReFungible]);26 await usingEthPlaygrounds(async (helper, privateKey) => {
27 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
28 donor = privateKey('//Alice');
29 });
33 });30 });
3431
35 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {32 itEth('Create collection', async ({helper}) => {
36 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);33 const owner = await helper.eth.createAccountWithBalance(donor);
37 const collectionHelper = evmCollectionHelpers(web3, owner);34
38 const collectionName = 'CollectionEVM';35 const name = 'CollectionEVM';
39 const description = 'Some description';36 const description = 'Some description';
40 const tokenPrefix = 'token prefix';37 const prefix = 'token prefix';
41 38
42 const collectionCountBefore = await getCreatedCollectionCount(api);39 // todo:playgrounds this might fail when in async environment.
40 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
43 const result = await collectionHelper.methods41 const {collectionId} = await helper.eth.createRefungibleCollection(owner, name, description, prefix);
44 .createRFTCollection(collectionName, description, tokenPrefix)
45 .send();
46 const collectionCountAfter = await getCreatedCollectionCount(api);42 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
47 43
48 const {collectionId, collection} = await getCollectionAddressFromResult(api, result);44 const data = (await helper.rft.getData(collectionId))!;
45
49 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);46 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
50 expect(collectionId).to.be.eq(collectionCountAfter);47 expect(collectionId).to.be.eq(collectionCountAfter);
51 expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);48 expect(data.name).to.be.eq(name);
52 expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);49 expect(data.description).to.be.eq(description);
53 expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);50 expect(data.raw.tokenPrefix).to.be.eq(prefix);
54 expect(collection.mode.isReFungible).to.be.true;51 expect(data.raw.mode).to.be.eq('ReFungible');
55 });52 });
5653
57 itWeb3('Check collection address exist', async ({api, web3, privateKeyWrapper}) => {54 // todo:playgrounds this test will fail when in async environment.
55 itEth('Check collection address exist', async ({helper}) => {
58 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);56 const owner = await helper.eth.createAccountWithBalance(donor);
57
59 const collectionHelpers = evmCollectionHelpers(web3, owner);58 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
60
61 const expectedCollectionId = await getCreatedCollectionCount(api) + 1;59 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
62 const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);60 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
61
63 expect(await collectionHelpers.methods62 expect(await collectionHelpers.methods
64 .isCollectionExist(expectedCollectionAddress)63 .isCollectionExist(expectedCollectionAddress)
73 .call()).to.be.true;72 .call()).to.be.true;
74 });73 });
75 74
76 itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {75 itEth('Set sponsorship', async ({helper}) => {
77 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);76 const owner = await helper.eth.createAccountWithBalance(donor);
78 const collectionHelpers = evmCollectionHelpers(web3, owner);77 const sponsor = await helper.eth.createAccountWithBalance(donor);
79 let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send();78 const ss58Format = helper.chain.getChainProperties().ss58Format;
80 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);79 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');
81 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);80
82 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});81 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
83 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();82 await collection.methods.setCollectionSponsor(sponsor).send();
83
84 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;84 let data = (await helper.rft.getData(collectionId))!;
85 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
86 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
87 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));85 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
86
88 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');87 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
88
89 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);89 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
90 await sponsorCollection.methods.confirmCollectionSponsorship().send();90 await sponsorCollection.methods.confirmCollectionSponsorship().send();
91
91 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;92 data = (await helper.rft.getData(collectionId))!;
92 expect(collectionSub.sponsorship.isConfirmed).to.be.true;93 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
93 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
94 });94 });
9595
96 itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {96 itEth('Set limits', async ({helper}) => {
97 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 const owner = await helper.eth.createAccountWithBalance(donor);
98 const collectionHelpers = evmCollectionHelpers(web3, owner);98 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'INSI');
99 const result = await collectionHelpers.methods.createRFTCollection('Const collection', '5', '5').send();
100 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
101 const limits = {99 const limits = {
102 accountTokenOwnershipLimit: 1000,100 accountTokenOwnershipLimit: 1000,
103 sponsoredDataSize: 1024,101 sponsoredDataSize: 1024,
110 transfersEnabled: false,108 transfersEnabled: false,
111 };109 };
112110
113 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});111 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
114 await collectionEvm.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();112 await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
115 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();113 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
116 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();114 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
117 await collectionEvm.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();115 await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
118 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();116 await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
119 await collectionEvm.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();117 await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
120 await collectionEvm.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();118 await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
121 await collectionEvm.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();119 await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
122 await collectionEvm.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();120 await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
123 121
124 const collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;122 const data = (await helper.rft.getData(collectionId))!;
125 expect(collectionSub.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.eq(limits.accountTokenOwnershipLimit);123 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);
126 expect(collectionSub.limits.sponsoredDataSize.unwrap().toNumber()).to.be.eq(limits.sponsoredDataSize);124 expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);
127 expect(collectionSub.limits.sponsoredDataRateLimit.unwrap().asBlocks.toNumber()).to.be.eq(limits.sponsoredDataRateLimit);125 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);
128 expect(collectionSub.limits.tokenLimit.unwrap().toNumber()).to.be.eq(limits.tokenLimit);126 expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);
129 expect(collectionSub.limits.sponsorTransferTimeout.unwrap().toNumber()).to.be.eq(limits.sponsorTransferTimeout);127 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);
130 expect(collectionSub.limits.sponsorApproveTimeout.unwrap().toNumber()).to.be.eq(limits.sponsorApproveTimeout);128 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);
131 expect(collectionSub.limits.ownerCanTransfer.toHuman()).to.be.eq(limits.ownerCanTransfer);129 expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);
132 expect(collectionSub.limits.ownerCanDestroy.toHuman()).to.be.eq(limits.ownerCanDestroy);130 expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);
133 expect(collectionSub.limits.transfersEnabled.toHuman()).to.be.eq(limits.transfersEnabled);131 expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);
134 });132 });
135133
136 itWeb3('Collection address exist', async ({api, web3, privateKeyWrapper}) => {134 itEth('Collection address exist', async ({helper}) => {
137 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);135 const owner = await helper.eth.createAccountWithBalance(donor);
138 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';136 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
139 const collectionHelpers = evmCollectionHelpers(web3, owner);137 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)
140 expect(await collectionHelpers.methods
141 .isCollectionExist(collectionAddressForNonexistentCollection).call())138 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
142 .to.be.false;139 .to.be.false;
143 140
144 const result = await collectionHelpers.methods.createRFTCollection('Collection address exist', '7', '7').send();141 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Exister', 'absolutely anything', 'WIWT');
145 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);142 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)
146 expect(await collectionHelpers.methods
147 .isCollectionExist(collectionIdAddress).call())143 .methods.isCollectionExist(collectionAddress).call())
148 .to.be.true;144 .to.be.true;
149 });145 });
150});146});
151147
152describe('(!negative tests!) Create RFT collection from EVM', () => {148describe('(!negative tests!) Create RFT collection from EVM', () => {
149 let donor: IKeyringPair;
150
153 before(async function() {151 before(async function() {
154 await requirePallets(this, [Pallets.ReFungible]);152 await usingEthPlaygrounds(async (helper, privateKey) => {
153 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
154 donor = privateKey('//Alice');
155 });
155 });156 });
156157
157 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {158 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
158 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);159 const owner = await helper.eth.createAccountWithBalance(donor);
159 const helper = evmCollectionHelpers(web3, owner);160 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
160 {161 {
161 const MAX_NAME_LENGHT = 64;162 const MAX_NAME_LENGTH = 64;
162 const collectionName = 'A'.repeat(MAX_NAME_LENGHT + 1);163 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
163 const description = 'A';164 const description = 'A';
164 const tokenPrefix = 'A';165 const tokenPrefix = 'A';
165 166
166 await expect(helper.methods167 await expect(collectionHelper.methods
167 .createRFTCollection(collectionName, description, tokenPrefix)168 .createRFTCollection(collectionName, description, tokenPrefix)
168 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);169 .call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);
169
170 }170 }
171 { 171 {
172 const MAX_DESCRIPTION_LENGHT = 256;172 const MAX_DESCRIPTION_LENGTH = 256;
173 const collectionName = 'A';173 const collectionName = 'A';
174 const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);174 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);
175 const tokenPrefix = 'A';175 const tokenPrefix = 'A';
176 await expect(helper.methods176 await expect(collectionHelper.methods
177 .createRFTCollection(collectionName, description, tokenPrefix)177 .createRFTCollection(collectionName, description, tokenPrefix)
178 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);178 .call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);
179 }179 }
180 { 180 {
181 const MAX_TOKEN_PREFIX_LENGHT = 16;181 const MAX_TOKEN_PREFIX_LENGTH = 16;
182 const collectionName = 'A';182 const collectionName = 'A';
183 const description = 'A';183 const description = 'A';
184 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);184 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);
185 await expect(helper.methods185 await expect(collectionHelper.methods
186 .createRFTCollection(collectionName, description, tokenPrefix)186 .createRFTCollection(collectionName, description, tokenPrefix)
187 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);187 .call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);
188 }188 }
189 });189 });
190 190
191 itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {191 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {
192 const owner = createEthAccount(web3);192 const owner = helper.eth.createAccount();
193 const helper = evmCollectionHelpers(web3, owner);193 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
194 const collectionName = 'A';194 await expect(collectionHelper.methods
195 const description = 'A';
196 const tokenPrefix = 'A';
197
198 await expect(helper.methods
199 .createRFTCollection(collectionName, description, tokenPrefix)195 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')
200 .call()).to.be.rejectedWith('NotSufficientFounds');196 .call()).to.be.rejectedWith('NotSufficientFounds');
201 });197 });
202198
203 itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {199 itEth('(!negative test!) Check owner', async ({helper}) => {
204 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);200 const owner = await helper.eth.createAccountWithBalance(donor);
205 const notOwner = createEthAccount(web3);201 const peasant = helper.eth.createAccount();
206 const collectionHelpers = evmCollectionHelpers(web3, owner);202 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');
207 const result = await collectionHelpers.methods.createRFTCollection('A', 'A', 'A').send();
208 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);203 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);
209 const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress, {type: 'ReFungible'});
210 const EXPECTED_ERROR = 'NoPermission';204 const EXPECTED_ERROR = 'NoPermission';
211 {205 {
212 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);206 const sponsor = await helper.eth.createAccountWithBalance(donor);
213 await expect(contractEvmFromNotOwner.methods207 await expect(peasantCollection.methods
214 .setCollectionSponsor(sponsor)208 .setCollectionSponsor(sponsor)
215 .call()).to.be.rejectedWith(EXPECTED_ERROR);209 .call()).to.be.rejectedWith(EXPECTED_ERROR);
216 210
217 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);211 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
218 await expect(sponsorCollection.methods212 await expect(sponsorCollection.methods
219 .confirmCollectionSponsorship()213 .confirmCollectionSponsorship()
220 .call()).to.be.rejectedWith('caller is not set as sponsor');214 .call()).to.be.rejectedWith('caller is not set as sponsor');
221 }215 }
222 {216 {
223 await expect(contractEvmFromNotOwner.methods217 await expect(peasantCollection.methods
224 .setCollectionLimit('account_token_ownership_limit', '1000')218 .setCollectionLimit('account_token_ownership_limit', '1000')
225 .call()).to.be.rejectedWith(EXPECTED_ERROR);219 .call()).to.be.rejectedWith(EXPECTED_ERROR);
226 }220 }
227 });221 });
228222
229 itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {223 itEth('(!negative test!) Set limits', async ({helper}) => {
230 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);224 const owner = await helper.eth.createAccountWithBalance(donor);
231 const collectionHelpers = evmCollectionHelpers(web3, owner);225 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'ISNI');
232 const result = await collectionHelpers.methods.createRFTCollection('Schema collection', 'A', 'A').send();
233 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);226 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
234 const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
235 await expect(collectionEvm.methods227 await expect(collectionEvm.methods
236 .setCollectionLimit('badLimit', 'true')228 .setCollectionLimit('badLimit', 'true')
237 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');229 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
modifiedtests/src/eth/crossTransfer.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17/*import {createCollectionExpectSuccess,
18 createFungibleItemExpectSuccess,
19 transferExpectSuccess,
20 transferFromExpectSuccess,
21 setCollectionLimitsExpectSuccess,
22 createItemExpectSuccess} from '../util/helpers';
23import {collectionIdToAddress,
24 createEthAccountWithBalance,
25 subToEth,
26 GAS_ARGS, itEth} from './util/helpers';
27import fungibleAbi from './fungibleAbi.json';
28import nonFungibleAbi from './nonFungibleAbi.json';*/
17import {createCollectionExpectSuccess,29import {itEth, usingEthPlaygrounds} from './util/playgrounds';
18 createFungibleItemExpectSuccess,
19 transferExpectSuccess,
20 transferFromExpectSuccess,
21 setCollectionLimitsExpectSuccess,
22 createItemExpectSuccess} from '../util/helpers';
23import {collectionIdToAddress,30import {CrossAccountId} from '../util/playgrounds/unique';
24 createEthAccountWithBalance,
25 subToEth,
26 GAS_ARGS, itWeb3} from './util/helpers';
27import fungibleAbi from './fungibleAbi.json';31import {IKeyringPair} from '@polkadot/types/types';
28import nonFungibleAbi from './nonFungibleAbi.json';
2932
30describe('Token transfer between substrate address and EVM address. Fungible', () => {33describe('Token transfer between substrate address and EVM address. Fungible', () => {
34 let donor: IKeyringPair;
35 let alice: IKeyringPair;
36 let bob: IKeyringPair;
37 let charlie: IKeyringPair;
38
39 before(async function() {
40 await usingEthPlaygrounds(async (helper, privateKey) => {
41 donor = privateKey('//Alice');
42 [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
43 });
44 });
45
31 itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({privateKeyWrapper}) => {46 itEth('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({helper}) => {
32 const collection = await createCollectionExpectSuccess({47 const bobCA = CrossAccountId.fromKeyring(bob);
33 name: 'token name',
34 mode: {type: 'Fungible', decimalPoints: 0},
35 });
36 const alice = privateKeyWrapper('//Alice');48 const charlieCA = CrossAccountId.fromKeyring(charlie);
49
37 const bob = privateKeyWrapper('//Bob');50 const collection = await helper.ft.mintCollection(alice);
38 const charlie = privateKeyWrapper('//Charlie');
39 await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});51 await collection.setLimits(alice, {ownerCanTransfer: true});
52
40 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});53 await collection.mint(alice, 200n);
41 await transferExpectSuccess(collection, 0, alice, {Ethereum: subToEth(charlie.address)} , 200, 'Fungible');54 await collection.transfer(alice, charlieCA.toEthereum(), 200n);
42 await transferFromExpectSuccess(collection, 0, alice, {Ethereum: subToEth(charlie.address)}, charlie, 50, 'Fungible');55 await collection.transferFrom(alice, charlieCA.toEthereum(), charlieCA, 50n);
43 await transferExpectSuccess(collection, 0, charlie, bob, 50, 'Fungible');56 await collection.transfer(charlie, bobCA, 50n);
44 });57 });
4558
46 itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({api, web3, privateKeyWrapper}) => {59 itEth('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({helper}) => {
47 const collection = await createCollectionExpectSuccess({60 const aliceProxy = await helper.eth.createAccountWithBalance(donor);
48 name: 'token name',
49 mode: {type: 'Fungible', decimalPoints: 0},
50 });
51 const alice = privateKeyWrapper('//Alice');61 const bobProxy = await helper.eth.createAccountWithBalance(donor);
62
52 const bob = privateKeyWrapper('//Bob');63 const collection = await helper.ft.mintCollection(alice);
53 await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});64 await collection.setLimits(alice, {ownerCanTransfer: true});
65
54 const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);66 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
55 const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);67 const contract = helper.ethNativeContract.collection(address, 'ft', aliceProxy);
5668
57 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, alice.address);
58 await transferExpectSuccess(collection, 0, alice, {Ethereum: aliceProxy} , 200, 'Fungible');69 await collection.mint(alice, 200n, {Ethereum: aliceProxy});
59 const address = collectionIdToAddress(collection);
60 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS});
61
62 await contract.methods.transfer(bobProxy, 50).send({from: aliceProxy});70 await contract.methods.transfer(bobProxy, 50).send({from: aliceProxy});
63 await transferFromExpectSuccess(collection, 0, alice, {Ethereum: bobProxy}, bob, 50, 'Fungible');71 await collection.transferFrom(alice, {Ethereum: bobProxy}, CrossAccountId.fromKeyring(bob), 50n);
64 await transferExpectSuccess(collection, 0, bob, alice, 50, 'Fungible');72 await collection.transfer(bob, CrossAccountId.fromKeyring(alice), 50n);
65 });73 });
66});74});
6775
68describe('Token transfer between substrate address and EVM address. NFT', () => {76describe('Token transfer between substrate address and EVM address. NFT', () => {
77 let donor: IKeyringPair;
78 let alice: IKeyringPair;
79 let bob: IKeyringPair;
80 let charlie: IKeyringPair;
81
82 before(async function() {
83 await usingEthPlaygrounds(async (helper, privateKey) => {
84 donor = privateKey('//Alice');
85 [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
86 });
87 });
88
69 itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({privateKeyWrapper}) => {89 itEth('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({helper}) => {
70 const collection = await createCollectionExpectSuccess({90 const charlieEth = CrossAccountId.fromKeyring(charlie, 'Ethereum');
71 name: 'token name',91
72 mode: {type: 'NFT'},
73 });
74 const alice = privateKeyWrapper('//Alice');92 const collection = await helper.nft.mintCollection(alice);
75 const bob = privateKeyWrapper('//Bob');
76 const charlie = privateKeyWrapper('//Charlie');
77 await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});93 await collection.setLimits(alice, {ownerCanTransfer: true});
78 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});94 const token = await collection.mintToken(alice);
79 await transferExpectSuccess(collection, tokenId, alice, {Ethereum: subToEth(charlie.address)}, 1, 'NFT');95 await token.transfer(alice, charlieEth);
80 await transferFromExpectSuccess(collection, tokenId, alice, {Ethereum: subToEth(charlie.address)}, charlie, 1, 'NFT');96 await token.transferFrom(alice, charlieEth, CrossAccountId.fromKeyring(charlie));
81 await transferExpectSuccess(collection, tokenId, charlie, bob, 1, 'NFT');97 await token.transfer(charlie, CrossAccountId.fromKeyring(bob));
82 });98 });
8399
84 itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({api, web3, privateKeyWrapper}) => {100 itEth('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({helper}) => {
85 const collection = await createCollectionExpectSuccess({101 const aliceProxy = await helper.eth.createAccountWithBalance(donor);
86 name: 'token name',
87 mode: {type: 'NFT'},
88 });
89 const alice = privateKeyWrapper('//Alice');102 const bobProxy = await helper.eth.createAccountWithBalance(donor);
103
90 const bob = privateKeyWrapper('//Bob');104 const collection = await helper.nft.mintCollection(alice);
91 const charlie = privateKeyWrapper('//Charlie');
92 await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});105 await collection.setLimits(alice, {ownerCanTransfer: true});
106
93 const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);107 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
94 const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);108 const contract = helper.ethNativeContract.collection(address, 'nft', aliceProxy);
109
95 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});110 const token = await collection.mintToken(alice);
96 await transferExpectSuccess(collection, tokenId, alice, {Ethereum: aliceProxy} , 1, 'NFT');111 await token.transfer(alice, {Ethereum: aliceProxy});
97 const address = collectionIdToAddress(collection);
98 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS});
99 await contract.methods.transfer(bobProxy, 1).send({from: aliceProxy});112 await contract.methods.transfer(bobProxy, 1).send({from: aliceProxy});
100 await transferFromExpectSuccess(collection, tokenId, alice, {Ethereum: bobProxy}, bob, 1, 'NFT');113 await token.transferFrom(alice, {Ethereum: bobProxy}, {Substrate: bob.address});
101 await transferExpectSuccess(collection, tokenId, bob, charlie, 1, 'NFT');114 await token.transfer(bob, {Substrate: charlie.address});
102 });115 });
103});116});
104117
modifiedtests/src/eth/helpersSmoke.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {expect} from 'chai';17import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
18import {createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers} from './util/helpers';18import {IKeyringPair} from '@polkadot/types/types';
1919
20describe('Helpers sanity check', () => {20describe('Helpers sanity check', () => {
21 let donor: IKeyringPair;
22
23 before(async function() {
24 await usingEthPlaygrounds(async (_helper, privateKey) => {
25 donor = privateKey('//Alice');
26 });
27 });
28
21 itWeb3('Contract owner is recorded', async ({api, web3, privateKeyWrapper}) => {29 itEth('Contract owner is recorded', async ({helper}) => {
22 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);30 const owner = await helper.eth.createAccountWithBalance(donor);
2331
24 const flipper = await deployFlipper(web3, owner);32 const flipper = await helper.eth.deployFlipper(owner);
2533
26 expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);34 expect(await helper.ethNativeContract.contractHelpers(owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);
27 });35 });
2836
29 itWeb3('Flipper is working', async ({api, web3, privateKeyWrapper}) => {37 itEth('Flipper is working', async ({helper}) => {
30 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);38 const owner = await helper.eth.createAccountWithBalance(donor);
39
31 const flipper = await deployFlipper(web3, owner);40 const flipper = await helper.eth.deployFlipper(owner);
3241
33 expect(await flipper.methods.getValue().call()).to.be.false;42 expect(await flipper.methods.getValue().call()).to.be.false;
34 await flipper.methods.flip().send({from: owner});43 await flipper.methods.flip().send({from: owner});
modifiedtests/src/eth/migration.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {expect} from 'chai';17import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';
18import {submitTransactionAsync} from '../substrate/substrate-api';
19import {createEthAccountWithBalance, GAS_ARGS, itWeb3} from './util/helpers';18import {IKeyringPair} from '@polkadot/types/types';
2019
21describe('EVM Migrations', () => {20describe('EVM Migrations', () => {
21 let superuser: IKeyringPair;
22
23 before(async function() {
24 await usingEthPlaygrounds(async (_helper, privateKey) => {
25 superuser = privateKey('//Alice');
26 });
27 });
28
29 // todo:playgrounds requires sudo, look into later
22 itWeb3('Deploy contract saved state', async ({web3, api, privateKeyWrapper}) => {30 itEth('Deploy contract saved state', async ({helper}) => {
23 /*31 /*
24 contract StatefulContract {32 contract StatefulContract {
25 uint counter;33 uint counter;
53 ['0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643', '0x0000000000000000000000000000000000000000000000000000000000000004'],61 ['0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643', '0x0000000000000000000000000000000000000000000000000000000000000004'],
54 ];62 ];
63
64 const caller = await helper.eth.createAccountWithBalance(superuser);
5565
56 const alice = privateKeyWrapper('//Alice');66 const txBegin = helper.constructApiCall('api.tx.evmMigration.begin', [ADDRESS]);
57 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);67 const txSetData = helper.constructApiCall('api.tx.evmMigration.setData', [ADDRESS, DATA]);
5868 const txFinish = helper.constructApiCall('api.tx.evmMigration.finish', [ADDRESS, CODE]);
59 await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.begin(ADDRESS) as any));69 await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txBegin])).to.be.fulfilled;
60 await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.setData(ADDRESS, DATA as any) as any));70 await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txSetData])).to.be.fulfilled;
61 await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.finish(ADDRESS, CODE) as any));71 await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [txFinish])).to.be.fulfilled;
6272
73 const web3 = helper.getWeb3();
63 const contract = new web3.eth.Contract([74 const contract = new web3.eth.Contract([
64 {75 {
65 inputs: [],76 inputs: [],
87 stateMutability: 'view',98 stateMutability: 'view',
88 type: 'function',99 type: 'function',
89 },100 },
90 ], ADDRESS, {from: caller, ...GAS_ARGS});101 ], ADDRESS, {from: caller, gas: helper.eth.DEFAULT_GAS});
91102
92 expect(await contract.methods.counterValue().call()).to.be.equal('10');103 expect(await contract.methods.counterValue().call()).to.be.equal('10');
93 for (let i = 1; i <= 4; i++) {104 for (let i = 1; i <= 4; i++) {
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
171 });171 });
172172
173 //TODO: CORE-302 add eth methods173 //TODO: CORE-302 add eth methods
174 /* todo:playgrounds skipped test!174 itEth.skip('Can perform mintBulk()', async ({helper}) => {
175 itWeb3.skip('Can perform mintBulk()', async ({helper}) => {175 const caller = await helper.eth.createAccountWithBalance(donor);
176 const collection = await createCollectionExpectSuccess({176 const receiver = helper.eth.createAccount();
177 mode: {type: 'NFT'},177
178 });178 const collection = await helper.nft.mintCollection(alice);
179 const alice = privateKeyWrapper('//Alice');179 await collection.addAdmin(alice, {Ethereum: caller});
180180
181 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);181 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
182 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});182 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);
183 await submitTransactionAsync(alice, changeAdminTx);183 {
184 const receiver = createEthAccount(web3);184 const bulkSize = 3;
185185 const nextTokenId = await contract.methods.nextTokenId().call();
186 const address = collectionIdToAddress(collection);186 expect(nextTokenId).to.be.equal('1');
187 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});187 const result = await contract.methods.mintBulkWithTokenURI(
188188 receiver,
189 {189 Array.from({length: bulkSize}, (_, i) => (
190 const nextTokenId = await contract.methods.nextTokenId().call();190 [+nextTokenId + i, `Test URI ${i}`]
191 expect(nextTokenId).to.be.equal('1');191 )),
192 const result = await contract.methods.mintBulkWithTokenURI(192 ).send({from: caller});
193 receiver,193
194 [194 const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.tokenId - b.returnValues.tokenId);
195 [nextTokenId, 'Test URI 0'],195 for (let i = 0; i < bulkSize; i++) {
196 [+nextTokenId + 1, 'Test URI 1'],196 const event = events[i];
197 [+nextTokenId + 2, 'Test URI 2'],197 expect(event.address).to.equal(collectionAddress);
198 ],198 expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');
199 ).send({from: caller});199 expect(event.returnValues.to).to.equal(receiver);
200 const events = normalizeEvents(result.events);200 expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);
201201
202 expect(events).to.be.deep.equal([202 expect(await contract.methods.tokenURI(+nextTokenId + i).call()).to.be.equal(`Test URI ${i}`);
203 {203 }
204 address,204 }
205 event: 'Transfer',205 });
206 args: {
207 from: '0x0000000000000000000000000000000000000000',
208 to: receiver,
209 tokenId: nextTokenId,
210 },
211 },
212 {
213 address,
214 event: 'Transfer',
215 args: {
216 from: '0x0000000000000000000000000000000000000000',
217 to: receiver,
218 tokenId: String(+nextTokenId + 1),
219 },
220 },
221 {
222 address,
223 event: 'Transfer',
224 args: {
225 from: '0x0000000000000000000000000000000000000000',
226 to: receiver,
227 tokenId: String(+nextTokenId + 2),
228 },
229 },
230 ]);
231
232 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');
233 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');
234 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');
235 }
236 });
237 */
238206
239 itEth('Can perform burn()', async ({helper}) => {207 itEth('Can perform burn()', async ({helper}) => {
240 const caller = await helper.eth.createAccountWithBalance(donor);208 const caller = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth

no syntactic changes

modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
20 if (account.Ethereum) this.Ethereum = account.Ethereum;20 if (account.Ethereum) this.Ethereum = account.Ethereum;
21 }21 }
2222
23 static fromKeyring(account: IKeyringPair) {23 static fromKeyring(account: IKeyringPair, domain: 'Substrate' | 'Ethereum' = 'Substrate') {
24 switch (domain) {
24 return new CrossAccountId({Substrate: account.address});25 case 'Substrate': return new CrossAccountId({Substrate: account.address});
26 case 'Ethereum': return new CrossAccountId({Substrate: account.address}).toEthereum();
27 }
25 }28 }
2629
27 static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {30 static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {
41 return this;44 return this;
42 }45 }
43 46
47 static translateSubToEth(address: TSubstrateAccount): TEthereumAccount {
48 return nesting.toChecksumAddress('0x' + Array.from(addressToEvm(address), i => i.toString(16).padStart(2, '0')).join(''));
49 }
50
51 toEthereum(): CrossAccountId {
52 if (this.Substrate) return new CrossAccountId({Ethereum: CrossAccountId.translateSubToEth(this.Substrate)});
53 return this;
54 }
55
56 static translateEthToSub(address: TEthereumAccount, ss58Format?: number): TSubstrateAccount {
57 return evmToAddress(address, ss58Format);
58 }
59
60 toSubstrate(ss58Format?: number): CrossAccountId {
61 if (this.Ethereum) return new CrossAccountId({Substrate: CrossAccountId.translateEthToSub(this.Ethereum, ss58Format)});
62 return this;
63 }
64
44 toLowerCase(): CrossAccountId {65 toLowerCase(): CrossAccountId {
45 if (this.Substrate) this.Substrate = this.Substrate.toLowerCase();66 if (this.Substrate) this.Substrate = this.Substrate.toLowerCase();
2093 * @example normalizeSubstrateToChainFormat("5GrwvaEF5zXb26Fz...") // returns unjKJQJrRd238pkUZZ... for Unique Network2114 * @example normalizeSubstrateToChainFormat("5GrwvaEF5zXb26Fz...") // returns unjKJQJrRd238pkUZZ... for Unique Network
2094 * @returns address in chain format2115 * @returns address in chain format
2095 */2116 */
2096 async normalizeSubstrateToChainFormat(address: TSubstrateAccount): Promise<TSubstrateAccount> {2117 normalizeSubstrateToChainFormat(address: TSubstrateAccount): TSubstrateAccount {
2097 const info = this.helper.chain.getChainProperties();2118 return this.normalizeSubstrate(address, this.helper.chain.getChainProperties().ss58Format);
2098 return encodeAddress(decodeAddress(address), info.ss58Format);
2099 }2119 }
21002120
2101 /**2121 /**
2105 * @example ethToSubstrate('0x9F0583DbB855d...')2125 * @example ethToSubstrate('0x9F0583DbB855d...')
2106 * @returns substrate mirror of a provided ethereum address2126 * @returns substrate mirror of a provided ethereum address
2107 */2127 */
2108 async ethToSubstrate(ethAddress: TEthereumAccount, toChainFormat=false): Promise<TSubstrateAccount> {2128 ethToSubstrate(ethAddress: TEthereumAccount, toChainFormat=false): TSubstrateAccount {
2109 if(!toChainFormat) return evmToAddress(ethAddress);
2110 const info = this.helper.chain.getChainProperties();2129 return CrossAccountId.translateEthToSub(ethAddress, toChainFormat ? this.helper.chain.getChainProperties().ss58Format : undefined);
2111 return evmToAddress(ethAddress, info.ss58Format);
2112 }2130 }
21132131
2114 /**2132 /**
2118 * @returns ethereum mirror of a provided substrate address2136 * @returns ethereum mirror of a provided substrate address
2119 */2137 */
2120 substrateToEth(subAddress: TSubstrateAccount): TEthereumAccount {2138 substrateToEth(subAddress: TSubstrateAccount): TEthereumAccount {
2121 return nesting.toChecksumAddress('0x' + Array.from(addressToEvm(subAddress), i => i.toString(16).padStart(2, '0')).join(''));2139 return CrossAccountId.translateSubToEth(subAddress);
2122 }2140 }
2123}2141}
21242142