@lidofinance/lido-ethereum-sdk
TypeScript icon, indicating that this package has built-in type declarations

3.2.0 • Public • Published

Lido Ethereum SDK

GitHub license Downloads npm Version npm npm bundle size GitHub top language GitHub Pull Requests GitHub open issues

Lido Ethereum SDK is a package that provides convenient tools for interacting with Lido contracts on the Ethereum network through a software development kit (SDK). This SDK simplifies working with Lido contracts and accessing their functionality.

⚒️ Work In Progress ⚒️

The project is currently under active development and may experience breaking changes in the future.

Changelog

For changes between versions see CHANGELOG.MD

Migration

For breaking changes between versions see MIGRATION.md

Table of contents

Installation

You can install the Lido Ethereum SDK using npm or yarn:

yarn:

yarn add @lidofinance/lido-ethereum-sdk

npm:

npm install @lidofinance/lido-ethereum-sdk

Modules

The Lido Ethereum SDK consists of several modules:

  • Core - provides access to the SDK core functionality
  • Stake - provides access to the Lido staking functionality
  • Withdraw - provides access to the Lido withdrawals functionality
  • Wrap - provides access to the Lido wrap functionality
  • (w)stETH - provides access to the stETH and wstETH tokens functionality
  • unstETH NFT - provides access to the unstETH NFT functionality
  • Shares - provides access to the underlying share token
  • Statistics - provides access to the Lido stats, mainly APR
  • Rewards - provides access to historical data on stETH rewards

Usage

Import

To get started with the Lido Ethereum SDK, you need to import the necessary modules. You can use CJS or ES6+ imports. Import from root package or each module separately to improve on bundle size.

// CSJ
const { LidoSDK } = require('@lidofinance/lido-ethereum-sdk');
// or
const { LidoSDKStake } = require('@lidofinance/lido-ethereum-sdk/stake');
// or
// ES6+, all other modules are available from root
import { LidoSDK, LidoSDKStake } from '@lidofinance/lido-ethereum-sdk';

// Full list of separate imports
import { LidoSDKCore } from '@lidofinance/lido-ethereum-sdk/core';
import { LidoSDKStake } from '@lidofinance/lido-ethereum-sdk/stake';
import { LidoSDKWithdraw } from '@lidofinance/lido-ethereum-sdk/withdraw';
import { LidoSDKWrap } from '@lidofinance/lido-ethereum-sdk/wrap';
import {
  LidoSDKstETH,
  LidoSDKwstETH,
} from '@lidofinance/lido-ethereum-sdk/erc20';
import { LidoSDKUnstETH } from '@lidofinance/lido-ethereum-sdk/unsteth';
import { LidoSDKShares } from '@lidofinance/lido-ethereum-sdk/shares';
import { LidoSDKStatistics } from '@lidofinance/lido-ethereum-sdk/statistics';
import { LidoSDKRewards } from '@lidofinance/lido-ethereum-sdk/rewards';

Initialization

Before using the SDK, you need to create an instance of the LidoSDK class:

Pass your own viem PublicClient:

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';
import { createPublicClient, http } from 'viem';
import { goerli } from 'viem/chains';

const rpcProvider = createPublicClient({
  chain: goerli,
  transport: http(),
});
const sdk = new LidoSDK({
  chainId: 5,
  rpcProvider,
  web3Provider: provider, // optional
});

Or just rpc urls so it can be created under the hood:

const sdk = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3Provider: provider, // optional
});

Replace "https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}" with the address of your Ethereum provider.

With web3Provider

In order to access transaction signing functionality you need to provide viem WalletClient instance. Accessing web3 methods without web3Provider will result in error.

We support account hoisting as per Viem WalletClient, so passing account is not required for transactions and related functions. Some functions don't usually require web3provider to be present like simulate... or populate.. but not passing an account to them will result in request to web3provider and an error if it is missing.

import { LidoSDK, LidoSDKCore } from '@lidofinance/lido-ethereum-sdk';
import { createWalletClient, custom } from 'viem';
import { goerli } from 'viem/chains';

let web3Provider = createWalletClient({
  chain: goerli,
  transport: custom(window.ethereum),
});

// or use our helper to pass any eip-1193 provider
let web3Provider = LidoSDKCore.createWeb3Provider(5, window.ethereum);

const sdk = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3Provider,
});

Separate modules

Every SDK module needs LidoSDKCore to function. You can pass same arguments as to LidoSDKCore constructor to create it under the hood or pass existing instance. This allows you to build up your SDK only out of parts you need.

import { LidoSDKStake } from '@lidofinance/lido-ethereum-sdk/stake';
import { LidoSDKWrap } from '@lidofinance/lido-ethereum-sdk/stake';
import { LidoSDKCore } from '@lidofinance/lido-ethereum-sdk/core';

const params = {
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
};
// core is created under the hood
const stake = new LidoSDKStake(params);

const core = new LidoSDKCore(params);
const wrap = new LidoSDKWrap({ core });

Basic Examples

Core example

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
});

// Views
const balanceETH = await lidoSDK.core.balanceETH(address);

console.log(balanceETH.toString(), 'ETH balance');

Stake example

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

// Contracts
const addressStETH = await lidoSDK.stake.contractAddressStETH();
const contractStETH = await lidoSDK.stake.getContractStETH();

// Calls
const stakeTx = await lidoSDK.stake.stakeEth({
  value,
  callback,
  referralAddress,
});

console.log(addressStETH, 'stETH contract address');
console.log(contractStETH, 'stETH contract');
console.log(stakeTx, 'stake tx result');

Withdraw example

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

// Contracts
const addressWithdrawalQueue =
  await lidoSDK.withdraw.contract.contractAddressWithdrawalQueue();
const contractWithdrawalQueue =
  await lidoSDK.withdraw.contract.getContractWithdrawalQueue();

// Calls
const requestTx = await lidoSDK.withdraw.request.requestWithdrawalWithPermit({
  amount: 10000000n, // `10000000` string is accepted as well
  token: 'stETH',
  // account will be requested from provider
});

console.log(addressWithdrawalQueue, 'Withdrawal Queue contract address');
console.log(contractWithdrawalQueue, 'Withdrawal Queue contract');
console.log(requestTx.result.requests, 'array of created requests');

Wrap example

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

// Contracts
const addressWstETH = await lidoSDK.wrap.contractAddressWstETH();
const contractWstETH = await lidoSDK.withdraw.getContractWstETH();

// Calls
const wrapTx = await lidoSDK.wrap.wrapEth({
  value,
  account,
});

const { stethWrapped, wstethReceived } = wrapTx.result;

console.log(addressWstETH, 'wstETH contract address');
console.log(contractWstETH, 'wstETH contract');
console.log({ stethWrapped, wstethReceived }, 'wrap result');

Error Codes

  • INVALID_ARGUMENT: arguments passed to SDK method are not valid
  • NOT_SUPPORTED: behavior or feature though possible is not currently supported by SDK
  • PROVIDER_ERROR: error with RPC or Web3 Provider
  • READ_ERROR: error while accessing Blockchain or External Resource for read
  • UNKNOWN_ERROR error was not recognized by SDK and is not directly thrown by it's code

Lido contract addresses

import { LidoSDK, LIDO_CONTRACT_NAMES } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
});

const stethAddress = await lidoSDK.core.getContractAddress(
  LIDO_CONTRACT_NAMES.lido,
);
const wsteth = await lidoSDK.core.getContractAddress(
  LIDO_CONTRACT_NAMES.wsteth,
);

Stake

Call

Arguments:

  • value: string | bigint - amount of ETH to stake (in wei)
  • callback: StageCallback - callback function that will be on each stage of the transaction
  • referralAddress: string - referral address (optional)

Callback stages:

  • sign - waiting for the user to sign the transaction
  • receipt = waiting for the transaction to be included in the block
  • confirmation - transaction is confirmed by the network
  • done - transaction is successful
  • multisig_done - transaction with multisig is successful
  • error - transaction is failed
import {
  LidoSDK,
  LidoSDKCore,
  StakeStageCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: StakeStageCallback = ({ stage, payload }) => {
  switch (stage) {
    case TransactionCallbackStage.SIGN:
      console.log('wait for sign');
      break;
    case TransactionCallbackStage.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case TransactionCallbackStage.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case TransactionCallbackStage.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const stakeTx = await lidoSDK.stake.stakeEth({
    value,
    callback,
    referralAddress,
    account,
  });

  console.log(
    stakeTx,
    'transaction hash, transaction receipt, confirmations, stake result',
    stakeTx.result.stethReceived,
    stakeTx.result.sharesReceived,
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Populate transaction

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
});

const populateResult = await lidoSDK.stake.stakeEthPopulateTx({
  value,
  callback,
  referralAddress,
  account,
});

console.log(populateResult, 'to, from, value, data');

Simulate transaction

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
});

const simulateResult = await lidoSDK.staking.stakeEthSimulateTx({
  value,
  callback,
  referralAddress,
  account,
});

Wrap

Calls

Wrap ETH

Arguments:

  • value: string | bigint - amount of ETH to wrap to wstETH (staking ETH and then wrapping stETH to wstETH in a single tx)
  • callback: StageCallback - callback function that will be on each stage of the transaction
import {
  LidoSDK,
  TransactionCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: TransactionCallback = ({ stage, payload }) => {
  switch (stage) {
    case TransactionCallbackStage.SIGN:
      console.log('wait for sign');
      break;
    case TransactionCallbackStage.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case TransactionCallbackStage.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case TransactionCallbackStage.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const wrapTx = await lidoSDK.staking.wrapETH({
    value,
    callback,
    account,
  });

  console.log(
    wrapTx,
    'transaction hash, transaction receipt, confirmations, wrap result',
    wrapTx.result.stethWrapped,
    wrapTx.result.wstethReceived,
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Wrap stETH

To wrap stETH you first need to approve stETH to wrap contract:

import {
  LidoSDK,
  TransactionCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

// get existing allowance
const allowance = await lidoSDK.wrap.getStethForWrapAllowance(account);

// if value is more than allowance perform approve
const approveResult = await lidoSDK.wrap.approveStethForWrap({
  value,
  callback,
});

// wrap stETH
const wrapResult = await lidoSDK.wrap.wrapSteth({ value, callback });

Unwrap

// unwrap wstETH to receive stETH
const unwrapTx = await lidoSDK.wrap.unwrap({
  value: unwrapAmount,
  callback,
});

console.log(unwrapTx.result.stethReceived, unwrapTx.result.wstethUnwrapped);

Wrap utilities

For all transaction methods helper methods are available similar to stake module:

  • ...populateTX: returns ready to sign transaction object with all data encoded
  • ...simulateTX: performs dry-ran of the transaction to see if it will execute on the network

For wrapEth only wrapEthEstimateGas is available instead of simulateTx but you can use it all the same for checking transaction validity.

Withdraw

Call

Send request withdrawal with Permit

Signing Permit is only supported for EOA

Arguments:

  • requests: (Type: bigint[] ) - array of requests ids or

  • amount: (Type: String | BigInt ) - amount of token to withdraw, will be split into minimum amount of requests

  • token: (Type: 'stETH' | 'wstETH') - token name

  • permit: (Type: SignedPermit optional) - presigned permit, will be requested if not present

  • callback: (Type: TransactionCallback optional) - callback function that will be on each stage of the transaction

  • account (Type: Address | Account optional): The account address.

import {
  LidoSDK,
  TransactionCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: TransactionCallback = ({ stage, payload }) => {
  switch (stage) {
    case TransactionCallbackStage.PERMIT:
      console.log('wait for permit');
      break;
    case TransactionCallbackStage.GAS_LIMIT:
      console.log('wait for gas limit');
      break;
    case TransactionCallbackStage.SIGN:
      console.log('wait for sign');
      break;
    case TransactionCallbackStage.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case TransactionCallbackStage.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case TransactionCallbackStage.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.MULTISIG_DONE:
      console.log('multisig_done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const requestTx = await lidoSDK.withdrawals.request.requestWithPermit({
    requests,
    token, // 'stETH' | 'wstETH'
    callback,
    account,
  });

  console.log(
     'transaction hash, transaction receipt, confirmations',
    requestResult,
    'array of requests(nfts) created with ids, amounts,creator, owner',
    request.results.requests,
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Send request withdrawal with preallocated allowance

Supports EOA and Multisig

Arguments:

  • requests: (Type: bigint[] ) - array of requests ids or

  • amount: (Type: String | BigInt ) - amount of token to withdraw, will be split into minimum amount of requests

  • token: (Type: string) - token name ('stETH' | 'wstETH')

  • callback: (Type: TransactionCallback optional) - callback function that will be on each stage of the transaction

  • account (Type: Address | Account optional): The account address.

import {
  LidoSDK,
  TransactionCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: TransactionCallback = ({ stage, payload }) => {
  switch (stage) {
    case TransactionCallbackStage.GAS_LIMIT:
      console.log('wait for gas limit');
      break;
    case TransactionCallbackStage.SIGN:
      console.log('wait for sign');
      break;
    case TransactionCallbackStage.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case TransactionCallbackStage.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case TransactionCallbackStage.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const requestResult = await lidoSDK.withdrawals.request.requestWithdrawal({
    amount,
    token, // 'stETH' | 'wstETH'
    callback,
  });

  console.log(
    requestResult,
    'transaction hash, transaction receipt, confirmations',
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Request helpers

  • populate and simulate helpers are available
  • splitAmountToRequests({amount, token}) splits token amount into minimal possible array of withdrawal requests

Claim requests

Arguments:

  • requestsIds: (Type: bigint[]): An array of request ids.
  • hints (Type: bigint[] optional): An array of hints per each request, will be calculated if not provided.
  • account: (Type: Address optional): The account address.
  • callback: (Type: TransactionCallback optional): callback function that will be on each stage of the transaction
import {
  LidoSDK,
  TransactionCallback,
  TransactionCallbackStage,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: TransactionCallback = ({ stage, payload }) => {
  switch (stage) {
    case TransactionCallbackStage.GAS_LIMIT:
      console.log('wait for gas limit');
      break;
    case TransactionCallbackStage.SIGN:
      console.log('wait for sign');
      break;
    case TransactionCallbackStage.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case TransactionCallbackStage.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case TransactionCallbackStage.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case TransactionCallbackStage.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const claimTx = await lidoSDK.withdrawals.claim.claimRequests({
    requestsIds,
    callback,
  });

  console.log(
    claimTx,
    'transaction hash, transaction receipt, confirmations',
    claim.result.requests,
    'array of claimed requests, with amounts of ETH claimed',
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Claim helpers

populate and simulate helpers are available

Withdraw utilities

Set allowance of WithdrawalQueue contract

Supports EOA and Multisig

import {
  LidoSDK,
  ApproveCallbackStages,
  ApproveStageCallback,
  SDKError,
} from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const callback: ApproveStageCallback = ({ stage, payload }) => {
  switch (stage) {
    case ApproveCallbackStages.GAS_LIMIT:
      console.log('wait for gas limit');
      break;
    case ApproveCallbackStages.SIGN:
      console.log('wait for sign');
      break;
    case ApproveCallbackStages.RECEIPT:
      console.log('wait for receipt');
      console.log(payload, 'transaction hash');
      break;
    case ApproveCallbackStages.CONFIRMATION:
      console.log('wait for confirmation');
      console.log(payload, 'transaction receipt');
      break;
    case ApproveCallbackStages.DONE:
      console.log('done');
      console.log(payload, 'transaction confirmations');
      break;
    case ApproveCallbackStages.ERROR:
      console.log('error');
      console.log(payload, 'error object with code and message');
      break;
    default:
  }
};

try {
  const approveResult = await lidoSDK.withdrawals.approval.approve({
    amount,
    token, // 'stETH' | 'wstETH'
    callback,
    account,
  });

  console.log(
    approveResult,
    'transaction hash, transaction receipt, confirmations',
  );
} catch (error) {
  console.log((error as SDKError).errorMessage, (error as SDKError).code);
}

Allowance other methods

Views
  • populate and simulate helpers are available
  • getAllowance returns current allowance for token
  • checkAllowance return current allowance and compares with amount to check if you need to approve

Views

  • getWithdrawalRequestsIds
  • getLastCheckpointIndex
  • getWithdrawalStatus
  • findCheckpointHints
  • getClaimableEther
  • getUnfinalizedStETH

Constants

  • minStethWithdrawalAmount
  • maxStethWithdrawalAmount
  • minWStethWithdrawalAmount
  • maxWStethWithdrawalAmount
  • isPaused
  • isBunkerModeActive
  • isTurboModeActive

Requests info

getWithdrawalRequestsInfo
Input Parameters:
  • props: { account: Address | Account }
    • account (Type: Address | Account): The account address.
Output Parameters:
  • Type: Object

  • Structure:

    • claimableInfo (Type: Object): Information about withdrawal requests that can be claimed.
      • claimableRequests (Type: Array[RequestStatusWithId]): A list of requests with their statuses and identifiers.
      • claimableAmountStETH (Type: bigint): The amount of ETH available for claiming.
    • pendingInfo (Type: Object): Information about pending withdrawal requests.
      • pendingRequests (Type: Array[RequestStatusWithId]): A list of requests with their statuses and identifiers.
      • pendingAmountStETH (Type: bigint): The amount of ETH pending for withdrawal.
    • claimableETH (Type: bigint): The amount of ETH available for claiming.
getWithdrawalRequestsStatus
Input Parameters:
  • props: { account: Address }
    • account (Type: Address | Account): The account address.
Output Parameters:
  • Type: Array of RequestStatusWithId objects

  • Structure of each object:

    • id (Type: bigint): The request identifier.
    • isFinalized (Type: boolean): A flag indicating whether the request has been finalized.
    • isClaimed (Type: boolean): A flag indicating whether the request has already been claimed.
    • amountOfStETH (Type: bigint): The amount of stETH to be withdrawn.
    • amountOfShares (Type: bigint): The amount of shares to be burned.
    • owner (Type: Address): The account address that initiated the request.
    • timestamp (Type: bigint): The timestamp of the request.
    • stringId (Type: string): The request identifier in string format.
getClaimableRequestsInfo
Input Parameters:
  • props: { account: Address }
    • account (Type: Address | Account): The account address.
Output Parameters:
  • Type: Object

  • Structure:

    • claimableRequests (Type: Array[RequestStatusWithId]): A list of requests that can be claimed.
    • claimableAmountStETH (Type: bigint): The amount of ETH available for claiming.
getClaimableRequestsETHByIds
Input Parameters:
  • props: { claimableRequestsIds: (bigint | RequestStatusWithId)[] }
    • claimableRequestsIds (Type: Array): An array of request identifiers for which information is needed.
Output Parameters:
  • Type: Object

  • Structure:

    • ethByRequests (Type: Array of bigint): A list of ETH amounts for each request.
    • ethSum (Type: bigint): The sum of all ETH amounts in the list.
    • hints (Type: Array of bigint): A list of hints for each request.
getClaimableRequestsETHByAccount
Input Parameters:
  • props: { account: Address }
    • account (Type: Address | Account): The account address.
Output Parameters:
  • Type: Object

  • Structure:

    • ethByRequests (Type: Array of bigint): A list of ETH amounts for each request.
    • ethSum (Type: bigint): The sum of all ETH amounts in the list.
    • hints (Type: Array of bigint): A list of hints for each request.
    • requests (Type: Array of RequestStatusWithId): A list of requests with their statuses and identifiers.
    • sortedIds (Type: Array of bigint): A list of request identifiers sorted by id.
getPendingRequestsInfo
Input Parameters:
  • props: { account: Address | Account }
    • account (Type: Address | Account): The account address.
Output Parameters:
  • Type: Object

  • Structure:

    • pendingRequests (Type: Array[RequestStatusWithId]): A list of requests pending finalization.
    • pendingAmountStETH (Type: bigint): The amount of ETH pending claiming.

Waiting time

Methods

Get time by amount
getWithdrawalWaitingTimeByAmount
Input Parameters:
  • props: { amount?: bigint }
    • amount? (Type: bigint optional): The amount of withdrawable eth. In case when it is not passed, it is calculated as default information about queue.
Output Parameters:
  • Type: Object
  • Structure:
    • requestInfo (Type: Object): Information about withdrawal request
      • finalizationIn (Type: number): The time needed for withdrawal in milliseconds.
      • finalizationAt (Type: string): The time when request finalized for withdrawal.
      • type (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal.
    • status (Type: WaitingTimeStatus): Status of withdrawal request.
    • nextCalculationAt (Type: string): Time when next calculation can be changed.
Get time by request ids
getWithdrawalWaitingTimeByRequestIds
Input Parameters:
  • props: { ids: bigint[] }
    • ids (ids: Array[bigint]): The ids of withdrawal requests.
Output Parameters:
  • Type: Array of WithdrawalWaitingTimeRequestInfo objects
  • Structure of each object:
    • requestInfo (Type: RequestByIdInfoDto): Information about withdrawal request.
      • finalizationIn (Type: number): The time needed for withdrawal in milliseconds.
      • finalizationAt (Type: string): The time when request finalized for withdrawal.
      • requestId (Type: string): The request id.
      • requestedAt (Type: string): The time when withdrawal requested.
      • type (Type: WaitingTimeCalculationType): Type of final source of eth for withdrawal.
    • status (Type: WaitingTimeStatus): Status of withdrawal request.
    • nextCalculationAt (Type: string): Time when next calculation can be changed.

(w)stETH

stETH and wstETH tokens functionality is presented trough modules with same ERC20 interface that exposes balances, allowances, transfers and ERC2612 permits signing.

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

// Views
const balanceStETH = await lidoSDK.steth.balance(address);
const balanceWStETH = await lidoSDK.wsteth.balance(address);

// Contracts
const contractStETH = await lidoSDK.steth.getContract();
const addressStETH = await lidoSDK.steth.contractAddress();

const contractWStETH = await lidoSDK.wsteth.getContract();
const addressWStETH = await lidoSDK.wsteth.contractAddress();

// Calls
const transfer = await lidoSDK.steth.transfer({
  amount,
  to,
});

Transfer

const transferTx = await lidoSDK.steth.transfer({
  amount,
  to,
  from, // pass from to call transferFrom method
  account,
  callback,
});

Allowance

const approveTx = await lidoSDK.steth.approve({
  amount,
  to,
  account,
  callback,
});

const allowance = await lidoSDK.steth.allowance({ to, account });
// bigint representing how much stETH is `to` address allowed to spend from `account` address
console.log(allowance);

Permit

// initiate permit signing for stETH
const permit = await lidoSDK.steth.signPermit({
  amount,
  spender,
  account,
  deadline, // optional, leave empty for infinite deadline
});

Token Metadata

Other helpful functions are exposed

  • erc20Metadata returns token name, symbol, decimals and ERC2612 Domain separator.
  • nonces returns current permit nonce for account
  • totalSupply returns total supply of the token, for (w)stETH tokens this is a variable that changes over time
  • erc721Domain return unhashed ERC2612 domain, used for signing permits

Utility methods

For all transaction methods helper methods are available similar to stake module:

  • ...populate: returns ready to sign transaction object with all data encoded
  • ...simulate: performs dry-ran of the transaction to see if it will execute on the network

For permit signing ...populate helpers requests and fills out all needed data for signTypedData RPC call

Custom token (experimental)

Both token classes inherit from the same abstract class AbstractLidoSDKErc20 which is exposed from erc20 SDK module. If you want to use this with other token extend from this abstract class and implementingcontractAddress method that returns address of the token contract on current chain from this.core. Consult with source code of this sdk module to get started. Use at your own risk, be aware that this is experimental feature and ABI used may not fit your custom token fully or correctly.

unstETH NFT

This modules exposes NFT functionality of Lido Withdrawal Request NFT.

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
});

// Contracts
const addressUnstETH = await lidoSDK.unsteth.contractAddress();
const contractUnstETH = await lidoSDK.unsteth.getContract();

// views
const nfts = await lidoSDK.unsteth.getNFTsByAccount(account);
const owner = await lidoSDK.unsteth.getAccountByNFT(tokenId);

// Calls
const transfer = await lidoSDK.unsteth.transfer({
  id,
  to,
  from, // optional to call transferFrom
  account,
  callback,
});

Shares

This module exposes methods of Lido(stETH) contract that allow interaction with underlying shares mechanism with interface similar to ERC20. You can query balance, transfer and convert values between shares and stETH. It's best used for tracking balances and performing operations in values unchanged by rebases.

Example

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
  web3Provider: LidoSDKCore.createWeb3Provider(5, window.ethereum),
});

const balanceShares = await lidoSDK.shares.balance(address);

// transferring shares is equivalent to transferring corresponding amount of stETH
const transferTx = await lidoSDK.shares.transfer({ account, amount, to });

// converting stETH amount to shares trough on-chain call based on actual share rate
const shares = await lidoSDK.convertToShares(1000n);
// reverse
const steth = await lidoSDK.convertToSteth(1000n);

// total supply of shares and ether in protocol
const { totalEther, totalShares } = await lidoSDK.getTotalSupply();

// get current share rate from protocol
const shareRate = await lidoSDK.getShareRate();

Lido statistics

APR

Methods

getLastApr
Output Parameters:
  • Type: number
getSmaApr
Input Parameters:
  • props: { days }
    • days (Type: number): The number of days back to return sma apr.
Output Parameters:
  • Type: number

Examples

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
});

const lastApr = await lidoSDK.statistics.apr.getLastApr();
const smaApr = await lidoSDK.statistics.apr.getSmaApr({ days: 7 });

console.log(lastApr, 'last apr');
console.log(smaApr, 'sma apr by 7 days');

Lido events

Rebase

Methods

getLastRebaseEvent
Output Parameters:
  • Type: RebaseEvent
getFirstRebaseEvent
Input Parameters:
  • props: { days, fromBlockNumber }
    • days (Type: number): The number of days ago from which to start searching for the first rebase event.
    • fromBlockNumber (Type: number | undefined): Block number from which to start the search.
Output Parameters:
  • Type: RebaseEvent
getRebaseEvents
Input Parameters:

Warning: specifying timestamp/seconds/days will result in binary search for fitting block number which will negatively affect rpc request count and execution time

Sub types:

  • blockType object that contains one of possible fields:

    • block block number(Type: BigInt) or Block Tag(excluding pending)
    • timestamp timestamp in seconds(type:BigInt) since epoch time
  • backType object that contains one of possible fields:

    • seconds (Type: BigInt): seconds back
    • days (Type: BigInt): days back
    • blocks (Type: BigInt): block back

Props:

  • to (Type: blockType optional) defaults to {block:"latests"} upper bound for events parsing

  • maxCount (Type: number optional) maximum count of events to return, if omitted will return all events in range

  • stepBlock: (Type: number optional) defaults to 50000, maximum block range per 1 request

  • from (Type: blockType) lower bound for events parsing or

  • back (Type: backType) alternative way to define lower bound relative to to

Output Parameters:
  • Type: Array of RebaseEvent objects
getLastRebaseEvents
Input Parameters:
  • props: { count, stepBlock? }
    • count (Type: number): how many last rebase events to return
    • stepBlock: (Type: number optional) defaults to 50000, maximum block range per 1 request
Output Parameters:
  • Type: Array of RebaseEvent objects

Examples

import { LidoSDK } from '@lidofinance/lido-ethereum-sdk';

const lidoSDK = new LidoSDK({
  rpcUrls: ['https://rpc-url'],
  chainId: 5,
});

const lastRebaseEvent = await lidoSDK.events.stethEvents.getLastRebaseEvent();
const firstRebaseEvent = await lidoSDK.events.stethEvents.getFirstRebaseEvent({
  days: 3,
});
const lastRebaseEventsByCount =
  await lidoSDK.events.stethEvents.getLastRebaseEvents({ count: 7 });
const lastRebaseEventsByDays =
  await lidoSDK.events.stethEvents.getRebaseEventsByDays({ days: 7 });

console.log(lastRebaseEvent, 'last rebase event');
console.log(firstRebaseEvent, 'first rebase event');
console.log(lastRebaseEventsByCount, 'last rebase events by count');
console.log(lastRebaseEventsByDays, 'last rebase events by days');

Rewards

This module allows you to query historical rewards data for given address via chain events or subgraph.

Common Options

  • address - (Type: Address) address of an account you want to query rewards for

  • to (Type: blockType) defaults to {block: "latest"}, upper bound for query

  • from (Type: blockType) lower bound for query or

  • back (Type: backType) alternative way to define lower bound relative to to

  • includeZeroRebases [default: false ] - include rebase events when users had no rewards(because of empty balance)

  • includeOnlyRewards [default: false ] - include only rebase events

Common Return

type RewardsResult = {
  // pre query states
  baseBalance: bigint;
  baseBalanceShares: bigint;
  baseShareRate: number;
  // commutative rewards in stETH
  totalRewards: bigint;
  // computed block numbers
  fromBlock: bigint;
  toBlock: bigint;
  // query result in block/logIndex ascending order
  rewards: {
    type: 'submit' | 'withdrawal' | 'rebase' | 'transfer_in' | 'transfer_out';
    change: bigint; // negative or positive change in stETH
    changeShares: bigint; // same in shares
    balance: bigint; // post event balance in stETH
    balanceShares: bigint; // same in shares
    shareRate: number; // apx share rate at a time of event
    apr?: number; // apr for rebase events
    originalEvent: RewardsChainEvents | RewardsSubgraphEvents ; // original event from chain/subgraph, contains extra info
  }[]
};

Get Rewards from chain

This method heavily utilizes RPC fetching chain event logs. It's better suited for smaller,recent queries. Beware that this might cause rate limit issues on free RPC endpoints.

const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
});

const rewardsQuery = await lidoSDK.rewards.getRewardsFromChain({
  address: rewardsAddress,
  stepBlock: 10000, // defaults to 50000, max block range per 1 query
  back: {
    days: 10n,
  },
});

console.log(rewardsQuery.rewards);

Get Rewards from subgraph

This method requires you to provide API URL to send subgraph requests to. It's better suited for larger, more historical queries.

Important notes

  • to is capped by last indexed block in subgraph. Block number is available in result object by lastIndexedBlock.
  • getSubgraphUrl can also return object of type {url:string,requestHeaders?: Record<string,string> } that is passed to graphql-request for extra configurability
const lidoSDK = new LidoSDK({
  chainId: 5,
  rpcUrls: ['https://eth-goerli.alchemyapi.io/v2/{ALCHEMY_API_KEY}'],
});

const rewardsQuery = await lidoSDK.rewards.getRewardsFromSubgraph({
  address: rewardsAddress,
  blocksBack: 10000,
  stepEntities: 500, // defaults to 1000,  max entities per one request to endpoint
  getSubgraphUrl(graphId, chainId) {
    return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/${id}`;
  },
});

console.log(rewardsQuery.rewards);

Package Sidebar

Install

npm i @lidofinance/lido-ethereum-sdk

Weekly Downloads

304

Version

3.2.0

License

MIT

Unpacked Size

2.02 MB

Total Files

527

Last publish

Collaborators

  • lidofinance-ui
  • lidofinance-group