Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement Pairing API #3

Merged
merged 81 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
0e8b8c3
implement rpc methods
borngraced Aug 30, 2024
900f72f
implement pairing-uri generation from pairing
borngraced Aug 30, 2024
3096073
save dev state
borngraced Aug 30, 2024
9679ee4
save dev state
borngraced Aug 30, 2024
9f73ef1
implement pairing unit test
borngraced Sep 1, 2024
3ab024c
scope mutex guard operation
borngraced Sep 1, 2024
dedf579
move rpc related to rpc crate and some refactorings
borngraced Sep 2, 2024
84febe9
git add files
borngraced Sep 2, 2024
0fe5eff
use async mutex
borngraced Sep 2, 2024
b13def3
minor changes
borngraced Sep 2, 2024
1d540af
minor changes and add doc comment
borngraced Sep 3, 2024
7079def
add more unit tests
borngraced Sep 3, 2024
43057cc
minor changes
borngraced Sep 3, 2024
548a821
cargo clippy
borngraced Sep 3, 2024
c3d8f4e
improve pairing client implementation
borngraced Sep 4, 2024
b4f8b43
use expected message_id for wallet response
borngraced Sep 4, 2024
ab51d8e
print connectino uri
borngraced Sep 4, 2024
656d945
implement pair method
borngraced Sep 4, 2024
1bfb7e2
cargo fmt
borngraced Sep 4, 2024
36e015b
commit uri_parser.rs
borngraced Sep 4, 2024
d0d5118
create common lib
borngraced Sep 5, 2024
8c0c215
commit pairing, uri mod
borngraced Sep 5, 2024
2395848
minor changes
borngraced Sep 6, 2024
e9107b7
cargo clippy fmt
borngraced Sep 6, 2024
f4db2a3
improve pairing code
borngraced Sep 6, 2024
528219f
impl session params
borngraced Sep 6, 2024
ddaf123
commit session files
borngraced Sep 6, 2024
0926bcc
save dev state
borngraced Sep 9, 2024
b955bbb
save dev state
borngraced Sep 9, 2024
3f82d7b
commit wc_common
borngraced Sep 9, 2024
f57b631
refactoring request and response params
borngraced Sep 11, 2024
6757cda
update expiry derivation
borngraced Sep 11, 2024
a85bc6a
minor changes
borngraced Sep 16, 2024
1f1044a
minor changes and fix failing tests
borngraced Sep 16, 2024
76bdbad
delegate pairing topic subscription to client
borngraced Sep 16, 2024
c8f06e0
minor changes
borngraced Sep 18, 2024
8efb1da
fix review notes
borngraced Sep 18, 2024
37c929d
fix cargo clippy
borngraced Sep 19, 2024
71acc1a
use idiomatic code for sym_key gen
borngraced Sep 20, 2024
98211ed
use macro for default impl in PairingClient struct
borngraced Sep 20, 2024
f7bde84
don't append methods to url if empty
borngraced Sep 23, 2024
6740313
Merge branch 'kdf' of github.com:KomodoPlatform/WalletConnectRust int…
borngraced Sep 23, 2024
2af7e1a
fix generate url fn
borngraced Sep 23, 2024
3bfcc41
fix connection uri generator fn
borngraced Sep 26, 2024
c02d999
use Default to initialize PairingClient and minor fix
borngraced Oct 1, 2024
14e9726
fix review notes
borngraced Oct 9, 2024
052ea1d
fix clippy
borngraced Oct 10, 2024
17b1e31
fix disconnect bug
borngraced Oct 10, 2024
974907e
minor changes
borngraced Oct 10, 2024
9836e93
fix pairing delete
borngraced Oct 10, 2024
8175331
use rustls for tokio wss
borngraced Oct 10, 2024
61add9a
remove tokio-rustls dep
borngraced Oct 10, 2024
3ea808b
add sessionProperties to SettleSettle structure
borngraced Oct 11, 2024
91cb115
abstract timestamp check into a function
borngraced Oct 16, 2024
423c67c
revert mod import deletion
borngraced Oct 16, 2024
fd8c7be
extend Params enums with Arbitrary response variant and fix review notes
borngraced Oct 24, 2024
994db68
fix sym_key len check
borngraced Oct 24, 2024
174d386
fix review notes and add caip validation for settle namespaces
borngraced Oct 27, 2024
a271959
export connection_event_loop
borngraced Oct 31, 2024
5c974ad
handle pairing SymKey exporting properly/securely
borngraced Nov 4, 2024
f766404
fix pairing test
borngraced Nov 4, 2024
b427ff0
cargo fmt!!
borngraced Nov 4, 2024
2372fa5
refactor Client new_unmanged and update rand crate
borngraced Nov 6, 2024
90d4008
add doc to PairingClient struct and explicity take Topic as arg
borngraced Nov 8, 2024
f9d9952
handle possible out of bounds error
borngraced Nov 8, 2024
b8040e1
rename expiry, reuse sym_key
borngraced Nov 9, 2024
a7e7339
use DashMap for perfomance
borngraced Nov 9, 2024
cdf38a5
use try_fill_bytes
borngraced Nov 9, 2024
4e09437
debug ws socket dirty close
borngraced Nov 11, 2024
d643b29
fix doc test
borngraced Nov 11, 2024
4a78c4b
debug connection closed
borngraced Nov 12, 2024
95da428
debug ws send
borngraced Nov 12, 2024
9b78f48
debug
borngraced Nov 12, 2024
edd96c9
remove debug log
borngraced Nov 12, 2024
d208b54
nits
borngraced Nov 12, 2024
aab0f30
reuse activate pairing fn
borngraced Nov 19, 2024
eb384d6
fix review notes
borngraced Nov 27, 2024
848d100
don't build example features
borngraced Nov 27, 2024
897cf78
replace dashmap with RwLock
borngraced Nov 28, 2024
99674a0
fix cargo clippy
borngraced Nov 28, 2024
0bd862f
debug ci
borngraced Nov 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions pairing_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "pairing_api"
version = "0.1.0"
edition = "2021"

[features]
example = ["dep:structopt", "dep:tokio", "dep:getrandom"]

[dependencies]
chrono = { version = "0.4", default-features = false, features = [
"std",
Expand All @@ -19,7 +22,7 @@ relay_client = { path = "../relay_client" }
relay_rpc = { path = "../relay_rpc" }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive", "rc"] }
structopt = { version = "0.3", default-features = false }
structopt = { version = "0.3", default-features = false, optional = true }
thiserror = "1.0"
url = "2.3"
wc_common = { path = "../wc_common" }
Expand All @@ -32,11 +35,12 @@ tokio = { version = "1.22", features = [
"macros",
"time",
"signal",
] }
], optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
tokio = { version = "1.22", features = ["sync", "macros"] }
getrandom = { version = "0.2", features = ["js"], optional = true }
tokio = { version = "1.22", features = ["sync", "macros"], optional = true }

[[example]]
name = "pairing"
required-features = ["example"]
1 change: 0 additions & 1 deletion pairing_api/examples/pairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ async fn connect_to_pairing(pairing_client: &PairingClient, client: &Client) ->
b99c41b1219a6c3131f2960e64cc015900b6880b49470e43bf14e9e520bd922d@2?
expiryTimestamp=1725467415&relay-protocol=irn&
symKey=4a7cccd69a33ac0a3debfbee49e8ff0e65edbdc2031ba600e37880f73eb5b638",
true,
)
.unwrap();
client.subscribe(topic.clone()).await.unwrap();
Expand Down
53 changes: 17 additions & 36 deletions pairing_api/src/pairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ use {
};

// Duration for short-term expiry (5 minutes) in seconds.
pub(crate) const EXPIRY_5_MINS: u64 = 300; // 5 mins
/// The relay protocol used for WalletConnect communications.
pub(crate) const EXPIRY_5_MINS: u64 = 300;
// Duration for long-term expiry (30 days) in seconds.
pub(crate) const EXPIRY_30_DAYS: u64 = 24 * 30 * 60 * 60;
/// The relay protocol used for WalletConnect communications.
const RELAY_PROTOCOL: &str = "irn";
/// The version of the WalletConnect protocol.
const VERSION: &str = "2";
/// Pairing Delete error code.
const PAIRING_DELETE_ERROR_CODE: i64 = 6000;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something we need to do when writing doc comments is not to add unnecessary ones, this is the same as the const name and not needed. If a comment doesn't explain something not obvious then it's not needed. For pub items we need doc comments, so we should try to write something that makes it clearer to the user of the sdk.


/// Errors that can occur during pairing operations.
Expand Down Expand Up @@ -102,10 +103,7 @@ pub struct Pairing {
impl Pairing {
pub fn try_from_url(url: &str) -> Result<Self, PairingClientError> {
let parsed = parse_wc_uri(url)?;
let sym_key = hex::decode(parsed.sym_key).map_err(|_| PairingClientError::InvalidSymKey)?;
let sym_key: SymKey = sym_key
.try_into()
.map_err(|_| PairingClientError::InvalidSymKey)?;
let sym_key = parsed.sym_key;
let expiry = parsed.expiry_timestamp;
let relay = Relay {
protocol: parsed.relay_protocol,
Expand Down Expand Up @@ -166,14 +164,14 @@ pub struct PairingClient {
}

impl PairingClient {
/// initializes the client with persisted storage and a network connection
/// Initializes pairing client with in-memory storage
pub fn new() -> Self {
Self::default()
}

/// Calculates and validates the current Unix timestamp
/// to use as a base for pairing expiry times.
fn calc_expiry(&self) -> Result<u64, PairingClientError> {
fn calc_expiry_timestamp(&self) -> Result<u64, PairingClientError> {
let expiry = Utc::now().timestamp();
if expiry < 0 {
return Err(PairingClientError::TimeError(
Expand All @@ -185,14 +183,13 @@ impl PairingClient {
}

/// Attempts to generate a new pairing, stores it in the client's pairing
/// list, subscribes to the pairing topic, and returns the necessary
/// information to establish a connection.
/// list and return the pairing uri and [Topic]
pub fn create(
&self,
metadata: Metadata,
methods: Option<Methods>,
) -> Result<(Topic, String), PairingClientError> {
let expiry = self.calc_expiry()?;
let expiry = self.calc_expiry_timestamp()?;
let topic = Topic::generate();
let relay = Relay {
protocol: RELAY_PROTOCOL.to_owned(),
Expand Down Expand Up @@ -222,22 +219,12 @@ impl PairingClient {
Ok((topic, uri))
}

/// for responder to pair a pairing created by a proposer
pub fn pair(&self, url: &str, activate: bool) -> Result<Topic, PairingClientError> {
let expiry = self.calc_expiry()?;
let mut pairing = Pairing::try_from_url(url)?;
/// for responder to pair a pairing created by a proposer.
/// NOTE: caller is required to call the [PairingClient::activate] method.
/// On a successful pairing creation.
pub fn pair(&self, url: &str) -> Result<Topic, PairingClientError> {
let pairing = Pairing::try_from_url(url)?;
let topic = pairing.pairing.topic.clone();

// Check if the pairing already exists
if self.activate(&topic).is_ok() {
return Ok(topic.clone());
}

// Activate the pairing if requested
if activate {
self.active_impl(&mut pairing, expiry)
}

self.pairings.insert(topic.clone(), pairing);

Ok(topic)
Expand All @@ -257,19 +244,15 @@ impl PairingClient {

/// for either to activate a previously created pairing
pub fn activate(&self, topic: &Topic) -> Result<(), PairingClientError> {
let expiry = self.calc_expiry()?;
if let Some(mut pairing) = self.pairings.get_mut(topic) {
self.active_impl(&mut pairing, expiry)
let expiry = self.calc_expiry_timestamp()?;
pairing.pairing.active = true;
pairing.pairing.expiry = expiry + EXPIRY_30_DAYS;
}

Err(PairingClientError::PairingNotFound)
}

fn active_impl(&self, pairing: &mut Pairing, expiry: u64) {
pairing.pairing.active = true;
pairing.pairing.expiry = expiry + EXPIRY_30_DAYS;
}

/// for either to update the expiry of an existing pairing.
pub fn update_expiry(&self, topic: &Topic, expiry: u64) {
if let Some(mut pairing) = self.pairings.get_mut(topic) {
Expand Down Expand Up @@ -390,15 +373,13 @@ impl PairingClient {
payload: Payload,
client: &Client,
) -> Result<(), PairingClientError> {
// try to extend session before updating local store.
// try to extend session before updating in-memory store.
let sym_key = self.sym_key(topic)?;

let payload = serde_json::to_string(&payload)
.map_err(|err| PairingClientError::EncodeError(err.to_string()))?;
let message = encrypt_and_encode(EnvelopeType::Type0, payload, &sym_key)
.map_err(|err| PairingClientError::EncodeError(err.to_string()))?;

// Publish the encrypted message
{
client
.publish(
Expand Down
7 changes: 6 additions & 1 deletion pairing_api/src/uri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {
std::collections::HashMap,
thiserror::Error,
url::Url,
wc_common::SymKey,
};

lazy_static! {
Expand Down Expand Up @@ -43,7 +44,7 @@ pub enum ParseError {
pub struct ParsedWcUri {
pub topic: Topic,
pub version: String,
pub sym_key: String,
pub sym_key: SymKey,
pub methods: Methods,
pub relay_protocol: String,
pub relay_data: Option<String>,
Expand Down Expand Up @@ -84,6 +85,10 @@ pub fn parse_wc_uri(uri: &str) -> Result<ParsedWcUri, ParseError> {
let methods = parse_methods(methods_str.as_deref())?;

let sym_key = params.remove("symKey").ok_or(ParseError::MissingSymKey)?;
let sym_key = hex::decode(sym_key)
.map_err(|_| ParseError::InvalidSymKey)?
.try_into()
.map_err(|_| ParseError::InvalidSymKey)?;
let relay_protocol = params
.remove("relay-protocol")
.ok_or(ParseError::MissingRelayProtocol)?;
Expand Down
Loading