pyth-crosschain/contract_manager/src/base.ts

189 lines
5.7 KiB
TypeScript

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
*/
abstract getId(): string;
/**
* Returns the type of this object. This is used to reconstruct the object and should match
* the static field type in the class responsible for constructing this object.
*/
abstract getType(): string;
/**
* Returns a JSON representation of this object. It should be possible to
* reconstruct the object from the JSON using the fromJson method.
*/
abstract toJson(): KeyValueConfig;
}
export interface Price {
price: string;
conf: string;
publishTime: string;
expo: string;
}
export interface PriceFeed {
price: Price;
emaPrice: Price;
}
export abstract class Contract extends Storable {
/**
* Returns the time period in seconds that stale data is considered valid for.
*/
abstract getValidTimePeriod(): Promise<number>;
/**
* Returns the chain that this contract is deployed on
*/
abstract getChain(): Chain;
/**
* Returns an array of data sources that this contract accepts price feed messages from
*/
abstract getDataSources(): Promise<DataSource[]>;
/**
* Returns the base update fee for this contract
* This is the required fee for updating the price feeds in the contract
*/
abstract getBaseUpdateFee(): Promise<{ amount: string; denom?: string }>;
/**
* Returns the last governance sequence that was executed on this contract
* this number increases based on the sequence number of the governance messages
* that are executed on this contract
*
* This is used to determine which governance messages are stale and can not be executed
*/
abstract getLastExecutedGovernanceSequence(): Promise<number>;
/**
* Returns the price feed for the given feed id or undefined if not found
* @param feedId hex encoded feed id without 0x prefix
*/
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: PrivateKey,
vaas: Buffer[]
): Promise<TxResult>;
/**
* 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
* @param vaa the VAA to execute
*/
abstract executeGovernanceInstruction(
senderPrivateKey: PrivateKey,
vaa: Buffer
): Promise<TxResult>;
/**
* Returns the single data source that this contract accepts governance messages from
*/
abstract getGovernanceDataSource(): Promise<DataSource>;
}
export function getDefaultDeploymentConfig(deploymentType: DeploymentType): {
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 === "beta")
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}`);
}