Jelajahi Sumber

[contract-manager] General improvements (#1024)

* Better return types for transaction execution functions

* Use new type for passing PrivateKey

* Small typing improvements

* Stricter liniting

* Rename edge to beta for DeploymentType

* Reduce any usage across the contract manager

* Fix explicit any linting warnings
Mohammad Amin Khashkhashi Moghaddam 2 tahun lalu
induk
melakukan
b9dbd54d5a

+ 6 - 0
contract_manager/.eslintrc.js

@@ -0,0 +1,6 @@
+module.exports = {
+  root: true,
+  parser: "@typescript-eslint/parser",
+  plugins: ["@typescript-eslint"],
+  extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
+};

+ 2 - 1
contract_manager/package.json

@@ -10,7 +10,8 @@
   ],
   "scripts": {
     "build": "tsc",
-    "shell": "ts-node ./src/shell.ts"
+    "shell": "ts-node ./src/shell.ts",
+    "lint": "eslint src/"
   },
   "author": "",
   "license": "Apache-2.0",

+ 7 - 4
contract_manager/scripts/update_pricefeed.ts

@@ -1,6 +1,6 @@
 import yargs from "yargs";
 import { hideBin } from "yargs/helpers";
-import { DefaultStore } from "../src";
+import { DefaultStore, toPrivateKey } from "../src";
 import { PriceServiceConnection } from "@pythnetwork/price-service-client";
 
 const parser = yargs(hideBin(process.argv))
@@ -43,9 +43,12 @@ async function main() {
     argv.endpoint || defaultEndpoint
   );
   const vaas = await priceService.getLatestVaas(argv["feed-id"] as string[]);
-  await contract.executeUpdatePriceFeed(
-    argv["private-key"],
-    vaas.map((vaa) => Buffer.from(vaa, "base64"))
+  const privateKey = toPrivateKey(argv["private-key"]);
+  console.log(
+    await contract.executeUpdatePriceFeed(
+      privateKey,
+      vaas.map((vaa) => Buffer.from(vaa, "base64"))
+    )
   );
 }
 

+ 26 - 8
contract_manager/src/base.ts

@@ -1,6 +1,24 @@
 import { DataSource } from "xc_admin_common";
 import { Chain } from "./chains";
 
+export interface TxResult {
+  id: string;
+  info: unknown; // chain specific info
+}
+
+export type DeploymentType = "stable" | "beta";
+export type PrivateKey = string & { __type: "PrivateKey" };
+function checkIsPrivateKey(key: string): asserts key is PrivateKey {
+  if (Buffer.from(key, "hex").length !== 32)
+    throw new Error("Invalid private key, must be 64 hex chars");
+}
+export function toPrivateKey(key: string): PrivateKey {
+  checkIsPrivateKey(key);
+  return key;
+}
+
+export type KeyValueConfig = Record<string, string | number | boolean>;
+
 export abstract class Storable {
   /**
    * Returns the unique identifier for this object
@@ -17,7 +35,7 @@ export abstract class Storable {
    * Returns a JSON representation of this object. It should be possible to
    * reconstruct the object from the JSON using the fromJson method.
    */
-  abstract toJson(): any;
+  abstract toJson(): KeyValueConfig;
 }
 
 export interface Price {
@@ -75,9 +93,9 @@ export abstract class Contract extends Storable {
    * @param vaas an array of VAAs containing price update messages to execute
    */
   abstract executeUpdatePriceFeed(
-    senderPrivateKey: string,
+    senderPrivateKey: PrivateKey,
     vaas: Buffer[]
-  ): Promise<any>;
+  ): Promise<TxResult>;
 
   /**
    * Executes the governance instruction contained in the VAA using the sender credentials
@@ -85,9 +103,9 @@ export abstract class Contract extends Storable {
    * @param vaa the VAA to execute
    */
   abstract executeGovernanceInstruction(
-    senderPrivateKey: string,
+    senderPrivateKey: PrivateKey,
     vaa: Buffer
-  ): Promise<any>;
+  ): Promise<TxResult>;
 
   /**
    * Returns the single data source that this contract accepts governance messages from
@@ -95,11 +113,11 @@ export abstract class Contract extends Storable {
   abstract getGovernanceDataSource(): Promise<DataSource>;
 }
 
-export function getDefaultDeploymentConfig(deploymentType: "stable" | "edge"): {
+export function getDefaultDeploymentConfig(deploymentType: DeploymentType): {
   dataSources: DataSource[];
   governanceDataSource: DataSource;
   wormholeConfig: {
-    governanceChainId: Number;
+    governanceChainId: number;
     governanceContract: string; // 32 byte address in 64 char hex format
     initialGuardianSet: string[]; // 20 byte addresses in 40 char hex format
   };
@@ -135,7 +153,7 @@ export function getDefaultDeploymentConfig(deploymentType: "stable" | "edge"): {
         initialGuardianSet: ["58cc3ae5c097b213ce3c81979e1b9f9570746aa5"],
       },
     };
-  else if (deploymentType === "edge")
+  else if (deploymentType === "beta")
     return {
       dataSources: [
         {

+ 24 - 21
contract_manager/src/chains.ts

@@ -1,7 +1,6 @@
-import { Storable } from "./base";
+import { KeyValueConfig, PrivateKey, Storable } from "./base";
 import {
   ChainName,
-  CHAINS,
   SetFee,
   CosmosUpgradeContract,
   EvmUpgradeContract,
@@ -22,6 +21,10 @@ import {
 } from "@pythnetwork/cosmwasm-deploy-tools";
 import { Network } from "@injectivelabs/networks";
 
+export type ChainConfig = Record<string, string> & {
+  mainnet: boolean;
+  id: string;
+};
 export abstract class Chain extends Storable {
   public wormholeChainName: ChainName;
 
@@ -92,15 +95,15 @@ export abstract class Chain extends Storable {
    * Returns the payload for a governance contract upgrade instruction for contracts deployed on this chain
    * @param upgradeInfo based on the contract type, this can be a contract address, codeId, package digest, etc.
    */
-  abstract generateGovernanceUpgradePayload(upgradeInfo: any): Buffer;
+  abstract generateGovernanceUpgradePayload(upgradeInfo: unknown): Buffer;
 }
 
 export class GlobalChain extends Chain {
-  static type: string = "GlobalChain";
+  static type = "GlobalChain";
   constructor() {
     super("global", true, "unset");
   }
-  generateGovernanceUpgradePayload(upgradeInfo: any): Buffer {
+  generateGovernanceUpgradePayload(): Buffer {
     throw new Error(
       "Can not create a governance message for upgrading contracts on all chains!"
     );
@@ -110,7 +113,7 @@ export class GlobalChain extends Chain {
     return GlobalChain.type;
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       id: this.id,
       wormholeChainName: this.wormholeChainName,
@@ -121,7 +124,7 @@ export class GlobalChain extends Chain {
 }
 
 export class CosmWasmChain extends Chain {
-  static type: string = "CosmWasmChain";
+  static type = "CosmWasmChain";
 
   constructor(
     id: string,
@@ -135,7 +138,7 @@ export class CosmWasmChain extends Chain {
     super(id, mainnet, wormholeChainName);
   }
 
-  static fromJson(parsed: any): CosmWasmChain {
+  static fromJson(parsed: ChainConfig): CosmWasmChain {
     if (parsed.type !== CosmWasmChain.type) throw new Error("Invalid type");
     return new CosmWasmChain(
       parsed.id,
@@ -148,7 +151,7 @@ export class CosmWasmChain extends Chain {
     );
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       endpoint: this.endpoint,
       id: this.id,
@@ -174,7 +177,7 @@ export class CosmWasmChain extends Chain {
     return new CosmosUpgradeContract(this.wormholeChainName, codeId).encode();
   }
 
-  async getExecutor(privateKey: string) {
+  async getExecutor(privateKey: PrivateKey) {
     if (this.getId().indexOf("injective") > -1) {
       return InjectiveExecutor.fromPrivateKey(
         this.isMainnet() ? Network.Mainnet : Network.Testnet,
@@ -190,7 +193,7 @@ export class CosmWasmChain extends Chain {
 }
 
 export class SuiChain extends Chain {
-  static type: string = "SuiChain";
+  static type = "SuiChain";
 
   constructor(
     id: string,
@@ -201,7 +204,7 @@ export class SuiChain extends Chain {
     super(id, mainnet, wormholeChainName);
   }
 
-  static fromJson(parsed: any): SuiChain {
+  static fromJson(parsed: ChainConfig): SuiChain {
     if (parsed.type !== SuiChain.type) throw new Error("Invalid type");
     return new SuiChain(
       parsed.id,
@@ -211,7 +214,7 @@ export class SuiChain extends Chain {
     );
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       id: this.id,
       wormholeChainName: this.wormholeChainName,
@@ -238,7 +241,7 @@ export class SuiChain extends Chain {
 }
 
 export class EvmChain extends Chain {
-  static type: string = "EvmChain";
+  static type = "EvmChain";
 
   constructor(
     id: string,
@@ -250,7 +253,7 @@ export class EvmChain extends Chain {
     super(id, mainnet, wormholeChainName);
   }
 
-  static fromJson(parsed: any): EvmChain {
+  static fromJson(parsed: ChainConfig & { networkId: number }): EvmChain {
     if (parsed.type !== EvmChain.type) throw new Error("Invalid type");
     return new EvmChain(
       parsed.id,
@@ -277,7 +280,7 @@ export class EvmChain extends Chain {
     return new EvmSetWormholeAddress(this.wormholeChainName, address).encode();
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       id: this.id,
       wormholeChainName: this.wormholeChainName,
@@ -311,10 +314,10 @@ export class EvmChain extends Chain {
    * @returns the address of the deployed contract
    */
   async deploy(
-    privateKey: string,
-    abi: any,
+    privateKey: PrivateKey,
+    abi: any, // eslint-disable-line  @typescript-eslint/no-explicit-any
     bytecode: string,
-    deployArgs: any[]
+    deployArgs: any[] // eslint-disable-line  @typescript-eslint/no-explicit-any
   ): Promise<string> {
     const web3 = new Web3(this.getRpcUrl());
     const signer = web3.eth.accounts.privateKeyToAccount(privateKey);
@@ -375,7 +378,7 @@ export class AptosChain extends Chain {
     return AptosChain.type;
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       id: this.id,
       wormholeChainName: this.wormholeChainName,
@@ -385,7 +388,7 @@ export class AptosChain extends Chain {
     };
   }
 
-  static fromJson(parsed: any): AptosChain {
+  static fromJson(parsed: ChainConfig): AptosChain {
     if (parsed.type !== AptosChain.type) throw new Error("Invalid type");
     return new AptosChain(
       parsed.id,

+ 54 - 24
contract_manager/src/contracts/aptos.ts

@@ -1,11 +1,11 @@
-import { Contract, PriceFeed } from "../base";
-import { AptosAccount, BCS, TxnBuilderTypes } from "aptos";
+import { Contract, PriceFeed, PrivateKey, TxResult } from "../base";
+import { ApiError, AptosAccount, BCS, TxnBuilderTypes } from "aptos";
 import { AptosChain, Chain } from "../chains";
 import { DataSource } from "xc_admin_common";
 import { CoinClient } from "aptos";
 
 export class AptosContract extends Contract {
-  static type: string = "AptosContract";
+  static type = "AptosContract";
 
   /**
    * Given the ids of the pyth state and wormhole state, create a new AptosContract
@@ -23,7 +23,10 @@ export class AptosContract extends Contract {
     super();
   }
 
-  static fromJson(chain: Chain, parsed: any): AptosContract {
+  static fromJson(
+    chain: Chain,
+    parsed: { type: string; stateId: string; wormholeStateId: string }
+  ): AptosContract {
     if (parsed.type !== AptosContract.type) throw new Error("Invalid type");
     if (!(chain instanceof AptosChain))
       throw new Error(`Wrong chain type ${chain}`);
@@ -31,9 +34,9 @@ export class AptosContract extends Contract {
   }
 
   async executeGovernanceInstruction(
-    senderPrivateKey: string,
+    senderPrivateKey: PrivateKey,
     vaa: Buffer
-  ): Promise<any> {
+  ): Promise<TxResult> {
     const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
       TxnBuilderTypes.EntryFunction.natural(
         `${this.stateId}::governance`,
@@ -45,23 +48,28 @@ export class AptosContract extends Contract {
     return this.sendTransaction(senderPrivateKey, txPayload);
   }
 
-  private sendTransaction(
-    senderPrivateKey: string,
+  private async sendTransaction(
+    senderPrivateKey: PrivateKey,
     txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
-  ) {
+  ): Promise<TxResult> {
     const client = this.chain.getClient();
     const sender = new AptosAccount(
       new Uint8Array(Buffer.from(senderPrivateKey, "hex"))
     );
-    return client.generateSignSubmitWaitForTransaction(sender, txPayload, {
-      maxGasAmount: BigInt(30000),
-    });
+    const result = await client.generateSignSubmitWaitForTransaction(
+      sender,
+      txPayload,
+      {
+        maxGasAmount: BigInt(30000),
+      }
+    );
+    return { id: result.hash, info: result };
   }
 
   async executeUpdatePriceFeed(
-    senderPrivateKey: string,
+    senderPrivateKey: PrivateKey,
     vaas: Buffer[]
-  ): Promise<any> {
+  ): Promise<TxResult> {
     const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
       TxnBuilderTypes.EntryFunction.natural(
         `${this.stateId}::pyth`,
@@ -93,7 +101,7 @@ export class AptosContract extends Contract {
   }
 
   async getBaseUpdateFee() {
-    const data = (await this.findResource("BaseUpdateFee")) as any;
+    const data = (await this.findResource("BaseUpdateFee")) as { fee: string };
     return { amount: data.fee };
   }
 
@@ -101,7 +109,12 @@ export class AptosContract extends Contract {
     return this.chain;
   }
 
-  private parsePrice(priceInfo: any) {
+  private parsePrice(priceInfo: {
+    expo: { magnitude: string; negative: boolean };
+    price: { magnitude: string; negative: boolean };
+    conf: string;
+    timestamp: string;
+  }) {
     let expo = priceInfo.expo.magnitude;
     if (priceInfo.expo.negative) expo = "-" + expo;
     let price = priceInfo.price.magnitude;
@@ -116,7 +129,9 @@ export class AptosContract extends Contract {
 
   async getPriceFeed(feedId: string): Promise<PriceFeed | undefined> {
     const client = this.chain.getClient();
-    const res = (await this.findResource("LatestPriceInfo")) as any;
+    const res = (await this.findResource("LatestPriceInfo")) as {
+      info: { handle: string };
+    };
     const handle = res.info.handle;
     try {
       const priceItemRes = await client.getTableItem(handle, {
@@ -130,15 +145,23 @@ export class AptosContract extends Contract {
         price: this.parsePrice(priceItemRes.price_feed.price),
         emaPrice: this.parsePrice(priceItemRes.price_feed.ema_price),
       };
-    } catch (e: any) {
-      if (e.errorCode === "table_item_not_found") return undefined;
+    } catch (e) {
+      if (e instanceof ApiError && e.errorCode === "table_item_not_found")
+        return undefined;
       throw e;
     }
   }
 
   async getDataSources(): Promise<DataSource[]> {
-    const data = (await this.findResource("DataSources")) as any;
-    return data.sources.keys.map((source: any) => {
+    const data = (await this.findResource("DataSources")) as {
+      sources: {
+        keys: {
+          emitter_chain: string;
+          emitter_address: { external_address: string };
+        }[];
+      };
+    };
+    return data.sources.keys.map((source) => {
       return {
         emitterChain: Number(source.emitter_chain),
         emitterAddress: source.emitter_address.external_address.replace(
@@ -150,7 +173,12 @@ export class AptosContract extends Contract {
   }
 
   async getGovernanceDataSource(): Promise<DataSource> {
-    const data = (await this.findResource("GovernanceDataSource")) as any;
+    const data = (await this.findResource("GovernanceDataSource")) as {
+      source: {
+        emitter_chain: string;
+        emitter_address: { external_address: string };
+      };
+    };
     return {
       emitterChain: Number(data.source.emitter_chain),
       emitterAddress: data.source.emitter_address.external_address.replace(
@@ -163,7 +191,7 @@ export class AptosContract extends Contract {
   async getLastExecutedGovernanceSequence() {
     const data = (await this.findResource(
       "LastExecutedGovernanceSequence"
-    )) as any;
+    )) as { sequence: string };
     return Number(data.sequence);
   }
 
@@ -181,7 +209,9 @@ export class AptosContract extends Contract {
   }
 
   async getValidTimePeriod() {
-    const data = (await this.findResource("StalePriceThreshold")) as any;
+    const data = (await this.findResource("StalePriceThreshold")) as {
+      threshold_secs: string;
+    };
     return Number(data.threshold_secs);
   }
 

+ 76 - 71
contract_manager/src/contracts/cosmwasm.ts

@@ -9,30 +9,29 @@ import {
   PythWrapperExecutor,
   PythWrapperQuerier,
 } from "@pythnetwork/cosmwasm-deploy-tools";
+import { Coin } from "@cosmjs/stargate";
 import { CHAINS, DataSource } from "xc_admin_common";
 import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
-import { Contract } from "../base";
+import { Contract, PrivateKey, TxResult } from "../base";
 import { WormholeContract } from "./wormhole";
 
 /**
  * Variables here need to be snake case to match the on-chain contract configs
  */
-namespace CosmWasmContract {
-  export interface WormholeSource {
-    emitter: string;
-    chain_id: number;
-  }
-
-  export interface DeploymentConfig {
-    data_sources: WormholeSource[];
-    governance_source: WormholeSource;
-    wormhole_contract: string;
-    governance_source_index: number;
-    governance_sequence_number: number;
-    chain_id: number;
-    valid_time_period_secs: number;
-    fee: { amount: string; denom: string };
-  }
+export interface WormholeSource {
+  emitter: string;
+  chain_id: number;
+}
+
+export interface DeploymentConfig {
+  data_sources: WormholeSource[];
+  governance_source: WormholeSource;
+  wormhole_contract: string;
+  governance_source_index: number;
+  governance_sequence_number: number;
+  chain_id: number;
+  valid_time_period_secs: number;
+  fee: { amount: string; denom: string };
 }
 
 export class WormholeCosmWasmContract extends WormholeContract {
@@ -44,7 +43,7 @@ export class WormholeCosmWasmContract extends WormholeContract {
     const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
     return (await chainQuerier.getAllContractState({
       contractAddr: this.address,
-    })) as any;
+    })) as Record<string, string>;
   }
 
   async getCurrentGuardianSetIndex(): Promise<number> {
@@ -68,28 +67,31 @@ export class WormholeCosmWasmContract extends WormholeContract {
   }
 
   async upgradeGuardianSets(
-    senderPrivateKey: string,
+    senderPrivateKey: PrivateKey,
     vaa: Buffer
-  ): Promise<any> {
+  ): Promise<TxResult> {
     const executor = await this.chain.getExecutor(senderPrivateKey);
-    return executor.executeContract({
+    const result = await executor.executeContract({
       contractAddr: this.address,
       msg: {
         submit_v_a_a: { vaa: vaa.toString("base64") },
       },
     });
+    return { id: result.txHash, info: result };
   }
 }
 
 export class CosmWasmContract extends Contract {
   async getDataSources(): Promise<DataSource[]> {
     const config = await this.getConfig();
-    return config.config_v1.data_sources.map(({ emitter, chain_id }: any) => {
-      return {
-        emitterChain: Number(chain_id),
-        emitterAddress: Buffer.from(emitter, "base64").toString("hex"),
-      };
-    });
+    return config.config_v1.data_sources.map(
+      ({ emitter, chain_id }: { emitter: string; chain_id: string }) => {
+        return {
+          emitterChain: Number(chain_id),
+          emitterAddress: Buffer.from(emitter, "base64").toString("hex"),
+        };
+      }
+    );
   }
 
   async getGovernanceDataSource(): Promise<DataSource> {
@@ -108,7 +110,10 @@ export class CosmWasmContract extends Contract {
     super();
   }
 
-  static fromJson(chain: Chain, parsed: any): CosmWasmContract {
+  static fromJson(
+    chain: Chain,
+    parsed: { type: string; address: string }
+  ): CosmWasmContract {
     if (parsed.type !== CosmWasmContract.type) throw new Error("Invalid type");
     if (!(chain instanceof CosmWasmChain))
       throw new Error(`Wrong chain type ${chain}`);
@@ -119,17 +124,16 @@ export class CosmWasmContract extends Contract {
     return CosmWasmContract.type;
   }
 
-  //TODO : make deploymentType enum stable  | edge
   static getDeploymentConfig(
     chain: CosmWasmChain,
-    deploymentType: string,
+    deploymentType: DeploymentType,
     wormholeContract: string
-  ): CosmWasmContract.DeploymentConfig {
+  ): DeploymentConfig {
     return getPythConfig({
       feeDenom: chain.feeDenom,
-      wormholeChainId: CHAINS[chain.getId() as keyof typeof CHAINS],
+      wormholeChainId: CHAINS[chain.wormholeChainName],
       wormholeContract,
-      deploymentType: deploymentType as DeploymentType,
+      deploymentType: deploymentType,
     });
   }
 
@@ -142,11 +146,11 @@ export class CosmWasmContract extends Contract {
    */
   static async storeCode(
     chain: CosmWasmChain,
-    privateKey: string,
+    privateKey: PrivateKey,
     wasmPath: string
   ) {
     const contractBytes = readFileSync(wasmPath);
-    let executor = await chain.getExecutor(privateKey);
+    const executor = await chain.getExecutor(privateKey);
     return executor.storeCode({ contractBytes });
   }
 
@@ -160,11 +164,11 @@ export class CosmWasmContract extends Contract {
   static async initialize(
     chain: CosmWasmChain,
     codeId: number,
-    config: CosmWasmContract.DeploymentConfig,
-    privateKey: string
+    config: DeploymentConfig,
+    privateKey: PrivateKey
   ): Promise<CosmWasmContract> {
-    let executor = await chain.getExecutor(privateKey);
-    let result = await executor.instantiateContract({
+    const executor = await chain.getExecutor(privateKey);
+    const result = await executor.instantiateContract({
       codeId: codeId,
       instMsg: config,
       label: "pyth",
@@ -190,10 +194,10 @@ export class CosmWasmContract extends Contract {
   static async deploy(
     chain: CosmWasmChain,
     wormholeContract: string,
-    privateKey: string,
+    privateKey: PrivateKey,
     wasmPath: string
   ): Promise<CosmWasmContract> {
-    let config = this.getDeploymentConfig(chain, "edge", wormholeContract);
+    const config = this.getDeploymentConfig(chain, "beta", wormholeContract);
     const { codeId } = await this.storeCode(chain, privateKey, wasmPath);
     return this.initialize(chain, codeId, config, privateKey);
   }
@@ -217,7 +221,7 @@ export class CosmWasmContract extends Contract {
   }
 
   async getCodeId(): Promise<number> {
-    let result = await this.getWasmContractInfo();
+    const result = await this.getWasmContractInfo();
     return result.codeId;
   }
 
@@ -228,10 +232,10 @@ export class CosmWasmContract extends Contract {
 
   async getConfig() {
     const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
-    let allStates = (await chainQuerier.getAllContractState({
+    const allStates = (await chainQuerier.getAllContractState({
       contractAddr: this.address,
-    })) as any;
-    let config = {
+    })) as Record<string, string>;
+    const config = {
       config_v1: JSON.parse(allStates["\x00\tconfig_v1"]),
       contract_version: JSON.parse(allStates["\x00\x10contract_version"]),
     };
@@ -256,7 +260,7 @@ export class CosmWasmContract extends Contract {
   }
 
   async getPriceFeed(feedId: string) {
-    let querier = await this.getQuerier();
+    const querier = await this.getQuerier();
     try {
       const response = await querier.getPriceFeed(this.address, feedId);
       return {
@@ -269,8 +273,8 @@ export class CosmWasmContract extends Contract {
   }
 
   equalDataSources(
-    dataSources1: CosmWasmContract.WormholeSource[],
-    dataSources2: CosmWasmContract.WormholeSource[]
+    dataSources1: WormholeSource[],
+    dataSources2: WormholeSource[]
   ): boolean {
     if (dataSources1.length !== dataSources2.length) return false;
     for (let i = 0; i < dataSources1.length; i++) {
@@ -290,19 +294,19 @@ export class CosmWasmContract extends Contract {
   }
 
   async getDeploymentType(): Promise<string> {
-    let config = await this.getConfig();
-    let wormholeContract = config.config_v1.wormhole_contract;
-    let stableConfig = getPythConfig({
+    const config = await this.getConfig();
+    const wormholeContract = config.config_v1.wormhole_contract;
+    const stableConfig = getPythConfig({
       feeDenom: this.chain.feeDenom,
       wormholeChainId: CHAINS[this.chain.getId() as keyof typeof CHAINS],
       wormholeContract,
       deploymentType: "stable",
     });
-    let edgeConfig = getPythConfig({
+    const betaConfig = getPythConfig({
       feeDenom: this.chain.feeDenom,
       wormholeChainId: CHAINS[this.chain.getId() as keyof typeof CHAINS],
       wormholeContract,
-      deploymentType: "edge",
+      deploymentType: "beta",
     });
     if (
       this.equalDataSources(
@@ -314,52 +318,53 @@ export class CosmWasmContract extends Contract {
     else if (
       this.equalDataSources(
         config.config_v1.data_sources,
-        edgeConfig.data_sources
+        betaConfig.data_sources
       )
     )
-      return "edge";
+      return "beta";
     else return "unknown";
   }
 
-  async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
+  async executeUpdatePriceFeed(senderPrivateKey: PrivateKey, vaas: Buffer[]) {
     const base64Vaas = vaas.map((v) => v.toString("base64"));
     const fund = await this.getUpdateFee(base64Vaas);
-    let executor = await this.chain.getExecutor(senderPrivateKey);
-    let pythExecutor = new PythWrapperExecutor(executor);
-    return pythExecutor.executeUpdatePriceFeeds({
+    const executor = await this.chain.getExecutor(senderPrivateKey);
+    const pythExecutor = new PythWrapperExecutor(executor);
+    const result = await pythExecutor.executeUpdatePriceFeeds({
       contractAddr: this.address,
       vaas: base64Vaas,
       fund,
     });
+    return { id: result.txHash, info: result };
   }
 
-  async executeGovernanceInstruction(privateKey: string, vaa: Buffer) {
-    let executor = await this.chain.getExecutor(privateKey);
-    let pythExecutor = new PythWrapperExecutor(executor);
-    return pythExecutor.executeGovernanceInstruction({
+  async executeGovernanceInstruction(privateKey: PrivateKey, vaa: Buffer) {
+    const executor = await this.chain.getExecutor(privateKey);
+    const pythExecutor = new PythWrapperExecutor(executor);
+    const result = await pythExecutor.executeGovernanceInstruction({
       contractAddr: this.address,
       vaa: vaa.toString("base64"),
     });
+    return { id: result.txHash, info: result };
   }
 
   async getWormholeContract(): Promise<WormholeCosmWasmContract> {
-    let config = await this.getConfig();
-    const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
+    const config = await this.getConfig();
     const wormholeAddress = config.config_v1.wormhole_contract;
     return new WormholeCosmWasmContract(this.chain, wormholeAddress);
   }
 
-  async getUpdateFee(msgs: string[]): Promise<any> {
-    let querier = await this.getQuerier();
+  async getUpdateFee(msgs: string[]): Promise<Coin> {
+    const querier = await this.getQuerier();
     return querier.getUpdateFee(this.address, msgs);
   }
 
-  async getBaseUpdateFee(): Promise<any> {
+  async getBaseUpdateFee(): Promise<{ amount: string; denom: string }> {
     const config = await this.getConfig();
     return config.config_v1.fee;
   }
 
-  async getVersion(): Promise<any> {
+  async getVersion(): Promise<string> {
     const config = await this.getConfig();
     return config.contract_version;
   }
@@ -378,8 +383,8 @@ export class CosmWasmContract extends Contract {
   }
 
   async getValidTimePeriod() {
-    let client = await CosmWasmClient.connect(this.chain.endpoint);
-    let result = await client.queryContractSmart(
+    const client = await CosmWasmClient.connect(this.chain.endpoint);
+    const result = await client.queryContractSmart(
       this.address,
       "get_valid_time_period"
     );

+ 21 - 12
contract_manager/src/contracts/evm.ts

@@ -1,6 +1,6 @@
-import Web3 from "web3"; //TODO: decide on using web3 or ethers.js
+import Web3 from "web3";
 import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
-import { Contract } from "../base";
+import { Contract, PrivateKey } from "../base";
 import { Chain, EvmChain } from "../chains";
 import { DataSource } from "xc_admin_common";
 import { WormholeContract } from "./wormhole";
@@ -138,7 +138,7 @@ const EXTENDED_PYTH_ABI = [
     type: "function",
   },
   ...PythInterfaceAbi,
-] as any;
+] as any; // eslint-disable-line  @typescript-eslint/no-explicit-any
 
 const WORMHOLE_ABI = [
   {
@@ -211,7 +211,7 @@ const WORMHOLE_ABI = [
     stateMutability: "view",
     type: "function",
   },
-] as any;
+] as any; // eslint-disable-line  @typescript-eslint/no-explicit-any
 export class WormholeEvmContract extends WormholeContract {
   constructor(public chain: EvmChain, public address: string) {
     super();
@@ -256,7 +256,7 @@ export class WormholeEvmContract extends WormholeContract {
     }
   }
 
-  async upgradeGuardianSets(senderPrivateKey: string, vaa: Buffer) {
+  async upgradeGuardianSets(senderPrivateKey: PrivateKey, vaa: Buffer) {
     const web3 = new Web3(this.chain.getRpcUrl());
     const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
     const wormholeContract = new web3.eth.Contract(WORMHOLE_ABI, this.address);
@@ -267,11 +267,12 @@ export class WormholeEvmContract extends WormholeContract {
       from: address,
       gas: 100000000,
     });
-    return transactionObject.send({
+    const result = await transactionObject.send({
       from: address,
       gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
       gasPrice: await this.chain.getGasPrice(),
     });
+    return { id: result.transactionHash, info: result };
   }
 }
 
@@ -282,7 +283,10 @@ export class EvmContract extends Contract {
     super();
   }
 
-  static fromJson(chain: Chain, parsed: any): EvmContract {
+  static fromJson(
+    chain: Chain,
+    parsed: { type: string; address: string }
+  ): EvmContract {
     if (parsed.type !== EvmContract.type) throw new Error("Invalid type");
     if (!(chain instanceof EvmChain))
       throw new Error(`Wrong chain type ${chain}`);
@@ -321,7 +325,7 @@ export class EvmContract extends Contract {
   async getImplementationAddress(): Promise<string> {
     const web3 = new Web3(this.chain.getRpcUrl());
     // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) according to EIP-1967
-    let storagePosition =
+    const storagePosition =
       "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
     let address = await web3.eth.getStorageAt(this.address, storagePosition);
     address = "0x" + address.slice(26);
@@ -433,7 +437,7 @@ export class EvmContract extends Contract {
     };
   }
 
-  async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
+  async executeUpdatePriceFeed(senderPrivateKey: PrivateKey, vaas: Buffer[]) {
     const web3 = new Web3(this.chain.getRpcUrl());
     const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
     const pythContract = new web3.eth.Contract(EXTENDED_PYTH_ABI, this.address);
@@ -448,15 +452,19 @@ export class EvmContract extends Contract {
       gas: 100000000,
       value: updateFee,
     });
-    return transactionObject.send({
+    const result = await transactionObject.send({
       from: address,
       value: updateFee,
       gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
       gasPrice: await this.chain.getGasPrice(),
     });
+    return { id: result.transactionHash, info: result };
   }
 
-  async executeGovernanceInstruction(senderPrivateKey: string, vaa: Buffer) {
+  async executeGovernanceInstruction(
+    senderPrivateKey: PrivateKey,
+    vaa: Buffer
+  ) {
     const web3 = new Web3(this.chain.getRpcUrl());
     const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
     const pythContract = new web3.eth.Contract(EXTENDED_PYTH_ABI, this.address);
@@ -467,11 +475,12 @@ export class EvmContract extends Contract {
       from: address,
       gas: 100000000,
     });
-    return transactionObject.send({
+    const result = await transactionObject.send({
       from: address,
       gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
       gasPrice: await this.chain.getGasPrice(),
     });
+    return { id: result.transactionHash, info: result };
   }
 
   getChain(): EvmChain {

+ 52 - 26
contract_manager/src/contracts/sui.ts

@@ -9,7 +9,7 @@ import {
 } from "@mysten/sui.js";
 import { Chain, SuiChain } from "../chains";
 import { DataSource } from "xc_admin_common";
-import { Contract } from "../base";
+import { Contract, PrivateKey, TxResult } from "../base";
 import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
 
 export class SuiContract extends Contract {
@@ -31,7 +31,10 @@ export class SuiContract extends Contract {
     super();
   }
 
-  static fromJson(chain: Chain, parsed: any): SuiContract {
+  static fromJson(
+    chain: Chain,
+    parsed: { type: string; stateId: string; wormholeStateId: string }
+  ): SuiContract {
     if (parsed.type !== SuiContract.type) throw new Error("Invalid type");
     if (!(chain instanceof SuiChain))
       throw new Error(`Wrong chain type ${chain}`);
@@ -81,7 +84,7 @@ export class SuiContract extends Contract {
    */
   async getPriceTableId(): Promise<ObjectId> {
     const provider = this.getProvider();
-    let result = await provider.getDynamicFieldObject({
+    const result = await provider.getDynamicFieldObject({
       parentId: this.stateId,
       name: {
         type: "vector<u8>",
@@ -94,7 +97,15 @@ export class SuiContract extends Contract {
     return result.data.objectId;
   }
 
-  private async parsePrice(priceInfo: any) {
+  private async parsePrice(priceInfo: {
+    type: string;
+    fields: {
+      expo: { fields: { magnitude: string; negative: boolean } };
+      price: { fields: { magnitude: string; negative: boolean } };
+      conf: string;
+      timestamp: string;
+    };
+  }) {
     const packageId = await this.getPythPackageId();
     const expectedType = `${packageId}::price::Price`;
     if (priceInfo.type !== expectedType) {
@@ -117,7 +128,7 @@ export class SuiContract extends Contract {
   async getPriceFeedObjectId(feedId: string): Promise<ObjectId | undefined> {
     const tableId = await this.getPriceTableId();
     const provider = this.getProvider();
-    let result = await provider.getDynamicFieldObject({
+    const result = await provider.getDynamicFieldObject({
       parentId: tableId,
       name: {
         type: `${await this.getPythPackageId()}::price_identifier::PriceIdentifier`,
@@ -137,9 +148,9 @@ export class SuiContract extends Contract {
 
   async getPriceFeed(feedId: string) {
     const provider = this.getProvider();
-    let priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
+    const priceInfoObjectId = await this.getPriceFeedObjectId(feedId);
     if (!priceInfoObjectId) return undefined;
-    let priceInfo = await provider.getObject({
+    const priceInfo = await provider.getObject({
       id: priceInfoObjectId,
       options: { showContent: true },
     });
@@ -173,7 +184,7 @@ export class SuiContract extends Contract {
   async executeMigrateInstruction(vaa: Buffer, keypair: Ed25519Keypair) {
     const tx = new TransactionBlock();
     const packageId = await this.getPythPackageId();
-    let verificationReceipt = await this.getVaaVerificationReceipt(
+    const verificationReceipt = await this.getVaaVerificationReceipt(
       tx,
       packageId,
       vaa
@@ -187,7 +198,7 @@ export class SuiContract extends Contract {
     return this.executeTransaction(tx, keypair);
   }
 
-  async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
+  async executeUpdatePriceFeed(): Promise<TxResult> {
     // We need the feed ids to be able to execute the transaction
     // it may be possible to get them from the VAA but in batch transactions,
     // it is also possible to hava fewer feeds that user wants to update compared to
@@ -207,17 +218,20 @@ export class SuiContract extends Contract {
     senderPrivateKey: string,
     vaas: Buffer[],
     feedIds: string[]
-  ) {
+  ): Promise<TxResult> {
     const tx = new TransactionBlock();
     const client = this.getSdkClient();
     await client.updatePriceFeeds(tx, vaas, feedIds);
     const keypair = Ed25519Keypair.fromSecretKey(
       Buffer.from(senderPrivateKey, "hex")
     );
-    let result = await this.executeTransaction(tx, keypair);
-    return result.digest;
+    const result = await this.executeTransaction(tx, keypair);
+    return { id: result.digest, info: result };
   }
-  async executeCreatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
+  async executeCreatePriceFeed(
+    senderPrivateKey: string,
+    vaas: Buffer[]
+  ): Promise<TxResult> {
     const tx = new TransactionBlock();
     const client = this.getSdkClient();
     await client.createPriceFeed(tx, vaas);
@@ -225,17 +239,20 @@ export class SuiContract extends Contract {
       Buffer.from(senderPrivateKey, "hex")
     );
 
-    let result = await this.executeTransaction(tx, keypair);
-    return result.digest;
+    const result = await this.executeTransaction(tx, keypair);
+    return { id: result.digest, info: result };
   }
 
-  async executeGovernanceInstruction(senderPrivateKey: string, vaa: Buffer) {
+  async executeGovernanceInstruction(
+    senderPrivateKey: PrivateKey,
+    vaa: Buffer
+  ): Promise<TxResult> {
     const keypair = Ed25519Keypair.fromSecretKey(
       Buffer.from(senderPrivateKey, "hex")
     );
     const tx = new TransactionBlock();
     const packageId = await this.getPythPackageId();
-    let verificationReceipt = await this.getVaaVerificationReceipt(
+    const verificationReceipt = await this.getVaaVerificationReceipt(
       tx,
       packageId,
       vaa
@@ -246,7 +263,8 @@ export class SuiContract extends Contract {
       arguments: [tx.object(this.stateId), verificationReceipt],
     });
 
-    return this.executeTransaction(tx, keypair);
+    const result = await this.executeTransaction(tx, keypair);
+    return { id: result.digest, info: result };
   }
 
   async executeUpgradeInstruction(
@@ -257,7 +275,7 @@ export class SuiContract extends Contract {
   ) {
     const tx = new TransactionBlock();
     const packageId = await this.getPythPackageId();
-    let verificationReceipt = await this.getVaaVerificationReceipt(
+    const verificationReceipt = await this.getVaaVerificationReceipt(
       tx,
       packageId,
       vaa
@@ -279,7 +297,8 @@ export class SuiContract extends Contract {
       target: `${packageId}::contract_upgrade::commit_upgrade`,
       arguments: [tx.object(this.stateId), upgradeReceipt],
     });
-    return this.executeTransaction(tx, keypair);
+    const result = await this.executeTransaction(tx, keypair);
+    return { id: result.digest, info: result };
   }
 
   /**
@@ -297,7 +316,7 @@ export class SuiContract extends Contract {
   ) {
     const wormholePackageId = await this.getWormholePackageId();
 
-    let [verifiedVAA] = tx.moveCall({
+    const [verifiedVAA] = tx.moveCall({
       target: `${wormholePackageId}::vaa::parse_and_verify`,
       arguments: [
         tx.object(this.wormholeStateId),
@@ -306,7 +325,7 @@ export class SuiContract extends Contract {
       ],
     });
 
-    let [verificationReceipt] = tx.moveCall({
+    const [verificationReceipt] = tx.moveCall({
       target: `${packageId}::governance::verify_vaa`,
       arguments: [tx.object(this.stateId), verifiedVAA],
     });
@@ -325,7 +344,7 @@ export class SuiContract extends Contract {
     keypair: Ed25519Keypair
   ) {
     const provider = this.getProvider();
-    let txBlock = {
+    const txBlock = {
       transactionBlock: tx,
       options: {
         showEffects: true,
@@ -333,7 +352,7 @@ export class SuiContract extends Contract {
       },
     };
     const wallet = new RawSigner(keypair, provider);
-    let gasCost = await wallet.getGasCostEstimation(txBlock);
+    const gasCost = await wallet.getGasCostEstimation(txBlock);
     tx.setGasBudget(gasCost * BigInt(2));
     return wallet.signAndExecuteTransactionBlock(txBlock);
   }
@@ -345,7 +364,7 @@ export class SuiContract extends Contract {
 
   async getDataSources(): Promise<DataSource[]> {
     const provider = this.getProvider();
-    let result = await provider.getDynamicFieldObject({
+    const result = await provider.getDynamicFieldObject({
       parentId: this.stateId,
       name: {
         type: "vector<u8>",
@@ -361,7 +380,14 @@ export class SuiContract extends Contract {
       throw new Error("Data Sources type mismatch");
     }
     return result.data.content.fields.value.fields.keys.map(
-      ({ fields }: any) => {
+      ({
+        fields,
+      }: {
+        fields: {
+          emitter_address: { fields: { value: { fields: { data: string } } } };
+          emitter_chain: string;
+        };
+      }) => {
         return {
           emitterChain: Number(fields.emitter_chain),
           emitterAddress: Buffer.from(

File diff ditekan karena terlalu besar
+ 5 - 3
contract_manager/src/contracts/wormhole.ts


+ 2 - 1
contract_manager/src/executor.ts

@@ -1,13 +1,14 @@
 import { parseVaa } from "@certusone/wormhole-sdk";
 import { decodeGovernancePayload } from "xc_admin_common";
 import { DefaultStore } from "./store";
+import { PrivateKey } from "./base";
 
 /**
  * A general executor that tries to find any contract that can execute a given VAA and executes it
  * @param senderPrivateKey the private key to execute the governance instruction with
  * @param vaa the VAA to execute
  */
-export async function executeVaa(senderPrivateKey: string, vaa: Buffer) {
+export async function executeVaa(senderPrivateKey: PrivateKey, vaa: Buffer) {
   const parsedVaa = parseVaa(vaa);
   const action = decodeGovernancePayload(parsedVaa.payload);
   if (!action) return; //TODO: handle other actions

+ 20 - 16
contract_manager/src/governance.ts

@@ -31,7 +31,7 @@ import {
   deriveFeeCollectorKey,
   deriveWormholeBridgeDataKey,
 } from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
-import { Storable } from "./base";
+import { KeyValueConfig, Storable } from "./base";
 
 class InvalidTransactionError extends Error {
   constructor(message: string) {
@@ -75,8 +75,8 @@ export class SubmittedWormholeMessage {
       )
     );
 
-    const wormholeAddress =
-      WORMHOLE_ADDRESS[cluster as keyof typeof WORMHOLE_ADDRESS]!;
+    const wormholeAddress = WORMHOLE_ADDRESS[cluster];
+    if (!wormholeAddress) throw new Error(`Invalid cluster ${cluster}`);
     let emitter: PublicKey | undefined = undefined;
 
     let allInstructions: (ParsedInstruction | PartiallyDecodedInstruction)[] =
@@ -103,10 +103,10 @@ export class SubmittedWormholeMessage {
    * before giving up and throwing an error
    * @param waitingSeconds how long to wait before giving up
    */
-  async fetchVaa(waitingSeconds: number = 1): Promise<Buffer> {
-    let rpcUrl = WORMHOLE_API_ENDPOINT[this.cluster];
+  async fetchVaa(waitingSeconds = 1): Promise<Buffer> {
+    const rpcUrl = WORMHOLE_API_ENDPOINT[this.cluster];
 
-    let startTime = Date.now();
+    const startTime = Date.now();
     while (Date.now() - startTime < waitingSeconds * 1000) {
       const response = await fetch(
         `${rpcUrl}/v1/signed_vaa/1/${this.emitter.toBuffer().toString("hex")}/${
@@ -158,12 +158,12 @@ export class WormholeEmitter {
         preflightCommitment: "confirmed",
       }
     );
-    let wormholeAddress =
-      WORMHOLE_ADDRESS[this.cluster as keyof typeof WORMHOLE_ADDRESS]!;
-    let kp = Keypair.generate();
-    let feeCollector = deriveFeeCollectorKey(wormholeAddress);
-    let emitter = this.wallet.publicKey;
-    let accounts = {
+    const wormholeAddress = WORMHOLE_ADDRESS[this.cluster];
+    if (!wormholeAddress) throw new Error(`Invalid cluster ${this.cluster}`);
+    const kp = Keypair.generate();
+    const feeCollector = deriveFeeCollectorKey(wormholeAddress);
+    const emitter = this.wallet.publicKey;
+    const accounts = {
       bridge: deriveWormholeBridgeDataKey(wormholeAddress),
       message: kp.publicKey,
       emitter: emitter,
@@ -230,7 +230,7 @@ export class WormholeMultiSigTransaction {
             this.cluster
           )
         );
-      } catch (e: any) {
+      } catch (e) {
         if (!(e instanceof InvalidTransactionError)) throw e;
       }
     }
@@ -240,7 +240,7 @@ export class WormholeMultiSigTransaction {
 }
 
 export class Vault extends Storable {
-  static type: string = "vault";
+  static type = "vault";
   key: PublicKey;
   squad?: SquadsMesh;
   cluster: PythCluster;
@@ -255,7 +255,11 @@ export class Vault extends Storable {
     return Vault.type;
   }
 
-  static fromJson(parsed: any): Vault {
+  static fromJson(parsed: {
+    type: string;
+    key: string;
+    cluster: string;
+  }): Vault {
     if (parsed.type !== Vault.type) throw new Error("Invalid type");
     return new Vault(parsed.key, parsed.cluster);
   }
@@ -264,7 +268,7 @@ export class Vault extends Storable {
     return `${this.cluster}_${this.key.toString()}`;
   }
 
-  toJson(): any {
+  toJson(): KeyValueConfig {
     return {
       key: this.key.toString(),
       cluster: this.cluster,

+ 1 - 0
contract_manager/src/shell.ts

@@ -12,5 +12,6 @@ repl.evalCode(
     "import { WormholeEvmContract, EvmContract } from './src/contracts/evm';" +
     "import { AptosContract } from './src/contracts/aptos';" +
     "import { DefaultStore } from './src/store';" +
+    "import { toPrivateKey } from './src/base';" +
     "DefaultStore"
 );

+ 9 - 9
contract_manager/src/store.ts

@@ -53,7 +53,7 @@ export class Store {
   }
 
   loadAllChains() {
-    let allChainClasses = {
+    const allChainClasses = {
       [CosmWasmChain.type]: CosmWasmChain,
       [SuiChain.type]: SuiChain,
       [EvmChain.type]: EvmChain,
@@ -61,10 +61,10 @@ export class Store {
     };
 
     this.getYamlFiles(`${this.path}/chains/`).forEach((yamlFile) => {
-      let parsedArray = parse(readFileSync(yamlFile, "utf-8"));
+      const parsedArray = parse(readFileSync(yamlFile, "utf-8"));
       for (const parsed of parsedArray) {
         if (allChainClasses[parsed.type] === undefined) return;
-        let chain = allChainClasses[parsed.type].fromJson(parsed);
+        const chain = allChainClasses[parsed.type].fromJson(parsed);
         if (this.chains[chain.getId()])
           throw new Error(`Multiple chains with id ${chain.getId()} found`);
         this.chains[chain.getId()] = chain;
@@ -73,7 +73,7 @@ export class Store {
   }
 
   saveAllContracts() {
-    let contractsByType: Record<string, Contract[]> = {};
+    const contractsByType: Record<string, Contract[]> = {};
     for (const contract of Object.values(this.contracts)) {
       if (!contractsByType[contract.getType()]) {
         contractsByType[contract.getType()] = [];
@@ -89,7 +89,7 @@ export class Store {
   }
 
   saveAllChains() {
-    let chainsByType: Record<string, Chain[]> = {};
+    const chainsByType: Record<string, Chain[]> = {};
     for (const chain of Object.values(this.chains)) {
       if (!chainsByType[chain.getType()]) {
         chainsByType[chain.getType()] = [];
@@ -105,20 +105,20 @@ export class Store {
   }
 
   loadAllContracts() {
-    let allContractClasses = {
+    const allContractClasses = {
       [CosmWasmContract.type]: CosmWasmContract,
       [SuiContract.type]: SuiContract,
       [EvmContract.type]: EvmContract,
       [AptosContract.type]: AptosContract,
     };
     this.getYamlFiles(`${this.path}/contracts/`).forEach((yamlFile) => {
-      let parsedArray = parse(readFileSync(yamlFile, "utf-8"));
+      const parsedArray = parse(readFileSync(yamlFile, "utf-8"));
       for (const parsed of parsedArray) {
         if (allContractClasses[parsed.type] === undefined) return;
         if (!this.chains[parsed.chain])
           throw new Error(`Chain ${parsed.chain} not found`);
         const chain = this.chains[parsed.chain];
-        let chainContract = allContractClasses[parsed.type].fromJson(
+        const chainContract = allContractClasses[parsed.type].fromJson(
           chain,
           parsed
         );
@@ -133,7 +133,7 @@ export class Store {
 
   loadAllVaults() {
     this.getYamlFiles(`${this.path}/vaults/`).forEach((yamlFile) => {
-      let parsedArray = parse(readFileSync(yamlFile, "utf-8"));
+      const parsedArray = parse(readFileSync(yamlFile, "utf-8"));
       for (const parsed of parsedArray) {
         if (parsed.type !== Vault.type) return;
 

+ 2 - 2
target_chains/cosmwasm/tools/src/helper.ts

@@ -18,7 +18,7 @@ export function getChainIdsForStableDeployment(): ChainId[] {
   ];
 }
 
-export function getChainIdsForEdgeDeployment(): ChainId[] {
+export function getChainIdsForBetaDeployment(): ChainId[] {
   return [
     ChainId.INJECTIVE_TESTNET,
     ChainId.OSMOSIS_TESTNET_5,
@@ -28,7 +28,7 @@ export function getChainIdsForEdgeDeployment(): ChainId[] {
   ];
 }
 
-export type DeploymentType = "stable" | "edge";
+export type DeploymentType = "stable" | "beta";
 
 // We have released the compile contacts on github. If a chain needs some specific
 // feature in a contract, a version of the contract with that specific features is

+ 3 - 3
target_chains/cosmwasm/tools/src/instantiate-pyth.ts

@@ -12,7 +12,7 @@ import { Pipeline } from "./pipeline";
 import {
   DeploymentType,
   WORMHOLE_CONTRACT_VERSION,
-  getChainIdsForEdgeDeployment,
+  getChainIdsForBetaDeployment,
   getChainIdsForStableDeployment,
   getContractBytesDict,
   getPythInstantiateFileName,
@@ -35,7 +35,7 @@ const argv = yargs(hideBin(process.argv))
   .option("deploy", {
     type: "string",
     desc: "Execute this script for the given networks.",
-    choices: ["edge", "stable"],
+    choices: ["beta", "stable"],
     demandOption: "Please provide the deployment type",
   })
   .help()
@@ -48,7 +48,7 @@ async function run() {
   if (argv.deploy === "stable") {
     chainIds = getChainIdsForStableDeployment();
   } else {
-    chainIds = getChainIdsForEdgeDeployment();
+    chainIds = getChainIdsForBetaDeployment();
   }
 
   // get the wasm code from github

+ 3 - 3
target_chains/cosmwasm/tools/src/test.ts

@@ -8,7 +8,7 @@ import { Pipeline } from "./pipeline";
 import { PythWrapperExecutor, PythWrapperQuerier } from "./pyth-wrapper";
 import {
   DeploymentType,
-  getChainIdsForEdgeDeployment,
+  getChainIdsForBetaDeployment,
   getChainIdsForStableDeployment,
   getPythContractAddress,
   getTestPythContractFileName,
@@ -29,7 +29,7 @@ const argv = yargs(hideBin(process.argv))
   .option("deploy", {
     type: "string",
     desc: "test the following deployment type.",
-    choices: ["stable", "edge"],
+    choices: ["stable", "beta"],
     demandOption: "Please provide the deployment type",
   })
   .help()
@@ -42,7 +42,7 @@ async function run() {
   if (argv.deploy === "stable") {
     chainIds = getChainIdsForStableDeployment();
   } else {
-    chainIds = getChainIdsForEdgeDeployment();
+    chainIds = getChainIdsForBetaDeployment();
   }
 
   for (let chainId of chainIds) {

+ 3 - 3
target_chains/cosmwasm/tools/src/wormhole-stub.ts

@@ -12,7 +12,7 @@ import {
 import { Pipeline } from "./pipeline";
 import {
   DeploymentType,
-  getChainIdsForEdgeDeployment,
+  getChainIdsForBetaDeployment,
   getChainIdsForStableDeployment,
   getWormholeFileName,
   hexToBase64,
@@ -33,7 +33,7 @@ const argv = yargs(hideBin(process.argv))
   .option("deploy", {
     type: "string",
     desc: "Execute this script for the given deployment type.",
-    choices: ["stable", "edge"],
+    choices: ["stable", "beta"],
     demandOption: "Please provide the deployment type",
   })
   .help()
@@ -60,7 +60,7 @@ async function run() {
   if (argv.deploy === "stable") {
     chainIds = getChainIdsForStableDeployment();
   } else {
-    chainIds = getChainIdsForEdgeDeployment();
+    chainIds = getChainIdsForBetaDeployment();
   }
 
   for (let chainId of chainIds) {

+ 1 - 1
target_chains/ethereum/contracts/scripts/contractManagerConfig.js

@@ -16,7 +16,7 @@ function convertChainId(number) {
 function getDefaultConfig(chainName) {
   const chain = DefaultStore.chains[chainName];
   const { dataSources, governanceDataSource, wormholeConfig } =
-    getDefaultDeploymentConfig(chain.isMainnet() ? "stable" : "edge");
+    getDefaultDeploymentConfig(chain.isMainnet() ? "stable" : "beta");
 
   const emitterChainIds = dataSources.map((dataSource) =>
     convertChainId(dataSource.emitterChain)

+ 1 - 1
target_chains/sui/cli/src/cli.ts

@@ -182,7 +182,7 @@ yargs(hideBin(process.argv))
         provider
       );
       const result = await publishPackage(wallet, argv.path);
-      const deploymentType = chain.isMainnet() ? "stable" : "edge";
+      const deploymentType = chain.isMainnet() ? "stable" : "beta";
       const config = getDefaultDeploymentConfig(deploymentType);
       await initPyth(
         wallet,

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini