forc 0.3.3

Fuel Orchestrator.
Documentation
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)?;

            // parse the main file and check is it a contract
            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,
    )
}