Skip to content

Commit

Permalink
[add] store CRUD operations feature in client cli
Browse files Browse the repository at this point in the history
Signed-off-by: Asem-Abdelhady <asemshawkey@gmail.com>
  • Loading branch information
Asem-Abdelhady committed Dec 22, 2023
1 parent a14d757 commit e955051
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 5 deletions.
101 changes: 97 additions & 4 deletions client_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use iroha_client::{
config::{path::Path as ConfigPath, Configuration as ClientConfiguration},
data_model::prelude::*,
};
use iroha_primitives::addr::SocketAddr;
use iroha_primitives::addr::{Ipv4Addr, Ipv6Addr, SocketAddr};

/// Metadata wrapper, which can be captured from cli arguments (from user supplied file).
#[derive(Debug, Clone)]
Expand All @@ -45,6 +45,24 @@ impl FromStr for Metadata {
}
}

#[derive(Debug, Clone)]
struct ValueArg(Value);

impl FromStr for ValueArg {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<bool>()
.map(Value::Bool)
.or_else(|_| s.parse::<Ipv4Addr>().map(Value::Ipv4Addr))
.or_else(|_| s.parse::<Ipv6Addr>().map(Value::Ipv6Addr))
.or_else(|_| s.parse::<NumericValue>().map(Value::Numeric))
.or_else(|_| s.parse::<PublicKey>().map(Value::PublicKey))
.or_else(|_| serde_json::from_str::<Value>(s).map_err(|e| e.into()))
.map(ValueArg)
}
}

/// Client configuration wrapper. Allows getting itself from arguments from cli (from user supplied file).
#[derive(Debug, Clone)]
struct Configuration(pub ClientConfiguration);
Expand Down Expand Up @@ -663,14 +681,17 @@ mod account {
}

mod asset {
use iroha_client::client::{self, asset, Client};
use iroha_client::{
client::{self, asset, Client},
data_model::{asset::AssetDefinition, name::Name},
};

use super::*;

/// Subcommand for dealing with asset
#[derive(StructOpt, Debug)]
pub enum Args {
/// Register subcommand of asset
/// Command for Registering a new asset
Register(Register),
/// Command for minting asset in existing Iroha account
Mint(Mint),
Expand All @@ -683,13 +704,19 @@ mod asset {
/// List assets
#[clap(subcommand)]
List(List),
/// Put a key-value in a store Asset defintion
SetKeyValue(SetKeyValue),
/// Remove a key-value via key in a store Asset definition
RemoveKeyValue(RemoveKeyValue),
/// Get a value from store Asset definition via key
GetKeyValue(GetKeyValue),
}

impl RunArgs for Args {
fn run(self, context: &mut dyn RunContext) -> Result<()> {
match_all!(
(self, context),
{ Args::Register, Args::Mint, Args::Burn, Args::Transfer, Args::Get, Args::List }
{ Args::Register, Args::Mint, Args::Burn, Args::Transfer, Args::Get, Args::List, Args::SetKeyValue, Args::RemoveKeyValue, Args::GetKeyValue}
)
}
}
Expand Down Expand Up @@ -892,6 +919,72 @@ mod asset {
Ok(())
}
}

#[derive(StructOpt, Debug)]
pub struct SetKeyValue {
/// AssetId for the Store asset (in form of `asset##account@domain_name')
#[structopt(long = "asset-id")]
pub asset_id: AssetId,
/// The key for the store value
#[structopt(long)]
pub key: Name,
/// The value to be associated with the key
#[structopt(long)]
pub value: ValueArg,
}

impl RunArgs for SetKeyValue {
fn run(self, context: &mut dyn RunContext) -> Result<()> {
let Self {
asset_id,
key,
value: ValueArg(value),
} = self;

let set = iroha_client::data_model::isi::SetKeyValue::asset(asset_id, key, value);
submit([set], UnlimitedMetadata::default(), context)?;
Ok(())
}
}
#[derive(StructOpt, Debug)]
pub struct RemoveKeyValue {
#[structopt(long = "asset-id")]
pub asset_id: AssetId,
/// The key for the store value
#[structopt(long)]
pub key: Name,
}

impl RunArgs for RemoveKeyValue {
fn run(self, context: &mut dyn RunContext) -> Result<()> {
let Self { asset_id, key } = self;
let remove = iroha_client::data_model::isi::RemoveKeyValue::asset(asset_id, key);
submit([remove], UnlimitedMetadata::default(), context)?;
Ok(())
}
}

#[derive(StructOpt, Debug)]
pub struct GetKeyValue {
#[structopt(long = "asset-id")]
pub asset_id: AssetId,
// The key for the store value
#[structopt(long)]
pub key: Name,
}

impl RunArgs for GetKeyValue {
fn run(self, context: &mut dyn RunContext) -> Result<()> {
let Self { asset_id, key } = self;
let client = Client::new(context.configuration())?;
let find_key_value = FindAssetKeyValueByIdAndKey::new(asset_id, key.clone());
let asset = client
.request(find_key_value)
.wrap_err("Failed to get key-value")?;
context.print_data(&asset)?;
Ok(())
}
}
}

mod peer {
Expand Down
2 changes: 1 addition & 1 deletion data_model/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ impl FromStr for AssetId {
})?,
account_id.domain_id.clone())
} else {
return Err(ParseError { reason: "The `definition_id` part of the `asset_id` failed to parse. Ensure that you have it in the right format: `name#domain_of_asset#account_name@domain_of_account`." });
return Err(ParseError { reason: "The `definition_id` part of the `asset_id` failed to parse. Ensure that you have it in the right format: `name#domain_of_asset#account_name@domain_of_account` or `name##account_name@domain_of_account` in case of same domain" });
}
};
Ok(Self {
Expand Down

0 comments on commit e955051

Please sign in to comment.