Skip to content

Feature: support safe login within app#22

Merged
krishan711 merged 3 commits into
mainfrom
safe
Mar 12, 2026
Merged

Feature: support safe login within app#22
krishan711 merged 3 commits into
mainfrom
safe

Conversation

@krishan711
Copy link
Copy Markdown
Contributor

Description

Screenshots:

Checklist:

  • I have updated the CHANGELOG with a summary of my changes
  • I have updated the documentation accordingly

Copilot AI review requested due to automatic review settings March 12, 2026 16:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Safe (Gnosis Safe) in-app detection so the library can automatically initialize an EIP-1193 provider and account when embedded as a Safe App.

Changes:

  • Added SafeSync to detect Safe App environment and wire up SafeAppProvider + account/chain state.
  • Extended the Web3 account context with isSafeApp plus a new useIsSafeApp() hook.
  • Added @safe-global/safe-apps-sdk and @safe-global/safe-apps-provider dependencies.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/Web3AccountContext.tsx Implements Safe App detection/sync and exposes isSafeApp via context + hook.
package.json Adds Safe SDK/provider dependencies needed for Safe App integration.
package-lock.json Locks the newly added Safe packages and transitive deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return;
}
// Safe is handled by SafeSync, not here
if (savedRdns === 'safe') {
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The new savedRdns === 'safe' early-return means that if a user previously opened the app inside Safe (so web3Account-chosenEip1193ProviderRdns is persisted as safe) and later opens it in a normal top-level browser window, autoReconnectProvider will never clear the saved value or set web3Account to null. Because SafeSync also bails out when not in an iframe, this can leave web3Account stuck as undefined and isRestoringSession stuck true indefinitely. Consider clearing the stored rdns (and setting web3Account/eip1193Provider to null) when Safe detection is not possible or fails, or only skipping auto-reconnect when Safe detection has positively succeeded in this session.

Suggested change
if (savedRdns === 'safe') {
if (savedRdns === 'safe') {
// If we're not running inside an iframe, Safe cannot handle this session.
// Clear the persisted Safe rdns and reset state so we don't get stuck restoring.
const isIframe = typeof window !== 'undefined' && window.self !== window.top;
if (!isIframe) {
props.localStorageClient.removeValue('web3Account-chosenEip1193ProviderRdns');
setWeb3Account(null);
setEip1193Provider(null);
}

Copilot uses AI. Check for mistakes.
}
};
detectSafe();
}, [props]);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

SafeSync's effect depends on [props], which will typically change identity every render and can cause repeated Safe detection attempts (multiple dynamic imports/timeouts) until hasSetAccountRef.current flips. It would be more stable to depend on the specific props used (or none, if they are stable) and/or memoize the callbacks passed into SafeSync to avoid rerunning the detection work unnecessarily.

Suggested change
}, [props]);
}, [
props.localStorageClient,
props.setEip1193Provider,
props.setWeb3Account,
props.setWeb3ChainId,
props.setIsSafeApp,
props.setLoginCount,
]);

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +205
hasSetAccountRef.current = true;
props.setIsSafeApp(true);
const safeProvider = new SafeAppProvider(safeInfo, safeSDK);
const eip1193Provider = safeProvider as unknown as Eip1193Provider;
props.setEip1193Provider(eip1193Provider);
props.localStorageClient.setValue('web3Account-chosenEip1193ProviderRdns', 'safe');
const browserProvider = new EthersBrowserProvider(eip1193Provider);
const signer = await browserProvider.getSigner();
const address = await signer.getAddress();
props.setWeb3Account({ address, signer });
props.setWeb3ChainId(safeInfo.chainId);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

hasSetAccountRef.current is set to true before the async signer/address/chainId sync completes. If any of the subsequent awaits throw (e.g., provider instantiation or getSigner()), the ref will prevent further retries and can leave state partially updated (e.g., isSafeApp true but no account). Consider only setting the ref after the critical state is fully established, or resetting/cleaning up state in the catch path so the app can recover.

Copilot uses AI. Check for mistakes.
@krishan711 krishan711 merged commit 3bf01ea into main Mar 12, 2026
3 checks passed
@krishan711 krishan711 deleted the safe branch March 12, 2026 16:25
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.

2 participants