From 1c9cfe085a82bf34ad4e7c10d4296a2c53dfd5c1 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Sat, 14 Sep 2024 16:56:58 +0100 Subject: [PATCH] minor changes and code organization --- mm2src/kdf_walletconnect/src/error.rs | 7 +++ mm2src/kdf_walletconnect/src/lib.rs | 50 +++--------------- mm2src/kdf_walletconnect/src/pairing.rs | 46 ++++++++++++++--- mm2src/kdf_walletconnect/src/session.rs | 67 ++++++++++++++++++++++--- 4 files changed, 113 insertions(+), 57 deletions(-) diff --git a/mm2src/kdf_walletconnect/src/error.rs b/mm2src/kdf_walletconnect/src/error.rs index 35f496fd61..7e7679e504 100644 --- a/mm2src/kdf_walletconnect/src/error.rs +++ b/mm2src/kdf_walletconnect/src/error.rs @@ -4,6 +4,8 @@ use relay_client::error::{ClientError, Error}; use relay_rpc::rpc::{PublishError, SubscriptionError}; use serde::{Deserialize, Serialize}; +use crate::session_key::SessionError; + #[derive(Debug, Display, Serialize, Deserialize)] pub enum WalletConnectCtxError { PairingError(String), @@ -15,6 +17,7 @@ pub enum WalletConnectCtxError { InternalError(String), SerdeError(String), UnsuccessfulResponse(String), + SessionError(String), } impl From for WalletConnectCtxError { @@ -36,3 +39,7 @@ impl From> for WalletConnectCtxError { impl From for WalletConnectCtxError { fn from(value: serde_json::Error) -> Self { WalletConnectCtxError::SerdeError(value.to_string()) } } + +impl From for WalletConnectCtxError { + fn from(value: SessionError) -> Self { WalletConnectCtxError::SessionError(value.to_string()) } +} diff --git a/mm2src/kdf_walletconnect/src/lib.rs b/mm2src/kdf_walletconnect/src/lib.rs index b81d7f27c2..1a3fd9cd60 100644 --- a/mm2src/kdf_walletconnect/src/lib.rs +++ b/mm2src/kdf_walletconnect/src/lib.rs @@ -2,8 +2,8 @@ mod error; mod handler; mod inbound_message; mod metadata; -mod pairing; -mod session; +#[allow(unused)] mod pairing; +#[allow(unused)] mod session; mod session_key; use common::{executor::Timer, log::info}; @@ -17,16 +17,13 @@ use metadata::{generate_metadata, AUTH_TOKEN_SUB, PROJECT_ID, RELAY_ADDRESS}; use mm2_err_handle::prelude::MmResult; use mm2_err_handle::prelude::*; use pairing_api::{Methods, PairingClient}; -use rand::rngs::OsRng; use relay_client::{websocket::{Client, PublishedMessage}, ConnectionOptions, MessageIdGenerator}; -use relay_rpc::rpc::params::RelayProtocolMetadata; use relay_rpc::{auth::{ed25519_dalek::SigningKey, AuthToken}, domain::{MessageId, Topic}, - rpc::{params::{session_propose::SessionProposeRequest, IrnMetadata, RequestParams}, - Params, Payload, Request, Response, SuccessfulResponse, JSON_RPC_VERSION_STR}}; -use session::{Session, SessionInfo, SessionType}; -use session_key::SessionKey; + rpc::{params::IrnMetadata, Params, Payload, Request, Response, SuccessfulResponse, + JSON_RPC_VERSION_STR}}; +use session::Session; use std::{sync::Arc, time::Duration}; use wc_common::{decode_and_decrypt_type0, encrypt_and_encode, EnvelopeType}; @@ -123,41 +120,9 @@ impl WalletConnectCtx { .create(metadata.clone(), Some(methods), &self.client) .await?; - let signing_key = SigningKey::generate(&mut OsRng); - let public_key = signing_key.verifying_key(); - let session_key = SessionKey::from_osrng(public_key.as_bytes()) - .map_to_mm(|err| WalletConnectCtxError::EncodeError(err.to_string()))?; - let session_topic: Topic = session_key.generate_topic().into(); - let subscription_id = self - .client - .subscribe(session_topic.clone()) - .await - .map_to_mm(|err| WalletConnectCtxError::SubscriptionError(err.to_string()))?; - let session = SessionInfo::new( - subscription_id, - session_key, - topic.clone(), - metadata, - SessionType::Proposer, - ); - - let session_proposal = RequestParams::SessionPropose(SessionProposeRequest { - relays: vec![session.relay.clone()], - proposer: session.proposer.clone(), - required_namespaces: session.namespaces.clone(), - }); - - { - let mut sessions = self.session.lock().await; - sessions.insert(session_topic.clone(), session); - } - - let irn_metadata = session_proposal.irn_metadata(); - self.publish_request(&topic, session_proposal.into(), irn_metadata) - .await?; + Session::create_proposal_session(self, topic, metadata).await?; - let clean_url = url.replace("&", "&"); - Ok(clean_url) + Ok(url) } pub async fn connect_to_pairing(&self, url: &str, activate: bool) -> MmResult { @@ -248,6 +213,7 @@ impl WalletConnectCtx { Payload::Response(response) => process_inbound_response(self.clone(), response, &msg.topic).await, }; + // TODO: Handle errors. match result { Ok(()) => info!("Inbound message was handled succesfully"), Err(err) => info!("Error while handling inbound message: {err:?}"), diff --git a/mm2src/kdf_walletconnect/src/pairing.rs b/mm2src/kdf_walletconnect/src/pairing.rs index a781722e90..ee637c7169 100644 --- a/mm2src/kdf_walletconnect/src/pairing.rs +++ b/mm2src/kdf_walletconnect/src/pairing.rs @@ -1,11 +1,14 @@ -use crate::{error::WalletConnectCtxError, session::WcRequestResult, WalletConnectCtx}; +use crate::session::{WcRequestResponseResult, THIRTY_DAYS}; +use crate::{error::WalletConnectCtxError, WalletConnectCtx}; -use relay_rpc::rpc::params::RelayProtocolMetadata; +use chrono::Utc; +use relay_rpc::rpc::params::pairing_ping::PairingPingRequest; +use relay_rpc::rpc::params::{RelayProtocolMetadata, RequestParams}; use relay_rpc::{domain::Topic, rpc::params::{pairing_delete::PairingDeleteRequest, pairing_extend::PairingExtendRequest, ResponseParamsSuccess}}; -pub(crate) async fn process_pairing_ping_response() -> WcRequestResult { +pub(crate) async fn process_pairing_ping_response() -> WcRequestResponseResult { let response = ResponseParamsSuccess::PairingPing(true); let irn_metadata = response.irn_metadata(); let value = serde_json::to_value(response).map_err(|err| WalletConnectCtxError::EncodeError(err.to_string()))?; @@ -17,7 +20,7 @@ pub(crate) async fn process_pairing_extend_response( ctx: &WalletConnectCtx, topic: &Topic, extend: PairingExtendRequest, -) -> WcRequestResult { +) -> WcRequestResponseResult { { let mut pairings = ctx.pairing.pairings.lock().await; if let Some(pairing) = pairings.get_mut(topic.as_ref()) { @@ -28,7 +31,7 @@ pub(crate) async fn process_pairing_extend_response( let response = ResponseParamsSuccess::PairingPing(true); let irn_metadata = response.irn_metadata(); - let value = serde_json::to_value(response).map_err(|err| WalletConnectCtxError::EncodeError(err.to_string()))?; + let value = serde_json::to_value(response)?; Ok((value, irn_metadata)) } @@ -37,14 +40,43 @@ pub(crate) async fn process_pairing_delete_response( ctx: &WalletConnectCtx, topic: &Topic, _delete: PairingDeleteRequest, -) -> WcRequestResult { +) -> WcRequestResponseResult { { ctx.pairing.disconnect(topic.as_ref(), &ctx.client).await?; } let response = ResponseParamsSuccess::PairingDelete(true); let irn_metadata = response.irn_metadata(); - let value = serde_json::to_value(response).map_err(|err| WalletConnectCtxError::EncodeError(err.to_string()))?; + let value = serde_json::to_value(response)?; + + Ok((value, irn_metadata)) +} + +pub(crate) async fn pairing_ping_request() -> WcRequestResponseResult { + let request = RequestParams::PairingPing(PairingPingRequest {}); + let irn_metadata = request.irn_metadata(); + let value = serde_json::to_value(request)?; + + Ok((value, irn_metadata)) +} + +pub(crate) async fn pairing_delete_request() -> WcRequestResponseResult { + let request = RequestParams::PairingDelete(PairingDeleteRequest { + code: 6000, + message: "Delete my pairing".to_string(), + }); + let irn_metadata = request.irn_metadata(); + let value = serde_json::to_value(request)?; + + Ok((value, irn_metadata)) +} + +pub(crate) async fn pairing_extend_request() -> WcRequestResponseResult { + let request = RequestParams::PairingExtend(PairingExtendRequest { + expiry: Utc::now().timestamp() as u64 + THIRTY_DAYS, + }); + let irn_metadata = request.irn_metadata(); + let value = serde_json::to_value(request)?; Ok((value, irn_metadata)) } diff --git a/mm2src/kdf_walletconnect/src/session.rs b/mm2src/kdf_walletconnect/src/session.rs index cc30867946..fdaedc353e 100644 --- a/mm2src/kdf_walletconnect/src/session.rs +++ b/mm2src/kdf_walletconnect/src/session.rs @@ -4,6 +4,8 @@ use chrono::Utc; use common::log::info; use futures::lock::Mutex; use mm2_err_handle::prelude::{MapToMmResult, MmResult}; +use rand::rngs::OsRng; +use relay_rpc::auth::ed25519_dalek::SigningKey; use relay_rpc::rpc::params::session_delete::SessionDeleteRequest; use relay_rpc::rpc::params::session_extend::SessionExtendRequest; use relay_rpc::rpc::params::session_propose::Proposer; @@ -20,9 +22,9 @@ use std::ops::Deref; use std::{collections::BTreeMap, sync::Arc}; const FIVE_MINUTES: u64 = 300; -const THIRTY_DAYS: u64 = 60 * 60 * 30; +pub(crate) const THIRTY_DAYS: u64 = 60 * 60 * 30; -pub(crate) type WcRequestResult = MmResult<(Value, IrnMetadata), WalletConnectCtxError>; +pub(crate) type WcRequestResponseResult = MmResult<(Value, IrnMetadata), WalletConnectCtxError>; #[derive(Debug, Clone)] pub enum SessionType { @@ -156,6 +158,52 @@ impl Session { } } + pub(crate) async fn create_proposal_session( + ctx: &WalletConnectCtx, + topic: Topic, + metadata: Metadata, + ) -> MmResult<(), WalletConnectCtxError> { + let (session, session_topic) = { + let signing_key = SigningKey::generate(&mut OsRng); + let public_key = signing_key.verifying_key(); + let session_key = SessionKey::from_osrng(public_key.as_bytes())?; + let session_topic: Topic = session_key.generate_topic().into(); + let subscription_id = ctx + .client + .subscribe(session_topic.clone()) + .await + .map_to_mm(|err| WalletConnectCtxError::SubscriptionError(err.to_string()))?; + + ( + SessionInfo::new( + subscription_id, + session_key, + topic.clone(), + metadata, + SessionType::Proposer, + ), + session_topic, + ) + }; + + { + let mut sessions = ctx.session.lock().await; + sessions.insert(session_topic.clone(), session.clone()); + } + + let session_proposal = RequestParams::SessionPropose(SessionProposeRequest { + relays: vec![session.relay], + proposer: session.proposer, + required_namespaces: session.namespaces, + }); + let irn_metadata = session_proposal.irn_metadata(); + + ctx.publish_request(&topic, session_proposal.into(), irn_metadata) + .await?; + + Ok(()) + } + pub(crate) async fn handle_session_propose_response( &self, session_topic: &Topic, @@ -174,7 +222,7 @@ impl Session { &self, topic: &Topic, extend: SessionExtendRequest, - ) -> WcRequestResult { + ) -> WcRequestResponseResult { let mut sessions = self.session.lock().await; if let Some(session) = sessions.get_mut(topic) { session.expiry = extend.expiry; @@ -195,7 +243,7 @@ impl Session { ctx: &WalletConnectCtx, proposal: SessionProposeRequest, pairing_topic: Topic, - ) -> WcRequestResult { + ) -> WcRequestResponseResult { let sender_public_key = hex::decode(&proposal.proposer.public_key) .map_to_mm(|err| WalletConnectCtxError::EncodeError(err.to_string()))? .as_slice() @@ -240,7 +288,7 @@ impl Session { &self, topic: &Topic, settle: SessionSettleRequest, - ) -> WcRequestResult { + ) -> WcRequestResponseResult { { let mut sessions = self.session.lock().await; if let Some(session) = sessions.get_mut(topic) { @@ -262,7 +310,7 @@ impl Session { Ok((value, irn_metadata)) } - pub(crate) fn process_session_ping_request(&self) -> WcRequestResult { + pub(crate) fn process_session_ping_request(&self) -> WcRequestResponseResult { let response = ResponseParamsSuccess::SessionPing(true); let irn_metadata = response.irn_metadata(); let value = @@ -271,7 +319,10 @@ impl Session { Ok((value, irn_metadata)) } - pub(crate) fn process_session_delete_request(&self, delete_params: SessionDeleteRequest) -> WcRequestResult { + pub(crate) fn process_session_delete_request( + &self, + delete_params: SessionDeleteRequest, + ) -> WcRequestResponseResult { info!( "\nSession is being terminated reason={}, code={}", delete_params.message, delete_params.code, @@ -315,7 +366,7 @@ impl Session { &self, topic: &Topic, update: SessionUpdateRequest, - ) -> WcRequestResult { + ) -> WcRequestResponseResult { let mut sessions = self.session.lock().await; if let Some(session) = sessions.get_mut(topic) { session.settled_namespaces = update.namespaces.clone();