Skip to content

Commit

Permalink
chore: clean up interface for info::shared::fetch
Browse files Browse the repository at this point in the history
Follow-up to #1780,
implementing @leighmcculloch's [suggestions].

  [suggestions]: #1780 (review)
  • Loading branch information
chadoh committed Dec 18, 2024
1 parent e347870 commit 9ee88d4
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 46 deletions.
29 changes: 19 additions & 10 deletions cmd/soroban-cli/src/commands/contract/bindings/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ impl NetworkRunnable for Cmd {
) -> Result<(), Error> {
let print = Print::new(global_args.is_some_and(|a| a.quiet));

let (spec, contract_address, network) =
wasm_or_contract::fetch_wasm(&self.wasm_or_hash_or_contract_id, &print).await?;
let wasm_or_contract::Fetched { contract, source } =
wasm_or_contract::fetch(&self.wasm_or_hash_or_contract_id, &print).await?;

let spec = if let Some(spec) = spec {
Spec::new(&spec)?.spec
} else {
soroban_spec::read::parse_raw(&soroban_sdk::token::StellarAssetSpec::spec_xdr())?
let spec = match contract {
wasm_or_contract::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?.spec,
wasm_or_contract::Contract::StellarAssetContract => {
soroban_spec::read::parse_raw(&soroban_sdk::token::StellarAssetSpec::spec_xdr())?
}
};

if self.output_dir.is_file() {
Expand All @@ -88,12 +89,20 @@ impl NetworkRunnable for Cmd {
let contract_name = &file_name
.to_str()
.ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?;
if let Some(contract_address) = contract_address.clone() {
print.infoln(format!("Embedding contract address: {contract_address}"));
}
let (resolved_address, network) = match source {
wasm_or_contract::Source::Contract {
resolved_address,
network,
} => {
print.infoln(format!("Embedding contract address: {resolved_address}"));
(Some(resolved_address), Some(network))
}
wasm_or_contract::Source::Wasm { network, .. } => (None, Some(network)),
wasm_or_contract::Source::File { .. } => (None, None),
};
p.init(
contract_name,
contract_address.as_deref(),
resolved_address.as_deref(),
network.as_ref().map(|n| n.rpc_url.as_ref()),
network.as_ref().map(|n| n.network_passphrase.as_ref()),
&spec,
Expand Down
10 changes: 5 additions & 5 deletions cmd/soroban-cli/src/commands/contract/info/env_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
commands::{
contract::info::{
env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta},
shared::{self, fetch_wasm, MetasInfoOutput},
shared::{self, fetch, Fetched, MetasInfoOutput},
},
global,
},
Expand Down Expand Up @@ -43,12 +43,12 @@ pub enum Error {
impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<String, Error> {
let print = Print::new(global_args.quiet);
let (bytes, ..) = fetch_wasm(&self.common, &print).await?;
let Fetched { contract, .. } = fetch(&self.common, &print).await?;

let Some(bytes) = bytes else {
return Err(NoSACEnvMeta());
let spec = match contract {
shared::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?,
_ => return Err(NoSACEnvMeta()),
};
let spec = Spec::new(&bytes)?;

let Some(env_meta_base64) = spec.env_meta_base64 else {
return Err(NoEnvMetaPresent());
Expand Down
24 changes: 13 additions & 11 deletions cmd/soroban-cli/src/commands/contract/info/interface.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::fmt::Debug;

use crate::commands::contract::info::interface::Error::NoInterfacePresent;
use crate::commands::contract::info::shared;
use crate::commands::contract::info::shared::fetch_wasm;
use crate::commands::contract::info::shared::{self, fetch, Fetched};
use crate::commands::global;
use crate::print::Print;
use clap::{command, Parser};
Expand Down Expand Up @@ -47,18 +46,21 @@ pub enum Error {
impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<String, Error> {
let print = Print::new(global_args.quiet);
let (bytes, ..) = fetch_wasm(&self.common, &print).await?;
let Fetched { contract, .. } = fetch(&self.common, &print).await?;

let (base64, spec) = if bytes.is_none() {
Spec::spec_to_base64(&soroban_sdk::token::StellarAssetSpec::spec_xdr())?
} else {
let spec = Spec::new(&bytes.unwrap())?;
let (base64, spec) = match contract {
shared::Contract::Wasm { wasm_bytes } => {
let spec = Spec::new(&wasm_bytes)?;

if spec.env_meta_base64.is_none() {
return Err(NoInterfacePresent());
}
if spec.env_meta_base64.is_none() {
return Err(NoInterfacePresent());
}

(spec.spec_base64.unwrap(), spec.spec)
(spec.spec_base64.unwrap(), spec.spec)
}
shared::Contract::StellarAssetContract => {
Spec::spec_to_base64(&soroban_sdk::token::StellarAssetSpec::spec_xdr())?
}
};

let res = match self.output {
Expand Down
11 changes: 5 additions & 6 deletions cmd/soroban-cli/src/commands/contract/info/meta.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::fmt::Debug;

use crate::commands::contract::info::meta::Error::{NoMetaPresent, NoSACMeta};
use crate::commands::contract::info::shared;
use crate::commands::contract::info::shared::{fetch_wasm, MetasInfoOutput};
use crate::commands::contract::info::shared::{self, fetch, Fetched, MetasInfoOutput};
use crate::commands::global;
use crate::print::Print;
use clap::{command, Parser};
Expand Down Expand Up @@ -36,12 +35,12 @@ pub enum Error {
impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<String, Error> {
let print = Print::new(global_args.quiet);
let (bytes, ..) = fetch_wasm(&self.common, &print).await?;
let Fetched { contract, .. } = fetch(&self.common, &print).await?;

let Some(bytes) = bytes else {
return Err(NoSACMeta());
let spec = match contract {
shared::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?,
_ => return Err(NoSACMeta()),
};
let spec = Spec::new(&bytes)?;

let Some(meta_base64) = spec.meta_base64 else {
return Err(NoMetaPresent());
Expand Down
78 changes: 64 additions & 14 deletions cmd/soroban-cli/src/commands/contract/info/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,51 @@ pub enum Error {
Locator(#[from] locator::Error),
}

pub async fn fetch_wasm(
args: &Args,
print: &Print,
) -> Result<(Option<Vec<u8>>, Option<String>, Option<Network>), Error> {
pub struct Fetched {
pub contract: Contract,
pub source: Source,
}

pub enum Contract {
Wasm { wasm_bytes: Vec<u8> },
StellarAssetContract,
}

pub enum Source {
File {
path: PathBuf,
},
Wasm {
hash: String,
network: Network,
},
Contract {
resolved_address: String,
network: Network,
},
}

impl Source {
pub fn network(&self) -> Option<&Network> {
match self {
Source::File { .. } => None,
Source::Wasm { ref network, .. } | Source::Contract { ref network, .. } => {
Some(network)
}
}
}
}

pub async fn fetch(args: &Args, print: &Print) -> Result<Fetched, Error> {
// Check if a local WASM file path is provided
if let Some(path) = &args.wasm {
// Read the WASM file and return its contents
print.infoln("Loading contract spec from file...");
let wasm_bytes = wasm::Args { wasm: path.clone() }.read()?;
return Ok((Some(wasm_bytes), None, None));
return Ok(Fetched {
contract: Contract::Wasm { wasm_bytes },
source: Source::File { path: path.clone() },
});
}

// If no local wasm, then check for wasm_hash and fetch from the network
Expand All @@ -116,21 +151,36 @@ pub async fn fetch_wasm(
print.globeln(format!(
"Downloading contract spec for wasm hash: {wasm_hash}"
));
Ok((
Some(get_remote_wasm_from_hash(&client, &hash).await?),
None,
Some(network.clone()),
))
let wasm_bytes = get_remote_wasm_from_hash(&client, &hash).await?;
Ok(Fetched {
contract: Contract::Wasm { wasm_bytes },
source: Source::Wasm {
hash: wasm_hash.clone(),
network: network.clone(),
},
})
} else if let Some(contract_id) = &args.contract_id {
let contract_id =
contract_id.resolve_contract_id(&args.locator, &network.network_passphrase)?;
let contract_address = xdr::ScAddress::Contract(xdr::Hash(contract_id.0)).to_string();
print.globeln(format!("Downloading contract spec: {contract_address}"));
let derived_address = xdr::ScAddress::Contract(xdr::Hash(contract_id.0)).to_string();
print.globeln(format!("Downloading contract spec: {derived_address}"));
let res = wasm::fetch_from_contract(&contract_id, network).await;
if let Some(ContractIsStellarAsset) = res.as_ref().err() {
return Ok((None, Some(contract_address), Some(network.clone())));
return Ok(Fetched {
contract: Contract::StellarAssetContract,
source: Source::Contract {
resolved_address: derived_address,
network: network.clone(),
},
});
}
Ok((Some(res?), Some(contract_address), Some(network.clone())))
Ok(Fetched {
contract: Contract::Wasm { wasm_bytes: res? },
source: Source::Contract {
resolved_address: derived_address,
network: network.clone(),
},
})
} else {
return Err(Error::MalformedWasmOrWasmHashOrContractId);
}
Expand Down

0 comments on commit 9ee88d4

Please sign in to comment.