From 71406d2be75f3d342020e72b5c9ee21d6d6f7607 Mon Sep 17 00:00:00 2001 From: classicalliu Date: Wed, 8 Mar 2023 18:57:12 +0800 Subject: [PATCH] fix(web3): `GwConfig` is not a constructor For `EthRegistryAddress` and `GwConfig` circular references --- web3/packages/api-server/src/base/address.ts | 39 ++--------------- .../src/base/base-eth-registry-address.ts | 43 +++++++++++++++++++ .../packages/api-server/src/base/gw-config.ts | 11 ++--- .../api-server/tests/utils/config.test.ts | 17 +++++++- 4 files changed, 68 insertions(+), 42 deletions(-) create mode 100644 web3/packages/api-server/src/base/base-eth-registry-address.ts diff --git a/web3/packages/api-server/src/base/address.ts b/web3/packages/api-server/src/base/address.ts index 3b444312c..23160f788 100644 --- a/web3/packages/api-server/src/base/address.ts +++ b/web3/packages/api-server/src/base/address.ts @@ -1,54 +1,21 @@ import { Hash, HexString, Script, utils } from "@ckb-lumos/base"; import { GodwokenClient } from "@godwoken-web3/godwoken"; import { Store } from "../cache/store"; +import { BaseEthRegistryAddress } from "./base-eth-registry-address"; import { gwConfig } from "./index"; import { logger } from "./logger"; -import { Uint32 } from "./types/uint"; // the eth address vs script hash is not changeable, so we set no expire for cache const scriptHashCache = new Store(false); // Only support eth address now! -export class EthRegistryAddress { - private registryId: number; - private addressByteSize: number = 20; - public readonly address: HexString; - +export class EthRegistryAddress extends BaseEthRegistryAddress { // Using optional registryId when gwConfig not initialized constructor( address: HexString, { registryId }: { registryId?: number } = {} ) { - if (!address.startsWith("0x") || address.length !== 42) { - throw new Error(`Eth address format error: ${address}`); - } - this.address = address.toLowerCase(); - - this.registryId = registryId || +gwConfig.accounts.ethAddrReg.id; - } - - public serialize(): HexString { - return ( - "0x" + - new Uint32(this.registryId).toLittleEndian().slice(2) + - new Uint32(this.addressByteSize).toLittleEndian().slice(2) + - this.address.slice(2) - ); - } - - public static Deserialize(hex: HexString): EthRegistryAddress { - const hexWithoutPrefix = hex.slice(2); - const registryId: number = Uint32.fromLittleEndian( - hexWithoutPrefix.slice(0, 8) - ).getValue(); - const addressByteSize: number = Uint32.fromLittleEndian( - hexWithoutPrefix.slice(8, 16) - ).getValue(); - const address: HexString = hexWithoutPrefix.slice(16); - if (addressByteSize !== 20 || address.length !== 40) { - throw new Error(`Eth address deserialize error: ${hex}`); - } - return new EthRegistryAddress("0x" + address, { registryId }); + super(address, registryId || +gwConfig.accounts.ethAddrReg.id); } } diff --git a/web3/packages/api-server/src/base/base-eth-registry-address.ts b/web3/packages/api-server/src/base/base-eth-registry-address.ts new file mode 100644 index 000000000..571f7f49f --- /dev/null +++ b/web3/packages/api-server/src/base/base-eth-registry-address.ts @@ -0,0 +1,43 @@ +import { HexString } from "@ckb-lumos/base"; +import { Uint32 } from "./types/uint"; + +// NOTE: Not to import `gwConfig` +export class BaseEthRegistryAddress { + private registryId: number; + private addressByteSize: number = 20; + public readonly address: HexString; + + // Using optional registryId when gwConfig not initialized + constructor(address: HexString, registryId: number) { + if (!address.startsWith("0x") || address.length !== 42) { + throw new Error(`Eth address format error: ${address}`); + } + this.address = address.toLowerCase(); + + this.registryId = registryId; + } + + public serialize(): HexString { + return ( + "0x" + + new Uint32(this.registryId).toLittleEndian().slice(2) + + new Uint32(this.addressByteSize).toLittleEndian().slice(2) + + this.address.slice(2) + ); + } + + public static Deserialize(hex: HexString): BaseEthRegistryAddress { + const hexWithoutPrefix = hex.slice(2); + const registryId: number = Uint32.fromLittleEndian( + hexWithoutPrefix.slice(0, 8) + ).getValue(); + const addressByteSize: number = Uint32.fromLittleEndian( + hexWithoutPrefix.slice(8, 16) + ).getValue(); + const address: HexString = hexWithoutPrefix.slice(16); + if (addressByteSize !== 20 || address.length !== 40) { + throw new Error(`Eth address deserialize error: ${hex}`); + } + return new BaseEthRegistryAddress("0x" + address, registryId); + } +} diff --git a/web3/packages/api-server/src/base/gw-config.ts b/web3/packages/api-server/src/base/gw-config.ts index 7c4800cf0..d10d705d0 100644 --- a/web3/packages/api-server/src/base/gw-config.ts +++ b/web3/packages/api-server/src/base/gw-config.ts @@ -19,7 +19,7 @@ import { CKB_SUDT_ID, ZERO_ETH_ADDRESS } from "../methods/constant"; import { Uint32 } from "./types/uint"; import { snakeToCamel } from "../util"; import { EntryPointContract } from "../gasless/entrypoint"; -import { EthRegistryAddress } from "./address"; +import { BaseEthRegistryAddress } from "./base-eth-registry-address"; import { logger } from "./logger"; // source: https://github.com/nervosnetwork/godwoken/commit/d6c98d8f8a199b6ec29bc77c5065c1108220bb0a#diff-c56fda2ca3b1366049c88e633389d9b6faa8366151369fd7314c81f6e389e5c7R5 @@ -39,7 +39,7 @@ export class GwConfig { private iNodeVersion: string | undefined; private iEntryPointContract: EntryPointContract | undefined; - constructor(rpcOrUrl: GodwokenClient | string) { + constructor(rpcOrUrl: string) { if (typeof rpcOrUrl === "string") { this.rpc = new GodwokenClient(rpcOrUrl); return; @@ -441,9 +441,10 @@ async function zeroAddressAccount( rpc: GodwokenClient, registryId: number ): Promise { - const registryAddress = new EthRegistryAddress(ZERO_ETH_ADDRESS, { - registryId, - }); + const registryAddress = new BaseEthRegistryAddress( + ZERO_ETH_ADDRESS, + registryId + ); const scriptHash: Hash | undefined = await rpc.getScriptHashByRegistryAddress( registryAddress.serialize() ); diff --git a/web3/packages/api-server/tests/utils/config.test.ts b/web3/packages/api-server/tests/utils/config.test.ts index fbc5af01c..f16204a47 100644 --- a/web3/packages/api-server/tests/utils/config.test.ts +++ b/web3/packages/api-server/tests/utils/config.test.ts @@ -31,6 +31,9 @@ mockRpc.getAccountIdByScriptHash = async (scriptHash: HexString) => { case "0xb5f81e2d10af9600194606989583ae8cc3fcb822a24fdea95f42da5ea18606da": return 2; + case "0xc48e0895b9fd1af6c0770dbdc2d46a2fa93e4efc4af79e616a2bb87eebfabd84": + return 5; + default: throw new Error( `getAccountIdByScriptHash not mock for script hash ${scriptHash}` @@ -77,6 +80,17 @@ mockRpc.getScript = async (scriptHash: HexString) => { } }; +mockRpc.getScriptHashByRegistryAddress = async (registryAddress: HexString) => { + switch (registryAddress) { + case "0x02000000140000000000000000000000000000000000000000000000": + return "0xc48e0895b9fd1af6c0770dbdc2d46a2fa93e4efc4af79e616a2bb87eebfabd84"; + default: + throw new Error( + `getScriptHashByRegistryAddress not mock for registryAddress: ${registryAddress}` + ); + } +}; + mockRpc.getNodeInfo = async () => { const nodeInfo: NodeInfo = { backends: [ @@ -197,7 +211,8 @@ test("init gw config", async (t) => { }, }); t.is(config.accounts.polyjuiceCreator.id, "0x4"); - t.is(config.accounts.defaultFrom.id, "0x3"); + // Using zero address as default address + t.is(config.accounts.defaultFrom.id, "0x5"); t.is(config.accounts.ethAddrReg.id, "0x2"); t.is(config.nodeMode, NodeMode.FullNode); t.is(config.web3ChainId, "0x116e8");