Logo
New RPC users get 35% off their first monthView the offer
RPC Assistant

Acala Liquid Staking: How LDOT Works and What to Check Before You Stake

Summary

Acala liquid staking lets you deposit DOT into Acala's staking module and receive LDOT, a transferable derivative token that keeps earning staking rewards while you use it elsewhere in DeFi. This article explains how the flow works, what LDOT represents, and the RPC and API surface you need to read staking state or build a liquid staking integration. It also covers the operational questions developers hit first: which endpoints to use, how to query exchange rates and unbonding state, and when a shared public endpoint is enough versus when a dedicated node fits better.

Acala liquid staking is the part of the Acala network that lets you stake DOT without locking your capital into a single illiquid position. You deposit DOT, the protocol stakes it through its staking module, and you receive LDOT — a derivative token that represents your staked position and stays transferable. LDOT can be held, moved, or used in other Acala DeFi primitives while the underlying DOT keeps accruing staking rewards.

If you are a developer or infrastructure buyer, the interesting part is not the token mechanics alone. It is the data surface: how you read staking state, how you track the LDOT exchange rate, how you detect unbonding windows, and which RPC endpoint you point your backend at. This article walks through both sides — the staking model and the API calls you will actually write.

Quick recommendation: shared endpoint or dedicated node?

Before you write any integration code, decide what kind of workload you are running. Acala liquid staking touches the chain in two very different ways, and they have different infrastructure needs.

WorkloadTypical call patternWhat to start with
Wallet or dashboard reading balances and exchange rateLow-volume, periodic readsA shared RPC endpoint from a managed provider
Staking bot that watches unbonding queues and reward accrualFrequent polling, sometimes subscriptionsA dedicated node or a provider plan with predictable throughput
Indexer that backfills historical staking eventsLarge block ranges, archive-style readsArchive-capable infrastructure, not a public endpoint
dApp that submits staking extrinsics on behalf of usersWrite path plus confirmation trackingA provider you can fail over between, with monitoring

A shared endpoint is usually fine for read-only dashboards and prototypes. The moment you poll staking state on a tight interval, backfill history, or submit extrinsics that users depend on, the shared path becomes the bottleneck. That is the point where a dedicated node or a managed RPC plan with clear throughput expectations is the safer choice. OnFinality offers both RPC API access and dedicated node infrastructure for Acala, so you can start shared and move to dedicated without changing your application code.

How the Acala liquid staking flow actually works

The flow has four moving parts you should understand before you touch the API.

  1. Deposit. You send DOT to the staking module. The protocol bonds that DOT to its validator set.
  2. Mint. In return you receive LDOT at the current exchange rate. LDOT is not a fixed 1:1 claim — it represents a share of the pooled staked position.
  3. Accrue. As the underlying DOT earns staking rewards, the value backing each LDOT grows. The exchange rate between LDOT and DOT drifts upward over time.
  4. Redeem. When you want DOT back, you redeem LDOT. Depending on the module's state, redemption may be immediate or may enter an unbonding queue that settles over an unbonding period.

The key implication for developers: LDOT is not a static balance. If your UI shows "1 LDOT = 1 DOT" you are showing the wrong number. You need to read the current exchange rate from chain state and recompute the user's underlying DOT value every time you display it.

Reading staking state over RPC

Acala is a Substrate-based chain, so you interact with it through the Polkadot.js-style JSON-RPC interface and the runtime's storage and extrinsic metadata. The exact storage keys and extrinsic names come from the runtime, so always resolve them from the chain's metadata rather than hardcoding them from a blog post — including this one. The pattern below shows the shape of the calls.

First, confirm you are talking to the right chain and that your endpoint responds:

curl -s https://acala.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "system_chain",
    "params": []
  }'

A healthy response returns the chain name. If you get a timeout or an empty body, that is your first debugging signal — check the endpoint, not your staking logic.

Next, read the runtime version and metadata so your client knows which storage items and extrinsics exist:

curl -s https://acala.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "state_getRuntimeVersion",
    "params": []
  }'

From there, a Polkadot.js client can query the staking module's storage directly. In JavaScript, the pattern looks like this:

import { ApiPromise, WsProvider } from '@polkadot/api';

const provider = new WsProvider('wss://acala.api.onfinality.io/public-ws');
const api = await ApiPromise.create({ provider });

// Resolve the staking module and its storage from live metadata
const staking = api.query.homa || api.query.homaLite;

// Example: read total staked and the current exchange rate
const totalStaked = await staking.totalStakingBonded();
const exchangeRate = await staking.liquidTokenExchangeRate();

console.log('Total staked:', totalStaked.toString());
console.log('LDOT exchange rate:', exchangeRate.toString());

The module name and storage item names depend on the runtime version. If api.query.homa is undefined, inspect api.query keys at runtime and confirm the module that is actually deployed on the chain you are connected to. This is the single most common source of "my staking call returns nothing" bugs.

Querying the LDOT exchange rate and unbonding state

Two numbers matter most for any liquid staking integration: the exchange rate and the unbonding state.

Exchange rate. This is what converts an LDOT balance into its underlying DOT value. Read it from chain state, cache it briefly, and refresh it on a schedule that matches how often it actually changes. Polling it every block is usually wasteful; polling it once per epoch is usually too slow for a live dashboard. Pick a cadence and document it.

Unbonding state. When a user redeems, the DOT may not be available instantly. Your UI should distinguish between "redeemable now" and "in unbonding queue, settles in N eras." That means reading the queue length and the unbonding period from the runtime, not guessing.

What you want to showWhere it comes fromRefresh cadence
User's LDOT balanceAccount storage for the liquid tokenOn demand / per block
Underlying DOT valueLDOT balance × current exchange rateEvery few minutes
Pending redemptionUnbonding queue storageEvery few minutes
Time until settlementUnbonding period from runtime constantsOn runtime upgrade
Reward accrual trendExchange rate historyHourly or daily

If you need historical exchange rates for charts, you are now in archive territory. A public endpoint is not the right tool for backfilling months of state; plan for archive-capable infrastructure.

Acala chain settings at a glance

Keep these settings consistent across your wallet config, your backend, and your monitoring.

SettingValue
NetworkAcala (Polkadot parachain)
TokenACA (native), DOT (staking asset), LDOT (liquid derivative)
InterfaceSubstrate JSON-RPC and WebSocket
Public HTTP endpointhttps://acala.api.onfinality.io/public
Public WebSocket endpointwss://acala.api.onfinality.io/public-ws
Transport supportHTTP and WebSocket

You can find the current endpoint list and network details on the Acala network page. If you are integrating through an EVM-compatible path, note that Acala's EVM layer is a separate concern from the Substrate staking module — liquid staking state lives on the Substrate side, so do not expect an ERC-20-style call to return it.

Common failure modes and how to debug them

Liquid staking integrations fail in a small number of predictable ways. Here is the short diagnostic list.

  • Storage item returns null. Your client is on a runtime where the module or item name changed, or you are connected to a different chain. Check system_chain and state_getRuntimeVersion first.
  • Exchange rate looks frozen. You are reading a cached value, or your polling interval is longer than the rate's update cadence. Log the raw value and the block number together.
  • Extrinsic submits but never finalizes. You are tracking inclusion, not finalization. Subscribe to finalized heads, not just new heads, before you mark a staking action complete.
  • WebSocket disconnects under load. Long-lived subscriptions need reconnect logic with backoff. Treat a dropped socket as normal, not exceptional.
  • Reads get slow at peak. Shared endpoints absorb traffic from many callers. If your latency is unpredictable, that is a signal to move to a dedicated node rather than to retry harder.

A minimal monitoring probe keeps you ahead of most of these:

#!/usr/bin/env bash
# Probe Acala RPC health and record the block height
RESP=$(curl -s --max-time 5 https://acala.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"chain_getHeader","params":[]}')
echo "$(date -u +%FT%TZ) $RESP" >> acala-rpc-health.log

Run this on a schedule, alert when the height stops advancing, and you will catch endpoint problems before your users do.

Build versus buy for a staking backend

If you are running a liquid staking dashboard, a rewards tracker, or a bot that acts on unbonding windows, you have a build-versus-buy decision on infrastructure.

Running your own Acala node gives you full control and no shared throughput ceiling, but it means provisioning, syncing, upgrading on runtime changes, and monitoring the node yourself. For a team whose product is the staking logic, that is often a distraction.

A managed RPC provider removes the node operations but introduces a dependency: you need to know the provider's throughput expectations, whether they support WebSocket subscriptions, whether archive reads are available, and how you fail over. When you evaluate options, put the questions in this order:

  1. Does it support both HTTP and WebSocket for Acala?
  2. Can it handle your polling cadence without unpredictable latency?
  3. Is there an archive path if you need historical state?
  4. What happens when the endpoint degrades — can you switch without redeploying?
  5. Is pricing predictable at your request volume?

OnFinality provides Acala RPC through its API service and offers dedicated nodes when you need isolated throughput. You can review RPC pricing and the full list of supported RPC networks to see how Acala fits alongside the other chains you run. For a broader framework, the RPC provider selection guide covers the evaluation criteria in more depth.

Key Takeaways

  • Acala liquid staking turns staked DOT into LDOT, a transferable derivative that keeps earning rewards.
  • LDOT is not 1:1 with DOT — always read the live exchange rate from chain state before displaying value.
  • Acala is Substrate-based, so you query staking state through the Polkadot.js-style JSON-RPC and runtime metadata, not an ERC-20 call.
  • Resolve module and storage names from live metadata; hardcoded names break on runtime upgrades.
  • Track finalized heads, not just new heads, before marking a staking extrinsic complete.
  • Shared endpoints suit dashboards and prototypes; dedicated nodes suit bots, indexers, and write-heavy paths.
  • Monitor block height on a schedule so endpoint degradation surfaces before users notice.

Frequently Asked Questions

Is LDOT always worth the same as DOT? No. LDOT represents a share of a pooled staked position, so its DOT value changes as rewards accrue. Read the exchange rate from chain state.

Can I read liquid staking state through an EVM call? The staking module lives on the Substrate side of Acala. Use the Substrate JSON-RPC interface rather than expecting an ERC-20-style contract call to return staking state.

Why does my staking storage query return null? Usually because the module or storage item name changed in a runtime upgrade, or because you are connected to a different chain. Verify with system_chain and state_getRuntimeVersion.

Do I need a dedicated node for a staking dashboard? Not necessarily. A shared endpoint is fine for low-volume reads. Move to a dedicated node when your polling cadence, subscription count, or write path makes shared throughput unpredictable.

How often should I refresh the exchange rate? Match your cadence to how often the value actually changes. Polling every block is usually wasteful; polling once per epoch is usually too slow for a live UI.

Can I backfill historical staking data on a public endpoint? Public endpoints are not intended for large historical reads. Plan for archive-capable infrastructure if you need to backfill state or events.

RPC Knowledge Base

Related RPC details

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started