Skip to main content
Zodia Custody enables you to delegate SOL from a DeFi custody wallet to a Solana validator directly through the Digital Asset Service Desk API, and to track your stake accounts and balances with a dashboard endpoint. For ETH staking, see ETH Staking.

How SOL Staking Works

SOL staking is made of three separate operations, each submitted as its own service request: Unstaking and withdrawing are always two steps, for every provider: unstake, wait for the cooldown to complete, then withdraw.

Providers

Staking providers are onboarded for your company by Zodia, together with the validator your SOL is delegated to. You choose a provider in the provider field of the Stake payload, in upper case, for example BLOCKDAEMON or MARINADE. You don’t choose the validator in the request. The payload is the same for every provider. MARINADE differs from the other providers when withdrawing: a Withdrawal doesn’t use amount, and everything that is ready to withdraw is withdrawn. With any other provider, the amount you send is withdrawn.

Staking Operations

Every SOL staking operation is submitted the same way as any other Digital Asset Service Desk product: create the instruction with POST /v3/api/servicedesk/create and a {"serviceId": ..., "payload": ...} body, then submit, confirm and approve it following the same steps described in Signing the Payload and demonstrated end-to-end in Wallet Creation. What follows is what’s specific to each SOL operation; see Products & Services for the exact payload template of each one. All three operations require a DeFi wallet, otherwise the request is rejected with ER-259. Amounts are expressed in SOL and sent as strings.

Stake (0x0020-024)

Staking delegates amount SOL from walletId through the provider you choose.
  • Minimum amount: amount must be at least 1 SOL, for every provider.
  • Balance: the wallet must hold the staked amount plus the network fee and the rent-exempt reserve of the new stake account.
  • One provider per wallet: a wallet is pinned to the first staking provider it was used with. Staking again with a different provider is rejected with ER-3004.
  • Validator: your SOL is delegated to the validator Zodia has set up for your account and the provider you choose. It isn’t chosen in the request.

Unstake (0x0020-025)

Unstaking deactivates amount SOL and starts the cooldown. provider isn’t needed, it’s taken from the wallet’s staking history.
  • Amount: amount can’t exceed the amount currently available to unstake. A larger amount is rejected with ER-122, and the message gives the limit in lamports (1 SOL = 1,000,000,000 lamports). If the available amount can’t be checked at that moment, the request fails with a 500 and can be retried.
  • Stake accounts: you can’t choose which stake accounts are unstaked. The amount is applied across your stake accounts, and an account may be split so that exactly amount is deactivated.
  • Available balance: to create the request, the wallet must hold a minimum available SOL balance on top of the network fee, currently 1 SOL in production, whatever the amount you are unstaking. Otherwise the request is rejected with ER-214 or ER-255.
Once the cooldown is over, the SOL moves to inactive stake accounts and shows up as withdrawable in the dashboard.

Withdrawal (0x0020-026)

Withdrawal moves SOL from inactive stake accounts back to your custody wallet.
  • Amount: amount can’t exceed the withdrawable amount. A larger amount is rejected with ER-122 (limit in lamports). If the withdrawable amount can’t be checked at that moment, the request fails with a 500 and can be retried.
  • Marinade: amount is not used. All funds that are ready to withdraw are withdrawn, and the request is rejected with ER-ASE-011 if there are none.

Tracking Your Position

Get SOL Staking Dashboard returns the staking position of a SOL wallet: balances, and the stake accounts behind them grouped by state. It takes the wallet ID only:
Here is an example response for a wallet with one active stake account and one inactive stake account that is ready to be withdrawn:

Balances

Each entry in balances covers the stake accounts in one state, and excludes the rent-exempt reserve that every stake account holds. stakeAccounts lists, for each state, the number of stake accounts (count), their addresses (accounts) and their combined balance. That balance includes the rent-exempt reserve of each account, so it is slightly higher than the matching figure in balances. Inactive accounts with nothing left to withdraw are not listed. The dashboard covers every stake account controlled by the wallet, whichever provider it was created with, and doesn’t break the position down by validator.

Amounts

  • amount is a string in SOL with 8 decimals and comma thousands separators. Use amountUnit, the amount in lamports, when you need the exact value.
  • fiatValue is a number with 2 decimals, expressed in fiatCurrency, the fiat currency configured for your account.
  • provider is the provider the wallet has staked with. It is left out when the wallet has no staking history.
  • A wallet that has never staked returns zero amounts and empty accounts lists.

Data Freshness

Dashboard figures are not real time. lastUpdated shows when they were last updated, and a stake, unstake or withdrawal can take up to about 15 minutes to be reflected. If the position can’t be retrieved at that moment, the endpoint returns a 503 (ER-206): retry later.

Notifications

Each SOL operation results in at least one on-chain transaction, and an Unstake or a Withdrawal can result in several, for example when several stake accounts are involved. If you have webhooks configured, you receive Transfer notifications as each transaction is posted on chain and confirmed. To follow your overall position, use the dashboard: SOL moves to withdrawable once the cooldown following an unstake is over.

Errors

See Staking Error Codes for the errors specific to SOL staking.

FAQs

How long does it take for staked SOL to start earning rewards?

A stake account is activating until the delegation takes effect on the Solana network, which happens at an epoch boundary. Use the dashboard to follow it.

Why does my dashboard not show my last operation yet?

Dashboard figures are not real time and can take up to about 15 minutes to reflect an operation. Compare lastUpdated with the time of your operation.

Can I choose which stake account is unstaked or withdrawn?

No. You send an amount, and the provider decides which stake accounts are used.

Why did my Unstake or Withdrawal result in several transactions?

An Unstake or a Withdrawal can involve several stake accounts, which results in several on-chain transactions. They all belong to the same service request, and each is notified separately through your webhooks as it is posted on chain and confirmed. The dashboard reflects the combined result.

Contact

If you’re a Zodia client and want to learn more about this feature or enable it, contact our customer service team. Email us at customerservice@zodia.io. We’re here to answer questions, provide more details, or help activate the feature. Our team is ready to assist you with quick and effective support.