@sqds/grid/migration does this from inside your app: it asks Grid for the swap, checks Grid’s transaction before anything is signed, has the user’s Grid session sign it, and confirms on-chain that no Grid authority remains.
Overview
- One login per account: the end user signs in once with their email code. Grid’s paymaster pays for the swap, so the user needs no SOL.
- Nothing is signed unchecked: the kit decodes Grid’s prepared transaction and refuses to sign unless it does exactly what you asked.
- Self-custodial or custodial: the new key can be the user’s own wallet (the kit runs in your front end) or a key your backend holds (the kit runs on your server).
Migration Steps
1
Install the packages
The migration entry points load For React apps, also install the hook:
@solana/kit and the Smart Account SDK; your existing @sqds/grid import is unchanged.ESM only.
@sqds/grid/migration and @sqds/grid-react/migration are ES modules. From CommonJS, use await import('@sqds/grid/migration').2
Check that your new key signs v1 transactions
After the swap, every transaction goes through the Smart Account SDK, which sends Solana v1 transactions only. Confirm your wallet or key provider signs them before you migrate any user.
3
Log the user in to Grid
The user’s Grid session authorizes the swap. Log them in the way you do today and wrap the session with
gridSession.4
Plan the migration
planMigration is read-only. It reads the account from the chain, rejects accounts the kit cannot migrate, and lists the steps that remain.5
Run the swap
runMigration asks Grid for the swap, checks it, has the session sign it and submits it. Save the pending swap in onBeforeSubmit so a crash or refresh can never submit twice.6
Handle the outcome, clean up and confirm
On If the outcome is
confirmed, remove Grid’s standing-order spending limits with the new key, then confirm with checkMigrated. On failed or expired, nothing changed on-chain: plan and run again.unknown, keep outcome.pending and resolve it later. Never start a new swap while one is pending.7
Rehearse on sandbox
Before migrating production users, run the same code end to end with a test email: create the
GridClient with environment: 'sandbox' and your sandbox API key, point createSolanaRpc at https://api.devnet.solana.com, and use a devnet key as the new signer. Confirm checkMigrated returns done, then send one transfer with the Smart Account SDK.React
useGridMigration runs the same steps from a component. It stores the pending swap in localStorage before anything is signed, so a page refresh never submits twice.
Every step is user-triggered. The hook runs nothing on mount.
phase, error.code and error.retryable tell you what to show.Not using @sqds/grid?
If you call Grid over HTTP or from another backend, you can still install @sqds/grid and import only @sqds/grid/migration. Skip gridSession and pass runMigration your own GridSession, an object with two methods:
prepareSignerUpdate(vault, request): callsPATCH /api/grid/v1/accounts/{address}and returns Grid’s{ transaction, transactionSigners, kmsPayloads }.signAndSubmit(vault, prepared): signs the KMS payloads with the user’s Grid session, calls/submitand returns the transaction signature. If it fails before anything reached/submit, throw aGridMigrationErrorwith codeSIGNING_FAILED.
Need a single-file version? Email support@grid.squads.xyz for
grid-migration.ts, the same code as one file you can copy into your project.Next Steps
Operate accounts without Grid
Replace each Grid call with the Smart Account SDK
Troubleshooting
Error codes, outages and accounts the kit does not migrate