1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';20import {21 approveExpectFail,22 approveExpectSuccess,23 createCollectionExpectSuccess,24 createItemExpectSuccess,25} from './util/helpers';26import {usingPlaygrounds} from './util/playgrounds';2728let donor: IKeyringPair;2930before(async () => {31 await usingPlaygrounds(async (_, privateKey) => {32 donor = privateKey('//Alice');33 });34});3536chai.use(chaiAsPromised);37const expect = chai.expect;3839describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {40 let alice: IKeyringPair;41 let bob: IKeyringPair;42 let charlie: IKeyringPair;4344 before(async () => {45 await usingPlaygrounds(async (helper) => {46 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);47 });48 });4950 it('[nft] Execute the extrinsic and check approvedList', async () => {51 await usingPlaygrounds(async (helper) => {52 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});53 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});54 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});55 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;56 });57 });5859 it('[fungible] Execute the extrinsic and check approvedList', async () => {60 await usingPlaygrounds(async (helper) => {61 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);62 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);63 const tokenId = await helper.ft.getLastTokenId(collectionId);64 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});65 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});66 expect(amount).to.be.equal(BigInt(1));67 });68 });6970 it('[refungible] Execute the extrinsic and check approvedList', async function() {71 await usingPlaygrounds(async (helper) => {72 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});73 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});74 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});75 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});76 expect(amount).to.be.equal(BigInt(1));77 });78 });7980 it('[nft] Remove approval by using 0 amount', async () => {81 await usingPlaygrounds(async (helper) => {82 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});83 const collectionId = collection.collectionId;84 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});85 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});86 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;87 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));88 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;89 });90 });9192 it('[fungible] Remove approval by using 0 amount', async () => {93 await usingPlaygrounds(async (helper) => {94 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);95 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);96 const tokenId = await helper.ft.getLastTokenId(collectionId);97 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});98 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});99 expect(amountBefore).to.be.equal(BigInt(1));100101 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);102 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});103 expect(amountAfter).to.be.equal(BigInt(0));104 });105 });106107 it('[refungible] Remove approval by using 0 amount', async function() {108 await usingPlaygrounds(async (helper) => {109 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});110 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});111 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});112 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});113 expect(amountBefore).to.be.equal(BigInt(1));114115 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);116 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});117 expect(amountAfter).to.be.equal(BigInt(0));118 });119 });120121 it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {122 await usingPlaygrounds(async (helper) => {123 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});124 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});125 const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});126 await expect(approveTokenTx()).to.be.rejected;127 });128 });129});130131describe('Normal user can approve other users to transfer:', () => {132 let alice: IKeyringPair;133 let bob: IKeyringPair;134 let charlie: IKeyringPair;135136 before(async () => {137 await usingPlaygrounds(async (helper) => {138 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);139 });140 });141142 it('NFT', async () => {143 await usingPlaygrounds(async (helper) => {144 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});145 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});146 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});147 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;148 });149 });150151 it('Fungible up to an approved amount', async () => {152 await usingPlaygrounds(async (helper) => {153 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);154 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);155 const tokenId = await helper.ft.getLastTokenId(collectionId);156 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});157 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});158 expect(amount).to.be.equal(BigInt(1));159 });160 });161162 it('ReFungible up to an approved amount', async function() {163 await usingPlaygrounds(async (helper) => {164 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});165 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});166 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);167 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});168 expect(amount).to.be.equal(BigInt(100n));169 });170 });171});172173describe('Approved users can transferFrom up to approved amount:', () => {174 let alice: IKeyringPair;175 let bob: IKeyringPair;176 let charlie: IKeyringPair;177178 before(async () => {179 await usingPlaygrounds(async (helper) => {180 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);181 });182 });183184 it('NFT', async () => {185 await usingPlaygrounds(async (helper) => {186 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});187 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});188 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});189 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});190 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);191 expect(owner.Substrate).to.be.equal(alice.address);192 });193 });194195 it('Fungible up to an approved amount', async () => {196 await usingPlaygrounds(async (helper) => {197 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);198 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);199 const tokenId = await helper.ft.getLastTokenId(collectionId);200 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});201 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});202 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);203 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});204 expect(after - before).to.be.equal(BigInt(1));205 });206 });207208 it('ReFungible up to an approved amount', async function() {209 await usingPlaygrounds(async (helper) => {210 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});211 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});212 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});213 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});214 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);215 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});216 expect(after - before).to.be.equal(BigInt(1));217 });218 });219});220221describe('Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:', () => {222 let alice: IKeyringPair;223 let bob: IKeyringPair;224 let charlie: IKeyringPair;225226 before(async () => {227 await usingPlaygrounds(async (helper) => {228 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);229 });230 });231232 it('NFT', async () => {233 await usingPlaygrounds(async (helper) => {234 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});235 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});236 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});237 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});238 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);239 expect(owner.Substrate).to.be.equal(alice.address);240 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});241 await expect(transferTokenFromTx()).to.be.rejected;242 });243 });244245 it('Fungible up to an approved amount', async () => {246 await usingPlaygrounds(async (helper) => {247 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);248 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);249 const tokenId = await helper.ft.getLastTokenId(collectionId);250 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});251 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});252 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);253 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});254 expect(after - before).to.be.equal(BigInt(1));255256 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);257 await expect(transferTokenFromTx()).to.be.rejected;258 });259 });260261 it('ReFungible up to an approved amount', async function() {262 await usingPlaygrounds(async (helper) => {263 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});264 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});265 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);266 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});267 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);268 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});269 expect(after - before).to.be.equal(BigInt(100));270 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);271 await expect(transferTokenFromTx()).to.be.rejected;272 });273 });274});275276describe('Approved amount decreases by the transferred amount.:', () => {277 let alice: IKeyringPair;278 let bob: IKeyringPair;279 let charlie: IKeyringPair;280 let dave: IKeyringPair;281282 before(async () => {283 await usingPlaygrounds(async (helper) => {284 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);285 });286 });287288 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 () => {289 await usingPlaygrounds(async (helper) => {290 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);291 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);292 const tokenId = await helper.ft.getLastTokenId(collectionId);293 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);294295 const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});296 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);297 const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});298 expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));299300 const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});301 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);302 const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});303 expect(daveAfter - daveBefore).to.be.equal(BigInt(8));304 });305 });306});307308describe('User may clear the approvals to approving for 0 amount:', () => {309 let alice: IKeyringPair;310 let bob: IKeyringPair;311 let charlie: IKeyringPair;312313 before(async () => {314 await usingPlaygrounds(async (helper) => {315 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);316 });317 });318319 it('NFT', async () => {320 await usingPlaygrounds(async (helper) => {321 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});322 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});323 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});324 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;325 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));326 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;327 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});328 await expect(transferTokenFromTx()).to.be.rejected;329 });330 });331332 it('Fungible', async () => {333 await usingPlaygrounds(async (helper) => {334 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);335 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);336 const tokenId = await helper.ft.getLastTokenId(collectionId);337 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});338 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});339 expect(amountBefore).to.be.equal(BigInt(1));340341 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);342 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});343 expect(amountAfter).to.be.equal(BigInt(0));344345 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);346 await expect(transferTokenFromTx()).to.be.rejected;347 });348 });349350 it('ReFungible', async function() {351 await usingPlaygrounds(async (helper) => {352 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});353 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});354 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});355 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});356 expect(amountBefore).to.be.equal(BigInt(1));357358 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);359 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});360 expect(amountAfter).to.be.equal(BigInt(0));361362 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);363 await expect(transferTokenFromTx()).to.be.rejected;364 });365 });366});367368describe('User cannot approve for the amount greater than they own:', () => {369 let alice: IKeyringPair;370 let bob: IKeyringPair;371 let charlie: IKeyringPair;372373 before(async () => {374 await usingPlaygrounds(async (helper) => {375 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);376 });377 });378379 it('1 for NFT', async () => {380 await usingPlaygrounds(async (helper) => {381 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});382 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});383 const approveTx = async () => helper.signTransaction(bob, helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2));384 await expect(approveTx()).to.be.rejected;385 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;386 });387 });388389 it('Fungible', async () => {390 await usingPlaygrounds(async (helper) => {391 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);392 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);393 const tokenId = await helper.ft.getLastTokenId(collectionId);394 const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);395 await expect(approveTx()).to.be.rejected;396 });397 });398399 it('ReFungible', async function() {400 await usingPlaygrounds(async (helper) => {401 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});402 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});403 const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);404 await expect(approveTx()).to.be.rejected;405 });406 });407});408409describe('Administrator and collection owner do not need approval in order to execute TransferFrom (with owner_can_transfer_flag = true):', () => {410 let alice: IKeyringPair;411 let bob: IKeyringPair;412 let charlie: IKeyringPair;413 let dave: IKeyringPair;414415 before(async () => {416 await usingPlaygrounds(async (helper) => {417 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);418 });419 });420421 it('NFT', async () => {422 await usingPlaygrounds(async (helper) => {423 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});424 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});425 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});426427 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});428 const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);429 expect(owner1.Substrate).to.be.equal(dave.address);430431 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});432 await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});433 const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);434 expect(owner2.Substrate).to.be.equal(alice.address);435 });436 });437438 it('Fungible up to an approved amount', async () => {439 await usingPlaygrounds(async (helper) => {440 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);441 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});442 await helper.ft.mintTokens(alice, collectionId, charlie.address, 10n);443 const tokenId = await helper.ft.getLastTokenId(collectionId);444445 const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});446 await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);447 const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});448 expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));449450 await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});451452 const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});453 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);454 const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});455 expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));456 });457 });458459 it('ReFungible up to an approved amount', async function() {460 await usingPlaygrounds(async (helper) => {461 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});462 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});463 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});464465 const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});466 await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);467 const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});468 expect(daveAfter - daveBefore).to.be.equal(BigInt(1));469470 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});471472 const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});473 await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);474 const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});475 expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));476 });477 });478});479480describe('Repeated approvals add up', () => {481 let alice: IKeyringPair;482 let bob: IKeyringPair;483 let charlie: IKeyringPair;484 let dave: IKeyringPair;485486 before(async () => {487 await usingPlaygrounds(async (helper) => {488 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);489 });490 });491492 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {493 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});494 await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);495 await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);496 await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);497 498 499 500 });501502 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {503 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});504 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);505 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);506 await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);507 508 509 510 });511512 513 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 () => {514 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});515 await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);516 await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);517 await approveExpectFail(collectionId, 0, dave, charlie, 6);518 });519520 521 it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {522 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});523 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);524 await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);525 await approveExpectFail(collectionId, itemId, dave, charlie, 51);526 });527});528529describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {530 let alice: IKeyringPair;531 let bob: IKeyringPair;532 let charlie: IKeyringPair;533534 before(async () => {535 await usingPlaygrounds(async (helper) => {536 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);537 });538 });539540 it('can be called by collection admin on non-owned item', async () => {541 await usingPlaygrounds(async (helper) => {542 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});543 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});544 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});545 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});546 await expect(approveTx()).to.be.rejected;547 });548 });549});550551describe('Negative Integration Test approve(spender, collection_id, item_id, amount):', () => {552 let alice: IKeyringPair;553 let bob: IKeyringPair;554 let charlie: IKeyringPair;555556 before(async () => {557 await usingPlaygrounds(async (helper) => {558 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);559 });560 });561562 it('[nft] Approve for a collection that does not exist', async () => {563 await usingPlaygrounds(async (helper) => {564 const collectionId = 1 << 32 - 1;565 const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});566 await expect(approveTx()).to.be.rejected;567 });568 });569570 it('[fungible] Approve for a collection that does not exist', async () => {571 await usingPlaygrounds(async (helper) => {572 const collectionId = 1 << 32 - 1;573 const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});574 await expect(approveTx()).to.be.rejected;575 });576 });577578 it('[refungible] Approve for a collection that does not exist', async function() {579 await usingPlaygrounds(async (helper) => {580 const collectionId = 1 << 32 - 1;581 const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});582 await expect(approveTx()).to.be.rejected;583 });584 });585586 it('[nft] Approve for a collection that was destroyed', async () => {587 await usingPlaygrounds(async (helper) => {588 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});589 await helper.nft.burn(alice, collectionId);590 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});591 await expect(approveTx()).to.be.rejected;592 });593 });594595 it('[fungible] Approve for a collection that was destroyed', async () => {596 await usingPlaygrounds(async (helper) => {597 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});598 await helper.ft.burn(alice, collectionId);599 const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});600 await expect(approveTx()).to.be.rejected;601 });602 });603604 it('[refungible] Approve for a collection that was destroyed', async function() {605 await usingPlaygrounds(async (helper) => {606 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});607 await helper.rft.burn(alice, collectionId);608 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});609 await expect(approveTx()).to.be.rejected;610 });611 });612613 it('[nft] Approve transfer of a token that does not exist', async () => {614 await usingPlaygrounds(async (helper) => {615 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});616 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});617 await expect(approveTx()).to.be.rejected;618 });619 });620621 it('[refungible] Approve transfer of a token that does not exist', async function() {622 await usingPlaygrounds(async (helper) => {623 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});624 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});625 await expect(approveTx()).to.be.rejected;626 });627 });628629 it('[nft] Approve using the address that does not own the approved token', async () => {630 await usingPlaygrounds(async (helper) => {631 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});632 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});633 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});634 await expect(approveTx()).to.be.rejected;635 });636 });637638 it('[fungible] Approve using the address that does not own the approved token', async () => {639 await usingPlaygrounds(async (helper) => {640 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});641 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);642 const tokenId = await helper.ft.getLastTokenId(collectionId);643 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});644 await expect(approveTx()).to.be.rejected;645 });646 });647648 it('[refungible] Approve using the address that does not own the approved token', async function() {649 await usingPlaygrounds(async (helper) => {650 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});651 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});652 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});653 await expect(approveTx()).to.be.rejected;654 });655 });656657 it('should fail if approved more ReFungibles than owned', async function() {658 await usingPlaygrounds(async (helper) => {659 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});660 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});661 await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);662 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);663664 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);665 await expect(approveTx()).to.be.rejected;666 });667 });668669 it('should fail if approved more Fungibles than owned', async () => {670 await usingPlaygrounds(async (helper) => {671 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});672 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);673 const tokenId = await helper.ft.getLastTokenId(collectionId);674675 await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);676 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);677 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);678 await expect(approveTx()).to.be.rejected;679 });680 });681682 it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {683 await usingPlaygrounds(async (helper) => {684 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});685 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});686 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});687688 const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});689 await expect(approveTx()).to.be.rejected;690 });691 });692});