Skip to content

Commit

Permalink
Move transcode example to doc test, add helper method (#705)
Browse files Browse the repository at this point in the history
* Move transcode example to doc test

* Fmt

* Remove spaces in example

* Fix example

* Fix typo

* Refactor transcoder construction to provide helper method

* Fix tests

* Fix example

* Add comment

* Don't run transcoder doc test

* Update transcode version

* Cargo.lock

* Publish transcode package
  • Loading branch information
ascjones authored Aug 24, 2022
1 parent 21a3501 commit 8708023
Show file tree
Hide file tree
Showing 14 changed files with 154 additions and 153 deletions.
1 change: 1 addition & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ test-registry-publish-install:
- echo -e '[registries]\nestuary = { index = "http://0.0.0.0:7878/git/index" }' > .cargo/config.toml
- echo 0000 | cargo login --registry estuary
- rusty-cachier snapshot create
- cd transcode && cargo publish --registry estuary && cd ..
- cargo publish --registry estuary
- cargo install cargo-contract --index http://0.0.0.0:7878/git/index

Expand Down
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ toml = "0.5.9"
rustc_version = "0.4.0"
blake2 = "0.10.4"
contract-metadata = { version = "1", path = "./metadata" }
transcode = { package = "contract-transcode", version = "0.1.0", path = "./transcode" }
transcode = { package = "contract-transcode", version = "0.2.0", path = "./transcode" }
semver = { version = "1.0.13", features = ["serde"] }
serde = { version = "1.0.144", default-features = false, features = ["derive"] }
serde_json = "1.0.85"
Expand All @@ -47,7 +47,6 @@ regex = "1.6.0"

# dependencies for extrinsics (deploying and calling a contract)
async-std = { version = "1.12.0", features = ["attributes", "tokio1"] }
ink_metadata = { version = "3.3", features = ["derive"] }
sp-core = "6.0.0"
pallet-contracts-primitives = "6.0.0"
subxt = "0.23.0"
Expand Down
10 changes: 4 additions & 6 deletions src/cmd/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use crate::{
cmd::extrinsics::{
load_metadata,
ContractMessageTranscoder,
},
crate_metadata::CrateMetadata,
util::decode_hex,
DEFAULT_KEY_COL_WIDTH,
};
Expand All @@ -27,6 +24,7 @@ use anyhow::{
Result,
};
use colored::Colorize as _;
use transcode::ContractMessageTranscoder;

#[derive(Debug, Clone, clap::Args)]
#[clap(
Expand All @@ -51,8 +49,8 @@ enum DataType {

impl DecodeCommand {
pub fn run(&self) -> Result<()> {
let (_, contract_metadata) = load_metadata(None)?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let crate_metadata = CrateMetadata::from_manifest_path(None)?;
let transcoder = ContractMessageTranscoder::load(crate_metadata.metadata_path())?;

const ERR_MSG: &str = "Failed to decode specified data as a hex value";
let decoded_data = match self.r#type {
Expand Down
11 changes: 6 additions & 5 deletions src/cmd/extrinsics/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ use super::{
display_contract_exec_result,
display_events,
error_details,
load_metadata,
parse_balance,
prompt_confirm_tx,
state_call,
submit_extrinsic,
Balance,
Client,
ContractMessageTranscoder,
CrateMetadata,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand Down Expand Up @@ -74,9 +74,10 @@ pub struct CallCommand {

impl CallCommand {
pub fn run(&self) -> Result<()> {
let (_, contract_metadata) =
load_metadata(self.extrinsic_opts.manifest_path.as_ref())?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let crate_metadata = CrateMetadata::from_manifest_path(
self.extrinsic_opts.manifest_path.as_ref(),
)?;
let transcoder = ContractMessageTranscoder::load(crate_metadata.metadata_path())?;
let call_data = transcoder.encode(&self.message, &self.args)?;
tracing::debug!("Message data: {:?}", hex::encode(&call_data));

Expand Down Expand Up @@ -146,7 +147,7 @@ impl CallCommand {
client: &Client,
data: Vec<u8>,
signer: &PairSigner,
transcoder: &ContractMessageTranscoder<'_>,
transcoder: &ContractMessageTranscoder,
) -> Result<()> {
tracing::debug!("calling contract {:?}", self.contract);

Expand Down
6 changes: 5 additions & 1 deletion src/cmd/extrinsics/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ pub fn display_events(
name
});

let decoded_field = events_transcoder.decode(*field_ty, event_data)?;
let decoded_field = events_transcoder.decode(
&runtime_metadata.types,
*field_ty,
event_data,
)?;
maybe_println!(
verbosity,
"{:width$}{}",
Expand Down
14 changes: 8 additions & 6 deletions src/cmd/extrinsics/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use super::{
CodeHash,
ContractAccount,
ContractMessageTranscoder,
CrateMetadata,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand Down Expand Up @@ -121,9 +122,10 @@ impl InstantiateCommand {
/// Creates an extrinsic with the `Contracts::instantiate` Call, submits via RPC, then waits for
/// the `ContractsEvent::Instantiated` event.
pub fn run(&self) -> Result<()> {
let (crate_metadata, contract_metadata) =
super::load_metadata(self.extrinsic_opts.manifest_path.as_ref())?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let crate_metadata = CrateMetadata::from_manifest_path(
self.extrinsic_opts.manifest_path.as_ref(),
)?;
let transcoder = ContractMessageTranscoder::load(crate_metadata.metadata_path())?;
let data = transcoder.encode(&self.constructor, &self.args)?;
let signer = super::pair_signer(self.extrinsic_opts.signer()?);
let url = self.extrinsic_opts.url_to_string();
Expand Down Expand Up @@ -190,17 +192,17 @@ struct InstantiateArgs {
salt: Vec<u8>,
}

pub struct Exec<'a> {
pub struct Exec {
opts: ExtrinsicOpts,
args: InstantiateArgs,
verbosity: Verbosity,
url: String,
client: Client,
signer: PairSigner,
transcoder: ContractMessageTranscoder<'a>,
transcoder: ContractMessageTranscoder,
}

impl<'a> Exec<'a> {
impl Exec {
async fn exec(&self, code: Code, dry_run: bool) -> Result<()> {
tracing::debug!("instantiate data {:?}", self.args.data);
if dry_run {
Expand Down
37 changes: 0 additions & 37 deletions src/cmd/extrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use jsonrpsee::{
ws_client::WsClientBuilder,
};
use std::{
fs::File,
io::{
self,
Write,
Expand All @@ -48,7 +47,6 @@ use self::events::display_events;
use crate::{
crate_metadata::CrateMetadata,
name_value_println,
workspace::ManifestPath,
Verbosity,
VerbosityFlags,
DEFAULT_KEY_COL_WIDTH,
Expand All @@ -58,7 +56,6 @@ use scale::{
Decode,
Encode,
};
use serde_json::Value;
use sp_core::{
crypto::Pair,
sr25519,
Expand Down Expand Up @@ -144,40 +141,6 @@ impl ExtrinsicOpts {
}
}

/// For a contract project with its `Cargo.toml` at the specified `manifest_path`, load the cargo
/// [`CrateMetadata`] along with the contract metadata [`ink_metadata::InkProject`].
pub fn load_metadata(
manifest_path: Option<&PathBuf>,
) -> Result<(CrateMetadata, ink_metadata::InkProject)> {
let manifest_path = ManifestPath::try_from(manifest_path)?;
let crate_metadata = CrateMetadata::collect(&manifest_path)?;
let path = crate_metadata.metadata_path();

if !path.exists() {
return Err(anyhow!(
"Metadata file not found. Try building with `cargo contract build`."
))
}

let file = File::open(&path)
.context(format!("Failed to open metadata file {}", path.display()))?;
let metadata: contract_metadata::ContractMetadata = serde_json::from_reader(file)
.context(format!(
"Failed to deserialize metadata file {}",
path.display()
))?;
let ink_metadata =
serde_json::from_value(Value::Object(metadata.abi)).context(format!(
"Failed to deserialize ink project metadata from file {}",
path.display()
))?;
if let ink_metadata::MetadataVersioned::V3(ink_project) = ink_metadata {
Ok((crate_metadata, ink_project))
} else {
Err(anyhow!("Unsupported ink metadata version. Expected V1"))
}
}

/// Parse Rust style integer balance literals which can contain underscores.
fn parse_balance(input: &str) -> Result<Balance> {
input
Expand Down
10 changes: 6 additions & 4 deletions src/cmd/extrinsics/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use super::{
Client,
CodeHash,
ContractMessageTranscoder,
CrateMetadata,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand Down Expand Up @@ -59,9 +60,10 @@ pub struct UploadCommand {

impl UploadCommand {
pub fn run(&self) -> Result<()> {
let (crate_metadata, contract_metadata) =
super::load_metadata(self.extrinsic_opts.manifest_path.as_ref())?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let crate_metadata = CrateMetadata::from_manifest_path(
self.extrinsic_opts.manifest_path.as_ref(),
)?;
let transcoder = ContractMessageTranscoder::load(crate_metadata.metadata_path())?;
let signer = super::pair_signer(self.extrinsic_opts.signer()?);

let wasm_path = match &self.wasm_path {
Expand Down Expand Up @@ -135,7 +137,7 @@ impl UploadCommand {
client: &Client,
code: Vec<u8>,
signer: &PairSigner,
transcoder: &ContractMessageTranscoder<'_>,
transcoder: &ContractMessageTranscoder,
) -> Result<Option<api::contracts::events::CodeStored>> {
let call = super::runtime_api::api::tx()
.contracts()
Expand Down
6 changes: 6 additions & 0 deletions src/crate_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ pub struct CrateMetadata {
}

impl CrateMetadata {
/// Attempt to construct [`CrateMetadata`] from the given manifest path.
pub fn from_manifest_path(manifest_path: Option<&PathBuf>) -> Result<Self> {
let manifest_path = ManifestPath::try_from(manifest_path)?;
Self::collect(&manifest_path)
}

/// Parses the contract manifest and returns relevant metadata.
pub fn collect(manifest_path: &ManifestPath) -> Result<Self> {
let (metadata, root_package) = get_cargo_metadata(manifest_path)?;
Expand Down
2 changes: 1 addition & 1 deletion transcode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "contract-transcode"
version = "0.1.0"
version = "0.2.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2021"

Expand Down
35 changes: 1 addition & 34 deletions transcode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,4 @@ Contains utilities for encoding smart contract calls to SCALE.
Currently part of [`cargo-contract`](https://github.com/paritytech/cargo-contract), the build tool for smart
contracts written in [ink!](https://github.com/paritytech/ink).


# Example

```rust
use transcode::ContractMessageTranscoder;

fn main() {
let metadata_path = "/path/to/metadata.json";

let metadata = load_metadata(&metadata_path.into())?;
let transcoder = ContractMessageTranscoder::new(&metadata);

let constructor = "new";
let args = ["foo", "bar"];
let data = transcoder.encode(&constructor, &args).unwrap();

println!("Encoded constructor data {:?}", data);
}

fn load_metadata(path: &Path) -> anyhow::Result<ink_metadata::InkProject> {
let file = File::open(&path).expect("Failed to open metadata file");
let metadata: ContractMetadata =
serde_json::from_reader(file).expect("Failed to deserialize metadata file");
let ink_metadata = serde_json::from_value(serde_json::Value::Object(metadata.abi))
.expect("Failed to deserialize ink project metadata");

if let ink_metadata::MetadataVersioned::V3(ink_project) = ink_metadata {
Ok(ink_project)
} else {
Err(anyhow!("Unsupported ink metadata version. Expected V3"))
}
}

```
See [crate docs](https://docs.rs/contract-transcode/latest/contract_transcode/) for example usage.
Loading

0 comments on commit 8708023

Please sign in to comment.