forked from reown-com/reown-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1bfb7e2
commit 36e015b
Showing
1 changed file
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
use { | ||
serde::{Deserialize, Serialize}, | ||
std::collections::HashMap, | ||
thiserror::Error, | ||
url::Url, | ||
}; | ||
|
||
#[derive(Debug, Error)] | ||
pub enum ParseError { | ||
#[error("Invalid URI")] | ||
InvalidUri, | ||
#[error("Missing topic")] | ||
MissingTopic, | ||
#[error("Invalid version")] | ||
InvalidVersion, | ||
#[error("Missing symmetric key")] | ||
MissingSymKey, | ||
#[error("Invalid symmetric key")] | ||
InvalidSymKey, | ||
#[error("Missing methods")] | ||
MissingMethods, | ||
#[error("Invalid methods format")] | ||
InvalidMethods, | ||
#[error("Missing relay protocol")] | ||
MissingRelayProtocol, | ||
#[error("Invalid expiry timestamp")] | ||
InvalidExpiryTimestamp, | ||
#[error("Unexpected parameter: {0}")] | ||
UnexpectedParameter(String), | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct ParsedWcUri { | ||
pub topic: String, | ||
pub version: String, | ||
pub sym_key: String, | ||
pub methods: Methods, | ||
pub relay_protocol: String, | ||
pub relay_data: Option<String>, | ||
pub expiry_timestamp: u64, | ||
} | ||
|
||
pub fn parse_wc_uri(uri: &str) -> Result<ParsedWcUri, ParseError> { | ||
let url = Url::parse(uri).map_err(|_| ParseError::InvalidUri)?; | ||
|
||
if url.scheme() != "wc" { | ||
return Err(ParseError::InvalidUri); | ||
} | ||
|
||
let mut parts = url.path().split('@'); | ||
let topic = parts.next().ok_or(ParseError::MissingTopic)?.to_string(); | ||
let version = parts.next().ok_or(ParseError::InvalidVersion)?.to_string(); | ||
|
||
let mut params = HashMap::new(); | ||
for (key, value) in url.query_pairs() { | ||
params.insert(key.to_string(), value.to_string()); | ||
} | ||
|
||
let methods_str = params.remove("methods"); | ||
let methods = parse_methods(methods_str.as_deref())?; | ||
|
||
let sym_key = params.remove("symKey").ok_or(ParseError::MissingSymKey)?; | ||
let relay_protocol = params | ||
.remove("relay-protocol") | ||
.ok_or(ParseError::MissingRelayProtocol)?; | ||
let relay_data = params.remove("relay-data"); | ||
let expiry_timestamp = params | ||
.remove("expiryTimestamp") | ||
.ok_or(ParseError::InvalidExpiryTimestamp)? | ||
.parse::<u64>() | ||
.map_err(|_| ParseError::InvalidExpiryTimestamp)?; | ||
|
||
// Check for unexpected parameters | ||
if !params.is_empty() { | ||
return Err(ParseError::UnexpectedParameter( | ||
params.keys().next().unwrap().clone(), | ||
)); | ||
} | ||
|
||
Ok(ParsedWcUri { | ||
topic, | ||
version, | ||
sym_key, | ||
methods, | ||
relay_protocol, | ||
relay_data, | ||
expiry_timestamp, | ||
}) | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||
pub struct Methods(pub Vec<Vec<String>>); | ||
|
||
fn parse_methods(methods_str: Option<&str>) -> Result<Methods, ParseError> { | ||
if methods_str.is_none() { | ||
return Ok(Methods(vec![])); | ||
} | ||
|
||
let trimmed = methods_str.unwrap().trim_matches('[').trim_matches(']'); | ||
if trimmed.is_empty() { | ||
return Ok(Methods(vec![])); | ||
} | ||
|
||
let method_groups: Vec<Vec<String>> = trimmed | ||
.split("],[") | ||
.map(|group| { | ||
group | ||
.split(',') | ||
.map(|s| s.trim().to_string()) | ||
.collect::<Vec<String>>() | ||
}) | ||
.collect(); | ||
|
||
Ok(Methods(method_groups)) | ||
} |