1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {itEth, usingEthPlaygrounds} from './eth/util';19import {itSub, Pallets, usingPlaygrounds, expect} from './util';20import {NON_EXISTENT_COLLECTION_ID} from './util/playgrounds/types';2122describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {23 let donor: IKeyringPair;24 let alice: IKeyringPair;25 let bob: IKeyringPair;2627 before(async () => {28 await usingPlaygrounds(async (helper, privateKey) => {29 donor = await privateKey({url: import.meta.url});30 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);31 });32 });3334 itSub('Balance transfers and check balance', async ({helper}) => {35 const alicesBalanceBefore = await helper.balance.getSubstrate(alice.address);36 const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);3738 expect(await helper.balance.transferToSubstrate(alice, bob.address, 1n)).to.be.true;3940 const alicesBalanceAfter = await helper.balance.getSubstrate(alice.address);41 const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address);4243 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;44 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;45 });4647 itSub('Inability to pay fees error message is correct', async ({helper}) => {48 const [zero] = await helper.arrange.createAccounts([0n], donor);4950 51 52 await expect(helper.balance.transferToSubstrate(zero, donor.address, 1n))53 .to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');54 });5556 itSub('[nft] User can transfer owned token', async ({helper}) => {57 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-1-NFT', description: '', tokenPrefix: 'T'});58 const nft = await collection.mintToken(alice);5960 await nft.transfer(alice, {Substrate: bob.address});61 expect(await nft.getOwner()).to.be.deep.equal({Substrate: bob.address});62 });6364 itSub('[fungible] User can transfer owned token', async ({helper}) => {65 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-1-FT', description: '', tokenPrefix: 'T'});66 await collection.mint(alice, 10n);6768 await collection.transfer(alice, {Substrate: bob.address}, 9n);69 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);70 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);71 });7273 itSub.ifWithPallets('[refungible] User can transfer owned token', [Pallets.ReFungible], async ({helper}) => {74 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});75 const rft = await collection.mintToken(alice, 10n);7677 await rft.transfer(alice, {Substrate: bob.address}, 9n);78 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);79 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);80 });8182 itSub('[nft] Collection admin can transfer owned token', async ({helper}) => {83 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-2-NFT', description: '', tokenPrefix: 'T'});84 await collection.addAdmin(alice, {Substrate: bob.address});8586 const nft = await collection.mintToken(bob, {Substrate: bob.address});87 await nft.transfer(bob, {Substrate: alice.address});8889 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});90 });9192 itSub('[fungible] Collection admin can transfer owned token', async ({helper}) => {93 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-2-FT', description: '', tokenPrefix: 'T'});94 await collection.addAdmin(alice, {Substrate: bob.address});9596 await collection.mint(bob, 10n, {Substrate: bob.address});97 await collection.transfer(bob, {Substrate: alice.address}, 1n);9899 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);100 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);101 });102103 itSub.ifWithPallets('[refungible] Collection admin can transfer owned token', [Pallets.ReFungible], async ({helper}) => {104 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-2-RFT', description: '', tokenPrefix: 'T'});105 await collection.addAdmin(alice, {Substrate: bob.address});106107 const rft = await collection.mintToken(bob, 10n, {Substrate: bob.address});108 await rft.transfer(bob, {Substrate: alice.address}, 1n);109110 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);111 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);112 });113});114115describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {116 let alice: IKeyringPair;117 let bob: IKeyringPair;118119 before(async () => {120 await usingPlaygrounds(async (helper, privateKey) => {121 const donor = await privateKey({url: import.meta.url});122 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);123 });124 });125126127 itSub('[nft] Transfer with not existed collection_id', async ({helper}) => {128 await expect(helper.nft.transferToken(alice, NON_EXISTENT_COLLECTION_ID, 1, {Substrate: bob.address}))129 .to.be.rejectedWith(/common\.CollectionNotFound/);130 });131132 itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => {133 await expect(helper.ft.transfer(alice, NON_EXISTENT_COLLECTION_ID, {Substrate: bob.address}))134 .to.be.rejectedWith(/common\.CollectionNotFound/);135 });136137 itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => {138 await expect(helper.rft.transferToken(alice, NON_EXISTENT_COLLECTION_ID, 1, {Substrate: bob.address}))139 .to.be.rejectedWith(/common\.CollectionNotFound/);140 });141142 itSub('[nft] Transfer with deleted collection_id', async ({helper}) => {143 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-1-NFT', description: '', tokenPrefix: 'T'});144 const nft = await collection.mintToken(alice);145146 await nft.burn(alice);147 await collection.burn(alice);148149 await expect(nft.transfer(alice, {Substrate: bob.address}))150 .to.be.rejectedWith(/common\.CollectionNotFound/);151 });152153 itSub('[fungible] Transfer with deleted collection_id', async ({helper}) => {154 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-1-FT', description: '', tokenPrefix: 'T'});155 await collection.mint(alice, 10n);156157 await collection.burnTokens(alice, 10n);158 await collection.burn(alice);159160 await expect(collection.transfer(alice, {Substrate: bob.address}))161 .to.be.rejectedWith(/common\.CollectionNotFound/);162 });163164 itSub.ifWithPallets('[refungible] Transfer with deleted collection_id', [Pallets.ReFungible], async ({helper}) => {165 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-1-RFT', description: '', tokenPrefix: 'T'});166 const rft = await collection.mintToken(alice, 10n);167168 await rft.burn(alice, 10n);169 await collection.burn(alice);170171 await expect(rft.transfer(alice, {Substrate: bob.address}))172 .to.be.rejectedWith(/common\.CollectionNotFound/);173 });174175 itSub('[nft] Transfer with not existed item_id', async ({helper}) => {176 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-2-NFT', description: '', tokenPrefix: 'T'});177 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))178 .to.be.rejectedWith(/common\.TokenNotFound/);179 });180181 itSub('[fungible] Transfer with not existed item_id', async ({helper}) => {182 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-2-FT', description: '', tokenPrefix: 'T'});183 await expect(collection.transfer(alice, {Substrate: bob.address}))184 .to.be.rejectedWith(/common\.TokenValueTooLow/);185 });186187 itSub.ifWithPallets('[refungible] Transfer with not existed item_id', [Pallets.ReFungible], async ({helper}) => {188 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-2-RFT', description: '', tokenPrefix: 'T'});189 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))190 .to.be.rejectedWith(/common\.TokenValueTooLow/);191 });192193 itSub('Zero transfer NFT', async ({helper}) => {194 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'});195 const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address});196 const tokenBob = await collection.mintToken(alice, {Substrate: bob.address});197 198 await helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: bob.address}, collection.collectionId, tokenAlice.tokenId, 0]);199 200 await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, tokenBob.tokenId, 0])).to.be.rejectedWith('common.NoPermission');201 202 await expect(helper.executeExtrinsic(alice, 'api.tx.unique.transfer', [{Substrate: alice.address}, collection.collectionId, 10, 0])).to.be.rejectedWith('common.TokenNotFound');203 expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: alice.address});204 expect(await tokenBob.getOwner()).to.deep.eq({Substrate: bob.address});205 206 await tokenAlice.transfer(alice, {Substrate: bob.address});207 await tokenBob.transfer(bob, {Substrate: alice.address});208 expect(await tokenAlice.getOwner()).to.deep.eq({Substrate: bob.address});209 expect(await tokenBob.getOwner()).to.deep.eq({Substrate: alice.address});210 });211212 itSub('[nft] Transfer with deleted item_id', async ({helper}) => {213 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'});214 const nft = await collection.mintToken(alice);215216 await nft.burn(alice);217218 await expect(nft.transfer(alice, {Substrate: bob.address}))219 .to.be.rejectedWith(/common\.TokenNotFound/);220 });221222 itSub('[fungible] Transfer with deleted item_id', async ({helper}) => {223 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-3-FT', description: '', tokenPrefix: 'T'});224 await collection.mint(alice, 10n);225226 await collection.burnTokens(alice, 10n);227228 await expect(collection.transfer(alice, {Substrate: bob.address}))229 .to.be.rejectedWith(/common\.TokenValueTooLow/);230 });231232 itSub.ifWithPallets('[refungible] Transfer with deleted item_id', [Pallets.ReFungible], async ({helper}) => {233 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-3-RFT', description: '', tokenPrefix: 'T'});234 const rft = await collection.mintToken(alice, 10n);235236 await rft.burn(alice, 10n);237238 await expect(rft.transfer(alice, {Substrate: bob.address}))239 .to.be.rejectedWith(/common\.TokenValueTooLow/);240 });241242 itSub('[nft] Transfer with recipient that is not owner', async ({helper}) => {243 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-4-NFT', description: '', tokenPrefix: 'T'});244 const nft = await collection.mintToken(alice);245246 await expect(nft.transfer(bob, {Substrate: bob.address}))247 .to.be.rejectedWith(/common\.NoPermission/);248 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});249 });250251 itSub('[fungible] Transfer with recipient that is not owner', async ({helper}) => {252 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-4-FT', description: '', tokenPrefix: 'T'});253 await collection.mint(alice, 10n);254255 await expect(collection.transfer(bob, {Substrate: bob.address}, 9n))256 .to.be.rejectedWith(/common\.TokenValueTooLow/);257 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);258 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(10n);259 });260261 itSub.ifWithPallets('[refungible] Transfer with recipient that is not owner', [Pallets.ReFungible], async ({helper}) => {262 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});263 const rft = await collection.mintToken(alice, 10n);264265 await expect(rft.transfer(bob, {Substrate: bob.address}, 9n))266 .to.be.rejectedWith(/common\.TokenValueTooLow/);267 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(0n);268 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(10n);269 });270});271272describe('Transfers to self (potentially over substrate-evm boundary)', () => {273 let donor: IKeyringPair;274275 before(async function() {276 await usingEthPlaygrounds(async (_, privateKey) => {277 donor = await privateKey({url: import.meta.url});278 });279 });280281 itEth('Transfers to self. In case of same frontend', async ({helper}) => {282 const [owner] = await helper.arrange.createAccounts([10n], donor);283 const collection = await helper.ft.mintCollection(owner, {});284 await collection.mint(owner, 100n);285286 const ownerProxy = helper.address.substrateToEth(owner.address);287288 289 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);290 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);291 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);292293 294 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Ethereum: ownerProxy}, 5n);295 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);296 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);297 });298299 itEth('Transfers to self. In case of substrate-evm boundary', async ({helper}) => {300 const [owner] = await helper.arrange.createAccounts([10n], donor);301 const collection = await helper.ft.mintCollection(owner, {});302 await collection.mint(owner, 100n);303304 const ownerProxy = helper.address.substrateToEth(owner.address);305306 307 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);308 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);309 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);310311 312 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Substrate: owner.address}, 5n);313 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(95n);314 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(5n);315 });316317 itEth('Transfers to self. In case of inside substrate-evm', async ({helper}) => {318 const [owner] = await helper.arrange.createAccounts([10n], donor);319 const collection = await helper.ft.mintCollection(owner, {});320 await collection.mint(owner, 100n);321322 323 await collection.transfer(owner, {Substrate: owner.address}, 10n);324 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);325326 327 await collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 5n);328 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);329 });330331 itEth('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({helper}) => {332 const [owner] = await helper.arrange.createAccounts([10n], donor);333 const collection = await helper.ft.mintCollection(owner, {});334 await collection.mint(owner, 10n);335336 337 await expect(collection.transfer(owner, {Substrate: owner.address}, 11n))338 .to.be.rejectedWith(/common\.TokenValueTooLow/);339340 341 await expect(collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 12n))342 .to.be.rejectedWith(/common\.TokenValueTooLow/);343 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(10n);344 });345});