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

RequiredNamespaces return by dapps is not well managed [code: 5102] #230

Closed
Fabrice-Fabio opened this issue Dec 5, 2023 · 8 comments
Closed

Comments

@Fabrice-Fabio
Copy link

Fabrice-Fabio commented Dec 5, 2023

Use cases.

Connection from a uniswap or pancakeswap type dapp, the connection will work every other time.
Sometimes it returns an error which is caught by wcClient.onSessionProposalError.subscribe() in the format:

"SessionProposalErrorEvent(id: 1701782571459814, requiredNamespaces: {eip155: RequiredNamespace(chains: [eip155:137], methods: [eth_sendTransaction, personal_sign], events: [chainChanged, accountsChanged])}, namespaces: {eip155: Namespace(accounts: [ eip155:137:0xfc4124d107ac29e3b1638c335d768d54a8cf5700], methods: [personal_sign, eth_sendTransaction], events: [chainChanged])}, error: WalletConnectError(code: 5102, message: Unsupported events. onSessionProposeRequest namespaces events don't satisfy requiredNamespaces events for eip155.Requested: [chainChanged, accountsChanged], Supported: [chainChanged], data: null))"

While the app namespace is configured like this :

await wcClient.approveSession(
id: id,
namespaces: {
'eip155': Namespace(
accounts: [
"eip155:1:$_currentAddress",
"eip155:137:$_currentAddress",
"eip155:56:$_currentAddress",
"eip155:43114:$_currentAddress",
"eip155:42161:$_currentAddress",
"eip155:250:$_currentAddress",
"eip155:${this._currentNetworkId}:$_currentAddress"],
methods: [
"eth_sendTransaction",
"eth_signTransaction",
"eth_sign",
"personal_sign",
"eth_signTypedData",
"eth_signTypedData_v4"
],
events: ["chainChanged", "accountsChanged", "message", "disconnect", "connect"],
),
}
);

Which should logically take into account all cases.
Is there a way to avoid all of this?

Thanks

@Fabrice-Fabio
Copy link
Author

When you have same network on both (dapp and my wallet) i'm getting this errors :

SessionProposalErrorEvent(id: 1701784882276298, requiredNamespaces: {eip155: RequiredNamespace(chains: [eip155:56], methods: [eth_sendTransaction, personal_sign], events: [chainChanged, accountsChanged])}, namespaces: {eip155: Namespace(accounts: [eip155:56:0xfc4124d107ac29e3b1638c335d768d54a8cf5700], methods: [personal_sign, eth_sendTransaction], events: [chainChanged])}, error: WalletConnectError(code: 5102, message: Unsupported events. onSessionProposeRequest namespaces events don't satisfy requiredNamespaces events for eip155. Requested: [chainChanged, accountsChanged], Supported: [chainChanged], data: null))

but approveSession got this configuration :

await wcClient.approveSession(
id: id,
namespaces: {
'eip155': Namespace(
accounts: [
"eip155:1:$_currentAddress",
"eip155:137:$_currentAddress",
"eip155:56:$_currentAddress",
"eip155:43114:$_currentAddress",
"eip155:42161:$_currentAddress",
"eip155:250:$_currentAddress",
"eip155:${this._currentNetworkId}:$_currentAddress"],
methods: [
"eth_sendTransaction",
"eth_signTransaction",
"eth_sign",
"personal_sign",
"eth_signTypedData",
"eth_signTypedData_v4"
],
events: ["chainChanged", "accountsChanged", "message", "disconnect", "connect"],
),
}
);

Is there a way to give it the default namespace before it even attempts to pair, because I have the impression that at times it blocks it.

@quetool
Copy link
Collaborator

quetool commented Dec 5, 2023

Hello @Fabrice-Fabio, I don't fully understand your issue but will try to help. First question I have is: are you developing a wallet or dapp?
Furthermore, from the error you shared

message: Unsupported events. onSessionProposeRequest namespaces events don't satisfy requiredNamespaces events for eip155. Requested: [chainChanged, accountsChanged], Supported: [chainChanged]

I can see the wallet only supports chainChanged event, if you are in the dApp side you should send every other method as optional. Or you can just send everything as optional and let the wallet approve whatever supports.

dApp side:

final connection = await web3App.connect(
   optionalNamespaces: {/* every namespace */},
);

Wallet side (onSessionProposalEvent):

web3Wallet.approveSession(
  id: args.id, // args from SessionProposalEvent
  namespaces: args.params.generatedNamespaces!,  // args from SessionProposalEvent
);

Let me know if this helps.

@Fabrice-Fabio
Copy link
Author

Hello @quetool first of all, thank you for the response. I was unaware that it was necessary to use “eventData.params.generatedNamespaces” instead of hard-coding the namespaces as indicated in the documentation.

await wcClient.approveSession({
    id: id,
    namespaces: eventData.params.generatedNamespaces!
});

I will better contextualize the problem for your understanding.
I am developing a wallet.
I use dapps like Uniswap or PancakeSwap to ensure everything works correctly.

Process

In the normal process, it happens as follows:

wcClient.onSessionProposal.subscribe((SessionProposalEvent? args) async {
    id = args!.id;
    final eventData = args;

    await _onSessionRequest(eventData);
});

And in the “_onSessionRequest()”, I display a modal with two buttons, namely “approve” and “cancel”.
In the approve button, the action is:

await wcClient.approveSession({
    id: id,
    namespaces: eventData.params.generatedNamespaces!
});

Errors

“message: Unsupported events. onSessionProposeRequest namespaces events don't satisfy requiredNamespaces events for eip155. Requested: [chainChanged, accountsChanged], Supported: [chainChanged]”

The following error occurs even before the user approves or refuses, that is, it happens upon connection.
I've noticed that it happens once out of 10 times on Android, but on iOS, I get the error all the time.

So, I was wondering if there is a way to avoid this, maybe an initialization during...

@quetool
Copy link
Collaborator

quetool commented Dec 6, 2023

Thanks for the clarification!
I'll explain a bit how things works on a high level because I know we are lacking on documentation Flutter-wise and I apologize for that:

On one side we have the Wallet (you in this case)
On the other side we have the dApp (PancakeSwap for instance).

The way the protocol works, in regards of namespaces (chains + methods + events), is as follows:

The wallet "register" handlers (for handling methods) and event emitters (for emitting events) for any chain the wallet developer wants to support. Which chains, which handlers and which emitters it's up to the wallet dev, could be just one, could be two, could be every EVM chain and this will determine which ones are approved during session proposal.

Register handler example:

web3wallet.registerRequestHandler(
  chainId: '1',
  method: 'persona_sign',
  handler: _personalSignHandler,
);

Register event emitter example:

web3wallet.registerEventEmitter(
  chainId: '1',
  event: 'chainChanged',
);

You should do this for every chain, method and event you want to support on your wallet.

Ok so now the dApp would propose a session by asking for required and optional namespaces during connection

final connection = await web3App.connect(
   requiredNamespaces: {/* every namespace you want */},
   optionalNamespaces: {/* every namespace you want */},
);

and based on what the wallet supports (by registering or not handlers and emitters) a session request will be created along with a new set of generatedNamespaces (which is the result of the "union" of required and approved optionals namespaces)

Note: There's currently an issue with generatedNamespaces that we are taking care of but I don't think you are affected by this anyway. #205

So now my question would be: Are you (as wallet) registering an event emitter for accountsChanged for every chain you support?
I wouldn't mind a minimum reproducible code of your Wallet to try it out myself.

@Fabrice-Fabio
Copy link
Author

Hello @quetool, thank you for your response. The background workings are now a bit clearer to me.

Indeed, I've also noticed bug #205. When I used "eventData.params.generatedNamespaces!", it generally works well, but sometimes it returns "null". What I suggest, and I think this should solve the issue, is to continue performing the calculation and return what you currently return. However, wallet dev could also return a defaultNamespace that covers all cases in case something got wrong or if "generatedNamespaces" return null.

P.S. In my case, I did something like this:

await wcClient.approveSession(
    id: id,
    namespaces: eventData.params.generatedNamespaces ?? defaultNamespaces
);

And I configured my "defaultNamespaces" myself.

I had also made a PR (Pull Request) for the documentation in the meantime. If you could merge it, that would be great. I'll probably make another one this weekend that takes into account what we've discussed because, yes, it lacks quite a bit of information.

Regarding my bug, I now understand better that one needs to have a registerEventEmitter() of each type for each supported network. I'll set that up and get back to you soon

@quetool
Copy link
Collaborator

quetool commented Dec 7, 2023

@Fabrice-Fabio I'm about to push the fix for #205 so your workaround won't be needed.

About documentation PRs you can open them but I won't be able to check them any time soon. We are anyway aware of our lack of documentation Flutter-wise and updating them is in the roadmap, we are just focusing on some other big things.

@quetool
Copy link
Collaborator

quetool commented Dec 7, 2023

@Fabrice-Fabio in my explanation here I forgot to mention that Wallet should register the accounts as well in order to fully support a Namespace.

Bottom line: To fully support a Namespace such as

'eip155': const RequiredNamespace(
  chains: ['eip155:1'],
  methods: ['persona_sign'],
  events: ['chainChanged'],
)

you will need to register 3 things: an eventEmitter, a methodHandler and an account

web3wallet.registerEventEmitter(
  chainId: '1',
  event: 'chainChanged',
);
web3wallet.registerRequestHandler(
  chainId: '1',
  method: 'personal_sign',
  handler: _personalSignHandler,
);
web3Wallet.registerAccount(
  chainId: '1',
  accountAddress: '0x**************************', 
);

@Fabrice-Fabio
Copy link
Author

Thanks it works.

You're doing a good job.
Keep going and I'll get back to you as soon as I find other solutions.

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

No branches or pull requests

2 participants