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} from './util/helpers';4041import chai from 'chai';42import chaiAsPromised from 'chai-as-promised';43chai.use(chaiAsPromised);44const expect = chai.expect;4546let alice: IKeyringPair;47let bob: IKeyringPair;4849describe('integration test: Refungible functionality:', () => {50 before(async () => {51 await usingApi(async (api, privateKeyWrapper) => {52 alice = privateKeyWrapper('//Alice');53 bob = privateKeyWrapper('//Bob');54 });55 });5657 it('Create refungible collection and token', async () => {58 await usingApi(async api => {59 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});60 expect(createCollectionResult.success).to.be.true;61 const collectionId = createCollectionResult.collectionId;62 63 const itemCountBefore = await getLastTokenId(api, collectionId);64 const result = await createRefungibleToken(api, alice, collectionId, 100n);65 66 const itemCountAfter = await getLastTokenId(api, collectionId);67 68 69 70 expect(result.success).to.be.true;71 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);72 expect(collectionId).to.be.equal(result.collectionId);73 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());74 });75 });76 77 it('RPC method tokenOnewrs for refungible collection and token', async () => {78 await usingApi(async (api, privateKeyWrapper) => {79 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};80 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));81 82 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});83 const collectionId = createCollectionResult.collectionId;84 85 const result = await createRefungibleToken(api, alice, collectionId, 10_000n);86 const aliceTokenId = result.itemId;87 88 89 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);90 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);91 92 for (let i = 0; i < 7; i++) {93 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 50*(i+1));94 } 95 96 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);97 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));98 99 const aliceID = normalizeAccountId(alice);100 const bobId = normalizeAccountId(bob);101 102 103 104 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);105 expect(owners.length).to.be.equal(10);106 107 const eleven = privateKeyWrapper('11');108 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;109 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);110 });111 });112 113 it('Transfer token pieces', async () => {114 await usingApi(async api => {115 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;116 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;117118 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);119 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;120121 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);122 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);123 await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected;124 });125 });126127 it('Create multiple tokens', async () => {128 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});129 const args = [130 {ReFungible: {pieces: 1}},131 {ReFungible: {pieces: 2}},132 {ReFungible: {pieces: 100}},133 ];134 await createMultipleItemsExpectSuccess(alice, collectionId, args);135136 await usingApi(async api => { 137 const tokenId = await getLastTokenId(api, collectionId);138 expect(tokenId).to.be.equal(3);139 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);140 });141 });142143 it('Burn some pieces', async () => {144 await usingApi(async api => { 145 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;146 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;147 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;148 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);149 expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;150 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;151 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);152 });153 });154155 it('Burn all pieces', async () => {156 await usingApi(async api => { 157 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;158 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;159 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;160 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);161 expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;162 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;163 });164 });165166 it('Burn some pieces for multiple users', async () => {167 await usingApi(async api => { 168 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;169 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;170 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;171172 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);173 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;174175 176 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);177 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);178 expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true;179180 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);181 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;182 expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;183184 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);185 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;186 expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;187 188 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;189 });190 });191192 it('Set allowance for token', async () => {193 await usingApi(async api => {194 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;195 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;196197 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);198199 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;200 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);201202 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;203 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);204 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);205 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);206 });207 });208209 it('Repartition', async () => {210 await usingApi(async api => {211 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;212 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;213214 expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;215 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);216217 expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;218 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);219 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);220221 await expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).to.eventually.be.rejected;222223 expect(await transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;224 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);225 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(200n);226227 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;228 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;229 });230 });231232 it('Repartition with increased amount', async () => {233 await usingApi(async api => {234 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;235 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;236237 const tx = api.tx.unique.repartition(collectionId, tokenId, 200n);238 const events = await submitTransactionAsync(alice, tx);239 const substrateEvents = getCreateItemsResult(events);240 expect(substrateEvents).to.include.deep.members([241 {242 success: true,243 collectionId,244 itemId: tokenId,245 recipient: {Substrate: alice.address},246 amount: 100,247 },248 ]);249 });250 });251252 it('Repartition with decreased amount', async () => {253 await usingApi(async api => {254 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;255 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;256257 const tx = api.tx.unique.repartition(collectionId, tokenId, 50n);258 const events = await submitTransactionAsync(alice, tx);259 const substrateEvents = getDestroyItemsResult(events);260 expect(substrateEvents).to.include.deep.members([261 {262 success: true,263 collectionId,264 itemId: tokenId,265 owner: {Substrate: alice.address},266 amount: 50,267 },268 ]);269 });270 });271});272273describe('Test Refungible properties:', () => {274 before(async () => {275 await usingApi(async (api, privateKeyWrapper) => {276 alice = privateKeyWrapper('//Alice');277 bob = privateKeyWrapper('//Bob');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});