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(walletconnect): walletconnect client #2183

Closed
wants to merge 29 commits into from
Closed

Conversation

borngraced
Copy link
Member

@borngraced borngraced commented Jul 30, 2024

Originally, the WalletConnect client implementation only supported non-WASM targets. In this pull request (PR), I have ported the WebSocket client code and modified it to be compatible with both WASM and non-WASM targets.

While some code might change when implementing the session/pairing API in my next PR, this provides a functional WebSocket client implementation for WalletConnect as it stands.

@borngraced borngraced self-assigned this Jul 30, 2024
@borngraced borngraced changed the title [feat]: WalletConnect Client feat(walletconnect): WalletConnect Client Aug 7, 2024
@shamardy shamardy requested a review from onur-ozkan August 12, 2024 12:34
Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

Let's try to make unrelated changes in a separate PR next time. It adds more changes to review and makes it harder to identify the actual work.

I haven't reviewed the logical parts yet, but here are some notes from a quick review iteration:

mm2src/kdf_walletconnect/Cargo.toml Outdated Show resolved Hide resolved
mm2src/mm2_main/Cargo.toml Outdated Show resolved Hide resolved
mm2src/kdf_walletconnect/src/lib.rs Outdated Show resolved Hide resolved
mm2src/kdf_walletconnect/src/lib.rs Outdated Show resolved Hide resolved
mm2src/crypto/src/mnemonic.rs Outdated Show resolved Hide resolved
Cargo.lock Outdated Show resolved Hide resolved
mm2src/mm2_main/Cargo.toml Outdated Show resolved Hide resolved
//! Initially, the implementation was restricted to non-WASM targets,
//! which limited its utility in web-based environments.
//!
//! This module contains the WebSocket client code that has been ported and modified to achieve cross-platform compatibility.
Copy link
Member

Choose a reason for hiding this comment

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

Can we reference the actual crate here? We might want to review it later to see any improvements they have made.

Copy link
Member

Choose a reason for hiding this comment

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

Also, why did we hard-code/port the entire crate here instead of forking it? Porting the entire source code brings some challanges (such as not being able to track the difference between us and upstream in the future).

Copy link
Member Author

Choose a reason for hiding this comment

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

the library is still in its early stages and not very useful at the moment. Important features like the sign API and session management haven’t been implemented yet, so there might be more changes needed when integrating the sign API in the next iteration. So I think it’s reasonable to proceed with porting it..

cc. @onur-ozkan @shamardy

Copy link
Member

Choose a reason for hiding this comment

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

IMO we can still do the same with forking the repository and maintaining it separately. We can publish it to crates.io as well once it's well documented.

Copy link
Member Author

Choose a reason for hiding this comment

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

agreed!

@borngraced borngraced changed the title feat(walletconnect): WalletConnect Client feat(walletconnect): walletconnect client Aug 13, 2024
Copy link
Collaborator

@mariocynicys mariocynicys left a comment

Choose a reason for hiding this comment

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

Thanks!
First review iteration.

mm2src/kdf_walletconnect/src/client/connection.rs Outdated Show resolved Hide resolved
stream.close().await?;
}

Err(WebsocketClientError::TransportError("Error while closing connection".to_owned()).into())
Copy link
Collaborator

Choose a reason for hiding this comment

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

is that a transport error tho? I think that should be NotConnected.

p.s. we don't have to error anyways, unless this info is used by the caller.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm leaving the fn to return Result for now..

},

Err(err) => {
tx.send(Err(ClientError::SerdeError(err.to_string()))).ok();
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think we better call this deserialization error instead of serde.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

Comment on lines 34 to 35
#[from_stringify("serde_json::Error")]
SerdeError(String),
Copy link
Collaborator

Choose a reason for hiding this comment

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

if this covers also serialization errors, it would be more specific if we make two instances of these (one for serialization and one for deserialization).

Copy link
Member Author

Choose a reason for hiding this comment

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

done

match data {
Some(result) => {
if let Some(event) =
self.parse_inbound(result.map_err(|err| WebsocketClientError::TransportError(err.to_string())))
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: would be nicer if we handle the erroring case of the result here and only parse_inbound the valid msgs.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

Comment on lines +147 to +148
InboundRequest::new(id, data, self.outbound_tx.clone()),
),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't really follow why we use an unbounded response channel here?
isn't it gonne be just one resposne? it also seems not to be used anywhere later in PublishedMessage.

Copy link
Member Author

Choose a reason for hiding this comment

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

note: This code is part of original code from WalletConnect, I also had similar question but I think there might be a good reason to use unbounded_channel e.g when we don't want to miss a message or have sender blocking

Comment on lines 21 to 25
/// Inbound request for receiving a subscription message.
///
/// Currently, [`Subscription`] is the only request that the Relay sends to
/// the clients.
InboundSubscriptionRequest(InboundRequest<Subscription>),
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: I would go for calling this just plain InboundRequest to be general and not mention specific names in this enum. and move the possible request types (currently only this one) into another enum.

Comment on lines +74 to +75
} else if self.has_more {
let (req, fut) = create_request(self.request.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Q: won't this fetch the same request over and over again?

i mean, if we end up with a batch_fut that has_more, i expect the next time we call create_request we specify some different request construction that tells where did the last batch stop.

Copy link
Member Author

@borngraced borngraced Aug 13, 2024

Choose a reason for hiding this comment

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

won't this fetch the same request over and over again

No, it won't and sending same request using same Topics make sense for streaming messages for some given Topics.

the rpc includes has_more in FetchMessages response body which is later used to update our internal has_more here

self.batch = Some(data.messages.into_iter());
self.has_more = data.has_more;
self.batch_fut = None;

and then we check this condition to make another request with same Topic only if batch and batch_fut is none.
} else if self.has_more {
let (req, fut) = create_request(self.request.clone());
self.client.request(req);
self.batch_fut = Some(fut);

What I'm saying is that, I believe WalletConnect RPC def uses has_more internally to stream the request to our client to prevent duplicates.

Does this make sense @mariocynicys

Copy link
Member

Choose a reason for hiding this comment

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

Is it your editor making these changes automatically, or are you making them intentionally?

Copy link
Member Author

Choose a reason for hiding this comment

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

that's my editor.. sorry 🙁

Copy link
Member

Choose a reason for hiding this comment

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

The formatting is fine, it's just too much out-of-context change for a feature PR in my opinion

Copy link
Member Author

@borngraced borngraced Aug 15, 2024

Choose a reason for hiding this comment

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

...and the formatting in some Cargo.toml files aren't consistent enough

Comment on lines 23 to 25
trezor-udp = [
"crypto/trezor-udp",
] # use for tests to connect to trezor emulator over udp
Copy link
Member

@onur-ozkan onur-ozkan Aug 15, 2024

Choose a reason for hiding this comment

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

This seems quite bad way of formatting things..

@@ -34,6 +34,7 @@ mm2_err_handle = { path = "../mm2_err_handle" }
num-traits = "0.2"
parking_lot = { version = "0.12.0", features = ["nightly"] }
primitives = { path = "../mm2_bitcoin/primitives" }
rand = { version = "0.8.0", features = ["std", "small_rng"] }
Copy link
Member

Choose a reason for hiding this comment

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

Any reason?

Copy link
Member Author

Choose a reason for hiding this comment

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

had problem with rand crate earlier.. will revert

@borngraced
Copy link
Member Author

closing in favor of KomodoPlatform/WalletConnectRust#1

@borngraced borngraced closed this Aug 18, 2024
@borngraced borngraced deleted the walletconnect branch August 18, 2024 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants