Skip to content

Commit

Permalink
Code refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
smiasojed committed Jan 16, 2024
1 parent 1079a7e commit 0b570fd
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/cargo-contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jsonschema = "0.17"
schemars = "0.8"
ink_metadata = "5.0.0-rc"
crossterm = "0.27.0"
scale-value = "0.13.0"

# dependencies for extrinsics (deploying and calling a contract)
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Expand Down
63 changes: 44 additions & 19 deletions crates/cargo-contract/src/cmd/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ use contract_extrinsics::{
Rpc,
RpcRequest,
};
use contract_transcode::scon::parse_value;
use serde_json::value::RawValue;
use scale_value::{
stringify::{
from_str_custom,
ParseError,
},
Value,
};
use subxt::backend::rpc::RpcParams;

#[derive(Debug, clap::Args)]
#[clap(name = "rpc", about = "Make a raw RPC call")]
Expand Down Expand Up @@ -51,27 +57,46 @@ impl RpcCommand {
pub async fn run(&self) -> Result<(), ErrorVariant> {
let rpc = Rpc::new(&self.url).await?;
let request = RpcRequest::new(rpc);
let str_parser = from_str_custom();
let str_parser = str_parser.add_custom_parser(custom_parse_hex);

let params = self
.params
.iter()
.map(|e| str_parser.parse(e).0)
.collect::<Result<Vec<_>, ParseError>>()
.map_err(|e| anyhow::anyhow!("Function arguments parsing failed: {e}"))?;

let mut params = None;
if !self.params.is_empty() {
let mut json = String::new();
for i in &self.params {
let p = parse_value(i).unwrap();
json = format!("{json}, {}", serde_json::to_string(&p)?);
let params = match params.is_empty() {
true => None,
false => {
params
.iter()
.try_fold(RpcParams::new(), |mut v, e| {
v.push(e)?;
Ok(v)
})
.map_err(|e: subxt::Error| {
anyhow::anyhow!("Method arguments parsing failed: {e}")
})?
.build()
}
json = format!("[{json}]");
println!("{json}");
params = Some(
RawValue::from_string(json)
.map_err(|e| anyhow::anyhow!("Raw Value creation failed: {e}"))?,
);
}
println!("{:?}", self.params);
};

// println!("params: {:?}", params);
let res = request
.exec(&self.method, params)
.raw_call(&self.method, params)
.await
.map_err(|e| anyhow::anyhow!("Err: {}", e))?;
println!("{res}");
.map_err(|e| anyhow::anyhow!("Method call failed: {}", e))?;
let json: serde_json::Value = serde_json::from_str(res.get())?;
println!("{}", serde_json::to_string_pretty(&json)?);
Ok(())
}
}

pub fn custom_parse_hex(s: &mut &str) -> Option<Result<Value<()>, ParseError>> {
if !s.starts_with("0x") {
return None
}
Some(Ok(Value::string(s.to_string())))
}
85 changes: 71 additions & 14 deletions crates/extrinsics/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,100 @@
// You should have received a copy of the GNU General Public License
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use subxt::backend::rpc::{
RawRpcFuture,
RawValue,
RpcClient,
use subxt::{
backend::{
legacy::LegacyRpcMethods,
rpc::{
RawValue,
RpcClient,
},
},
Config,
OnlineClient,
PolkadotConfig,
};

use crate::url_to_string;

use anyhow::Result;
use anyhow::{
anyhow,
bail,
Result,
};

pub struct RpcRequest {
rpc: Rpc,
rpc: Rpc<PolkadotConfig>,
}

impl RpcRequest {
pub fn new(rpc: Rpc) -> Self {
pub fn new(rpc: Rpc<PolkadotConfig>) -> Self {
Self { rpc }
}

pub fn exec<'a>(
pub async fn raw_call<'a>(
&'a self,
method: &'a str,
params: Option<Box<RawValue>>,
) -> RawRpcFuture<'a, Box<RawValue>> {
self.rpc.rpc_client.request_raw(method, params)
) -> Result<Box<RawValue>> {
let methods = self.get_supported_methods().await?;
if !methods.iter().any(|e| e == method) {
bail!(
"Method not found, supported methods: {}",
methods.join(", ")
);
}
self.rpc
.rpc_client
.request_raw(method, params)
.await
.map_err(|e| anyhow!("Raw RPC call failed: {e}"))
}

pub async fn get_supported_methods(&self) -> Result<Vec<String>> {
let raw_value = self
.rpc
.rpc_client
.request_raw("rpc_methods", None)
.await
.map_err(|e| anyhow!("Rpc method call failed: {e}"))?;

let value: serde_json::Value = serde_json::from_str(raw_value.get())?;

let methods = value
.get("methods")
.and_then(|v| v.as_array())
.ok_or_else(|| anyhow!("Methods parsing failed!"))?;
let patterns = ["watch", "unstable", "subscribe"];
let filtered_methods: Vec<String> = methods
.iter()
.filter_map(|v| v.as_str().map(String::from))
.filter(|s| {
patterns
.iter()
.all(|&pattern| !s.to_lowercase().contains(pattern))
})
.collect();

Ok(filtered_methods)
}
}

/// Methods for querying over RPC.
pub struct Rpc {
pub struct Rpc<C: Config> {
rpc_client: RpcClient,
_rpc_methods: LegacyRpcMethods<C>,
_client: OnlineClient<C>,
}

impl Rpc {
impl<C: Config> Rpc<C> {
/// Create a new instance of the Rpc.
pub async fn new(url: &url::Url) -> Result<Self> {
let rpc_client = RpcClient::from_url(url_to_string(url)).await?;
Ok(Self { rpc_client })
let _client = OnlineClient::from_rpc_client(rpc_client.clone()).await?;
let _rpc_methods = LegacyRpcMethods::new(rpc_client.clone());
Ok(Self {
rpc_client,
_rpc_methods,
_client,
})
}
}
4 changes: 4 additions & 0 deletions crates/transcode/src/scon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ impl Seq {
pub fn len(&self) -> usize {
self.elems.len()
}

pub fn is_empty(&self) -> bool {
self.elems.is_empty()
}
}

#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
Expand Down

0 comments on commit 0b570fd

Please sign in to comment.