TxnLab / use-wallet

A framework agnostic wallet integration library for Algorand dApps
https://txnlab.gitbook.io/use-wallet
MIT License
82 stars 34 forks source link

Add `isPeraDiscoverBrowser` check to enable auto-connect #311

Open yasincaliskan opened 1 month ago

yasincaliskan commented 1 month ago

Currently, we use an isPeraDiscoverBrowser property within Pera Connect to detect if the dApp is opened within the Pera Discover Browser. When this property returns true, we bypass the typical wallet selection screen and directly initiate the Pera Connect connection, providing a smoother user experience. Reference

In use-wallet, the default flow initiates the wallet selection screen immediately after the "Connect wallet" button is clicked. This works well in general scenarios, but in cases where isPeraDiscoverBrowser is true, it would be more efficient to skip this step and auto-connect with Pera Connect.

The only workaround I see is listing only the PeraWallet option, but this isn't ideal, especially since the "Connect wallet" button is controlled by the dApp and cannot be manipulated externally.

Is there a way to incorporate isPeraDiscoverBrowser into use-wallet to enable an auto-connect flow when detected?

drichar commented 4 weeks ago

Currently the library waits until a wallet provider's connect method is invoked for the first time to lazily load its dependencies. This is a performance optimization for apps that are configured to support multiple wallets. If a wallet isn't used its dependencies are never loaded.

The auto-connect flow would require bypassing this behavior in the Pera provider. Pera Connect would need to be loaded every time the app mounts, whether the user is on a mobile device using the Discover browser or not. I'd like to give developers a way to opt-in to this behavior.

There are two approaches that would work:

  1. Expose a configuration property like autoConnect: true to signal that the provider should load the module right away
  2. The app imports the module and passes it directly to a property like staticModule: PeraWalletConnect

With the module available in the constructor, the client is initialized and conditionally triggers the automatic connection.

I'm leaning towards option 2, because it aligns with a change I'm considering for the next major release. Lazy loading by default prohibits the library from being used in projects that don't support dynamic imports. Actually I think it makes sense to save this feature for v4.0.0 so it can be incorporated with the broader change.

I'll tag you @yasincaliskan in the PR when the feature is ready to review.

SilentRhetoric commented 3 weeks ago

@yasincaliskan It seems a bit inside out to need to use a function from Pera Connect to know if the app should be connecting to Pera Connect in the first place.

In AlgoDirectory, for example, loading Pera Connect nearly doubles the size of the downloaded JS from 260kb-->474kb, so I would want to avoid loading Pera Connect until I know the user intends to use Pera.

Looking through Pera Connect appears to yield a simple one-liner that would enable an app to know if the user is in Pera's Discover browser:

const isPeraDiscover = window.navigator.userAgent.includes("pera")

My suggestion would be that use-wallet and/or app developers use this one-liner in their application code and then load and connect to Pera Connect if isPeraDiscover = true.

drichar commented 3 weeks ago

Thank you @SilentRhetoric for calling this out!

By simply checking the userAgent Pera Connect will only be loaded when it's needed:

  1. if the user is in Pera's Discover browser, to auto-connect
  2. if the user is in a standard browser and initiates a connection to Pera

In the first scenario, Pera Connect can be loaded and initialized in the client constructor. This is a much simpler solution and doesn't require special casing anything for the Pera provider.

yasincaliskan commented 3 weeks ago

Thanks @SilentRhetoric , @drichar ! Yes, we check the userAgent basically. It can be checked without loading Pera Connect. I will add this to our docs.

@drichar Yes, it can be loaded and initialized in the constructor but if we don't call connect(), we will just list the Pera Wallet option. The user will still need to select the Pera Wallet option to start a connection. Actually, we are aiming to remove this step and start the connection right before listing the wallet options. If we call connect() in the constructor, that will probably produce undesirable results. Am I thinking right?