Skip to main content
If you’re a token holder, this is the page you want. If you’re an operator, this is also how you self-delegate.

Prerequisites

  • A Solana wallet/keypair (the same keypair works on L1 and L2 — same address space).
  • LAYER in your wallet — either already on the L2 (the common case, since LAYER is L2-native), or the wrapped form on L1 devnet (mint in the overview), which you bridge back below.
  • SOL on L2 for L2 tx fees (native gas on the Solayer chain is SOL). If you have none yet, seed it while bridging via the additionalSolGas parameter, or bridge SOL separately.
  • SOL on L1 devnet — only if you’re bridging from L1: it pays the bridge tx + L1 fees (solana airdrop 2 -u devnet).
  • Node 18+ and these packages in your project:
If you already hold LAYER on the L2, you don’t need the bridge at all — skip straight to Delegate.

Bridge wrapped LAYER L1 to L2

Skip this section if you already hold LAYER on the L2 — since LAYER is L2-native, many holders never touch the bridge. Go straight to Delegate. LAYER’s home mint lives on the L2; the Solana (L1) form is a wrapped representation created by the bridge. For a Solayer-native token the bridge directions are therefore the reverse of what you may know from Solana-native tokens:
  • L2 → L1: native LAYER is locked in the L2 bridge vault, and wrapped LAYER is minted on L1 by the bridge handler (which holds the wrapped mint’s authority).
  • L1 → L2 (this section): your wrapped LAYER is burned on L1, and native LAYER is released from the L2 bridge vault to your L2 address.
You submit one transaction on L1; an off-chain guardian set observes it, multi-sig signs, and completes the release on L2. The whole thing is asynchronous — your L2 tokens appear once the guardians complete it (seconds to a couple of minutes).
The L2 side pays out of a vault, not a mint. An L1 → L2 release only works if the L2 bridge vault holds enough native LAYER — i.e. at least that much was previously bridged L2 → L1, or the team has seeded the vault. If the vault is short, your L1 burn still succeeds but the L2 completion cannot execute (InsufficientFunds on the bridge) until liquidity exists. You can check first: the vault is the LAYER ATA of the bridge handler PDA on the L2.
Bridge the wrapped form of LAYER, not just any token. Once the staking program is live, it only accepts deposits of Config.stake_mint — the native L2 LAYER mint. For a Solayer-native token this is not the PDA-derived ["mint", bridgeHandler, l1Mint] address (that derivation only applies to tokens whose home chain is the source chain, e.g. Solana-native tokens being wrapped onto the L2); what you receive on L2 is the original native mint recorded in the bridge’s TokenInfo account. After bridging, confirm the mint you received equals Config.stake_mint (see Check your position). If they differ, you bridged the wrong token and cannot stake it.
Only legacy SPL Token (Token-2020) mints and native SOL are bridgeable. Token-2022 is not supported.

Submit the bridge on L1

Because wrapped LAYER is a bridge-created token (not native to L1), this transaction burns it from your L1 account — the LAYER you’ll receive on L2 comes out of the L2 bridge vault, not a mint. additionalSolGas is useful on your first bridge: it gives the recipient L2 SOL to pay for the upcoming delegate/claim txs. Leave it 0 if you already have L2 SOL.
Bridging native SOL instead? Use bridge.createBridgeAssetSourceChainSolTransaction({ bridgeProofNonce, amount, recipient }).

Wait for the L2 release to complete

The guardians create a “bridge proof” on L2 when the vault release is done. Poll for it using the L1 signature:

Confirm what you received on L2

What lands on L2 is LAYER’s original native mint — on devnet LAYER4xPpTCb3QL8S9u41EAhAX7mhBn8Q6xMTwY2Yzc — as recorded in the bridge’s on-chain TokenInfo pairing (solana_mint = wrapped, solayer_mint = native). It is not a PDA-derived wrapped mint. Check your balance and, once the staking program is initialized, verify against the canonical Config.stake_mint:
The bridge SDK’s get_target_mint helper derives ["mint", bridgeHandler, sourceMint], which is only meaningful for tokens being bridged away from their home chain (e.g. a Solana-native token heading to the L2). Don’t rely on it for the wrapped-LAYER → native-LAYER direction documented here — confirm the mint against Config.stake_mint (or the bridge SDK docs) instead.

Delegate

Everything from here runs against the L2 RPC. We use @coral-xyz/anchor with the staking program’s IDL. Set up the client and PDA helpers once:
Now delegate. VALIDATOR_IDENTITY is the pubkey of the validator you chose; the validator must be active.
What happens: your amount is transferred from your ATA into the program vault, a StakeDelegation account is created (first time only), and any already-accrued rewards are settled to your wallet. From this moment your position earns the configured APY less your validator’s commission (effective apy * (1 - commission)). Calling delegate again on the same validator tops up the same position.

Claim, request unstake, complete unstake

Claim rewards (anytime)

Mints your accrued rewards to your ATA. Safe to call whenever; if nothing has accrued it’s a no-op.

Request unstake (starts the cooldown)

Moves amount of your active stake into a cooldown bucket. It stops earning immediately; your remaining stake keeps earning. Pending rewards are settled in the same call. Only one pending unstake per position at a time — wait for the current one to complete before requesting another.

Complete unstake (after the cooldown)

After Config.cooldown_seconds (7 days by default) have passed since the request, withdraw the cooled-down tokens from the vault back to your ATA.
Calling before the cooldown elapses fails with CooldownNotElapsed; calling with nothing pending fails with NoPendingUnstake.

Check your position & the deployment

Amounts are in the token’s base units. Divide by 10 ** decimals (read decimals from the mint via getMint) for human-readable values.