Skip to content

[Writer] Add Privy signer migration guides (React + JWT auth)#1230

Open
JackReacher0807 wants to merge 8 commits intomainfrom
docs/writer/privy-signer-migration-guides
Open

[Writer] Add Privy signer migration guides (React + JWT auth)#1230
JackReacher0807 wants to merge 8 commits intomainfrom
docs/writer/privy-signer-migration-guides

Conversation

@JackReacher0807
Copy link
Copy Markdown
Collaborator

Adds 2 new documentation pages under the Wallets > Privy section for signer migration:

  • React migration (content/wallets/wallet-integrations/privy/react-migration.mdx): Step-by-step guide to migrate embedded wallets from Alchemy Account Kit to Privy using the React migration SDK
  • JWT auth migration (content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx): Guide for developers using JWT authentication, covering both client-side and server-side migration paths

Both pages are added to the nav under a new 'Signer migration' group within the Privy section.

Linear: DOCS-42

@JackReacher0807 JackReacher0807 requested a review from a team as a code owner April 17, 2026 16:39
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 17, 2026

🔗 Preview Mode

Name Status Preview Updated (UTC)
Alchemy Docs ✅ Ready 🔗 Visit Preview Apr 21, 2026, 5:03 PM

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0fe1f72171

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 17, 2026

🔍 Link Check

Status: ❌ Failed

Summary

Status Count
🔍 Total 7913
✅ Successful 6748
⏳ Timeouts 0
🔀 Redirected 404
👻 Excluded 675
❓ Unknown 0
🚫 Errors 85
⛔ Unsupported 1
Broken links (85) — click to expand

Errors per input

Errors in ./content/api-reference/katana/katana-api-overview.mdx

Errors in ./content/wallets/pages/smart-wallets/quickstart/index.mdx

Errors in ./content/wallets/pages/recipes/send-usdc.mdx

Errors in ./content/wallets/pages/recipes/smart-wallets-aave.mdx

Errors in ./content/wallets/pages/react-native/getting-started/getting-started-rn-bare.mdx

Errors in ./content/wallets/pages/index.mdx

Errors in ./content/changelog/2026-03-26.md

Errors in ./content/api-reference/op-mainnet/op-mainnet-api-faq/op-mainnet-api-faq.mdx

Errors in ./content/changelog/2026-04-09.md

Errors in ./content/wallets/pages/concepts/smart-account-client.mdx

Errors in ./content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx

Errors in ./content/wallets/pages/authentication/overview.mdx

Errors in ./content/api-reference/arbitrum/arbitrum-api-faq/arbitrum-api-faq.mdx

Errors in ./content/tutorials/alchemy-university/smart-contract-basics/multi-sig-contracts.mdx

Errors in ./content/wallets/pages/react-native/getting-started/getting-started-expo.mdx

Errors in ./content/api-reference/hyperevm/hyperevm-api-overview.mdx

Errors in ./content/wallets/pages/bundler-api/bundler-faqs.mdx

Errors in ./content/api-reference/arbitrum-nova/arbitrum-nova-deprecation-notice.mdx

Errors in ./content/wallets/pages/recipes/onramp-funds.mdx

Errors in ./content/wallets/wallet-integrations/privy/react-migration.mdx

Errors in ./content/wallets/pages/recipes/upgrade-to-smart-accounts.mdx

Errors in ./content/wallets/pages/smart-wallets/how-to-stamp-requests.mdx

View workflow run

@avarobinson avarobinson requested a review from SahilAujla April 20, 2026 16:03
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
// Add custom logic to only create a new embedded wallet
const walletCreationPluginOptions = {
shouldCreateWallet: ({user}: {user: User}) =>
user.customMetadata?.['alchemy_org_id'] === undefined,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

was this confirmed with danny? I remember they were looking to ship something that just did this automatically

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.

Good catch — went with the simpler path that matches the FAQ at the bottom: drop the custom wallet creation plugin entirely and set createOnLogin: "off" during the migration window, then flip it to "users-without-wallets" once everyone's migrated. That way we're not relying on the alchemy_org_id metadata check, and it's consistent whether or not Privy ships auto-detection down the road.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@JackReacher0807 Revert this back to the original implementation. We do need the custom wallet creation plugin and should not pass the createOnLogin. Auto-detection was not shipped.

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 in feee767. Step 1b is back to the original implementation: createWalletCreationOnLoginPlugin with shouldCreateWallet gated on alchemy_org_id, and createOnLogin: "users-without-wallets". Dropped the auto-detection / createOnLogin: "off" framing.

Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx Outdated

### 5a. Integrate Privy auth (server-side)

When selecting "Server side" in the Privy dashboard JWT configuration (Step 2a), Privy accepts JWTs directly from your backend. Your server exchanges the user's JWT for a Privy session via the REST API.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the reasoning behind recommending that? I thought it was to do it more securely (end to end encrypted), but it seems like this is just recommending they take 'custody' of the private key to migrate it themselves?

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.

Fair point — the original framing made it sound like server-side was the 'more secure' path, which isn't accurate since it does mean your server briefly holds the plaintext key. Reworked the section to be explicit: use the client-side path by default, only reach for server-side if you have a specific reason to do the import from the backend (e.g. attaching policies/owners at import time). Also replaced 'Server-side path' with 'Server-side path (import only)' in the heading so readers can't miss the scope.

const user = await getUserFromDB(userId);

if (!user.signer_migrated) {
// 1. Export private key from Alchemy (Follow the steps from 4c)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

step 4c is for the client. as far as I'm aware we have no customers authenticating a JWT signer on the backend and we do not support this

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.

This was the big one — thanks for catching it. Rewrote the whole server-side section to reflect that AlchemyWebSigner + JWT auth is browser-only and we don't support a backend Alchemy JWT signer auth. New flow: 1) client authenticates with Alchemy and calls exportPrivateKeyEncrypted against a public key your server owns, 2) client POSTs the ciphertext to your server, 3) server decrypts and calls privy.wallets().import(...). Added a at the top of the section making this explicit, and updated the 'Security considerations' section to match.

…options, clarify server-side JWT path

- react-migration: drop cookieToInitialState references; switch to createOnLogin "off" during migration (removes custom wallet creation plugin)
- react-migration: remove unnecessary 'Function, not hook' distinction and cookieToInitialState row from hook mapping
- react-migration: move Info callout with deeper links below the bullet list
- react-migration: passkey migration supports anonymous too
- react-migration: use mode: 'redirect' (popup was never effective)
- react-migration: load Alchemy API key from env var + add security Warning
- react-migration: drop skipOrgVerification prop from the docs
- react-migration: update FAQ to match simplified provider setup
- jwt-auth-migration: explain new-user flow when createOnLogin is 'off'
- jwt-auth-migration: fold redundant 4c 'Authenticate with Alchemy' into 4b; renumber subsequent steps
- jwt-auth-migration: reframe server-side path as import-only (Alchemy JWT signer auth is client-only/unsupported on backend); show client export -> encrypted handoff -> server import
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
|---|---|
| `useSignerStatus().isConnected` | `usePrivy().authenticated` |
| `useAuthModal().openAuthModal()` | `usePrivy().login()` |
| `useLogout()` | `usePrivy().logout` |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
| `useLogout()` | `usePrivy().logout` |
| `useLogout()` | `usePrivy().logout()` |

consistency

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.

Fixed: Added the parens — usePrivy().logout() now matches the other rows in the table. Commit: 3d7b2b2

Wire Privy wallets to Alchemy's transaction infrastructure so gasless transactions, batching, and all your existing flows work again. This uses Alchemy SDK v5 with Wallet APIs.

* The client defaults to EIP-7702, which delegates the Privy wallet to a smart wallet at send time.
* If you were previously using ERC-4337 (with assets directly in smart accounts), see the EIP-7702 guide for non-7702 mode. You'll need to add an additional call to `wallet_requestAccount` before sending.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should actually link to non-7702 guide here

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.

Fixed: Replaced the generic "EIP-7702 guide for non-7702 mode" link with a direct link to the non-7702 mode section: /wallets/transactions/using-eip-7702#how-to-use-non-7702-mode. Commit: 3d7b2b2

Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
);
```

<Warning>Never commit your Alchemy API key to source control. Load it from an environment variable (for example `NEXT_PUBLIC_ALCHEMY_API_KEY` in Next.js) and restrict the key to the correct apps, networks, and origins from the [Alchemy Dashboard](https://dashboard.alchemy.com/).</Warning>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

technically it's best for the api key to be secured on the backend

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.

Fixed: Strengthened the Warning — it now explicitly notes that for production apps the best practice is to keep the API key on the backend and proxy Alchemy requests through it rather than exposing it in the client bundle at all. Commit: 3d7b2b2

Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/react-migration.mdx Outdated
Comment thread content/wallets/wallet-integrations/privy/jwt-auth-migration.mdx Outdated
- Retitle React guide to clarify signer-only migration
- Move Prerequisites to top of guide
- Add React-only callout in intro
- Condense Privy dashboard setup steps (remove redundant step, use current nav naming)
- Fix usePrivy().logout() -> add parens for consistency
- Link non-7702 mode guide directly (with anchor)
- Note that chain can be any viem chain
- Split migration SDK install so @account-kit/react/infra only install when not already present
- Combine @account-kit/infra imports onto one line
- Strengthen API key warning: recommend backend proxy for production
- Polish Step 4 intro wording
- Remove duplicate 'Redeploy app' step from cutover sequence
- Use 'each wallet independently' instead of 'each chain independently' in FAQ
- Link specific Privy JWT setup page in jwt-auth-migration.mdx
transport: alchemyWalletTransport({
apiKey: "YOUR_ALCHEMY_API_KEY",
}),
chain: arbitrumSepolia,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clarify that you should import the needed chain(s) from viem/chains. ensure the chain is enabled on your Alchemy app and support gas sponsorship.

// Add custom logic to only create a new embedded wallet
const walletCreationPluginOptions = {
shouldCreateWallet: ({user}: {user: User}) =>
user.customMetadata?.['alchemy_org_id'] === undefined,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@JackReacher0807 Revert this back to the original implementation. We do need the custom wallet creation plugin and should not pass the createOnLogin. Auto-detection was not shipped.

### 3a. Install

```bash
npm install @privy-io/alchemy-migration @account-kit/react @account-kit/infra
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove the note to install @account-kit/react. We only need to install the migration pakage.

avarobinson and others added 2 commits April 21, 2026 10:45
- Revert provider setup to original implementation: restore custom
  wallet creation plugin with createOnLogin set to 'users-without-wallets'
  (comment 3118799901).
- Clarify Step 2c chain note: import chain(s) from viem/chains, ensure
  the chain is enabled on your Alchemy app, and confirm it supports
  Gas Manager sponsorship (comment 3118681754).
- Remove the note about installing @account-kit/react and
  @account-kit/infra in Step 3a. The migration SDK is the only required
  install (comment 3118815590).
@JackReacher0807
Copy link
Copy Markdown
Collaborator Author

Thanks for the review, @avarobinson! Addressed all three in feee767 on content/wallets/wallet-integrations/privy/react-migration.mdx:

  1. Line 48 (provider setup): Reverted to the original implementation. Restored createWalletCreationOnLoginPlugin with the shouldCreateWallet gate on alchemy_org_id, and set createOnLogin back to "users-without-wallets". Dropped the auto-detection framing.
  2. Line 140 (chain note): Reworded the callout to cover all three points: import chain(s) from viem/chains, confirm the chain is enabled on your Alchemy app, and confirm it supports Gas Manager sponsorship.
  3. Line 193 (migration SDK install): Removed the follow-up note about installing @account-kit/react and @account-kit/infra. Step 3a is now a single npm install @privy-io/alchemy-migration.

Ready for another pass when you have a minute.

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.

5 participants