Skip to content

Commit 587d234

Browse files
[feat]: Add Chain ID verification against RPC (#37)
* Chore: Add Chain ID verification against RPC * Fix: Config.service.ts validateChainIdFromRPC function * Style: Remove white spaces * Fix: Improve the way the chainID is validated to be called from the constructor * Fix: Clean and improve minor changes * Fix: Add isReady to main.ts * refactor: Minor formatting recover and improvement * chore: Add comment --------- Co-authored-by: Jorge Sanmiguel <[email protected]>
1 parent 75f6098 commit 587d234

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

src/config/config.service.ts

+41
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as yaml from 'js-yaml';
44
import dotenv from 'dotenv';
55
import { PRICING_SCHEMA, getConfigValidator } from './config.schema';
66
import { GlobalConfig, ChainConfig, AMBConfig, GetterGlobalConfig, SubmitterGlobalConfig, PersisterConfig, WalletGlobalConfig, GetterConfig, SubmitterConfig, WalletConfig, MonitorConfig, MonitorGlobalConfig, PricingConfig, PricingGlobalConfig } from './config.types';
7+
import { JsonRpcProvider } from 'ethers6';
78

89
@Injectable()
910
export class ConfigService {
@@ -15,6 +16,8 @@ export class ConfigService {
1516
readonly chainsConfig: Map<string, ChainConfig>;
1617
readonly ambsConfig: Map<string, AMBConfig>;
1718

19+
readonly isReady: Promise<void>;
20+
1821
constructor() {
1922
this.nodeEnv = this.loadNodeEnv();
2023

@@ -24,6 +27,16 @@ export class ConfigService {
2427
this.globalConfig = this.loadGlobalConfig();
2528
this.chainsConfig = this.loadChainsConfig();
2629
this.ambsConfig = this.loadAMBsConfig();
30+
31+
this.isReady = this.initialize();
32+
}
33+
34+
35+
// NOTE: The OnModuleInit hook is not being used as it does not guarantee the order in which it
36+
// is executed across services (i.e. there is no guarantee that the config service will be the
37+
// first to initialize). The `isReady` promise must be awaited on Relayer initialization.
38+
private async initialize(): Promise<void> {
39+
await this.validateChains(this.chainsConfig);
2740
}
2841

2942
private loadNodeEnv(): string {
@@ -154,6 +167,34 @@ export class ConfigService {
154167
return this.ambsConfig.get(amb)?.globalProperties[key];
155168
}
156169

170+
private async validateChains(chainsConfig: Map<string, ChainConfig>): Promise<void> {
171+
const validateChainIdFromRPC = async (rpc: string, expectedChainId: string): Promise<boolean> => {
172+
const provider = new JsonRpcProvider(rpc, undefined, { staticNetwork: true });
173+
try {
174+
const network = await provider.getNetwork();
175+
const actualChainId = network.chainId.toString();
176+
return actualChainId === expectedChainId;
177+
} catch (error) {
178+
return false;
179+
}
180+
};
181+
182+
const validationPromises = [];
183+
184+
for (const [chainId, config] of chainsConfig) {
185+
const validationPromise = async () => {
186+
const chainIdValidate = await validateChainIdFromRPC(config.rpc, chainId);
187+
if (!chainIdValidate) {
188+
throw new Error(`Error validating the Chain ID for chain ${chainId}`);
189+
}
190+
};
191+
validationPromises.push(validationPromise());
192+
}
193+
194+
await Promise.all(validationPromises);
195+
}
196+
197+
157198

158199
// Formatting helpers
159200
// ********************************************************************************************

src/main.ts

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ async function bootstrap() {
2929

3030
logLoadedOptions(configService, loggerService);
3131

32+
await configService.isReady;
33+
3234
await app.listen(configService.globalConfig.port);
3335
}
3436
void bootstrap();

0 commit comments

Comments
 (0)