Welcome, Solana builder 👋 You are about to give your users a single-click staking flow while keeping full programmatic control in your codebase. The Helius Node.js SDK already wraps every low-level detail, so your job is mostly to decide when to call each helper and who signs the resulting transaction

This guide starts with general information about staking on Solana, then shows how to install the SDK, and finally walks through the full staking lifecycle with practical examples


1. Staking on Solana

  • Stake account
    A special account that locks up SOL. The SOL inside is delegated to a validator of your choice. You can have as many stake accounts as you like and each one points at exactly one validator
  • Rewards
    The validator earns rewards for producing blocks. Those rewards flow back into every stake account that selected that validator. When you use the Helius validator the commission rate is 0 %, so users keep everything
  • Life-cycle
    1 ) Create and delegate
    2 ) Cool down (optional deactivation)
    3 ) Withdraw or re-delegate

    The helper methods map to these exact lifecycle phases

2. One-time Setup

# Install only what is required
npm i helius-sdk @solana/web3.js bs58

From this point on, every snippet will assume you imported this helius instance and that you hold a funded Keypair called payer.


3. Method Reference with Example Calls

createStakeTransaction

Builds a serialized, unsigned transaction that creates a new stake account, and delegates it to the Helius validator

Example call:

await helius.rpc.createStakeTransaction(owner, 1.5)

Return value:

{'{ serializedTx, stakeAccountPubkey }'}

getStakeInstructions

The same as createStakeTransaction, except it only returns the TransactionInstruction[]. This is useful inside browser wallets that construct their own transaction object, or pairing with the SDK’s smart transactions

Example call:

await helius.rpc.getStakeInstructions(owner, 1.5)

Return value:

{'{ instructions, stakeAccount }'}

createUnstakeTransaction

Builds a serialized, unsigned transaction that sends a Deactivate instruction to an existing stake account

Example call:

await helius.rpc.createUnstakeTransaction(owner, stakeAcc)

Return value:

serializedTx

getUnstakeInstruction

Single Deactivate instruction with no wrapper transaction

Example call:

helius.rpc.getUnstakeInstruction(owner, stakeAcc)

Return value:

TransactionInstruction

getWithdrawableAmount

Returns the number of lamports that can be withdrawn right now from a given stake account. Pass true to include the rent-exempt minimum into the withdrawable amount

Example call:

await helius.rpc.getWithdrawableAmount(stakeAcc, true)

Return value:

number

createWithdrawTransaction

Builds a serialized, unsigned transaction that moves lamports out of a stake account into any destination address. Works only after the cooldown period has ended

Example call:

await helius.rpc.createWithdrawTransaction(owner, stakeAcc, dest, amount)

Return value:

serializedTx

getWithdrawInstruction

Stand-alone withdraw instruction

Example call:

helius.rpc.getWithdrawInstruction(owner, stakeAcc, dest, amount)

Return value:

TransactionInstruction

getHeliusStakeAccounts

Returns all stake accounts that are currently delegated to the Helius validator for a given wallet

Example call:

await helius.rpc.getHeliusStakeAccounts(wallet)

Return value:

ParsedAccountData[]

4. Quickstart: Stake in Three Simple Steps

import { Transaction } from '@solana/web3.js';
import bs58 from 'bs58';

/* 1. Build the unsigned transaction */
const { serializedTx, stakeAccountPubkey } =
  await helius.rpc.createStakeTransaction(payer.publicKey, 1.5); // amount in SOL, rent added automatically

/* 2. Sign with the fee payer */
const tx = Transaction.from(bs58.decode(serializedTx));
tx.partialSign(payer);          // the new stake account is already signed by the SDK

/* 3. Broadcast */
const sig = await helius.connection.sendRawTransaction(tx.serialize());
console.log(`Staked 1.5 SOL. Track it at https://orb.helius.dev/tx/${sig}`);

5. Full Lifecycle Cookbook

5.1 Fetch every stake account that delegates to Helius for a given wallet

import { LAMPORTS_PER_SOL } from '@solana/web3.js';

const accounts = await helius.rpc.getHeliusStakeAccounts(payer.publicKey.toBase58());

accounts.forEach(acc => {
  const d = (acc.account.data as any).parsed.info.stake.delegation;
  console.log(
    `${acc.pubkey.toBase58()} holds ${d.stake / LAMPORTS_PER_SOL} SOL (activated in epoch ${d.activationEpoch})`
  );
});

5.2 Deactivate (begin cooldown)

const blob = await helius.rpc.createUnstakeTransaction(payer.publicKey, stakeAccountPubkey);

const tx = Transaction.from(bs58.decode(blob));
tx.partialSign(payer);

await helius.connection.sendRawTransaction(tx.serialize());
console.log('Deactivation requested. The stake becomes withdrawable at the end of the current epoch.');

5.3 Check how many lamports can be withdrawn

const lamportsNow   = await helius.rpc.getWithdrawableAmount(stakeAccountPubkey);
const lamportsTotal = await helius.rpc.getWithdrawableAmount(stakeAccountPubkey, true);

console.log(`Available right now: ${lamportsNow}. Full balance: ${lamportsTotal}.`);

5.4 Withdraw part, or all, of the balance

const instruction = helius.rpc.getWithdrawInstruction(
  payer.publicKey,
  stakeAccountPubkey,
  destinationPubkey,
  lamportsTotal        // withdraw everything; use a smaller number for partial
);

const sig = await helius.rpc.sendSmartTransaction([instruction], [payer]);
console.log(`Withdrawal sent. Track it at https://orb.helius.dev/tx/${sig}`);

6. Power User Patterns


7. Common Pitfalls

  • Epoch timing
    A Solana epoch lasts roughly two days. If you deactivate halfway through epoch 600, the stake stays locked until epoch 601 begins

  • Rent exempt minimum
    The stake account will be closed if you withdraw the full balance, including rent. If you withdraw less than the rent-exempt threshold, the account will remain open

  • Hardware wallets
    Users see two prompts: one signature for the new stake account (already signed within the blob) and one for the fee payer. Make sure your UX explains this


8. One-page Cheat Sheet

// Stake SOL to Helius validator
await helius.rpc.createStakeTransaction(owner, amountInSol);

// Deactivate stake account
await helius.rpc.createUnstakeTransaction(owner, stakeAccount);

// Withdraw SOL (after cooldown)
helius.rpc.getWithdrawInstruction(owner, stakeAccount, destination, lamports);

Next Steps

Happy building and happy earning!