SDK v2 to v3
SDK v3 uses API version2026-09.caucasus. EVM-only integrations also need the changes below; adding a Solana account is optional. For HTTP request bodies, estimates and wire-level signing, see the Blanc to Caucasus API migration.
Target @rhinestone/sdk@3.0.0 on both your client and backend, then run your type checker:
Nest account configuration by VM
Move your existing account configuration underevm, including account, owners, sessions, recovery, eoa, modules and initData. Keep your existing owner, nonce and account version to preserve the EVM address.
The examples reuse your existing viem owner. Shared SDK authentication and provider configuration stay on RhinestoneSDK:
new RhinestoneSDK({ apiKey }) shorthand is removed and throws; use auth as shown. Keep API-key mode server-side. Browser integrations continue using JWT authentication.
account.config.evm, not account.config.owners. Let TypeScript infer the configuration: widening it to RhinestoneAccountConfig can hide the managed-account methods. An address-only entry such as { evm: { address } } is a receiver, not an account that can sign, fund or execute transactions.
Use VM-specific imports
@rhinestone/sdk/utils is removed. Its helpers keep their names under @rhinestone/sdk/evm. EVM validator constants also move there; solanaMainnet moves to @rhinestone/sdk/solana.
experimental_getV0InitData, experimental_getRhinestoneInitData, experimental_getModuleSetup, toViewOnlyAccount, and the WebAuthn, multi-factor and smart-session constants. VM-specific configuration types live in /evm or /solana; errors stay in @rhinestone/sdk/errors.
The EVM initialization and module-setup helpers still take the inner EVM configuration, not the composite { evm: ... } object.
Name one source and one destination
The SDK no longer discovers funding chains or tokens. Choose one source chain/token and one destination token per transaction. Multiple source chains, multiple source tokens and multiple delivery tokens have no equivalent in one v3 transaction.bigint amounts in token base units. Do not copy the HTTP API’s decimal-string amounts or destination.execution wrapper into SDK transaction inputs.
Amount and funding rules:
destination.tokenwithamountrequests exact output. With onlytoken, receive the maximum output the source yields. Omit both for execution without token delivery.source.maxAmountcaps the source balance available to the route; it does not promise to debit exactly that amount. Replace exact-input assumptions accordingly. For EVM sources, auxiliary funds are added after this cap.- A delivery always needs
source, even when sponsored. Execution without delivery can omit it only when gas-sponsored. HyperCore, Tron and Stellar destinations still need an explicit EVMsource.chain. source.callsrun before the claim. Theirprovidesentries must namesource.token; those amounts add tosource.auxiliaryFunds. Calls formerly omitted by source selection now run or are refused.- An explicit
destination.recipientis delivery-only: do not combine it with destination calls. To execute through the invoking managed account, omitrecipient. - Put
gasLimitalongside non-emptydestination.calls, not on a delivery-only request. Cross-chaincustomDeadlineandhyperCoreoptions on non-HyperCore destinations are refused rather than ignored.
{ chain: base, calls } becomes:
{ destination: { chain: base, calls }, sponsored: true }. If a smart session still needs enabling, name a source or enable it first; source-free preparation cannot insert its enable call.
Update deployment and setup
deploy now takes the VM first. Unsponsored intent-path deployment and setup also require a same-chain fee token:
account.deploy('evm', base, { sponsored: true }). UserOperation execution and funding options remain unchanged; the VM argument still applies to deploy.
Read quote requirements
Keep selectingprepared.quotes.best, or pass { intentId } to sign another quote from prepared.quotes.all. The quote now includes purpose, plan, requirements and signingRequests.
requirements is an array of erc20Approval and wrapNative requirements, replacing the chain/token map. Preparing discloses these prerequisites; it does not approve or wrap funds for you.
Quote costs, plans, requirements, signing context and bridgeFill.destinationChainId use CAIP-2 strings such as 'eip155:8453', not 8453. Bridge-fill variants include fillStatusTimeout; provider-specific IDs remain separate metadata, not replacements for chain identity. SDK transaction inputs and the submission handle’s sourceChains/targetChain remain numeric/viem-based.
Migrate custom and detached signing
The ordinary lifecycle stays the same:payload.kind explicitly:
eip712: honorsignatureFormat; an account-validator envelope is not a raw secp256k1 signature.personalSign: signmessage.valueas UTF-8 characters, not decoded hex.eip7702: return the authorization nonce and{ r, s, yParity }signature.webauthn: return the assertion, not an ECDSA signature.
eip712 proof containing { preClaim, notarizedClaim }, not two slots. signIntent now takes SigningRequest[] instead of SignData and returns { proofs }.
Detached EVM owner signing keeps the same method flow:
slots instead of origin, and covers all required account-authorized requests, including target execution. Do not rebuild it from the old serialized shape. Contributions must belong to the same intent and ordered request set. Independent owner signing is not supported for smart-session or Solana-origin transactions.
EIP-7702 authorizations
Normal signing now collects delegation proofs automatically. Remove the separate submission option:signAuthorizations returns intent-bound, indexed proof contributions. Pass them to assembly, not submission:
Upgrade sponsorship before clients
For intent-bound JWT sponsorship, deploy the updated@rhinestone/sdk/jwt-server helpers, or your custom signer, before upgrading clients. The v3 approval identifier is sdk-3.0.0-caucasus.
The updated shouldSponsor helper accepts this input and the Blanc input without a contractVersion from v2 clients, so you can upgrade the backend while v2 clients remain active. Other contract identifiers, including those from earlier v3 snapshots, are not supported by the helper.
Custom policies must stop reading the old approval fields:
These are approval-input fields, not SDK transaction inputs. Forward the exact
intentInput supplied to getIntentExtensionToken; do not reconstruct it from your UI transaction. See the sponsorship section of the API migration guide for the wire contract and digest rules.
Using the built-in policy adapter avoids hard-coding those approval fields. Its callbacks retain numeric chain IDs and bigint call values:
createJwtSigner, configure shouldSponsor filters explicitly; omitting filters does not validate your sponsorship policy. For Solana-only operations, the account filter receives the Swig wallet rather than an EVM address, and a calls filter is not a Solana-instruction policy.
As in current v2 releases, approval runs during preparation, not submission. Denial stops preparation without an unsponsored fallback; submitting a restored prepared transaction does not request another grant.
Swap sponsorship continues to use sponsored.swaps, as in current v2 releases. If older integration code still sends sponsored.swapValue, remove it; there is no separate client switch for swap-value sponsorship:
Handle grouped status and native transaction references
PENDING, COMPLETED and FAILED remain unchanged. Replace the flat operation list with chain groups containing operation items:
vm: EVM and Stellar use txHash, Solana uses signature, and Tron uses txId. Historical unknown-chain records can retain a numeric chain ID and { vm: 'unknown', id }; do not fabricate a chain mapping.
Do not infer missing account or Swig-authority evidence. An empty refund list means none were observed, not proof no refund occurred.
HyperCore’s six outcomes are unchanged. On failure, inspect
IntentFailedError.context.operations instead of .hyperCore. For partial, error or unknown outcomes, check the Hyperliquid account before retrying to avoid duplicate orders.
Use rhinestone.getIntentStatus(intentId, { full: true }) for recorded details. Execution details describe the intended execution, not individual call-success results; use operation status and transaction evidence to establish completion.
Replace removed public types
Reconcile persisted transactions
Do not restore v2 prepared or signed transactions into v3. Reconcile any possible submission using its original intent ID before deliberately preparing a replacement; a timeout is not proof the spend failed. Persist the complete new prepared artifact, including its opaquerequest binding, using serialization that preserves bigint values. Do not retain only intentInput, edit the binding, or combine proofs with a fresh quote. Old-generation artifacts or artifacts missing request fail with InvalidPreparedTransactionError; the SDK does not convert or automatically re-quote them. Older Solana snapshot artifacts can fail with InvalidSolanaTransactionArtifactError.
Review smart session definitions
v3 removes these inputs. Delete the keys entirely: setting them toundefined or an empty value still throws.
v2 deprecates the shorthand and
claimPolicies but still accepts them. Nested API-key and JWT auth, and bundler and paymaster credentials, are unchanged.
Smart session behavior changed in v2 2.17.0, and v3 carries it forward. If you are upgrading from 2.17.x, your session semantics already match; remove the inputs above, and pass an explicit source on one-time-use intents. If you are upgrading from 2.16.x or earlier:
- Cross-chain permits are scoped by default. Open wildcard access is opt-in through
fallback. - Omitted settlement layers select every layer that can settle the permit, and explicit lists are strict.
ECOis retired; useECO_IE. - A reusable permit’s
maxAmountis a lifetime budget. Re-enabling an enabled session requiresallowBudgetReset. - Sessions add permit, swap, and one-time-use windows, and a one-time-use option.
- When
signingis omitted, scoped sessions default to disabled signing; see Session signing.
createSession, inspect validateSession output, and persist the result. Sessions you already stored stay usable for enable, sign, and disable: pass the stored Session directly and do not rebuild it from a definition. An installed grant keeps its installed policies, so revoke it or authorize a replacement deliberately. See Store the created session.
These session changes do not change account addresses or factory data.
What stays the same for EVM-only integrations
- You do not need a Solana account, signer or dependency. Configure only
evm. - Existing EVM account identities remain stable with the same configuration. Preserve any older Startale version explicitly, as described above.
- The prepare → sign → submit → wait lifecycle, quote selection and terminal status names stay the same.
- Managed EVM accounts retain reads, message signing, modules, recovery and UserOperation methods. UserOperation inputs remain flat
{ chain, calls, ... }; do not apply the intent input migration to them. - Shared authentication/providers,
appFees,protocolFees, settlement-layer/quoter filters, and HyperCore order builders retain their roles. Move only the transaction-specific fields described above. - Preparation neither signs, spends nor deploys.
getAddress('solana') returns the asset-holding wallet, not the Swig state account; construction alone does not deploy or verify it. EVM-to-Solana delivery does not require a managed Solana account when you provide the recipient. It does not authorize destination instructions. Solana-to-EVM calls remain restricted to a backend-compatible EVM-derived Swig pairing; unrelated pairs support delivery only.
Before switching traffic, verify derived EVM addresses, explicit funding and amount behavior, custom signing, sponsored preparation, status rendering, and your existing UserOperation path.
SDK v1 to v2
This section is historical v2 guidance. For v3, also apply the migration above. This guide targets@rhinestone/sdk 2.16.1. Upgrade and run your type checker before changing behavior:
import syntax and only published entry points such as @rhinestone/sdk, @rhinestone/sdk/utils, @rhinestone/sdk/actions/*, and @rhinestone/sdk/smart-sessions.
Initialize the SDK and account
createRhinestoneAccount is removed. Create one SDK instance for shared authentication, RPC, bundler, and paymaster configuration, then create accounts from it.
Replace transaction shortcuts
account.sendTransaction is removed for intents. Use the explicit lifecycle:
- Pass token addresses, not symbols such as
USDCorWETH. - Read the recommended route from
prepared.quotes.best; all routes are inprepared.quotes.all. - To select another route, call
signTransaction(prepared, { intentId })with an ID fromquotes.all. - Change
settlementLayersarrays to{ include: [...] }or{ exclude: [...] }. - Pass EIP-7702 authorizations as
submitTransaction(signed, { authorizations }). - Remove the second
acceptsPreconfirmationsargument fromwaitForExecution. - Store intent IDs as strings before passing them to
rhinestone.getIntentStatus(intentId).
Migrate session keys
The 1.x experimental session names became stable in 2.x. Replaceexperimental_sessions and type: 'experimental_session' with sessions and type: 'session', then remove the experimental_ prefix from session account methods.
Do not copy a 1.x resolved Session.actions object into 2.x. Recreate the permission with the current ABI-driven configuration and verify its permission ID before enabling it. Continue with create a session for the current session workflow.
Update account and provider configuration
- Alchemy’s
{ type: 'alchemy', apiKey }provider configuration is removed. Supply complete per-chain URLs with{ type: 'custom', urls }; see JSON-RPC providers. passportaccounts are removed.- Nexus supports
1.2.0and1.2.1; Kernel supports3.3. Remove older pinned versions. submitTransactionoptions are now an object, including EIP-7702 authorizations.PortfolioToken.decimalsand aggregatebalancesmoved to per-chain entries aschains[].decimalsandchains[].amount.
Update imports and removed helpers
Use these published 2.x locations:deployAccountsForOwners, and checkERC20AllowanceDirect are also removed. Replace allowance reads with viem readContract; use the current account deployment methods and orchestrator-provided signing data for the other flows.
After migration, verify derived account addresses, session permission IDs, token decimals per chain, and both intent and UserOperation paths in a test environment.