Skip to content
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

refactor: sign transacitons with ForcClientAccounts instead of raw sdk wallets #6577

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 31 additions & 34 deletions forc-plugins/forc-client/src/op/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use crate::{
cmd,
constants::TX_SUBMIT_TIMEOUT_MS,
util::{
account::ForcClientAccount,
node_url::get_node_url,
pkg::{built_pkgs, create_proxy_contract, update_proxy_address_in_manifest},
target::Target,
tx::{
bech32_from_secret, prompt_forc_wallet_password, select_secret_key,
update_proxy_contract_target, WalletSelectionMode,
prompt_forc_wallet_password, select_account, update_proxy_contract_target,
SignerSelectionMode,
},
},
};
Expand All @@ -24,9 +25,12 @@ use fuel_tx::{Salt, Transaction};
use fuel_vm::prelude::*;
use fuels::{
programs::contract::{LoadConfiguration, StorageConfiguration},
types::{bech32::Bech32ContractId, transaction_builders::Blob},
types::{
bech32::Bech32ContractId,
transaction_builders::{Blob, TransactionBuilder},
},
};
use fuels_accounts::{provider::Provider, wallet::WalletUnlocked, Account};
use fuels_accounts::{provider::Provider, Account, ViewOnlyAccount};
use fuels_core::types::{transaction::TxPolicies, transaction_builders::CreateTransactionBuilder};
use futures::FutureExt;
use pkg::{manifest::build_profile::ExperimentalFlags, BuildProfile, BuiltPackage};
Expand Down Expand Up @@ -158,7 +162,7 @@ async fn deploy_chunked(
command: &cmd::Deploy,
compiled: &BuiltPackage,
salt: Salt,
signing_key: &SecretKey,
account: &ForcClientAccount,
provider: &Provider,
pkg_name: &str,
) -> anyhow::Result<ContractId> {
Expand All @@ -172,7 +176,6 @@ async fn deploy_chunked(
None => "".to_string(),
};

let wallet = WalletUnlocked::new_from_private_key(*signing_key, Some(provider.clone()));
let blobs = compiled
.bytecode
.bytes
Expand All @@ -183,7 +186,7 @@ async fn deploy_chunked(
let tx_policies = tx_policies_from_cmd(command);
let contract_id =
fuels::programs::contract::Contract::loader_from_blobs(blobs, salt, storage_slots)?
.deploy(&wallet, tx_policies)
.deploy(account, tx_policies)
.await?
.into();

Expand All @@ -201,7 +204,7 @@ async fn deploy_new_proxy(
pkg_name: &str,
impl_contract: &fuel_tx::ContractId,
provider: &Provider,
signing_key: &SecretKey,
account: &ForcClientAccount,
) -> Result<ContractId> {
fuels::macros::abigen!(Contract(
name = "ProxyContract",
Expand Down Expand Up @@ -931,8 +934,7 @@ async fn deploy_new_proxy(
}"#,
));
let proxy_dir_output = create_proxy_contract(pkg_name)?;
let address = bech32_from_secret(signing_key)?;
let wallet = WalletUnlocked::new_from_private_key(*signing_key, Some(provider.clone()));
let address = account.address();

let storage_path = proxy_dir_output.join("proxy-storage_slots.json");
let storage_configuration =
Expand All @@ -951,7 +953,7 @@ async fn deploy_new_proxy(
proxy_dir_output.join("proxy.bin"),
configuration,
)?
.deploy(&wallet, tx_policies)
.deploy(account, tx_policies)
.await?
.into();

Expand All @@ -968,7 +970,7 @@ async fn deploy_new_proxy(
);

let proxy_contract_bech_id: Bech32ContractId = proxy_contract_id.into();
let instance = ProxyContract::new(&proxy_contract_bech_id, wallet);
let instance = ProxyContract::new(&proxy_contract_bech_id, account.clone());
instance.methods().initialize_proxy().call().await?;
println_action_green("Initialized", &format!("proxy contract for {pkg_name}"));
Ok(proxy_contract_id)
Expand Down Expand Up @@ -1059,7 +1061,7 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
}

// Confirmation step. Summarize the transaction(s) for the deployment.
let (provider, signing_key) =
let (provider, account) =
confirm_transaction_details(&pkgs_to_deploy, &command, node_url.clone()).await?;

for pkg in pkgs_to_deploy {
Expand Down Expand Up @@ -1087,13 +1089,13 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
&command,
pkg,
salt,
&signing_key,
&account,
&provider,
&pkg.descriptor.name,
)
.await?
} else {
deploy_pkg(&command, pkg, salt, &provider, &signing_key).await?
deploy_pkg(&command, pkg, salt, &provider, &account).await?
};

let proxy_id = match &pkg.descriptor.manifest_file.proxy {
Expand All @@ -1108,13 +1110,8 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
let proxy_contract =
ContractId::from_str(proxy_addr).map_err(|e| anyhow::anyhow!(e))?;

update_proxy_contract_target(
&provider,
signing_key,
proxy_contract,
deployed_contract_id,
)
.await?;
update_proxy_contract_target(&account, proxy_contract, deployed_contract_id)
.await?;
Some(proxy_contract)
}
Some(forc_pkg::manifest::Proxy {
Expand All @@ -1128,7 +1125,7 @@ pub async fn deploy(command: cmd::Deploy) -> Result<Vec<DeployedContract>> {
pkg_name,
&deployed_contract_id,
&provider,
&signing_key,
&account,
)
.await?;

Expand Down Expand Up @@ -1158,7 +1155,7 @@ async fn confirm_transaction_details(
pkgs_to_deploy: &[&Arc<BuiltPackage>],
command: &cmd::Deploy,
node_url: String,
) -> Result<(Provider, SecretKey)> {
) -> Result<(Provider, ForcClientAccount)> {
// Confirmation step. Summarize the transaction(s) for the deployment.
let mut tx_count = 0;
let tx_summary = pkgs_to_deploy
Expand Down Expand Up @@ -1203,27 +1200,26 @@ async fn confirm_transaction_details(
let provider = Provider::connect(node_url.clone()).await?;

let wallet_mode = if command.default_signer || command.signing_key.is_some() {
WalletSelectionMode::Manual
SignerSelectionMode::Manual
} else {
println_action_green("", &format!("Wallet: {}", default_wallet_path().display()));
let password = prompt_forc_wallet_password()?;
WalletSelectionMode::ForcWallet(password)
SignerSelectionMode::ForcWallet(password)
};

// TODO: Display the estimated gas cost of the transaction(s).
// https://github.com/FuelLabs/sway/issues/6277

let signing_key = select_secret_key(
let account = select_account(
&wallet_mode,
command.default_signer || command.unsigned,
command.signing_key,
&provider,
tx_count,
)
.await?
.ok_or_else(|| anyhow::anyhow!("failed to select a signer for the transaction"))?;
.await?;

Ok((provider.clone(), signing_key))
Ok((provider.clone(), account))
}

/// Deploy a single pkg given deploy command and the manifest file
Expand All @@ -1232,7 +1228,7 @@ pub async fn deploy_pkg(
compiled: &BuiltPackage,
salt: Salt,
provider: &Provider,
signing_key: &SecretKey,
account: &ForcClientAccount,
) -> Result<fuel_tx::ContractId> {
let manifest = &compiled.descriptor.manifest_file;
let node_url = provider.url();
Expand All @@ -1255,10 +1251,11 @@ pub async fn deploy_pkg(
storage_slots.clone(),
tx_policies,
);
let wallet = WalletUnlocked::new_from_private_key(*signing_key, Some(provider.clone()));

wallet.add_witnesses(&mut tb)?;
wallet.adjust_for_fee(&mut tb, 0).await?;
account.add_witnesses(&mut tb)?;
account.adjust_for_fee(&mut tb, 0).await?;
tb.add_signer(account.clone())?;

let tx = tb.build(provider).await?;
let tx = Transaction::from(tx);

Expand Down
85 changes: 56 additions & 29 deletions forc-plugins/forc-client/src/op/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@ use crate::{
cmd,
constants::TX_SUBMIT_TIMEOUT_MS,
util::{
gas::get_script_gas_used,
node_url::get_node_url,
pkg::built_pkgs,
tx::{prompt_forc_wallet_password, TransactionBuilderExt, WalletSelectionMode},
tx::{prompt_forc_wallet_password, select_account, SignerSelectionMode},
},
};
use anyhow::{anyhow, bail, Context, Result};
use forc_pkg::{self as pkg, fuel_core_not_running, PackageManifestFile};
use forc_tracing::println_warning;
use forc_util::tx_utils::format_log_receipts;
use fuel_core_client::client::FuelClient;
use fuel_tx::{ContractId, Transaction, TransactionBuilder};
use fuels_accounts::provider::Provider;
use fuel_tx::{ContractId, Transaction};
use fuels::{
programs::calls::{traits::TransactionTuner, ScriptCall},
types::{
bech32::Bech32ContractId,
transaction::TxPolicies,
transaction_builders::{BuildableTransaction, VariableOutputPolicy},
},
};
use fuels_accounts::{provider::Provider, Account};
use fuels_core::types::transaction_builders::TransactionBuilder;
use pkg::{manifest::build_profile::ExperimentalFlags, BuiltPackage};
use std::time::Duration;
use std::{path::PathBuf, str::FromStr};
Expand Down Expand Up @@ -51,10 +59,10 @@ pub async fn run(command: cmd::Run) -> Result<Vec<RanScript>> {
let build_opts = build_opts_from_cmd(&command);
let built_pkgs_with_manifest = built_pkgs(&curr_dir, &build_opts)?;
let wallet_mode = if command.default_signer || command.signing_key.is_some() {
WalletSelectionMode::Manual
SignerSelectionMode::Manual
} else {
let password = prompt_forc_wallet_password()?;
WalletSelectionMode::ForcWallet(password)
SignerSelectionMode::ForcWallet(password)
};
for built in built_pkgs_with_manifest {
if built
Expand All @@ -77,13 +85,34 @@ pub async fn run(command: cmd::Run) -> Result<Vec<RanScript>> {
Ok(receipts)
}

fn tx_policies_from_cmd(cmd: &cmd::Run) -> TxPolicies {
let mut tx_policies = TxPolicies::default();
if let Some(max_fee) = cmd.gas.max_fee {
tx_policies = tx_policies.with_max_fee(max_fee);
}
if let Some(script_gas_limit) = cmd.gas.script_gas_limit {
tx_policies = tx_policies.with_script_gas_limit(script_gas_limit);
}
tx_policies
}

pub async fn run_pkg(
command: &cmd::Run,
manifest: &PackageManifestFile,
compiled: &BuiltPackage,
wallet_mode: &WalletSelectionMode,
signer_mode: &SignerSelectionMode,
) -> Result<RanScript> {
let node_url = get_node_url(&command.node, &manifest.network)?;
let provider = Provider::connect(node_url.clone()).await?;
let tx_count = 1;
let account = select_account(
&signer_mode,
command.default_signer || command.unsigned,
command.signing_key,
&provider,
tx_count,
)
.await?;

let script_data = match (&command.data, &command.args) {
(None, Some(args)) => {
Expand Down Expand Up @@ -116,31 +145,29 @@ pub async fn run_pkg(
})
.collect::<Result<Vec<ContractId>>>()?;

let mut tb = TransactionBuilder::script(compiled.bytecode.bytes.clone(), script_data);
tb.maturity(command.maturity.maturity.into())
.add_contracts(contract_ids);

let provider = Provider::connect(node_url.clone()).await?;

let script_gas_limit = if compiled.bytecode.bytes.is_empty() {
0
} else if let Some(script_gas_limit) = command.gas.script_gas_limit {
script_gas_limit
// Dry run tx and get `gas_used`
} else {
get_script_gas_used(tb.clone().finalize_without_signature_inner(), &provider).await?
let script_binary = compiled.bytecode.bytes.clone();
let external_contracts = contract_ids
.into_iter()
.map(|contract| Bech32ContractId::from(contract))
.collect::<Vec<_>>();
let call = ScriptCall {
script_binary,
encoded_args: Ok(script_data),
inputs: vec![],
outputs: vec![],
external_contracts,
};
tb.script_gas_limit(script_gas_limit);

let tx = tb
.finalize_signed(
Provider::connect(node_url.clone()).await?,
command.default_signer,
command.signing_key,
wallet_mode,
)
let tx_policies = tx_policies_from_cmd(command);
let mut tb = call
.transaction_builder(tx_policies, VariableOutputPolicy::EstimateMinimum, &account)
.await?;

account.add_witnesses(&mut tb)?;
Copy link
Contributor

@alfiedotwtf alfiedotwtf Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add_witnesses() need to be added to ForcClientAccount? Because AFAIC the default implementation is a NOP.

Edit: sorry, I just noticed this is in draft. Ignore this comment 😅

account.adjust_for_fee(&mut tb, 0).await?;
tb.add_signer(account)?;

let tx = tb.build(provider).await?;

if command.dry_run {
info!("{:?}", tx);
Ok(RanScript { receipts: vec![] })
Expand Down
Loading
Loading