Skip to content

Commit dc1d11e

Browse files
Add sncast balance command (#3817)
<!-- Reference any GitHub issues resolved by this PR --> Towards #2319 **Stack**: - #3818 - #3817 ⬅ ## Introduced changes Add `sncast balance` command ## Checklist <!-- Make sure all of these are complete --> - [x] Linked relevant issue - [ ] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [ ] Added changes to `CHANGELOG.md`
1 parent f9733da commit dc1d11e

File tree

12 files changed

+494
-7
lines changed

12 files changed

+494
-7
lines changed

Cargo.lock

Lines changed: 16 additions & 3 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
@@ -93,7 +93,7 @@ snapbox = "0.4.17"
9393
scarb-ui = "0.1.7"
9494
semver = "1.0.27"
9595
bimap = "0.6.3"
96-
primitive-types = "0.13.1"
96+
primitive-types = { version = "0.13.1", features = ["serde"] }
9797
shellexpand = "3.1.0"
9898
toml = "0.8.20"
9999
rpassword = "7.3.1"

crates/sncast/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ universal-sierra-compiler-api = { path = "../universal-sierra-compiler-api" }
6161
tracing-subscriber.workspace = true
6262
tracing.workspace = true
6363
tracing-log.workspace = true
64+
strum.workspace = true
65+
strum_macros.workspace = true
66+
primitive-types.workspace = true
6467

6568
[dev-dependencies]
6669
ctor.workspace = true

crates/sncast/src/helpers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub mod interactive;
1111
pub mod output_format;
1212
pub mod rpc;
1313
pub mod scarb_utils;
14+
pub mod token;

crates/sncast/src/helpers/token.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use clap::ValueEnum;
2+
use serde::Serialize;
3+
use starknet::macros::felt;
4+
use starknet_types_core::felt::Felt;
5+
6+
const STRK_CONTRACT_ADDRESS: Felt =
7+
felt!("0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d");
8+
9+
const ETH_CONTRACT_ADDRESS: Felt =
10+
felt!("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7");
11+
12+
#[derive(Default, Serialize, Clone, Copy, Debug, ValueEnum, strum_macros::Display)]
13+
// Both serde and strum enums need to have proper
14+
// casing configuration in clap and for serialization.
15+
#[strum(serialize_all = "lowercase")]
16+
#[serde(rename_all = "lowercase")]
17+
pub enum Token {
18+
#[default]
19+
Strk,
20+
Eth,
21+
}
22+
23+
impl Token {
24+
#[must_use]
25+
pub fn contract_address(&self) -> Felt {
26+
match self {
27+
Token::Strk => STRK_CONTRACT_ADDRESS,
28+
Token::Eth => ETH_CONTRACT_ADDRESS,
29+
}
30+
}
31+
}

crates/sncast/src/main.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use crate::starknet_commands::balance::Balance;
12
use crate::starknet_commands::declare::declare;
23
use crate::starknet_commands::declare_from::DeclareFrom;
34
use crate::starknet_commands::deploy::DeployArguments;
45
use crate::starknet_commands::multicall;
56
use crate::starknet_commands::script::run_script_command;
67
use crate::starknet_commands::utils::{self, Utils};
78
use crate::starknet_commands::{
8-
account, account::Account, call::Call, declare::Declare, deploy::Deploy, invoke::Invoke,
9-
multicall::Multicall, script::Script, show_config::ShowConfig, tx_status::TxStatus,
9+
account, account::Account as AccountCommand, call::Call, declare::Declare, deploy::Deploy,
10+
invoke::Invoke, multicall::Multicall, script::Script, show_config::ShowConfig,
11+
tx_status::TxStatus,
1012
};
1113
use anyhow::{Context, Result, bail};
1214
use camino::Utf8PathBuf;
@@ -37,6 +39,7 @@ use sncast::{
3739
ValidatedWaitParams, WaitForTx, get_account, get_block_id, get_class_hash_by_address,
3840
get_contract_class,
3941
};
42+
use starknet::accounts::Account;
4043
use starknet::core::types::ContractClass;
4144
use starknet::core::types::contract::{AbiEntry, SierraClass};
4245
use starknet::core::utils::get_selector_from_name;
@@ -139,7 +142,7 @@ enum Commands {
139142
Multicall(Multicall),
140143

141144
/// Create and deploy an account
142-
Account(Account),
145+
Account(AccountCommand),
143146

144147
/// Show current configuration being used
145148
ShowConfig(ShowConfig),
@@ -160,6 +163,9 @@ enum Commands {
160163

161164
/// Utility commands
162165
Utils(Utils),
166+
167+
/// Fetch balance of the account for specified token
168+
Balance(Balance),
163169
}
164170

165171
#[derive(Debug, Clone, clap::Args)]
@@ -679,6 +685,25 @@ async fn run_async_command(cli: Cli, config: CastConfig, ui: &UI) -> Result<()>
679685
Ok(())
680686
}
681687

688+
Commands::Balance(balance) => {
689+
let provider = balance.rpc.get_provider(&config, ui).await?;
690+
let account = get_account(
691+
&config,
692+
&provider,
693+
&balance.rpc,
694+
config.keystore.as_ref(),
695+
ui,
696+
)
697+
.await?;
698+
699+
let result =
700+
starknet_commands::balance::balance(account.address(), &provider, &balance).await?;
701+
702+
process_command_result("balance", Ok(result), ui, None);
703+
704+
Ok(())
705+
}
706+
682707
Commands::Script(_) => unreachable!(),
683708
}
684709
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::{
2+
helpers::token::Token,
3+
response::{
4+
cast_message::{SncastCommandMessage, SncastMessage},
5+
command::CommandResponse,
6+
},
7+
};
8+
use foundry_ui::styling;
9+
use primitive_types::U256;
10+
use serde::ser::{Serialize, SerializeStruct, Serializer};
11+
12+
#[derive(Debug)]
13+
pub struct BalanceResponse {
14+
pub balance: U256,
15+
pub token: Option<Token>,
16+
}
17+
18+
impl CommandResponse for BalanceResponse {}
19+
20+
impl SncastCommandMessage for SncastMessage<BalanceResponse> {
21+
fn text(&self) -> String {
22+
let balance_str = if let Some(token) = self.command_response.token {
23+
format!("{} {}", self.command_response.balance, token)
24+
} else {
25+
self.command_response.balance.to_string()
26+
};
27+
28+
styling::OutputBuilder::new()
29+
.field("Balance", &balance_str)
30+
.build()
31+
}
32+
}
33+
34+
// We need custom serialization because U256's default serialization is hex string
35+
impl Serialize for BalanceResponse {
36+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
37+
where
38+
S: Serializer,
39+
{
40+
let mut s = serializer.serialize_struct("BalanceResponse", 2)?;
41+
// Default U256 serialization uses hex string, we want decimal string
42+
s.serialize_field("balance", &self.balance.to_string())?;
43+
s.serialize_field("token", &self.token)?;
44+
s.end()
45+
}
46+
}

crates/sncast/src/response/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod account;
2+
pub mod balance;
23
pub mod call;
34
pub mod cast_message;
45
pub mod command;

0 commit comments

Comments
 (0)