-
Notifications
You must be signed in to change notification settings - Fork 239
Allow declaring with deployment #3783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: spr/master/94945a36
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,3 +1,4 @@ | ||||||
use crate::starknet_commands::declare::declare; | ||||||
use crate::starknet_commands::declare_from::DeclareFrom; | ||||||
use crate::starknet_commands::deploy::DeployArguments; | ||||||
use crate::starknet_commands::multicall; | ||||||
|
@@ -11,6 +12,7 @@ use anyhow::{Context, Result, bail}; | |||||
use camino::Utf8PathBuf; | ||||||
use clap::{CommandFactory, Parser, Subcommand}; | ||||||
use configuration::load_config; | ||||||
use conversions::IntoConv; | ||||||
use data_transformer::transform; | ||||||
use foundry_ui::components::warning::WarningMessage; | ||||||
use foundry_ui::{Message, UI}; | ||||||
|
@@ -24,7 +26,10 @@ use sncast::helpers::rpc::generate_network_flag; | |||||
use sncast::helpers::scarb_utils::{ | ||||||
BuildConfig, assert_manifest_path_exists, build_and_load_artifacts, get_package_metadata, | ||||||
}; | ||||||
use sncast::response::declare::{DeclareResponse, DeployCommandMessage}; | ||||||
use sncast::response::declare::{ | ||||||
AlreadyDeclaredResponse, DeclareResponse, DeclareTransactionResponse, DeployCommandMessage, | ||||||
}; | ||||||
use sncast::response::deploy::{DeployResponse, DeployResponseWithDeclare}; | ||||||
use sncast::response::errors::handle_starknet_command_error; | ||||||
use sncast::response::explorer_link::block_explorer_link_if_allowed; | ||||||
use sncast::response::transformed_call::transform_response; | ||||||
|
@@ -393,9 +398,11 @@ async fn run_async_command(cli: Cli, config: CastConfig, ui: &UI) -> Result<()> | |||||
|
||||||
Commands::Deploy(deploy) => { | ||||||
let Deploy { | ||||||
contract_identifier: identifier, | ||||||
arguments, | ||||||
fee_args, | ||||||
rpc, | ||||||
mut nonce, | ||||||
.. | ||||||
} = deploy; | ||||||
|
||||||
|
@@ -404,28 +411,98 @@ async fn run_async_command(cli: Cli, config: CastConfig, ui: &UI) -> Result<()> | |||||
let account = | ||||||
get_account(&config, &provider, &rpc, config.keystore.as_ref(), ui).await?; | ||||||
|
||||||
let (class_hash, declare_response) = if let Some(class_hash) = identifier.class_hash { | ||||||
(class_hash, None) | ||||||
} else if let Some(contract_name) = identifier.contract_name { | ||||||
let manifest_path = assert_manifest_path_exists()?; | ||||||
let package_metadata = get_package_metadata(&manifest_path, &None)?; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this feature work for workspaces? |
||||||
let artifacts = build_and_load_artifacts( | ||||||
&package_metadata, | ||||||
&BuildConfig { | ||||||
scarb_toml_path: manifest_path, | ||||||
json: cli.json, | ||||||
profile: cli.profile.unwrap_or("release".to_string()), | ||||||
}, | ||||||
false, | ||||||
ui, | ||||||
) | ||||||
.expect("Failed to build contract"); | ||||||
|
||||||
let declare_result = declare( | ||||||
contract_name, | ||||||
fee_args.clone(), | ||||||
nonce, | ||||||
&account, | ||||||
&artifacts, | ||||||
WaitForTx { | ||||||
wait: true, | ||||||
wait_params: wait_config.wait_params, | ||||||
show_ui_outputs: true, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if someone passes the |
||||||
}, | ||||||
true, | ||||||
ui, | ||||||
) | ||||||
.await | ||||||
.map_err(handle_starknet_command_error); | ||||||
|
||||||
// Increment nonce after successful declare if it was explicitly provided | ||||||
nonce = nonce.map(|n| n + Felt::ONE); | ||||||
|
||||||
match declare_result { | ||||||
Ok(DeclareResponse::AlreadyDeclared(AlreadyDeclaredResponse { | ||||||
class_hash, | ||||||
})) => (class_hash.into_(), None), | ||||||
Ok(DeclareResponse::Success(declare_transaction_response)) => ( | ||||||
declare_transaction_response.class_hash.into_(), | ||||||
Some(declare_transaction_response), | ||||||
), | ||||||
Err(err) => { | ||||||
process_command_result::<DeclareTransactionResponse>( | ||||||
"deploy", | ||||||
Err(err), | ||||||
ui, | ||||||
None, | ||||||
); | ||||||
return Ok(()); | ||||||
} | ||||||
} | ||||||
} else { | ||||||
unreachable!("One of class_hash or contract_name must be provided"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||
}; | ||||||
|
||||||
// safe to unwrap because "constructor" is a standardized name | ||||||
let selector = get_selector_from_name("constructor").unwrap(); | ||||||
|
||||||
let contract_class = get_contract_class(deploy.class_hash, &provider).await?; | ||||||
let contract_class = get_contract_class(class_hash, &provider).await?; | ||||||
|
||||||
let arguments: Arguments = arguments.into(); | ||||||
let calldata = arguments.try_into_calldata(contract_class, &selector)?; | ||||||
|
||||||
let result = starknet_commands::deploy::deploy( | ||||||
deploy.class_hash, | ||||||
class_hash, | ||||||
&calldata, | ||||||
deploy.salt, | ||||||
deploy.unique, | ||||||
fee_args, | ||||||
deploy.nonce, | ||||||
nonce, | ||||||
&account, | ||||||
wait_config, | ||||||
ui, | ||||||
) | ||||||
.await | ||||||
.map_err(handle_starknet_command_error); | ||||||
|
||||||
let result = if let Some(declare_response) = declare_response { | ||||||
result.map(|r| { | ||||||
DeployResponse::DeployWithDeclare(DeployResponseWithDeclare::from_responses( | ||||||
&r, | ||||||
&declare_response, | ||||||
)) | ||||||
}) | ||||||
} else { | ||||||
result.map(DeployResponse::Deploy) | ||||||
}; | ||||||
|
||||||
let block_explorer_link = | ||||||
block_explorer_link_if_allowed(&result, provider.chain_id().await?, &rpc, &config); | ||||||
process_command_result("deploy", result, ui, block_explorer_link); | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,38 +1,31 @@ | ||||||||||
use super::command::CommandResponse; | ||||||||||
use crate::helpers::block_explorer::LinkProvider; | ||||||||||
use crate::response::cast_message::SncastMessage; | ||||||||||
use crate::response::declare::DeclareTransactionResponse; | ||||||||||
use crate::response::explorer_link::OutputLink; | ||||||||||
use conversions::string::IntoPaddedHexStr; | ||||||||||
use conversions::{padded_felt::PaddedFelt, serde::serialize::CairoSerialize}; | ||||||||||
use foundry_ui::Message; | ||||||||||
use foundry_ui::styling; | ||||||||||
use indoc::formatdoc; | ||||||||||
use serde::{Deserialize, Serialize}; | ||||||||||
use serde_json::Value; | ||||||||||
use serde_json::json; | ||||||||||
|
||||||||||
use super::{command::CommandResponse, explorer_link::OutputLink}; | ||||||||||
use crate::response::cast_message::SncastMessage; | ||||||||||
use serde_json::{Value, json}; | ||||||||||
|
||||||||||
#[derive(Clone, Serialize, Deserialize, CairoSerialize, Debug, PartialEq)] | ||||||||||
pub struct DeployResponse { | ||||||||||
pub contract_address: PaddedFelt, | ||||||||||
pub transaction_hash: PaddedFelt, | ||||||||||
#[serde(untagged)] | ||||||||||
pub enum DeployResponse { | ||||||||||
Deploy(StandardDeployResponse), | ||||||||||
DeployWithDeclare(DeployResponseWithDeclare), | ||||||||||
Comment on lines
+17
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||||
} | ||||||||||
|
||||||||||
impl CommandResponse for DeployResponse {} | ||||||||||
|
||||||||||
impl Message for SncastMessage<DeployResponse> { | ||||||||||
fn text(&self) -> String { | ||||||||||
styling::OutputBuilder::new() | ||||||||||
.success_message("Deployment completed") | ||||||||||
.blank_line() | ||||||||||
.field( | ||||||||||
"Contract Address", | ||||||||||
&self.command_response.contract_address.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.field( | ||||||||||
"Transaction Hash", | ||||||||||
&self.command_response.transaction_hash.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.build() | ||||||||||
match &self.command_response { | ||||||||||
DeployResponse::Deploy(response) => response.text(), | ||||||||||
DeployResponse::DeployWithDeclare(response) => response.text(), | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
fn json(&self) -> Value { | ||||||||||
|
@@ -50,13 +43,99 @@ impl OutputLink for DeployResponse { | |||||||||
const TITLE: &'static str = "deployment"; | ||||||||||
|
||||||||||
fn format_links(&self, provider: Box<dyn LinkProvider>) -> String { | ||||||||||
formatdoc!( | ||||||||||
" | ||||||||||
contract: {} | ||||||||||
transaction: {} | ||||||||||
", | ||||||||||
provider.contract(self.contract_address), | ||||||||||
provider.transaction(self.transaction_hash) | ||||||||||
) | ||||||||||
match self { | ||||||||||
DeployResponse::Deploy(deploy) => { | ||||||||||
formatdoc!( | ||||||||||
" | ||||||||||
contract: {} | ||||||||||
transaction: {} | ||||||||||
", | ||||||||||
provider.contract(deploy.contract_address), | ||||||||||
provider.transaction(deploy.transaction_hash) | ||||||||||
) | ||||||||||
} | ||||||||||
DeployResponse::DeployWithDeclare(deploy_with_declare) => { | ||||||||||
formatdoc!( | ||||||||||
" | ||||||||||
contract: {} | ||||||||||
class: {} | ||||||||||
declare transaction: {} | ||||||||||
deploy transaction: {} | ||||||||||
", | ||||||||||
provider.contract(deploy_with_declare.contract_address), | ||||||||||
provider.class(deploy_with_declare.class_hash), | ||||||||||
provider.transaction(deploy_with_declare.declare_transaction_hash), | ||||||||||
provider.transaction(deploy_with_declare.deploy_transaction_hash) | ||||||||||
) | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
#[derive(Clone, Serialize, Deserialize, CairoSerialize, Debug, PartialEq)] | ||||||||||
pub struct StandardDeployResponse { | ||||||||||
pub contract_address: PaddedFelt, | ||||||||||
pub transaction_hash: PaddedFelt, | ||||||||||
} | ||||||||||
|
||||||||||
impl StandardDeployResponse { | ||||||||||
fn text(&self) -> String { | ||||||||||
styling::OutputBuilder::new() | ||||||||||
.success_message("Deployment completed") | ||||||||||
.blank_line() | ||||||||||
.field( | ||||||||||
"Contract Address", | ||||||||||
&self.contract_address.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.field( | ||||||||||
"Transaction Hash", | ||||||||||
&self.transaction_hash.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.build() | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
#[derive(Clone, Serialize, Deserialize, CairoSerialize, Debug, PartialEq)] | ||||||||||
pub struct DeployResponseWithDeclare { | ||||||||||
contract_address: PaddedFelt, | ||||||||||
class_hash: PaddedFelt, | ||||||||||
deploy_transaction_hash: PaddedFelt, | ||||||||||
declare_transaction_hash: PaddedFelt, | ||||||||||
} | ||||||||||
|
||||||||||
impl DeployResponseWithDeclare { | ||||||||||
#[must_use] | ||||||||||
pub fn from_responses( | ||||||||||
deploy: &StandardDeployResponse, | ||||||||||
declare: &DeclareTransactionResponse, | ||||||||||
) -> Self { | ||||||||||
Self { | ||||||||||
contract_address: deploy.contract_address, | ||||||||||
class_hash: declare.class_hash, | ||||||||||
deploy_transaction_hash: deploy.transaction_hash, | ||||||||||
declare_transaction_hash: declare.transaction_hash, | ||||||||||
} | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
impl DeployResponseWithDeclare { | ||||||||||
fn text(&self) -> String { | ||||||||||
styling::OutputBuilder::new() | ||||||||||
.success_message("Deployment completed") | ||||||||||
.blank_line() | ||||||||||
.field( | ||||||||||
"Contract Address", | ||||||||||
&self.contract_address.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.field("Class Hash", &self.class_hash.into_padded_hex_str()) | ||||||||||
.field( | ||||||||||
"Declare Transaction Hash", | ||||||||||
&self.declare_transaction_hash.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.field( | ||||||||||
"Deploy Transaction Hash", | ||||||||||
&self.deploy_transaction_hash.into_padded_hex_str(), | ||||||||||
) | ||||||||||
.build() | ||||||||||
} | ||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -4,7 +4,7 @@ use conversions::IntoConv; | |||||||||||||||||||||||||||||||||||||||||||||||
use foundry_ui::UI; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::helpers::fee::{FeeArgs, FeeSettings}; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::helpers::rpc::RpcArgs; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::response::deploy::DeployResponse; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::response::deploy::StandardDeployResponse; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::response::errors::StarknetCommandError; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::{WaitForTx, apply_optional_fields, handle_wait_for_tx}; | ||||||||||||||||||||||||||||||||||||||||||||||||
use sncast::{extract_or_generate_salt, udc_uniqueness}; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -17,12 +17,23 @@ use starknet::providers::jsonrpc::HttpTransport; | |||||||||||||||||||||||||||||||||||||||||||||||
use starknet::signers::LocalWallet; | ||||||||||||||||||||||||||||||||||||||||||||||||
use starknet_types_core::felt::Felt; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
#[derive(Args, Debug, Clone)] | ||||||||||||||||||||||||||||||||||||||||||||||||
#[group(required = true, multiple = false)] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub struct ContractIdentifier { | ||||||||||||||||||||||||||||||||||||||||||||||||
/// Class hash of contract to deploy | ||||||||||||||||||||||||||||||||||||||||||||||||
#[arg(short = 'g', long)] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub class_hash: Option<Felt>, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
/// Contract name | ||||||||||||||||||||||||||||||||||||||||||||||||
#[arg(long, conflicts_with = "class_hash")] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub contract_name: Option<String>, | ||||||||||||||||||||||||||||||||||||||||||||||||
cptartur marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+20
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Usage of
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
#[derive(Args)] | ||||||||||||||||||||||||||||||||||||||||||||||||
#[command(about = "Deploy a contract on Starknet")] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub struct Deploy { | ||||||||||||||||||||||||||||||||||||||||||||||||
/// Class hash of contract to deploy | ||||||||||||||||||||||||||||||||||||||||||||||||
#[arg(short = 'g', long)] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub class_hash: Felt, | ||||||||||||||||||||||||||||||||||||||||||||||||
#[command(flatten)] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub contract_identifier: ContractIdentifier, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
#[command(flatten)] | ||||||||||||||||||||||||||||||||||||||||||||||||
pub arguments: DeployArguments, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -69,7 +80,7 @@ pub async fn deploy( | |||||||||||||||||||||||||||||||||||||||||||||||
account: &SingleOwnerAccount<&JsonRpcClient<HttpTransport>, LocalWallet>, | ||||||||||||||||||||||||||||||||||||||||||||||||
wait_config: WaitForTx, | ||||||||||||||||||||||||||||||||||||||||||||||||
ui: &UI, | ||||||||||||||||||||||||||||||||||||||||||||||||
) -> Result<DeployResponse, StarknetCommandError> { | ||||||||||||||||||||||||||||||||||||||||||||||||
) -> Result<StandardDeployResponse, StarknetCommandError> { | ||||||||||||||||||||||||||||||||||||||||||||||||
let salt = extract_or_generate_salt(salt); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
// TODO(#3628): Use `ContractFactory::new` once new UDC address is the default one in starknet-rs | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -114,7 +125,7 @@ pub async fn deploy( | |||||||||||||||||||||||||||||||||||||||||||||||
Ok(result) => handle_wait_for_tx( | ||||||||||||||||||||||||||||||||||||||||||||||||
account.provider(), | ||||||||||||||||||||||||||||||||||||||||||||||||
result.transaction_hash, | ||||||||||||||||||||||||||||||||||||||||||||||||
DeployResponse { | ||||||||||||||||||||||||||||||||||||||||||||||||
StandardDeployResponse { | ||||||||||||||||||||||||||||||||||||||||||||||||
contract_address: get_udc_deployed_address( | ||||||||||||||||||||||||||||||||||||||||||||||||
salt, | ||||||||||||||||||||||||||||||||||||||||||||||||
class_hash, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.