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

[r2r] MetaMask PoC #1551

Merged
merged 12 commits into from
Dec 5, 2022
Merged

[r2r] MetaMask PoC #1551

merged 12 commits into from
Dec 5, 2022

Conversation

sergeyboyko0791
Copy link

@sergeyboyko0791 sergeyboyko0791 commented Nov 19, 2022

TODOs:

@sergeyboyko0791 sergeyboyko0791 linked an issue Nov 21, 2022 that may be closed by this pull request
@sergeyboyko0791 sergeyboyko0791 self-assigned this Nov 21, 2022
* Add `MetamaskTransport`
* Rename `Web3Transport` to `HttpTransport`
* Add `MetamaskSession` to prevent concurrent requests
@sergeyboyko0791 sergeyboyko0791 changed the title [wip] MetaMask PoC [r2r] MetaMask PoC Nov 22, 2022
Copy link
Member

@artemii235 artemii235 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Few questions and minor proposals for the first iteration.

mm2src/coins/eth/v2_activation.rs Outdated Show resolved Hide resolved
mm2src/coins/eth/v2_activation.rs Outdated Show resolved Hide resolved
mm2src/coins/eth/v2_activation.rs Show resolved Hide resolved
mm2src/crypto/src/crypto_ctx.rs Outdated Show resolved Hide resolved
mm2src/mm2_metamask/src/metamask_provider.rs Show resolved Hide resolved
_ => MmError::err(DispatcherError::NoSuchMethod),
wasm_only_methods => match wasm_only_methods {
"init_metamask::cancel" => handle_mmrpc(ctx, request, cancel_init_metamask).await,
"init_metamask::init" => handle_mmrpc(ctx, request, init_metamask).await,
Copy link
Member

Choose a reason for hiding this comment

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

Do I understand correctly that GUI will first have to invoke init_metamask::init before attempting to initialize e.g. ETH in Metamask mode?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, right

Copy link
Member

Choose a reason for hiding this comment

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

Ok, after thinking for some time, I think it's fine and even good. I hope it won't cause confusion or tricky state tracking on GUI side - will clarify it with Flutter team later 🙂

* Compile `EthRpcMode::Metamask` in WASM only
* Add `rpc_mode: EthRpcMode` to `EthActivationV2Request`
* Update wasm-timer
artemii235
artemii235 previously approved these changes Nov 23, 2022
Copy link
Member

@artemii235 artemii235 left a comment

Choose a reason for hiding this comment

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

Thanks for the great work! I have just one note for the future.

@@ -0,0 +1,168 @@
//! This module is inspired by https://github.com/tomusdrw/rust-web3/blob/master/src/transports/eip_1193.rs
Copy link
Member

Choose a reason for hiding this comment

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

For the next iteration: should we update rust-web3 dependency instead? We use a quite outdated fork now.

Copy link
Author

Choose a reason for hiding this comment

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

This can be difficult due to the fact that Eip1193 transport is local only, so we'll need to make a workaround anyway.
Currently, EthProvider is Send because it's wrapped into the event-driven pattern

Copy link
Member

Choose a reason for hiding this comment

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

This can be difficult due to the fact that Eip1193 transport is local only, so we'll need to make a workaround anyway.

@sergeyboyko0791 Could you please try to find a work around next sprint? It might be great to not reinvent the wheel, if work around itself is not too hard, of course 🙂

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.

Awesome feature implementation 🔥

My first review iteration:

Comment on lines 348 to 356
impl fmt::Debug for EthPrivKeyPolicy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EthPrivKeyPolicy::KeyPair(_) => write!(f, "KeyPair"),
#[cfg(target_arch = "wasm32")]
EthPrivKeyPolicy::Metamask(_) => write!(f, "Metamask"),
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This isn't used. Should we keep it implemented?

Copy link
Author

Choose a reason for hiding this comment

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

Oh, looks like it used to be used before. Will remove it, thanks

Copy link
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 363 to 374
pub fn key_pair(&self) -> Option<&KeyPair> {
match self {
EthPrivKeyPolicy::KeyPair(key_pair) => Some(key_pair),
#[cfg(target_arch = "wasm32")]
EthPrivKeyPolicy::Metamask(_) => None,
}
}

pub fn key_pair_or_err(&self) -> MmResult<&KeyPair, PrivKeyPolicyNotAllowed> {
self.key_pair()
.or_mm_err(|| PrivKeyPolicyNotAllowed::HardwareWalletNotSupported)
}
Copy link
Member

Choose a reason for hiding this comment

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

fn key_pair itself isn't used anywhere. What do you think returning MmResult directly in key_pair fn and remove key_pair_or_err?

Copy link
Author

Choose a reason for hiding this comment

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

I repeated the same methods from lp_coins::PrivKeyPolicy, so how about removing EthPrivKeyPolicy::key_pair method, but leaving EthPrivKeyPolicy::key_pair_or_err as it is? If renaming it to key_pair, it's also worth to rename PrivKeyPolicy::key_pair_or_err. But this will result in changes to files not related to this task.
What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

how about removing EthPrivKeyPolicy::key_pair method, but leaving EthPrivKeyPolicy::key_pair_or_err as it is?

I think it's also fine.

Copy link
Author

Choose a reason for hiding this comment

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

Done

mm2src/coins/eth.rs Show resolved Hide resolved
Comment on lines 52 to 53
/// The function can be used as a default deserialization constructor:
/// `#[serde(default = "EthPrivKeyActivationPolicy::context_priv_key")]`
Copy link
Member

Choose a reason for hiding this comment

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

Is there a specific reason why we didn't implement Default trait for this use case?

Copy link
Author

Choose a reason for hiding this comment

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

No, there is no reason. I think I also can implement Default for lp_coins::PrivKeyActivationPolicy

Copy link
Author

Choose a reason for hiding this comment

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

Done

use web3::helpers::build_request;
use web3::{RequestId, Transport};

const REQUEST_ID: RequestId = 0;
Copy link
Member

Choose a reason for hiding this comment

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

If this is only related with fn prepare, it can be defined there I think. When we see values defined on top-level, it gives an idea that they are used in different spots.

Copy link
Author

Choose a reason for hiding this comment

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

Done

}

#[cfg(test)]
#[inline]
Copy link
Member

Choose a reason for hiding this comment

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

Inlining doesn't help much but increases compilation for tests

Copy link
Author

Choose a reason for hiding this comment

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

Removed it

@@ -44,6 +46,10 @@ impl From<EthActivationV2Error> for EnablePlatformCoinWithTokensError {
EthActivationV2Error::PrivKeyPolicyNotAllowed(e) => {
EnablePlatformCoinWithTokensError::PrivKeyPolicyNotAllowed(e)
},
#[cfg(target_arch = "wasm32")]
EthActivationV2Error::MetamaskCtxNotInitialized => EnablePlatformCoinWithTokensError::PreparationRequired(
"MetaMask context is not initialized. Consider using 'task::init_metamask::init' RPC".to_string(),
Copy link
Member

Choose a reason for hiding this comment

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

What about using RPC method name here?

Suggested change
"MetaMask context is not initialized. Consider using 'task::init_metamask::init' RPC".to_string(),
"MetaMask context is not initialized. Consider using 'init_metamask::init' RPC".to_string(),

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Member

@onur-ozkan onur-ozkan Nov 23, 2022

Choose a reason for hiding this comment

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

Oops. I didn't saw it :)

Can it be task::metamask::init/cancel/status or task::metamask_activation::init/cancel/status ?

Copy link
Author

Choose a reason for hiding this comment

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

This definitely makes sense! My initial though was to follow this naming scheme:
task::<Purpose of the task/what it does>::<An action on the task>, so we could add task::update_metamask::<ACTION> or task::check_metamask::<ACTION> RPCs later.
How about task::connect_metamask::<ACTION>?

Copy link
Member

Choose a reason for hiding this comment

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

How about task::connect_metamask::<ACTION>?

Seems completely fine :)

Copy link
Author

Choose a reason for hiding this comment

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

Done, I decided not to rename related structures like InitMetamaskRequest and functions like CryptoCtx::init_metamask_ctx. Is it fine? I'm afraid there will be many changes.

* Rename `task::init_metamask::*` to `task::connect_metamask::*`
@sergeyboyko0791
Copy link
Author

@ozkanonur PR is ready for the next review :)

shamardy
shamardy previously approved these changes Nov 28, 2022
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

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

Great progress on such an important feature 🔥
Only 2 non-blockers :)

mm2src/mm2_metamask/src/lib.rs Outdated Show resolved Hide resolved
mm2src/mm2_metamask/src/metamask_provider.rs Outdated Show resolved Hide resolved
Copy link
Member

@artemii235 artemii235 left a comment

Choose a reason for hiding this comment

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

Re-approving

@artemii235 artemii235 merged commit 7ea1436 into dev Dec 5, 2022
@artemii235 artemii235 deleted the metamask-poc branch December 5, 2022 10:05
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.

Add possibility to login with metamask-like browser wallets
4 participants