[contract-manager] Contract manager improvements (#1000)
* Use arrays instead of separate files per config * Remove redundant endpoint on cosmwasm * Add functions for upgrading the wormhole guardian sets * Add wormhole contract management on evm and cosmwasm * Add getter functions to check what sort of wormhole-deployment is used * Reorganize contract manager package to be used via other packages * Remove .env files per network and create a script that outputs the same file * Use env variables in truffle config and output config in deployments * Add executeUpdatePriceFeed to contract interface * Add update pricefeed script * Add saving functionality to store * Save new contract configs automatically on Evm * Make deploy script use the create-env.js internally * Add utility function to get implementation address for Evm Proxy contracts * Add shimmer testnet and replace evmos nunfunctional rpc * New procedure for contract verification * Update docs and remove duplicate configurations * Remove shimmer configs * Read default data source configs via contract manager * Remove flattened contract before compiling/deploying
This commit is contained in:
parent
a9a21ae977
commit
272f3c1984
|
@ -1,10 +1,15 @@
|
|||
{
|
||||
"name": "@pythnetwork/pyth-contract-manager",
|
||||
"name": "contract_manager",
|
||||
"version": "1.0.0",
|
||||
"description": "Set of tools to manage pyth contracts",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"shell": "ts-node ./src/shell.ts"
|
||||
},
|
||||
"author": "",
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { DefaultStore } from "../src";
|
||||
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
|
||||
|
||||
const parser = yargs(hideBin(process.argv))
|
||||
.scriptName("update_pricefeed.ts")
|
||||
.usage(
|
||||
"Usage: $0 --contract <contract_id> --feed-id <feed-id> --private-key <private-key>"
|
||||
)
|
||||
.options({
|
||||
contract: {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Contract to update price feeds for (e.g mumbai_0xff1a0f4744e8582DF1aE09D5611b887B6a12925C)",
|
||||
},
|
||||
"feed-id": {
|
||||
type: "array",
|
||||
demandOption: true,
|
||||
desc: "Price feed ids to update without the leading 0x (e.g f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b). Can be provided multiple times for multiple feed updates",
|
||||
},
|
||||
"private-key": {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Private key to use to sign transaction",
|
||||
},
|
||||
endpoint: {
|
||||
type: "string",
|
||||
desc: "Price service endpoint to use, defaults to https://xc-mainnet.pyth.network for mainnet and https://xc-testnet.pyth.network for testnet",
|
||||
},
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const argv = await parser.argv;
|
||||
const contract = DefaultStore.contracts[argv.contract];
|
||||
if (!contract) {
|
||||
throw new Error(`Contract ${argv.contract} not found`);
|
||||
}
|
||||
const defaultEndpoint = contract.getChain().isMainnet()
|
||||
? "https://xc-mainnet.pyth.network"
|
||||
: "https://xc-testnet.pyth.network";
|
||||
const priceService = new PriceServiceConnection(
|
||||
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"))
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
|
@ -69,6 +69,16 @@ export abstract class Contract extends Storable {
|
|||
*/
|
||||
abstract getPriceFeed(feedId: string): Promise<PriceFeed | undefined>;
|
||||
|
||||
/**
|
||||
* Executes the update instructions contained in the VAAs using the sender credentials
|
||||
* @param senderPrivateKey private key of the sender in hex format without 0x prefix
|
||||
* @param vaas an array of VAAs containing price update messages to execute
|
||||
*/
|
||||
abstract executeUpdatePriceFeed(
|
||||
senderPrivateKey: string,
|
||||
vaas: Buffer[]
|
||||
): Promise<any>;
|
||||
|
||||
/**
|
||||
* Executes the governance instruction contained in the VAA using the sender credentials
|
||||
* @param senderPrivateKey private key of the sender in hex format without 0x prefix
|
||||
|
@ -84,3 +94,77 @@ export abstract class Contract extends Storable {
|
|||
*/
|
||||
abstract getGovernanceDataSource(): Promise<DataSource>;
|
||||
}
|
||||
|
||||
export function getDefaultDeploymentConfig(deploymentType: "stable" | "edge"): {
|
||||
dataSources: DataSource[];
|
||||
governanceDataSource: DataSource;
|
||||
wormholeConfig: {
|
||||
governanceChainId: Number;
|
||||
governanceContract: string; // 32 byte address in 64 char hex format
|
||||
initialGuardianSet: string[]; // 20 byte addresses in 40 char hex format
|
||||
};
|
||||
} {
|
||||
if (deploymentType === "stable")
|
||||
return {
|
||||
dataSources: [
|
||||
{
|
||||
emitterChain: 1,
|
||||
emitterAddress:
|
||||
"6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25",
|
||||
},
|
||||
{
|
||||
emitterChain: 26,
|
||||
emitterAddress:
|
||||
"f8cd23c2ab91237730770bbea08d61005cdda0984348f3f6eecb559638c0bba0",
|
||||
},
|
||||
{
|
||||
emitterChain: 26,
|
||||
emitterAddress:
|
||||
"e101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71",
|
||||
},
|
||||
],
|
||||
governanceDataSource: {
|
||||
emitterChain: 1,
|
||||
emitterAddress:
|
||||
"5635979a221c34931e32620b9293a463065555ea71fe97cd6237ade875b12e9e",
|
||||
},
|
||||
wormholeConfig: {
|
||||
governanceChainId: 1,
|
||||
governanceContract:
|
||||
"0000000000000000000000000000000000000000000000000000000000000004",
|
||||
initialGuardianSet: ["58cc3ae5c097b213ce3c81979e1b9f9570746aa5"],
|
||||
},
|
||||
};
|
||||
else if (deploymentType === "edge")
|
||||
return {
|
||||
dataSources: [
|
||||
{
|
||||
emitterChain: 1,
|
||||
emitterAddress:
|
||||
"f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0",
|
||||
},
|
||||
{
|
||||
emitterChain: 26,
|
||||
emitterAddress:
|
||||
"a27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6",
|
||||
},
|
||||
{
|
||||
emitterChain: 26,
|
||||
emitterAddress:
|
||||
"e101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71",
|
||||
},
|
||||
],
|
||||
governanceDataSource: {
|
||||
emitterChain: 1,
|
||||
emitterAddress:
|
||||
"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385",
|
||||
},
|
||||
wormholeConfig: {
|
||||
governanceChainId: 1,
|
||||
governanceContract:
|
||||
"0000000000000000000000000000000000000000000000000000000000000004",
|
||||
initialGuardianSet: ["13947bd48b18e53fdaeee77f3473391ac727c638"],
|
||||
},
|
||||
};
|
||||
else throw new Error(`Invalid deployment type ${deploymentType}`);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,12 @@ import {
|
|||
} from "xc_admin_common";
|
||||
import { AptosClient } from "aptos";
|
||||
import Web3 from "web3";
|
||||
import { CosmwasmQuerier } from "@pythnetwork/cosmwasm-deploy-tools";
|
||||
import {
|
||||
CosmwasmExecutor,
|
||||
CosmwasmQuerier,
|
||||
InjectiveExecutor,
|
||||
} from "@pythnetwork/cosmwasm-deploy-tools";
|
||||
import { Network } from "@injectivelabs/networks";
|
||||
|
||||
export abstract class Chain extends Storable {
|
||||
public wormholeChainName: ChainName;
|
||||
|
@ -119,8 +124,7 @@ export class CosmWasmChain extends Chain {
|
|||
id: string,
|
||||
mainnet: boolean,
|
||||
wormholeChainName: string,
|
||||
public querierEndpoint: string,
|
||||
public executorEndpoint: string,
|
||||
public endpoint: string,
|
||||
public gasPrice: string,
|
||||
public prefix: string,
|
||||
public feeDenom: string
|
||||
|
@ -134,8 +138,7 @@ export class CosmWasmChain extends Chain {
|
|||
parsed.id,
|
||||
parsed.mainnet,
|
||||
parsed.wormholeChainName,
|
||||
parsed.querierEndpoint,
|
||||
parsed.executorEndpoint,
|
||||
parsed.endpoint,
|
||||
parsed.gasPrice,
|
||||
parsed.prefix,
|
||||
parsed.feeDenom
|
||||
|
@ -144,8 +147,7 @@ export class CosmWasmChain extends Chain {
|
|||
|
||||
toJson(): any {
|
||||
return {
|
||||
querierEndpoint: this.querierEndpoint,
|
||||
executorEndpoint: this.executorEndpoint,
|
||||
endpoint: this.endpoint,
|
||||
id: this.id,
|
||||
wormholeChainName: this.wormholeChainName,
|
||||
mainnet: this.mainnet,
|
||||
|
@ -161,13 +163,27 @@ export class CosmWasmChain extends Chain {
|
|||
}
|
||||
|
||||
async getCode(codeId: number): Promise<Buffer> {
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.querierEndpoint);
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.endpoint);
|
||||
return await chainQuerier.getCode({ codeId });
|
||||
}
|
||||
|
||||
generateGovernanceUpgradePayload(codeId: bigint): Buffer {
|
||||
return new CosmosUpgradeContract(this.wormholeChainName, codeId).encode();
|
||||
}
|
||||
|
||||
async getExecutor(privateKey: string) {
|
||||
if (this.getId().indexOf("injective") > -1) {
|
||||
return InjectiveExecutor.fromPrivateKey(
|
||||
this.isMainnet() ? Network.Mainnet : Network.Testnet,
|
||||
privateKey
|
||||
);
|
||||
}
|
||||
return new CosmwasmExecutor(
|
||||
this.endpoint,
|
||||
await CosmwasmExecutor.getSignerFromPrivateKey(privateKey, this.prefix),
|
||||
this.gasPrice + this.feeDenom
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class SuiChain extends Chain {
|
||||
|
|
|
@ -2,19 +2,17 @@ import { Chain, CosmWasmChain } from "../chains";
|
|||
import { readFileSync } from "fs";
|
||||
import {
|
||||
ContractInfoResponse,
|
||||
CosmwasmExecutor,
|
||||
CosmwasmQuerier,
|
||||
DeploymentType,
|
||||
getPythConfig,
|
||||
InjectiveExecutor,
|
||||
Price,
|
||||
PythWrapperExecutor,
|
||||
PythWrapperQuerier,
|
||||
} from "@pythnetwork/cosmwasm-deploy-tools";
|
||||
import { CHAINS, DataSource } from "xc_admin_common";
|
||||
import { Network } from "@injectivelabs/networks";
|
||||
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
|
||||
import { Contract } from "../base";
|
||||
import { WormholeContract } from "./wormhole";
|
||||
|
||||
/**
|
||||
* Variables here need to be snake case to match the on-chain contract configs
|
||||
|
@ -37,6 +35,52 @@ namespace CosmWasmContract {
|
|||
}
|
||||
}
|
||||
|
||||
export class WormholeCosmWasmContract extends WormholeContract {
|
||||
constructor(public chain: CosmWasmChain, public address: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getConfig() {
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
|
||||
return (await chainQuerier.getAllContractState({
|
||||
contractAddr: this.address,
|
||||
})) as any;
|
||||
}
|
||||
|
||||
async getCurrentGuardianSetIndex(): Promise<number> {
|
||||
const config = await this.getConfig();
|
||||
return JSON.parse(config["\x00\x06config"])["guardian_set_index"];
|
||||
}
|
||||
|
||||
async getGuardianSet(): Promise<string[]> {
|
||||
const config = await this.getConfig();
|
||||
const guardianSetIndex = JSON.parse(config["\x00\x06config"])[
|
||||
"guardian_set_index"
|
||||
];
|
||||
let key = "\x00\fguardian_set";
|
||||
//append guardianSetIndex as 4 bytes to key string
|
||||
key += Buffer.from(guardianSetIndex.toString(16).padStart(8, "0"), "hex");
|
||||
|
||||
const guardianSet = JSON.parse(config[key])["addresses"];
|
||||
return guardianSet.map((entry: { bytes: string }) =>
|
||||
Buffer.from(entry.bytes, "base64").toString("hex")
|
||||
);
|
||||
}
|
||||
|
||||
async upgradeGuardianSets(
|
||||
senderPrivateKey: string,
|
||||
vaa: Buffer
|
||||
): Promise<any> {
|
||||
const executor = await this.chain.getExecutor(senderPrivateKey);
|
||||
return executor.executeContract({
|
||||
contractAddr: this.address,
|
||||
msg: {
|
||||
submit_v_a_a: { vaa: vaa.toString("base64") },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CosmWasmContract extends Contract {
|
||||
async getDataSources(): Promise<DataSource[]> {
|
||||
const config = await this.getConfig();
|
||||
|
@ -102,7 +146,7 @@ export class CosmWasmContract extends Contract {
|
|||
wasmPath: string
|
||||
) {
|
||||
const contractBytes = readFileSync(wasmPath);
|
||||
let executor = await this.getExecutor(chain, privateKey);
|
||||
let executor = await chain.getExecutor(privateKey);
|
||||
return executor.storeCode({ contractBytes });
|
||||
}
|
||||
|
||||
|
@ -119,7 +163,7 @@ export class CosmWasmContract extends Contract {
|
|||
config: CosmWasmContract.DeploymentConfig,
|
||||
privateKey: string
|
||||
): Promise<CosmWasmContract> {
|
||||
let executor = await this.getExecutor(chain, privateKey);
|
||||
let executor = await chain.getExecutor(privateKey);
|
||||
let result = await executor.instantiateContract({
|
||||
codeId: codeId,
|
||||
instMsg: config,
|
||||
|
@ -154,20 +198,6 @@ export class CosmWasmContract extends Contract {
|
|||
return this.initialize(chain, codeId, config, privateKey);
|
||||
}
|
||||
|
||||
private static async getExecutor(chain: CosmWasmChain, privateKey: string) {
|
||||
if (chain.getId().indexOf("injective") > -1) {
|
||||
return InjectiveExecutor.fromPrivateKey(
|
||||
chain.isMainnet() ? Network.Mainnet : Network.Testnet,
|
||||
privateKey
|
||||
);
|
||||
}
|
||||
return new CosmwasmExecutor(
|
||||
chain.executorEndpoint,
|
||||
await CosmwasmExecutor.getSignerFromPrivateKey(privateKey, chain.prefix),
|
||||
chain.gasPrice + chain.feeDenom
|
||||
);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return `${this.chain.getId()}_${this.address}`;
|
||||
}
|
||||
|
@ -181,9 +211,7 @@ export class CosmWasmContract extends Contract {
|
|||
}
|
||||
|
||||
async getQuerier(): Promise<PythWrapperQuerier> {
|
||||
const chainQuerier = await CosmwasmQuerier.connect(
|
||||
this.chain.querierEndpoint
|
||||
);
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
|
||||
const pythQuerier = new PythWrapperQuerier(chainQuerier);
|
||||
return pythQuerier;
|
||||
}
|
||||
|
@ -194,16 +222,12 @@ export class CosmWasmContract extends Contract {
|
|||
}
|
||||
|
||||
async getWasmContractInfo(): Promise<ContractInfoResponse> {
|
||||
const chainQuerier = await CosmwasmQuerier.connect(
|
||||
this.chain.querierEndpoint
|
||||
);
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
|
||||
return chainQuerier.getContractInfo({ contractAddr: this.address });
|
||||
}
|
||||
|
||||
async getConfig() {
|
||||
const chainQuerier = await CosmwasmQuerier.connect(
|
||||
this.chain.querierEndpoint
|
||||
);
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
|
||||
let allStates = (await chainQuerier.getAllContractState({
|
||||
contractAddr: this.address,
|
||||
})) as any;
|
||||
|
@ -300,10 +324,7 @@ export class CosmWasmContract extends Contract {
|
|||
async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
|
||||
const base64Vaas = vaas.map((v) => v.toString("base64"));
|
||||
const fund = await this.getUpdateFee(base64Vaas);
|
||||
let executor = await CosmWasmContract.getExecutor(
|
||||
this.chain,
|
||||
senderPrivateKey
|
||||
);
|
||||
let executor = await this.chain.getExecutor(senderPrivateKey);
|
||||
let pythExecutor = new PythWrapperExecutor(executor);
|
||||
return pythExecutor.executeUpdatePriceFeeds({
|
||||
contractAddr: this.address,
|
||||
|
@ -313,7 +334,7 @@ export class CosmWasmContract extends Contract {
|
|||
}
|
||||
|
||||
async executeGovernanceInstruction(privateKey: string, vaa: Buffer) {
|
||||
let executor = await CosmWasmContract.getExecutor(this.chain, privateKey);
|
||||
let executor = await this.chain.getExecutor(privateKey);
|
||||
let pythExecutor = new PythWrapperExecutor(executor);
|
||||
return pythExecutor.executeGovernanceInstruction({
|
||||
contractAddr: this.address,
|
||||
|
@ -321,6 +342,13 @@ export class CosmWasmContract extends Contract {
|
|||
});
|
||||
}
|
||||
|
||||
async getWormholeContract(): Promise<WormholeCosmWasmContract> {
|
||||
let config = await this.getConfig();
|
||||
const chainQuerier = await CosmwasmQuerier.connect(this.chain.endpoint);
|
||||
const wormholeAddress = config.config_v1.wormhole_contract;
|
||||
return new WormholeCosmWasmContract(this.chain, wormholeAddress);
|
||||
}
|
||||
|
||||
async getUpdateFee(msgs: string[]): Promise<any> {
|
||||
let querier = await this.getQuerier();
|
||||
return querier.getUpdateFee(this.address, msgs);
|
||||
|
@ -341,7 +369,7 @@ export class CosmWasmContract extends Contract {
|
|||
}
|
||||
|
||||
async getValidTimePeriod() {
|
||||
let client = await CosmWasmClient.connect(this.chain.querierEndpoint);
|
||||
let client = await CosmWasmClient.connect(this.chain.endpoint);
|
||||
let result = await client.queryContractSmart(
|
||||
this.address,
|
||||
"get_valid_time_period"
|
||||
|
|
|
@ -3,6 +3,7 @@ import PythInterfaceAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
|
|||
import { Contract } from "../base";
|
||||
import { Chain, EvmChain } from "../chains";
|
||||
import { DataSource } from "xc_admin_common";
|
||||
import { WormholeContract } from "./wormhole";
|
||||
|
||||
// Just to make sure tx gas limit is enough
|
||||
const GAS_ESTIMATE_MULTIPLIER = 2;
|
||||
|
@ -184,27 +185,94 @@ const WORMHOLE_ABI = [
|
|||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: "bytes",
|
||||
name: "_vm",
|
||||
type: "bytes",
|
||||
},
|
||||
],
|
||||
name: "submitNewGuardianSet",
|
||||
outputs: [],
|
||||
stateMutability: "nonpayable",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: "messageFee",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "uint256",
|
||||
name: "",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
] as any;
|
||||
export class WormholeEvmContract {
|
||||
constructor(public chain: EvmChain, public address: string) {}
|
||||
export class WormholeEvmContract extends WormholeContract {
|
||||
constructor(public chain: EvmChain, public address: string) {
|
||||
super();
|
||||
}
|
||||
getContract() {
|
||||
const web3 = new Web3(this.chain.getRpcUrl());
|
||||
return new web3.eth.Contract(WORMHOLE_ABI, this.address);
|
||||
}
|
||||
|
||||
async getCurrentGuardianSetIndex(): Promise<number> {
|
||||
const wormholeContract = this.getContract();
|
||||
return Number(
|
||||
await wormholeContract.methods.getCurrentGuardianSetIndex().call()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of guardian addresses used for VAA verification in this contract
|
||||
*/
|
||||
async getGuardianSet(): Promise<string[]> {
|
||||
const wormholeContract = this.getContract();
|
||||
const currentIndex = await wormholeContract.methods
|
||||
.getCurrentGuardianSetIndex()
|
||||
.call();
|
||||
const currentIndex = await this.getCurrentGuardianSetIndex();
|
||||
const [currentSet] = await wormholeContract.methods
|
||||
.getGuardianSet(currentIndex)
|
||||
.call();
|
||||
return currentSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this contract is a deployment of wormhole-receiver or wormhole.
|
||||
* The wormhole-receiver is a subset of the wormhole contract optimized for just verifying the VAAs.
|
||||
* The check is done by calling a function that only exists in the wormhole contract and not in the wormhole-receiver.
|
||||
* If the function call fails, we know that this is a wormhole-receiver contract.
|
||||
*/
|
||||
async isWormholeReceiver(): Promise<boolean> {
|
||||
const wormholeContract = this.getContract();
|
||||
try {
|
||||
await wormholeContract.methods.messageFee().call();
|
||||
return false;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async upgradeGuardianSets(senderPrivateKey: string, 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);
|
||||
const transactionObject = wormholeContract.methods.submitNewGuardianSet(
|
||||
"0x" + vaa.toString("hex")
|
||||
);
|
||||
const gasEstiamte = await transactionObject.estimateGas({
|
||||
from: address,
|
||||
gas: 100000000,
|
||||
});
|
||||
return transactionObject.send({
|
||||
from: address,
|
||||
gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
|
||||
gasPrice: await this.chain.getGasPrice(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class EvmContract extends Contract {
|
||||
|
@ -283,6 +351,16 @@ export class EvmContract extends Contract {
|
|||
return web3.eth.getCode(this.address);
|
||||
}
|
||||
|
||||
async getImplementationAddress(): Promise<string> {
|
||||
const web3 = new Web3(this.chain.getRpcUrl());
|
||||
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) according to EIP-1967
|
||||
let storagePosition =
|
||||
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
||||
let address = await web3.eth.getStorageAt(this.address, storagePosition);
|
||||
address = "0x" + address.slice(26);
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keccak256 digest of the contract bytecode after replacing any occurrences of the contract addr in
|
||||
* the bytecode with 0.The bytecode stores the deployment address as an immutable variable.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export * from "./aptos";
|
||||
export * from "./cosmwasm";
|
||||
export * from "./evm";
|
||||
export * from "./sui";
|
||||
export * from "./wormhole";
|
|
@ -195,6 +195,10 @@ export class SuiContract extends Contract {
|
|||
return this.executeTransaction(tx, keypair);
|
||||
}
|
||||
|
||||
async executeUpdatePriceFeed(senderPrivateKey: string, vaas: Buffer[]) {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
|
||||
async executeGovernanceInstruction(senderPrivateKey: string, vaa: Buffer) {
|
||||
const keypair = Ed25519Keypair.fromSecretKey(
|
||||
Buffer.from(senderPrivateKey, "hex")
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
export abstract class WormholeContract {
|
||||
abstract getCurrentGuardianSetIndex(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of guardian addresses used for VAA verification in this contract
|
||||
*/
|
||||
abstract getGuardianSet(): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Upgrades the guardian set of this contract using an upgrade VAA
|
||||
* @param senderPrivateKey
|
||||
* @param vaa
|
||||
*/
|
||||
abstract upgradeGuardianSets(
|
||||
senderPrivateKey: string,
|
||||
vaa: Buffer
|
||||
): Promise<any>;
|
||||
|
||||
/**
|
||||
* Upgrades the guardian set of this contract with the 3 pre-configured VAAs for mainnet assuming this is a mainnet contract
|
||||
* @param senderPrivateKey
|
||||
*/
|
||||
async syncMainnetGuardianSets(senderPrivateKey: string) {
|
||||
const MAINNET_UPGRADE_VAAS = [
|
||||
"010000000001007ac31b282c2aeeeb37f3385ee0de5f8e421d30b9e5ae8ba3d4375c1c77a86e77159bb697d9c456d6f8c02d22a94b1279b65b0d6a9957e7d3857423845ac758e300610ac1d2000000030001000000000000000000000000000000000000000000000000000000000000000400000000000005390000000000000000000000000000000000000000000000000000000000436f7265020000000000011358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cdeb5f7389fa26941519f0863349c223b73a6ddee774a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d",
|
||||
"01000000010d0012e6b39c6da90c5dfd3c228edbb78c7a4c97c488ff8a346d161a91db067e51d638c17216f368aa9bdf4836b8645a98018ca67d2fec87d769cabfdf2406bf790a0002ef42b288091a670ef3556596f4f47323717882881eaf38e03345078d07a156f312b785b64dae6e9a87e3d32872f59cb1931f728cecf511762981baf48303668f0103cef2616b84c4e511ff03329e0853f1bd7ee9ac5ba71d70a4d76108bddf94f69c2a8a84e4ee94065e8003c334e899184943634e12043d0dda78d93996da073d190104e76d166b9dac98f602107cc4b44ac82868faf00b63df7d24f177aa391e050902413b71046434e67c770b19aecdf7fce1d1435ea0be7262e3e4c18f50ddc8175c0105d9450e8216d741e0206a50f93b750a47e0a258b80eb8fed1314cc300b3d905092de25cd36d366097b7103ae2d184121329ba3aa2d7c6cc53273f11af14798110010687477c8deec89d36a23e7948feb074df95362fc8dcbd8ae910ac556a1dee1e755c56b9db5d710c940938ed79bc1895a3646523a58bc55f475a23435a373ecfdd0107fb06734864f79def4e192497362513171530daea81f07fbb9f698afe7e66c6d44db21323144f2657d4a5386a954bb94eef9f64148c33aef6e477eafa2c5c984c01088769e82216310d1827d9bd48645ec23e90de4ef8a8de99e2d351d1df318608566248d80cdc83bdcac382b3c30c670352be87f9069aab5037d0b747208eae9c650109e9796497ff9106d0d1c62e184d83716282870cef61a1ee13d6fc485b521adcce255c96f7d1bca8d8e7e7d454b65783a830bddc9d94092091a268d311ecd84c26010c468c9fb6d41026841ff9f8d7368fa309d4dbea3ea4bbd2feccf94a92cc8a20a226338a8e2126cd16f70eaf15b4fc9be2c3fa19def14e071956a605e9d1ac4162010e23fcb6bd445b7c25afb722250c1acbc061ed964ba9de1326609ae012acdfb96942b2a102a2de99ab96327859a34a2b49a767dbdb62e0a1fb26af60fe44fd496a00106bb0bac77ac68b347645f2fb1ad789ea9bd76fb9b2324f25ae06f97e65246f142df717f662e73948317182c62ce87d79c73def0dba12e5242dfc038382812cfe00126da03c5e56cb15aeeceadc1e17a45753ab4dc0ec7bf6a75ca03143ed4a294f6f61bc3f478a457833e43084ecd7c985bf2f55a55f168aac0e030fc49e845e497101626e9d9a5d9e343f00010000000000000000000000000000000000000000000000000000000000000004c1759167c43f501c2000000000000000000000000000000000000000000000000000000000436f7265020000000000021358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cd66b9590e1c41e0b226937bf9217d1d67fd4e91f574a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d",
|
||||
"01000000020d00ce45474d9e1b1e7790a2d210871e195db53a70ffd6f237cfe70e2686a32859ac43c84a332267a8ef66f59719cf91cc8df0101fd7c36aa1878d5139241660edc0010375cc906156ae530786661c0cd9aef444747bc3d8d5aa84cac6a6d2933d4e1a031cffa30383d4af8131e929d9f203f460b07309a647d6cd32ab1cc7724089392c000452305156cfc90343128f97e499311b5cae174f488ff22fbc09591991a0a73d8e6af3afb8a5968441d3ab8437836407481739e9850ad5c95e6acfcc871e951bc30105a7956eefc23e7c945a1966d5ddbe9e4be376c2f54e45e3d5da88c2f8692510c7429b1ea860ae94d929bd97e84923a18187e777aa3db419813a80deb84cc8d22b00061b2a4f3d2666608e0aa96737689e3ba5793810ff3a52ff28ad57d8efb20967735dc5537a2e43ef10f583d144c12a1606542c207f5b79af08c38656d3ac40713301086b62c8e130af3411b3c0d91b5b50dcb01ed5f293963f901fc36e7b0e50114dce203373b32eb45971cef8288e5d928d0ed51cd86e2a3006b0af6a65c396c009080009e93ab4d2c8228901a5f4525934000b2c26d1dc679a05e47fdf0ff3231d98fbc207103159ff4116df2832eea69b38275283434e6cd4a4af04d25fa7a82990b707010aa643f4cf615dfff06ffd65830f7f6cf6512dabc3690d5d9e210fdc712842dc2708b8b2c22e224c99280cd25e5e8bfb40e3d1c55b8c41774e287c1e2c352aecfc010b89c1e85faa20a30601964ccc6a79c0ae53cfd26fb10863db37783428cd91390a163346558239db3cd9d420cfe423a0df84c84399790e2e308011b4b63e6b8015010ca31dcb564ac81a053a268d8090e72097f94f366711d0c5d13815af1ec7d47e662e2d1bde22678113d15963da100b668ba26c0c325970d07114b83c5698f46097010dc9fda39c0d592d9ed92cd22b5425cc6b37430e236f02d0d1f8a2ef45a00bde26223c0a6eb363c8b25fd3bf57234a1d9364976cefb8360e755a267cbbb674b39501108db01e444ab1003dd8b6c96f8eb77958b40ba7a85fefecf32ad00b7a47c0ae7524216262495977e09c0989dd50f280c21453d3756843608eacd17f4fdfe47600001261025228ef5af837cb060bcd986fcfa84ccef75b3fa100468cfd24e7fadf99163938f3b841a33496c2706d0208faab088bd155b2e20fd74c625bb1cc8c43677a0163c53c409e0c5dfa000100000000000000000000000000000000000000000000000000000000000000046c5a054d7833d1e42000000000000000000000000000000000000000000000000000000000436f7265020000000000031358cc3ae5c097b213ce3c81979e1b9f9570746aa5ff6cb952589bde862c25ef4392132fb9d4a42157114de8460193bdf3a2fcf81f86a09765f4762fd1107a0086b32d7a0977926a205131d8731d39cbeb8c82b2fd82faed2711d59af0f2499d16e726f6b211b39756c042441be6d8650b69b54ebe715e234354ce5b4d348fb74b958e8966e2ec3dbd4958a7cd15e7caf07c4e3dc8e7c469f92c8cd88fb8005a2074a3bf913953d695260d88bc1aa25a4eee363ef0000ac0076727b35fbea2dac28fee5ccb0fea768eaf45ced136b9d9e24903464ae889f5c8a723fc14f93124b7c738843cbb89e864c862c38cddcccf95d2cc37a4dc036a8d232b48f62cdd4731412f4890da798f6896a3331f64b48c12d1d57fd9cbe7081171aa1be1d36cafe3867910f99c09e347899c19c38192b6e7387ccd768277c17dab1b7a5027c0b3cf178e21ad2e77ae06711549cfbb1f9c7a9d8096e85e1487f35515d02a92753504a8d75471b9f49edb6fbebc898f403e4773e95feb15e80c9a99c8348d",
|
||||
];
|
||||
const currentIndex = await this.getCurrentGuardianSetIndex();
|
||||
for (let i = currentIndex; i < MAINNET_UPGRADE_VAAS.length; i++) {
|
||||
const vaa = MAINNET_UPGRADE_VAAS[i];
|
||||
await this.upgradeGuardianSets(senderPrivateKey, Buffer.from(vaa, "hex"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { parseVaa } from "@certusone/wormhole-sdk";
|
||||
import { decodeGovernancePayload } from "xc_admin_common";
|
||||
import { DefaultStore } from "./store";
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
const parsedVaa = parseVaa(vaa);
|
||||
const action = decodeGovernancePayload(parsedVaa.payload);
|
||||
if (!action) return; //TODO: handle other actions
|
||||
for (const contract of Object.values(DefaultStore.contracts)) {
|
||||
if (
|
||||
action.targetChainId === "unset" ||
|
||||
contract.getChain().wormholeChainName === action.targetChainId
|
||||
) {
|
||||
const governanceSource = await contract.getGovernanceDataSource();
|
||||
if (
|
||||
governanceSource.emitterAddress ===
|
||||
parsedVaa.emitterAddress.toString("hex") &&
|
||||
governanceSource.emitterChain === parsedVaa.emitterChain
|
||||
) {
|
||||
// TODO: check governance sequence number as well
|
||||
await contract.executeGovernanceInstruction(senderPrivateKey, vaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@ import SquadsMesh from "@sqds/mesh";
|
|||
import { AnchorProvider, Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
|
||||
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
|
||||
import {
|
||||
decodeGovernancePayload,
|
||||
executeProposal,
|
||||
MultisigVault,
|
||||
WORMHOLE_ADDRESS,
|
||||
|
@ -33,8 +32,6 @@ import {
|
|||
deriveWormholeBridgeDataKey,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
|
||||
import { Storable } from "./base";
|
||||
import { parseVaa } from "@certusone/wormhole-sdk";
|
||||
import { DefaultStore } from "./store";
|
||||
|
||||
class InvalidTransactionError extends Error {
|
||||
constructor(message: string) {
|
||||
|
@ -127,33 +124,6 @@ export class SubmittedWormholeMessage {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
const parsedVaa = parseVaa(vaa);
|
||||
const action = decodeGovernancePayload(parsedVaa.payload);
|
||||
if (!action) return; //TODO: handle other actions
|
||||
for (const contract of Object.values(DefaultStore.contracts)) {
|
||||
if (
|
||||
action.targetChainId === "unset" ||
|
||||
contract.getChain().wormholeChainName === action.targetChainId
|
||||
) {
|
||||
const governanceSource = await contract.getGovernanceDataSource();
|
||||
if (
|
||||
governanceSource.emitterAddress ===
|
||||
parsedVaa.emitterAddress.toString("hex") &&
|
||||
governanceSource.emitterChain === parsedVaa.emitterChain
|
||||
) {
|
||||
// TODO: check governance sequence number as well
|
||||
await contract.executeGovernanceInstruction(senderPrivateKey, vaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function asPythCluster(cluster: string): PythCluster {
|
||||
const pythCluster = cluster as PythCluster;
|
||||
getPythClusterApiUrl(pythCluster); // throws if cluster is invalid
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export * from "./governance";
|
||||
export * from "./chains";
|
||||
export * from "./store";
|
||||
export * from "./base";
|
||||
export * from "./contracts";
|
|
@ -6,23 +6,18 @@ import {
|
|||
GlobalChain,
|
||||
SuiChain,
|
||||
} from "./chains";
|
||||
import { CosmWasmContract } from "./contracts/cosmwasm";
|
||||
import { SuiContract } from "./contracts/sui";
|
||||
import {
|
||||
AptosContract,
|
||||
CosmWasmContract,
|
||||
EvmContract,
|
||||
SuiContract,
|
||||
} from "./contracts";
|
||||
import { Contract } from "./base";
|
||||
import { parse, stringify } from "yaml";
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
readdirSync,
|
||||
readFileSync,
|
||||
statSync,
|
||||
writeFileSync,
|
||||
} from "fs";
|
||||
import { EvmContract } from "./contracts/evm";
|
||||
import { AptosContract } from "./contracts/aptos";
|
||||
import { readdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
||||
import { Vault } from "./governance";
|
||||
|
||||
class Store {
|
||||
export class Store {
|
||||
public chains: Record<string, Chain> = { global: new GlobalChain() };
|
||||
public contracts: Record<string, Contract> = {};
|
||||
public vaults: Record<string, Vault> = {};
|
||||
|
@ -33,30 +28,8 @@ class Store {
|
|||
this.loadAllVaults();
|
||||
}
|
||||
|
||||
save(obj: any) {
|
||||
let dir, file, content;
|
||||
if (obj instanceof Contract) {
|
||||
let contract = obj;
|
||||
dir = `${this.path}/contracts/${contract.getType()}`;
|
||||
file = contract.getId();
|
||||
content = contract.toJson();
|
||||
} else if (obj instanceof Chain) {
|
||||
let chain = obj;
|
||||
dir = `${this.path}/chains/${chain.getType()}`;
|
||||
file = chain.getId();
|
||||
content = chain.toJson();
|
||||
} else if (obj instanceof Vault) {
|
||||
let vault = obj;
|
||||
dir = `${this.path}/vaults`;
|
||||
file = vault.getId();
|
||||
content = vault.toJson();
|
||||
} else {
|
||||
throw new Error("Invalid type");
|
||||
}
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
writeFileSync(`${dir}/${file}.yaml`, stringify(content));
|
||||
static serialize(obj: Contract | Chain | Vault) {
|
||||
return stringify([obj.toJson()]);
|
||||
}
|
||||
|
||||
getYamlFiles(path: string) {
|
||||
|
@ -88,15 +61,49 @@ class Store {
|
|||
};
|
||||
|
||||
this.getYamlFiles(`${this.path}/chains/`).forEach((yamlFile) => {
|
||||
let parsed = parse(readFileSync(yamlFile, "utf-8"));
|
||||
if (allChainClasses[parsed.type] === undefined) return;
|
||||
let 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;
|
||||
let parsedArray = parse(readFileSync(yamlFile, "utf-8"));
|
||||
for (const parsed of parsedArray) {
|
||||
if (allChainClasses[parsed.type] === undefined) return;
|
||||
let 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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
saveAllContracts() {
|
||||
let contractsByType: Record<string, Contract[]> = {};
|
||||
for (const contract of Object.values(this.contracts)) {
|
||||
if (!contractsByType[contract.getType()]) {
|
||||
contractsByType[contract.getType()] = [];
|
||||
}
|
||||
contractsByType[contract.getType()].push(contract);
|
||||
}
|
||||
for (const [type, contracts] of Object.entries(contractsByType)) {
|
||||
writeFileSync(
|
||||
`${this.path}/contracts/${type}s.yaml`,
|
||||
stringify(contracts.map((c) => c.toJson()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
saveAllChains() {
|
||||
let chainsByType: Record<string, Chain[]> = {};
|
||||
for (const chain of Object.values(this.chains)) {
|
||||
if (!chainsByType[chain.getType()]) {
|
||||
chainsByType[chain.getType()] = [];
|
||||
}
|
||||
chainsByType[chain.getType()].push(chain);
|
||||
}
|
||||
for (const [type, chains] of Object.entries(chainsByType)) {
|
||||
writeFileSync(
|
||||
`${this.path}/chains/${type}s.yaml`,
|
||||
stringify(chains.map((c) => c.toJson()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
loadAllContracts() {
|
||||
let allContractClasses = {
|
||||
[CosmWasmContract.type]: CosmWasmContract,
|
||||
|
@ -105,32 +112,36 @@ class Store {
|
|||
[AptosContract.type]: AptosContract,
|
||||
};
|
||||
this.getYamlFiles(`${this.path}/contracts/`).forEach((yamlFile) => {
|
||||
let parsed = parse(readFileSync(yamlFile, "utf-8"));
|
||||
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(
|
||||
chain,
|
||||
parsed
|
||||
);
|
||||
if (this.contracts[chainContract.getId()])
|
||||
throw new Error(
|
||||
`Multiple contracts with id ${chainContract.getId()} found`
|
||||
let 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(
|
||||
chain,
|
||||
parsed
|
||||
);
|
||||
this.contracts[chainContract.getId()] = chainContract;
|
||||
if (this.contracts[chainContract.getId()])
|
||||
throw new Error(
|
||||
`Multiple contracts with id ${chainContract.getId()} found`
|
||||
);
|
||||
this.contracts[chainContract.getId()] = chainContract;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadAllVaults() {
|
||||
this.getYamlFiles(`${this.path}/vaults/`).forEach((yamlFile) => {
|
||||
let parsed = parse(readFileSync(yamlFile, "utf-8"));
|
||||
if (parsed.type !== Vault.type) return;
|
||||
let parsedArray = parse(readFileSync(yamlFile, "utf-8"));
|
||||
for (const parsed of parsedArray) {
|
||||
if (parsed.type !== Vault.type) return;
|
||||
|
||||
const vault = Vault.fromJson(parsed);
|
||||
if (this.vaults[vault.getId()])
|
||||
throw new Error(`Multiple vaults with id ${vault.getId()} found`);
|
||||
this.vaults[vault.getId()] = vault;
|
||||
const vault = Vault.fromJson(parsed);
|
||||
if (this.vaults[vault.getId()])
|
||||
throw new Error(`Multiple vaults with id ${vault.getId()} found`);
|
||||
this.vaults[vault.getId()] = vault;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { DefaultStore } from "./store";
|
||||
|
||||
async function test() {
|
||||
for (const contract of Object.values(DefaultStore.contracts)) {
|
||||
console.log("Contract", contract.getId());
|
||||
console.log(await contract.getGovernanceDataSource());
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
|
@ -1,5 +0,0 @@
|
|||
id: aptos_mainnet
|
||||
wormholeChainName: aptos
|
||||
mainnet: true
|
||||
rpcUrl: https://fullnode.mainnet.aptoslabs.com/v1
|
||||
type: AptosChain
|
|
@ -1,5 +0,0 @@
|
|||
id: aptos_testnet
|
||||
wormholeChainName: aptos
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.testnet.aptoslabs.com/v1
|
||||
type: AptosChain
|
|
@ -0,0 +1,10 @@
|
|||
- id: aptos_testnet
|
||||
wormholeChainName: aptos
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.testnet.aptoslabs.com/v1
|
||||
type: AptosChain
|
||||
- id: aptos_mainnet
|
||||
wormholeChainName: aptos
|
||||
mainnet: true
|
||||
rpcUrl: https://fullnode.mainnet.aptoslabs.com/v1
|
||||
type: AptosChain
|
|
@ -1,5 +0,0 @@
|
|||
querierEndpoint: https://injective-rpc.quickapi.com:443
|
||||
id: injective
|
||||
wormholeChainName: injective
|
||||
mainnet: true
|
||||
type: CosmWasmChain
|
|
@ -1,5 +0,0 @@
|
|||
querierEndpoint: https://k8s.testnet.tm.injective.network:443
|
||||
id: injective_testnet
|
||||
wormholeChainName: injective_testnet
|
||||
mainnet: false
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc.uni.junonetwork.io/
|
||||
executorEndpoint: https://rpc.uni.junonetwork.io/
|
||||
id: juno_testnet
|
||||
wormholeChainName: juno_testnet
|
||||
mainnet: false
|
||||
gasPrice: "0.025"
|
||||
prefix: juno
|
||||
feeDenom: ujunox
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc-kralum.neutron-1.neutron.org
|
||||
executorEndpoint: https://rpc-kralum.neutron-1.neutron.org
|
||||
id: neutron
|
||||
wormholeChainName: neutron
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: neutron
|
||||
feeDenom: untrn
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc-palvus.pion-1.ntrn.tech/
|
||||
executorEndpoint: https://rpc-palvus.pion-1.ntrn.tech/
|
||||
id: neutron_testnet_pion_1
|
||||
wormholeChainName: neutron_testnet_pion_1
|
||||
mainnet: false
|
||||
gasPrice: "0.05"
|
||||
prefix: neutron
|
||||
feeDenom: untrn
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc.osmosis.zone:443
|
||||
executorEndpoint: https://rpc.osmosis.zone:443
|
||||
id: osmosis
|
||||
wormholeChainName: osmosis
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: osmo
|
||||
feeDenom: uosmo
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc.osmotest5.osmosis.zone/
|
||||
executorEndpoint: https://rpc.osmotest5.osmosis.zone/
|
||||
id: osmosis_testnet_5
|
||||
wormholeChainName: osmosis_testnet_5
|
||||
mainnet: false
|
||||
gasPrice: "0.025"
|
||||
prefix: osmo
|
||||
feeDenom: uosmo
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://sei-rpc.polkachu.com
|
||||
executorEndpoint: https://sei-rpc.polkachu.com
|
||||
id: sei_pacific_1
|
||||
wormholeChainName: sei_pacific_1
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: sei
|
||||
feeDenom: usei
|
||||
type: CosmWasmChain
|
|
@ -1,9 +0,0 @@
|
|||
querierEndpoint: https://rpc.atlantic-2.seinetwork.io/
|
||||
executorEndpoint: https://rpc.atlantic-2.seinetwork.io/
|
||||
id: sei_testnet_atlantic_2
|
||||
wormholeChainName: sei_testnet_atlantic_2
|
||||
mainnet: false
|
||||
gasPrice: "0.10"
|
||||
prefix: sei
|
||||
feeDenom: usei
|
||||
type: CosmWasmChain
|
|
@ -0,0 +1,66 @@
|
|||
- endpoint: https://injective-rpc.quickapi.com:443
|
||||
id: injective
|
||||
wormholeChainName: injective
|
||||
mainnet: true
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc.atlantic-2.seinetwork.io/
|
||||
id: sei_testnet_atlantic_2
|
||||
wormholeChainName: sei_testnet_atlantic_2
|
||||
mainnet: false
|
||||
gasPrice: "0.10"
|
||||
prefix: sei
|
||||
feeDenom: usei
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc.osmosis.zone:443
|
||||
id: osmosis
|
||||
wormholeChainName: osmosis
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: osmo
|
||||
feeDenom: uosmo
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://k8s.testnet.tm.injective.network:443
|
||||
id: injective_testnet
|
||||
wormholeChainName: injective_testnet
|
||||
mainnet: false
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc-palvus.pion-1.ntrn.tech/
|
||||
id: neutron_testnet_pion_1
|
||||
wormholeChainName: neutron_testnet_pion_1
|
||||
mainnet: false
|
||||
gasPrice: "0.05"
|
||||
prefix: neutron
|
||||
feeDenom: untrn
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc.osmotest5.osmosis.zone/
|
||||
id: osmosis_testnet_5
|
||||
wormholeChainName: osmosis_testnet_5
|
||||
mainnet: false
|
||||
gasPrice: "0.025"
|
||||
prefix: osmo
|
||||
feeDenom: uosmo
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://sei-rpc.polkachu.com
|
||||
id: sei_pacific_1
|
||||
wormholeChainName: sei_pacific_1
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: sei
|
||||
feeDenom: usei
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc-kralum.neutron-1.neutron.org
|
||||
id: neutron
|
||||
wormholeChainName: neutron
|
||||
mainnet: true
|
||||
gasPrice: "0.025"
|
||||
prefix: neutron
|
||||
feeDenom: untrn
|
||||
type: CosmWasmChain
|
||||
- endpoint: https://rpc.uni.junonetwork.io/
|
||||
id: juno_testnet
|
||||
wormholeChainName: juno_testnet
|
||||
mainnet: false
|
||||
gasPrice: "0.025"
|
||||
prefix: juno
|
||||
feeDenom: ujunox
|
||||
type: CosmWasmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: arbitrum
|
||||
wormholeChainName: arbitrum
|
||||
mainnet: true
|
||||
rpcUrl: https://arb1.arbitrum.io/rpc
|
||||
networkId: 42161
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: arbitrum_testnet
|
||||
wormholeChainName: arbitrum
|
||||
mainnet: false
|
||||
rpcUrl: https://goerli-rollup.arbitrum.io/rpc
|
||||
networkId: 421613
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: aurora
|
||||
wormholeChainName: aurora
|
||||
mainnet: true
|
||||
rpcUrl: https://mainnet.aurora.dev
|
||||
networkId: 1313161554
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: aurora_testnet
|
||||
wormholeChainName: aurora
|
||||
mainnet: false
|
||||
rpcUrl: https://testnet.aurora.dev
|
||||
networkId: 1313161555
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: avalanche
|
||||
wormholeChainName: avalanche
|
||||
mainnet: true
|
||||
rpcUrl: https://api.avax.network/ext/bc/C/rpc
|
||||
networkId: 43114
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: base
|
||||
wormholeChainName: base
|
||||
mainnet: true
|
||||
rpcUrl: https://developer-access-mainnet.base.org/
|
||||
networkId: 8453
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: base_goerli
|
||||
wormholeChainName: base
|
||||
mainnet: false
|
||||
rpcUrl: https://goerli.base.org
|
||||
networkId: 84531
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: bnb
|
||||
wormholeChainName: bsc
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/bsc
|
||||
networkId: 56
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: bnb_testnet
|
||||
wormholeChainName: bsc
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/bsc_testnet_chapel
|
||||
networkId: 97
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: canto
|
||||
wormholeChainName: canto
|
||||
mainnet: true
|
||||
rpcUrl: https://canto.gravitychain.io
|
||||
networkId: 7700
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: canto_testnet
|
||||
wormholeChainName: canto
|
||||
mainnet: false
|
||||
rpcUrl: https://canto-testnet.plexnode.wtf
|
||||
networkId: 7701
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: celo
|
||||
wormholeChainName: celo
|
||||
mainnet: true
|
||||
rpcUrl: https://forno.celo.org
|
||||
networkId: 42220
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: celo_alfajores_testnet
|
||||
wormholeChainName: celo
|
||||
mainnet: false
|
||||
rpcUrl: https://alfajores-forno.celo-testnet.org
|
||||
networkId: 44787
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: chiado
|
||||
wormholeChainName: gnosis
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.chiadochain.net
|
||||
networkId: 10200
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: conflux_espace
|
||||
wormholeChainName: conflux_espace
|
||||
mainnet: true
|
||||
rpcUrl: https://evm.confluxrpc.org
|
||||
networkId: 1030
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: conflux_espace_testnet
|
||||
wormholeChainName: conflux_espace
|
||||
mainnet: false
|
||||
rpcUrl: https://evmtestnet.confluxrpc.com
|
||||
networkId: 71
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: cronos
|
||||
wormholeChainName: cronos
|
||||
mainnet: true
|
||||
rpcUrl: https://cronosrpc-1.xstaking.sg
|
||||
networkId: 25
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: cronos_testnet
|
||||
wormholeChainName: cronos
|
||||
mainnet: false
|
||||
rpcUrl: https://evm-t3.cronos.org
|
||||
networkId: 338
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: eos
|
||||
wormholeChainName: eos
|
||||
mainnet: true
|
||||
rpcUrl: https://api.evm.eosnetwork.com
|
||||
networkId: 17777
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: eos_testnet
|
||||
wormholeChainName: eos
|
||||
mainnet: false
|
||||
rpcUrl: https://api.testnet.evm.eosnetwork.com
|
||||
networkId: 15557
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: ethereum
|
||||
wormholeChainName: ethereum
|
||||
mainnet: true
|
||||
rpcUrl: https://eth.llamarpc.com
|
||||
networkId: 1
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: evmos
|
||||
wormholeChainName: evmos
|
||||
mainnet: true
|
||||
rpcUrl: https://eth.bd.evmos.org:8545/
|
||||
networkId: 9001
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: evmos_testnet
|
||||
wormholeChainName: evmos
|
||||
mainnet: false
|
||||
rpcUrl: https://eth.bd.evmos.dev:8545/
|
||||
networkId: 9000
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: fantom
|
||||
wormholeChainName: fantom
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/fantom
|
||||
networkId: 250
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: fantom_testnet
|
||||
wormholeChainName: fantom
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/fantom_testnet
|
||||
networkId: 4002
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: fuji
|
||||
wormholeChainName: avalanche
|
||||
mainnet: false
|
||||
rpcUrl: https://api.avax-test.network/ext/bc/C/rpc
|
||||
networkId: 43113
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: gnosis
|
||||
wormholeChainName: gnosis
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.gnosischain.com
|
||||
networkId: 100
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: goerli
|
||||
wormholeChainName: ethereum
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.goerli.eth.gateway.fm
|
||||
networkId: 5
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: kava
|
||||
wormholeChainName: kava
|
||||
mainnet: true
|
||||
rpcUrl: https://evm.kava.io
|
||||
networkId: 2222
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: kava_testnet
|
||||
wormholeChainName: kava
|
||||
mainnet: false
|
||||
rpcUrl: https://evm.testnet.kava.io
|
||||
networkId: 2221
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: kcc
|
||||
wormholeChainName: kcc
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc-mainnet.kcc.network
|
||||
networkId: 321
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: kcc_testnet
|
||||
wormholeChainName: kcc
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc-testnet.kcc.network
|
||||
networkId: 322
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: linea
|
||||
wormholeChainName: linea
|
||||
mainnet: true
|
||||
rpcUrl: https://linea.rpc.thirdweb.com
|
||||
networkId: 59144
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: linea_goerli
|
||||
wormholeChainName: linea
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.goerli.linea.build
|
||||
networkId: 59140
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: mantle
|
||||
wormholeChainName: mantle
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.mantle.xyz/
|
||||
networkId: 5000
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: mantle_testnet
|
||||
wormholeChainName: mantle
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.testnet.mantle.xyz/
|
||||
networkId: 5001
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: meter
|
||||
wormholeChainName: meter
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc-meter.jellypool.xyz
|
||||
networkId: 82
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: meter_testnet
|
||||
wormholeChainName: meter
|
||||
mainnet: false
|
||||
rpcUrl: https://rpctest.meter.io
|
||||
networkId: 83
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: mumbai
|
||||
wormholeChainName: polygon
|
||||
mainnet: false
|
||||
rpcUrl: https://polygon-testnet-rpc.allthatnode.com:8545
|
||||
networkId: 80001
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: neon
|
||||
wormholeChainName: neon
|
||||
mainnet: true
|
||||
rpcUrl: https://neon-proxy-mainnet.solana.p2p.org
|
||||
networkId: 245022934
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: neon_devnet
|
||||
wormholeChainName: neon
|
||||
mainnet: false
|
||||
rpcUrl: https://devnet.neonevm.org
|
||||
networkId: 245022926
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: optimism
|
||||
wormholeChainName: optimism
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/optimism
|
||||
networkId: 10
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: optimism_goerli
|
||||
wormholeChainName: optimism
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/optimism_testnet
|
||||
networkId: 420
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: polygon
|
||||
wormholeChainName: polygon
|
||||
mainnet: true
|
||||
rpcUrl: https://polygon-rpc.com
|
||||
networkId: 137
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: polygon_zkevm
|
||||
wormholeChainName: polygon_zkevm
|
||||
mainnet: true
|
||||
rpcUrl: https://zkevm-rpc.com
|
||||
networkId: 1101
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: polygon_zkevm_testnet
|
||||
wormholeChainName: polygon_zkevm
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.public.zkevm-test.net/
|
||||
networkId: 1442
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: shimmer_testnet
|
||||
wormholeChainName: shimmer
|
||||
mainnet: false
|
||||
rpcUrl: https://json-rpc.evm.testnet.shimmer.network
|
||||
networkId: 1072
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: syndr_nitro_testnet
|
||||
wormholeChainName: syndr
|
||||
mainnet: false
|
||||
rpcUrl: https://syndr-nitro-testnet.calderachain.xyz/http
|
||||
networkId: 412346
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: wemix
|
||||
wormholeChainName: wemix
|
||||
mainnet: true
|
||||
rpcUrl: https://api.wemix.com
|
||||
networkId: 1111
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: wemix_testnet
|
||||
wormholeChainName: wemix
|
||||
mainnet: false
|
||||
rpcUrl: https://api.test.wemix.com
|
||||
networkId: 1112
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: zksync
|
||||
wormholeChainName: zksync
|
||||
mainnet: true
|
||||
rpcUrl: https://zksync2-mainnet.zksync.io
|
||||
networkId: 324
|
||||
type: EvmChain
|
|
@ -1,6 +0,0 @@
|
|||
id: zksync_goerli
|
||||
wormholeChainName: zksync
|
||||
mainnet: false
|
||||
rpcUrl: https://zksync2-testnet.zksync.dev
|
||||
networkId: 280
|
||||
type: EvmChain
|
|
@ -0,0 +1,312 @@
|
|||
- id: linea_goerli
|
||||
wormholeChainName: linea
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.goerli.linea.build
|
||||
networkId: 59140
|
||||
type: EvmChain
|
||||
- id: kava
|
||||
wormholeChainName: kava
|
||||
mainnet: true
|
||||
rpcUrl: https://evm.kava.io
|
||||
networkId: 2222
|
||||
type: EvmChain
|
||||
- id: evmos
|
||||
wormholeChainName: evmos
|
||||
mainnet: true
|
||||
rpcUrl: https://json-rpc.evmos.blockhunters.org
|
||||
networkId: 9001
|
||||
type: EvmChain
|
||||
- id: goerli
|
||||
wormholeChainName: ethereum
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.goerli.eth.gateway.fm
|
||||
networkId: 5
|
||||
type: EvmChain
|
||||
- id: canto
|
||||
wormholeChainName: canto
|
||||
mainnet: true
|
||||
rpcUrl: https://canto.gravitychain.io
|
||||
networkId: 7700
|
||||
type: EvmChain
|
||||
- id: fuji
|
||||
wormholeChainName: avalanche
|
||||
mainnet: false
|
||||
rpcUrl: https://api.avax-test.network/ext/bc/C/rpc
|
||||
networkId: 43113
|
||||
type: EvmChain
|
||||
- id: base_goerli
|
||||
wormholeChainName: base
|
||||
mainnet: false
|
||||
rpcUrl: https://goerli.base.org
|
||||
networkId: 84531
|
||||
type: EvmChain
|
||||
- id: avalanche
|
||||
wormholeChainName: avalanche
|
||||
mainnet: true
|
||||
rpcUrl: https://api.avax.network/ext/bc/C/rpc
|
||||
networkId: 43114
|
||||
type: EvmChain
|
||||
- id: cronos_testnet
|
||||
wormholeChainName: cronos
|
||||
mainnet: false
|
||||
rpcUrl: https://evm-t3.cronos.org
|
||||
networkId: 338
|
||||
type: EvmChain
|
||||
- id: arbitrum_testnet
|
||||
wormholeChainName: arbitrum
|
||||
mainnet: false
|
||||
rpcUrl: https://goerli-rollup.arbitrum.io/rpc
|
||||
networkId: 421613
|
||||
type: EvmChain
|
||||
- id: zksync_goerli
|
||||
wormholeChainName: zksync
|
||||
mainnet: false
|
||||
rpcUrl: https://zksync2-testnet.zksync.dev
|
||||
networkId: 280
|
||||
type: EvmChain
|
||||
- id: canto_testnet
|
||||
wormholeChainName: canto
|
||||
mainnet: false
|
||||
rpcUrl: https://canto-testnet.plexnode.wtf
|
||||
networkId: 7701
|
||||
type: EvmChain
|
||||
- id: polygon_zkevm_testnet
|
||||
wormholeChainName: polygon_zkevm
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.public.zkevm-test.net/
|
||||
networkId: 1442
|
||||
type: EvmChain
|
||||
- id: aurora_testnet
|
||||
wormholeChainName: aurora
|
||||
mainnet: false
|
||||
rpcUrl: https://testnet.aurora.dev
|
||||
networkId: 1313161555
|
||||
type: EvmChain
|
||||
- id: mantle_testnet
|
||||
wormholeChainName: mantle
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.testnet.mantle.xyz/
|
||||
networkId: 5001
|
||||
type: EvmChain
|
||||
- id: gnosis
|
||||
wormholeChainName: gnosis
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.gnosischain.com
|
||||
networkId: 100
|
||||
type: EvmChain
|
||||
- id: fantom_testnet
|
||||
wormholeChainName: fantom
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/fantom_testnet
|
||||
networkId: 4002
|
||||
type: EvmChain
|
||||
- id: neon
|
||||
wormholeChainName: neon
|
||||
mainnet: true
|
||||
rpcUrl: https://neon-proxy-mainnet.solana.p2p.org
|
||||
networkId: 245022934
|
||||
type: EvmChain
|
||||
- id: fantom
|
||||
wormholeChainName: fantom
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/fantom
|
||||
networkId: 250
|
||||
type: EvmChain
|
||||
- id: mumbai
|
||||
wormholeChainName: polygon
|
||||
mainnet: false
|
||||
rpcUrl: https://polygon-testnet-rpc.allthatnode.com:8545
|
||||
networkId: 80001
|
||||
type: EvmChain
|
||||
- id: neon_devnet
|
||||
wormholeChainName: neon
|
||||
mainnet: false
|
||||
rpcUrl: https://devnet.neonevm.org
|
||||
networkId: 245022926
|
||||
type: EvmChain
|
||||
- id: meter
|
||||
wormholeChainName: meter
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc-meter.jellypool.xyz
|
||||
networkId: 82
|
||||
type: EvmChain
|
||||
- id: chiado
|
||||
wormholeChainName: gnosis
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.chiadochain.net
|
||||
networkId: 10200
|
||||
type: EvmChain
|
||||
- id: mantle
|
||||
wormholeChainName: mantle
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.mantle.xyz/
|
||||
networkId: 5000
|
||||
type: EvmChain
|
||||
- id: kava_testnet
|
||||
wormholeChainName: kava
|
||||
mainnet: false
|
||||
rpcUrl: https://evm.testnet.kava.io
|
||||
networkId: 2221
|
||||
type: EvmChain
|
||||
- id: evmos_testnet
|
||||
wormholeChainName: evmos
|
||||
mainnet: false
|
||||
rpcUrl: https://eth.bd.evmos.dev:8545/
|
||||
networkId: 9000
|
||||
type: EvmChain
|
||||
- id: cronos
|
||||
wormholeChainName: cronos
|
||||
mainnet: true
|
||||
rpcUrl: https://cronosrpc-1.xstaking.sg
|
||||
networkId: 25
|
||||
type: EvmChain
|
||||
- id: ethereum
|
||||
wormholeChainName: ethereum
|
||||
mainnet: true
|
||||
rpcUrl: https://eth.llamarpc.com
|
||||
networkId: 1
|
||||
type: EvmChain
|
||||
- id: bnb_testnet
|
||||
wormholeChainName: bsc
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/bsc_testnet_chapel
|
||||
networkId: 97
|
||||
type: EvmChain
|
||||
- id: wemix
|
||||
wormholeChainName: wemix
|
||||
mainnet: true
|
||||
rpcUrl: https://api.wemix.com
|
||||
networkId: 1111
|
||||
type: EvmChain
|
||||
- id: aurora
|
||||
wormholeChainName: aurora
|
||||
mainnet: true
|
||||
rpcUrl: https://mainnet.aurora.dev
|
||||
networkId: 1313161554
|
||||
type: EvmChain
|
||||
- id: bnb
|
||||
wormholeChainName: bsc
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/bsc
|
||||
networkId: 56
|
||||
type: EvmChain
|
||||
- id: eos
|
||||
wormholeChainName: eos
|
||||
mainnet: true
|
||||
rpcUrl: https://api.evm.eosnetwork.com
|
||||
networkId: 17777
|
||||
type: EvmChain
|
||||
- id: conflux_espace_testnet
|
||||
wormholeChainName: conflux_espace
|
||||
mainnet: false
|
||||
rpcUrl: https://evmtestnet.confluxrpc.com
|
||||
networkId: 71
|
||||
type: EvmChain
|
||||
- id: conflux_espace
|
||||
wormholeChainName: conflux_espace
|
||||
mainnet: true
|
||||
rpcUrl: https://evm.confluxrpc.org
|
||||
networkId: 1030
|
||||
type: EvmChain
|
||||
- id: optimism_goerli
|
||||
wormholeChainName: optimism
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc.ankr.com/optimism_testnet
|
||||
networkId: 420
|
||||
type: EvmChain
|
||||
- id: celo
|
||||
wormholeChainName: celo
|
||||
mainnet: true
|
||||
rpcUrl: https://forno.celo.org
|
||||
networkId: 42220
|
||||
type: EvmChain
|
||||
- id: polygon
|
||||
wormholeChainName: polygon
|
||||
mainnet: true
|
||||
rpcUrl: https://polygon-rpc.com
|
||||
networkId: 137
|
||||
type: EvmChain
|
||||
- id: wemix_testnet
|
||||
wormholeChainName: wemix
|
||||
mainnet: false
|
||||
rpcUrl: https://api.test.wemix.com
|
||||
networkId: 1112
|
||||
type: EvmChain
|
||||
- id: kcc
|
||||
wormholeChainName: kcc
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc-mainnet.kcc.network
|
||||
networkId: 321
|
||||
type: EvmChain
|
||||
- id: polygon_zkevm
|
||||
wormholeChainName: polygon_zkevm
|
||||
mainnet: true
|
||||
rpcUrl: https://zkevm-rpc.com
|
||||
networkId: 1101
|
||||
type: EvmChain
|
||||
- id: celo_alfajores_testnet
|
||||
wormholeChainName: celo
|
||||
mainnet: false
|
||||
rpcUrl: https://alfajores-forno.celo-testnet.org
|
||||
networkId: 44787
|
||||
type: EvmChain
|
||||
- id: syndr_nitro_testnet
|
||||
wormholeChainName: syndr
|
||||
mainnet: false
|
||||
rpcUrl: https://syndr-nitro-testnet.calderachain.xyz/http
|
||||
networkId: 412346
|
||||
type: EvmChain
|
||||
- id: zksync
|
||||
wormholeChainName: zksync
|
||||
mainnet: true
|
||||
rpcUrl: https://zksync2-mainnet.zksync.io
|
||||
networkId: 324
|
||||
type: EvmChain
|
||||
- id: base
|
||||
wormholeChainName: base
|
||||
mainnet: true
|
||||
rpcUrl: https://developer-access-mainnet.base.org/
|
||||
networkId: 8453
|
||||
type: EvmChain
|
||||
- id: arbitrum
|
||||
wormholeChainName: arbitrum
|
||||
mainnet: true
|
||||
rpcUrl: https://arb1.arbitrum.io/rpc
|
||||
networkId: 42161
|
||||
type: EvmChain
|
||||
- id: optimism
|
||||
wormholeChainName: optimism
|
||||
mainnet: true
|
||||
rpcUrl: https://rpc.ankr.com/optimism
|
||||
networkId: 10
|
||||
type: EvmChain
|
||||
- id: kcc_testnet
|
||||
wormholeChainName: kcc
|
||||
mainnet: false
|
||||
rpcUrl: https://rpc-testnet.kcc.network
|
||||
networkId: 322
|
||||
type: EvmChain
|
||||
- id: eos_testnet
|
||||
wormholeChainName: eos
|
||||
mainnet: false
|
||||
rpcUrl: https://api.testnet.evm.eosnetwork.com
|
||||
networkId: 15557
|
||||
type: EvmChain
|
||||
- id: meter_testnet
|
||||
wormholeChainName: meter
|
||||
mainnet: false
|
||||
rpcUrl: https://rpctest.meter.io
|
||||
networkId: 83
|
||||
type: EvmChain
|
||||
- id: linea
|
||||
wormholeChainName: linea
|
||||
mainnet: true
|
||||
rpcUrl: https://linea.rpc.thirdweb.com
|
||||
networkId: 59144
|
||||
type: EvmChain
|
||||
- id: shimmer_testnet
|
||||
wormholeChainName: shimmer
|
||||
mainnet: false
|
||||
rpcUrl: https://json-rpc.evm.testnet.shimmer.network
|
||||
networkId: 1072
|
||||
type: EvmChain
|
|
@ -1,5 +0,0 @@
|
|||
id: sui_devnet
|
||||
wormholeChainName: sui
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.devnet.sui.io:443
|
||||
type: SuiChain
|
|
@ -1,5 +0,0 @@
|
|||
id: sui_mainnet
|
||||
wormholeChainName: sui
|
||||
mainnet: true
|
||||
rpcUrl: https://fullnode.mainnet.sui.io:443
|
||||
type: SuiChain
|
|
@ -1,5 +0,0 @@
|
|||
id: sui_testnet
|
||||
wormholeChainName: sui
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.testnet.sui.io:443
|
||||
type: SuiChain
|
|
@ -0,0 +1,15 @@
|
|||
- id: sui_testnet
|
||||
wormholeChainName: sui
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.testnet.sui.io:443
|
||||
type: SuiChain
|
||||
- id: sui_devnet
|
||||
wormholeChainName: sui
|
||||
mainnet: false
|
||||
rpcUrl: https://fullnode.devnet.sui.io:443
|
||||
type: SuiChain
|
||||
- id: sui_mainnet
|
||||
wormholeChainName: sui
|
||||
mainnet: true
|
||||
rpcUrl: https://fullnode.mainnet.sui.io:443
|
||||
type: SuiChain
|
|
@ -1,4 +0,0 @@
|
|||
chain: aptos_mainnet
|
||||
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
|
||||
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
|
||||
type: AptosContract
|
|
@ -1,4 +0,0 @@
|
|||
chain: aptos_testnet
|
||||
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
|
||||
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
|
||||
type: AptosContract
|
|
@ -0,0 +1,8 @@
|
|||
- chain: aptos_mainnet
|
||||
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
|
||||
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
|
||||
type: AptosContract
|
||||
- chain: aptos_testnet
|
||||
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
|
||||
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
|
||||
type: AptosContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: injective
|
||||
address: inj12j43nf2f0qumnt2zrrmpvnsqgzndxefujlvr08
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: injective_testnet
|
||||
address: inj18hckkzqf47mdhd734g6papk6wj20y24rm43sk9
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: injective_testnet
|
||||
address: inj18rlflp3735h25jmjx97d22c72sxk260amdjxlu
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: juno_testnet
|
||||
address: juno1eacsrua27njc35pxz37y97gmcjs899t59f8pf0rkejjyvtmhws5q6lxsdd
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: juno_testnet
|
||||
address: juno1h93q9kwlnfml2gum4zj54al9w4jdmuhtzrh6vhycnemsqlqv9l9snnznxs
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: neutron
|
||||
address: neutron1m2emc93m9gpwgsrsf2vylv9xvgqh654630v7dfrhrkmr5slly53spg85wv
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: neutron_testnet_pion_1
|
||||
address: neutron15ldst8t80982akgr8w8ekcytejzkmfpgdkeq4xgtge48qs7435jqp87u3t
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: neutron_testnet_pion_1
|
||||
address: neutron16zwrmx3zgggmxhzau86xfycm42cr4sj888hdvzsxya3qarp6zhhqzhlkvz
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: osmosis
|
||||
address: osmo13ge29x4e2s63a8ytz2px8gurtyznmue4a69n5275692v3qn3ks8q7cwck7
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: osmosis_testnet_5
|
||||
address: osmo1hpdzqku55lmfmptpyj6wdlugqs5etr6teqf7r4yqjjrxjznjhtuqqu5kdh
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: osmosis_testnet_5
|
||||
address: osmo1lltupx02sj99suakmuk4sr4ppqf34ajedaxut3ukjwkv6469erwqtpg9t3
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: sei_pacific_1
|
||||
address: sei15d2tyq2jzxmpg32y3am3w62dts32qgzmds9qnr6c87r0gwwr7ynqal0x38
|
||||
type: CosmWasmContract
|
|
@ -1,3 +0,0 @@
|
|||
chain: sei_testnet_atlantic_2
|
||||
address: sei1kpntez76v38yuxhhaaahdmvjxnr5tkr8tq077smefs7uw70rj5yqw2aewy
|
||||
type: CosmWasmContract
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue