1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {ApiPromise} from '@polkadot/api';19import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';21import {default as usingApi} from './substrate/substrate-api';22import {23 approveExpectFail,24 approveExpectSuccess,25 createCollectionExpectSuccess,26 createItemExpectSuccess,27 destroyCollectionExpectSuccess,28 setCollectionLimitsExpectSuccess,29 transferExpectSuccess,30 addCollectionAdminExpectSuccess,31 adminApproveFromExpectFail,32 getCreatedCollectionCount,33 transferFromExpectSuccess,34 transferFromExpectFail,35 requirePallets,36 Pallets,37} from './util/helpers';38import { usingPlaygrounds } from './util/playgrounds';3940let donor: IKeyringPair;4142before(async () => {43 await usingPlaygrounds(async (_, privateKeyWrapper) => {44 donor = privateKeyWrapper('//Alice');45 });46});4748chai.use(chaiAsPromised);49const expect = chai.expect;5051describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {52 let alice: IKeyringPair;53 let bob: IKeyringPair;54 let charlie: IKeyringPair;5556 before(async () => {57 await usingPlaygrounds(async (helper) => {58 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);59 });60 });6162 it('[nft] Execute the extrinsic and check approvedList', async () => {63 await usingPlaygrounds(async (helper) => {64 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});65 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});66 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});67 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;68 });69 });7071 it('[fungible] Execute the extrinsic and check approvedList', async () => {72 await usingPlaygrounds(async (helper) => {73 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);74 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);75 const tokenId = await helper.ft.getLastTokenId(collectionId);76 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});77 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});78 expect(amount).to.be.equal(BigInt(1));79 });80 });8182 it('[refungible] Execute the extrinsic and check approvedList', async function() {83 await usingPlaygrounds(async (helper) => {84 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});85 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});86 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});87 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});88 expect(amount).to.be.equal(BigInt(100));89 });90 });9192 it('[nft] Remove approval by using 0 amount', async () => {93 await usingPlaygrounds(async (helper) => {94 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});95 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});96 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});97 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;98 await helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);99 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;100 });101 });102103 it('[fungible] Remove approval by using 0 amount', async () => {104 await usingPlaygrounds(async (helper) => {105 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);106 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);107 const tokenId = await helper.ft.getLastTokenId(collectionId);108 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});109 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});110 expect(amountBefore).to.be.equal(BigInt(1));111112 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);113 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});114 expect(amountAfter).to.be.equal(BigInt(0));115 });116 });117118 it('[refungible] Remove approval by using 0 amount', async function() {119 await usingPlaygrounds(async (helper) => {120 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});121 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});122 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});123 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});124 expect(amountBefore).to.be.equal(BigInt(100));125126 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);127 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});128 expect(amountAfter).to.be.equal(BigInt(0));129 });130 });131132 it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {133 await usingPlaygrounds(async (helper) => {134 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});135 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});136 const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});137 await expect(approveTokenTx()).to.be.rejected;138 });139 });140});141142describe('Normal user can approve other users to transfer:', () => {143 let alice: IKeyringPair;144 let bob: IKeyringPair;145 let charlie: IKeyringPair;146147 before(async () => {148 await usingPlaygrounds(async (helper) => {149 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);150 });151 });152153 it('NFT', async () => {154 await usingPlaygrounds(async (helper) => {155 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});156 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});157 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});158 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;159 });160 });161162 it('Fungible up to an approved amount', async () => {163 await usingPlaygrounds(async (helper) => {164 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);165 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);166 const tokenId = await helper.ft.getLastTokenId(collectionId);167 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});168 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});169 expect(amount).to.be.equal(BigInt(1));170 });171 });172173 it('ReFungible up to an approved amount', async function() {174 await usingPlaygrounds(async (helper) => {175 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});176 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});177 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});178 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});179 expect(amount).to.be.equal(BigInt(100));180 });181 });182});183184describe('Approved users can transferFrom up to approved amount:', () => {185 let alice: IKeyringPair;186 let bob: IKeyringPair;187 let charlie: IKeyringPair;188189 before(async () => {190 await usingPlaygrounds(async (helper) => {191 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);192 });193 });194195 it('NFT', async () => {196 await usingPlaygrounds(async (helper) => {197 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});198 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});199 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});200 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});201 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);202 expect(owner.Substrate).to.be.equal(alice.address);203 });204 });205206 it('Fungible up to an approved amount', async () => {207 await usingPlaygrounds(async (helper) => {208 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);209 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);210 const tokenId = await helper.ft.getLastTokenId(collectionId);211 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});212 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});213 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);214 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});215 expect(after - before).to.be.equal(BigInt(1));216 });217 });218219 it('ReFungible up to an approved amount', async function() {220 await usingPlaygrounds(async (helper) => {221 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});222 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});223 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});224 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});225 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);226 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});227 expect(after - before).to.be.equal(BigInt(1));228 });229 });230});231232describe('Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:', () => {233 let alice: IKeyringPair;234 let bob: IKeyringPair;235 let charlie: IKeyringPair;236237 before(async () => {238 await usingPlaygrounds(async (helper) => {239 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);240 });241 });242243 it('NFT', async () => {244 await usingPlaygrounds(async (helper) => {245 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});246 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});247 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});248 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});249 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);250 expect(owner.Substrate).to.be.equal(alice.address);251 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});252 await expect(transferTokenFromTx()).to.be.rejected;253 });254 });255256 it('Fungible up to an approved amount', async () => {257 await usingPlaygrounds(async (helper) => {258 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);259 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);260 const tokenId = await helper.ft.getLastTokenId(collectionId);261 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});262 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});263 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);264 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});265 expect(after - before).to.be.equal(BigInt(1));266267 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);268 await expect(transferTokenFromTx()).to.be.rejected;269 });270 });271272 it('ReFungible up to an approved amount', async function() {273 await usingPlaygrounds(async (helper) => {274 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});275 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});276 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});277 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});278 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);279 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});280 expect(after - before).to.be.equal(BigInt(100));281 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);282 await expect(transferTokenFromTx()).to.be.rejected;283 });284 });285});286287describe('Approved amount decreases by the transferred amount.:', () => {288 let alice: IKeyringPair;289 let bob: IKeyringPair;290 let charlie: IKeyringPair;291 let dave: IKeyringPair;292293 before(async () => {294 await usingPlaygrounds(async (helper) => {295 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);296 });297 });298299 it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {300 await usingPlaygrounds(async (helper) => {301 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);302 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);303 const tokenId = await helper.ft.getLastTokenId(collectionId);304 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 10n);305306 const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});307 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);308 const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});309 expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));310311 const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});312 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);313 const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});314 expect(daveAfter - daveBefore).to.be.equal(BigInt(8));315 });316 });317});318319describe('User may clear the approvals to approving for 0 amount:', () => {320 let alice: IKeyringPair;321 let bob: IKeyringPair;322 let charlie: IKeyringPair;323324 before(async () => {325 await usingPlaygrounds(async (helper) => {326 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);327 });328 });329330 it('NFT', async () => {331 await usingPlaygrounds(async (helper) => {332 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});333 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});334 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});335 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;336 await helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);337 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;338 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});339 await expect(transferTokenFromTx()).to.be.rejected;340 });341 });342343 it('Fungible', async () => {344 await usingPlaygrounds(async (helper) => {345 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);346 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);347 const tokenId = await helper.ft.getLastTokenId(collectionId);348 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});349 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});350 expect(amountBefore).to.be.equal(BigInt(1));351352 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);353 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});354 expect(amountAfter).to.be.equal(BigInt(0));355356 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);357 await expect(transferTokenFromTx()).to.be.rejected;358 });359 });360361 it('ReFungible', async function() {362 await usingPlaygrounds(async (helper) => {363 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});364 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});365 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});366 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});367 expect(amountBefore).to.be.equal(BigInt(100));368369 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);370 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});371 expect(amountAfter).to.be.equal(BigInt(0));372373 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);374 await expect(transferTokenFromTx()).to.be.rejected;375 });376 });377});378379describe('User cannot approve for the amount greater than they own:', () => {380 let alice: IKeyringPair;381 let bob: IKeyringPair;382 let charlie: IKeyringPair;383384 before(async () => {385 await usingPlaygrounds(async (helper) => {386 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);387 });388 });389390 it('1 for NFT', async () => {391 await usingPlaygrounds(async (helper) => {392 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});393 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});394 await helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2).signAndSend(bob);395 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;396 });397 });398399 it('Fungible', async () => {400 await usingPlaygrounds(async (helper) => {401 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);402 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);403 const tokenId = await helper.ft.getLastTokenId(collectionId);404 const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 11n);405 await expect(approveTx()).to.be.rejected;406 });407 });408409 it('ReFungible', async function() {410 await usingPlaygrounds(async (helper) => {411 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});412 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});413 const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 101n);414 await expect(approveTx()).to.be.rejected;415 });416 });417});418419describe('Administrator and collection owner do not need approval in order to execute TransferFrom (with owner_can_transfer_flag = true):', () => {420 let alice: IKeyringPair;421 let bob: IKeyringPair;422 let charlie: IKeyringPair;423 let dave: IKeyringPair;424425 before(async () => {426 await usingPlaygrounds(async (helper) => {427 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);428 });429 });430431 it('NFT', async () => {432 await usingPlaygrounds(async (helper) => {433 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});434 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});435 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});436437 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});438 const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);439 expect(owner1.Substrate).to.be.equal(dave.address);440441 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});442 await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});443 const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);444 expect(owner2.Substrate).to.be.equal(alice.address);445 });446 });447448 it('Fungible up to an approved amount', async () => {449 await usingPlaygrounds(async (helper) => {450 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);451 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});452 await helper.ft.mintTokens(alice, collectionId, charlie.address, 10n);453 const tokenId = await helper.ft.getLastTokenId(collectionId);454455 const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});456 await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);457 const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});458 expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));459460 await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});461462 const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});463 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);464 const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});465 expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));466 });467 });468469 it('ReFungible up to an approved amount', async function() {470 await usingPlaygrounds(async (helper) => {471 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});472 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});473 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});474475 const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});476 await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);477 const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});478 expect(daveAfter - daveBefore).to.be.equal(BigInt(1));479480 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});481482 const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});483 await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);484 const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});485 expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));486 });487 });488});489490describe('Repeated approvals add up', () => {491 let alice: IKeyringPair;492 let bob: IKeyringPair;493 let charlie: IKeyringPair;494 let dave: IKeyringPair;495496 before(async () => {497 await usingPlaygrounds(async (helper) => {498 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);499 });500 });501502 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {503 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});504 await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);505 await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);506 await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);507 508 509 510 });511512 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {513 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});514 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);515 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);516 await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);517 518 519 520 });521522 523 it.skip('Cannot approve for more than total user`s amount (owned: 10, approval 1: 5 - should succeed, approval 2: 6 - should fail). Fungible', async () => {524 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});525 await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);526 await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);527 await approveExpectFail(collectionId, 0, dave, charlie, 6);528 });529530 531 it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {532 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});533 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);534 await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);535 await approveExpectFail(collectionId, itemId, dave, charlie, 51);536 });537});538539describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {540 let alice: IKeyringPair;541 let bob: IKeyringPair;542 let charlie: IKeyringPair;543544 before(async () => {545 await usingPlaygrounds(async (helper) => {546 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);547 });548 });549550 it('can be called by collection admin on non-owned item', async () => {551 await usingPlaygrounds(async (helper) => {552 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});553 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});554 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});555 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});556 await expect(approveTx()).to.be.rejected;557 });558 });559});560561describe('Negative Integration Test approve(spender, collection_id, item_id, amount):', () => {562 let alice: IKeyringPair;563 let bob: IKeyringPair;564 let charlie: IKeyringPair;565566 before(async () => {567 await usingPlaygrounds(async (helper) => {568 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);569 });570 });571572 it('[nft] Approve for a collection that does not exist', async () => {573 await usingPlaygrounds(async (helper) => {574 const collectionId = 1 << 32 - 1;575 const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});576 await expect(approveTx()).to.be.rejected;577 });578 });579580 it('[fungible] Approve for a collection that does not exist', async () => {581 await usingPlaygrounds(async (helper) => {582 const collectionId = 1 << 32 - 1;583 const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});584 await expect(approveTx()).to.be.rejected;585 });586 });587588 it('[refungible] Approve for a collection that does not exist', async function() {589 await usingPlaygrounds(async (helper) => {590 const collectionId = 1 << 32 - 1;591 const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});592 await expect(approveTx()).to.be.rejected;593 });594 });595596 it('[nft] Approve for a collection that was destroyed', async () => {597 await usingPlaygrounds(async (helper) => {598 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});599 await helper.nft.burn(alice, collectionId);600 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});601 await expect(approveTx()).to.be.rejected;602 });603 });604605 it('[fungible] Approve for a collection that was destroyed', async () => {606 await usingPlaygrounds(async (helper) => {607 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});608 await helper.ft.burn(alice, collectionId);609 const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});610 await expect(approveTx()).to.be.rejected;611 });612 });613614 it('[refungible] Approve for a collection that was destroyed', async function() {615 await usingPlaygrounds(async (helper) => {616 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});617 await helper.rft.burn(alice, collectionId);618 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});619 await expect(approveTx()).to.be.rejected;620 });621 });622623 it('[nft] Approve transfer of a token that does not exist', async () => {624 await usingPlaygrounds(async (helper) => {625 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});626 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});627 await expect(approveTx()).to.be.rejected;628 });629 });630631 it('[refungible] Approve transfer of a token that does not exist', async function() {632 await usingPlaygrounds(async (helper) => {633 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});634 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});635 await expect(approveTx()).to.be.rejected;636 });637 });638639 it('[nft] Approve using the address that does not own the approved token', async () => {640 await usingPlaygrounds(async (helper) => {641 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});642 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});643 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});644 await expect(approveTx()).to.be.rejected;645 });646 });647648 it('[fungible] Approve using the address that does not own the approved token', async () => {649 await usingPlaygrounds(async (helper) => {650 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});651 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);652 const tokenId = await helper.ft.getLastTokenId(collectionId);653 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});654 await expect(approveTx()).to.be.rejected;655 });656 });657658 it('[refungible] Approve using the address that does not own the approved token', async function() {659 await usingPlaygrounds(async (helper) => {660 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});661 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});662 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});663 await expect(approveTx()).to.be.rejected;664 });665 });666667 it('should fail if approved more ReFungibles than owned', async function() {668 await usingPlaygrounds(async (helper) => {669 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});670 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});671 await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);672 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 100n);673674 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 101n);675 await expect(approveTx()).to.be.rejected;676 });677 });678679 it('should fail if approved more Fungibles than owned', async () => {680 await usingPlaygrounds(async (helper) => {681 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});682 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);683 const tokenId = await helper.ft.getLastTokenId(collectionId);684685 await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);686 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 10n);687 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 11n);688 await expect(approveTx()).to.be.rejected;689 });690 });691692 it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {693 await usingPlaygrounds(async (helper) => {694 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});695 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});696 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});697698 const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});699 await expect(approveTx()).to.be.rejected;700 });701 });702});