1use crate::{
2 cmd::tip20::mine::{self, RegisterMessages},
3 tx::{SendTxOpts, TxParams},
4};
5use alloy_primitives::{Address, B256};
6use eyre::Result;
7use foundry_cli::json::print_json_success;
8use foundry_common::shell;
9use serde_json::json;
10use tempo_primitives::{TempoAddressExt, UserTag};
11
12const MESSAGES: RegisterMessages = RegisterMessages {
13 no_signer: "cast vaddr create requires a signer (for example --private-key or --from)",
14 mismatch: "signer mismatch: salt is for",
15 submitting: "...",
16};
17
18const MAX_USER_TAG: u64 = 0x0000_FFFF_FFFF_FFFF;
20
21#[allow(clippy::too_many_arguments)]
22pub(super) async fn run(
23 owner: Address,
24 salt: Option<B256>,
25 tag: u64,
26 count: u32,
27 threads: Option<usize>,
28 seed: Option<B256>,
29 no_random: bool,
30 no_register: bool,
31 send_tx: SendTxOpts,
32 tx_opts: TxParams,
33) -> Result<()> {
34 if count == 0 {
35 return Ok(());
36 }
37
38 let json = shell::is_json();
39 let (output, elapsed) = mine::find_salt(owner, salt, threads, seed, no_random, json, "owner")?;
40 if let Some(elapsed) = elapsed
41 && !json
42 {
43 sh_status!("Found salt in {elapsed:?}")?;
44 }
45
46 let mut virtual_addresses = Vec::with_capacity(count as usize);
47 for i in 0..count {
48 let tag_value = tag
49 .checked_add(i as u64)
50 .filter(|&t| t <= MAX_USER_TAG)
51 .ok_or_else(|| eyre::eyre!("tag overflow: tag + count exceeds the 6-byte user tag range (max {MAX_USER_TAG:#x})"))?;
52 let user_tag = UserTag::new(tag_value.to_be_bytes()[2..].try_into().unwrap());
53 virtual_addresses.push((user_tag, Address::new_virtual(output.master_id, user_tag)));
54 }
55
56 let mut payload = json!({
57 "salt": format!("{}", output.salt),
58 "registration_hash": format!("{}", output.registration_hash),
59 "master_id": format!("{}", output.master_id),
60 "virtual_addresses": virtual_addresses.iter().map(|(tag, addr)| json!({
61 "tag": format!("{tag}"),
62 "address": format!("{addr}"),
63 })).collect::<Vec<_>>(),
64 });
65
66 if !json {
67 sh_println!(
68 "Salt: {}\nRegistration hash: {}\nMaster ID: {}",
69 output.salt,
70 output.registration_hash,
71 output.master_id,
72 )?;
73 sh_println!("\nVirtual addresses:")?;
74 for (tag, vaddr) in &virtual_addresses {
75 sh_println!(" tag={tag} {vaddr}")?;
76 }
77 }
78
79 if !no_register {
80 let tx_hash =
81 mine::register_virtual_master(owner, output.salt, send_tx, tx_opts, json, &MESSAGES)
82 .await?;
83 payload["registration_tx_hash"] = json!(format!("{tx_hash:#x}"));
84 }
85 if json {
86 print_json_success(payload)?;
87 }
88 Ok(())
89}