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.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);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});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.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);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 await helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2).signAndSend(bob);384 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;385 });386 });387388 it('Fungible', async () => {389 await usingPlaygrounds(async (helper) => {390 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);391 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);392 const tokenId = await helper.ft.getLastTokenId(collectionId);393 const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);394 await expect(approveTx()).to.be.rejected;395 });396 });397398 it('ReFungible', async function() {399 await usingPlaygrounds(async (helper) => {400 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});401 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});402 const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);403 await expect(approveTx()).to.be.rejected;404 });405 });406});407408describe('Administrator and collection owner do not need approval in order to execute TransferFrom (with owner_can_transfer_flag = true):', () => {409 let alice: IKeyringPair;410 let bob: IKeyringPair;411 let charlie: IKeyringPair;412 let dave: IKeyringPair;413414 before(async () => {415 await usingPlaygrounds(async (helper) => {416 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);417 });418 });419420 it('NFT', async () => {421 await usingPlaygrounds(async (helper) => {422 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});423 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});424 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});425426 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});427 const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);428 expect(owner1.Substrate).to.be.equal(dave.address);429430 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});431 await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});432 const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);433 expect(owner2.Substrate).to.be.equal(alice.address);434 });435 });436437 it('Fungible up to an approved amount', async () => {438 await usingPlaygrounds(async (helper) => {439 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);440 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});441 await helper.ft.mintTokens(alice, collectionId, charlie.address, 10n);442 const tokenId = await helper.ft.getLastTokenId(collectionId);443444 const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});445 await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);446 const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});447 expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));448449 await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});450451 const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});452 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);453 const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});454 expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));455 });456 });457458 it('ReFungible up to an approved amount', async function() {459 await usingPlaygrounds(async (helper) => {460 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});461 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});462 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});463464 const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});465 await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);466 const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});467 expect(daveAfter - daveBefore).to.be.equal(BigInt(1));468469 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});470471 const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});472 await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);473 const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});474 expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));475 });476 });477});478479describe('Repeated approvals add up', () => {480 let alice: IKeyringPair;481 let bob: IKeyringPair;482 let charlie: IKeyringPair;483 let dave: IKeyringPair;484485 before(async () => {486 await usingPlaygrounds(async (helper) => {487 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);488 });489 });490491 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {492 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});493 await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);494 await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);495 await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);496 497 498 499 });500501 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {502 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});503 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);504 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);505 await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);506 507 508 509 });510511 512 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 () => {513 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});514 await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);515 await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);516 await approveExpectFail(collectionId, 0, dave, charlie, 6);517 });518519 520 it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {521 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});522 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);523 await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);524 await approveExpectFail(collectionId, itemId, dave, charlie, 51);525 });526});527528describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {529 let alice: IKeyringPair;530 let bob: IKeyringPair;531 let charlie: IKeyringPair;532533 before(async () => {534 await usingPlaygrounds(async (helper) => {535 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);536 });537 });538539 it('can be called by collection admin on non-owned item', async () => {540 await usingPlaygrounds(async (helper) => {541 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});542 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});543 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});544 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});545 await expect(approveTx()).to.be.rejected;546 });547 });548});549550describe('Negative Integration Test approve(spender, collection_id, item_id, amount):', () => {551 let alice: IKeyringPair;552 let bob: IKeyringPair;553 let charlie: IKeyringPair;554555 before(async () => {556 await usingPlaygrounds(async (helper) => {557 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);558 });559 });560561 it('[nft] Approve for a collection that does not exist', async () => {562 await usingPlaygrounds(async (helper) => {563 const collectionId = 1 << 32 - 1;564 const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});565 await expect(approveTx()).to.be.rejected;566 });567 });568569 it('[fungible] Approve for a collection that does not exist', async () => {570 await usingPlaygrounds(async (helper) => {571 const collectionId = 1 << 32 - 1;572 const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});573 await expect(approveTx()).to.be.rejected;574 });575 });576577 it('[refungible] Approve for a collection that does not exist', async function() {578 await usingPlaygrounds(async (helper) => {579 const collectionId = 1 << 32 - 1;580 const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});581 await expect(approveTx()).to.be.rejected;582 });583 });584585 it('[nft] Approve for a collection that was destroyed', async () => {586 await usingPlaygrounds(async (helper) => {587 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});588 await helper.nft.burn(alice, collectionId);589 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});590 await expect(approveTx()).to.be.rejected;591 });592 });593594 it('[fungible] Approve for a collection that was destroyed', async () => {595 await usingPlaygrounds(async (helper) => {596 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});597 await helper.ft.burn(alice, collectionId);598 const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});599 await expect(approveTx()).to.be.rejected;600 });601 });602603 it('[refungible] Approve for a collection that was destroyed', async function() {604 await usingPlaygrounds(async (helper) => {605 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});606 await helper.rft.burn(alice, collectionId);607 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});608 await expect(approveTx()).to.be.rejected;609 });610 });611612 it('[nft] Approve transfer of a token that does not exist', async () => {613 await usingPlaygrounds(async (helper) => {614 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});615 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});616 await expect(approveTx()).to.be.rejected;617 });618 });619620 it('[refungible] Approve transfer of a token that does not exist', async function() {621 await usingPlaygrounds(async (helper) => {622 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});623 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});624 await expect(approveTx()).to.be.rejected;625 });626 });627628 it('[nft] Approve using the address that does not own the approved token', async () => {629 await usingPlaygrounds(async (helper) => {630 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});631 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});632 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});633 await expect(approveTx()).to.be.rejected;634 });635 });636637 it('[fungible] Approve using the address that does not own the approved token', async () => {638 await usingPlaygrounds(async (helper) => {639 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});640 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);641 const tokenId = await helper.ft.getLastTokenId(collectionId);642 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});643 await expect(approveTx()).to.be.rejected;644 });645 });646647 it('[refungible] Approve using the address that does not own the approved token', async function() {648 await usingPlaygrounds(async (helper) => {649 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});650 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});651 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});652 await expect(approveTx()).to.be.rejected;653 });654 });655656 it('should fail if approved more ReFungibles than owned', async function() {657 await usingPlaygrounds(async (helper) => {658 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});659 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});660 await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);661 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);662663 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);664 await expect(approveTx()).to.be.rejected;665 });666 });667668 it('should fail if approved more Fungibles than owned', async () => {669 await usingPlaygrounds(async (helper) => {670 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});671 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);672 const tokenId = await helper.ft.getLastTokenId(collectionId);673674 await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);675 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);676 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);677 await expect(approveTx()).to.be.rejected;678 });679 });680681 it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {682 await usingPlaygrounds(async (helper) => {683 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});684 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});685 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});686687 const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});688 await expect(approveTx()).to.be.rejected;689 });690 });691});