Skip to content

Commit

Permalink
Refactored call, deploy and invoke handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
integraledelebesgue committed Sep 27, 2024
1 parent 9e7afcc commit d8b9b67
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 166 deletions.
16 changes: 16 additions & 0 deletions crates/sncast/src/helpers/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ pub enum FeeSettings {
},
}

impl From<ScriptFeeSettings> for FeeSettings {
fn from(value: ScriptFeeSettings) -> Self {
match value {
ScriptFeeSettings::Eth { max_fee } => FeeSettings::Eth { max_fee },
ScriptFeeSettings::Strk {
max_gas,
max_gas_unit_price,
..
} => FeeSettings::Strk {
max_gas,
max_gas_unit_price,
},
}
}
}

pub trait PayableTransaction {
fn error_message(&self, token: &str, version: &str) -> String;
fn validate(&self) -> Result<()>;
Expand Down
100 changes: 87 additions & 13 deletions crates/sncast/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::starknet_commands::{
};
use anyhow::{Context, Result};
use configuration::load_global_config;
use sncast::helpers::data_transformer::transformer::transform;
use sncast::response::explorer_link::print_block_explorer_link_if_allowed;
use sncast::response::print::{print_command_result, OutputFormat};

Expand All @@ -20,9 +21,10 @@ use sncast::helpers::scarb_utils::{
};
use sncast::response::errors::handle_starknet_command_error;
use sncast::{
chain_id_to_network_name, get_account, get_block_id, get_chain_id, get_default_state_file_name,
NumbersFormat, ValidatedWaitParams, WaitForTx,
chain_id_to_network_name, get_account, get_block_id, get_chain_id, get_class_hash_by_address,
get_contract_class, get_default_state_file_name, NumbersFormat, ValidatedWaitParams, WaitForTx,
};
use starknet::accounts::ConnectedAccount;
use starknet::core::utils::get_selector_from_name;
use starknet::providers::Provider;
use starknet_commands::account::list::print_account_list;
Expand Down Expand Up @@ -224,6 +226,7 @@ async fn run_async_command(
let provider = deploy.rpc.get_provider(&config).await?;

deploy.validate()?;

let account = get_account(
&config.account,
&config.accounts_file,
Expand All @@ -232,9 +235,36 @@ async fn run_async_command(
)
.await?;

let result = starknet_commands::deploy::deploy(deploy, &account, wait_config)
.await
.map_err(handle_starknet_command_error);
let fee_settings = deploy
.fee_args
.clone()
.fee_token(deploy.token_from_version())
.try_into_fee_settings(&provider, account.block_id())
.await?;

let constructor_calldata = deploy.constructor_calldata;

let selector = get_selector_from_name("constructor").unwrap();

let contract_class = get_contract_class(deploy.class_hash, &provider).await?;

let serialized_calldata = match constructor_calldata {
Some(ref data) => transform(data, contract_class, &selector)?,
None => vec![],
};

let result = starknet_commands::deploy::deploy(
deploy.class_hash,
&serialized_calldata,
deploy.salt,
deploy.unique,
fee_settings,
deploy.nonce,
&account,
wait_config,
)
.await
.map_err(handle_starknet_command_error);

print_command_result("deploy", &result, numbers_format, output_format)?;
print_block_explorer_link_if_allowed(
Expand All @@ -252,11 +282,26 @@ async fn run_async_command(

let block_id = get_block_id(&call.block_id)?;

let class_hash = get_class_hash_by_address(&provider, call.contract_address)
.await?
.with_context(|| {
format!(
"Couldn't retrieve class hash of a contract with address {:#x}",
call.contract_address
)
})?;

let contract_class = get_contract_class(class_hash, &provider).await?;

let entry_point_selector = get_selector_from_name(&call.function)
.context("Failed to convert entry point selector to FieldElement")?;

let calldata = transform(&call.calldata, contract_class, &entry_point_selector)?;

let result = starknet_commands::call::call(
call.contract_address,
get_selector_from_name(&call.function)
.context("Failed to convert entry point selector to FieldElement")?,
call.calldata,
entry_point_selector,
calldata,
&provider,
block_id.as_ref(),
)
Expand All @@ -268,21 +313,50 @@ async fn run_async_command(
}

Commands::Invoke(invoke) => {
let provider = invoke.rpc.get_provider(&config).await?;

invoke.validate()?;

let fee_token = invoke.token_from_version();

let Invoke {
contract_address,
function,
calldata,
fee_args,
rpc,
nonce,
..
} = invoke;

let provider = rpc.get_provider(&config).await?;

let account = get_account(
&config.account,
&config.accounts_file,
&provider,
config.keystore,
)
.await?;

let fee_args = fee_args.fee_token(fee_token);

let selector = get_selector_from_name(&function)
.context("Failed to convert entry point selector to FieldElement")?;

let class_hash = get_class_hash_by_address(&provider, contract_address)
.await
.with_context(|| format!("Failed to retrieve class hash of a contract at address {contract_address:#x}"))?
.with_context(|| format!("Failed to retrieve class hash of a contract at address {contract_address:#x}"))?;

let contract_class = get_contract_class(class_hash, &provider).await?;

let calldata = transform(&calldata, contract_class, &selector)?;

let result = starknet_commands::invoke::invoke(
invoke.clone(),
get_selector_from_name(&invoke.function)
.context("Failed to convert entry point selector to FieldElement")?,
contract_address,
calldata,
nonce,
fee_args,
selector,
&account,
wait_config,
)
Expand Down
16 changes: 2 additions & 14 deletions crates/sncast/src/starknet_commands/call.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use anyhow::{Context, Result};
use anyhow::Result;
use clap::Args;
use sncast::helpers::data_transformer::transformer::transform;
use sncast::helpers::rpc::RpcArgs;
use sncast::response::errors::StarknetCommandError;
use sncast::response::structs::CallResponse;
use sncast::{get_class_hash_by_address, get_contract_class};
use starknet::core::types::{BlockId, Felt, FunctionCall};
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::{JsonRpcClient, Provider};
Expand Down Expand Up @@ -38,20 +36,10 @@ pub struct Call {
pub async fn call(
contract_address: Felt,
entry_point_selector: Felt,
calldata: Vec<String>,
calldata: Vec<Felt>,
provider: &JsonRpcClient<HttpTransport>,
block_id: &BlockId,
) -> Result<CallResponse, StarknetCommandError> {
let class_hash = get_class_hash_by_address(provider, contract_address)
.await?
.with_context(|| {
format!("Couldn't retrieve class hash of a contract with address {contract_address:#x}")
})?;

let contract_class = get_contract_class(class_hash, provider).await?;

let calldata = transform(&calldata, contract_class, &entry_point_selector)?;

let function_call = FunctionCall {
contract_address,
entry_point_selector,
Expand Down
53 changes: 18 additions & 35 deletions crates/sncast/src/starknet_commands/deploy.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use anyhow::{anyhow, Result};
use clap::{Args, ValueEnum};
use sncast::helpers::data_transformer::transformer::transform;
use sncast::helpers::error::token_not_supported_for_deployment;
use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction};
use sncast::helpers::rpc::RpcArgs;
use sncast::response::errors::StarknetCommandError;
use sncast::response::structs::DeployResponse;
use sncast::{
extract_or_generate_salt, get_contract_class, impl_payable_transaction, udc_uniqueness,
};
use sncast::{extract_or_generate_salt, impl_payable_transaction, udc_uniqueness};
use sncast::{handle_wait_for_tx, WaitForTx};
use starknet::accounts::AccountError::Provider;
use starknet::accounts::{Account, ConnectedAccount, SingleOwnerAccount};
use starknet::contract::ContractFactory;
use starknet::core::types::Felt;
use starknet::core::utils::{get_selector_from_name, get_udc_deployed_address};
use starknet::core::utils::get_udc_deployed_address;
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
use starknet::signers::LocalWallet;
Expand Down Expand Up @@ -64,41 +61,27 @@ impl_payable_transaction!(Deploy, token_not_supported_for_deployment,
DeployVersion::V3 => FeeToken::Strk
);

#[allow(clippy::ptr_arg)]
pub async fn deploy(
deploy: Deploy,
class_hash: Felt,
calldata: &Vec<Felt>,
salt: Option<Felt>,
unique: bool,
fee_settings: FeeSettings,
nonce: Option<Felt>,
account: &SingleOwnerAccount<&JsonRpcClient<HttpTransport>, LocalWallet>,
wait_config: WaitForTx,
) -> Result<DeployResponse, StarknetCommandError> {
let fee_settings = deploy
.fee_args
.clone()
.fee_token(deploy.token_from_version())
.try_into_fee_settings(account.provider(), account.block_id())
.await?;

let contract_class = get_contract_class(deploy.class_hash, account.provider()).await?;
// let selector = get_selector_from_name("constructor")
// .context("Couldn't retrieve constructor from contract class")?;

let selector = get_selector_from_name("constructor").unwrap();

let constructor_calldata = deploy.constructor_calldata;

let serialized_calldata = match constructor_calldata {
Some(ref data) => transform(data, contract_class, &selector)?,
None => vec![],
};

let salt = extract_or_generate_salt(deploy.salt);
let factory = ContractFactory::new(deploy.class_hash, account);
let salt = extract_or_generate_salt(salt);
let factory = ContractFactory::new(class_hash, account);
let result = match fee_settings {
FeeSettings::Eth { max_fee } => {
let execution = factory.deploy_v1(serialized_calldata.clone(), salt, deploy.unique);
let execution = factory.deploy_v1(calldata.clone(), salt, unique);
let execution = match max_fee {
None => execution,
Some(max_fee) => execution.max_fee(max_fee),
};
let execution = match deploy.nonce {
let execution = match nonce {
None => execution,
Some(nonce) => execution.nonce(nonce),
};
Expand All @@ -108,7 +91,7 @@ pub async fn deploy(
max_gas,
max_gas_unit_price,
} => {
let execution = factory.deploy_v3(serialized_calldata.clone(), salt, deploy.unique);
let execution = factory.deploy_v3(calldata.clone(), salt, unique);

let execution = match max_gas {
None => execution,
Expand All @@ -118,7 +101,7 @@ pub async fn deploy(
None => execution,
Some(max_gas_unit_price) => execution.gas_price(max_gas_unit_price),
};
let execution = match deploy.nonce {
let execution = match nonce {
None => execution,
Some(nonce) => execution.nonce(nonce),
};
Expand All @@ -133,9 +116,9 @@ pub async fn deploy(
DeployResponse {
contract_address: get_udc_deployed_address(
salt,
deploy.class_hash,
&udc_uniqueness(deploy.unique, account.address()),
&serialized_calldata,
class_hash,
&udc_uniqueness(unique, account.address()),
&calldata,
),
transaction_hash: result.transaction_hash,
},
Expand Down
34 changes: 9 additions & 25 deletions crates/sncast/src/starknet_commands/invoke.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Result};
use clap::{Args, ValueEnum};
use sncast::helpers::data_transformer::transformer::transform;

use sncast::helpers::error::token_not_supported_for_invoke;
use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction};
use sncast::helpers::rpc::RpcArgs;
use sncast::response::errors::StarknetCommandError;
use sncast::response::structs::InvokeResponse;
use sncast::{
apply_optional, get_class_hash_by_address, get_contract_class, handle_wait_for_tx,
impl_payable_transaction, WaitForTx,
};
use sncast::{apply_optional, handle_wait_for_tx, impl_payable_transaction, WaitForTx};
use starknet::accounts::AccountError::Provider;
use starknet::accounts::{Account, ConnectedAccount, ExecutionV1, ExecutionV3, SingleOwnerAccount};
use starknet::core::types::{Call, Felt, InvokeTransactionResult};
Expand Down Expand Up @@ -59,34 +56,21 @@ impl_payable_transaction!(Invoke, token_not_supported_for_invoke,
);

pub async fn invoke(
invoke: Invoke,
contract_address: Felt,
calldata: Vec<Felt>,
nonce: Option<Felt>,
fee_args: FeeArgs,
function_selector: Felt,
account: &SingleOwnerAccount<&JsonRpcClient<HttpTransport>, LocalWallet>,
wait_config: WaitForTx,
) -> Result<InvokeResponse, StarknetCommandError> {
let fee_args = invoke
.fee_args
.clone()
.fee_token(invoke.token_from_version());

let contract_address = invoke.contract_address;
let class_hash = get_class_hash_by_address(account.provider(), contract_address)
.await?
.with_context(|| {
format!("Couldn't retrieve class hash of a contract with address {contract_address:#x}")
})?;

let contract_class = get_contract_class(class_hash, account.provider()).await?;

let calldata = transform(&invoke.calldata, contract_class, &function_selector)?;

let call = Call {
to: invoke.contract_address,
to: contract_address,
selector: function_selector,
calldata,
};

execute_calls(account, vec![call], fee_args, invoke.nonce, wait_config).await
execute_calls(account, vec![call], fee_args, nonce, wait_config).await
}

pub async fn execute_calls(
Expand Down
Loading

0 comments on commit d8b9b67

Please sign in to comment.