Skip to main content

cast/
tempo.rs

1//! Tempo transaction helpers used by Cast-facing commands.
2
3use crate::tx::fill_transaction_gas_fees;
4use alloy_network::{Network, TransactionBuilder};
5use alloy_provider::Provider;
6use eyre::Result;
7use foundry_cli::opts::TempoOpts;
8use foundry_common::FoundryTransactionBuilder;
9use foundry_config::Chain;
10use foundry_wallets::{TempoAccessKeyConfig, WalletOpts, WalletSigner};
11use tempo_alloy::TempoNetwork;
12
13pub use foundry_common::tempo::{TempoSponsor, TempoSponsorPreview, resolve_tempo_sponsor_signer};
14
15pub(crate) fn print_expires(expires_at: Option<u64>) -> Result<()> {
16    if let Some(ts) = expires_at {
17        sh_status!("Transaction expires at unix timestamp {ts}")?;
18    }
19    Ok(())
20}
21
22/// Resolves a command signer, preferring an explicitly selected Tempo session.
23///
24/// Session resolution is fail-closed: when `--tempo.session` or `TEMPO_SESSION_ID` is set, wallet
25/// signer options are rejected by [`TempoOpts::session_signer_for_wallet`] instead of falling back
26/// to a long-lived signer.
27pub(crate) async fn resolve_session_or_wallet_signer(
28    tempo: &TempoOpts,
29    wallet: &WalletOpts,
30    chain_id: u64,
31) -> Result<(Option<WalletSigner>, Option<TempoAccessKeyConfig>)> {
32    match tempo.session_signer_for_wallet(wallet, chain_id)? {
33        Some(session) => Ok((Some(session.signer), Some(session.access_key))),
34        None => wallet.maybe_signer().await,
35    }
36}
37
38pub(crate) fn ensure_session_not_browser(tempo: &TempoOpts, browser: bool) -> Result<()> {
39    if browser && tempo.session_id()?.is_some() {
40        eyre::bail!("--tempo.session/TEMPO_SESSION_ID cannot be combined with --browser");
41    }
42    Ok(())
43}
44
45/// Fills a Tempo transaction request that was built outside [`crate::tx::CastTxBuilder`] before
46/// access-key signing.
47pub(crate) async fn fill_access_key_transaction<P>(
48    provider: &P,
49    tx: &mut <TempoNetwork as Network>::TransactionRequest,
50    access_key: &TempoAccessKeyConfig,
51    chain: Chain,
52) -> Result<()>
53where
54    P: Provider<TempoNetwork>,
55{
56    tx.set_from(access_key.wallet_address);
57    tx.set_chain_id(chain.id());
58    tx.set_key_id(access_key.key_address);
59    tx.prepare_access_key_authorization(
60        provider,
61        access_key.wallet_address,
62        access_key.key_address,
63        access_key.key_authorization.as_ref(),
64    )
65    .await?;
66
67    if tx.nonce().is_none() {
68        tx.set_nonce(provider.get_transaction_count(access_key.wallet_address).await?);
69    }
70    fill_transaction_gas_fees(provider, tx, chain.is_legacy(), false).await?;
71    if tx.gas_limit().is_none() {
72        tx.set_gas_limit(provider.estimate_gas(tx.clone()).await?);
73    }
74
75    Ok(())
76}