feat(infra): use private RPCs for warp monitor service (#4425)

### Description
- support private RPCs for warp monitor service

### Backward compatibility

Yes

### Testing

Manual
pull/4530/head
Mohammed Hussan 2 months ago committed by GitHub
parent fd2c3aac26
commit f81294ac16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConifg.ts
  2. 12
      typescript/infra/helm/warp-routes/templates/_helpers.tpl
  3. 44
      typescript/infra/helm/warp-routes/templates/env-var-external-secret.yaml
  4. 3
      typescript/infra/helm/warp-routes/values.yaml
  5. 13
      typescript/infra/scripts/warp-routes/deploy-warp-monitor.ts
  6. 36
      typescript/infra/scripts/warp-routes/monitor-warp-routes-balances.ts
  7. 3
      typescript/infra/src/utils/gcloud.ts
  8. 7
      typescript/infra/src/warp/helm.ts

@ -1,14 +1,13 @@
import {
ChainMap,
IsmType,
RouterConfig,
TokenRouterConfig,
TokenType,
buildAggregationIsmConfigs,
} from '@hyperlane-xyz/sdk';
import { symmetricDifference } from '@hyperlane-xyz/utils';
import { getRegistry } from '../../chains.js';
import { getRegistry as getMainnet3Registry } from '../../chains.js';
const lockbox = '0xC8140dA31E6bCa19b287cC35531c2212763C2059';
const xERC20 = '0x2416092f143378750bb29b79eD961ab195CcEea5';
@ -118,7 +117,7 @@ const ezEthSafes: Record<string, string> = {
export const getRenzoEZETHWarpConfig = async (): Promise<
ChainMap<TokenRouterConfig>
> => {
const registry = await getRegistry();
const registry = await getMainnet3Registry();
const validatorDiff = symmetricDifference(
new Set(chainsToDeploy),

@ -53,6 +53,13 @@ app.kubernetes.io/name: {{ include "hyperlane.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
The name of the ClusterSecretStore
*/}}
{{- define "hyperlane.cluster-secret-store.name" -}}
{{- default "external-secrets-gcp-cluster-secret-store" .Values.externalSecrets.clusterSecretStore }}
{{- end }}
{{/*
The warp-routes container
*/}}
@ -70,4 +77,9 @@ The warp-routes container
- "10000"
- -f
- {{ .Values.configFilePath }}
- -e
- {{ .Values.environment}}
envFrom:
- secretRef:
name: {{ include "hyperlane.fullname" . }}-secret
{{- end }}

@ -0,0 +1,44 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "hyperlane.fullname" . }}-external-secret
labels:
{{- include "hyperlane.labels" . | nindent 4 }}
spec:
secretStoreRef:
name: {{ include "hyperlane.cluster-secret-store.name" . }}
kind: ClusterSecretStore
refreshInterval: "1h"
# The secret that will be created
target:
name: {{ include "hyperlane.fullname" . }}-secret
template:
type: Opaque
metadata:
labels:
{{- include "hyperlane.labels" . | nindent 10 }}
annotations:
update-on-redeploy: "{{ now }}"
data:
GCP_SECRET_OVERRIDES_ENABLED: "true"
{{/*
* For each network, create an environment variable with the RPC endpoint.
* The templating of external-secrets will use the data section below to know how
* to replace the correct value in the created secret.
*/}}
{{- range .Values.hyperlane.chains }}
GCP_SECRET_OVERRIDE_{{ $.Values.hyperlane.runEnv | upper }}_RPC_ENDPOINTS_{{ . | upper }}: {{ printf "'{{ .%s_rpcs | toString }}'" . }}
{{- end }}
data:
- secretKey: deployer_key
remoteRef:
key: {{ printf "hyperlane-%s-key-deployer" .Values.hyperlane.runEnv }}
{{/*
* For each network, load the secret in GCP secret manager with the form: environment-rpc-endpoint-network,
* and associate it with the secret key networkname_rpc.
*/}}
{{- range .Values.hyperlane.chains }}
- secretKey: {{ printf "%s_rpcs" . }}
remoteRef:
key: {{ printf "%s-rpc-endpoints-%s" $.Values.hyperlane.runEnv . }}
{{- end }}

@ -4,5 +4,8 @@ image:
hyperlane:
runEnv: mainnet3
context: hyperlane
chains: []
nameOverride: ''
fullnameOverride: ''
externalSecrets:
clusterSecretStore:

@ -1,8 +1,9 @@
import yargs from 'yargs';
import { Contexts } from '../../config/contexts.js';
import { HelmCommand } from '../../src/utils/helm.js';
import { WarpRouteMonitorHelmManager } from '../../src/warp/helm.js';
import { assertCorrectKubeContext } from '../agent-utils.js';
import { assertCorrectKubeContext, getAgentConfig } from '../agent-utils.js';
import { getEnvironmentConfig } from '../core-utils.js';
async function main() {
@ -16,9 +17,15 @@ async function main() {
.string('filePath')
.parse();
await assertCorrectKubeContext(getEnvironmentConfig('mainnet3'));
const environment = 'mainnet3';
await assertCorrectKubeContext(getEnvironmentConfig(environment));
const agentConfig = getAgentConfig(Contexts.Hyperlane, environment);
const helmManager = new WarpRouteMonitorHelmManager(filePath, 'mainnet3');
const helmManager = new WarpRouteMonitorHelmManager(
filePath,
environment,
agentConfig.environmentChainNames,
);
await helmManager.runHelmCommand(HelmCommand.InstallOrUpgrade);
}

@ -1,7 +1,6 @@
import { SystemProgram } from '@solana/web3.js';
import { ethers } from 'ethers';
import { Gauge, Registry } from 'prom-client';
import yargs from 'yargs';
import {
HypXERC20Lockbox__factory,
@ -12,6 +11,7 @@ import {
import { ERC20__factory } from '@hyperlane-xyz/core';
import {
ChainMap,
ChainMetadata,
ChainName,
CosmNativeTokenAdapter,
CwNativeTokenAdapter,
@ -28,9 +28,10 @@ import {
rootLogger,
} from '@hyperlane-xyz/utils';
import { getChainMetadata } from '../../config/registry.js';
import { startMetricsServer } from '../../src/utils/metrics.js';
import { readYaml } from '../../src/utils/utils.js';
import { getArgs } from '../agent-utils.js';
import { getEnvironmentConfig } from '../core-utils.js';
const logger = rootLogger.child({ module: 'warp-balance-monitor' });
@ -76,7 +77,7 @@ export function readWarpRouteConfig(filePath: string) {
}
async function main(): Promise<boolean> {
const { checkFrequency, filePath } = await yargs(process.argv.slice(2))
const { checkFrequency, filePath, environment } = await getArgs()
.describe('checkFrequency', 'frequency to check balances in ms')
.demandOption('checkFrequency')
.alias('v', 'checkFrequency') // v as in Greek letter nu
@ -95,6 +96,10 @@ async function main(): Promise<boolean> {
const tokenConfig: WarpRouteConfig =
readWarpRouteConfig(filePath).data.config;
const envConfig = getEnvironmentConfig(environment);
const registry = await envConfig.getRegistry();
const chainMetadata = await registry.getMetadata();
// TODO: eventually support token balance checks for xERC20 token type also
if (
Object.values(tokenConfig).some(
@ -103,9 +108,9 @@ async function main(): Promise<boolean> {
token.type === TokenType.XERC20Lockbox,
)
) {
await checkXERC20Limits(checkFrequency, tokenConfig);
await checkXERC20Limits(checkFrequency, tokenConfig, chainMetadata);
} else {
await checkTokenBalances(checkFrequency, tokenConfig);
await checkTokenBalances(checkFrequency, tokenConfig, chainMetadata);
}
return true;
@ -299,8 +304,9 @@ export function updateXERC20LimitsMetrics(xERC20Limits: ChainMap<xERC20Limit>) {
async function getXERC20Limits(
tokenConfig: WarpRouteConfig,
chainMetadata: ChainMap<ChainMetadata>,
): Promise<ChainMap<xERC20Limit>> {
const multiProtocolProvider = new MultiProtocolProvider(getChainMetadata());
const multiProtocolProvider = new MultiProtocolProvider(chainMetadata);
const output = objMap(
tokenConfig,
@ -330,17 +336,13 @@ async function getXERC20Limits(
const xerc20 = IXERC20__factory.connect(xerc20Address, provider);
return getXERC20Limit(routerAddress, xerc20, token.decimals);
}
default:
throw new Error(`Unsupported token type ${token.type}`);
}
break;
}
default:
throw new Error(`Unsupported protocol type ${token.protocolType}`);
}
return {
chain: chain,
mint: 0,
mintMax: 0,
burn: 0,
burnMax: 0,
};
},
);
@ -367,10 +369,11 @@ const getXERC20Limit = async (
async function checkXERC20Limits(
checkFrequency: number,
tokenConfig: WarpRouteConfig,
chainMetadata: ChainMap<ChainMetadata>,
) {
setInterval(async () => {
try {
const xERC20Limits = await getXERC20Limits(tokenConfig);
const xERC20Limits = await getXERC20Limits(tokenConfig, chainMetadata);
logger.info('xERC20 Limits:', xERC20Limits);
updateXERC20LimitsMetrics(xERC20Limits);
} catch (e) {
@ -382,9 +385,10 @@ async function checkXERC20Limits(
async function checkTokenBalances(
checkFrequency: number,
tokenConfig: WarpRouteConfig,
chainMetadata: ChainMap<ChainMetadata>,
) {
logger.info('Starting Warp Route balance monitor');
const multiProtocolProvider = new MultiProtocolProvider(getChainMetadata());
const multiProtocolProvider = new MultiProtocolProvider(chainMetadata);
setInterval(async () => {
try {

@ -35,6 +35,7 @@ export async function fetchGCPSecret(
);
output = envVarOverride;
} else {
debugLog(`Fetching GCP secret with name ${secretName}`);
output = await fetchLatestGCPSecret(secretName);
}
@ -74,8 +75,10 @@ function tryGCPSecretFromEnvVariable(gcpSecretName: string) {
process.env.GCP_SECRET_OVERRIDES_ENABLED &&
process.env.GCP_SECRET_OVERRIDES_ENABLED.length > 0;
if (!overridingEnabled) {
debugLog('GCP secret overrides disabled');
return undefined;
}
debugLog('GCP secret overrides enabled');
const overrideEnvVarName = `GCP_SECRET_OVERRIDE_${gcpSecretName
.replaceAll('-', '_')
.toUpperCase()}`;

@ -13,6 +13,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager {
constructor(
readonly configFilePath: string,
readonly runEnv: DeployEnvironment,
readonly environmentChainNames: string[],
) {
super();
}
@ -26,10 +27,14 @@ export class WarpRouteMonitorHelmManager extends HelmManager {
return {
image: {
repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo',
tag: '38ff1c4-20240823-093934',
tag: 'fce6adf-20240905-094435',
},
configFilePath: pathRelativeToMonorepoRoot,
fullnameOverride: this.helmReleaseName,
environment: this.runEnv,
hyperlane: {
chains: this.environmentChainNames,
},
};
}

Loading…
Cancel
Save