Skip to content

Commit

Permalink
[feat]: Add Chain ID verification against RPC (#37)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
ajimeno04 and jsanmigimeno authored Jul 2, 2024
1 parent 75f6098 commit 587d234
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/config/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as yaml from 'js-yaml';
import dotenv from 'dotenv';
import { PRICING_SCHEMA, getConfigValidator } from './config.schema';
import { GlobalConfig, ChainConfig, AMBConfig, GetterGlobalConfig, SubmitterGlobalConfig, PersisterConfig, WalletGlobalConfig, GetterConfig, SubmitterConfig, WalletConfig, MonitorConfig, MonitorGlobalConfig, PricingConfig, PricingGlobalConfig } from './config.types';
import { JsonRpcProvider } from 'ethers6';

@Injectable()
export class ConfigService {
Expand All @@ -15,6 +16,8 @@ export class ConfigService {
readonly chainsConfig: Map<string, ChainConfig>;
readonly ambsConfig: Map<string, AMBConfig>;

readonly isReady: Promise<void>;

constructor() {
this.nodeEnv = this.loadNodeEnv();

Expand All @@ -24,6 +27,16 @@ export class ConfigService {
this.globalConfig = this.loadGlobalConfig();
this.chainsConfig = this.loadChainsConfig();
this.ambsConfig = this.loadAMBsConfig();

this.isReady = this.initialize();
}


// NOTE: The OnModuleInit hook is not being used as it does not guarantee the order in which it
// is executed across services (i.e. there is no guarantee that the config service will be the
// first to initialize). The `isReady` promise must be awaited on Relayer initialization.
private async initialize(): Promise<void> {
await this.validateChains(this.chainsConfig);
}

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

private async validateChains(chainsConfig: Map<string, ChainConfig>): Promise<void> {
const validateChainIdFromRPC = async (rpc: string, expectedChainId: string): Promise<boolean> => {
const provider = new JsonRpcProvider(rpc, undefined, { staticNetwork: true });
try {
const network = await provider.getNetwork();
const actualChainId = network.chainId.toString();
return actualChainId === expectedChainId;
} catch (error) {
return false;
}
};

const validationPromises = [];

for (const [chainId, config] of chainsConfig) {
const validationPromise = async () => {
const chainIdValidate = await validateChainIdFromRPC(config.rpc, chainId);
if (!chainIdValidate) {
throw new Error(`Error validating the Chain ID for chain ${chainId}`);
}
};
validationPromises.push(validationPromise());
}

await Promise.all(validationPromises);
}



// Formatting helpers
// ********************************************************************************************
Expand Down
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ async function bootstrap() {

logLoadedOptions(configService, loggerService);

await configService.isReady;

await app.listen(configService.globalConfig.port);
}
void bootstrap();

0 comments on commit 587d234

Please sign in to comment.