Open Funkatronics opened 1 year ago
I think the proper fix here is for the wallets to add the app link verification stuff as described here. I have not yet confirmed this myself, but I believe this will allow chrome to open the wallet uris in the native app instead of navigating the page to that url.
Another workaround might be to modify
mobile-wallet-adapter-protocol
to use the customintent:
scheme IFF a validwalletUriBase
is provided AND the domain cannot be verified. This will require us to implement manual verification, like we do in our digital asset links library. More info here.
Update: further investigation has revealed that even properly verified links still exhibit this behavior so its not related to app link verification.
Question: If my above theories are correct, why do some sites work but others dont? For example, Ultimate wallet does not work with drip.haus (see gif above), but it does work as expected with jup.ag. Is Jupiter using a custom implementation of mobile wallet adapter that works around this issue? Or am I incorrect in my assumptions and something else is causing some apps to navigate to the wallet url instead of launching it as an app link/android intent?
Workaround At this moment, wallets can work around this issue by removing the walletUriBase field that is returned during authorization. This will force wallet adapter on the website to use the solana-wallet:// uri scheme that works generically with all wallets thus circumventing the problem. The wallet could add a check to only remove this field when connecting to a web based dapp, and could continue to use the walletUriBase field for connections with natives apps. Note that this workaround has other negative impacts (wallet disambiguation dialog might be used, webpage will not have a fallback url to take the users to) so should only be used as a temporary solution.
This workaround was found to only work with some sites. Its not a reliable solution, and the solana-wallet:// uri can still be blocked by chromes popup blocker so the above info is not actually correct. Further investigation is needed to understand why some sites (like drip.haus) seem to work with this workaround. Their error logic might give us a clue on how to handle this case.
Proposed Solution:
authorize
and sign message
into a single transact
block so that web dapps can perform this "auto" sign in flow without needing to switch back to the web between connecting the wallet and requesting a signaturetransact
method that returns an error if transact was not initiated from a user action. This can be accomplished by adding a new event
parameter to the transact
method that should represent the user event that initiated the action. The transact method will check this event and verify that this event was user initiated (event.isTrusted
). This would be a breaking change so if there is another way to verify that the action originated from a user event I am all ears! CC @Michaelsulistio @sdlaver @steveluscher
I would say that there are 2 things to implement here:
WalletButton
components to accept callbacks before and after their onClick
events like so beforeConnect
, afterConnect
, beforeDisconnect
, afterDisconnect
otherwise all the developers looking to support MWA on their web apps will have to implement it on their own if they're ever looking to have support for a single button which both authorizes the app and does any other action like signing a message.This is the naive approach, there is more to the solution proposed under the point 2. and it's implementation will probably take a lot of thought and time. The biggest issue would be the connect
function from the wallet-adapter library which is not friendly enough towards the mobile-wallet-adapter library.
For example, if we want authorize a dApp and sign a message in a single wallet session on mobile web apps, our afterConnect
would need to pass in the authorized account and the mobile wallet object from the transacts callback.
Roughly something like this:
await transact(async (mobileWallet) => {
const freshAccount = await authorizeSession(mobileWallet)
const account = selectedAccount ?? freshAccount
if (typeof afterConnect === 'function') {
await afterConnect(mobileWallet, account)
}
}
can also be reproduced using our example web app
On a side note, I don't think this issue has anything to do with the example app? That could be an issue of it's own, but shouldn't be this one since the example app does not use useEffect
which makes the event not trusted. Right?
cc: @Funkatronics
Describe the bug Some dapps attempt to do a sign in flow by automatically triggering a message sign as soon as a wallet is connected. On Chrome for Android (and most if not all other mobile browsers), both app links (eg
solana-wallet://
) and universal links (eghttps://my.app/...
) are blocked if they do not come from a direct user action. This causes these sites to not funciton with Mobile Wallet Adapter. The sign message attempt is blocked, and in most cases this causes the site to get stuck in a sort of infinite loop because a cookie is stored for the connected wallet (reload>connected wallet is saved and reconnects>triggers auto sign message again>blocked>reload>repeat).To Reproduce Steps to reproduce the behavior:
{walletUriBase}/v1/associate/...
{walletUriBase}/v1/associate/...
Note:
Expected behavior Upon returning to the webpage after approving the connection in the wallet app, subsequent requests sent to the wallet should function as expected (launch the wallet app and continue with MWA request as usual)
Screenshots Using drip.haus and Ultimate:
Using drip.haus and Fakewallet:
Using example web app and Fakewallet:
Smartphone (please complete the following information):
Additional context
This was confirmed to be false. The issue is almost certainly due to mobile browsers blocking navigation (app links, universal links) that do not originate from a user action (popup blocking).