diff --git a/docs/book/src/forc/plugins/forc_client/index.md b/docs/book/src/forc/plugins/forc_client/index.md index 34b96191c0f..ce81872e9e1 100644 --- a/docs/book/src/forc/plugins/forc_client/index.md +++ b/docs/book/src/forc/plugins/forc_client/index.md @@ -69,3 +69,19 @@ Also the default value of the "gas price" parameter is 0 for both `forc-deploy` ```sh forc-deploy --node-url https://beta-3.fuel.network/graphql --gas-price 1 ``` + +## Deployment Artifacts + +forc-deploy saves the details of each deployment in the `out/deployments` folder within the project's root directory. Below is an example of a deployment artifact: + +```json +{ + "transaction_id": "0xec27bb7a4c8a3b8af98070666cf4e6ea22ca4b9950a0862334a1830520012f5d", + "salt": "0x9e35d1d5ef5724f29e649a3465033f5397d3ebb973c40a1d76bb35c253f0dec7", + "network_endpoint": "http://127.0.0.1:4000", + "chain_id": 0, + "contract_id": "0x767eeaa7af2621e637f9785552620e175d4422b17d4cf0d76335c38808608a7b", + "deployment_size": 68, + "deployed_block_id": "0x915c6f372252be6bc54bd70df6362dae9bf750ba652bf5582d9b31c7023ca6cf" +} +``` diff --git a/forc-plugins/forc-client/src/op/deploy.rs b/forc-plugins/forc-client/src/op/deploy.rs index 008e7e11220..92bc43ff9d4 100644 --- a/forc-plugins/forc-client/src/op/deploy.rs +++ b/forc-plugins/forc-client/src/op/deploy.rs @@ -8,14 +8,20 @@ use crate::{ use anyhow::{bail, Context, Result}; use forc_pkg::{self as pkg, PackageManifestFile}; use forc_tx::Gas; +use forc_util::default_output_directory; use fuel_core_client::client::types::TransactionStatus; use fuel_core_client::client::FuelClient; +use fuel_crypto::fuel_types::ChainId; use fuel_tx::{Output, Salt, TransactionBuilder}; use fuel_vm::prelude::*; use futures::FutureExt; use pkg::BuiltPackage; +use serde::{Deserialize, Serialize}; use std::time::Duration; -use std::{collections::BTreeMap, path::PathBuf}; +use std::{ + collections::BTreeMap, + path::{Path, PathBuf}, +}; use sway_core::language::parsed::TreeType; use sway_core::BuildTarget; use tracing::{info, warn}; @@ -25,6 +31,38 @@ pub struct DeployedContract { pub id: fuel_tx::ContractId, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DeploymentArtifact { + transaction_id: String, + salt: String, + network_endpoint: String, + chain_id: ChainId, + contract_id: String, + deployment_size: usize, + deployed_block_id: String, +} + +impl DeploymentArtifact { + pub fn to_file( + &self, + output_dir: &Path, + pkg_name: &str, + contract_id: ContractId, + ) -> Result<()> { + if !output_dir.exists() { + std::fs::create_dir_all(output_dir)?; + } + + let deployment_artifact_json = format!("{pkg_name}-deployment-0x{contract_id}"); + let deployments_path = output_dir + .join(deployment_artifact_json) + .with_extension("json"); + let deployments_file = std::fs::File::create(deployments_path)?; + serde_json::to_writer_pretty(&deployments_file, &self)?; + Ok(()) + } +} + type ContractSaltMap = BTreeMap; /// Takes the contract member salt inputs passed via the --salt option, validates them against @@ -245,6 +283,7 @@ pub async fn deploy_pkg( .await?; let tx = Transaction::from(tx); + let chain_id = client.chain_info().await?.consensus_parameters.chain_id; let deployment_request = client.submit_and_await_commit(&tx).map(|res| match res { Ok(logs) => match logs { @@ -258,6 +297,28 @@ pub async fn deploy_pkg( info!("\nNetwork: {node_url}"); info!("Contract ID: 0x{contract_id}"); info!("Deployed in block {}", &block_id); + + // Create a deployment artifact. + let deployment_size = bytecode.len(); + let deployment_artifact = DeploymentArtifact { + transaction_id: format!("0x{}", tx.id(&chain_id)), + salt: format!("0x{}", salt), + network_endpoint: node_url.to_string(), + chain_id, + contract_id: format!("0x{}", contract_id), + deployment_size, + deployed_block_id: block_id, + }; + + let output_dir = command + .pkg + .output_directory + .as_ref() + .map(PathBuf::from) + .unwrap_or_else(|| default_output_directory(manifest.dir())) + .join("deployments"); + deployment_artifact.to_file(&output_dir, pkg_name, contract_id)?; + Ok(contract_id) } e => {