difftreelog
CORE-386 Implement eth methods
in: master
5 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -253,6 +253,42 @@
save(self);
Ok(())
}
+
+ fn set_access(&mut self, caller: caller, mode: string) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ self.check_is_owner_or_admin(&caller)
+ .map_err(dispatch_to_evm::<T>)?;
+ self.collection.permissions.access = Some(match mode.as_str() {
+ "Normal" => AccessMode::Normal,
+ "AllowList" => AccessMode::AllowList,
+ _ => return Err("Not supported access mode".into()),
+ });
+ save(self);
+ Ok(())
+ }
+
+ fn add_to_allow_list(&self, caller: caller, user: address) -> Result<void> {
+ let caller = check_is_owner_or_admin(caller, self)?;
+ let user = T::CrossAccountId::from_eth(user);
+ <Pallet<T>>::toggle_allowlist(self, &caller, &user, true)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ fn remove_from_allow_list(&self, caller: caller, user: address) -> Result<void> {
+ let caller = check_is_owner_or_admin(caller, self)?;
+ let user = T::CrossAccountId::from_eth(user);
+ <Pallet<T>>::toggle_allowlist(self, &caller, &user, false)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ fn set_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
+ check_is_owner_or_admin(caller, self)?;
+ self.collection.permissions.mint_mode = Some(mode);
+ save(self);
+ Ok(())
+ }
}
fn check_is_owner<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<void> {
@@ -263,10 +299,7 @@
Ok(())
}
-fn check_is_owner_or_admin<T: Config>(
- caller: caller,
- collection: &CollectionHandle<T>,
-) -> Result<T::CrossAccountId> {
+fn check_is_owner_or_admin<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<T::CrossAccountId> {
let caller = T::CrossAccountId::from_eth(caller);
collection
.check_is_owner_or_admin(&caller)
@@ -274,11 +307,7 @@
Ok(caller)
}
-fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {
- // TODO possibly delete for the lack of transaction
- collection
- .check_is_internal()
- .map_err(dispatch_to_evm::<T>)?;
+fn save<T: Config>(collection: &CollectionHandle<T>) {
<crate::CollectionById<T>>::insert(collection.id, collection.collection.clone());
Ok(())
}
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -51,105 +51,6 @@
event MintingFinished();
}
-// Selector: 3a54513b
-contract Collection is Dummy, ERC165 {
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- public
- {
- require(false, stub_error);
- key;
- value;
- dummy = 0;
- }
-
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) public {
- require(false, stub_error);
- key;
- dummy = 0;
- }
-
- // Throws error if key not found
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
- public
- view
- returns (bytes memory)
- {
- require(false, stub_error);
- key;
- dummy;
- return hex"";
- }
-
- // Selector: ethSetSponsor(address) 8f9af356
- function ethSetSponsor(address sponsor) public {
- require(false, stub_error);
- sponsor;
- dummy = 0;
- }
-
- // Selector: ethConfirmSponsorship() a8580d1a
- function ethConfirmSponsorship() public {
- require(false, stub_error);
- dummy = 0;
- }
-
- // Selector: setLimit(string,uint32) 68db30ca
- function setLimit(string memory limit, uint32 value) public {
- require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Selector: setLimit(string,bool) ea67e4c2
- function setLimit(string memory limit, bool value) public {
- require(false, stub_error);
- limit;
- value;
- dummy = 0;
- }
-
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() public view returns (address) {
- require(false, stub_error);
- dummy;
- return 0x0000000000000000000000000000000000000000;
- }
-
- // Selector: addAdmin(address) 70480275
- function addAdmin(address newAdmin) public view {
- require(false, stub_error);
- newAdmin;
- dummy;
- }
-
- // Selector: removeAdmin(address) 1785f53c
- function removeAdmin(address admin) public view {
- require(false, stub_error);
- admin;
- dummy;
- }
-
- // Selector: setNesting(bool) e8fc50dd
- function setNesting(bool enable) public {
- require(false, stub_error);
- enable;
- dummy = 0;
- }
-
- // Selector: setNesting(bool,address[]) 7df12a9a
- function setNesting(bool enable, address[] memory collections) public {
- require(false, stub_error);
- enable;
- collections;
- dummy = 0;
- }
-}
-
// Selector: 41369377
contract TokenProperties is Dummy, ERC165 {
// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
@@ -479,6 +380,133 @@
}
}
+// Selector: f56cd7fa
+contract Collection is Dummy, ERC165 {
+ // Selector: setCollectionProperty(string,bytes) 2f073f66
+ function setCollectionProperty(string memory key, bytes memory value)
+ public
+ {
+ require(false, stub_error);
+ key;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: deleteCollectionProperty(string) 7b7debce
+ function deleteCollectionProperty(string memory key) public {
+ require(false, stub_error);
+ key;
+ dummy = 0;
+ }
+
+ // Throws error if key not found
+ //
+ // Selector: collectionProperty(string) cf24fd6d
+ function collectionProperty(string memory key)
+ public
+ view
+ returns (bytes memory)
+ {
+ require(false, stub_error);
+ key;
+ dummy;
+ return hex"";
+ }
+
+ // Selector: ethSetSponsor(address) 8f9af356
+ function ethSetSponsor(address sponsor) public {
+ require(false, stub_error);
+ sponsor;
+ dummy = 0;
+ }
+
+ // Selector: ethConfirmSponsorship() a8580d1a
+ function ethConfirmSponsorship() public {
+ require(false, stub_error);
+ dummy = 0;
+ }
+
+ // Selector: setLimit(string,uint32) 68db30ca
+ function setLimit(string memory limit, uint32 value) public {
+ require(false, stub_error);
+ limit;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: setLimit(string,bool) ea67e4c2
+ function setLimit(string memory limit, bool value) public {
+ require(false, stub_error);
+ limit;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: contractAddress() f6b4dfb4
+ function contractAddress() public view returns (address) {
+ require(false, stub_error);
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ // Selector: addAdmin(address) 70480275
+ function addAdmin(address newAdmin) public view {
+ require(false, stub_error);
+ newAdmin;
+ dummy;
+ }
+
+ // Selector: removeAdmin(address) 1785f53c
+ function removeAdmin(address admin) public view {
+ require(false, stub_error);
+ admin;
+ dummy;
+ }
+
+ // Selector: setNesting(bool) e8fc50dd
+ function setNesting(bool enable) public {
+ require(false, stub_error);
+ enable;
+ dummy = 0;
+ }
+
+ // Selector: setNesting(bool,address[]) 7df12a9a
+ function setNesting(bool enable, address[] memory collections) public {
+ require(false, stub_error);
+ enable;
+ collections;
+ dummy = 0;
+ }
+
+ // Selector: setAccess(string) 488f56aa
+ function setAccess(string memory mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+
+ // Selector: addToAllowList(address) 31f59102
+ function addToAllowList(address user) public view {
+ require(false, stub_error);
+ user;
+ dummy;
+ }
+
+ // Selector: removeFromAllowList(address) eba8dabc
+ function removeFromAllowList(address user) public view {
+ require(false, stub_error);
+ user;
+ dummy;
+ }
+
+ // Selector: setMintMode(bool) 5dea9bd5
+ function setMintMode(bool mode) public {
+ require(false, stub_error);
+ mode;
+ dummy = 0;
+ }
+}
+
contract UniqueNFT is
Dummy,
ERC165,
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -42,51 +42,6 @@
event MintingFinished();
}
-// Selector: 3a54513b
-interface Collection is Dummy, ERC165 {
- // Selector: setCollectionProperty(string,bytes) 2f073f66
- function setCollectionProperty(string memory key, bytes memory value)
- external;
-
- // Selector: deleteCollectionProperty(string) 7b7debce
- function deleteCollectionProperty(string memory key) external;
-
- // Throws error if key not found
- //
- // Selector: collectionProperty(string) cf24fd6d
- function collectionProperty(string memory key)
- external
- view
- returns (bytes memory);
-
- // Selector: ethSetSponsor(address) 8f9af356
- function ethSetSponsor(address sponsor) external;
-
- // Selector: ethConfirmSponsorship() a8580d1a
- function ethConfirmSponsorship() external;
-
- // Selector: setLimit(string,uint32) 68db30ca
- function setLimit(string memory limit, uint32 value) external;
-
- // Selector: setLimit(string,bool) ea67e4c2
- function setLimit(string memory limit, bool value) external;
-
- // Selector: contractAddress() f6b4dfb4
- function contractAddress() external view returns (address);
-
- // Selector: addAdmin(address) 70480275
- function addAdmin(address newAdmin) external view;
-
- // Selector: removeAdmin(address) 1785f53c
- function removeAdmin(address admin) external view;
-
- // Selector: setNesting(bool) e8fc50dd
- function setNesting(bool enable) external;
-
- // Selector: setNesting(bool,address[]) 7df12a9a
- function setNesting(bool enable, address[] memory collections) external;
-}
-
// Selector: 41369377
interface TokenProperties is Dummy, ERC165 {
// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
@@ -258,6 +213,63 @@
returns (bool);
}
+// Selector: f56cd7fa
+interface Collection is Dummy, ERC165 {
+ // Selector: setCollectionProperty(string,bytes) 2f073f66
+ function setCollectionProperty(string memory key, bytes memory value)
+ external;
+
+ // Selector: deleteCollectionProperty(string) 7b7debce
+ function deleteCollectionProperty(string memory key) external;
+
+ // Throws error if key not found
+ //
+ // Selector: collectionProperty(string) cf24fd6d
+ function collectionProperty(string memory key)
+ external
+ view
+ returns (bytes memory);
+
+ // Selector: ethSetSponsor(address) 8f9af356
+ function ethSetSponsor(address sponsor) external;
+
+ // Selector: ethConfirmSponsorship() a8580d1a
+ function ethConfirmSponsorship() external;
+
+ // Selector: setLimit(string,uint32) 68db30ca
+ function setLimit(string memory limit, uint32 value) external;
+
+ // Selector: setLimit(string,bool) ea67e4c2
+ function setLimit(string memory limit, bool value) external;
+
+ // Selector: contractAddress() f6b4dfb4
+ function contractAddress() external view returns (address);
+
+ // Selector: addAdmin(address) 70480275
+ function addAdmin(address newAdmin) external view;
+
+ // Selector: removeAdmin(address) 1785f53c
+ function removeAdmin(address admin) external view;
+
+ // Selector: setNesting(bool) e8fc50dd
+ function setNesting(bool enable) external;
+
+ // Selector: setNesting(bool,address[]) 7df12a9a
+ function setNesting(bool enable, address[] memory collections) external;
+
+ // Selector: setAccess(string) 488f56aa
+ function setAccess(string memory mode) external;
+
+ // Selector: addToAllowList(address) 31f59102
+ function addToAllowList(address user) external view;
+
+ // Selector: removeFromAllowList(address) eba8dabc
+ function removeFromAllowList(address user) external view;
+
+ // Selector: setMintMode(bool) 5dea9bd5
+ function setMintMode(bool mode) external;
+}
+
interface UniqueNFT is
Dummy,
ERC165,
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -221,6 +221,7 @@
expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
});
+ //TODO: CORE-302 add eth methods
itWeb3('Sponsoring collection from evm address via access list', async ({api, web3}) => {
const owner = await createEthAccountWithBalance(api, web3);
const collectionHelpers = evmCollectionHelpers(web3, owner);
@@ -228,65 +229,60 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const sponsor = await createEthAccountWithBalance(api, web3);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
- result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
+ result = await collectionEvm.methods.ethSetSponsor(sponsor).send({from: owner});
let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
- await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
+ await collectionEvm.methods.ethConfirmSponsorship().send({from: sponsor});
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isConfirmed).to.be.true;
expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
const user = createEthAccount(web3);
- let nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
expect(oldPermissions.mintMode).to.be.false;
expect(oldPermissions.access).to.be.equal('Normal');
- //TODO: change value, when enum generated
- await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
- await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
- await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
+ await collectionEvm.methods.setAccess('AllowList').send({from: owner});
+ await collectionEvm.methods.addToAllowList(user).send({from: owner});
+ await collectionEvm.methods.setMintMode(true).send({from: owner});
const newPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
expect(newPermissions.mintMode).to.be.true;
expect(newPermissions.access).to.be.equal('AllowList');
- const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
- const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
+ // const [alicesBalanceBefore] = await getBalance(api, [alicesPublicKey]);
- nextTokenId = await collectionEvm.methods.nextTokenId().call({from: user});
- expect(nextTokenId).to.be.equal('1');
- result = await collectionEvm.methods.mintWithTokenURI(
- user,
- nextTokenId,
- 'Test URI',
- ).send({from: user});
- const events = normalizeEvents(result.events);
- events[0].address = events[0].address.toLocaleLowerCase();
+ {
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const result = await collectionEvm.methods.mintWithTokenURI(
+ user,
+ nextTokenId,
+ 'Test URI',
+ ).call({from: user});
+ console.log(result);
+ const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address: collectionIdAddress.toLocaleLowerCase(),
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: user,
- tokenId: nextTokenId,
+ expect(events).to.be.deep.equal([
+ {
+ collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: nextTokenId,
+ },
},
- },
- ]);
-
- expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ ]);
- const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
- expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
- const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);
- expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ }
});
itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3}) => {
@@ -296,22 +292,23 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const sponsor = await createEthAccountWithBalance(api, web3);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
- result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
+ result = await collectionEvm.methods.ethSetSponsor(sponsor).send();
let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
+ await expect(collectionEvm.methods.ethConfirmSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
- await sponsorCollection.methods.confirmCollectionSponsorship().send();
+ await sponsorCollection.methods.ethConfirmSponsorship().send();
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
expect(collectionSub.sponsorship.isConfirmed).to.be.true;
expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
const user = createEthAccount(web3);
- await collectionEvm.methods.addCollectionAdmin(user).send();
+ await collectionEvm.methods.addAdmin(user).send();
const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
+
const userCollectionEvm = evmCollection(web3, user, collectionIdAddress);
const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth1[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 { "internalType": "address", "name": "newAdmin", "type": "address" }86 ],87 "name": "addAdmin",88 "outputs": [],89 "stateMutability": "view",90 "type": "function"91 },92 {93 "inputs": [94 { "internalType": "address", "name": "approved", "type": "address" },95 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }96 ],97 "name": "approve",98 "outputs": [],99 "stateMutability": "nonpayable",100 "type": "function"101 },102 {103 "inputs": [104 { "internalType": "address", "name": "owner", "type": "address" }105 ],106 "name": "balanceOf",107 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],108 "stateMutability": "view",109 "type": "function"110 },111 {112 "inputs": [113 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }114 ],115 "name": "burn",116 "outputs": [],117 "stateMutability": "nonpayable",118 "type": "function"119 },120 {121 "inputs": [122 { "internalType": "address", "name": "from", "type": "address" },123 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }124 ],125 "name": "burnFrom",126 "outputs": [],127 "stateMutability": "nonpayable",128 "type": "function"129 },130 {131 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],132 "name": "collectionProperty",133 "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],134 "stateMutability": "view",135 "type": "function"136 },137 {138 "inputs": [],139 "name": "confirmCollectionSponsorship",140 "outputs": [],141 "stateMutability": "nonpayable",142 "type": "function"143 },144 {145 "inputs": [],146 "name": "contractAddress",147 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],148 "stateMutability": "view",149 "type": "function"150 },151 {152 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],153 "name": "deleteCollectionProperty",154 "outputs": [],155 "stateMutability": "nonpayable",156 "type": "function"157 },158 {159 "inputs": [160 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },161 { "internalType": "string", "name": "key", "type": "string" }162 ],163 "name": "deleteProperty",164 "outputs": [],165 "stateMutability": "nonpayable",166 "type": "function"167 },168 {169 "inputs": [],170 "name": "finishMinting",171 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],172 "stateMutability": "nonpayable",173 "type": "function"174 },175 {176 "inputs": [177 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }178 ],179 "name": "getApproved",180 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],181 "stateMutability": "view",182 "type": "function"183 },184 {185 "inputs": [186 { "internalType": "address", "name": "owner", "type": "address" },187 { "internalType": "address", "name": "operator", "type": "address" }188 ],189 "name": "isApprovedForAll",190 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],191 "stateMutability": "view",192 "type": "function"193 },194 {195 "inputs": [196 { "internalType": "address", "name": "to", "type": "address" },197 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }198 ],199 "name": "mint",200 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],201 "stateMutability": "nonpayable",202 "type": "function"203 },204 {205 "inputs": [206 { "internalType": "address", "name": "to", "type": "address" },207 { "internalType": "uint256[]", "name": "tokenIds", "type": "uint256[]" }208 ],209 "name": "mintBulk",210 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],211 "stateMutability": "nonpayable",212 "type": "function"213 },214 {215 "inputs": [216 { "internalType": "address", "name": "to", "type": "address" },217 {218 "components": [219 { "internalType": "uint256", "name": "field_0", "type": "uint256" },220 { "internalType": "string", "name": "field_1", "type": "string" }221 ],222 "internalType": "struct Tuple0[]",223 "name": "tokens",224 "type": "tuple[]"225 }226 ],227 "name": "mintBulkWithTokenURI",228 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],229 "stateMutability": "nonpayable",230 "type": "function"231 },232 {233 "inputs": [234 { "internalType": "address", "name": "to", "type": "address" },235 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },236 { "internalType": "string", "name": "tokenUri", "type": "string" }237 ],238 "name": "mintWithTokenURI",239 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],240 "stateMutability": "nonpayable",241 "type": "function"242 },243 {244 "inputs": [],245 "name": "mintingFinished",246 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],247 "stateMutability": "view",248 "type": "function"249 },250 {251 "inputs": [],252 "name": "name",253 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],254 "stateMutability": "view",255 "type": "function"256 },257 {258 "inputs": [],259 "name": "nextTokenId",260 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],261 "stateMutability": "view",262 "type": "function"263 },264 {265 "inputs": [266 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }267 ],268 "name": "ownerOf",269 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],270 "stateMutability": "view",271 "type": "function"272 },273 {274 "inputs": [275 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },276 { "internalType": "string", "name": "key", "type": "string" }277 ],278 "name": "property",279 "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],280 "stateMutability": "view",281 "type": "function"282 },283 {284 "inputs": [285 { "internalType": "address", "name": "admin", "type": "address" }286 ],287 "name": "removeAdmin",288 "outputs": [],289 "stateMutability": "view",290 "type": "function"291 },292 {293 "inputs": [294 { "internalType": "address", "name": "from", "type": "address" },295 { "internalType": "address", "name": "to", "type": "address" },296 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }297 ],298 "name": "safeTransferFrom",299 "outputs": [],300 "stateMutability": "nonpayable",301 "type": "function"302 },303 {304 "inputs": [305 { "internalType": "address", "name": "from", "type": "address" },306 { "internalType": "address", "name": "to", "type": "address" },307 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },308 { "internalType": "bytes", "name": "data", "type": "bytes" }309 ],310 "name": "safeTransferFromWithData",311 "outputs": [],312 "stateMutability": "nonpayable",313 "type": "function"314 },315 {316 "inputs": [317 { "internalType": "address", "name": "operator", "type": "address" },318 { "internalType": "bool", "name": "approved", "type": "bool" }319 ],320 "name": "setApprovalForAll",321 "outputs": [],322 "stateMutability": "nonpayable",323 "type": "function"324 },325 {326 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],327 "name": "setCollectionAccess",328 "outputs": [],329 "stateMutability": "nonpayable",330 "type": "function"331 },332 {333 "inputs": [334 { "internalType": "string", "name": "limit", "type": "string" },335 { "internalType": "uint32", "name": "value", "type": "uint32" }336 ],337 "name": "setCollectionLimit",338 "outputs": [],339 "stateMutability": "nonpayable",340 "type": "function"341 },342 {343 "inputs": [344 { "internalType": "string", "name": "limit", "type": "string" },345 { "internalType": "bool", "name": "value", "type": "bool" }346 ],347 "name": "setCollectionLimit",348 "outputs": [],349 "stateMutability": "nonpayable",350 "type": "function"351 },352 {353 "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],354 "name": "setCollectionMintMode",355 "outputs": [],356 "stateMutability": "nonpayable",357 "type": "function"358 },359 {360 "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],361 "name": "setCollectionNesting",362 "outputs": [],363 "stateMutability": "nonpayable",364 "type": "function"365 },366 {367 "inputs": [368 { "internalType": "bool", "name": "enable", "type": "bool" },369 {370 "internalType": "address[]",371 "name": "collections",372 "type": "address[]"373 }374 ],375 "name": "setCollectionNesting",376 "outputs": [],377 "stateMutability": "nonpayable",378 "type": "function"379 },380 {381 "inputs": [382 { "internalType": "string", "name": "key", "type": "string" },383 { "internalType": "bytes", "name": "value", "type": "bytes" }384 ],385 "name": "setCollectionProperty",386 "outputs": [],387 "stateMutability": "nonpayable",388 "type": "function"389 },390 {391 "inputs": [392 { "internalType": "address", "name": "sponsor", "type": "address" }393 ],394 "name": "setCollectionSponsor",395 "outputs": [],396 "stateMutability": "nonpayable",397 "type": "function"398 },399 {400 "inputs": [401 { "internalType": "bool", "name": "enable", "type": "bool" },402 {403 "internalType": "address[]",404 "name": "collections",405 "type": "address[]"406 }407 ],408 "name": "setNesting",409 "outputs": [],410 "stateMutability": "nonpayable",411 "type": "function"412 },413 {414 "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],415 "name": "setNesting",416 "outputs": [],417 "stateMutability": "nonpayable",418 "type": "function"419 },420 {421 "inputs": [422 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },423 { "internalType": "string", "name": "key", "type": "string" },424 { "internalType": "bytes", "name": "value", "type": "bytes" }425 ],426 "name": "setProperty",427 "outputs": [],428 "stateMutability": "nonpayable",429 "type": "function"430 },431 {432 "inputs": [433 { "internalType": "string", "name": "key", "type": "string" },434 { "internalType": "bool", "name": "isMutable", "type": "bool" },435 { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },436 { "internalType": "bool", "name": "tokenOwner", "type": "bool" }437 ],438 "name": "setTokenPropertyPermission",439 "outputs": [],440 "stateMutability": "nonpayable",441 "type": "function"442 },443 {444 "inputs": [445 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }446 ],447 "name": "supportsInterface",448 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],449 "stateMutability": "view",450 "type": "function"451 },452 {453 "inputs": [],454 "name": "symbol",455 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],456 "stateMutability": "view",457 "type": "function"458 },459 {460 "inputs": [461 { "internalType": "uint256", "name": "index", "type": "uint256" }462 ],463 "name": "tokenByIndex",464 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],465 "stateMutability": "view",466 "type": "function"467 },468 {469 "inputs": [470 { "internalType": "address", "name": "owner", "type": "address" },471 { "internalType": "uint256", "name": "index", "type": "uint256" }472 ],473 "name": "tokenOfOwnerByIndex",474 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],475 "stateMutability": "view",476 "type": "function"477 },478 {479 "inputs": [480 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }481 ],482 "name": "tokenURI",483 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],484 "stateMutability": "view",485 "type": "function"486 },487 {488 "inputs": [],489 "name": "totalSupply",490 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],491 "stateMutability": "view",492 "type": "function"493 },494 {495 "inputs": [496 { "internalType": "address", "name": "to", "type": "address" },497 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }498 ],499 "name": "transfer",500 "outputs": [],501 "stateMutability": "nonpayable",502 "type": "function"503 },504 {505 "inputs": [506 { "internalType": "address", "name": "from", "type": "address" },507 { "internalType": "address", "name": "to", "type": "address" },508 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }509 ],510 "name": "transferFrom",511 "outputs": [],512 "stateMutability": "nonpayable",513 "type": "function"514 }515]