Skip to content

Commit fda06c0

Browse files
refactor: name every foreign chain by ForeignChain::label
Covers the avalanche and adi sections main added to ForeignChainsConfig, and applies review feedback from the earlier PRs in the stack: named structs in place of positional tuples in the probe tests, bare Given/When/Then markers, and comments that no longer restate the code.
1 parent 8d1c106 commit fda06c0

8 files changed

Lines changed: 153 additions & 65 deletions

File tree

crates/e2e-tests/src/foreign_chain_mock.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ impl MockServerExt {
7575
}
7676
}
7777

78+
/// Answered by every EVM mock regardless of the chain it stands in for, so a test probing one has
79+
/// to expect Base's id.
7880
pub const MOCK_EVM_CHAIN_ID: u64 = 8453;
79-
8081
pub const MOCK_BLOCK_HASH: &str =
8182
"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20";
8283
pub const MOCK_TX_ID: &str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";

crates/e2e-tests/tests/foreign_chain_probe.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const WRONG_NETWORK_PROVIDER: &str = "wrong-network";
1515
/// Any chain id the mock does not serve, so the probe reads a network mismatch.
1616
const ANOTHER_NETWORK: u64 = 1;
1717

18-
fn base_config(rpc_url: &str, expected_network: u64, provider: &str) -> ForeignChainConfig {
18+
fn base_chain_config(rpc_url: &str, expected_network: u64, provider: &str) -> ForeignChainConfig {
1919
ForeignChainConfig {
2020
timeout_sec: NonZeroU64::new(10).unwrap(),
2121
max_retries: NonZeroU64::new(1).unwrap(),
@@ -30,36 +30,41 @@ fn base_config(rpc_url: &str, expected_network: u64, provider: &str) -> ForeignC
3030
}
3131
}
3232

33-
/// Both nodes configure one provider, so only `healthy` separates them.
33+
/// Both nodes point one Base provider at the same mock and differ only in the fingerprint they
34+
/// expect, so the healthy gauge is the only one that separates them.
3435
#[tokio::test]
3536
#[expect(non_snake_case)]
3637
async fn foreign_chain_probe__should_publish_provider_health_on_startup() {
37-
// given
38+
// Given
3839
let server = MockServer::start();
3940
setup_evm_mock(&server, MockAuthExpectation::None);
4041
let url = server.url("/");
4142

42-
// when
43+
// When
4344
let (cluster, _running) = common::must_setup_cluster(
4445
common::FOREIGN_CHAIN_PROBE_PORT_SEED,
4546
|c: &mut e2e_tests::MpcClusterConfig| {
4647
c.num_nodes = 2;
4748
c.threshold = 2;
4849
c.foreign_chains.node_configs = vec![
4950
ForeignChainsConfig {
50-
base: Some(base_config(&url, MOCK_EVM_CHAIN_ID, HEALTHY_PROVIDER)),
51+
base: Some(base_chain_config(&url, MOCK_EVM_CHAIN_ID, HEALTHY_PROVIDER)),
5152
..Default::default()
5253
},
5354
ForeignChainsConfig {
54-
base: Some(base_config(&url, ANOTHER_NETWORK, WRONG_NETWORK_PROVIDER)),
55+
base: Some(base_chain_config(
56+
&url,
57+
ANOTHER_NETWORK,
58+
WRONG_NETWORK_PROVIDER,
59+
)),
5560
..Default::default()
5661
},
5762
];
5863
},
5964
)
6065
.await;
6166

62-
// then
67+
// Then
6368
common::wait_metric_on_nodes(
6469
&cluster,
6570
&[0, 1],

crates/foreign-chain-health-check/src/lib.rs

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use foreign_chain_rpc_interfaces::sui::GrpcSuiClient;
3131
use http::{HeaderName, HeaderValue};
3232
use mpc_node_config::foreign_chains::RpcProviderName;
3333
use mpc_node_config::{ForeignChainConfig, ForeignChainProviderConfig, ForeignChainsConfig};
34+
use near_mpc_contract_interface::types::ForeignChain;
3435

3536
pub use network::Network;
3637
pub use results::{ProviderResult, Status};
@@ -57,71 +58,111 @@ pub async fn check_all_providers(
5758
mark_not_configured("ethereum", &mut out);
5859
}
5960
if let Some(cfg) = &fc.base {
60-
run_evm::<Base>("base", cfg, golden.base, network, &mut out).await;
61+
run_evm::<Base>(ForeignChain::Base, cfg, golden.base, network, &mut out).await;
6162
} else {
62-
mark_not_configured("base", &mut out);
63+
mark_not_configured(ForeignChain::Base, &mut out);
6364
}
6465
if let Some(cfg) = &fc.bnb {
65-
run_evm::<Bnb>("bnb", cfg, golden.bnb, network, &mut out).await;
66+
run_evm::<Bnb>(ForeignChain::Bnb, cfg, golden.bnb, network, &mut out).await;
6667
} else {
67-
mark_not_configured("bnb", &mut out);
68+
mark_not_configured(ForeignChain::Bnb, &mut out);
6869
}
6970
if let Some(cfg) = &fc.arbitrum {
70-
run_evm::<Arbitrum>("arbitrum", cfg, golden.arbitrum, network, &mut out).await;
71+
run_evm::<Arbitrum>(
72+
ForeignChain::Arbitrum,
73+
cfg,
74+
golden.arbitrum,
75+
network,
76+
&mut out,
77+
)
78+
.await;
7179
} else {
72-
mark_not_configured("arbitrum", &mut out);
80+
mark_not_configured(ForeignChain::Arbitrum, &mut out);
7381
}
7482
if let Some(cfg) = &fc.polygon {
75-
run_evm::<Polygon>("polygon", cfg, golden.polygon, network, &mut out).await;
83+
run_evm::<Polygon>(
84+
ForeignChain::Polygon,
85+
cfg,
86+
golden.polygon,
87+
network,
88+
&mut out,
89+
)
90+
.await;
7691
} else {
77-
mark_not_configured("polygon", &mut out);
92+
mark_not_configured(ForeignChain::Polygon, &mut out);
7893
}
7994
if let Some(cfg) = &fc.hyper_evm {
80-
run_evm::<HyperEvm>("hyper_evm", cfg, golden.hyper_evm, network, &mut out).await;
95+
run_evm::<HyperEvm>(
96+
ForeignChain::HyperEvm,
97+
cfg,
98+
golden.hyper_evm,
99+
network,
100+
&mut out,
101+
)
102+
.await;
81103
} else {
82-
mark_not_configured("hyper_evm", &mut out);
104+
mark_not_configured(ForeignChain::HyperEvm, &mut out);
83105
}
84106
if let Some(cfg) = &fc.avalanche {
85-
run_evm::<Avalanche>("avalanche", cfg, golden.avalanche, network, &mut out).await;
107+
run_evm::<Avalanche>(
108+
ForeignChain::Avalanche,
109+
cfg,
110+
golden.avalanche,
111+
network,
112+
&mut out,
113+
)
114+
.await;
86115
} else {
87-
mark_not_configured("avalanche", &mut out);
116+
mark_not_configured(ForeignChain::Avalanche, &mut out);
88117
}
89118
if let Some(cfg) = &fc.adi {
90-
run_evm::<Adi>("adi", cfg, golden.adi, network, &mut out).await;
119+
run_evm::<Adi>(ForeignChain::Adi, cfg, golden.adi, network, &mut out).await;
91120
} else {
92-
mark_not_configured("adi", &mut out);
121+
mark_not_configured(ForeignChain::Adi, &mut out);
93122
}
94123
if let Some(cfg) = &fc.abstract_chain {
95-
run_evm::<Abstract>("abstract", cfg, golden.abstract_chain, network, &mut out).await;
124+
run_evm::<Abstract>(
125+
ForeignChain::Abstract,
126+
cfg,
127+
golden.abstract_chain,
128+
network,
129+
&mut out,
130+
)
131+
.await;
96132
} else {
97-
mark_not_configured("abstract", &mut out);
133+
mark_not_configured(ForeignChain::Abstract, &mut out);
98134
}
99135
if let Some(cfg) = &fc.bitcoin {
100136
run_bitcoin(cfg, golden.bitcoin, network, &mut out).await;
101137
} else {
102-
mark_not_configured("bitcoin", &mut out);
138+
mark_not_configured(ForeignChain::Bitcoin, &mut out);
103139
}
104140
if let Some(cfg) = &fc.starknet {
105141
run_starknet(cfg, golden.starknet, network, &mut out).await;
106142
} else {
107-
mark_not_configured("starknet", &mut out);
143+
mark_not_configured(ForeignChain::Starknet, &mut out);
108144
}
109145
if let Some(cfg) = &fc.aptos {
110146
run_aptos(cfg, golden.aptos, network, &mut out).await;
111147
} else {
112-
mark_not_configured("aptos", &mut out);
148+
mark_not_configured(ForeignChain::Aptos, &mut out);
113149
}
114150
if let Some(cfg) = &fc.sui {
115151
run_sui(cfg, golden.sui, network, &mut out).await;
116152
} else {
117-
mark_not_configured("sui", &mut out);
153+
mark_not_configured(ForeignChain::Sui, &mut out);
118154
}
119155

120156
// Configured but not yet supported by the node (see verify_foreign_tx/sign.rs).
121157
if let Some(cfg) = &fc.solana {
122-
mark_skipped("solana", cfg, "not yet supported by the node", &mut out);
158+
mark_skipped(
159+
ForeignChain::Solana,
160+
cfg,
161+
"not yet supported by the node",
162+
&mut out,
163+
);
123164
} else {
124-
mark_not_configured("solana", &mut out);
165+
mark_not_configured(ForeignChain::Solana, &mut out);
125166
}
126167

127168
out
@@ -172,7 +213,7 @@ async fn run_check(timeout: Duration, fut: impl Future<Output = anyhow::Result<(
172213
}
173214

174215
async fn run_evm<Chain: EvmChain + Send + Sync>(
175-
chain: &'static str,
216+
chain: ForeignChain,
176217
cfg: &ForeignChainConfig,
177218
vector: Option<BlockHashVector>,
178219
network: Network,
@@ -194,7 +235,7 @@ async fn run_evm<Chain: EvmChain + Send + Sync>(
194235
}
195236
};
196237
out.push(ProviderResult {
197-
chain,
238+
chain: chain.label(),
198239
provider: provider_name(name),
199240
status,
200241
});
@@ -208,7 +249,12 @@ async fn run_bitcoin(
208249
out: &mut Vec<ProviderResult>,
209250
) {
210251
let Some(vector) = vector else {
211-
mark_skipped("bitcoin", cfg, &no_reference_reason(network), out);
252+
mark_skipped(
253+
ForeignChain::Bitcoin,
254+
cfg,
255+
&no_reference_reason(network),
256+
out,
257+
);
212258
return;
213259
};
214260
let timeout = timeout_of(cfg);
@@ -223,7 +269,7 @@ async fn run_bitcoin(
223269
}
224270
};
225271
out.push(ProviderResult {
226-
chain: "bitcoin",
272+
chain: ForeignChain::Bitcoin.label(),
227273
provider: provider_name(name),
228274
status,
229275
});
@@ -237,7 +283,12 @@ async fn run_starknet(
237283
out: &mut Vec<ProviderResult>,
238284
) {
239285
let Some(vector) = vector else {
240-
mark_skipped("starknet", cfg, &no_reference_reason(network), out);
286+
mark_skipped(
287+
ForeignChain::Starknet,
288+
cfg,
289+
&no_reference_reason(network),
290+
out,
291+
);
241292
return;
242293
};
243294
let timeout = timeout_of(cfg);
@@ -252,7 +303,7 @@ async fn run_starknet(
252303
}
253304
};
254305
out.push(ProviderResult {
255-
chain: "starknet",
306+
chain: ForeignChain::Starknet.label(),
256307
provider: provider_name(name),
257308
status,
258309
});
@@ -266,7 +317,7 @@ async fn run_aptos(
266317
out: &mut Vec<ProviderResult>,
267318
) {
268319
let Some(vector) = vector else {
269-
mark_skipped("aptos", cfg, &no_reference_reason(network), out);
320+
mark_skipped(ForeignChain::Aptos, cfg, &no_reference_reason(network), out);
270321
return;
271322
};
272323
let timeout = timeout_of(cfg);
@@ -291,7 +342,7 @@ async fn run_aptos(
291342
}
292343
};
293344
out.push(ProviderResult {
294-
chain: "aptos",
345+
chain: ForeignChain::Aptos.label(),
295346
provider: provider_name(name),
296347
status,
297348
});
@@ -309,7 +360,7 @@ async fn run_sui(
309360
out: &mut Vec<ProviderResult>,
310361
) {
311362
let Some(vector) = vector else {
312-
mark_skipped("sui", cfg, &no_reference_reason(network), out);
363+
mark_skipped(ForeignChain::Sui, cfg, &no_reference_reason(network), out);
313364
return;
314365
};
315366
let timeout = timeout_of(cfg);
@@ -319,7 +370,7 @@ async fn run_sui(
319370
Ok(client) => run_check(timeout, checks::check_sui(client, vector.chain_id)).await,
320371
};
321372
out.push(ProviderResult {
322-
chain: "sui",
373+
chain: ForeignChain::Sui.label(),
323374
provider: provider_name(name),
324375
status,
325376
});
@@ -344,21 +395,25 @@ fn prepare_sui(
344395
}
345396

346397
fn mark_skipped(
347-
chain: &'static str,
398+
chain: ForeignChain,
348399
cfg: &ForeignChainConfig,
349400
reason: &str,
350401
out: &mut Vec<ProviderResult>,
351402
) {
352403
for name in cfg.providers.keys() {
353-
out.push(ProviderResult::skipped(chain, provider_name(name), reason));
404+
out.push(ProviderResult::skipped(
405+
chain.label(),
406+
provider_name(name),
407+
reason,
408+
));
354409
}
355410
}
356411

357412
/// A chain absent from the config has no providers to enumerate; emit one
358413
/// placeholder [`ProviderResult`] so it still appears in the returned results.
359-
fn mark_not_configured(chain: &'static str, out: &mut Vec<ProviderResult>) {
414+
fn mark_not_configured(chain: ForeignChain, out: &mut Vec<ProviderResult>) {
360415
out.push(ProviderResult::skipped(
361-
chain,
416+
chain.label(),
362417
"-".to_string(),
363418
"not configured",
364419
));

crates/near-mpc-contract-interface/src/types/foreign_chain.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,7 @@ pub enum ForeignChain {
13901390
}
13911391

13921392
impl ForeignChain {
1393+
/// The chain's key in an operator's `foreign_chains` config, also used as its metric label.
13931394
pub fn label(&self) -> &'static str {
13941395
match self {
13951396
Self::Solana => "solana",

crates/node-config/src/foreign_chains.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ ckd:
737737
polygon: Some(section()),
738738
aptos: Some(section()),
739739
sui: Some(section()),
740+
avalanche: Some(section()),
741+
adi: Some(section()),
740742
};
741743

742744
// When

0 commit comments

Comments
 (0)