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(100));77 });78 });7980 it('[nft] Remove approval by using 0 amount', async () => {81 await usingPlaygrounds(async (helper) => {82 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});83 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});84 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});85 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;86 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);87 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;88 });89 });9091 it('[fungible] Remove approval by using 0 amount', async () => {92 await usingPlaygrounds(async (helper) => {93 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);94 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);95 const tokenId = await helper.ft.getLastTokenId(collectionId);96 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});97 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});98 expect(amountBefore).to.be.equal(BigInt(1));99100 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);101 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});102 expect(amountAfter).to.be.equal(BigInt(0));103 });104 });105106 it('[refungible] Remove approval by using 0 amount', async function() {107 await usingPlaygrounds(async (helper) => {108 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});109 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});110 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});111 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});112 expect(amountBefore).to.be.equal(BigInt(100));113114 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);115 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});116 expect(amountAfter).to.be.equal(BigInt(0));117 });118 });119120 it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {121 await usingPlaygrounds(async (helper) => {122 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});123 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});124 const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});125 await expect(approveTokenTx()).to.be.rejected;126 });127 });128});129130describe('Normal user can approve other users to transfer:', () => {131 let alice: IKeyringPair;132 let bob: IKeyringPair;133 let charlie: IKeyringPair;134135 before(async () => {136 await usingPlaygrounds(async (helper) => {137 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);138 });139 });140141 it('NFT', async () => {142 await usingPlaygrounds(async (helper) => {143 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});144 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});145 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});146 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;147 });148 });149150 it('Fungible up to an approved amount', async () => {151 await usingPlaygrounds(async (helper) => {152 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);153 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);154 const tokenId = await helper.ft.getLastTokenId(collectionId);155 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});156 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});157 expect(amount).to.be.equal(BigInt(1));158 });159 });160161 it('ReFungible up to an approved amount', async function() {162 await usingPlaygrounds(async (helper) => {163 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});164 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});165 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});166 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});167 expect(amount).to.be.equal(BigInt(100));168 });169 });170});171172describe('Approved users can transferFrom up to approved amount:', () => {173 let alice: IKeyringPair;174 let bob: IKeyringPair;175 let charlie: IKeyringPair;176177 before(async () => {178 await usingPlaygrounds(async (helper) => {179 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);180 });181 });182183 it('NFT', async () => {184 await usingPlaygrounds(async (helper) => {185 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});186 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});187 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});188 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});189 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);190 expect(owner.Substrate).to.be.equal(alice.address);191 });192 });193194 it('Fungible up to an approved amount', async () => {195 await usingPlaygrounds(async (helper) => {196 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);197 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);198 const tokenId = await helper.ft.getLastTokenId(collectionId);199 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});200 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});201 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);202 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});203 expect(after - before).to.be.equal(BigInt(1));204 });205 });206207 it('ReFungible up to an approved amount', async function() {208 await usingPlaygrounds(async (helper) => {209 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});210 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});211 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});212 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});213 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);214 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});215 expect(after - before).to.be.equal(BigInt(1));216 });217 });218});219220describe('Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:', () => {221 let alice: IKeyringPair;222 let bob: IKeyringPair;223 let charlie: IKeyringPair;224225 before(async () => {226 await usingPlaygrounds(async (helper) => {227 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);228 });229 });230231 it('NFT', async () => {232 await usingPlaygrounds(async (helper) => {233 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});234 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});235 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});236 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});237 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);238 expect(owner.Substrate).to.be.equal(alice.address);239 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});240 await expect(transferTokenFromTx()).to.be.rejected;241 });242 });243244 it('Fungible up to an approved amount', async () => {245 await usingPlaygrounds(async (helper) => {246 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);247 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);248 const tokenId = await helper.ft.getLastTokenId(collectionId);249 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});250 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});251 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);252 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});253 expect(after - before).to.be.equal(BigInt(1));254255 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);256 await expect(transferTokenFromTx()).to.be.rejected;257 });258 });259260 it('ReFungible up to an approved amount', async function() {261 await usingPlaygrounds(async (helper) => {262 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});263 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});264 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});265 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});266 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);267 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});268 expect(after - before).to.be.equal(BigInt(100));269 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);270 await expect(transferTokenFromTx()).to.be.rejected;271 });272 });273});274275describe('Approved amount decreases by the transferred amount.:', () => {276 let alice: IKeyringPair;277 let bob: IKeyringPair;278 let charlie: IKeyringPair;279 let dave: IKeyringPair;280281 before(async () => {282 await usingPlaygrounds(async (helper) => {283 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);284 });285 });286287 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 () => {288 await usingPlaygrounds(async (helper) => {289 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);290 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);291 const tokenId = await helper.ft.getLastTokenId(collectionId);292 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 10n);293294 const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});295 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);296 const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});297 expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));298299 const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});300 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);301 const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});302 expect(daveAfter - daveBefore).to.be.equal(BigInt(8));303 });304 });305});306307describe('User may clear the approvals to approving for 0 amount:', () => {308 let alice: IKeyringPair;309 let bob: IKeyringPair;310 let charlie: IKeyringPair;311312 before(async () => {313 await usingPlaygrounds(async (helper) => {314 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);315 });316 });317318 it('NFT', async () => {319 await usingPlaygrounds(async (helper) => {320 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});321 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});322 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});323 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;324 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);325 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;326 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});327 await expect(transferTokenFromTx()).to.be.rejected;328 });329 });330331 it('Fungible', async () => {332 await usingPlaygrounds(async (helper) => {333 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);334 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);335 const tokenId = await helper.ft.getLastTokenId(collectionId);336 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});337 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});338 expect(amountBefore).to.be.equal(BigInt(1));339340 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);341 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});342 expect(amountAfter).to.be.equal(BigInt(0));343344 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);345 await expect(transferTokenFromTx()).to.be.rejected;346 });347 });348349 it('ReFungible', async function() {350 await usingPlaygrounds(async (helper) => {351 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});352 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});353 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});354 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});355 expect(amountBefore).to.be.equal(BigInt(100));356357 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);358 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});359 expect(amountAfter).to.be.equal(BigInt(0));360361 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);362 await expect(transferTokenFromTx()).to.be.rejected;363 });364 });365});366367describe('User cannot approve for the amount greater than they own:', () => {368 let alice: IKeyringPair;369 let bob: IKeyringPair;370 let charlie: IKeyringPair;371372 before(async () => {373 await usingPlaygrounds(async (helper) => {374 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);375 });376 });377378 it('1 for NFT', async () => {379 await usingPlaygrounds(async (helper) => {380 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});381 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});382 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, undefined, 2n);383 await expect(approveTx()).to.be.rejected;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}, undefined, 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}, undefined, 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}, undefined, 100n);662663 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 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}, undefined, 10n);676 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 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});