Upgrading to 2.x
What changes when you move @lazorkit/wallet-mobile-adapter from 1.x or the 2.0.0 betas to 2.x, release by release.
@lazorkit/wallet-mobile-adapter 2.0.0 is the release that speaks protocol v2. 2.3.0 is
the current release. Full notes: the package
CHANGELOG
and the Changelog here.
npm install @lazorkit/wallet-mobile-adapter@^2.3.0Do not install @beta
The npm beta tag still points at 2.0.0-beta.4, a pre-v2 build from April 2026. Use
latest (2.3.0).
The adapter depends on expo-web-browser ^14.2.0 || ^15.0.0 (Expo SDK 53 / 54) and
expo-crypto ^15.0.8 (Expo SDK 54); it is built and tested against Expo SDK 54. Older
Expo SDKs have not been tested.
Checklist
smartWalletPubkeyis the vault (since the April 2026 betas; 1.x stored the wallet PDA there). Persisted wallets are migrated on load. UsesmartWalletPubkey(aliasvaultPubkey) as the user's address;walletPdaPubkeyis the internal wallet PDA. Do not derive addresses withfindVaultPda: the PDA helpers derive v2 addresses at the mainnet id.- Sessions need limits.
createSessionwithoutactionsthrows unless you passunrestricted: true. - Authorities need a role, and Delegates a policy.
addAuthorityEd25519has no default role (since 2.3.0: see below).role: ROLE_SPENDER(Delegate) on a v2 wallet throws withoutpolicy: serializeActions([...]). On a v1 wallet it requiresunrestricted: trueand refuses a policy. - v1 users need their relayer: set
v1ConfigPaymasterwhenconfigPaymasterpoints at a v2 relayer. See Migrating from v1. - RPC URLs that do not name a cluster need the
clusterprop. connectmay ask the user, with a chooser drawn as a React NativeModal. On iOS it cannot appear over another modal: see Wallet Confirmation › iOS. While a wallet is connected,connectreturns it without opening the portal; disconnect first to connect another passkey.- Sends resolve later and can reject in new ways (2.1.0). See Sending transactions.
- Callbacks run after
isSigningclears (2.2.0;connectanddisconnecttoo since 2.3.0), and the store'ssignAndExecuteTransaction,signMessageandtransferSolresolve with their results. - Removed or changed exports: the low-level
create*Ixbuilders are gone (useLazorKitClientmethods).readAuthorityStateis still exported for compatibility; new code should prepare passkey challenges with@lazorkit/sdk-legacy'sprepare*methods and theirminContextSlot/commitmentoptions (Passkey signing). - Android redirects. More than one app can claim a custom URL scheme on Android. Prefer a redirect only your app can receive, such as a verified App Link; see Wallet Confirmation.
Release by release
| Release | What changes for you |
|---|---|
| 2.0.0 (2026-09-29) | Protocol v2 beside v1, routed per wallet: protocolVersion, v1ConfigPaymaster, cluster, V1WalletRetiredError, V1WalletMigratedError. Wallet confirmation: onConfirmWallet, confirmWallet, trustedAuthorities, watchMints, <WalletChooser />, WalletChooserNotShownError, PortalCancelledError. A signing action always rejects on failure (it could resolve undefined). The breaking items above. |
| 2.1.0 (2026-09-30) | Sends resolve once confirmed (polling, no websocket); new errors TransactionFailedError, TransactionExpiredError, TransactionOutcomeUnknownError, ConfirmationTimeoutError, PreviousTransactionPendingError, SignatureReusedError, PaymasterError. Passkey transactions are sequenced. A passkey with no wallet can connect (key recovered from two signatures, one extra prompt). Large previews use the lookup tables instead of failing before the portal. expo-web-browser 15 accepted. |
| 2.2.0 (2026-09-30) | Callbacks run after isSigning clears; a send from onSuccess runs. Deferred window: expiryOffset 10–9000, default 1500 (was 300). DeferredExpiredError and its helpers. |
| 2.2.1 (2026-10-01) | An inner program's 3014 is no longer reported as DeferredExpiredError; isDeferredExpiredError is true for every DeferredExpiredError; DeferredFailureContext. |
| 2.3.0 (2026-10-02) | Breaking: addAuthorityEd25519 needs a role. connect and disconnect follow the callback contract, on the hook and the store; transferSol with no wallet calls onFail. The is*Error predicates recognise the adapter's own errors through wrappers. See below. |
Keys
The adapter never stores session or authority keys: createSession and
addAuthorityEd25519 take a public key, and you keep the secret key. Store it in the
platform's secure storage (for example expo-secure-store), not in AsyncStorage.
What the adapter keeps in AsyncStorage: the wallet record and config
(lazor-wallet-store), and per passkey the slot of its last transaction and any send
whose outcome is unknown (lazorkit:passkey-lane:…, the slot for ten minutes).
Keep the wallet a session key belongs to with the key, use the key only while that
wallet is connected, and delete it at disconnect and once its session is revoked or
expired. The package README's
Session keys
section (2.3.0) shows this with expo-secure-store.
Upgrading to 2.3.0
From 2.2.x. Full notes: the package CHANGELOG.
addAuthorityEd25519needs arole(breaking). There is no default any more. A call withoutroledoes not compile, and at runtime a missing role, or one that is notROLE_OWNER,ROLE_ADMINorROLE_SPENDER, throws before the portal opens. So doesROLE_OWNERon a v2 wallet, where the adapter never adds an Owner. Migration:addAuthorityEd25519({ newEd25519Pubkey, role: ROLE_SPENDER, policy }, options)keeps 2.2.1's behaviour. Ranks: useWallet › addAuthorityEd25519.connectanddisconnectcallbacks follow the sign actions' contract: they run once the call is over, and a throwingonSuccessis logged and changes nothing (in 2.2.1 it made the call reject). The store'sconnectcallsonSuccess/onFail(2.2.1 ignored them), and itsdisconnecttakes them. A secondconnectwhile one runs callsonFailat once.transferSolwith no wallet connected callsonFailand setserror, as every other action does (2.2.1 rejected without either).- Predicates.
isSignatureReusedError,isRetiredDeploymentErrorandisDeferredExpiredErrorrecognise the adapter's own errors, throughcauseand a wallet-adapterWalletError, so they work whereinstanceofdoes not.