Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Gateway functions to get Gateway address dynamically #205

Merged
merged 4 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"@solana/web3.js": "^1.95.3",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@zetachain/faucet-cli": "^4.1.1",
"@zetachain/networks": "v10.0.0",
"@zetachain/networks": "v10.0.0-rc1",
"@zetachain/protocol-contracts": "11.0.0-rc3",
"axios": "^1.4.0",
"bech32": "^2.0.0",
Expand Down
71 changes: 71 additions & 0 deletions packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Wallet as SolanaWallet } from "@coral-xyz/anchor";
import type { WalletContextState } from "@solana/wallet-adapter-react";
import { PublicKey } from "@solana/web3.js";
import { networks } from "@zetachain/networks";
import mainnetAddresses from "@zetachain/protocol-contracts/dist/data/addresses.mainnet.json";
import testnetAddresses from "@zetachain/protocol-contracts/dist/data/addresses.testnet.json";
import type { Signer, Wallet } from "ethers";
import merge from "lodash/merge";

Expand Down Expand Up @@ -31,6 +33,7 @@ import {

export interface ZetaChainClientParamsBase {
chains?: { [key: string]: any };
contracts?: LocalnetAddress[] | MainnetTestnetAddress[];
network?: string;
}

Expand Down Expand Up @@ -68,13 +71,28 @@ export type ZetaChainClientParams = ZetaChainClientParamsBase &
}
);

interface MainnetTestnetAddress {
address: string;
category: string;
chain_id: number;
chain_name: string;
type: string;
}

interface LocalnetAddress {
address: string;
chain: string;
type: string;
}

export class ZetaChainClient {
public chains: { [key: string]: any };
public network: string;
public wallet: Wallet | undefined;
public signer: any | undefined;
public solanaWallet: SolanaWallet | undefined;
public solanaAdapter: WalletContextState | undefined;
private contracts: LocalnetAddress[] | MainnetTestnetAddress[];

/**
* Initializes ZetaChainClient instance.
Expand Down Expand Up @@ -136,6 +154,16 @@ export class ZetaChainClient {
this.chains = { ...networks };
this.network = params.network || "";

if (params.contracts) {
this.contracts = params.contracts;
} else if (this.network === "localnet" || this.network === "localhost") {
throw new Error("Localnet contracts are required");
} else {
this.contracts = this.network.includes("test")
? testnetAddresses
: mainnetAddresses;
}

this.mergeChains(params.chains);
}

Expand All @@ -147,6 +175,49 @@ export class ZetaChainClient {
});
}

public getGatewayAddress(): string {
if (this.network === "localnet" || this.network === "localhost") {
const gateway = (this.contracts as LocalnetAddress[]).find(
(item) => item.type === "gatewayZEVM"
);

if (!gateway) {
throw new Error("Gateway address not found in localnet configuration");
}

return gateway.address;
} else {
let gateway;
if (this.wallet) {
try {
gateway = (this.contracts as MainnetTestnetAddress[]).find(
async (item) =>
(await this.wallet!.getChainId()) === item.chain_id &&
item.type === "gateway"
);
} catch (error) {
throw new Error("Failed to get gateway address: " + error);
}
} else {
try {
gateway = (this.contracts as MainnetTestnetAddress[]).find(
async (item) =>
(await this.signer!.getChainId()) === item.chain_id &&
item.type === "gateway"
);
} catch (error) {
throw new Error("Failed to get gateway address: " + error);
}
}

if (!gateway) {
throw new Error(`Gateway address not found in signer or wallet`);
}

return gateway.address;
}
}
Comment on lines +179 to +220
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor to reduce duplication and improve error handling

The current implementation has duplicate try-catch blocks and could be simplified.

Consider this refactored version:

 public getGatewayAddress(): string {
   if (this.network === "localnet" || this.network === "localhost") {
     const gateway = (this.contracts as LocalnetAddress[]).find(
       (item) => item.type === "gatewayZEVM"
     );

     if (!gateway) {
       throw new Error("Gateway address not found in localnet configuration");
     }

     return gateway.address;
   }
   
-  let gateway;
-  if (this.wallet) {
-    try {
-      gateway = (this.contracts as MainnetTestnetAddress[]).find(
-        async (item) =>
-          (await this.wallet!.getChainId()) === item.chain_id &&
-          item.type === "gateway"
-      );
-    } catch (error) {
-      throw new Error("Failed to get gateway address: " + error);
-    }
-  } else {
-    try {
-      gateway = (this.contracts as MainnetTestnetAddress[]).find(
-        async (item) =>
-          (await this.signer!.getChainId()) === item.chain_id &&
-          item.type === "gateway"
-      );
-    } catch (error) {
-      throw new Error("Failed to get gateway address: " + error);
-    }
-  }
+  try {
+    const provider = this.wallet || this.signer;
+    if (!provider) {
+      throw new Error("No wallet or signer available");
+    }
+    
+    const chainId = await provider.getChainId();
+    const gateway = (this.contracts as MainnetTestnetAddress[]).find(
+      (item) => item.chain_id === chainId && item.type === "gateway"
+    );
+    
+    if (!gateway) {
+      throw new Error(`Gateway address not found for chain ID ${chainId}`);
+    }
+    
+    return gateway.address;
+  } catch (error) {
+    throw new Error(`Failed to get gateway address: ${error}`);
+  }
-  if (!gateway) {
-    throw new Error(`Gateway address not found in signer or wallet`);
-  }
-
-  return gateway.address;
 }

This refactored version:

  1. Eliminates duplicate code by using a common provider
  2. Fixes the async/await issue in Array.find
  3. Provides more specific error messages
  4. Has better null checking
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public getGatewayAddress(): string {
if (this.network === "localnet" || this.network === "localhost") {
const gateway = (this.contracts as LocalnetAddress[]).find(
(item) => item.type === "gatewayZEVM"
);
if (!gateway) {
throw new Error("Gateway address not found in localnet configuration");
}
return gateway.address;
} else {
let gateway;
if (this.wallet) {
try {
gateway = (this.contracts as MainnetTestnetAddress[]).find(
async (item) =>
(await this.wallet!.getChainId()) === item.chain_id &&
item.type === "gateway"
);
} catch (error) {
throw new Error("Failed to get gateway address: " + error);
}
} else {
try {
gateway = (this.contracts as MainnetTestnetAddress[]).find(
async (item) =>
(await this.signer!.getChainId()) === item.chain_id &&
item.type === "gateway"
);
} catch (error) {
throw new Error("Failed to get gateway address: " + error);
}
}
if (!gateway) {
throw new Error(`Gateway address not found in signer or wallet`);
}
return gateway.address;
}
}
public getGatewayAddress(): string {
if (this.network === "localnet" || this.network === "localhost") {
const gateway = (this.contracts as LocalnetAddress[]).find(
(item) => item.type === "gatewayZEVM"
);
if (!gateway) {
throw new Error("Gateway address not found in localnet configuration");
}
return gateway.address;
}
try {
const provider = this.wallet || this.signer;
if (!provider) {
throw new Error("No wallet or signer available");
}
const chainId = await provider.getChainId();
const gateway = (this.contracts as MainnetTestnetAddress[]).find(
(item) => item.chain_id === chainId && item.type === "gateway"
);
if (!gateway) {
throw new Error(`Gateway address not found for chain ID ${chainId}`);
}
return gateway.address;
} catch (error) {
throw new Error(`Failed to get gateway address: ${error}`);
}
}


public getChains(): { [key: string]: any } {
return this.chains;
}
Expand Down
9 changes: 7 additions & 2 deletions packages/client/src/evmCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type { revertOptions, txOptions } from "./types";
export const evmCall = async function (
this: ZetaChainClient,
args: {
gatewayEvm: string;
gatewayEvm?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
Expand All @@ -34,7 +34,12 @@ export const evmCall = async function (
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);
const gatewayEvmAddress = args.gatewayEvm || this.getGatewayAddress();
const gateway = new ethers.Contract(
gatewayEvmAddress,
GatewayABI.abi,
signer
);

const valuesArray = args.values.map((value, index) => {
const type = args.types[index];
Expand Down
9 changes: 7 additions & 2 deletions packages/client/src/evmDeposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,20 @@ export const evmDeposit = async function (
args: {
amount: string;
erc20: string;
gatewayEvm: string;
gatewayEvm?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
}
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);
const gatewayEvmAddress = args.gatewayEvm || this.getGatewayAddress();
const gateway = new ethers.Contract(
gatewayEvmAddress,
GatewayABI.abi,
signer
);
lukema95 marked this conversation as resolved.
Show resolved Hide resolved

const revertOptions = {
abortAddress: "0x0000000000000000000000000000000000000000", // not used
Expand Down
9 changes: 7 additions & 2 deletions packages/client/src/evmDepositAndCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const evmDepositAndCall = async function (
args: {
amount: string;
erc20: string;
gatewayEvm: string;
gatewayEvm?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
Expand All @@ -39,7 +39,12 @@ export const evmDepositAndCall = async function (
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);
const gatewayEvmAddress = args.gatewayEvm || this.getGatewayAddress();
const gateway = new ethers.Contract(
gatewayEvmAddress,
GatewayABI.abi,
signer
);

const revertOptions = {
abortAddress: "0x0000000000000000000000000000000000000000", // not used
Expand Down
7 changes: 4 additions & 3 deletions packages/client/src/zetachainCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const zetachainCall = async function (
args: {
callOptions: any;
function: string;
gatewayZetaChain: string;
gatewayZetaChain?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
Expand All @@ -43,9 +43,10 @@ export const zetachainCall = async function (
) {
const signer = this.signer;
const { utils } = ethers;

const gatewayZetaChainAddress =
args.gatewayZetaChain || this.getGatewayAddress();
const gateway = new ethers.Contract(
args.gatewayZetaChain,
gatewayZetaChainAddress,
GatewayABI.abi,
signer
);
Expand Down
6 changes: 4 additions & 2 deletions packages/client/src/zetachainWithdraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const zetachainWithdraw = async function (
this: ZetaChainClient,
args: {
amount: string;
gatewayZetaChain: string;
gatewayZetaChain?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
Expand All @@ -38,8 +38,10 @@ export const zetachainWithdraw = async function (
const signer = this.signer;
const { utils } = ethers;

const gatewayZetaChainAddress =
args.gatewayZetaChain || this.getGatewayAddress();
const gateway = new ethers.Contract(
args.gatewayZetaChain,
gatewayZetaChainAddress,
GatewayABI.abi,
signer
);
Expand Down
6 changes: 4 additions & 2 deletions packages/client/src/zetachainWithdrawAndCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const zetachainWithdrawAndCall = async function (
amount: string;
callOptions: any;
function?: string;
gatewayZetaChain: string;
gatewayZetaChain?: string;
receiver: string;
revertOptions: revertOptions;
txOptions: txOptions;
Expand All @@ -46,8 +46,10 @@ export const zetachainWithdrawAndCall = async function (
const signer = this.signer;
const { utils } = ethers;

const gatewayZetaChainAddress =
args.gatewayZetaChain || this.getGatewayAddress();
const gateway = new ethers.Contract(
args.gatewayZetaChain,
gatewayZetaChainAddress,
lukema95 marked this conversation as resolved.
Show resolved Hide resolved
GatewayABI.abi,
signer
);
Expand Down
9 changes: 3 additions & 6 deletions packages/tasks/src/evmCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { ZetaChainClient } from "../../client/src/";
export const evmCall = async (args: any, hre: HardhatRuntimeEnvironment) => {
try {
const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const tx = await client.evmCall({
gatewayEvm: args.gatewayEvm,
receiver: args.receiver,
Expand All @@ -32,11 +33,7 @@ export const evmCall = async (args: any, hre: HardhatRuntimeEnvironment) => {

task("evm-call", "Call a universal app", evmCall)
.addParam("receiver", "Receiver address on ZetaChain")
.addOptionalParam(
"gatewayEvm",
"contract address of gateway on EVM",
"0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
)
.addOptionalParam("gatewayEvm", "contract address of gateway on EVM")
.addFlag("callOnRevert", "Whether to call on revert")
.addOptionalParam(
"revertAddress",
Expand Down
9 changes: 3 additions & 6 deletions packages/tasks/src/evmDeposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { ZetaChainClient } from "../../client/src/";
export const evmDeposit = async (args: any, hre: HardhatRuntimeEnvironment) => {
try {
const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const tx = await client.evmDeposit({
amount: args.amount,
erc20: args.erc20,
Expand Down Expand Up @@ -34,11 +35,7 @@ export const evmDeposit = async (args: any, hre: HardhatRuntimeEnvironment) => {

task("evm-deposit", "Deposit tokens", evmDeposit)
.addParam("receiver", "Receiver address on ZetaChain")
.addOptionalParam(
"gatewayEvm",
"contract address of gateway on EVM",
"0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
)
.addOptionalParam("gatewayEvm", "contract address of gateway on EVM")
.addFlag("callOnRevert", "Whether to call on revert")
.addOptionalParam(
"revertAddress",
Expand Down
9 changes: 3 additions & 6 deletions packages/tasks/src/evmDepositAndCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export const evmDepositAndCall = async (
) => {
try {
const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const tx = await client.evmDepositAndCall({
amount: args.amount,
erc20: args.erc20,
Expand Down Expand Up @@ -39,11 +40,7 @@ export const evmDepositAndCall = async (

task("evm-deposit-and-call", "Deposit tokens", evmDepositAndCall)
.addParam("receiver", "Receiver address on ZetaChain")
.addOptionalParam(
"gatewayEvm",
"contract address of gateway on EVM",
"0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
)
.addOptionalParam("gatewayEvm", "contract address of gateway on EVM")
.addFlag("callOnRevert", "Whether to call on revert")
.addOptionalParam(
"revertAddress",
Expand Down
6 changes: 3 additions & 3 deletions packages/tasks/src/zetachainCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const zetachainCall = async (

try {
const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const response = await client.zetachainCall({
callOptions,
function: args.function,
Expand Down Expand Up @@ -44,8 +45,7 @@ export const zetachainCall = async (
task("zetachain-call", "Call a contract on a connected chain", zetachainCall)
.addOptionalParam(
"gatewayZetaChain",
"contract address of gateway on ZetaChain",
"0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
"contract address of gateway on ZetaChain"
)
.addParam("zrc20", "The address of ZRC-20 to pay fees")
.addFlag("callOnRevert", "Whether to call on revert")
Expand Down
6 changes: 3 additions & 3 deletions packages/tasks/src/zetachainWithdraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export const zetachainWithdraw = async (
) => {
try {
const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const response = await client.zetachainWithdraw({
amount: args.amount,
gatewayZetaChain: args.gatewayZetaChain,
Expand Down Expand Up @@ -37,8 +38,7 @@ export const zetachainWithdraw = async (
task("zetachain-withdraw", "Withdraw tokens from ZetaChain", zetachainWithdraw)
.addOptionalParam(
"gatewayZetaChain",
"contract address of gateway on ZetaChain",
"0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
"contract address of gateway on ZetaChain"
)
.addOptionalParam("zrc20", "The address of the ZRC20 token")
.addFlag("callOnRevert", "Whether to call on revert")
Expand Down
6 changes: 3 additions & 3 deletions packages/tasks/src/zetachainWithdrawAndCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const zetachainWithdrawAndCall = async (
};

const [signer] = await hre.ethers.getSigners();
const client = new ZetaChainClient({ network: "testnet", signer });
const network = hre.network.name;
const client = new ZetaChainClient({ network, signer });
const response = await client.zetachainWithdrawAndCall({
amount: args.amount,
callOptions,
Expand Down Expand Up @@ -50,8 +51,7 @@ task(
)
.addOptionalParam(
"gatewayZetaChain",
"contract address of gateway on ZetaChain",
"0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
"contract address of gateway on ZetaChain"
)
.addOptionalParam("zrc20", "The address of the ZRC20 token")
.addFlag("callOnRevert", "Whether to call on revert")
Expand Down
Loading
Loading