use fuel_gql_client::client::FuelClient;
use fuel_tx::{Output, Salt, Transaction};
use fuel_vm::prelude::*;
use sway_core::{parse, TreeType};
use crate::cli::{BuildCommand, DeployCommand};
use crate::ops::forc_build;
use crate::utils::cli_error::CliError;
use crate::utils::helpers;
use helpers::{get_main_file, read_manifest};
use std::path::PathBuf;
use sway_utils::{constants::*, find_manifest_dir};
pub async fn deploy(command: DeployCommand) -> Result<fuel_tx::ContractId, CliError> {
let curr_dir = if let Some(ref path) = command.path {
PathBuf::from(path)
} else {
std::env::current_dir()?
};
let DeployCommand {
path,
use_ir,
print_finalized_asm,
print_intermediate_asm,
print_ir,
binary_outfile,
offline_mode,
silent_mode,
} = command;
match find_manifest_dir(&curr_dir) {
Some(manifest_dir) => {
let manifest = read_manifest(&manifest_dir)?;
let project_name = &manifest.project.name;
let main_file = get_main_file(&manifest, &manifest_dir)?;
let parsed_result = parse(main_file, None);
match parsed_result.value {
Some(parse_tree) => match parse_tree.tree_type {
TreeType::Contract => {
let build_command = BuildCommand {
path,
use_ir,
print_finalized_asm,
print_intermediate_asm,
print_ir,
binary_outfile,
offline_mode,
silent_mode,
};
let compiled_contract = forc_build::build(build_command)?;
let (tx, contract_id) = create_contract_tx(
compiled_contract,
Vec::<fuel_tx::Input>::new(),
Vec::<fuel_tx::Output>::new(),
);
let node_url = match &manifest.network {
Some(network) => &network.url,
_ => DEFAULT_NODE_URL,
};
let client = FuelClient::new(node_url)?;
match client.submit(&tx).await {
Ok(logs) => {
println!("Logs:\n{:?}", logs);
Ok(contract_id)
}
Err(e) => Err(e.to_string().into()),
}
}
TreeType::Script => Err(CliError::wrong_sway_type(
project_name,
SWAY_CONTRACT,
SWAY_SCRIPT,
)),
TreeType::Predicate => Err(CliError::wrong_sway_type(
project_name,
SWAY_CONTRACT,
SWAY_PREDICATE,
)),
TreeType::Library { .. } => Err(CliError::wrong_sway_type(
project_name,
SWAY_CONTRACT,
SWAY_LIBRARY,
)),
},
None => Err(CliError::parsing_failed(project_name, parsed_result.errors)),
}
}
None => Err(CliError::manifest_file_missing(curr_dir)),
}
}
fn create_contract_tx(
compiled_contract: Vec<u8>,
inputs: Vec<Input>,
outputs: Vec<Output>,
) -> (Transaction, fuel_tx::ContractId) {
let gas_price = 0;
let gas_limit = 10000000;
let maturity = 0;
let bytecode_witness_index = 0;
let witnesses = vec![compiled_contract.clone().into()];
let salt = Salt::new([0; 32]);
let static_contracts = vec![];
let contract = Contract::from(compiled_contract);
let root = contract.root();
let id = contract.id(&salt, &root);
println!("Contract id: 0x{}", hex::encode(id));
let outputs = [&[Output::ContractCreated { contract_id: id }], &outputs[..]].concat();
(
Transaction::create(
gas_price,
gas_limit,
maturity,
bytecode_witness_index,
salt,
static_contracts,
inputs,
outputs,
witnesses,
),
id,
)
}