Skip to content

Commit

Permalink
feat: generate deployment artifacts with forc-deploy (#4913)
Browse files Browse the repository at this point in the history
## Description
closes #4744.

This PR adds deployment artifact serialization to forc-deploy. Basically
each deployment info is saved as a json file in the out folder. So that
users wont lose precious deployment information after closing their
terminal.

An example deployment artifact can be seen below:
```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"
}                                                                                                                                                                                                                     
```
Since serde serialization for `ContarctId` and other deployment related
client/vm primitives do not emit 0x at the beginning i had to convert
them to `String`s with 0x prefixed. I feel like we can change human readable
serialization to include 0x to all hex fields by default.
  • Loading branch information
kayagokalp authored Aug 16, 2023
1 parent dbc083f commit 394ee40
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/book/src/forc/plugins/forc_client/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
```
63 changes: 62 additions & 1 deletion forc-plugins/forc-client/src/op/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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<String, Salt>;

/// Takes the contract member salt inputs passed via the --salt option, validates them against
Expand Down Expand Up @@ -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 {
Expand All @@ -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 => {
Expand Down

0 comments on commit 394ee40

Please sign in to comment.