git.delta.rocks / unique-network / refs/commits / 36c7382c2750

difftreelog

test mintBulk/metadata api

Yaroslav Bolyukin2021-09-01parent: #ac37b71.patch.diff
in: master

2 files changed

modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -4,9 +4,8 @@
 //
 
 import privateKey from '../substrate/privateKey';
-import { approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers';
+import { approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers';
 import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth } from './util/helpers';
-import { evmToAddress } from '@polkadot/util-crypto';
 import nonFungibleAbi from './nonFungibleAbi.json';
 import { expect } from 'chai';
 import waitNewBlocks from '../substrate/wait-new-blocks';
@@ -106,7 +105,70 @@
       expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
     }
   });
+  itWeb3.only('Can perform mintBulk()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const caller = await createEthAccountWithBalance(api, web3);
+    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: caller });
+    await submitTransactionAsync(alice, changeAdminTx);
+    const receiver = createEthAccount(web3);
 
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    {
+      const nextTokenId = await contract.methods.nextTokenId().call();
+      expect(nextTokenId).to.be.equal('1');
+      const result = await contract.methods.mintBulkWithTokenURI(
+        receiver,
+        [
+          [nextTokenId, 'Test URI 0'],
+          [+nextTokenId + 1, 'Test URI 1'],
+          [+nextTokenId + 2, 'Test URI 2'],
+        ],
+      ).send({ from: caller });
+      const events = normalizeEvents(result.events);
+
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: '0x0000000000000000000000000000000000000000',
+            to: receiver,
+            tokenId: nextTokenId,
+          },
+        },
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: '0x0000000000000000000000000000000000000000',
+            to: receiver,
+            tokenId: String(+nextTokenId + 1),
+          },
+        },
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: '0x0000000000000000000000000000000000000000',
+            to: receiver,
+            tokenId: String(+nextTokenId + 2),
+          },
+        },
+      ]);
+
+      await waitNewBlocks(api, 1);
+      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');
+      expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');
+      expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');
+    }
+  });
+
   itWeb3('Can perform burn()', async ({ web3, api }) => {
     const collection = await createCollectionExpectSuccess({
       mode: {type: 'NFT'},
@@ -264,6 +326,41 @@
       expect(+balance).to.equal(1);
     }
   });
+
+  itWeb3('Can perform getVariableMetadata', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    const item = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+    await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+    
+    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
+  });
+
+  itWeb3('Can perform setVariableMetadata', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    const item = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+    
+    expect(await contract.methods.setVariableMetadata(item, '0x010203').send({ from: owner }));
+    await waitNewBlocks(api, 1);
+    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
+  });
 });
 
 describe('NFT: Fees', () => {
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
before · tests/src/eth/nonFungibleAbi.json
1[2    {3        "anonymous": false,4        "inputs": [5            {6                "indexed": true,7                "internalType": "address",8                "name": "owner",9                "type": "address"10            },11            {12                "indexed": true,13                "internalType": "address",14                "name": "approved",15                "type": "address"16            },17            {18                "indexed": true,19                "internalType": "uint256",20                "name": "tokenId",21                "type": "uint256"22            }23        ],24        "name": "Approval",25        "type": "event"26    },27    {28        "anonymous": false,29        "inputs": [30            {31                "indexed": true,32                "internalType": "address",33                "name": "owner",34                "type": "address"35            },36            {37                "indexed": true,38                "internalType": "address",39                "name": "operator",40                "type": "address"41            },42            {43                "indexed": false,44                "internalType": "bool",45                "name": "approved",46                "type": "bool"47            }48        ],49        "name": "ApprovalForAll",50        "type": "event"51    },52    {53        "anonymous": true,54        "inputs": [],55        "name": "MintingFinished",56        "type": "event"57    },58    {59        "anonymous": false,60        "inputs": [61            {62                "indexed": true,63                "internalType": "address",64                "name": "from",65                "type": "address"66            },67            {68                "indexed": true,69                "internalType": "address",70                "name": "to",71                "type": "address"72            },73            {74                "indexed": true,75                "internalType": "uint256",76                "name": "tokenId",77                "type": "uint256"78            }79        ],80        "name": "Transfer",81        "type": "event"82    },83    {84        "inputs": [85            {86                "internalType": "address",87                "name": "approved",88                "type": "address"89            },90            {91                "internalType": "uint256",92                "name": "tokenId",93                "type": "uint256"94            }95        ],96        "name": "approve",97        "outputs": [],98        "stateMutability": "nonpayable",99        "type": "function"100    },101    {102        "inputs": [103            {104                "internalType": "address",105                "name": "owner",106                "type": "address"107            }108        ],109        "name": "balanceOf",110        "outputs": [111            {112                "internalType": "uint256",113                "name": "",114                "type": "uint256"115            }116        ],117        "stateMutability": "view",118        "type": "function"119    },120    {121        "inputs": [122            {123                "internalType": "uint256",124                "name": "tokenId",125                "type": "uint256"126            }127        ],128        "name": "burn",129        "outputs": [],130        "stateMutability": "nonpayable",131        "type": "function"132    },133    {134        "inputs": [],135        "name": "finishMinting",136        "outputs": [137            {138                "internalType": "bool",139                "name": "",140                "type": "bool"141            }142        ],143        "stateMutability": "nonpayable",144        "type": "function"145    },146    {147        "inputs": [148            {149                "internalType": "uint256",150                "name": "tokenId",151                "type": "uint256"152            }153        ],154        "name": "getApproved",155        "outputs": [156            {157                "internalType": "address",158                "name": "",159                "type": "address"160            }161        ],162        "stateMutability": "view",163        "type": "function"164    },165    {166        "inputs": [167            {168                "internalType": "address",169                "name": "owner",170                "type": "address"171            },172            {173                "internalType": "address",174                "name": "operator",175                "type": "address"176            }177        ],178        "name": "isApprovedForAll",179        "outputs": [180            {181                "internalType": "address",182                "name": "",183                "type": "address"184            }185        ],186        "stateMutability": "view",187        "type": "function"188    },189    {190        "inputs": [191            {192                "internalType": "address",193                "name": "to",194                "type": "address"195            },196            {197                "internalType": "uint256",198                "name": "tokenId",199                "type": "uint256"200            }201        ],202        "name": "mint",203        "outputs": [204            {205                "internalType": "bool",206                "name": "",207                "type": "bool"208            }209        ],210        "stateMutability": "nonpayable",211        "type": "function"212    },213    {214        "inputs": [215            {216                "internalType": "address",217                "name": "to",218                "type": "address"219            },220            {221                "internalType": "uint256",222                "name": "tokenId",223                "type": "uint256"224            },225            {226                "internalType": "string",227                "name": "tokenURI",228                "type": "string"229            }230        ],231        "name": "mintWithTokenURI",232        "outputs": [233            {234                "internalType": "bool",235                "name": "",236                "type": "bool"237            }238        ],239        "stateMutability": "nonpayable",240        "type": "function"241    },242    {243        "inputs": [],244        "name": "mintingFinished",245        "outputs": [246            {247                "internalType": "bool",248                "name": "",249                "type": "bool"250            }251        ],252        "stateMutability": "view",253        "type": "function"254    },255    {256        "inputs": [],257        "name": "name",258        "outputs": [259            {260                "internalType": "string",261                "name": "",262                "type": "string"263            }264        ],265        "stateMutability": "view",266        "type": "function"267    },268    {269        "inputs": [],270        "name": "nextTokenId",271        "outputs": [272            {273                "internalType": "uint256",274                "name": "",275                "type": "uint256"276            }277        ],278        "stateMutability": "view",279        "type": "function"280    },281    {282        "inputs": [283            {284                "internalType": "uint256",285                "name": "tokenId",286                "type": "uint256"287            }288        ],289        "name": "ownerOf",290        "outputs": [291            {292                "internalType": "address",293                "name": "",294                "type": "address"295            }296        ],297        "stateMutability": "view",298        "type": "function"299    },300    {301        "inputs": [302            {303                "internalType": "address",304                "name": "from",305                "type": "address"306            },307            {308                "internalType": "address",309                "name": "to",310                "type": "address"311            },312            {313                "internalType": "uint256",314                "name": "tokenId",315                "type": "uint256"316            }317        ],318        "name": "safeTransferFrom",319        "outputs": [],320        "stateMutability": "nonpayable",321        "type": "function"322    },323    {324        "inputs": [325            {326                "internalType": "address",327                "name": "from",328                "type": "address"329            },330            {331                "internalType": "address",332                "name": "to",333                "type": "address"334            },335            {336                "internalType": "uint256",337                "name": "tokenId",338                "type": "uint256"339            },340            {341                "internalType": "bytes",342                "name": "data",343                "type": "bytes"344            }345        ],346        "name": "safeTransferFromWithData",347        "outputs": [],348        "stateMutability": "nonpayable",349        "type": "function"350    },351    {352        "inputs": [353            {354                "internalType": "address",355                "name": "operator",356                "type": "address"357            },358            {359                "internalType": "bool",360                "name": "approved",361                "type": "bool"362            }363        ],364        "name": "setApprovalForAll",365        "outputs": [],366        "stateMutability": "nonpayable",367        "type": "function"368    },369    {370        "inputs": [371            {372                "internalType": "uint32",373                "name": "interfaceId",374                "type": "uint32"375            }376        ],377        "name": "supportsInterface",378        "outputs": [379            {380                "internalType": "bool",381                "name": "",382                "type": "bool"383            }384        ],385        "stateMutability": "view",386        "type": "function"387    },388    {389        "inputs": [],390        "name": "symbol",391        "outputs": [392            {393                "internalType": "string",394                "name": "",395                "type": "string"396            }397        ],398        "stateMutability": "view",399        "type": "function"400    },401    {402        "inputs": [403            {404                "internalType": "uint256",405                "name": "index",406                "type": "uint256"407            }408        ],409        "name": "tokenByIndex",410        "outputs": [411            {412                "internalType": "uint256",413                "name": "",414                "type": "uint256"415            }416        ],417        "stateMutability": "view",418        "type": "function"419    },420    {421        "inputs": [422            {423                "internalType": "address",424                "name": "owner",425                "type": "address"426            },427            {428                "internalType": "uint256",429                "name": "index",430                "type": "uint256"431            }432        ],433        "name": "tokenOfOwnerByIndex",434        "outputs": [435            {436                "internalType": "uint256",437                "name": "",438                "type": "uint256"439            }440        ],441        "stateMutability": "view",442        "type": "function"443    },444    {445        "inputs": [446            {447                "internalType": "uint256",448                "name": "tokenId",449                "type": "uint256"450            }451        ],452        "name": "tokenURI",453        "outputs": [454            {455                "internalType": "string",456                "name": "",457                "type": "string"458            }459        ],460        "stateMutability": "view",461        "type": "function"462    },463    {464        "inputs": [],465        "name": "totalSupply",466        "outputs": [467            {468                "internalType": "uint256",469                "name": "",470                "type": "uint256"471            }472        ],473        "stateMutability": "view",474        "type": "function"475    },476    {477        "inputs": [478            {479                "internalType": "address",480                "name": "to",481                "type": "address"482            },483            {484                "internalType": "uint256",485                "name": "tokenId",486                "type": "uint256"487            }488        ],489        "name": "transfer",490        "outputs": [],491        "stateMutability": "nonpayable",492        "type": "function"493    },494    {495        "inputs": [496            {497                "internalType": "address",498                "name": "from",499                "type": "address"500            },501            {502                "internalType": "address",503                "name": "to",504                "type": "address"505            },506            {507                "internalType": "uint256",508                "name": "tokenId",509                "type": "uint256"510            }511        ],512        "name": "transferFrom",513        "outputs": [],514        "stateMutability": "nonpayable",515        "type": "function"516    }517]
after · tests/src/eth/nonFungibleAbi.json
1[2    {3        "anonymous": false,4        "inputs": [5            {6                "indexed": true,7                "internalType": "address",8                "name": "owner",9                "type": "address"10            },11            {12                "indexed": true,13                "internalType": "address",14                "name": "approved",15                "type": "address"16            },17            {18                "indexed": true,19                "internalType": "uint256",20                "name": "tokenId",21                "type": "uint256"22            }23        ],24        "name": "Approval",25        "type": "event"26    },27    {28        "anonymous": false,29        "inputs": [30            {31                "indexed": true,32                "internalType": "address",33                "name": "owner",34                "type": "address"35            },36            {37                "indexed": true,38                "internalType": "address",39                "name": "operator",40                "type": "address"41            },42            {43                "indexed": false,44                "internalType": "bool",45                "name": "approved",46                "type": "bool"47            }48        ],49        "name": "ApprovalForAll",50        "type": "event"51    },52    {53        "anonymous": false,54        "inputs": [],55        "name": "MintingFinished",56        "type": "event"57    },58    {59        "anonymous": false,60        "inputs": [61            {62                "indexed": true,63                "internalType": "address",64                "name": "from",65                "type": "address"66            },67            {68                "indexed": true,69                "internalType": "address",70                "name": "to",71                "type": "address"72            },73            {74                "indexed": true,75                "internalType": "uint256",76                "name": "tokenId",77                "type": "uint256"78            }79        ],80        "name": "Transfer",81        "type": "event"82    },83    {84        "inputs": [85            {86                "internalType": "address",87                "name": "approved",88                "type": "address"89            },90            {91                "internalType": "uint256",92                "name": "tokenId",93                "type": "uint256"94            }95        ],96        "name": "approve",97        "outputs": [],98        "stateMutability": "nonpayable",99        "type": "function"100    },101    {102        "inputs": [103            {104                "internalType": "address",105                "name": "owner",106                "type": "address"107            }108        ],109        "name": "balanceOf",110        "outputs": [111            {112                "internalType": "uint256",113                "name": "",114                "type": "uint256"115            }116        ],117        "stateMutability": "view",118        "type": "function"119    },120    {121        "inputs": [122            {123                "internalType": "uint256",124                "name": "tokenId",125                "type": "uint256"126            }127        ],128        "name": "burn",129        "outputs": [],130        "stateMutability": "nonpayable",131        "type": "function"132    },133    {134        "inputs": [],135        "name": "finishMinting",136        "outputs": [137            {138                "internalType": "bool",139                "name": "",140                "type": "bool"141            }142        ],143        "stateMutability": "nonpayable",144        "type": "function"145    },146    {147        "inputs": [148            {149                "internalType": "uint256",150                "name": "tokenId",151                "type": "uint256"152            }153        ],154        "name": "getApproved",155        "outputs": [156            {157                "internalType": "address",158                "name": "",159                "type": "address"160            }161        ],162        "stateMutability": "view",163        "type": "function"164    },165    {166        "inputs": [167            {168                "internalType": "uint256",169                "name": "tokenId",170                "type": "uint256"171            }172        ],173        "name": "getVariableMetadata",174        "outputs": [175            {176                "internalType": "bytes",177                "name": "",178                "type": "bytes"179            }180        ],181        "stateMutability": "view",182        "type": "function"183    },184    {185        "inputs": [186            {187                "internalType": "address",188                "name": "owner",189                "type": "address"190            },191            {192                "internalType": "address",193                "name": "operator",194                "type": "address"195            }196        ],197        "name": "isApprovedForAll",198        "outputs": [199            {200                "internalType": "address",201                "name": "",202                "type": "address"203            }204        ],205        "stateMutability": "view",206        "type": "function"207    },208    {209        "inputs": [210            {211                "internalType": "address",212                "name": "to",213                "type": "address"214            },215            {216                "internalType": "uint256",217                "name": "tokenId",218                "type": "uint256"219            }220        ],221        "name": "mint",222        "outputs": [223            {224                "internalType": "bool",225                "name": "",226                "type": "bool"227            }228        ],229        "stateMutability": "nonpayable",230        "type": "function"231    },232    {233        "inputs": [234            {235                "internalType": "address",236                "name": "to",237                "type": "address"238            },239            {240                "internalType": "uint256[]",241                "name": "tokenIds",242                "type": "uint256[]"243            }244        ],245        "name": "mintBulk",246        "outputs": [247            {248                "internalType": "bool",249                "name": "",250                "type": "bool"251            }252        ],253        "stateMutability": "nonpayable",254        "type": "function"255    },256    {257        "inputs": [258            {259                "internalType": "address",260                "name": "to",261                "type": "address"262            },263            {264                "components": [265                    {266                        "internalType": "uint256",267                        "name": "field_0",268                        "type": "uint256"269                    },270                    {271                        "internalType": "string",272                        "name": "field_1",273                        "type": "string"274                    }275                ],276                "internalType": "struct Tuple0[]",277                "name": "tokens",278                "type": "tuple[]"279            }280        ],281        "name": "mintBulkWithTokenURI",282        "outputs": [283            {284                "internalType": "bool",285                "name": "",286                "type": "bool"287            }288        ],289        "stateMutability": "nonpayable",290        "type": "function"291    },292    {293        "inputs": [294            {295                "internalType": "address",296                "name": "to",297                "type": "address"298            },299            {300                "internalType": "uint256",301                "name": "tokenId",302                "type": "uint256"303            },304            {305                "internalType": "string",306                "name": "tokenUri",307                "type": "string"308            }309        ],310        "name": "mintWithTokenURI",311        "outputs": [312            {313                "internalType": "bool",314                "name": "",315                "type": "bool"316            }317        ],318        "stateMutability": "nonpayable",319        "type": "function"320    },321    {322        "inputs": [],323        "name": "mintingFinished",324        "outputs": [325            {326                "internalType": "bool",327                "name": "",328                "type": "bool"329            }330        ],331        "stateMutability": "view",332        "type": "function"333    },334    {335        "inputs": [],336        "name": "name",337        "outputs": [338            {339                "internalType": "string",340                "name": "",341                "type": "string"342            }343        ],344        "stateMutability": "view",345        "type": "function"346    },347    {348        "inputs": [],349        "name": "nextTokenId",350        "outputs": [351            {352                "internalType": "uint256",353                "name": "",354                "type": "uint256"355            }356        ],357        "stateMutability": "view",358        "type": "function"359    },360    {361        "inputs": [362            {363                "internalType": "uint256",364                "name": "tokenId",365                "type": "uint256"366            }367        ],368        "name": "ownerOf",369        "outputs": [370            {371                "internalType": "address",372                "name": "",373                "type": "address"374            }375        ],376        "stateMutability": "view",377        "type": "function"378    },379    {380        "inputs": [381            {382                "internalType": "address",383                "name": "from",384                "type": "address"385            },386            {387                "internalType": "address",388                "name": "to",389                "type": "address"390            },391            {392                "internalType": "uint256",393                "name": "tokenId",394                "type": "uint256"395            }396        ],397        "name": "safeTransferFrom",398        "outputs": [],399        "stateMutability": "nonpayable",400        "type": "function"401    },402    {403        "inputs": [404            {405                "internalType": "address",406                "name": "from",407                "type": "address"408            },409            {410                "internalType": "address",411                "name": "to",412                "type": "address"413            },414            {415                "internalType": "uint256",416                "name": "tokenId",417                "type": "uint256"418            },419            {420                "internalType": "bytes",421                "name": "data",422                "type": "bytes"423            }424        ],425        "name": "safeTransferFromWithData",426        "outputs": [],427        "stateMutability": "nonpayable",428        "type": "function"429    },430    {431        "inputs": [432            {433                "internalType": "address",434                "name": "operator",435                "type": "address"436            },437            {438                "internalType": "bool",439                "name": "approved",440                "type": "bool"441            }442        ],443        "name": "setApprovalForAll",444        "outputs": [],445        "stateMutability": "nonpayable",446        "type": "function"447    },448    {449        "inputs": [450            {451                "internalType": "uint256",452                "name": "tokenId",453                "type": "uint256"454            },455            {456                "internalType": "bytes",457                "name": "data",458                "type": "bytes"459            }460        ],461        "name": "setVariableMetadata",462        "outputs": [],463        "stateMutability": "nonpayable",464        "type": "function"465    },466    {467        "inputs": [468            {469                "internalType": "uint32",470                "name": "interfaceId",471                "type": "uint32"472            }473        ],474        "name": "supportsInterface",475        "outputs": [476            {477                "internalType": "bool",478                "name": "",479                "type": "bool"480            }481        ],482        "stateMutability": "view",483        "type": "function"484    },485    {486        "inputs": [],487        "name": "symbol",488        "outputs": [489            {490                "internalType": "string",491                "name": "",492                "type": "string"493            }494        ],495        "stateMutability": "view",496        "type": "function"497    },498    {499        "inputs": [500            {501                "internalType": "uint256",502                "name": "index",503                "type": "uint256"504            }505        ],506        "name": "tokenByIndex",507        "outputs": [508            {509                "internalType": "uint256",510                "name": "",511                "type": "uint256"512            }513        ],514        "stateMutability": "view",515        "type": "function"516    },517    {518        "inputs": [519            {520                "internalType": "address",521                "name": "owner",522                "type": "address"523            },524            {525                "internalType": "uint256",526                "name": "index",527                "type": "uint256"528            }529        ],530        "name": "tokenOfOwnerByIndex",531        "outputs": [532            {533                "internalType": "uint256",534                "name": "",535                "type": "uint256"536            }537        ],538        "stateMutability": "view",539        "type": "function"540    },541    {542        "inputs": [543            {544                "internalType": "uint256",545                "name": "tokenId",546                "type": "uint256"547            }548        ],549        "name": "tokenURI",550        "outputs": [551            {552                "internalType": "string",553                "name": "",554                "type": "string"555            }556        ],557        "stateMutability": "view",558        "type": "function"559    },560    {561        "inputs": [],562        "name": "totalSupply",563        "outputs": [564            {565                "internalType": "uint256",566                "name": "",567                "type": "uint256"568            }569        ],570        "stateMutability": "view",571        "type": "function"572    },573    {574        "inputs": [575            {576                "internalType": "address",577                "name": "to",578                "type": "address"579            },580            {581                "internalType": "uint256",582                "name": "tokenId",583                "type": "uint256"584            }585        ],586        "name": "transfer",587        "outputs": [],588        "stateMutability": "nonpayable",589        "type": "function"590    },591    {592        "inputs": [593            {594                "internalType": "address",595                "name": "from",596                "type": "address"597            },598            {599                "internalType": "address",600                "name": "to",601                "type": "address"602            },603            {604                "internalType": "uint256",605                "name": "tokenId",606                "type": "uint256"607            }608        ],609        "name": "transferFrom",610        "outputs": [],611        "stateMutability": "nonpayable",612        "type": "function"613    }614]