difftreelog
feat Add `collection_admins` method to eth collection.
in: master
19 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -580,7 +580,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
fn collection_owner(&self) -> Result<(address, uint256)> {
Ok(convert_cross_account_to_tuple::<T>(
@@ -616,13 +616,16 @@
// .map_err(dispatch_to_evm::<T>)
// }
- // TODO: need implement AbiWriter for &Vec<T>
- // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
- // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))
- // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))
- // .collect();
- // Ok(result)
- // }
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
+ let result = crate::IsAdmin::<T>::iter_prefix((self.id,))
+ .map(|(admin, _)| crate::eth::convert_cross_account_to_tuple::<T>(&admin))
+ .collect();
+ Ok(result)
+ }
}
/// ### Note
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -18,7 +18,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -282,7 +282,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -303,6 +303,18 @@
newOwner;
dummy = 0;
}
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() public view returns (Tuple6[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple6[](0);
+ }
}
/// @dev the ERC-165 identifier for this interface is 0x63034ac5
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -91,7 +91,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -355,7 +355,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -376,6 +376,18 @@
newOwner;
dummy = 0;
}
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() public view returns (Tuple17[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple17[](0);
+ }
}
/// @dev anonymous struct
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -91,7 +91,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -355,7 +355,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -376,6 +376,18 @@
newOwner;
dummy = 0;
}
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() public view returns (Tuple17[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple17[](0);
+ }
}
/// @dev anonymous struct
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -184,7 +184,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -197,6 +197,14 @@
/// @dev EVM selector for this function is: 0x4f53e226,
/// or in textual repr: changeCollectionOwner(address)
function changeCollectionOwner(address newOwner) external;
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() external view returns (Tuple6[] memory);
}
/// @dev the ERC-165 identifier for this interface is 0x63034ac5
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -62,7 +62,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -233,7 +233,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -246,6 +246,14 @@
/// @dev EVM selector for this function is: 0x4f53e226,
/// or in textual repr: changeCollectionOwner(address)
function changeCollectionOwner(address newOwner) external;
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() external view returns (Tuple17[] memory);
}
/// @dev anonymous struct
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -62,7 +62,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x62e22290
+/// @dev the ERC-165 identifier for this interface is 0x3af103fb
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -233,7 +233,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -246,6 +246,14 @@
/// @dev EVM selector for this function is: 0x4f53e226,
/// or in textual repr: changeCollectionOwner(address)
function changeCollectionOwner(address newOwner) external;
+
+ /// Get collection administrators
+ ///
+ /// @return Vector of tuples with admins address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0x5813216b,
+ /// or in textual repr: collectionAdmins()
+ function collectionAdmins() external view returns (Tuple17[] memory);
}
/// @dev anonymous struct
tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionAdmin.test.ts
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -14,6 +14,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
+import {IEthCrossAccountId} from '../util/playgrounds/types';
import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';
async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {
@@ -68,11 +69,31 @@
const newAdmin = helper.eth.createAccount();
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.false;
await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;
});
+
+ itEth.skip('Check adminlist', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ const admin1 = helper.eth.createAccount();
+ const [admin2] = await helper.arrange.createAccounts([10n], donor);
+ await collectionEvm.methods.addCollectionAdmin(admin1).send();
+ await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();
+ const adminListRpc = await helper.collection.getAdmins(collectionId);
+ let adminListEth = await collectionEvm.methods.collectionAdmins().call();
+ adminListEth = adminListEth.map((element: IEthCrossAccountId) => {
+ return helper.address.convertCrossAccountFromEthCrossAcoount(element);
+ });
+ expect(adminListRpc).to.be.like(adminListEth);
+ });
+
itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
tests/src/eth/fungibleAbi.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": "spender",15 "type": "address"16 },17 {18 "indexed": false,19 "internalType": "uint256",20 "name": "value",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": "from",34 "type": "address"35 },36 {37 "indexed": true,38 "internalType": "address",39 "name": "to",40 "type": "address"41 },42 {43 "indexed": false,44 "internalType": "uint256",45 "name": "value",46 "type": "uint256"47 }48 ],49 "name": "Transfer",50 "type": "event"51 },52 {53 "inputs": [54 { "internalType": "address", "name": "newAdmin", "type": "address" }55 ],56 "name": "addCollectionAdmin",57 "outputs": [],58 "stateMutability": "nonpayable",59 "type": "function"60 },61 {62 "inputs": [63 { "internalType": "address", "name": "user", "type": "address" }64 ],65 "name": "addToCollectionAllowList",66 "outputs": [],67 "stateMutability": "nonpayable",68 "type": "function"69 },70 {71 "inputs": [72 { "internalType": "address", "name": "owner", "type": "address" },73 { "internalType": "address", "name": "spender", "type": "address" }74 ],75 "name": "allowance",76 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],77 "stateMutability": "view",78 "type": "function"79 },80 {81 "inputs": [82 { "internalType": "address", "name": "user", "type": "address" }83 ],84 "name": "allowed",85 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],86 "stateMutability": "view",87 "type": "function"88 },89 {90 "inputs": [91 { "internalType": "address", "name": "spender", "type": "address" },92 { "internalType": "uint256", "name": "amount", "type": "uint256" }93 ],94 "name": "approve",95 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],96 "stateMutability": "nonpayable",97 "type": "function"98 },99 {100 "inputs": [101 { "internalType": "address", "name": "owner", "type": "address" }102 ],103 "name": "balanceOf",104 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],105 "stateMutability": "view",106 "type": "function"107 },108 {109 "inputs": [110 { "internalType": "address", "name": "from", "type": "address" },111 { "internalType": "uint256", "name": "amount", "type": "uint256" }112 ],113 "name": "burnFrom",114 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],115 "stateMutability": "nonpayable",116 "type": "function"117 },118 {119 "inputs": [120 { "internalType": "address", "name": "newOwner", "type": "address" }121 ],122 "name": "changeCollectionOwner",123 "outputs": [],124 "stateMutability": "nonpayable",125 "type": "function"126 },127 {128 "inputs": [],129 "name": "collectionOwner",130 "outputs": [131 {132 "components": [133 { "internalType": "address", "name": "field_0", "type": "address" },134 { "internalType": "uint256", "name": "field_1", "type": "uint256" }135 ],136 "internalType": "struct Tuple6",137 "name": "",138 "type": "tuple"139 }140 ],141 "stateMutability": "view",142 "type": "function"143 },144 {145 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],146 "name": "collectionProperty",147 "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],148 "stateMutability": "view",149 "type": "function"150 },151 {152 "inputs": [],153 "name": "collectionSponsor",154 "outputs": [155 {156 "components": [157 { "internalType": "address", "name": "field_0", "type": "address" },158 { "internalType": "uint256", "name": "field_1", "type": "uint256" }159 ],160 "internalType": "struct Tuple6",161 "name": "",162 "type": "tuple"163 }164 ],165 "stateMutability": "view",166 "type": "function"167 },168 {169 "inputs": [],170 "name": "confirmCollectionSponsorship",171 "outputs": [],172 "stateMutability": "nonpayable",173 "type": "function"174 },175 {176 "inputs": [],177 "name": "contractAddress",178 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],179 "stateMutability": "view",180 "type": "function"181 },182 {183 "inputs": [],184 "name": "decimals",185 "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],186 "stateMutability": "view",187 "type": "function"188 },189 {190 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],191 "name": "deleteCollectionProperty",192 "outputs": [],193 "stateMutability": "nonpayable",194 "type": "function"195 },196 {197 "inputs": [],198 "name": "hasCollectionPendingSponsor",199 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],200 "stateMutability": "view",201 "type": "function"202 },203 {204 "inputs": [205 { "internalType": "address", "name": "user", "type": "address" }206 ],207 "name": "isOwnerOrAdmin",208 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],209 "stateMutability": "view",210 "type": "function"211 },212 {213 "inputs": [214 { "internalType": "address", "name": "to", "type": "address" },215 { "internalType": "uint256", "name": "amount", "type": "uint256" }216 ],217 "name": "mint",218 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],219 "stateMutability": "nonpayable",220 "type": "function"221 },222 {223 "inputs": [224 {225 "components": [226 { "internalType": "address", "name": "field_0", "type": "address" },227 { "internalType": "uint256", "name": "field_1", "type": "uint256" }228 ],229 "internalType": "struct Tuple6[]",230 "name": "amounts",231 "type": "tuple[]"232 }233 ],234 "name": "mintBulk",235 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],236 "stateMutability": "nonpayable",237 "type": "function"238 },239 {240 "inputs": [],241 "name": "name",242 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],243 "stateMutability": "view",244 "type": "function"245 },246 {247 "inputs": [248 { "internalType": "address", "name": "admin", "type": "address" }249 ],250 "name": "removeCollectionAdmin",251 "outputs": [],252 "stateMutability": "nonpayable",253 "type": "function"254 },255 {256 "inputs": [],257 "name": "removeCollectionSponsor",258 "outputs": [],259 "stateMutability": "nonpayable",260 "type": "function"261 },262 {263 "inputs": [264 { "internalType": "address", "name": "user", "type": "address" }265 ],266 "name": "removeFromCollectionAllowList",267 "outputs": [],268 "stateMutability": "nonpayable",269 "type": "function"270 },271 {272 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],273 "name": "setCollectionAccess",274 "outputs": [],275 "stateMutability": "nonpayable",276 "type": "function"277 },278 {279 "inputs": [280 { "internalType": "string", "name": "limit", "type": "string" },281 { "internalType": "uint32", "name": "value", "type": "uint32" }282 ],283 "name": "setCollectionLimit",284 "outputs": [],285 "stateMutability": "nonpayable",286 "type": "function"287 },288 {289 "inputs": [290 { "internalType": "string", "name": "limit", "type": "string" },291 { "internalType": "bool", "name": "value", "type": "bool" }292 ],293 "name": "setCollectionLimit",294 "outputs": [],295 "stateMutability": "nonpayable",296 "type": "function"297 },298 {299 "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],300 "name": "setCollectionMintMode",301 "outputs": [],302 "stateMutability": "nonpayable",303 "type": "function"304 },305 {306 "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],307 "name": "setCollectionNesting",308 "outputs": [],309 "stateMutability": "nonpayable",310 "type": "function"311 },312 {313 "inputs": [314 { "internalType": "bool", "name": "enable", "type": "bool" },315 {316 "internalType": "address[]",317 "name": "collections",318 "type": "address[]"319 }320 ],321 "name": "setCollectionNesting",322 "outputs": [],323 "stateMutability": "nonpayable",324 "type": "function"325 },326 {327 "inputs": [328 { "internalType": "string", "name": "key", "type": "string" },329 { "internalType": "bytes", "name": "value", "type": "bytes" }330 ],331 "name": "setCollectionProperty",332 "outputs": [],333 "stateMutability": "nonpayable",334 "type": "function"335 },336 {337 "inputs": [338 { "internalType": "address", "name": "sponsor", "type": "address" }339 ],340 "name": "setCollectionSponsor",341 "outputs": [],342 "stateMutability": "nonpayable",343 "type": "function"344 },345 {346 "inputs": [347 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }348 ],349 "name": "supportsInterface",350 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],351 "stateMutability": "view",352 "type": "function"353 },354 {355 "inputs": [],356 "name": "symbol",357 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],358 "stateMutability": "view",359 "type": "function"360 },361 {362 "inputs": [],363 "name": "totalSupply",364 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],365 "stateMutability": "view",366 "type": "function"367 },368 {369 "inputs": [370 { "internalType": "address", "name": "to", "type": "address" },371 { "internalType": "uint256", "name": "amount", "type": "uint256" }372 ],373 "name": "transfer",374 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],375 "stateMutability": "nonpayable",376 "type": "function"377 },378 {379 "inputs": [380 { "internalType": "address", "name": "from", "type": "address" },381 { "internalType": "address", "name": "to", "type": "address" },382 { "internalType": "uint256", "name": "amount", "type": "uint256" }383 ],384 "name": "transferFrom",385 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],386 "stateMutability": "nonpayable",387 "type": "function"388 },389 {390 "inputs": [],391 "name": "uniqueCollectionType",392 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],393 "stateMutability": "view",394 "type": "function"395 }396]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": "spender",15 "type": "address"16 },17 {18 "indexed": false,19 "internalType": "uint256",20 "name": "value",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": "from",34 "type": "address"35 },36 {37 "indexed": true,38 "internalType": "address",39 "name": "to",40 "type": "address"41 },42 {43 "indexed": false,44 "internalType": "uint256",45 "name": "value",46 "type": "uint256"47 }48 ],49 "name": "Transfer",50 "type": "event"51 },52 {53 "inputs": [54 { "internalType": "address", "name": "newAdmin", "type": "address" }55 ],56 "name": "addCollectionAdmin",57 "outputs": [],58 "stateMutability": "nonpayable",59 "type": "function"60 },61 {62 "inputs": [63 { "internalType": "address", "name": "user", "type": "address" }64 ],65 "name": "addToCollectionAllowList",66 "outputs": [],67 "stateMutability": "nonpayable",68 "type": "function"69 },70 {71 "inputs": [72 { "internalType": "address", "name": "owner", "type": "address" },73 { "internalType": "address", "name": "spender", "type": "address" }74 ],75 "name": "allowance",76 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],77 "stateMutability": "view",78 "type": "function"79 },80 {81 "inputs": [82 { "internalType": "address", "name": "user", "type": "address" }83 ],84 "name": "allowed",85 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],86 "stateMutability": "view",87 "type": "function"88 },89 {90 "inputs": [91 { "internalType": "address", "name": "spender", "type": "address" },92 { "internalType": "uint256", "name": "amount", "type": "uint256" }93 ],94 "name": "approve",95 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],96 "stateMutability": "nonpayable",97 "type": "function"98 },99 {100 "inputs": [101 { "internalType": "address", "name": "owner", "type": "address" }102 ],103 "name": "balanceOf",104 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],105 "stateMutability": "view",106 "type": "function"107 },108 {109 "inputs": [110 { "internalType": "address", "name": "from", "type": "address" },111 { "internalType": "uint256", "name": "amount", "type": "uint256" }112 ],113 "name": "burnFrom",114 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],115 "stateMutability": "nonpayable",116 "type": "function"117 },118 {119 "inputs": [120 { "internalType": "address", "name": "newOwner", "type": "address" }121 ],122 "name": "changeCollectionOwner",123 "outputs": [],124 "stateMutability": "nonpayable",125 "type": "function"126 },127 {128 "inputs": [],129 "name": "collectionAdmins",130 "outputs": [131 {132 "components": [133 { "internalType": "address", "name": "field_0", "type": "address" },134 { "internalType": "uint256", "name": "field_1", "type": "uint256" }135 ],136 "internalType": "struct Tuple6[]",137 "name": "",138 "type": "tuple[]"139 }140 ],141 "stateMutability": "view",142 "type": "function"143 },144 {145 "inputs": [],146 "name": "collectionOwner",147 "outputs": [148 {149 "components": [150 { "internalType": "address", "name": "field_0", "type": "address" },151 { "internalType": "uint256", "name": "field_1", "type": "uint256" }152 ],153 "internalType": "struct Tuple6",154 "name": "",155 "type": "tuple"156 }157 ],158 "stateMutability": "view",159 "type": "function"160 },161 {162 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],163 "name": "collectionProperty",164 "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],165 "stateMutability": "view",166 "type": "function"167 },168 {169 "inputs": [],170 "name": "collectionSponsor",171 "outputs": [172 {173 "components": [174 { "internalType": "address", "name": "field_0", "type": "address" },175 { "internalType": "uint256", "name": "field_1", "type": "uint256" }176 ],177 "internalType": "struct Tuple6",178 "name": "",179 "type": "tuple"180 }181 ],182 "stateMutability": "view",183 "type": "function"184 },185 {186 "inputs": [],187 "name": "confirmCollectionSponsorship",188 "outputs": [],189 "stateMutability": "nonpayable",190 "type": "function"191 },192 {193 "inputs": [],194 "name": "contractAddress",195 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],196 "stateMutability": "view",197 "type": "function"198 },199 {200 "inputs": [],201 "name": "decimals",202 "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],203 "stateMutability": "view",204 "type": "function"205 },206 {207 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],208 "name": "deleteCollectionProperty",209 "outputs": [],210 "stateMutability": "nonpayable",211 "type": "function"212 },213 {214 "inputs": [],215 "name": "hasCollectionPendingSponsor",216 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],217 "stateMutability": "view",218 "type": "function"219 },220 {221 "inputs": [222 { "internalType": "address", "name": "user", "type": "address" }223 ],224 "name": "isOwnerOrAdmin",225 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],226 "stateMutability": "view",227 "type": "function"228 },229 {230 "inputs": [231 { "internalType": "address", "name": "to", "type": "address" },232 { "internalType": "uint256", "name": "amount", "type": "uint256" }233 ],234 "name": "mint",235 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],236 "stateMutability": "nonpayable",237 "type": "function"238 },239 {240 "inputs": [241 {242 "components": [243 { "internalType": "address", "name": "field_0", "type": "address" },244 { "internalType": "uint256", "name": "field_1", "type": "uint256" }245 ],246 "internalType": "struct Tuple6[]",247 "name": "amounts",248 "type": "tuple[]"249 }250 ],251 "name": "mintBulk",252 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],253 "stateMutability": "nonpayable",254 "type": "function"255 },256 {257 "inputs": [],258 "name": "name",259 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],260 "stateMutability": "view",261 "type": "function"262 },263 {264 "inputs": [265 { "internalType": "address", "name": "admin", "type": "address" }266 ],267 "name": "removeCollectionAdmin",268 "outputs": [],269 "stateMutability": "nonpayable",270 "type": "function"271 },272 {273 "inputs": [],274 "name": "removeCollectionSponsor",275 "outputs": [],276 "stateMutability": "nonpayable",277 "type": "function"278 },279 {280 "inputs": [281 { "internalType": "address", "name": "user", "type": "address" }282 ],283 "name": "removeFromCollectionAllowList",284 "outputs": [],285 "stateMutability": "nonpayable",286 "type": "function"287 },288 {289 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],290 "name": "setCollectionAccess",291 "outputs": [],292 "stateMutability": "nonpayable",293 "type": "function"294 },295 {296 "inputs": [297 { "internalType": "string", "name": "limit", "type": "string" },298 { "internalType": "uint32", "name": "value", "type": "uint32" }299 ],300 "name": "setCollectionLimit",301 "outputs": [],302 "stateMutability": "nonpayable",303 "type": "function"304 },305 {306 "inputs": [307 { "internalType": "string", "name": "limit", "type": "string" },308 { "internalType": "bool", "name": "value", "type": "bool" }309 ],310 "name": "setCollectionLimit",311 "outputs": [],312 "stateMutability": "nonpayable",313 "type": "function"314 },315 {316 "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],317 "name": "setCollectionMintMode",318 "outputs": [],319 "stateMutability": "nonpayable",320 "type": "function"321 },322 {323 "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],324 "name": "setCollectionNesting",325 "outputs": [],326 "stateMutability": "nonpayable",327 "type": "function"328 },329 {330 "inputs": [331 { "internalType": "bool", "name": "enable", "type": "bool" },332 {333 "internalType": "address[]",334 "name": "collections",335 "type": "address[]"336 }337 ],338 "name": "setCollectionNesting",339 "outputs": [],340 "stateMutability": "nonpayable",341 "type": "function"342 },343 {344 "inputs": [345 { "internalType": "string", "name": "key", "type": "string" },346 { "internalType": "bytes", "name": "value", "type": "bytes" }347 ],348 "name": "setCollectionProperty",349 "outputs": [],350 "stateMutability": "nonpayable",351 "type": "function"352 },353 {354 "inputs": [355 { "internalType": "address", "name": "sponsor", "type": "address" }356 ],357 "name": "setCollectionSponsor",358 "outputs": [],359 "stateMutability": "nonpayable",360 "type": "function"361 },362 {363 "inputs": [364 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }365 ],366 "name": "supportsInterface",367 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],368 "stateMutability": "view",369 "type": "function"370 },371 {372 "inputs": [],373 "name": "symbol",374 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],375 "stateMutability": "view",376 "type": "function"377 },378 {379 "inputs": [],380 "name": "totalSupply",381 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],382 "stateMutability": "view",383 "type": "function"384 },385 {386 "inputs": [387 { "internalType": "address", "name": "to", "type": "address" },388 { "internalType": "uint256", "name": "amount", "type": "uint256" }389 ],390 "name": "transfer",391 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],392 "stateMutability": "nonpayable",393 "type": "function"394 },395 {396 "inputs": [397 { "internalType": "address", "name": "from", "type": "address" },398 { "internalType": "address", "name": "to", "type": "address" },399 { "internalType": "uint256", "name": "amount", "type": "uint256" }400 ],401 "name": "transferFrom",402 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],403 "stateMutability": "nonpayable",404 "type": "function"405 },406 {407 "inputs": [],408 "name": "uniqueCollectionType",409 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],410 "stateMutability": "view",411 "type": "function"412 }413]tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -156,6 +156,23 @@
},
{
"inputs": [],
+ "name": "collectionAdmins",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"outputs": [
{
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -156,6 +156,23 @@
},
{
"inputs": [],
+ "name": "collectionAdmins",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"outputs": [
{
tests/src/util/playgrounds/types.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -70,6 +70,13 @@
ethereum?: TEthereumAccount;
}
+export interface IEthCrossAccountId {
+ 0: TEthereumAccount;
+ 1: TSubstrateAccount;
+ field_0: TEthereumAccount;
+ field_1: TSubstrateAccount;
+}
+
export interface ICollectionLimits {
accountTokenOwnershipLimit?: number | null;
sponsoredDataSize?: number | null;
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -7,9 +7,11 @@
import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';
import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';
-import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
+import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
-import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata} from './types';
+import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata, IEthCrossAccountId} from './types';
+import {hexToU8a} from '@polkadot/util/hex';
+import {u8aConcat} from '@polkadot/util/u8a';
export class CrossAccountId implements ICrossAccountId {
Substrate?: TSubstrateAccount;
@@ -2309,6 +2311,73 @@
return siblingPrefix + encodedParaId + suffix;
}
+
+ /**
+ * Encode key to substrate address
+ * @param key key for encoding address
+ * @param ss58Format prefix for encoding to the address of the corresponding network
+ * @returns encoded substrate address
+ */
+ encodeSubstrateAddress (key: Uint8Array | string | bigint, ss58Format = 42): string {
+ const u8a :Uint8Array = typeof key === 'string'
+ ? hexToU8a(key)
+ : typeof key === 'bigint'
+ ? hexToU8a(key.toString(16))
+ : key;
+
+ if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {
+ throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);
+ }
+
+ const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];
+ if (!allowedDecodedLengths.includes(u8a.length)) {
+ throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);
+ }
+
+ const u8aPrefix = ss58Format < 64
+ ? new Uint8Array([ss58Format])
+ : new Uint8Array([
+ ((ss58Format & 0xfc) >> 2) | 0x40,
+ (ss58Format >> 8) | ((ss58Format & 0x03) << 6),
+ ]);
+
+ const input = u8aConcat(u8aPrefix, u8a);
+
+ return base58Encode(u8aConcat(
+ input,
+ blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),
+ ));
+ }
+
+ /**
+ * Restore substrate address from bigint representation
+ * @param number decimal representation of substrate address
+ * @returns substrate address
+ */
+ restoreCrossAccountFromBigInt(number: bigint): TSubstrateAccount {
+ if (this.helper.api === null) {
+ throw 'Not connected';
+ }
+ const res = this.helper.api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();
+ if (res === undefined || res === null) {
+ throw 'Restore address error';
+ }
+ return res.toString();
+ }
+
+ /**
+ * Convert etherium cross account id to substrate cross account id
+ * @param ethCrossAccount etherium cross account
+ * @returns substrate cross account id
+ */
+ convertCrossAccountFromEthCrossAcoount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId {
+ if (ethCrossAccount.field_1 === '0') {
+ return {Ethereum: ethCrossAccount.field_0.toLocaleLowerCase()};
+ }
+
+ const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.field_1));
+ return {Substrate: ss58};
+ }
}
class StakingGroup extends HelperGroup<UniqueHelper> {