API

Extrinsic

Stake

User stake asset (KSM/DOT) to get liquid asset(sKSM/sDOT)
const hash = await api.tx.liquidStaking.stake(100).signAndSend(currentAccount)

Unstake

User unstake liquid asset(sKSM/sDOT) to get asset (KSM/DOT), this could be take 28 eras' locking period.
const hash = await api.tx.liquidStaking.unstake(100).signAndSend(currentAccount)

ClaimFor

Once locking time reach, user can claim their assets back, now Parallel team will claim for our users.
await api.tx.liquidStaking.claimFor(alice).signAndSend(currentAccount)

Storage

ExchangeRate

const exchangeRate = await api.query.liquidStaking.exchangeRate()

PendingUnstakes

const currentEra = await api.query.liquidStaking.currentEra()
const eraLength = api.consts.liquidStaking.eraLength
const bondingDuration = api.consts.liquidStaking.bondingDuration
const eraStartBlock = await api.query.liquidStaking.eraStartBlock()
const relayChainBlock = await relayApi.rpc.chain.getBlock()
const relayChainBlockNumber = relayChainBlock.block.header.number
const allPendingUnstakes = []
const unlockings = await api.query.liquidStaking.unlockings(alice)
unlockings.forEach(({era: targetEra, value: amount}) => {
allPendingUnstakes.push([amount, Math.max((targetEra - currentEra) * EraLength - (relayChainBlockNumber - eraStartBlock), 0) * 6s])
});
const totalPendingUnstake = _.sum(allPendingUnstakes.map(([amount,]) => amount))

CurrentEra

const currentEra = await api.query.liquidStaking.currentEra()
const historyEras = [...Array(currentEra).keys()]

Staking Currency

const stakingCurrency = api.consts.liquidStaking.stakingCurrency

LIquid Currency

const liquidCurrency = api.consts.liquidStaking.liquiCurrency

MinStake

const minStake = api.consts.liquidStaking.minStake

MinUnstake

const minUnstake = api.consts.liquidStaking.minUnstake

TotalBonded

import { stringToU8a, u8aConcat, bnToU8a } from '@polkadot/util'
import { blake2AsU8a } from '@polkadot/util-crypto'
import { decodeAddress, encodeAddress } from '@polkadot/keyring'
const EMPTY_U8A_32 = new Uint8Array(32)
export const sovereignAccountOf = (paraId: number): string =>
encodeAddress(
u8aConcat(
stringToU8a('para'),
bnToU8a(paraId, 32, true),
EMPTY_U8A_32
).subarray(0, 32)
)
export const subAccountId = (signer: string, index: number): string => {
const seedBytes = stringToU8a('modlpy/utilisuba')
const whoBytes = decodeAddress(signer)
const indexBytes = bnToU8a(index, 16).reverse()
const combinedBytes = new Uint8Array(
seedBytes.length + whoBytes.length + indexBytes.length
)
combinedBytes.set(seedBytes)
combinedBytes.set(whoBytes, seedBytes.length)
combinedBytes.set(indexBytes, seedBytes.length + whoBytes.length)
const entropy = blake2AsU8a(combinedBytes, 256)
return encodeAddress(entropy)
}
const derivativeIndexList = api.consts.liquidStaking.derivativeIndexList
const paraId = await api.query.parachainInfo.parachainId()
const { totalBonded, totalUnbonding } = derivativeIndexList.reduce(async (acc, cur) => {
const derivativeAccount = subAccountId(sovereignAccountOf(paraId), cur)
const ledger = await api.query.liquidStaking.stakingLedgers(derivativeIndex)
acc.totalBonded += ledger.active
acc.totalUnbonding += ledger.total - ledger.active
return acc
}, { totalBonded: 0, totalUnbonding: 0 })

TVL

import { stringToU8a, u8aConcat } from '@polkadot/util'
import { encodeAddress } from '@polkadot/keyring'
const EMPTY_U8A_32 = new Uint8Array(32)
const createAddress = (id: string): string =>
encodeAddress(u8aConcat(stringToU8a(`modl${id}`), EMPTY_U8A_32).subarray(0, 32))
const poolAccount = createAddress('par/lqsk')
const poolAccountBalance = (await api.query.assets.account(stakingCurrency, poolAccount)).balance
const totalReserves = await api.query.liquidStaking.totalReserves()
const tvl = (totalBonded + \
totalUnbonding + \
poolAccountBalance - \
totalReserves) * (KSM or DOT price)
# Note:
# `totalBonded + totalUnbonding` is tvl of the parachain
# `poolAccountBalance - totalReserves` = not distributed and not delivered yet

Wait Time

const bondingDuration = api.consts.liquidStaking.bondingDuration
const eraLength = api.consts.liquidStaking.eraLength
const waitTimePolkadotOrKusama = toDays(eraLength * (bondingDuration + 1) * 6s)
const waitTimeTestnet = toHours(eraLength * (bondingDuration + 1) * 6s)

Validators

const derivativeAccount = subAccountId(sovereignAccountOf(paraId), derivativeIndex)
const nominations = await relayApi.query.staking.nominators(derivativeAccount)
const validators = nominations.targets

StakingLedgers

const stakingLedgers = await api.query.liquidStaking.stakingLedgers()

APY

// Heiko APY
const startBlockHash = await api.rpc.chain.getBlockHash(907136)
const startTime = await api.query.timestamp.now.at(startBlockHash)
const now = await api.query.timestamp.now()
const elapsedInMillis = now.toBn().sub(startTime.toBn())
const millisPerYear = 365 * 24 * 60 * 60000
const apy = (exchangeRate ** (millisPerYear/elapsedInMillis) - 1) * 100%
//Parallel Apy
const startBlockHash = await api.rpc.chain.getBlockHash(739460)
const startTime = await api.query.timestamp.now.at(startBlockHash)
const now = await api.query.timestamp.now()
const elapsedInMillis = now.toBn().sub(startTime.toBn())
const millisPerYear = 365 * 24 * 60 * 60000
const apy = (exchangeRate ** (millisPerYear/elapsedInMillis) - 1) * 100%

ReserveFactor

const reserveFactor = await api.query.liquidStaking.reserveFactor()
const reserves = reserveFactor * amount

xcmFees

const xcmFees = api.consts.liquidStaking.xcmFees
Last modified 8mo ago