Skip to content

fix: split web and native wallet connectors#233

Merged
andrascodes merged 7 commits into
mainfrom
andras/fix-split-web-and-native-wallet-connectors
Jun 1, 2026
Merged

fix: split web and native wallet connectors#233
andrascodes merged 7 commits into
mainfrom
andras/fix-split-web-and-native-wallet-connectors

Conversation

@andrascodes
Copy link
Copy Markdown
Collaborator

@andrascodes andrascodes commented May 26, 2026

This PR is part of a stack created with Aviator.

Closes FS-2252

Summary

  • Split the React connector into shared core logic plus web/native wrappers.
  • Add React Native defaults that derive Origin: https://${rpId} from the connector config.
  • Remove rpId as a required prop from ZeroDevExportWebView; it now reads it from the ZeroDev wagmi connector.
  • Add a native core SDK wrapper that applies the same Turnkey Origin default.
  • Add separate Expo native/web typecheck configs.

Why

The connector now has platform-specific API needs. On React Native, consumers must provide native adapters and the SDK must send an Origin header that matches rpId so Turnkey and AA requests pass ACL checks. On web, browsers own the Origin header, so exposing fetchOptions for this path is misleading and does not solve the same problem.

Splitting the connector keeps the public API accurate for each platform while preserving one shared implementation for the actual wagmi connector behavior. The native wrapper can require the RN-only adapter fields and derive the Origin header automatically, while the web wrapper can keep the browser API smaller and avoid exposing options that do not apply there.

If Passkeys are used rpId needs to be a domain associated with the app - the KMS also enforces that the Passkey requests come from the same domain. So it makes sense to default the Origin header and the Passkey rpId to the same domain and have 1 source of truth.

  • When developing locally on a ZD project where an Origin allowlist is defined the developer can pass the localhost URL (for example http://localhost:3000) as the rpId and that will work for basic KMS requests (OTP email, Google OAuth). To use Passkeys or OTP Magic Link the user needs to set up Universal Links (with a domain association) and then the developer should use the same domain as the rpId as well. This way requests coming from the app, on the KMS's side will look like they're coming from the associated domain (Origin is set to the domain).

Testing

  • Tested the zerodev-signer-demo on web, the expo-example on both web and Android. All working.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zerodev-signer-demo Ready Ready Preview, Comment Jun 1, 2026 12:48pm

Request Review

@andrascodes andrascodes marked this pull request as ready for review May 26, 2026 17:21
@@ -1,3 +1,25 @@
throw new Error(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what do you mean by native-on-web is it react-native-web ? If so, I think naming it react-native-web.ts would be more clear

Copy link
Copy Markdown
Collaborator Author

@andrascodes andrascodes Jun 1, 2026

Choose a reason for hiding this comment

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

This has nothing to do with react-native-web. It's a file that is loaded when React Native code is imported on a Web environment and it throws an error.
Correction: it throws when the imported functions are called on the wrong platform. Not on import. This is documented in the comments in the file.

Comment on lines +8 to +12
export function originFromRpId(rpId: string): string {
return rpId.startsWith('http://') || rpId.startsWith('https://')
? rpId
: `https://${rpId}`
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we ever allow http without https? Maybe only if it's localhost, otherwise throw an error. Also, origin shouldn't have subpaths, e.g. https://zerodev.app/example and we currently just using it as-is.

And a nit, thinking we can rename this to sanitizeOrigin or normalizeOrigin since it's applicable more broadly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

reverted the file

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Isn't this exactly the same as packages/core/src/utils/originFromRpId.ts?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes, I'll change it so we import the one from wallet-core instead

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.

3 participants