import { EventEmitter } from 'events'; import * as wormholeSdk from '@certusone/wormhole-sdk'; import { SignedVaa, ChainId, EVMChainId, ParsedVaa, ChainName, ParsedTokenTransferVaa, TokenTransfer } from '@certusone/wormhole-sdk'; import * as winston from 'winston'; import { Logger } from 'winston'; import { Registry } from 'prom-client'; import * as ethers from 'ethers'; import { ethers as ethers$1, Signer } from 'ethers'; import * as solana from '@solana/web3.js'; import * as sui from '@mysten/sui.js'; import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'; import { ClusterNode, ClusterOptions, RedisOptions } from 'ioredis'; import { ITokenBridge } from '@certusone/wormhole-sdk/lib/cjs/ethers-contracts/index.js'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { Queue } from 'bullmq'; export { UnrecoverableError } from 'bullmq'; import Koa from 'koa'; declare enum Environment { MAINNET = "mainnet", TESTNET = "testnet", DEVNET = "devnet" } type FetchVaaFn = (emitterChain: ChainId | string, emitterAddress: Buffer | string, sequence: bigint | string, opts?: { retryTimeout?: number; retries?: number; }) => Promise; type FetchVaasFn = (opts: FetchaVaasOpts) => Promise; interface Context { vaa?: ParsedVaaWithBytes$1; vaaBytes?: SignedVaa; locals: Record; fetchVaa: FetchVaaFn; fetchVaas: FetchVaasFn; processVaa: (vaa: Buffer) => Promise; env: Environment; logger?: Logger; on: (eventName: RelayerEvents, listener: ListenerFn) => void; config: { spyFilters: { emitterFilter?: { chainId?: ChainId; emitterAddress?: string; }; }[]; }; } type Next = (i?: number) => any; type Middleware = (ctx: ContextT, next: Next) => Promise; type ErrorMiddleware = (err: Error, ctx: ContextT, next: Next) => Promise; declare function compose(middleware: Middleware[]): Middleware; declare function composeError(middleware: ErrorMiddleware[]): ErrorMiddleware; declare function isErrorMiddlewareList(list: any[]): list is ErrorMiddleware[]; type MakeOptional = Omit & Partial>> & Partial>; declare function encodeEmitterAddress(chainId: wormholeSdk.ChainId, emitterAddressStr: string): string; declare const strip0x: (str: string) => string; declare function sleep(ms: number): Promise; /** * Simple object check. * @param item * @returns {boolean} */ declare function isObject(item: T): item is T & ({} | null); declare function parseVaaWithBytes(bytes: SignedVaa): ParsedVaaWithBytes$1; /** * Deep merge two objects. * @param target * @param ...sources */ declare function mergeDeep(target: Partial, sources: Partial[], maxDepth?: number): T; declare const second = 1000; declare const minute: number; declare const hour: number; declare class EngineError extends Error { args?: Record | undefined; constructor(msg: string, args?: Record | undefined); } declare function maybeConcat(...arrs: (T[] | undefined)[]): T[]; declare function nnull(x: T | undefined | null, errMsg?: string): T; declare function assertStr(x: any, fieldName?: string): string; declare function assertInt(x: any, fieldName?: string): number; declare function assertArray(x: any, name: string, elemsPred?: (x: any) => boolean): T[]; declare function assertBool(x: any, fieldName?: string): boolean; declare function wormholeBytesToHex(address: Buffer | Uint8Array): string; declare function assertEvmChainId(chainId: number): EVMChainId; declare function assertChainId(chainId: number): ChainId; declare function dbg(x: T, msg?: string): T; declare function mapConcurrent(arr: any[], fn: (...args: any[]) => Promise, concurrency?: number): Promise; declare function printError(error: unknown): string; declare function min(lhs: bigint, rhs: bigint): bigint; declare function max(lhs: bigint, rhs: bigint): bigint; type VaaId = Pick; interface StorageContext extends Context { storage: { job: RelayJob; }; } interface RelayJob { id: string; name: string; data: { vaaBytes: Buffer; parsedVaa: ParsedVaa; }; attempts: number; maxAttempts: number; receivedAt: number; log(logRow: string): Promise; updateProgress(progress: number | object): Promise; } type onJobHandler = (job: RelayJob) => Promise; interface Storage { addVaaToQueue(vaa: SignedVaa): Promise; startWorker(cb: onJobHandler): void; stopWorker(): Promise; } interface RelayerAppOpts { wormholeRpcs: string[]; concurrency: number; } type FetchaVaasOpts = { ids: VaaId[]; delayBetweenRequestsInMs?: number; attempts?: number; }; declare const defaultWormholeRpcs: { mainnet: string[]; testnet: string[]; devnet: string[]; }; declare const defaultWormscanUrl: { mainnet: string; testnet: string; devnet: string; }; declare const defaultOpts: (env: Environment) => { wormholeRpcs: string[]; concurrency: number; }; interface SerializableVaaId { emitterChain: ChainId; emitterAddress: string; sequence: string; } interface ParsedVaaWithBytes$1 extends ParsedVaa { id: SerializableVaaId; bytes: SignedVaa; } type FilterFN = (vaaBytes: ParsedVaaWithBytes$1) => Promise | boolean; declare enum RelayerEvents { Received = "received", Added = "added", Skipped = "skipped", Completed = "completed", Failed = "failed" } type ListenerFn = (vaa: ParsedVaaWithBytes$1, job?: RelayJob) => void; declare class RelayerApp extends EventEmitter { env: Environment; storage?: Storage; filters: { emitterFilter?: { chainId?: ChainId; emitterAddress?: string; }; }[]; private pipeline?; private errorPipeline?; private chainRouters; private spyUrl?; private rootLogger?; private opts; private vaaFilters; private alreadyFilteredCache; private metrics; private registry; constructor(env?: Environment, opts?: Partial); get metricsRegistry(): Registry; /** * This function will run as soon as a VAA is received and will determine whether we want to process it or skip it. * This is useful if you're listening to a contract but you don't care about every one of the VAAs emitted by it (eg. The Token Bridge contract). * * WARNING: If your function throws, the VAA will be skipped (is this the right behavior?). If you want to process the VAA anyway, catch your errors and return true. * * @param newFilter pass in a function that will receive the raw bytes of the VAA and if it returns `true` or `Promise` the VAA will be processed, otherwise it will be skipped */ filter(newFilter: FilterFN): void; private shouldProcessVaa; on(eventName: RelayerEvents, listener: ListenerFn): this; emit(eventName: RelayerEvents, vaa: ParsedVaaWithBytes$1, job?: RelayJob, ...args: any): boolean; /** * Allows you to pass an object that specifies a combination of chains with address for which you want to run middleware. * * @example: * ``` * relayerApp.multiple({[CHAIN_ID_SOLANA]: "mysolanaAddress", [ CHAIN_ID_ETH ]: "0xMyEthAddress" }, middleware1, middleware2) * ``` * * This would run `middleware1` and `middleware2` for the address `mysolanaAddress` in Solana and for the address `0xMyEthAddress` in Ethereum. * @param chainsAndAddresses * @param middleware */ multiple(chainsAndAddresses: Partial<{ [k in ChainId]: string[] | string; }>, ...middleware: Middleware[]): void; /** * Pass in a set of middlewares that will run for each request * @example: * ``` * relayerApp.use(logging(logger)); * ``` * @param middleware */ use(...middleware: Middleware[] | ErrorMiddleware[]): void; fetchVaas(opts: FetchaVaasOpts): Promise; /** * Fetches a VAA from a wormhole compatible RPC. * You can specify how many times to retry in case it fails and how long to wait between retries * @param chain emitterChain * @param emitterAddress * @param sequence * @param retryTimeout backoff between retries * @param retries number of attempts */ readonly fetchVaa: FetchVaaFn; /** * processVaa allows you to put a VAA through the pipeline leveraging storage if needed. * @param vaa * @param opts You can use this to extend the context that will be passed to the middleware */ processVaa(vaa: Buffer, opts?: any): Promise; /** * Pushes a vaa through the pipeline. Unless you're the storage service you probably want to use `processVaa`. * @param vaa * @param opts */ private pushVaaThroughPipeline; /** * Gives you a Chain router so you can add middleware on an address. * @example: * ``` * relayerApp.chain(CHAIN_ID_ETH).address("0x0001234abcdef...", middleware1, middleware2); * ``` * * @param chainId */ chain(chainId: ChainId): ChainRouter; /** * A convenient shortcut to subscribe to tokenBridge messages. * @example: * ``` * relayerApp.tokenBridge(["ethereum", CHAIN_ID_SOLANA], middleware1, middleware2) * ``` * * Would run middleware1 and middleware2 for any tokenBridge vaa coming from ethereum or solana. * * @param chainsOrChain * @param handlers */ tokenBridge(chainsOrChain: ChainId[] | ChainName[] | ChainId | ChainName, ...handlers: Middleware[]): this; private spyFilters; /** * Pass in the URL where you have an instance of the spy listening. Usually localhost:7073 * * You can run the spy locally (for TESTNET) by doing: * ``` docker run \ --platform=linux/amd64 \ -p 7073:7073 \ --entrypoint /guardiand \ ghcr.io/wormhole-foundation/guardiand:latest \ spy --nodeKey /node.key --spyRPC "[::]:7073" --network /wormhole/testnet/2/1 --bootstrap 'dns4/t-guardian-01.testnet.xlabs.xyz/udp/8999/quic/p2p/12D3KooWCW3LGUtkCVkHZmVSZHzL3C4WRKWfqAiJPz1NR7dT9Bxh,/dns4/t-guardian-02.testnet.xlabs.xyz/udp/8999/quic/p2p/12D3KooWJXA6goBCiWM8ucjzc4jVUBSqL9Rri6UpjHbkMPErz5zK' * ``` * * You can run the spy locally (for MAINNET) by doing: * ``` docker run \ --platform=linux/amd64 \ -p 7073:7073 \ --entrypoint /guardiand \ ghcr.io/wormhole-foundation/guardiand:latest \ spy --nodeKey /node.key --spyRPC "[::]:7073" --network /wormhole/mainnet/2 --bootstrap '/dns4/wormhole-v2-mainnet-bootstrap.xlabs.xyz/udp/8999/quic/p2p/12D3KooWNQ9tVrcb64tw6bNs2CaNrUGPM7yRrKvBBheQ5yCyPHKC,/dns4/wormhole.mcf.rocks/udp/8999/quic/p2p/12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU,/dns4/wormhole-v2-mainnet-bootstrap.staking.fund/udp/8999/quic/p2p/12D3KooWG8obDX9DNi1KUwZNu9xkGwfKqTp2GFwuuHpWZ3nQruS1' * ``` * @param url */ spy(url: string): this; /** * Set a logger for the relayer app. Not to be confused with a logger for the middleware. This is for when the relayer app needs to log info/error. * * @param logger */ logger(logger: Logger): void; /** * Configure your storage by passing info redis connection info among other details. * If you are using RelayerApp, and you do not call this method, you will not be using storage. * Which means your VAAS will go straight through the pipeline instead of being added to a queue. * @param storage */ useStorage(storage: Storage): void; private generateChainRoutes; /** * Connect to the spy and start processing VAAs. */ listen(): Promise; private waitForReady; /** * Stop the worker from grabbing more jobs and wait until it finishes with the ones that it has. */ stop(): Promise | undefined; private onVaaFromQueue; } declare class ChainRouter { chainId: ChainId; _addressHandlers: Record>; constructor(chainId: ChainId); /** * Specify an address in native format (eg base58 for solana) and a set of middleware to run when we receive a VAA from that address * @param address * @param handlers */ address: (address: string, ...handlers: Middleware[]) => ChainRouter; spyFilters(): { emitterFilter: ContractFilter$1; }[]; process(ctx: ContextT, next: Next): Promise; } type ContractFilter$1 = { emitterAddress: string; chainId: ChainId; }; interface LoggingContext extends Context { logger: Logger; } declare function logging(logger: Logger): Middleware; type MetricRecord = Record; interface MetricsOpts { registry?: Registry; labels?: MetricLabelsOpts; buckets?: { processing?: number[]; total?: number[]; relay?: number[]; }; } declare class MetricLabelsOpts { labelNames: string[]; customizer: (context: C) => Promise; constructor(labelNames: string[] | undefined, customizer: (ctx: C) => Promise); } declare function metrics(opts?: MetricsOpts): Middleware; interface Providers$1 { evm: Partial>; solana: solana.Connection[]; untyped: Partial>; sui: sui.JsonRpcProvider[]; sei: CosmWasmClient[]; } type UntypedProvider$1 = { rpcUrl: string; }; interface ProviderContext extends Context { providers: Providers$1; } type ChainConfigInfo$1 = { [k in ChainId]: { endpoints: string[]; faucets?: string[]; websockets?: string[]; }; }; interface ProvidersOpts { chains: Partial; } /** * providers is a middleware that populates `ctx.providers` with provider information * @param opts */ declare function providers(opts?: ProvidersOpts, supportedChains?: string[]): Middleware; /// interface SourceTxOpts { wormscanEndpoint: string; retries: number; initialDelay: number; maxDelay: number; timeout: number; } interface SourceTxContext extends Context { sourceTxHash?: string; } declare function sourceTx(optsWithoutDefaults?: SourceTxOpts): Middleware; declare function fetchVaaHash(emitterChain: number, emitterAddress: Buffer, sequence: bigint, env: Environment, logger?: Logger, sourceTxOpts?: SourceTxOpts): Promise; interface StagingAreaContext extends Context { kv: StagingAreaKeyLock$1; } type StagingAreaOpts = ({ redisClusterEndpoints: ClusterNode[]; redisCluster: ClusterOptions; } | {}) & { redis?: RedisOptions; namespace?: string; }; declare function stagingArea(opts?: StagingAreaOpts): Middleware; interface StagingAreaKeyLock$1 { withKey>(keys: string[], f: (kvs: KV, ctx: OpaqueTx$1) => Promise<{ newKV: KV; val: T; }>, tx?: OpaqueTx$1): Promise; getKeys>(keys: string[]): Promise; } type OpaqueTx$1 = never; interface TokenBridgeContext extends ProviderContext { tokenBridge: { addresses: { [k in ChainName]?: string; }; contractConstructor: (address: string, signerOrProvider: Signer | ethers$1.providers.Provider) => ITokenBridge; contracts: { read: { evm: { [k in EVMChainId]?: ITokenBridge[]; }; }; }; vaa?: ParsedTokenTransferVaa; payload?: TokenTransfer; }; } type TokenBridgeChainConfigInfo = { evm: { [k in EVMChainId]: { contracts: ITokenBridge[]; }; }; }; declare function tokenBridgeContracts(): Middleware; interface WalletToolBox$1 extends Providers$1 { wallet: T; address: string; getBalance(): Promise; } declare function createWalletToolbox(providers: Providers$1, privateKey: string, chainId: wormholeSdk.ChainId): Promise>; type TokensByChain = Partial<{ [k in ChainId]: string[]; }>; type EVMWallet$1 = ethers$1.Wallet; type SuiWallet = sui.RawSigner; type SeiWallet = DirectSecp256k1Wallet; type SolanaWallet$1 = { conn: solana.Connection; payer: solana.Keypair; }; type Wallet$1 = EVMWallet$1 | SolanaWallet$1 | UntypedWallet$1 | SuiWallet | SeiWallet; type UntypedWallet$1 = UntypedProvider$1 & { privateKey: string; }; interface Action$1 { chainId: ChainId; f: ActionFunc$1; } type ActionFunc$1 = (walletToolBox: WalletToolBox$1, chaidId: ChainId) => Promise; interface ActionWithCont { action: Action$1; pluginName: string; resolve: (t: T) => void; reject: (reason: any) => void; } interface WorkerInfo { id: number; targetChainId: ChainId; targetChainName: string; walletPrivateKey: string; } interface ActionExecutor$1 { (chaindId: ChainId, f: ActionFunc$1): Promise; onSolana(f: ActionFunc$1): Promise; onEVM(chainId: EVMChainId, f: ActionFunc$1): Promise; onSei(f: ActionFunc$1): Promise; onSui(f: ActionFunc$1): Promise; } interface WalletContext extends ProviderContext { wallets: ActionExecutor$1; } interface WalletOpts { namespace: string; privateKeys: Partial<{ [k in ChainId]: any[]; }>; tokensByChain?: TokensByChain; logger?: Logger; metrics?: { enabled: boolean; registry: Registry; }; } declare function wallets(env: Environment, opts: WalletOpts): Middleware; interface RedisConnectionOpts { redisClusterEndpoints?: ClusterNode[]; redisCluster?: ClusterOptions; redis?: RedisOptions; namespace?: string; } interface ExponentialBackoffOpts { baseDelayMs: number; maxDelayMs: number; backOffFn?: (attemptsMade: number) => number; } interface StorageOptions extends RedisConnectionOpts { queueName: string; attempts: number; concurrency?: number; exponentialBackoff?: ExponentialBackoffOpts; maxCompletedQueueSize?: number; maxFailedQueueSize?: number; } type JobData = { parsedVaa: any; vaaBytes: string; }; declare class RedisStorage implements Storage { logger?: Logger; vaaQueue: Queue; registry: Registry; workerId?: string; private worker?; private readonly prefix; private readonly redis; private metrics; private opts; constructor(opts: StorageOptions); getPrefix(): string; addVaaToQueue(vaaBytes: Buffer): Promise; startWorker(handleJob: onJobHandler): void; stopWorker(): Promise; spawnGaugeUpdateWorker(ms?: number): Promise; storageKoaUI(path: string): Koa.Middleware; private vaaId; private updateGauges; } declare class HttpClientError extends Error { readonly status?: number; readonly data?: any; readonly headers?: Headers; constructor(message?: string, response?: Response, data?: any); /** * Parses the Retry-After header and returns the value in milliseconds. * @param maxDelay * @param error * @throws {HttpClientError} if retry-after is bigger than maxDelay. * @returns the retry-after value in milliseconds. */ getRetryAfter(maxDelay: number, error: HttpClientError): number | undefined; } interface Wormholescan { listVaas: (chain: number, emitterAddress: string, opts?: WormholescanOptions) => Promise>; getVaa: (chain: number, emitterAddress: string, sequence: bigint, opts?: WormholescanOptions) => Promise>; } /** * Client for the wormholescan API that never throws, but instead returns a WormholescanResult that may contain an error. */ declare class WormholescanClient implements Wormholescan { private baseUrl; private defaultOptions?; private client; constructor(baseUrl: URL, defaultOptions?: WormholescanOptions); listVaas(chain: number, emitterAddress: string, opts?: WormholescanOptions): Promise>; getVaa(chain: number, emitterAddress: string, sequence: bigint, opts?: WormholescanOptions): Promise>; getTransaction(chain: number, emitterAddress: string, sequence: bigint, opts?: WormholescanOptions): Promise>; private mapError; private getPage; private getPageSize; } type WormholescanOptions = { pageSize?: number; page?: number; retries?: number; initialDelay?: number; maxDelay?: number; timeout?: number; noCache?: boolean; }; /** * Parsed response model. */ type WormholescanVaa = { id: string; sequence: bigint; vaa: Buffer; emitterAddr: string; emitterChain: number; txHash?: string; }; /** * Wormhole Transaction response */ interface WormholescanTransactionResponse { id: string; timestamp: string; txHash: string; emitterChain: number; emitterAddress: string; emitterNativeAddress: string; tokenAmount: string; usdAmount: string; symbol: string; payload: Payload; standardizedProperties: StandardizedProperties; globalTx: GlobalTransaction; } type WormholescanTransaction = { id: string; timestamp: string; txHash: string; emitterChain: number; emitterAddress: string; emitterNativeAddress: string; tokenAmount: string; usdAmount: string; symbol: string; payload: Payload; standardizedProperties: StandardizedProperties; globalTx: GlobalTransaction; }; type GlobalTransaction = { id: string; originTx: { txHash: string; from: string; status: string; attribute: null | string; }; destinationTx: { chainId: number; status: string; method: string; txHash: string; from: string; to: string; blockNumber: string; timestamp: string; updatedAt: string; }; }; interface StandardizedProperties { amount: string; appIds: string[]; fee: string; feeAddress: string; feeChain: number; fromAddress: string; fromChain: number; toAddress: string; toChain: number; tokenAddress: string; tokenChain: number; } interface Payload { amount: string; fee: string; fromAddress: null | string; parsedPayload: null | string; payload: string; payloadType: number; toAddress: string; toChain: number; tokenAddress: string; tokenChain: number; } type WormholescanResult = { error: HttpClientError; } | { data: T; }; interface MissedVaaOpts extends RedisConnectionOpts { registry?: Registry; logger?: Logger; wormholeRpcs: string[]; wormscanUrl?: string; concurrency?: number; checkInterval?: number; fetchVaaRetries?: number; maxLookAhead?: number; vaasFetchConcurrency?: number; /** * "storagePrefix" is the prefix used by the storage (currently redis-storage) to * store workflows. See RedisStorage.getPrefix * * This is generating a dependency with the storage implementation, which is not ideal. * To solve this problem, we could add a new method to the storage interface to get seen sequences * and pass it to the missed vaas middleware * * Untill that happens, we assume that if you pass in a storagePrefix property, * then you are using redis-storage */ storagePrefix?: string; startingSequenceConfig?: Partial>; forceSeenKeysReindex?: boolean; } declare function spawnMissedVaaWorker(app: RelayerApp, opts: MissedVaaOpts): Promise; interface CommonPluginEnv { supportedChains: ChainConfigInfo[]; wormholeRpc: string; } interface ChainConfigInfo { chainId: ChainId; chainName: string; nodeUrl: string; } interface Workflow { id: WorkflowId; pluginName: string; scheduledAt?: Date; scheduledBy?: string; retryCount: number; maxRetries?: number; data: D; failedAt?: Date; errorMessage?: string; errorStacktrace?: string; completedAt?: Date; startedProcessingAt?: Date; processingBy?: string; emitterChain?: number; emitterAddress?: string; sequence?: string; } interface ActionExecutor { (action: Action): Promise; onSolana(f: ActionFunc): Promise; onEVM(action: Action): Promise; onSui(action: Action): Promise; } type ActionFunc = (walletToolBox: WalletToolBox, chaindId: ChainId) => Promise; interface Action { chainId: ChainId; f: ActionFunc; } type WorkflowId = string; type UntypedProvider = { rpcUrl: string; }; type EVMWallet = ethers.Wallet; type UntypedWallet = UntypedProvider & { privateKey: string; }; type SolanaWallet = { conn: solana.Connection; payer: solana.Keypair; }; type Wallet = EVMWallet | SolanaWallet | UntypedWallet; interface WalletToolBox extends Providers { wallet: T; } interface Providers { untyped: Partial>; evm: Partial>; solana: solana.Connection; sui: sui.JsonRpcProvider; sei: CosmWasmClient; } interface ParsedVaaWithBytes extends ParsedVaa { bytes: SignedVaa; } type EngineInitFn = (engineConfig: CommonPluginEnv, logger: winston.Logger) => PluginType; interface WorkflowOptions { maxRetries?: number; } interface Plugin { pluginName: string; pluginConfig: any; shouldSpy: boolean; shouldRest: boolean; maxRetries?: number; afterSetup?(providers: Providers, listenerResources?: { eventSource: EventSource; db: StagingAreaKeyLock; }): Promise; getFilters(): ContractFilter[]; consumeEvent(// Function to be defined in plug-in that takes as input a VAA outputs a list of actions vaa: ParsedVaaWithBytes, stagingArea: StagingAreaKeyLock, providers: Providers, extraData?: any[]): Promise<{ workflowData: WorkflowData; workflowOptions?: WorkflowOptions; } | undefined>; handleWorkflow(workflow: Workflow, providers: Providers, execute: ActionExecutor): Promise; } type EventSource = (event: SignedVaa, extraData?: any[]) => Promise; type ContractFilter = { emitterAddress: string; chainId: ChainId; doNotTransform?: boolean; }; interface StagingAreaKeyLock { withKey>(keys: string[], f: (kvs: KV, ctx: OpaqueTx) => Promise<{ newKV: KV; val: T; }>, tx?: OpaqueTx): Promise; getKeys>(keys: string[]): Promise; } type OpaqueTx = never; type PluginContext = LoggingContext & StorageContext & StagingAreaContext & WalletContext & ProviderContext & Ext; declare function legacyPluginCompat(app: RelayerApp>, plugin: Plugin): void; type RelayerEngineConfigs = { commonEnv: CommonEnv; listenerEnv?: ListenerEnv; executorEnv?: ExecutorEnv; }; declare enum StoreType { Redis = "Redis" } declare enum Mode { LISTENER = "LISTENER", EXECUTOR = "EXECUTOR", BOTH = "BOTH" } type NodeURI = string; interface RedisConfig { host: string; port: number; username?: string; password?: string; tls?: boolean; cluster?: boolean; } interface CommonEnv { namespace?: string; logLevel?: string; logFormat?: "json" | "console" | ""; promPort?: number; apiPort?: number; apiKey?: string; readinessPort?: number; logDir?: string; storeType: StoreType; redis?: RedisConfig; pluginURIs?: NodeURI[]; numGuardians?: number; wormholeRpc: string; mode: Mode; supportedChains: ChainConfigInfo[]; defaultWorkflowOptions: WorkflowOptions; } type ListenerEnv = { spyServiceHost: string; nextVaaFetchingWorkerTimeoutSeconds?: number; restPort?: number; }; type PrivateKeys = { [id in ChainId]: string[]; }; type ExecutorEnv = { privateKeys: PrivateKeys; actionInterval?: number; }; type CommonEnvRun = Omit; interface RunArgs { configs: string | { commonEnv: CommonEnvRun; executorEnv?: ExecutorEnv; listenerEnv?: ListenerEnv; }; mode: Mode; plugins: { [pluginName: string]: EngineInitFn; }; } /** @deprecated use the app builder directly, see example project for modern APIs or source code for this function*/ declare function run(args: RunArgs, env: Environment): Promise; declare function loadRelayerEngineConfig(dir: string, mode: Mode, { privateKeyEnv }?: { privateKeyEnv?: boolean; }): Promise; declare function loadFileAndParseToObject(path: string): Promise>; type index_Action = Action; type index_ActionExecutor = ActionExecutor; type index_ActionFunc = ActionFunc; type index_ChainConfigInfo = ChainConfigInfo; type index_CommonEnv = CommonEnv; type index_CommonEnvRun = CommonEnvRun; type index_CommonPluginEnv = CommonPluginEnv; type index_ContractFilter = ContractFilter; type index_EVMWallet = EVMWallet; type index_EngineInitFn = EngineInitFn; type index_EventSource = EventSource; type index_ExecutorEnv = ExecutorEnv; type index_ListenerEnv = ListenerEnv; type index_Mode = Mode; declare const index_Mode: typeof Mode; type index_OpaqueTx = OpaqueTx; type index_ParsedVaaWithBytes = ParsedVaaWithBytes; type index_Plugin = Plugin; type index_PluginContext = PluginContext; type index_Providers = Providers; type index_RunArgs = RunArgs; type index_SolanaWallet = SolanaWallet; type index_StagingAreaKeyLock = StagingAreaKeyLock; type index_UntypedProvider = UntypedProvider; type index_UntypedWallet = UntypedWallet; type index_Wallet = Wallet; type index_WalletToolBox = WalletToolBox; type index_Workflow = Workflow; type index_WorkflowId = WorkflowId; type index_WorkflowOptions = WorkflowOptions; declare const index_legacyPluginCompat: typeof legacyPluginCompat; declare const index_loadFileAndParseToObject: typeof loadFileAndParseToObject; declare const index_loadRelayerEngineConfig: typeof loadRelayerEngineConfig; declare const index_run: typeof run; declare namespace index { export { type index_Action as Action, type index_ActionExecutor as ActionExecutor, type index_ActionFunc as ActionFunc, type index_ChainConfigInfo as ChainConfigInfo, type index_CommonEnv as CommonEnv, type index_CommonEnvRun as CommonEnvRun, type index_CommonPluginEnv as CommonPluginEnv, type index_ContractFilter as ContractFilter, type index_EVMWallet as EVMWallet, type index_EngineInitFn as EngineInitFn, type index_EventSource as EventSource, type index_ExecutorEnv as ExecutorEnv, type index_ListenerEnv as ListenerEnv, index_Mode as Mode, type index_OpaqueTx as OpaqueTx, type index_ParsedVaaWithBytes as ParsedVaaWithBytes, type index_Plugin as Plugin, type index_PluginContext as PluginContext, type index_Providers as Providers, type index_RunArgs as RunArgs, type index_SolanaWallet as SolanaWallet, type index_StagingAreaKeyLock as StagingAreaKeyLock, type index_UntypedProvider as UntypedProvider, type index_UntypedWallet as UntypedWallet, type index_Wallet as Wallet, type index_WalletToolBox as WalletToolBox, type index_Workflow as Workflow, type index_WorkflowId as WorkflowId, type index_WorkflowOptions as WorkflowOptions, index_legacyPluginCompat as legacyPluginCompat, index_loadFileAndParseToObject as loadFileAndParseToObject, index_loadRelayerEngineConfig as loadRelayerEngineConfig, index_run as run }; } interface StandardMissedVaaOpts { concurrency?: number; checkInterval?: number; fetchVaaRetries?: number; vaasFetchConcurrency?: number; storagePrefix?: string; startingSequenceConfig?: Partial>; forceSeenKeysReindex?: boolean; } interface StandardRelayerAppOpts extends RelayerAppOpts { name: string; spyEndpoint: string; logger?: Logger; privateKeys?: Partial<{ [k in ChainId]: any[]; }>; tokensByChain?: TokensByChain; workflows?: { retries: number; }; providers?: ProvidersOpts; redisClusterEndpoints?: ClusterNode[]; redisCluster?: ClusterOptions; redis?: RedisOptions; fetchSourceTxhash?: boolean; retryBackoffOptions?: ExponentialBackoffOpts; missedVaaOptions?: StandardMissedVaaOpts; maxCompletedQueueSize?: number; maxFailedQueueSize?: number; } declare const defaultStdOpts: { spyEndpoint: string; workflows: { retries: number; }; fetchSourceTxhash: true; logger: Logger; }; type FullDefaultOpts = typeof defaultStdOpts & ReturnType; type StandardRelayerContext = LoggingContext & StorageContext & TokenBridgeContext & StagingAreaContext & WalletContext & SourceTxContext; declare class StandardRelayerApp extends RelayerApp { private readonly store; private readonly mergedRegistry; constructor(env: Environment, opts: MakeOptional); /** * Registry with prometheus metrics exported by the relayer. * Metrics include: * - active_workflows: Number of workflows currently running * - delayed_workflows: Number of worklows which are scheduled in the future either because they were scheduled that way or because they failed. * - waiting_workflows: Workflows waiting for a worker to pick them up. * - worklow_processing_duration: Processing time for completed jobs (processing until completed) * - workflow_total_duration: Processing time for completed jobs (processing until completed) */ get metricsRegistry(): Registry; /** * A UI that you can mount in a KOA app to show the status of the queue / jobs. * @param path */ storageKoaUI(path: string): Koa.Middleware; } declare const defaultLogger: winston.Logger; export { type Action$1 as Action, type ActionExecutor$1 as ActionExecutor, type ActionFunc$1 as ActionFunc, type ActionWithCont, type ChainConfigInfo$1 as ChainConfigInfo, type Context, type ContractFilter$1 as ContractFilter, type EVMWallet$1 as EVMWallet, EngineError, Environment, type ErrorMiddleware, type ExponentialBackoffOpts, type FetchVaaFn, type FetchVaasFn, type FetchaVaasOpts, type FilterFN, type GlobalTransaction, type JobData, index as LegacyPluginCompat, type ListenerFn, type LoggingContext, type MakeOptional, MetricLabelsOpts, type MetricsOpts, type Middleware, type MissedVaaOpts as MissedVaaWorkerOpts, type Next, type OpaqueTx$1 as OpaqueTx, type ParsedVaaWithBytes$1 as ParsedVaaWithBytes, type ProviderContext, type Providers$1 as Providers, type ProvidersOpts, type RedisConnectionOpts, RedisStorage, type RelayJob, RelayerApp, type RelayerAppOpts, RelayerEvents, type SeiWallet, type SerializableVaaId, type SolanaWallet$1 as SolanaWallet, type SourceTxContext, type SourceTxOpts, type StagingAreaContext, type StagingAreaKeyLock$1 as StagingAreaKeyLock, type StagingAreaOpts, type StandardMissedVaaOpts, StandardRelayerApp, type StandardRelayerAppOpts, type StandardRelayerContext, type Storage, type StorageContext, type StorageOptions, type SuiWallet, type TokenBridgeChainConfigInfo, type TokenBridgeContext, type UntypedProvider$1 as UntypedProvider, type UntypedWallet$1 as UntypedWallet, type Wallet$1 as Wallet, type WalletContext, type WalletOpts, type WalletToolBox$1 as WalletToolBox, type WorkerInfo, type Wormholescan, WormholescanClient, type WormholescanOptions, type WormholescanResult, type WormholescanTransaction, type WormholescanTransactionResponse, type WormholescanVaa, assertArray, assertBool, assertChainId, assertEvmChainId, assertInt, assertStr, compose, composeError, createWalletToolbox, dbg, defaultLogger, defaultOpts, defaultWormholeRpcs, defaultWormscanUrl, encodeEmitterAddress, fetchVaaHash, hour, isErrorMiddlewareList, isObject, logging, mapConcurrent, max, maybeConcat, mergeDeep, metrics, min, minute, nnull, type onJobHandler, parseVaaWithBytes, printError, providers, second, sleep, sourceTx, spawnMissedVaaWorker, stagingArea, strip0x, tokenBridgeContracts, wallets, wormholeBytesToHex };