Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
bd1f3a7
setup class hash command and response
Aug 18, 2025
a2cd991
complete logic to get class hash
Aug 18, 2025
7d5971d
start implementing ClassHash command logic
Aug 18, 2025
6b81895
add skip_compile to ClassHash
Aug 18, 2025
01374aa
complete class hash logic
Aug 18, 2025
f34a208
rename command
Aug 18, 2025
9e480f2
remove unused import
Aug 18, 2025
f0a6431
remove redundant lines
Aug 19, 2025
a60d9e0
create e2e file for class_hash
Aug 19, 2025
272ccc2
remove skip_compile command and load_artifacts separation
Aug 19, 2025
79af91d
remove unused import
Aug 19, 2025
c69f980
update response name
Aug 19, 2025
887573f
add e2e test test_happy_case_get_class_hash
Aug 19, 2025
388fd93
update changelog
Aug 19, 2025
1391500
Merge branch 'master' into 3584-sncast-util-calculate-contract-class-…
Aug 19, 2025
ed1b2af
add class_hash.md docs
Aug 19, 2025
ce9abb4
move class hash to utils
Aug 25, 2025
edd6847
update docs
Aug 25, 2025
006590a
remove unnecessary clone
Aug 25, 2025
2c40021
Update CHANGELOG.md
naijauser Aug 26, 2025
7a5b8e3
move class_hash to utils
Aug 26, 2025
44398b9
move class_hash to utils
Aug 26, 2025
d59ff24
clean up success message reporting
Aug 26, 2025
cea602a
update success response
Aug 26, 2025
25764dc
fix test
Aug 26, 2025
6aea513
update class-hash docs
Aug 26, 2025
aad4c7a
Update crates/sncast/src/response/class_hash.rs
naijauser Aug 26, 2025
ba2a64b
Update crates/sncast/src/response/class_hash.rs
naijauser Aug 26, 2025
9b7982d
Update crates/sncast/src/response/class_hash.rs
naijauser Aug 26, 2025
6939ec2
clippy: borrow
Aug 26, 2025
7050672
resolve lint warnings
Aug 26, 2025
3b85143
update test assert
Aug 26, 2025
b2c5873
fix padded felt test
Aug 26, 2025
942501f
Update docs/src/appendix/sncast/utils/class_hash.md
naijauser Aug 26, 2025
a17efae
update doc contract name
Aug 26, 2025
9d8d2c6
update test assertion
Aug 26, 2025
aabdc5a
Merge branch 'master' into 3584-sncast-util-calculate-contract-class-…
naijauser Aug 26, 2025
7d63af3
fmt
Aug 26, 2025
8fa30e1
add class-hash to SUMMARY.md
Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- A bug that caused `#[fuzzer]` attribute to fail when used with generic structs

### Cast

#### Added

- `utils class-hash` command to calculate the class hash for a contract

## [0.48.0] - 2025-08-05

### Forge
Expand Down
11 changes: 10 additions & 1 deletion crates/sncast/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,16 @@ async fn run_async_command(cli: Cli, config: CastConfig, ui: &UI) -> Result<()>
Ok(())
}

Commands::Utils(utils) => utils::utils(utils, config, ui).await,
Commands::Utils(utils) => {
utils::utils(
utils,
config,
ui,
cli.json,
cli.profile.clone().unwrap_or("release".to_string()),
)
.await
}

Commands::Multicall(multicall) => {
multicall::multicall(multicall, config, ui, wait_config).await
Expand Down
35 changes: 35 additions & 0 deletions crates/sncast/src/response/class_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use conversions::padded_felt::PaddedFelt;
use conversions::{serde::serialize::CairoSerialize, string::IntoPaddedHexStr};
use foundry_ui::{Message, styling};
use serde::{Deserialize, Serialize};
use serde_json::json;

use crate::response::{cast_message::SncastMessage, command::CommandResponse};

#[derive(Clone, Serialize, Deserialize, CairoSerialize, Debug, PartialEq)]
pub struct ClassHashResponse {
pub class_hash: PaddedFelt,
}

impl CommandResponse for ClassHashResponse {}

impl Message for SncastMessage<ClassHashResponse> {
fn text(&self) -> String {
styling::OutputBuilder::new()
.field(
"Class Hash",
&self.command_response.class_hash.into_padded_hex_str(),
)
.build()
}

fn json(&self) -> serde_json::Value {
serde_json::to_value(&self.command_response).unwrap_or_else(|err| {
json!({
"error": "Failed to serialize response",
"command": self.command,
"details": err.to_string()
})
})
}
}
1 change: 1 addition & 0 deletions crates/sncast/src/response/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod account;
pub mod call;
pub mod cast_message;
pub mod class_hash;
pub mod command;
pub mod declare;
pub mod deploy;
Expand Down
45 changes: 45 additions & 0 deletions crates/sncast/src/starknet_commands/utils/class_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use anyhow::Context;
use clap::Args;
use conversions::{IntoConv, byte_array::ByteArray};
use scarb_api::StarknetContractArtifacts;
use sncast::{
ErrorData,
response::{class_hash::ClassHashResponse, errors::StarknetCommandError},
};
use starknet::core::types::contract::SierraClass;
use std::collections::HashMap;

#[derive(Args, Debug)]
#[command(about = "Generate the class hash of a contract", long_about = None)]
pub struct ClassHash {
/// Contract name
#[arg(short = 'c', long = "contract-name")]
pub contract: String,

/// Specifies scarb package to be used
#[arg(long)]
pub package: Option<String>,
}

#[allow(clippy::result_large_err)]
pub fn get_class_hash(
class_hash: &ClassHash,
artifacts: &HashMap<String, StarknetContractArtifacts>,
) -> Result<ClassHashResponse, StarknetCommandError> {
let contract_artifacts = artifacts.get(&class_hash.contract).ok_or(
StarknetCommandError::ContractArtifactsNotFound(ErrorData {
data: ByteArray::from(class_hash.contract.as_str()),
}),
)?;

let contract_definition: SierraClass = serde_json::from_str(&contract_artifacts.sierra)
.context("Failed to parse sierra artifact")?;

let class_hash = contract_definition
.class_hash()
.map_err(anyhow::Error::from)?;

Ok(ClassHashResponse {
class_hash: class_hash.into_(),
})
}
50 changes: 47 additions & 3 deletions crates/sncast/src/starknet_commands/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
use clap::{Args, Subcommand};
use foundry_ui::UI;
use sncast::{helpers::configuration::CastConfig, response::errors::handle_starknet_command_error};
use sncast::{
helpers::{
configuration::CastConfig,
scarb_utils::{
BuildConfig, assert_manifest_path_exists, build_and_load_artifacts,
get_package_metadata,
},
},
response::errors::handle_starknet_command_error,
};

use crate::{
process_command_result,
starknet_commands::{self, utils::serialize::Serialize},
starknet_commands::{
self,
utils::{class_hash::ClassHash, serialize::Serialize},
},
};

pub mod class_hash;
pub mod serialize;

#[derive(Args)]
Expand All @@ -19,9 +32,18 @@ pub struct Utils {
#[derive(Debug, Subcommand)]
pub enum Commands {
Serialize(Serialize),

/// Get contract class hash
ClassHash(ClassHash),
}

pub async fn utils(utils: Utils, config: CastConfig, ui: &UI) -> anyhow::Result<()> {
pub async fn utils(
utils: Utils,
config: CastConfig,
ui: &UI,
json: bool,
profile: String,
) -> anyhow::Result<()> {
match utils.command {
Commands::Serialize(serialize) => {
let result = starknet_commands::utils::serialize::serialize(serialize, config, ui)
Expand All @@ -30,6 +52,28 @@ pub async fn utils(utils: Utils, config: CastConfig, ui: &UI) -> anyhow::Result<

process_command_result("serialize", Ok(result), ui, None);
}

Commands::ClassHash(class_hash) => {
let manifest_path = assert_manifest_path_exists()?;
let package_metadata = get_package_metadata(&manifest_path, &class_hash.package)?;

let artifacts = build_and_load_artifacts(
&package_metadata,
&BuildConfig {
scarb_toml_path: manifest_path,
json,
profile,
},
false,
ui,
)
.expect("Failed to build contract");

let result = class_hash::get_class_hash(&class_hash, &artifacts)
.map_err(handle_starknet_command_error)?;

process_command_result("class-hash", Ok(result), ui, None);
}
}

Ok(())
Expand Down
22 changes: 22 additions & 0 deletions crates/sncast/tests/e2e/class_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::helpers::{
constants::CONTRACTS_DIR, fixtures::duplicate_contract_directory_with_salt, runner::runner,
};
use indoc::indoc;
use shared::test_utils::output_assert::assert_stdout_contains;

#[test]
fn test_happy_case_get_class_hash() {
let contract_path = duplicate_contract_directory_with_salt(
CONTRACTS_DIR.to_string() + "/map",
"put",
"human_readable",
);

let args = vec!["utils", "class-hash", "--contract-name", "Map"];

let snapbox = runner(&args).current_dir(contract_path.path());

let output = snapbox.assert().success();

assert_stdout_contains(output, indoc! {r"Class Hash: 0x0[..]"});
}
1 change: 1 addition & 0 deletions crates/sncast/tests/e2e/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod account;
mod call;
mod class_hash;
mod completions;
mod declare;
mod deploy;
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
* [completions](appendix/sncast/completions.md)
* [utils](appendix/sncast/utils/utils.md)
* [serialize](appendix/sncast/utils/serialize.md)
* [class-hash](appendix/sncast/utils/class_hash.md)
* [`sncast` Library Reference](appendix/sncast-library.md)
* [declare](appendix/sncast-library/declare.md)
* [deploy](appendix/sncast-library/deploy.md)
Expand Down
23 changes: 23 additions & 0 deletions docs/src/appendix/sncast/utils/class_hash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Calculate contract class hash

## Overview
Use the `sncast utils class-hash` command to calculate the class hash of a contract.

## Examples

### General Example

```shell
$ sncast utils \
class-hash \
--contract-name HelloSncast
```

<details>
<summary>Output:</summary>

```shell
Class Hash: 0x0[..]
```
</details>
<br>
1 change: 1 addition & 0 deletions docs/src/appendix/sncast/utils/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Provides a set of utility commands.

It has the following subcommands:
* [`serialize`](./serialize.md)
* [`class-hash`](./class_hash.md)
Loading