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.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -126,6 +126,23 @@
},
{
"inputs": [],
+ "name": "collectionAdmins",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple6[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionOwner",
"outputs": [
{
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.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034import {IKeyringPair} from '@polkadot/types/types';56export interface IEvent {7 section: string;8 method: string;9 index: [number, number] | string;10 data: any[];11 phase: {applyExtrinsic: number} | 'Initialization',12}1314export interface ITransactionResult {15 status: 'Fail' | 'Success';16 result: {17 dispatchError: any,18 events: {19 phase: any, // {ApplyExtrinsic: number} | 'Initialization',20 event: IEvent;21 }[];22 },23 moduleError?: string;24}2526export interface ISubscribeBlockEventsData {27 number: number;28 hash: string;29 timestamp: number; 30 events: IEvent[];31}3233export interface ILogger {34 log: (msg: any, level?: string) => void;35 level: {36 ERROR: 'ERROR';37 WARNING: 'WARNING';38 INFO: 'INFO';39 [key: string]: string;40 }41}4243export interface IUniqueHelperLog {44 executedAt: number;45 executionTime: number;46 type: 'extrinsic' | 'rpc';47 status: 'Fail' | 'Success';48 call: string;49 params: any[];50 moduleError?: string;51 dispatchError?: any;52 events?: any;53}5455export interface IApiListeners {56 connected?: (...args: any[]) => any;57 disconnected?: (...args: any[]) => any;58 error?: (...args: any[]) => any;59 ready?: (...args: any[]) => any; 60 decorated?: (...args: any[]) => any;61}6263export interface ICrossAccountId {64 Substrate?: TSubstrateAccount;65 Ethereum?: TEthereumAccount;66}6768export interface ICrossAccountIdLower {69 substrate?: TSubstrateAccount;70 ethereum?: TEthereumAccount;71}7273export interface ICollectionLimits {74 accountTokenOwnershipLimit?: number | null;75 sponsoredDataSize?: number | null;76 sponsoredDataRateLimit?: {blocks: number} | {sponsoringDisabled: null} | null;77 tokenLimit?: number | null;78 sponsorTransferTimeout?: number | null;79 sponsorApproveTimeout?: number | null;80 ownerCanTransfer?: boolean | null;81 ownerCanDestroy?: boolean | null;82 transfersEnabled?: boolean | null;83}8485export interface INestingPermissions {86 tokenOwner?: boolean;87 collectionAdmin?: boolean;88 restricted?: number[] | null;89}9091export interface ICollectionPermissions {92 access?: 'Normal' | 'AllowList';93 mintMode?: boolean;94 nesting?: INestingPermissions;95}9697export interface IProperty {98 key: string;99 value?: string;100}101102export interface ITokenPropertyPermission {103 key: string;104 permission: {105 mutable?: boolean;106 tokenOwner?: boolean;107 collectionAdmin?: boolean;108 }109}110111export interface IToken {112 collectionId: number;113 tokenId: number;114}115116export interface IBlock {117 extrinsics: IExtrinsic[]118 header: {119 parentHash: string,120 number: number,121 };122}123124export interface IExtrinsic {125 isSigned: boolean,126 method: {127 method: string,128 section: string,129 args: any[]130 }131}132133export interface ICollectionCreationOptions {134 name?: string | number[];135 description?: string | number[];136 tokenPrefix?: string | number[];137 mode?: {138 nft?: null;139 refungible?: null;140 fungible?: number;141 }142 permissions?: ICollectionPermissions;143 properties?: IProperty[];144 tokenPropertyPermissions?: ITokenPropertyPermission[];145 limits?: ICollectionLimits;146 pendingSponsor?: TSubstrateAccount;147}148149export interface IChainProperties {150 ss58Format: number;151 tokenDecimals: number[];152 tokenSymbol: string[]153}154155export interface ISubstrateBalance {156 free: bigint,157 reserved: bigint,158 miscFrozen: bigint,159 feeFrozen: bigint160}161162export interface IStakingInfo {163 block: bigint,164 amount: bigint,165}166167export interface ISchedulerOptions {168 priority?: number,169 periodic?: {170 period: number,171 repetitions: number,172 },173}174175export interface IForeignAssetMetadata {176 name?: number | Uint8Array,177 symbol?: string,178 decimals?: number,179 minimalBalance?: bigint,180}181182export interface MoonbeamAssetInfo {183 location: any,184 metadata: {185 name: string,186 symbol: string,187 decimals: number,188 isFrozen: boolean,189 minimalBalance: bigint,190 },191 existentialDeposit: bigint,192 isSufficient: boolean,193 unitsPerSecond: bigint,194 numAssetsWeightHint: number,195}196197export interface AcalaAssetMetadata {198 name: string,199 symbol: string,200 decimals: number,201 minimalBalance: bigint,202}203204export interface DemocracyStandardAccountVote {205 balance: bigint,206 vote: {207 aye: boolean,208 conviction: number,209 },210}211212export type TSubstrateAccount = string;213export type TEthereumAccount = string;214export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';215export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';216export type TSiblingNetworkds = 'moonbeam' | 'moonriver' | 'acala' | 'karura' | 'westmint';217export type TRelayNetworks = 'rococo' | 'westend';218export type TNetworks = TUniqueNetworks | TSiblingNetworkds | TRelayNetworks;219export type TSigner = IKeyringPair; // | 'string'1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034import {IKeyringPair} from '@polkadot/types/types';56export interface IEvent {7 section: string;8 method: string;9 index: [number, number] | string;10 data: any[];11 phase: {applyExtrinsic: number} | 'Initialization',12}1314export interface ITransactionResult {15 status: 'Fail' | 'Success';16 result: {17 dispatchError: any,18 events: {19 phase: any, // {ApplyExtrinsic: number} | 'Initialization',20 event: IEvent;21 }[];22 },23 moduleError?: string;24}2526export interface ISubscribeBlockEventsData {27 number: number;28 hash: string;29 timestamp: number; 30 events: IEvent[];31}3233export interface ILogger {34 log: (msg: any, level?: string) => void;35 level: {36 ERROR: 'ERROR';37 WARNING: 'WARNING';38 INFO: 'INFO';39 [key: string]: string;40 }41}4243export interface IUniqueHelperLog {44 executedAt: number;45 executionTime: number;46 type: 'extrinsic' | 'rpc';47 status: 'Fail' | 'Success';48 call: string;49 params: any[];50 moduleError?: string;51 dispatchError?: any;52 events?: any;53}5455export interface IApiListeners {56 connected?: (...args: any[]) => any;57 disconnected?: (...args: any[]) => any;58 error?: (...args: any[]) => any;59 ready?: (...args: any[]) => any; 60 decorated?: (...args: any[]) => any;61}6263export interface ICrossAccountId {64 Substrate?: TSubstrateAccount;65 Ethereum?: TEthereumAccount;66}6768export interface ICrossAccountIdLower {69 substrate?: TSubstrateAccount;70 ethereum?: TEthereumAccount;71}7273export interface IEthCrossAccountId {74 0: TEthereumAccount;75 1: TSubstrateAccount;76 field_0: TEthereumAccount;77 field_1: TSubstrateAccount;78}7980export interface ICollectionLimits {81 accountTokenOwnershipLimit?: number | null;82 sponsoredDataSize?: number | null;83 sponsoredDataRateLimit?: {blocks: number} | {sponsoringDisabled: null} | null;84 tokenLimit?: number | null;85 sponsorTransferTimeout?: number | null;86 sponsorApproveTimeout?: number | null;87 ownerCanTransfer?: boolean | null;88 ownerCanDestroy?: boolean | null;89 transfersEnabled?: boolean | null;90}9192export interface INestingPermissions {93 tokenOwner?: boolean;94 collectionAdmin?: boolean;95 restricted?: number[] | null;96}9798export interface ICollectionPermissions {99 access?: 'Normal' | 'AllowList';100 mintMode?: boolean;101 nesting?: INestingPermissions;102}103104export interface IProperty {105 key: string;106 value?: string;107}108109export interface ITokenPropertyPermission {110 key: string;111 permission: {112 mutable?: boolean;113 tokenOwner?: boolean;114 collectionAdmin?: boolean;115 }116}117118export interface IToken {119 collectionId: number;120 tokenId: number;121}122123export interface IBlock {124 extrinsics: IExtrinsic[]125 header: {126 parentHash: string,127 number: number,128 };129}130131export interface IExtrinsic {132 isSigned: boolean,133 method: {134 method: string,135 section: string,136 args: any[]137 }138}139140export interface ICollectionCreationOptions {141 name?: string | number[];142 description?: string | number[];143 tokenPrefix?: string | number[];144 mode?: {145 nft?: null;146 refungible?: null;147 fungible?: number;148 }149 permissions?: ICollectionPermissions;150 properties?: IProperty[];151 tokenPropertyPermissions?: ITokenPropertyPermission[];152 limits?: ICollectionLimits;153 pendingSponsor?: TSubstrateAccount;154}155156export interface IChainProperties {157 ss58Format: number;158 tokenDecimals: number[];159 tokenSymbol: string[]160}161162export interface ISubstrateBalance {163 free: bigint,164 reserved: bigint,165 miscFrozen: bigint,166 feeFrozen: bigint167}168169export interface IStakingInfo {170 block: bigint,171 amount: bigint,172}173174export interface ISchedulerOptions {175 priority?: number,176 periodic?: {177 period: number,178 repetitions: number,179 },180}181182export interface IForeignAssetMetadata {183 name?: number | Uint8Array,184 symbol?: string,185 decimals?: number,186 minimalBalance?: bigint,187}188189export interface MoonbeamAssetInfo {190 location: any,191 metadata: {192 name: string,193 symbol: string,194 decimals: number,195 isFrozen: boolean,196 minimalBalance: bigint,197 },198 existentialDeposit: bigint,199 isSufficient: boolean,200 unitsPerSecond: bigint,201 numAssetsWeightHint: number,202}203204export interface AcalaAssetMetadata {205 name: string,206 symbol: string,207 decimals: number,208 minimalBalance: bigint,209}210211export interface DemocracyStandardAccountVote {212 balance: bigint,213 vote: {214 aye: boolean,215 conviction: number,216 },217}218219export type TSubstrateAccount = string;220export type TEthereumAccount = string;221export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';222export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';223export type TSiblingNetworkds = 'moonbeam' | 'moonriver' | 'acala' | 'karura' | 'westmint';224export type TRelayNetworks = 'rococo' | 'westend';225export type TNetworks = TUniqueNetworks | TSiblingNetworkds | TRelayNetworks;226export type TSigner = IKeyringPair; // | 'string'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> {