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::{json::print_json_success, opts::TempoOpts};
8use foundry_common::{FoundryTransactionBuilder, shell};
9use foundry_config::{Chain, Eip1559FeeEstimatePreset};
10use foundry_wallets::{TempoAccessKeyConfig, WalletOpts, WalletSigner};
11use serde_json::Value;
12use tempo_alloy::TempoNetwork;
13
14pub use foundry_common::tempo::{TempoSponsor, TempoSponsorPreview, resolve_tempo_sponsor_signer};
15
16/// Prints a command result: the raw payload in JSON mode, the human rendering otherwise.
17pub(crate) fn print_payload<F>(payload: Value, human: F) -> Result<()>
18where
19    F: FnOnce(&Value) -> Result<()>,
20{
21    if shell::is_json() {
22        print_json_success(payload)?;
23    } else {
24        human(&payload)?;
25    }
26    Ok(())
27}
28
29pub(crate) fn print_expires(expires_at: Option<u64>) -> Result<()> {
30    if let Some(ts) = expires_at {
31        sh_status!("Transaction expires at unix timestamp {ts}")?;
32    }
33    Ok(())
34}
35
36/// Resolves a command signer, preferring an explicitly selected Tempo session.
37///
38/// Session resolution is fail-closed: when `--tempo.session` or `TEMPO_SESSION_ID` is set, wallet
39/// signer options are rejected by [`TempoOpts::session_signer_for_wallet`] instead of falling back
40/// to a long-lived signer.
41pub(crate) async fn resolve_session_or_wallet_signer(
42    tempo: &TempoOpts,
43    wallet: &WalletOpts,
44    chain_id: u64,
45) -> Result<(Option<WalletSigner>, Option<TempoAccessKeyConfig>)> {
46    match tempo.session_signer_for_wallet(wallet, chain_id)? {
47        Some(session) => Ok((Some(session.signer), Some(session.access_key))),
48        None => wallet.maybe_signer().await,
49    }
50}
51
52pub(crate) fn ensure_session_not_browser(tempo: &TempoOpts, browser: bool) -> Result<()> {
53    if browser && tempo.session_id()?.is_some() {
54        eyre::bail!("--tempo.session/TEMPO_SESSION_ID cannot be combined with --browser");
55    }
56    Ok(())
57}
58
59/// Fills a Tempo transaction request that was built outside [`crate::tx::CastTxBuilder`] before
60/// access-key signing.
61pub(crate) async fn fill_access_key_transaction<P>(
62    provider: &P,
63    tx: &mut <TempoNetwork as Network>::TransactionRequest,
64    access_key: &TempoAccessKeyConfig,
65    chain: Chain,
66    eip1559_fee_estimate: Eip1559FeeEstimatePreset,
67) -> Result<()>
68where
69    P: Provider<TempoNetwork>,
70{
71    tx.set_from(access_key.wallet_address);
72    tx.set_chain_id(chain.id());
73    tx.set_key_id(access_key.key_address);
74    tx.prepare_access_key_authorization(
75        provider,
76        access_key.wallet_address,
77        access_key.key_address,
78        access_key.key_authorization.as_ref(),
79    )
80    .await?;
81
82    if tx.nonce().is_none() {
83        tx.set_nonce(provider.get_transaction_count(access_key.wallet_address).await?);
84    }
85    fill_transaction_gas_fees(provider, tx, chain.is_legacy(), false, eip1559_fee_estimate).await?;
86    if tx.gas_limit().is_none() {
87        tx.set_gas_limit(provider.estimate_gas(tx.clone()).await?);
88    }
89
90    Ok(())
91}