| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- import {
- AptosChain,
- Chain,
- CosmWasmChain,
- StarknetChain,
- EvmChain,
- FuelChain,
- GlobalChain,
- SuiChain,
- TonChain,
- NearChain,
- IotaChain,
- } from "./chains";
- import {
- AptosPriceFeedContract,
- AptosWormholeContract,
- CosmWasmPriceFeedContract,
- CosmWasmWormholeContract,
- EvmEntropyContract,
- EvmPriceFeedContract,
- EvmWormholeContract,
- SuiPriceFeedContract,
- SuiWormholeContract,
- FuelWormholeContract,
- WormholeContract,
- FuelPriceFeedContract,
- EvmExpressRelayContract,
- TonPriceFeedContract,
- TonWormholeContract,
- IotaWormholeContract,
- IotaPriceFeedContract,
- EvmPulseContract,
- } from "./contracts";
- import { Token } from "./token";
- import { PriceFeedContract, Storable } from "./base";
- import { parse, stringify } from "yaml";
- import { readdirSync, readFileSync, statSync, writeFileSync } from "fs";
- import { Vault } from "./governance";
- import {
- StarknetPriceFeedContract,
- StarknetWormholeContract,
- } from "./contracts/starknet";
- import { NearPriceFeedContract, NearWormholeContract } from "./contracts/near";
- export class Store {
- public chains: Record<string, Chain> = { global: new GlobalChain() };
- public contracts: Record<string, PriceFeedContract> = {};
- public entropy_contracts: Record<string, EvmEntropyContract> = {};
- public pulse_contracts: Record<string, EvmPulseContract> = {};
- public wormhole_contracts: Record<string, WormholeContract> = {};
- public express_relay_contracts: Record<string, EvmExpressRelayContract> = {};
- public tokens: Record<string, Token> = {};
- public vaults: Record<string, Vault> = {};
- constructor(public path: string) {
- this.loadAllChains();
- this.loadAllContracts();
- this.loadAllTokens();
- this.loadAllVaults();
- }
- static serialize(obj: Storable) {
- return stringify([obj.toJson()]);
- }
- getYamlFiles(path: string) {
- const walk = function (dir: string) {
- let results: string[] = [];
- const list = readdirSync(dir);
- list.forEach(function (file) {
- file = dir + "/" + file;
- const stat = statSync(file);
- if (stat && stat.isDirectory()) {
- // Recurse into a subdirectory
- results = results.concat(walk(file));
- } else {
- // Is a file
- results.push(file);
- }
- });
- return results;
- };
- return walk(path).filter((file) => file.endsWith(".yaml"));
- }
- loadAllChains() {
- const allChainClasses = {
- [CosmWasmChain.type]: CosmWasmChain,
- [SuiChain.type]: SuiChain,
- [EvmChain.type]: EvmChain,
- [AptosChain.type]: AptosChain,
- [FuelChain.type]: FuelChain,
- [StarknetChain.type]: StarknetChain,
- [TonChain.type]: TonChain,
- [NearChain.type]: NearChain,
- [SuiChain.type]: SuiChain,
- [IotaChain.type]: IotaChain,
- };
- this.getYamlFiles(`${this.path}/chains/`).forEach((yamlFile) => {
- const parsedArray = parse(readFileSync(yamlFile, "utf-8"));
- for (const parsed of parsedArray) {
- if (allChainClasses[parsed.type] === undefined) {
- throw new Error(
- `No chain class found for chain type: ${parsed.type}`
- );
- }
- 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;
- }
- });
- }
- saveAllContracts() {
- const contractsByType: Record<string, Storable[]> = {};
- const contracts: Storable[] = Object.values(this.contracts);
- contracts.push(...Object.values(this.entropy_contracts));
- contracts.push(...Object.values(this.wormhole_contracts));
- for (const contract of 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() {
- const 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() {
- const allContractClasses = {
- [CosmWasmPriceFeedContract.type]: CosmWasmPriceFeedContract,
- [CosmWasmWormholeContract.type]: CosmWasmWormholeContract,
- [SuiPriceFeedContract.type]: SuiPriceFeedContract,
- [SuiWormholeContract.type]: SuiWormholeContract,
- [EvmPriceFeedContract.type]: EvmPriceFeedContract,
- [AptosPriceFeedContract.type]: AptosPriceFeedContract,
- [AptosWormholeContract.type]: AptosWormholeContract,
- [EvmEntropyContract.type]: EvmEntropyContract,
- [EvmExpressRelayContract.type]: EvmExpressRelayContract,
- [EvmWormholeContract.type]: EvmWormholeContract,
- [FuelPriceFeedContract.type]: FuelPriceFeedContract,
- [FuelWormholeContract.type]: FuelWormholeContract,
- [StarknetPriceFeedContract.type]: StarknetPriceFeedContract,
- [StarknetWormholeContract.type]: StarknetWormholeContract,
- [TonPriceFeedContract.type]: TonPriceFeedContract,
- [TonWormholeContract.type]: TonWormholeContract,
- [NearPriceFeedContract.type]: NearPriceFeedContract,
- [NearWormholeContract.type]: NearWormholeContract,
- [IotaPriceFeedContract.type]: IotaPriceFeedContract,
- [IotaWormholeContract.type]: IotaWormholeContract,
- };
- this.getYamlFiles(`${this.path}/contracts/`).forEach((yamlFile) => {
- 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];
- const chainContract = allContractClasses[parsed.type].fromJson(
- chain,
- parsed
- );
- if (
- this.contracts[chainContract.getId()] ||
- this.entropy_contracts[chainContract.getId()] ||
- this.wormhole_contracts[chainContract.getId()]
- )
- throw new Error(
- `Multiple contracts with id ${chainContract.getId()} found`
- );
- if (chainContract instanceof EvmEntropyContract) {
- this.entropy_contracts[chainContract.getId()] = chainContract;
- } else if (chainContract instanceof EvmExpressRelayContract) {
- this.express_relay_contracts[chainContract.getId()] = chainContract;
- } else if (chainContract instanceof WormholeContract) {
- this.wormhole_contracts[chainContract.getId()] = chainContract;
- } else {
- this.contracts[chainContract.getId()] = chainContract;
- }
- }
- });
- }
- loadAllTokens() {
- this.getYamlFiles(`${this.path}/tokens/`).forEach((yamlFile) => {
- const parsedArray = parse(readFileSync(yamlFile, "utf-8"));
- for (const parsed of parsedArray) {
- if (parsed.type !== Token.type) return;
- const token = Token.fromJson(parsed);
- if (this.tokens[token.getId()])
- throw new Error(`Multiple tokens with id ${token.getId()} found`);
- this.tokens[token.getId()] = token;
- }
- });
- }
- loadAllVaults() {
- this.getYamlFiles(`${this.path}/vaults/`).forEach((yamlFile) => {
- const 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;
- }
- });
- }
- /**
- * Returns the chain with the given ID, or throws an error if it doesn't exist or is not of the specified type.
- * @param chainId The unique identifier of the chain to retrieve
- * @param ChainClass Optional class to validate the chain type.
- * @returns The chain instance of type T
- * @throws Error if chain doesn't exist or is not of the specified type
- * @template T Type of chain to return, extends base Chain class
- */
- getChainOrThrow<T extends Chain>(
- chainId: string,
- ChainClass?: { new (...args: any[]): T; type: string } // eslint-disable-line @typescript-eslint/no-explicit-any
- ): T {
- const chain = this.chains[chainId];
- if (!chain) {
- throw new Error(`Chain with ID '${chainId}' does not exist.`);
- }
- if (ChainClass && !(chain instanceof ChainClass)) {
- throw new Error(
- `Chain with ID '${chainId}' is not of type ${ChainClass.type}.`
- );
- }
- return chain as T;
- }
- }
- /**
- * DefaultStore loads all the contracts and chains from the store directory and provides a single point of access to them.
- */
- export const DefaultStore = new Store(`${__dirname}/../store`);
|