1234567891011121314151617import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';19import {20 createCollectionExpectSuccess,21 getBalance,22 createMultipleItemsExpectSuccess,23 isTokenExists,24 getLastTokenId,25 getAllowance,26 approve,27 transferFrom,28 createCollection,29 createRefungibleToken,30 transfer,31 burnItem,32 repartitionRFT,33 createCollectionWithPropsExpectSuccess,34 getDetailedCollectionInfo,35 normalizeAccountId,36 CrossAccountId,37 getCreateItemsResult,38 getDestroyItemsResult,39 getModuleNames,40 Pallets,41 requirePallets,42} from './util/helpers';4344import chai from 'chai';45import chaiAsPromised from 'chai-as-promised';46chai.use(chaiAsPromised);47const expect = chai.expect;4849let alice: IKeyringPair;50let bob: IKeyringPair;51525354describe('integration test: Refungible functionality:', async () => {55 before(async function() {56 await requirePallets(this, [Pallets.ReFungible]);5758 await usingApi(async (api, privateKeyWrapper) => {59 alice = privateKeyWrapper('//Alice');60 bob = privateKeyWrapper('//Bob');61 if (!getModuleNames(api).includes(Pallets.ReFungible)) this.skip();62 });63 64 });65 66 it('Create refungible collection and token', async () => {67 await usingApi(async api => {68 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});69 expect(createCollectionResult.success).to.be.true;70 const collectionId = createCollectionResult.collectionId;71 72 const itemCountBefore = await getLastTokenId(api, collectionId);73 const result = await createRefungibleToken(api, alice, collectionId, 100n);74 75 const itemCountAfter = await getLastTokenId(api, collectionId);76 77 78 79 expect(result.success).to.be.true;80 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);81 expect(collectionId).to.be.equal(result.collectionId);82 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());83 });84 });85 86 it('RPC method tokenOnewrs for refungible collection and token', async () => {87 await usingApi(async (api, privateKeyWrapper) => {88 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};89 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));90 91 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});92 const collectionId = createCollectionResult.collectionId;93 94 const result = await createRefungibleToken(api, alice, collectionId, 10_000n);95 const aliceTokenId = result.itemId;96 97 98 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);99 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);100 101 for (let i = 0; i < 7; i++) {102 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 50*(i+1));103 } 104 105 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);106 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));107 108 const aliceID = normalizeAccountId(alice);109 const bobId = normalizeAccountId(bob);110 111 112 113 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);114 expect(owners.length).to.be.equal(10);115 116 const eleven = privateKeyWrapper('11');117 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;118 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);119 });120 });121 122 it('Transfer token pieces', async () => {123 await usingApi(async api => {124 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;125 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;126127 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);128 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;129130 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);131 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);132 await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected;133 });134 });135136 it('Create multiple tokens', async () => {137 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});138 const args = [139 {ReFungible: {pieces: 1}},140 {ReFungible: {pieces: 2}},141 {ReFungible: {pieces: 100}},142 ];143 await createMultipleItemsExpectSuccess(alice, collectionId, args);144145 await usingApi(async api => { 146 const tokenId = await getLastTokenId(api, collectionId);147 expect(tokenId).to.be.equal(3);148 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);149 });150 });151152 it('Burn some pieces', async () => {153 await usingApi(async api => { 154 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;155 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;156 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;157 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);158 expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;159 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;160 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);161 });162 });163164 it('Burn all pieces', async () => {165 await usingApi(async api => { 166 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;167 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;168 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;169 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);170 expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;171 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;172 });173 });174175 it('Burn some pieces for multiple users', async () => {176 await usingApi(async api => { 177 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;178 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;179 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;180181 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);182 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;183184 185 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);186 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);187 expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true;188189 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);190 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;191 expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;192193 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);194 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;195 expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;196 197 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;198 });199 });200201 it('Set allowance for token', async () => {202 await usingApi(async api => {203 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;204 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;205206 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);207208 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;209 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);210211 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;212 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);213 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);214 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);215 });216 });217218 it('Repartition', async () => {219 await usingApi(async api => {220 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;221 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;222223 expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;224 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);225226 expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;227 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);228 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);229230 await expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).to.eventually.be.rejected;231232 expect(await transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;233 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);234 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(200n);235236 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;237 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;238 });239 });240241 it('Repartition with increased amount', async () => {242 await usingApi(async api => {243 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;244 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;245246 const tx = api.tx.unique.repartition(collectionId, tokenId, 200n);247 const events = await submitTransactionAsync(alice, tx);248 const substrateEvents = getCreateItemsResult(events);249 expect(substrateEvents).to.include.deep.members([250 {251 success: true,252 collectionId,253 itemId: tokenId,254 recipient: {Substrate: alice.address},255 amount: 100,256 },257 ]);258 });259 });260261 it('Repartition with decreased amount', async () => {262 await usingApi(async api => {263 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;264 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;265266 const tx = api.tx.unique.repartition(collectionId, tokenId, 50n);267 const events = await submitTransactionAsync(alice, tx);268 const substrateEvents = getDestroyItemsResult(events);269 expect(substrateEvents).to.include.deep.members([270 {271 success: true,272 collectionId,273 itemId: tokenId,274 owner: {Substrate: alice.address},275 amount: 50,276 },277 ]);278 });279 });280 281 it('Сreate new collection with properties', async () => {282 await usingApi(async api => {283 const properties = [{key: 'key1', value: 'val1'}];284 const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];285 const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},286 properties: properties,287 propPerm: propertyPermissions, 288 });289 const collection = (await getDetailedCollectionInfo(api, collectionId))!;290 expect(collection.properties.toHuman()).to.be.deep.equal(properties);291 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);292 });293 });294});295