Skip to main content
If your users have Grid email accounts, Grid manages their Privy and Turnkey keys. Before Grid shuts down, each account’s signers must be swapped for keys you control. @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 @solana/kit and the Smart Account SDK; your existing @sqds/grid import is unchanged.
For React apps, also install the hook:
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.
Check this first. If the new key cannot sign v1 transactions, the account still migrates, but you cannot use it afterwards until you can sign them.
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.
Keep the user’s permissions. Pass every permission the account needs (initiate, vote, execute) and a threshold your new keys can reach.
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 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.
If the outcome is 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): calls PATCH /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 /submit and returns the transaction signature. If it fails before anything reached /submit, throw a GridMigrationError with code SIGNING_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