Skip to main content

cast/cmd/
tempo.rs

1use alloy_primitives::Address;
2use alloy_signer_local::PrivateKeySigner;
3use clap::Parser;
4use eyre::Result;
5use foundry_common::tempo::{EnsureAccessKeyConfig, decode_key_authorization, ensure_access_key};
6use tempo_alloy::accounts::TempoAccountsStore;
7use tempo_primitives::transaction::SignedKeyAuthorization;
8
9/// Tempo wallet integration commands.
10#[derive(Debug, Parser)]
11#[allow(
12    clippy::large_enum_variant,
13    reason = "parsed once; retaining PrivateKeySigner keeps access-key input typed and redacted"
14)]
15pub enum TempoSubcommand {
16    /// Authorize a new access key against your Tempo wallet via wallet.tempo.
17    ///
18    /// Persists the key to `$TEMPO_HOME/wallet/store.json` (default
19    /// `~/.tempo/wallet/store.json`). Also runs automatically on a 402 from a
20    /// Tempo RPC when no local key is configured.
21    ///
22    /// Env: `TEMPO_HOME`, `TEMPO_CLI_AUTH_URL` (override auth service).
23    Login {
24        /// Chain ID to authorize the key for. Defaults to Tempo mainnet (4217).
25        #[arg(long, default_value_t = 4217)]
26        chain_id: u64,
27
28        /// Print the authorization URL to stderr instead of opening a browser.
29        #[arg(long)]
30        no_browser: bool,
31    },
32
33    /// Import a signed secp256k1 access key into the Tempo Accounts store.
34    ///
35    /// The signed authorization may be pending or already provisioned. The
36    /// access-key private key is persisted to `store.json`; the authorizing
37    /// root key is never stored.
38    ImportAccessKey {
39        /// Root Tempo account controlled by the access key.
40        #[arg(long)]
41        account: Address,
42
43        /// Access-key private key to persist.
44        #[arg(long, env = "TEMPO_ACCESS_KEY", hide_env_values = true)]
45        access_key: PrivateKeySigner,
46
47        /// Signed key authorization encoded as RLP hex.
48        #[arg(long)]
49        authorization: String,
50    },
51}
52
53impl TempoSubcommand {
54    pub async fn run(self) -> Result<()> {
55        match self {
56            Self::Login { chain_id, no_browser } => {
57                let mut cfg = EnsureAccessKeyConfig::from_env(chain_id);
58                if no_browser {
59                    cfg.no_browser = true;
60                }
61                let outcome = ensure_access_key(cfg).await?;
62                let _ = foundry_common::sh_status!(
63                    "Authorized key {} for wallet {} on chain {}",
64                    outcome.key_address,
65                    outcome.wallet_address,
66                    outcome.chain_id,
67                );
68                Ok(())
69            }
70            Self::ImportAccessKey { account, access_key, authorization } => {
71                let authorization =
72                    decode_key_authorization::<SignedKeyAuthorization>(&authorization)?;
73                let chain_id = authorization.chain_id;
74                let key_address = access_key.address();
75                let store = TempoAccountsStore::default_path()?;
76                store.upsert_secp256k1_access_key(account, &access_key, &authorization)?;
77                let _ = foundry_common::sh_status!(
78                    "Imported access key {} for wallet {} on chain {} into {}",
79                    key_address,
80                    account,
81                    chain_id,
82                    store.path().display(),
83                );
84                Ok(())
85            }
86        }
87    }
88}