miden_client_integration_tests/tests/agglayer/
mod.rs1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result};
4use miden_agglayer::create_bridge_account;
5use miden_client::Deserializable;
6use miden_client::account::{AccountFile, AccountId, AccountType};
7use miden_client::auth::RPO_FALCON_SCHEME_ID;
8use miden_client::crypto::FeltRng;
9use miden_client::keystore::Keystore;
10use miden_client::testing::common::{
11 FilesystemKeyStore,
12 TestClient,
13 insert_new_wallet,
14 wait_for_node,
15 wait_for_tx,
16};
17use miden_client::transaction::TransactionRequestBuilder;
18
19use crate::tests::config::ClientConfig;
20
21pub mod agglayer_bridge_in_out;
22mod agglayer_test_utils;
23pub mod ger;
24
25pub const MIDEN_AGGLAYER_NETWORK_ID: u32 = 77;
30
31pub struct AgglayerConfig {
41 pub bridge_admin: AccountFile,
42 pub ger_manager: AccountFile,
43 pub bridge: AccountFile,
44 pub faucet: AccountFile,
45}
46
47impl AgglayerConfig {
48 const BRIDGE_ADMIN_FILE: &str = "bridge_admin.mac";
50 const GER_MANAGER_FILE: &str = "ger_manager.mac";
51 const BRIDGE_FILE: &str = "bridge.mac";
52 const FAUCET_FILE: &str = "agglayer_faucet.mac";
53
54 pub fn from_env() -> Result<Option<Self>> {
57 match std::env::var("AGGLAYER_ACCOUNTS_DIR") {
58 Ok(dir) => {
59 let dir = PathBuf::from(dir);
60 let bridge_admin = Self::load_account_file(&dir, Self::BRIDGE_ADMIN_FILE)?;
61 let ger_manager = Self::load_account_file(&dir, Self::GER_MANAGER_FILE)?;
62 let bridge = Self::load_account_file(&dir, Self::BRIDGE_FILE)?;
63 let faucet = Self::load_account_file(&dir, Self::FAUCET_FILE)?;
64 Ok(Some(Self {
65 bridge_admin,
66 ger_manager,
67 bridge,
68 faucet,
69 }))
70 },
71 Err(_) => Ok(None),
72 }
73 }
74
75 pub fn bridge_admin_id(&self) -> AccountId {
76 self.bridge_admin.account.id()
77 }
78
79 pub fn ger_manager_id(&self) -> AccountId {
80 self.ger_manager.account.id()
81 }
82
83 pub fn bridge_id(&self) -> AccountId {
84 self.bridge.account.id()
85 }
86
87 pub fn faucet_id(&self) -> AccountId {
88 self.faucet.account.id()
89 }
90
91 pub async fn import_account(
94 &self,
95 account_id: AccountId,
96 client: &mut TestClient,
97 keystore: &FilesystemKeyStore,
98 ) -> Result<()> {
99 let account_file = [&self.bridge_admin, &self.ger_manager, &self.bridge, &self.faucet]
100 .into_iter()
101 .find(|f| f.account.id() == account_id)
102 .with_context(|| format!("account {account_id} not found in agglayer config"))?;
103
104 client
105 .import_account_by_id(account_id)
106 .await
107 .with_context(|| format!("failed to import account {account_id} from network"))?;
108
109 for secret_key in &account_file.auth_secret_keys {
110 keystore.add_key(secret_key, account_id).await.with_context(|| {
111 format!("failed to add key for account {account_id} to keystore")
112 })?;
113 }
114 Ok(())
115 }
116
117 fn load_account_file(dir: &Path, filename: &str) -> Result<AccountFile> {
118 let path = dir.join(filename);
119 let bytes =
120 std::fs::read(&path).with_context(|| format!("failed to read {}", path.display()))?;
121 AccountFile::read_from_bytes(&bytes)
122 .map_err(|e| anyhow::anyhow!("failed to deserialize {}: {}", path.display(), e))
123 }
124}
125
126pub struct ClientPair {
131 pub client: TestClient,
132 pub keystore: FilesystemKeyStore,
133}
134
135pub type CoreAccountIds = (AccountId, AccountId, AccountId);
137
138pub async fn create_agglayer_clients(
140 client_config: &ClientConfig,
141) -> Result<(ClientPair, ClientPair, ClientPair)> {
142 let (mut client, keystore) = client_config.clone().into_client().await?;
143 wait_for_node(&mut client).await;
144 client.sync_state().await?;
145 println!("[setup] Bridge admin client initialized");
146 let bridge_admin = ClientPair { client, keystore };
147
148 let (client, keystore) = ClientConfig::default()
149 .with_rpc_endpoint(client_config.rpc_endpoint())
150 .into_client()
151 .await?;
152 println!("[setup] GER manager client initialized");
153 let ger_manager = ClientPair { client, keystore };
154
155 let (client, keystore) = ClientConfig::default()
156 .with_rpc_endpoint(client_config.rpc_endpoint())
157 .into_client()
158 .await?;
159 println!("[setup] User client initialized");
160 let user = ClientPair { client, keystore };
161
162 Ok((bridge_admin, ger_manager, user))
163}
164
165pub async fn setup_core_accounts(
174 config: Option<&AgglayerConfig>,
175 bridge_admin: &mut ClientPair,
176 ger_manager: &mut ClientPair,
177 user: &mut ClientPair,
178) -> Result<CoreAccountIds> {
179 if let Some(config) = config {
180 println!("[setup] Loading core accounts from genesis");
181 println!("[setup] bridge admin: {}", config.bridge_admin_id());
182 println!("[setup] GER manager: {}", config.ger_manager_id());
183 println!("[setup] bridge: {}", config.bridge_id());
184
185 config
186 .import_account(
187 config.bridge_admin_id(),
188 &mut bridge_admin.client,
189 &bridge_admin.keystore,
190 )
191 .await?;
192 config
193 .import_account(config.ger_manager_id(), &mut ger_manager.client, &ger_manager.keystore)
194 .await?;
195
196 for pair in [&mut *bridge_admin, &mut *ger_manager, &mut *user] {
197 config
198 .import_account(config.bridge_id(), &mut pair.client, &pair.keystore)
199 .await?;
200 }
201
202 return Ok((config.bridge_admin_id(), config.ger_manager_id(), config.bridge_id()));
203 }
204
205 println!("[setup] Creating core accounts at runtime");
206
207 let (bridge_admin_account, ..) = insert_new_wallet(
209 &mut bridge_admin.client,
210 AccountType::Public,
211 &bridge_admin.keystore,
212 RPO_FALCON_SCHEME_ID,
213 )
214 .await?;
215 let (ger_manager_account, ..) = insert_new_wallet(
216 &mut ger_manager.client,
217 AccountType::Public,
218 &ger_manager.keystore,
219 RPO_FALCON_SCHEME_ID,
220 )
221 .await?;
222
223 let bridge_seed = bridge_admin.client.rng().draw_word();
226 let bridge_account = create_bridge_account(
227 bridge_seed,
228 bridge_admin_account.id(),
229 ger_manager_account.id(),
230 MIDEN_AGGLAYER_NETWORK_ID,
231 );
232 println!("[setup] bridge admin: {}", bridge_admin_account.id());
233 println!("[setup] GER manager: {}", ger_manager_account.id());
234 println!("[setup] bridge: {}", bridge_account.id());
235
236 for pair in [&mut *bridge_admin, &mut *ger_manager, &mut *user] {
237 pair.client.add_account(&bridge_account, false).await?;
238 }
239
240 let deploy_tx = TransactionRequestBuilder::new().build()?;
242 let tx_id = bridge_admin
243 .client
244 .submit_new_transaction(bridge_account.id(), deploy_tx)
245 .await?;
246 wait_for_tx(&mut bridge_admin.client, tx_id).await?;
247 println!("[setup] Bridge account deployed on-chain");
248
249 Ok((bridge_admin_account.id(), ger_manager_account.id(), bridge_account.id()))
250}