safe-apps-sdk icon indicating copy to clipboard operation
safe-apps-sdk copied to clipboard

Provide a sync way to check if an app is run inside gnosis safe

Open mmv08 opened this issue 2 years ago • 16 comments

We got a request for easy detection if the app is loaded as a safe app that doesn't require loading the SDK - in the web version, one can use desktop.referrer, but not on the desktop. It could be done with the query params.

mmv08 avatar Dec 10 '21 09:12 mmv08

Suggestion from @taylorjdawson

You could add a data- attribute to the iframe element and then I believe dapps could access this to determine if they are in a gnosis safe context

mmv08 avatar Dec 10 '21 12:12 mmv08

Since there is a requirement to auto-login with gnosis (if you want to release your app into gnosis apps) I would expect the straight-forward approach how to detect the gnosis provider availability. If I am trying to getInfo() from the safe, it is failing on net::ERR_BLOCKED_BY_CLIENT (probably cors), which you can't handle by try-catch statement. So what is the recommended approach for detecting it? Because I've inspected the React library (which I don't use), where it's used try-catch as well, so probably it has to fail

kleinpetr avatar Feb 02 '22 12:02 kleinpetr

getInfo() uses .postMessage and not http, it cannot fail with a CORS error.

Could you share the code? The problem must be somewhere else

mmv08 avatar Feb 02 '22 13:02 mmv08

Oh, srry. it is probably trouble with Sentry integration.... :/

kleinpetr avatar Feb 02 '22 13:02 kleinpetr

Ok, so the error is not related to the gnosis safe info. But when I am trying to get safe info, there is no error, but the app is just stuck.

kleinpetr avatar Feb 02 '22 15:02 kleinpetr

Ok, so the error is not related to the gnosis safe info. But when I am trying to get safe info, there is no error, but the app is just stuck.

could you share the code?

mmv08 avatar Feb 02 '22 17:02 mmv08

I just checked, and other apps are working, so we'd need a reproduction case to check it.

mmv08 avatar Feb 02 '22 17:02 mmv08

The code is very simple, before I mount the app I am waiting for this try-catch statement. And it looks that the Promise is never resolved.

try {
      const gnosisSdk = new SafeAppsSDK()
      const safeInfo = await gnosisSdk.safe.getInfo() 
      return safeInfo
    } catch (e) {
      console.log('Gnosis Safe is not detected', e)
    }

kleinpetr avatar Feb 04 '22 09:02 kleinpetr

The code is very simple, before I mount the app I am waiting for this try-catch statement. And it looks that the Promise is never resolved.

try {
      const gnosisSdk = new SafeAppsSDK()
      const safeInfo = await gnosisSdk.safe.getInfo() 
      return safeInfo
    } catch (e) {
      console.log('Gnosis Safe is not detected', e)
    }

It's expected to never resolve if you run it outside the Safe because there's no handler for this request. You need to add a timeout. Check the example here:
https://github.com/gnosis/safe-apps-sdk/blob/master/packages/safe-apps-web3modal/src/modal.ts#L45-L54

mmv08 avatar Feb 04 '22 10:02 mmv08

ok, thanks

kleinpetr avatar Feb 04 '22 10:02 kleinpetr

Hi, this feature would be useful for me: I work in an App that uses Gnosis, but 99% of our users don't use a multisig, so this is for very limited users. We also use web3js, but given we install @gnosis.pm/safe-apps-web3-react, it brings the SDK as a dependency, which also brings its own copy of ethers package, which is huge.

I understand that these packages are required, but I'd like to be able to know if I'm in Gnosis context so I can only load them in these scenarios, and not for all users. Thanks!

edit:

currently, to detect if I'm in Gnosis context, I use

const { connector: currentConnector } = useWeb3React()
if (currentConnector instanceof SafeAppConnector) {

but by importing SafeAppConnector I get the whole SDK as mentioned above

gndelia avatar May 25 '22 13:05 gndelia

Hi, this feature would be useful for me: I work in an App that uses Gnosis, but 99% of our users don't use a multisig, so this is for very limited users. We also use web3js, but given we install @gnosis.pm/safe-apps-web3-react, it brings the SDK as a dependency, which also brings its own copy of ethers package, which is huge.

I understand that these packages are required, but I'd like to be able to know if I'm in Gnosis context so I can only load them in these scenarios, and not for all users. Thanks!

edit:

currently, to detect if I'm in Gnosis context, I use

const { connector: currentConnector } = useWeb3React()
if (currentConnector instanceof SafeAppConnector) {

but by importing SafeAppConnector I get the whole SDK as mentioned above

There's an async approach above that may help. Unfortunately, synchronous is not possible because browsers do not have such a mechanism

mmv08 avatar Jun 21 '22 16:06 mmv08

It could be done with the query params.

I've just got reminded that it's possible with query params @dasanra

mmv08 avatar Jun 27 '22 12:06 mmv08

how's the query params approach?

The async approach still requires importing SafeAppsSDK, which I think still implies loading the entire SDK even for those users that are not in gnosis, which is the problem that I want to avoid in the first place

gndelia avatar Jun 27 '22 13:06 gndelia

how's the query params approach?

The async approach still requires importing SafeAppsSDK, which I think still implies loading the entire SDK even for those users that are not in gnosis, which is the problem that I want to avoid in the first place

Query params approach isn't possible at the moment. If you import the SDK only when the app is loaded in an iframe, the chances are high that the iframe is coming from the safe

mmv08 avatar Jun 28 '22 09:06 mmv08

Hey all!

Wondering if anyone has found a definitive solution to this since. We're having this exact problem now — we want to support being a Safe App in our frontend, but also have the same app support standalone usage.

The solution linked by @mikhailxyz works, but I really don't like the idea of delaying our app load by 200ms for everyone, especially given we expect the vast majority of sessions to not be within a safe.

I can also imagine making an environment variable that puts the app into "safe mode" and deploying our app twice — once with it on, once off (for the main deployment). But this just seems like a lot of effort.

efstajas avatar Mar 03 '23 15:03 efstajas