git.delta.rocks / unique-network / refs/commits / 8b9e255fd2b8

difftreelog

feat Add `collection_admins` method to eth collection.

Trubnikov Sergey2022-09-16parent: #2ffba98.patch.diff
in: master

2 files changed

modifiedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1515
16import {IKeyringPair} from '@polkadot/types/types';16import {IKeyringPair} from '@polkadot/types/types';
17import {IEthCrossAccountId} from '../util/playgrounds/types';
17import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';18import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util/playgrounds';
1819
19async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {20async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {
20 const before = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));21 const before = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));
94 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;95 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;
95 });96 });
9697
97 // itEth.skip('Check adminlist', async ({helper, privateKey}) => {98 itEth('Check adminlist', async ({helper, privateKey}) => {
98 // const owner = await helper.eth.createAccountWithBalance(donor);99 const owner = await helper.eth.createAccountWithBalance(donor);
99 100
100 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');101 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
101 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);102 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
102103
103 // const admin1 = helper.eth.createAccount();104 const admin1 = helper.eth.createAccount();
104 // const admin2 = await privateKey('admin');105 const admin2 = privateKey('admin');
105 // await collectionEvm.methods.addCollectionAdmin(admin1).send();106 await collectionEvm.methods.addCollectionAdmin(admin1).send();
106 // await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();107 await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();
107108
108 // const adminListRpc = await helper.collection.getAdmins(collectionId);109 const adminListRpc = await helper.collection.getAdmins(collectionId);
109 // let adminListEth = await collectionEvm.methods.collectionAdmins().call();110 let adminListEth = await collectionEvm.methods.collectionAdmins().call();
110 // adminListEth = adminListEth.map((element: IEthCrossAccountId) => {111 adminListEth = adminListEth.map((element: IEthCrossAccountId) => {
111 // return helper.address.convertCrossAccountFromEthCrossAcoount(element);112 return helper.address.convertCrossAccountFromEthCrossAcoount(element);
112 // });113 });
113 // expect(adminListRpc).to.be.like(adminListEth);114 expect(adminListRpc).to.be.like(adminListEth);
114 // });115 });
115 116
116 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {117 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {
117 const owner = await helper.eth.createAccountWithBalance(donor);118 const owner = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -7,8 +7,10 @@
 
 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 {hexToU8a} from '@polkadot/util/hex';
+import {u8aConcat} from '@polkadot/util/u8a';
 import {
   IApiListeners,
   IBlock,
@@ -2368,6 +2370,73 @@
     return CrossAccountId.translateSubToEth(subAddress);
   }
 
+  /**
+   * 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};
+  }
+
   paraSiblingSovereignAccount(paraid: number) {
     // We are getting a *sibling* parachain sovereign account,
     // so we need a sibling prefix: encoded(b"sibl") == 0x7369626c