Skip to content

Commit

Permalink
feat(law): add uri parser to Object
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux authored and amimart committed Mar 23, 2023
1 parent 886bffd commit 3ec96b2
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 18 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ cw2 = "0.15.1"
schemars = "0.8.12"
serde = { version = "1.0.158", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.40" }
serde-json-wasm = "0.5.0"
1 change: 1 addition & 0 deletions contracts/cw-law-stone/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ schemars.workspace = true
serde.workspace = true
thiserror.workspace = true
url = "2.3.1"
serde-json-wasm.workspace = true

[dev-dependencies]
cw-multi-test.workspace = true
Expand Down
22 changes: 21 additions & 1 deletion contracts/cw-law-stone/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use cosmwasm_std::StdError;
use cw_utils::ParseReplyError;
use serde_json_wasm::de::Error;
use thiserror::Error;
use url::ParseError;

Expand Down Expand Up @@ -30,12 +31,31 @@ pub enum ContractError {
}
}

impl ContractError {
pub fn dependency_uri(error: UriError, uri: String) -> ContractError {
ContractError::DependencyUri {
error, uri
}
}
}
#[derive(Error, Debug)]
pub enum UriError {
#[error("{0}")]
Parse(#[from] ParseError),

#[error("Incompatible uri scheme {scheme:?}. Should be {wanted:?}")]
WrongScheme{ scheme: String, wanted: Vec<String> }
WrongScheme{ scheme: String, wanted: Vec<String> },

#[error("The given path doesn't correspond to a cw-storage uri")]
IncompatiblePath,

#[error("URI doesn't contains needed query key")]
MissingQueryKey,

#[error("{0}")]
JSONDecoding(#[from] Error),

#[error("The given query is not compatible")]
IncompatibleQuery,
}

4 changes: 2 additions & 2 deletions contracts/cw-law-stone/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::ContractError;
use crate::state::Object;
use cw_storage::msg::ExecuteMsg as StorageMsg;
use crate::ContractError::NotImplemented;
use crate::uri::uri_to_object;

pub fn get_reply_event_attribute(events: Vec<Event>, key: String) -> Option<String> {
let r = events.iter()
Expand Down Expand Up @@ -39,7 +38,8 @@ pub fn ask_response_to_submsg(res: AskResponse, storage_addr: String, variable:

let mut msgs = vec![];
for uri in uris {
let object = uri_to_object(uri)?;
let url = Url::parse(uri.as_str()).map_err(|e| ContractError::dependency_uri(e.into(), uri.clone()))?;
let object = Object::try_from(url).map_err(|e| ContractError::dependency_uri(e, uri))?;
let msg = WasmMsg::Execute {
contract_addr: storage_addr.to_string(),
msg: to_binary(&StorageMsg::PinObject {
Expand Down
1 change: 0 additions & 1 deletion contracts/cw-law-stone/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ mod error;
pub mod msg;
pub mod state;
mod helper;
mod uri;

pub use crate::error::ContractError;
108 changes: 108 additions & 0 deletions contracts/cw-law-stone/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use std::borrow::Cow;
use std::collections::HashMap;
use cosmwasm_std::Binary;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cw_storage_plus::{Item, Map};
use url::Url;
use crate::ContractError;
use crate::ContractError::NotImplemented;
use crate::error::UriError;
use cw_storage::msg::QueryMsg;

/// State to store context during contract instantiation
pub const INSTANTIATE_CONTEXT: Item<'_, (String, Binary)> = Item::new("instantiate");
Expand All @@ -17,6 +24,107 @@ pub struct Object {
pub storage_address: String,
}

impl Object {
const COSMWASM_SCHEME: &'static str = "cosmwasm";
const COSMWASM_PATH_KEY: &'static str = "cw-storage";
}
impl TryFrom<Url> for Object {
type Error = UriError;

fn try_from(value: Url) -> Result<Self, UriError> {
if value.scheme() != Object::COSMWASM_SCHEME {
return Err(UriError::WrongScheme { scheme: value.scheme().to_string(), wanted: vec![Object::COSMWASM_SCHEME.to_string()] })
}

let path = value.path().to_string();
let paths = path.split(":").collect::<Vec<&str>>();
if paths.len() == 0 || paths.len() > 2 {
return Err(UriError::IncompatiblePath)
}
let storage_address = paths.last().ok_or(UriError::IncompatiblePath)?.to_string();

let queries = value.query_pairs().into_owned().collect::<HashMap<String, String>>();

if let Some(query) = queries.get("query") {
let json: QueryMsg = serde_json_wasm::from_str(query.as_str())?;

return match json {
QueryMsg::ObjectData { id: object_id } => Ok(Object { object_id, storage_address }),
_ => Err(UriError::IncompatibleQuery)
}
}

Err(UriError::MissingQueryKey)
}
}

pub const PROGRAM: Item<'_, Object> = Item::new("program");

pub const DEPENDENCIES: Map<'_, &str, Object> = Map::new("dependencies");

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn object_try_from() {
let cases = vec![
(
"coco:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
Some(UriError::WrongScheme { scheme: "coco".to_string(), wanted: vec!["cosmwasm".to_string()] }),
None
),
(
"cosmwasm:bob:alice:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
Some(UriError::IncompatiblePath),
None
),
(
"cosmwasm:cw-storage:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?q=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
Some(UriError::MissingQueryKey),
None
),
(
"cosmwasm:cw-storage:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?query=%7B%22object%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
Some(UriError::IncompatibleQuery),
None
),
(
"cosmwasm:cw-storage:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
None,
Some(
Object {
object_id: "4cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05".to_string(),
storage_address: "okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s".to_string(),
}
)
),
(
"cosmwasm:okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s?query=%7B%22object_data%22%3A%7B%22id%22%3A%20%224cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05%22%7D%7D".to_string(),
None,
Some(
Object {
object_id: "4cbe36399aabfcc7158ee7a66cbfffa525bb0ceab33d1ff2cff08759fe0a9b05".to_string(),
storage_address: "okp41dclchlcttf2uektxyryg0c6yau63eml5q9uq03myg44ml8cxpxnqavca4s".to_string(),
}
)
),
];

for case in cases {
match Url::parse(case.0.as_str()) {
Ok(url) => {
let result = Object::try_from(url);

if let Some(err) = case.1 {
assert_eq!(err.to_string(), result.unwrap_err().to_string())
}
else if let Some(o) = case.2 {
assert_eq!(o, result.unwrap())
}
}
Err(_) => panic!("no error should be thrown")
}
}
}
}
14 changes: 0 additions & 14 deletions contracts/cw-law-stone/src/uri.rs

This file was deleted.

0 comments on commit 3ec96b2

Please sign in to comment.