mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-24 20:10:34 +00:00
335 lines
8.6 KiB
TypeScript
335 lines
8.6 KiB
TypeScript
//
|
|
// Copyright 2021 Vulcanize, Inc.
|
|
//
|
|
|
|
import fs from 'fs-extra';
|
|
import path from 'path';
|
|
import toml from 'toml';
|
|
import debug from 'debug';
|
|
import { ConnectionOptions } from 'typeorm';
|
|
|
|
import { Config as CacheConfig } from '@cerc-io/cache';
|
|
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1319854183
|
|
import type { PubsubType } from '@cerc-io/peer';
|
|
|
|
const log = debug('vulcanize:config');
|
|
|
|
export interface JobQueueConfig {
|
|
dbConnectionString: string;
|
|
maxCompletionLagInSecs: number;
|
|
jobDelayInMilliSecs?: number;
|
|
eventsInBatch: number;
|
|
lazyUpdateBlockProgress?: boolean;
|
|
subgraphEventsOrder: boolean;
|
|
blockDelayInMilliSecs: number;
|
|
|
|
// Number of blocks by which block processing lags behind head (default: 0)
|
|
blockProcessingOffset?: number;
|
|
|
|
// Block range in which logs are fetched during historical blocks processing
|
|
historicalLogsBlockRange?: number;
|
|
|
|
// Factor to find the next multiple endBlock number when deciding eth_getLogs block range
|
|
// Used to fetch logs in aligned block ranges (paired with caching proxy server)
|
|
// If set to 0, historicalLogsBlockRange will be used to instead to decide block ranges
|
|
historicalLogsBlockRangeEndFactor?: number
|
|
|
|
// Max block range of historical processing after which it waits for completion of events processing
|
|
// If set to -1 historical processing does not wait for events processing and completes till latest canonical block
|
|
historicalMaxFetchAhead?: number;
|
|
|
|
// Boolean to switch between modes of processing events when starting the server
|
|
// Setting to true will fetch filtered events and required blocks in a range of blocks and then process them
|
|
// Setting to false will fetch blocks consecutively with its events and then process them (Behaviour is followed in realtime processing near head)
|
|
useBlockRanges: boolean;
|
|
|
|
// Max number of retries to fetch new block after which watcher will failover to other RPC endpoints
|
|
// Infinitely retry if not set
|
|
maxNewBlockRetries?: number;
|
|
}
|
|
|
|
export interface GQLCacheConfig {
|
|
enabled: boolean;
|
|
maxCacheSize?: number;
|
|
maxAge: number;
|
|
timeTravelMaxAge: number;
|
|
}
|
|
|
|
// Relay node config
|
|
export interface RelayConfig {
|
|
// Host to bind the relay server to
|
|
host?: string;
|
|
|
|
// Port to start listening on
|
|
port?: number;
|
|
|
|
// Relay peer id file path (json)
|
|
peerIdFile?: string;
|
|
|
|
// Domain name to be used in the announce address
|
|
announce?: string;
|
|
|
|
// Relay peer multiaddr(s) list
|
|
relayPeers?: string[];
|
|
|
|
// Blacklisted multiaddr(s) list
|
|
denyMultiaddrs?: string[];
|
|
|
|
// Timeout (ms) for dial to relay peers
|
|
dialTimeout?: number;
|
|
|
|
// Interval in ms to check relay peer connections using ping
|
|
pingInterval?: number;
|
|
|
|
// Redial interval in ms on connection failure
|
|
redialInterval?: number;
|
|
|
|
// Max number of dial retries to be attempted to a relay peer
|
|
maxDialRetry?: number;
|
|
|
|
// Pubsub to use ('floodsub' | 'gossipsub')
|
|
pubsub?: PubsubType;
|
|
|
|
// Broadcast node's info over pubsub on requests
|
|
enableDebugInfo?: boolean;
|
|
}
|
|
|
|
// L2 tx config
|
|
interface L2TxsConfig {
|
|
// Address of contract for which txs are sent
|
|
contractAddress: string;
|
|
|
|
// Private key of tx signer (needs to have some balance)
|
|
privateKey: string;
|
|
|
|
// Gas limit for tx
|
|
gasLimit?: number;
|
|
}
|
|
|
|
// Peer config
|
|
export interface PeerConfig {
|
|
// Multiaddr of the primary relay node for this peer
|
|
relayMultiaddr: string;
|
|
|
|
// Pubsub topic to subscribe this peer to
|
|
pubSubTopic: string;
|
|
|
|
// Interval (ms) to check relay peer connections using ping
|
|
pingInterval?: number;
|
|
|
|
// Ping timeout (ms) used to check if connection is alive
|
|
pingTimeout?: number;
|
|
|
|
// Max number of relay node connections for a peer
|
|
maxRelayConnections?: number;
|
|
|
|
// Redial interval (ms) to relay node on connection failure
|
|
relayRedialInterval?: number;
|
|
|
|
// Blacklisted multiaddr(s) list
|
|
denyMultiaddrs?: string[];
|
|
|
|
// Max number of connections for a peer
|
|
maxConnections?: number;
|
|
|
|
// Timeout (ms) for dial to peers
|
|
dialTimeout?: number;
|
|
|
|
// Peer id file path (json)
|
|
peerIdFile?: string;
|
|
|
|
// Pubsub to use ('floodsub' | 'gossipsub')
|
|
pubsub?: PubsubType;
|
|
|
|
// Direct peers list (only required with gossipsub)
|
|
directPeers?: string[];
|
|
|
|
// Participate in exchange of debug info over pubsub
|
|
enableDebugInfo?: boolean;
|
|
|
|
// Enable sending txs to L2 chain for every message received in P2P network
|
|
enableL2Txs: boolean;
|
|
|
|
// Config for sending txs to L2
|
|
l2TxsConfig?: L2TxsConfig;
|
|
}
|
|
|
|
export interface BaseRatesConfig {
|
|
freeQueriesLimit: number;
|
|
freeQueriesList: string[];
|
|
queries: { [key: string]: string };
|
|
mutations: { [key: string]: string };
|
|
}
|
|
|
|
export interface PaymentsCacheConfig {
|
|
maxAccounts: number;
|
|
accountTTLInSecs: number;
|
|
maxVouchersPerAccount: number;
|
|
voucherTTLInSecs: number;
|
|
maxPaymentChannels: number;
|
|
paymentChannelTTLInSecs: number;
|
|
}
|
|
|
|
// Payments manager config
|
|
export interface PaymentsConfig {
|
|
ratesFile: string;
|
|
requestTimeoutInSecs: number;
|
|
cache: PaymentsCacheConfig;
|
|
}
|
|
|
|
// ts-nitro config
|
|
export interface NitroConfig {
|
|
chainUrl: string;
|
|
store: string;
|
|
|
|
privateKey: string;
|
|
chainPrivateKey: string;
|
|
|
|
payments: PaymentsConfig;
|
|
}
|
|
|
|
// Consensus config
|
|
export interface ConsensusConfig {
|
|
enabled: boolean;
|
|
publicKey: string;
|
|
privateKey: string;
|
|
watcherPartyPeersFile: string;
|
|
}
|
|
|
|
// P2P config
|
|
export interface P2PConfig {
|
|
// Enable relay node
|
|
enableRelay: boolean;
|
|
relay: RelayConfig;
|
|
|
|
// Enable peer node
|
|
enablePeer: boolean;
|
|
peer: PeerConfig;
|
|
|
|
nitro: NitroConfig;
|
|
|
|
consensus: ConsensusConfig;
|
|
}
|
|
|
|
// GQL config
|
|
export interface GQLConfig {
|
|
path: string;
|
|
maxEventsBlockRange: number;
|
|
|
|
// GQL cache-control max-age settings (in seconds)
|
|
cache: GQLCacheConfig;
|
|
|
|
// Boolean to load GQL query nested entity relations sequentially
|
|
loadRelationsSequential: boolean;
|
|
|
|
// Max GQL API requests to process simultaneously (defaults to 1)
|
|
maxSimultaneousRequests?: number;
|
|
|
|
// Max GQL API requests in queue until reject (defaults to -1, means do not reject)
|
|
maxRequestQueueLimit?: number;
|
|
|
|
// Log directory for GQL requests
|
|
logDir?: string;
|
|
}
|
|
|
|
export interface ServerConfig {
|
|
host: string;
|
|
port: number;
|
|
mode: string;
|
|
kind: string;
|
|
enableConfigValidation: boolean;
|
|
checkpointing: boolean;
|
|
checkpointInterval: number;
|
|
subgraphPath: string;
|
|
enableState: boolean;
|
|
wasmRestartBlocksInterval: number;
|
|
clearEntitiesCacheInterval: number;
|
|
|
|
// Boolean to skip updating entity fields required in state creation and not required in the frontend
|
|
skipStateFieldsUpdate: boolean;
|
|
|
|
// GQL config for server
|
|
gql: GQLConfig
|
|
|
|
p2p: P2PConfig;
|
|
|
|
// TODO: Move flag to config upstream.ethServer
|
|
// Flag to specify whether RPC endpoint supports block hash as block tag parameter
|
|
// https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block
|
|
rpcSupportsBlockHashParam: boolean;
|
|
}
|
|
|
|
export interface FundingAmountsConfig {
|
|
directFund: string;
|
|
virtualFund: string;
|
|
}
|
|
export interface NitroPeerConfig {
|
|
address: string;
|
|
multiAddr: string;
|
|
fundingAmounts: FundingAmountsConfig;
|
|
}
|
|
|
|
export interface EthServerPaymentsConfig {
|
|
nitro: NitroPeerConfig;
|
|
paidRPCMethods: string[];
|
|
amount: string;
|
|
}
|
|
|
|
export interface UpstreamConfig {
|
|
cache: CacheConfig;
|
|
ethServer: {
|
|
gqlApiEndpoint: string;
|
|
rpcProviderEndpoints: string[];
|
|
rpcProviderMutationEndpoint: string;
|
|
|
|
// Boolean flag to specify if rpc-eth-client should be used for RPC endpoint instead of ipld-eth-client (ipld-eth-server GQL client)
|
|
rpcClient: boolean;
|
|
|
|
// Boolean flag to specify if rpcProviderEndpoint is an FEVM RPC endpoint
|
|
isFEVM: boolean;
|
|
|
|
// Boolean flag to filter event logs by contracts
|
|
filterLogsByAddresses: boolean;
|
|
|
|
// Boolean flag to filter event logs by topics
|
|
filterLogsByTopics: boolean;
|
|
|
|
// Switch clients if eth_getLogs call takes more than threshold (in secs)
|
|
getLogsClientSwitchThresholdInSecs?: number;
|
|
|
|
payments: EthServerPaymentsConfig;
|
|
}
|
|
traceProviderEndpoint: string;
|
|
}
|
|
|
|
export interface GQLMetricsConfig {
|
|
port: number;
|
|
}
|
|
|
|
export interface MetricsConfig {
|
|
host: string;
|
|
port: number;
|
|
gql: GQLMetricsConfig;
|
|
}
|
|
|
|
export interface Config {
|
|
server: ServerConfig;
|
|
database: ConnectionOptions;
|
|
upstream: UpstreamConfig;
|
|
jobQueue: JobQueueConfig;
|
|
metrics: MetricsConfig;
|
|
}
|
|
|
|
export const getConfig = async<ConfigType> (configFile: string): Promise<ConfigType> => {
|
|
const configFilePath = path.resolve(configFile);
|
|
const fileExists = await fs.pathExists(configFilePath);
|
|
if (!fileExists) {
|
|
throw new Error(`Config file not found: ${configFilePath}`);
|
|
}
|
|
|
|
const config = toml.parse(await fs.readFile(configFilePath, 'utf8'));
|
|
log('config', JSON.stringify(config, null, 2));
|
|
|
|
return config;
|
|
};
|