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
additionalSolGasparameter, 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:
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.
Only legacy SPL Token (Token-2020) mints and native SOL are bridgeable.
Token-2022 is not supported.
Submit the bridge on L1
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 devnetLAYER4xPpTCb3QL8S9u41EAhAX7mhBn8Q6xMTwY2Yzc — 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:
VALIDATOR_IDENTITY is the pubkey of the validator you chose;
the validator must be active.
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)
Movesamount 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)
AfterConfig.cooldown_seconds (7 days by default) have passed since the
request, withdraw the cooled-down tokens from the vault back to your ATA.
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.