1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
//! This module provides simple utilities for loading and parsing `.contract` files in context of `drink` tests.
use std::{path::PathBuf, rc::Rc};
use contract_metadata::ContractMetadata;
use contract_transcode::ContractMessageTranscoder;
use crate::{DrinkResult, Error};
/// A struct representing the result of parsing a `.contract` bundle file.
///
/// It can be used with the following methods of the `Session` struct:
/// - `deploy_bundle`
/// - `deploy_bundle_and`
/// - `upload_bundle`
/// - `upload_bundle_and`
#[derive(Clone)]
pub struct ContractBundle {
/// WASM blob of the contract
pub wasm: Vec<u8>,
/// Transcoder derived from the ABI/metadata
pub transcoder: Rc<ContractMessageTranscoder>,
}
impl ContractBundle {
/// Load and parse the information in a `.contract` bundle under `path`, producing a
/// `ContractBundle` struct.
pub fn load<P>(path: P) -> DrinkResult<Self>
where
P: AsRef<std::path::Path>,
{
let metadata: ContractMetadata = ContractMetadata::load(&path).map_err(|e| {
Error::BundleLoadFailed(format!("Failed to load the contract file:\n{e:?}"))
})?;
let ink_metadata = serde_json::from_value(serde_json::Value::Object(metadata.abi))
.map_err(|e| {
Error::BundleLoadFailed(format!(
"Failed to parse metadata from the contract file:\n{e:?}"
))
})?;
let transcoder = Rc::new(ContractMessageTranscoder::new(ink_metadata));
let wasm = metadata
.source
.wasm
.ok_or(Error::BundleLoadFailed(
"Failed to get the WASM blob from the contract file".to_string(),
))?
.0;
Ok(Self { wasm, transcoder })
}
/// Load the `.contract` bundle (`contract_file_name`) located in the `project_dir`` working directory.
///
/// This is meant to be used predominantly by the `local_contract_file!` macro.
pub fn local(project_dir: &str, contract_file_name: String) -> Self {
let mut path = PathBuf::from(project_dir);
path.push("target");
path.push("ink");
path.push(contract_file_name);
Self::load(path).expect("Loading the local bundle failed")
}
}
/// A convenience macro that allows you to load a bundle found in the target directory
/// of the current project.
#[macro_export]
macro_rules! local_contract_file {
() => {
drink::ContractBundle::local(
env!("CARGO_MANIFEST_DIR"),
env!("CARGO_CRATE_NAME").to_owned() + ".contract",
)
};
}