Skip to content

Commit ac21ff7

Browse files
committed
handy chain init util func
1 parent 0e605cd commit ac21ff7

File tree

7 files changed

+97
-8
lines changed

7 files changed

+97
-8
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
TIMEBOOST_KEY_MANAGER_MNEMONIC="test test test test test test test test test test test junk"
2+
TIMEBOOST_KEY_MANAGER_ACCOUNT_INDEX=0

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ rust-version = "1.85.0"
2929

3030
[workspace.dependencies]
3131
aes-gcm = { version = "0.10.3" }
32-
alloy = { version = "1.0", features = ["default", "arbitrary", "k256", "serde", "rlp", "node-bindings", "getrandom"] }
32+
alloy = { version = "1.0", features = ["default", "arbitrary", "k256", "serde", "rlp", "node-bindings", "getrandom", "signer-mnemonic"] }
3333
alloy-chains = "0.2"
3434
# derive feature is not exposed via `alloy`, thus has to explicitly declare here
3535
alloy-rlp = { version = "0.3.12", features = ["derive"] }

timeboost-contract/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ rust-version.workspace = true
77

88
[dependencies]
99
alloy = { workspace = true }
10+
anyhow = { workspace = true }
11+
dotenvy = "0.15"
1012
tracing = { workspace = true }
1113
tokio = { workspace = true }
1214

timeboost-contract/src/deployer.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,14 @@ pub async fn deploy_key_manager_contract(
4545

4646
#[cfg(test)]
4747
mod tests {
48-
use crate::{KeyManager, deployer::deploy_key_manager_contract};
49-
use alloy::{primitives::Address, providers::ProviderBuilder};
48+
use alloy::providers::WalletProvider;
49+
50+
use crate::KeyManager;
5051

5152
#[tokio::test]
5253
async fn test_key_manager_deployment() {
53-
let provider = ProviderBuilder::new().connect_anvil_with_wallet();
54-
let manager = Address::random();
55-
let addr = deploy_key_manager_contract(&provider, manager)
56-
.await
57-
.unwrap();
54+
let (provider, addr) = crate::init_test_chain().await.unwrap();
55+
let manager = provider.default_signer_address();
5856
let contract = KeyManager::new(addr, provider);
5957

6058
// try read from the contract storage

timeboost-contract/src/lib.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,46 @@
22
//!
33
//! This crate provides Rust bindings and API to interact with smart contracts,
44
5+
use alloy::{
6+
primitives::Address,
7+
providers::{ProviderBuilder, WalletProvider},
8+
transports::http::reqwest::Url,
9+
};
10+
use anyhow::Result;
11+
512
// Include the generated contract bindings
613
// The build script auto-detects contracts and generates bindings in src/bindings/
714
pub mod bindings;
815
pub mod deployer;
16+
pub mod provider;
917

1018
// We manually re-export the type here carefully due to alloy's lack of shared type:
1119
// tracking issue: https://github.com/foundry-rs/foundry/issues/10153
1220
pub use bindings::{erc1967proxy::ERC1967Proxy, keymanager::KeyManager};
21+
use provider::{HttpProviderWithWallet, TestProviderWithWallet, build_provider};
22+
23+
/// Connect to a real blockchain, deploy the KeyManager contract, set the
24+
/// `TIMEBOOST_KEY_MANAGER_MNEMONIC` as the manager.
25+
/// Returns the (wallet provider, KeyManager address).
26+
pub async fn init_chain(chain: Url) -> Result<(HttpProviderWithWallet, Address)> {
27+
dotenvy::dotenv()?;
28+
29+
let mnemonic = dotenvy::var("TIMEBOOST_KEY_MANAGER_MNEMONIC")?;
30+
let account_idx = dotenvy::var("TIMEBOOST_KEY_ACCOUNT_INDEX")?.parse::<u32>()?;
31+
let provider = build_provider(mnemonic, account_idx, chain);
32+
33+
let km_addr =
34+
deployer::deploy_key_manager_contract(&provider, provider.default_signer_address()).await?;
35+
36+
Ok((provider, km_addr))
37+
}
38+
39+
/// Similar to [`init_chain()`] but spawn a local test chain and deploy contracts there instead.
40+
pub async fn init_test_chain() -> Result<(TestProviderWithWallet, Address)> {
41+
// this provider wraps both the test chain instance (exit on drop), and the wallet provider
42+
let provider = ProviderBuilder::new().connect_anvil_with_wallet();
43+
let km_addr =
44+
deployer::deploy_key_manager_contract(&provider, provider.default_signer_address()).await?;
45+
46+
Ok((provider, km_addr))
47+
}

timeboost-contract/src/provider.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Helper functions to build Ethereum [providers](https://docs.rs/alloy/latest/alloy/providers/trait.Provider.html)
2+
//! Partial Credit: <https://github.com/EspressoSystems/espresso-network/tree/main/contracts/rust/deployer>
3+
4+
use alloy::{
5+
network::{Ethereum, EthereumWallet},
6+
providers::{
7+
ProviderBuilder, RootProvider,
8+
fillers::{FillProvider, JoinFill, WalletFiller},
9+
layers::AnvilProvider,
10+
utils::JoinedRecommendedFillers,
11+
},
12+
signers::local::{MnemonicBuilder, PrivateKeySigner, coins_bip39::English},
13+
transports::http::reqwest::Url,
14+
};
15+
16+
/// Type alias that connects to providers with recommended fillers and wallet
17+
/// use `<HttpProviderWithWallet as WalletProvider>::wallet()` to access internal wallet
18+
/// use `<HttpProviderWithWallet as WalletProvider>::default_signer_address(&provider)` to get
19+
/// wallet address
20+
pub type HttpProviderWithWallet = FillProvider<
21+
JoinFill<JoinedRecommendedFillers, WalletFiller<EthereumWallet>>,
22+
RootProvider,
23+
Ethereum,
24+
>;
25+
26+
pub type TestProviderWithWallet = FillProvider<
27+
JoinFill<JoinedRecommendedFillers, WalletFiller<EthereumWallet>>,
28+
AnvilProvider<RootProvider>,
29+
Ethereum,
30+
>;
31+
32+
/// Build a local signer from wallet mnemonic and account index
33+
pub fn build_signer(mnemonic: String, account_index: u32) -> PrivateKeySigner {
34+
MnemonicBuilder::<English>::default()
35+
.phrase(mnemonic)
36+
.index(account_index)
37+
.expect("wrong mnemonic or index")
38+
.build()
39+
.expect("fail to build signer")
40+
}
41+
42+
/// a handy thin wrapper around wallet builder and provider builder that directly
43+
/// returns an instantiated `Provider` with default fillers with wallet, ready to send tx
44+
pub fn build_provider(mnemonic: String, account_index: u32, url: Url) -> HttpProviderWithWallet {
45+
let signer = build_signer(mnemonic, account_index);
46+
let wallet = EthereumWallet::from(signer);
47+
ProviderBuilder::new().wallet(wallet).connect_http(url)
48+
}

0 commit comments

Comments
 (0)