# Getting Started

### Chorus One SDK

The **Chorus One SDK** is an all-in-one toolkit for building staking dApps. It supports non-custodial staking on networks validated by Chorus One, including **Ethereum**, **Solana**, **TON**, **Avalanche**, **Cosmos**, **NEAR**, **Polkadot**, **Polygon**, **Hyperliquid**, and **Monad**. With this SDK, you can build, sign, and broadcast transactions as well as retrieve staking information and rewards for user accounts.

### Why Choose the Chorus One SDK?

At Chorus One, we prioritize security, transparency, and user control in our staking solutions. Our choice to use a Software Development Kit (SDK) for staking integration reflects this commitment, offering several key advantages over traditional Application Programming Interfaces (APIs).

#### Enhanced Security and Decentralization

One of the core principles of crypto is *"Don't trust, verify."* This ethos is crucial in staking operations, where trustless environments and robust security are paramount.

**Local Transaction Signing**: The Chorus One SDK allows users to generate and sign transactions locally on their own devices. This means critical operations - staking, unstaking, delegation, and reward withdrawals - are securely performed without exposing private keys to external environments.

**Reduced Risk of Exposure**: By keeping private keys within the user’s environment, the risk of exposure to malicious actors is significantly minimized.

#### Verifiable Trust and Transparency

Using an API for staking can sometimes introduce concerns about transparency and control. With an SDK, these concerns are addressed head-on:

**Direct Verification**: Users can directly specify and verify the validator addresses they interact with, ensuring transparency and control over staking activities. This aligns with the decentralization ethos of blockchain technology, empowering users to manage their staking operations confidently.

**Elimination of External Dependencies**: The SDK approach removes potential attack vectors associated with relying on external APIs for critical operations. Users retain full control and can independently confirm all actions taken, enhancing overall trust and security.

#### Open-Source and Auditable

**Open-Source Code**: The Chorus One SDK is open-source, allowing users and developers to review, audit, and contribute to the codebase. This openness ensures that the SDK is transparent and trustworthy. You can access and review the code on our [GitHub repository](https://github.com/ChorusOne/chorus-one-sdk).

{% hint style="info" %}

#### Why does it matter?

#### Choosing the Chorus One SDK means prioritizing security, transparency, and user empowerment. With local transaction building and signing, and open-source transparency, users can confidently participate in staking activities across supported networks.

{% endhint %}

### Key Features

* **Comprehensive Transaction Management**:

  The Chorus One SDK offers a robust suite of tools for managing staking operations on a variety of networks.

  Users can seamlessly build, sign, and broadcast transactions for staking, unstaking, delegation, and reward withdrawal.
* **Detailed Information Retrieval**:

  Our SDK provides users with the ability to fetch detailed staking information and reward data for any account. This transparency ensures that the user has access to all the information they need to make informed decisions about their staking activities.
* **Flexible Custody Solutions**:

  Our SDK supports a variety of custody options, including mobile wallets, browser extensions, hardware wallets, and custom custodial solutions like Fireblocks.

  This flexibility ensures that the user can choose the solution that best fits their security and operational requirements.
* **Fireblocks Integration**:

  For users who prefer a convenient custodial solution, the Chorus One SDK provides easy-to-use tools for securely signing transactions with Fireblocks across supported blockchain networks. This integration ensures a smooth and secure staking experience.
* **Integrated Validator Support**:

  The SDK includes built-in support for Chorus One validators across all supported blockchain networks. Additionally, it allows users to specify their own validator addresses, providing a customizable staking experience.
* **CLI**:

  The SDK includes a Command Line Interface (CLI) for easy interaction with the SDK and supported networks. This feature simplifies operations, making it accessible for users who prefer command line tools for managing their staking activities.

{% hint style="info" %}

#### Our SDK offers users the freedom to stake with any validator they choose. This flexibility ensures a personalized staking experience and enhances user control over their staking activities.

{% endhint %}

### Modules Overview

#### Supported Networks

* [**Ethereum**](/build-your-staking-dapp/ethereum/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/ethereum))
* [**Solana**](/build-your-staking-dapp/solana/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/solana))
* [**TON**](/build-your-staking-dapp/ton/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/ton))
* [**Avalanche**](/build-your-staking-dapp/avalanche/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/avalanche))
* [**Cosmos**](/build-your-staking-dapp/cosmos/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/cosmos))
* [**NEAR**](/build-your-staking-dapp/near/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/near))
* [**Polkadot (Substrate)**](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/substrate/overview.md) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/substrate))
* [**Polygon**](/build-your-staking-dapp/polygon/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/polygon))
* [**Hyperliquid**](/build-your-staking-dapp/hyperliquid/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/hyperliquid))
* [**Monad**](/build-your-staking-dapp/monad/overview) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/monad))

#### Supported Signers (Custody Solutions)

* [**Fireblocks**](/signers-explained/fireblocks) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/signer-fireblocks))
* [**Mnemonic**](/signers-explained/local) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/signer-local))
* [**Ledger Device(Cosmos)**](/signers-explained/signing-with-a-ledger-device) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/signer-ledger-cosmos))
* [**Keplr**](/signers-explained/signing-with-a-browser-extension-wallet) ([📦 npm package](https://www.npmjs.com/package/@chorus-one/signer-keplr))
* [How to Implement a Custom Signer?](/signers-explained/custom-signer)

#### Command Line Interface (CLI)

* **Staking CLI** ([📦 npm package](https://www.npmjs.com/package/@chorus-one/staking-cli))

### Rewards Dashboard API Keys

For programmatic access to staking **rewards data** over REST, generate API keys in the **Chorus One Rewards Dashboard** and see the [Rewards API documentation](https://chorus-one.gitbook.io/rewards-api) for endpoints and authentication.

### Installation

The Chorus One SDK is available as a set of npm packages and supports both Node.js and browser environments.

* Please ensure you have **Node.js (v20)** installed on your machine.

To install the SDK, run some of the following commands depending on your setup:

{% tabs %}
{% tab title="npm" %}

```bash
# Networks

npm install @chorus-one/ethereum --save
npm install @chorus-one/solana --save
npm install @chorus-one/ton --save
npm install @chorus-one/avalanche --save
npm install @chorus-one/cosmos --save
npm install @chorus-one/near --save
npm install @chorus-one/substrate --save # Polkadot and other Substrate chains
npm install @chorus-one/polygon --save
npm install @chorus-one/hyperliquid --save
npm install @chorus-one/monad --save

# Signers

npm install @chorus-one/signer-fireblocks --save
npm install @chorus-one/signer-local --save
npm install @chorus-one/signer-keplr --save
npm install @chorus-one/signer-ledger-cosmos --save

# CLI

npm install @chorus-one/staking-cli --save --global
```

{% endtab %}

{% tab title="yarn" %}

```bash
# Networks

yarn add @chorus-one/ethereum
yarn add @chorus-one/solana
yarn add @chorus-one/ton
yarn add @chorus-one/avalanche
yarn add @chorus-one/cosmos
yarn add @chorus-one/near
yarn add @chorus-one/substrate # Polkadot and other Substrate chains
yarn add @chorus-one/polygon
yarn add @chorus-one/hyperliquid
yarn add @chorus-one/monad

# Signers

yarn add @chorus-one/signer-fireblocks
yarn add @chorus-one/signer-local
yarn add @chorus-one/signer-keplr
yarn add @chorus-one/signer-ledger-cosmos

# CLI

yarn add @chorus-one/staking-cli --global
```

{% endtab %}

{% tab title="pnpm" %}

```bash
# Networks

pnpm add @chorus-one/ethereum
pnpm add @chorus-one/solana
pnpm add @chorus-one/ton
pnpm add @chorus-one/avalanche
pnpm add @chorus-one/cosmos
pnpm add @chorus-one/near
pnpm add @chorus-one/substrate # Polkadot and other Substrate chains
pnpm add @chorus-one/polygon
pnpm add @chorus-one/hyperliquid
pnpm add @chorus-one/monad

# Signers

pnpm add @chorus-one/signer-fireblocks
pnpm add @chorus-one/signer-local
pnpm add @chorus-one/signer-keplr
pnpm add @chorus-one/signer-ledger-cosmos

# CLI

pnpm add @chorus-one/staking-cli --global
```

{% endtab %}

{% tab title="bun" %}

```bash
# Networks

bun add @chorus-one/ethereum
bun add @chorus-one/solana
bun add @chorus-one/ton
bun add @chorus-one/avalanche
bun add @chorus-one/cosmos
bun add @chorus-one/near
bun add @chorus-one/substrate # Polkadot and other Substrate chains
bun add @chorus-one/polygon
bun add @chorus-one/hyperliquid
bun add @chorus-one/monad

# Signers

bun add @chorus-one/signer-fireblocks
bun add @chorus-one/signer-local
bun add @chorus-one/signer-keplr
bun add @chorus-one/signer-ledger-cosmos

# CLI

bun add @chorus-one/staking-cli --global
```

{% endtab %}
{% endtabs %}

### Example Usage

Here is a basic example of how to use the Chorus One SDK to build, sign, and broadcast a staking transaction using Fireblocks as the signer.

{% tabs %}
{% tab title="Ethereum" %}

```javascript
// Configuration
// -------------

import { EthereumStaker, CHORUS_ONE_ETHEREUM_VALIDATORS } from '@chorus-one/ethereum'

const staker = new EthereumStaker({
  network: 'ethereum'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_ETHEREUM_VALIDATORS.ethereum.maxVault

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorAddress,
  amount: '1', // 1 ETH
  // Optional - Unique Ethereum address for tracking
  referrer: '0xReferrerAddressHere'
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const { txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

{% endtab %}

{% tab title="Solana" %}

```javascript
// Configuration
// -------------

import { SolanaStaker, CHORUS_ONE_SOLANA_VALIDATOR } from '@chorus-one/solana'

const staker = new SolanaStaker({
  rpcUrl: 'https://api.mainnet-beta.solana.com'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_SOLANA_VALIDATOR

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorAddress,
  amount: '1' // 1 SOL
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const { txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

{% endtab %}

{% tab title="TON" %}

```javascript
// Configuration
// -------------

import { TonPoolStaker } from '@chorus-one/ton'

const staker = new TonPoolStaker({
  rpcUrl: 'https://toncenter.com/api/v2/jsonRPC'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr'

// You can use the Chorus One validator address or specify your own
const validatorAddressPair = [
  'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F',
  'kQCltujow9Sq3ZVPPU6CYGfqwDxYwjlmFGZ1Wt0bAYebio4o'
]

const { tx } = await staker.buildStakeTx({
  validatorAddressPair,
  amount: '1' // 1 TON
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const txHash = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({
  address: delegatorAddress,
  txHash
})

console.log(status) // 'success'
```

{% endtab %}

{% tab title="Avalanche" %}

```javascript
// Configuration
// -------------

import { AvalancheStaker, CHORUS_ONE_AVALANCHE_VALIDATORS } from '@chorus-one/avalanche'

const staker = new AvalancheStaker({
  rpcUrl: 'https://api.avax.network',
  hrp: 'avax'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = 'P-avax10uzff2f0u8hstlr5ywt2x4lactmn28c5y9uddv'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_AVALANCHE_VALIDATORS[0]
// 'NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg'

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorAddress,
  amount: '1' // 1 AVAX,
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const { txId } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txId, chain: 'P' })

console.log(status) // 'success'
```

{% endtab %}

{% tab title="Cosmos" %}

```javascript
// Configuration
// -------------

import { CosmosStaker, CHORUS_ONE_COSMOS_VALIDATORS, CosmosConfigurator } from '@chorus-one/cosmos'

const networkConfig = await CosmosConfigurator.genNetworkConfig('cosmoshub')

const staker = new CosmosStaker(networkConfig)

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_COSMOS_VALIDATORS.COSMOS
// 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707'

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorAddress,
  amount: '1' // 1 ATOM
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx,
  memo: 'Staking 1 ATOM'
})

// Broadcasting the transaction
// ----------------------------

const { transactionHash: txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

{% endtab %}

{% tab title="NEAR" %}

```javascript
// Configuration
// -------------

import { NearStaker, CHORUS_ONE_NEAR_VALIDATOR } from '@chorus-one/near'

const staker = new NearStaker({
  networkId: 'mainnet',
  rpcUrl: 'https://rpc.mainnet.near.org'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = 'your.near'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_NEAR_VALIDATOR
// 'chorusone.poolv1.near'

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorAddress,
  amount: '1' // 1 NEAR
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const {
  transaction: { hash: txHash }
} = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({
  address: delegatorAddress,
  txHash
})

console.log(status) // 'success'
```

{% endtab %}

{% tab title="Polkadot" %}

```javascript
// Configuration
// -------------

import { SubstrateStaker, RewardDestination, CHORUS_ONE_SUBSTRATE_VALIDATORS } from '@chorus-one/substrate'

const staker = new SubstrateStaker({
  rpcUrl: 'wss://rpc.polkadot.io',
  denomMultiplier: 1000000000000,
  rewardDestination: RewardDestination.STASH
})

await staker.init()

// Building the transactions
// -------------------------

const delegatorAddress = '5CavrskYZHeLxTwERikgZDCZPmhpsM7oXZQmL6rkNryDD8FwN'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_SUBSTRATE_VALIDATORS.POLKADOT[0]
// '16XF84j2wQ9wjkqRM2Y8ceCaw8dQu7t3ve9P9XbBj5kaRZxY'

const { tx: stakeTx } = await staker.buildStakeTx({
  amount: '1' // 1 DOT
})

const { tx: nominateTx } = await staker.buildNominateTx({
  validatorAddress
})

// Signing the transactions with Fireblocks
// ----------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx: signedStakeTx } = await staker.sign({
  signerAddress: delegatorAddress,
  tx: stakeTx
})

const { signedTx: signedNominateTx } = await staker.sign({
  signer,
  tx: nominateTx
})

// Broadcasting the transactions
// -----------------------------

const { txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'

// Closing the connection
// ----------------------

await staker.close()
```

{% endtab %}

{% tab title="Polygon" %}

```javascript
// Configuration
// -------------

import { PolygonStaker, CHORUS_ONE_POLYGON_VALIDATORS } from '@chorus-one/polygon'

const staker = new PolygonStaker({
  network: 'mainnet',
  rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'

// You can use the Chorus One validator address or specify your own
const validatorShareAddress = CHORUS_ONE_POLYGON_VALIDATORS.mainnet

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorShareAddress,
  amount: '1', // 1 POL
  slippageBps: 50 // 0.5% slippage tolerance
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const { txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

{% endtab %}

{% tab title="Hyperliquid" %}

```javascript
// Configuration
// -------------

import { HyperliquidStaker, CHORUS_ONE_HYPERLIQUID_VALIDATOR } from '@chorus-one/hyperliquid'

const staker = new HyperliquidStaker({
  chain: 'Mainnet'
})

// Building the transaction
// ------------------------

const delegatorAddress = '0xYourAddress'

// You can use the Chorus One validator address or specify your own
const validatorAddress = CHORUS_ONE_HYPERLIQUID_VALIDATOR

// Step 1: Transfer HYPE from spot to staking account
const { tx: transferTx } = await staker.buildSpotToStakingTx({
  amount: '100' // 100 HYPE
})

// Step 2: Delegate to validator
const { tx: stakeTx } = await staker.buildStakeTx({
  validatorAddress,
  amount: '100' // 100 HYPE
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx: signedTransfer } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: transferTx
})

const { signedTx: signedStake } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: stakeTx
})

// Broadcasting the transaction
// ----------------------------

const { txHash: transferHash } = await staker.broadcast({
  signedTx: signedTransfer,
  delegatorAddress
})

const { txHash: stakeHash } = await staker.broadcast({
  signedTx: signedStake,
  delegatorAddress
})

// Tracking the transaction
// ------------------------

// Hyperliquid does not support getTxStatus - use getDelegatorHistory instead
await new Promise((resolve) => setTimeout(resolve, 1000))

const history = await staker.getDelegatorHistory({
  delegatorAddress
})

const recentEvents = history.slice(0, 5)
console.log('Recent events:', recentEvents)
```

{% endtab %}

{% tab title="Monad" %}

```javascript
// Configuration
// -------------

import { MonadStaker, CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const staker = new MonadStaker({
  rpcUrl: 'https://rpc-mainnet.monadinfra.com'
})

await staker.init()

// Building the transaction
// ------------------------

const delegatorAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'

// You can use the Chorus One validator ID or specify your own
const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildStakeTx({
  validatorId,
  amount: '1000' // 1000 MON
})

// Signing the transaction with Fireblocks
// ---------------------------------------

import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx
})

// Broadcasting the transaction
// ----------------------------

const { txHash } = await staker.broadcast({ signedTx })

// Tracking the transaction
// ------------------------

const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

{% endtab %}
{% endtabs %}

### Next Steps

To help you get started with specific blockchain networks, please check out the detailed guides for each supported chain below.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Ethereum</strong></td><td><a href="/pages/inFkuRbwZBHzLvsdD2xj">/pages/inFkuRbwZBHzLvsdD2xj</a></td><td><a href="/files/9ZisDvRKceazJ128Di6t">/files/9ZisDvRKceazJ128Di6t</a></td></tr><tr><td><strong>Solana</strong></td><td><a href="/pages/RuY1w45WM5H7KGThfVr9">/pages/RuY1w45WM5H7KGThfVr9</a></td><td><a href="/files/MlfluA66SZcGdcu0IqLc">/files/MlfluA66SZcGdcu0IqLc</a></td></tr><tr><td><strong>Near</strong></td><td><a href="/pages/sZ4hhJjzjPQdY3QjmQXK">/pages/sZ4hhJjzjPQdY3QjmQXK</a></td><td><a href="/files/fyAJq1A1Slx2WZ5GEGc5">/files/fyAJq1A1Slx2WZ5GEGc5</a></td></tr><tr><td><strong>Avalanche</strong></td><td><a href="/pages/SborpOadg6M48NbRh2R5">/pages/SborpOadg6M48NbRh2R5</a></td><td><a href="/files/1nxAuMGZNIO8jyJY0dMm">/files/1nxAuMGZNIO8jyJY0dMm</a></td></tr><tr><td><strong>TON</strong></td><td><a href="/pages/W2ZGvKHNn2N9EVPUhygl">/pages/W2ZGvKHNn2N9EVPUhygl</a></td><td><a href="/files/Sj5g4BrzmGuSfeQZTixd">/files/Sj5g4BrzmGuSfeQZTixd</a></td></tr><tr><td><strong>Polkadot (Substrate)</strong></td><td><a href="/pages/De0U01xAN2zhFmA7dXJS">/pages/De0U01xAN2zhFmA7dXJS</a></td><td><a href="/files/mvRo6yUw5UKgVNoTBbnw">/files/mvRo6yUw5UKgVNoTBbnw</a></td></tr><tr><td><strong>Cosmos</strong></td><td><a href="/pages/ACqP9PO31abBEZ7kS17Z">/pages/ACqP9PO31abBEZ7kS17Z</a></td><td><a href="/files/cogPh27tppBlKFkon6LA">/files/cogPh27tppBlKFkon6LA</a></td></tr><tr><td><strong>Polygon</strong></td><td><a href="/pages/jogzF11gtlrloQZqJrVk">/pages/jogzF11gtlrloQZqJrVk</a></td><td><a href="/files/gsE7ZrjlwbXuuL8k695J">/files/gsE7ZrjlwbXuuL8k695J</a></td></tr><tr><td><strong>Hyperliquid</strong></td><td><a href="/pages/o8eLcePYsU4Q4IMuAM1t">/pages/o8eLcePYsU4Q4IMuAM1t</a></td><td><a href="/files/4idBo6tPbLsbELAR68Sb">/files/4idBo6tPbLsbELAR68Sb</a></td></tr><tr><td><strong>Monad</strong></td><td><a href="/pages/phLMEfKz8e4pzOByAE3A">/pages/phLMEfKz8e4pzOByAE3A</a></td><td><a href="/files/vEvV7p1Rn7OqXeip7sqF">/files/vEvV7p1Rn7OqXeip7sqF</a></td></tr></tbody></table>


# Rewards Dashboard API Keys

For programmatic access to staking **rewards data** over REST, generate API keys in the **Chorus One Rewards Dashboard** and see the [Rewards API documentation](https://chorus-one.gitbook.io/rewards-api) for endpoints and authentication.


# Staking Overview

All you need to know about staking, delegations, and running your own Validator.

## Why Stake?

Staking offers a way for institutions and individual investors to earn rewards on their assets while still maintaining full custody of them.

Whether you're an individual investor seeking to make your assets work for you, or an institution managing a crypto treasury or providing services to clients, staking is the ideal solution.

Below, let's dive into why staking is the most important and reliable source of yield in crypto.

Or, if you prefer, you can review some of our latest research in the tab below.

{% tabs %}
{% tab title="Research" %}

* [MEV on the dYdX v4 chain](https://chorus.one/reports-research/mev-on-the-dydx-v4-chain)
* [Breaking Bots: An alternative way to capture MEV on Solana](https://chorus.one/reports-research/breaking-bots-an-alternative-way-to-capture-mev-on-solana)
* [Optimal Risk and Reward on EigenLayer: A first look](https://chorus.one/reports-research/optimal-risk-and-reward-on-eigenlayer-a-first-look)
  {% endtab %}
  {% endtabs %}

***

## What is Staking and Proof of Stake?

Let's look at a big picture conceptual overview of staking. While the finer nuances and details of the exact mechanics can vary from network to network, the core concept of Proof of Stake (otherwise referred to as PoS is generally quite similar between networks).

In a nutshell, non-custodial staking can be thought of as nearly the equivalent of depositing funds in a high yield savings account, ***however***, with four main differences.

1. You retain control of your assets and your stake remains in your custody.
2. The base value of the asset you're staking can increase or decrease in price.
3. The rewards you accrue from staking are generally in the native token you staked, however, for some networks there are exceptions.
4. By staking, you are contributing to the overall security of the network though a mechanism known as Proof of Stake.
   1. Note: Proof of Stake refers to the overall concept of securing a networks, however, the exact consensus mechanism may vary from network to network.

#### So How Does it Work?

Staking means that holders of a specific token (the staking token) provide the token as collateral vouching for the correct and honest behavior of the validator that they delegate (stake) to.

{% hint style="info" %}
It's worth noting that for many networks the terms "stake", "delegate", "bond", etc. are often referring to the same underlying concept.

For example, you may hear the term "unstake" and then the asset will go through an "unbonding period" before the unstaking process is finished.

Alternatively, you may hear the term "stake" also be referred to as "bond" or "delegate".

These guides will use these different terms but always try to make sure the terminology of the network is used while still conveying the correct gist of the concept for you.
{% endhint %}

When you stake, it involves locking away the assets in a non-custodial manner to incentivize network participants and validators to not act dishonestly. This in turn increases the security of the network via the validators, which are nodes on the network which receive the stake and verify transactions and ensure that the ledger (blockchain) is accurate and continues to move forward.

#### The Role of the Validator

The validator is responsible for processing and verifying transactions, producing blocks and securing the blockchain, thus reaching consensus. Chorus One specializes in running validators on many different Proof of Stake networks. Ensuring you stake to a reputable validator not only helps ensure the safety of your funds but also contributes to the health and security of the network.

In return validating the network, the validator earns rewards for contributing to the overall network security and moving the blockchain forward. Thus, they earn staking rewards which are distributed to the stakers (delegators) to that validator.

This is how staking earns passive rewards on the funds you stake (delegate) to a validator. PoS (Proof of Stake) blockchains generally pay inflationary rewards as well as transaction fees as staking rewards.

<details>

<summary>Where do these staking rewards come from?</summary>

Staking rewards go to the token holders who provide their assets as collateral minus a commission that the staking provider charges for providing their services.

If the validator does something that goes against the protocol rules (e.g. signing two different blocks at the same block height), it can lead to a destruction of the assets staked to that validator, known as "slashing". This discourages dishonest behavior from validators.

Staking is generally non-custodial. That means that the staking provider does not have access to the staked assets. The user retains full custody of the tokens they stake.

![](/files/q5leZPNkrkhRnvrzSfE7)

</details>

<details>

<summary>Staking to a Public Node versus a Whitelabel Validator (Staking as a Service)</summary>

Staking to a public node is a simple way to start earning rewards and is a viable option for both individual investors or institutions alike.

However, if you wish to have more control of your node, limit who has access to it, or provide branded staking services for your customer base, and receive detailed reports, a Whitelabel node (otherwise referred to VaaS - Validator as a Service) may be a good option to consider.

Certain networks also require the setup and maintenance of as validator node to participate in staking. In this case, pursuing VaaS is a great option to stake your assets.

By setting your staking fees for your customers and maintaining full control over your branding elements, providing non-custodial staking as a service and provide a competitive edge.

For questions and business inquiries, please reach out to us at <StakingBOS@bitwiseinvestments.com>

</details>

## What are Consensus Mechanisms?

The two main consensus mechanisms are Proof-of-Work (PoW) used by Bitcoin and other networks, and Proof of Stake (PoS), used by Ethereum, Solana, Cosmos, Avalanche, among others.

* **Proof of Work (PoW):** Miners compete to solve complex math problems using powerful computers. The first to solve the problem gets to add a new block to the blockchain and earn rewards. This process uses a lot of electricity and computing power. Bitcoin uses PoW.
* **Proof of Stake (PoS):** Validators are chosen to add new blocks based on how many delegated assets they hold and are willing to "stake" as collateral. The greater number of assets you stake, the higher your chances of being chosen to validate the next block. This method is more energy-efficient.

{% hint style="info" %}
Other networks have developed novel consensus mechanisms that go by different names, however, the same fundamental concepts of Proof of Stake are often an underlying aspect of how the network security works.
{% endhint %}

<figure><img src="/files/HnlpUwIrpD7GQdGo5cpa" alt=""><figcaption><p>Proof of Work enables greater speed, scalability, efficiency, faster transaction finality, and increased security.</p></figcaption></figure>

***

## Is Staking Safe?

Staking is not the only way to earn rewards in crypto, however, it is by far one of the safest.

Let's look at some of the perks outlined below.

<figure><img src="/files/nrbeDYHTu7PPVNJyTfPL" alt=""><figcaption><p>An overview of the perks of staking.</p></figcaption></figure>


# Staking Concepts

An overview of the newest developments in crypto staking and how to get involved.

## Staking Terms & Terminology

While we covered the overall gist of how staking works in our [Staking Overview](/staking-fundamentals/staking-overview), there are many nuances and different concepts in the world of staking that vary from network to network.

{% hint style="info" %}
Let's explore what some of the concepts are below that go beyond the traditional Proof of Stake model.
{% endhint %}

***

### Delegated Proof of Stake (DPoS)

A consensus mechanism where token holders delegate their staking power to validators who participate in network consensus on their behalf.

**Examples:**

* Networks like Tezos and Solana use DPoS among many others that use either DPoS directly or a combination of this consensus model with new novel models.

**Benefits:**

* Greater scalability and efficiency compared to traditional Proof of Stake (PoS).
* Lower barrier to entry for token holders who want to participate in staking.

***

### Staking as a Service (SaaS)

This is one of the many services Chorus One offers. SaaS involves a trusted third party solution that simplifies the staking process for users or institutions, typically by managing validator infrastructure.

{% hint style="info" %}
To learn more please feel free to review Staking Options: White Label vs Public Node
{% endhint %}

**Example:**

* Chorus One offers staking services for multiple networks, ensuring secure and reliable validator operations.

Benefits:

* Reduces technical complexity for stakers.
* Provides institutional-grade reliability.
* Allows White Label branding and dedicated support for all your staking needs.
* Comprehensive rewards reporting directly from Chorus One or via [Rewards](/our-products/chorus-one-rewards)

***

### Slashing

A penalty imposed on validators (and their delegators) for misbehavior, such as downtime or double-signing blocks. It is the punishment mechanism to ensure and incentivize good behavior on a network for all participants and helps keep the network secure.

{% hint style="info" %}
Slashing risks are a part of many networks using a staking model, although slashing is not active on every network that uses staking.

However, this is why choosing a reliable staking provider such as Chorus One is so important when considering which validator to stake with.

* By operating highly reliable validators, Chorus One minimizes slashing risks for its delegators.
  {% endhint %}

***

### Auto-Compounding Staking Rewards

A mechanism that automatically reinvests staking rewards into the staked principal, allowing users to earn compound interest without manual intervention.

{% hint style="warning" %}
Not all networks have auto-compounding of staking rewards.

For these networks, it is advisable to find a cadence that works for you to periodically claim and stake the newly earned rewards to maximize your reward potential.
{% endhint %}

**Benefits:**

* Auto-compounding maximizes yield without additional effort for the user.
* This can make networks with this mechanic ideal for long-term stakers.

***

### Staking Pools

Staking Pools use a collective staking approach where multiple users combine their tokens to meet the minimum requirements for staking to create accessibility for users who otherwise could not participate and to increase reward efficiency.

**Examples:**

* [Ethereum Staking Pool](/our-products/chorus-one-ethereum-staking) — By pooling ETH in a custom solution, Chorus One has created an Ethereum staking solution that allows any user to stake any amount of ETH instead of being limited to quantities of 32 ETH.

**Benefits:**

* Accessibility for for more users leading to more equitable access to rewards potential.
* Increased network decentralization.

***

### Proof of Liquidity (PoL)

A staking mechanism that locks liquidity-providing tokens (e.g., LP tokens) in return for network rewards, aligning staking with liquidity provisioning.

**Benefits:**

* Encourages liquidity in trading pairs.
* Dual rewards from staking and trading fees.

***

Feel free to reach out to our Support Team if you would like any clarification.

{% hint style="info" %}
For direct support, please create a ticket on our [support platform](https://support.chorus.one/hc/en-us/requests/new).

A link for a support request can also be found along the top of this webpage as well as many other Chorus One resources including [Ethereum Staking Pool](https://opus.chorus.one/pool/stake/), [The Chorus One SDK](https://chorus-one.gitbook.io/sdk), and [our Blog](https://chorus.one/insights-category/blog).
{% endhint %}

***

<details>

<summary>About Chorus One</summary>

Chorus One is one of the largest institutional staking providers globally, operating infrastructure for over 60 Proof-of-Stake (PoS) networks, including Ethereum, Cosmos, Solana, Avalanche, Near, and others.

Since 2018, we have been at the forefront of the PoS industry, offering easy-to-use, enterprise-grade staking solutions, conducting industry-leading research, and investing in innovative protocols through Chorus One Ventures.

As an ISO 27001 certified provider, Chorus One also offers slashing and double-signing insurance to its institutional clients. For more information, visit [chorus.one](https://chorus.one/) or follow us on [LinkedIn](https://www.linkedin.com/company/chorus-one/), [X (formerly Twitter)](https://twitter.com/ChorusOne), and [Telegram](https://t.me/chorusone).

</details>


# What is MEV?

MEV stands for Maximal Extractable Value. Let's explore what this means for staking.

## MEV Demystified

While it might sound complex, MEV is actually fairly simple from a big picture perspective, but of course the nitty-gritty technicals of how it works are far more nuanced.

{% hint style="success" %}
**MEV (Maximal Extractable Value)** refers to the extra profit validators can make by controlling the order of transactions in a block.
{% endhint %}

For institutional staking providers, how MEV is captured and distributed has a direct effect on validator performance and client yield. Chorus One operates validator infrastructure designed to capture MEV efficiently — through MEV-boost integration and internal research into proposer timing — while maintaining network integrity.

***

### That's MEV at a Glance

For a deeper technical perspective, Chorus One' research team has contributed to the public body of knowledge on MEV. This includes **Adagio**, an in-house optimized Ethereum MEV-boost client designed to capture additional rewards by improving timing behavior in the transaction supply chain ([research writeup](https://chorus.one/articles/timing-games-and-implications-on-mev-extraction)).

* In a pilot study, Adagio generated approximately 4.75% additional MEV rewards on Ethereum compared to baseline configurations.

Related research is publicly available on [EthResearch](https://ethresear.ch/t/the-cost-of-artificial-latency-in-the-pbs-context/17847).

***

Feel free to reach out to our Support Team if you would like any clarification.

{% hint style="info" %}
For direct support, please create a ticket on our [support platform](https://support.chorus.one/hc/en-us/requests/new).

A link for a support request can also be found along the top of this webpage as well as many other Chorus One resources including [Ethereum Staking Pool](https://opus.chorus.one/pool/stake/), [The Chorus One SDK](https://chorus-one.gitbook.io/sdk), and [our Blog](https://chorus.one/insights-category/blog).
{% endhint %}

***

<details>

<summary>About Chorus One</summary>

Chorus One is one of the largest institutional staking providers globally, operating infrastructure for over 60 Proof-of-Stake (PoS) networks, including Ethereum, Cosmos, Solana, Avalanche, Near, and others.

Since 2018, we have been at the forefront of the PoS industry, offering easy-to-use, enterprise-grade staking solutions, conducting industry-leading research, and investing in innovative protocols through Chorus One Ventures.

As an ISO 27001 certified provider, Chorus One also offers slashing and double-signing insurance to its institutional clients. For more information, visit [chorus.one](https://chorus.one/) or follow us on [LinkedIn](https://www.linkedin.com/company/chorus-one/), [X (formerly Twitter)](https://twitter.com/ChorusOne), and [Telegram](https://t.me/chorusone).

</details>


# What is Liquid Staking?

You may have heard the term, but what does it mean? Let's dive in.

## Staked Assets are Locked Right? Not with Liquid Staking!

When assets are staked, they generally can’t be used for other things. This creates some capital inefficiency.

{% hint style="success" %}
Enter Liquid Staking, a developing in the staking ecosystem that allows staked assets to be leveraged to earn additional yield.
{% endhint %}

***

### How Does it Work?

Liquid staking generally works by creating a smart contract that pools the stakeable asset.

The smart contract then stakes these assets with various providers.

The delegator receives a token that represents a claim on the staked assets. This is a token that can be used and transferred without limitations, opening up new possibilities to leverage your staked assets.

{% hint style="info" %}
These are known as Liquid Staking Tokens (LSTs) or Liquid Staking Derivatives (LSDs) and open up new ways to maximize the benefits of your staked assets.
{% endhint %}

***

### What are the Advantages of Liquid Staking?

Liquid staking allows quite a few benefits such as:

* Selling the staked asset instantly without going through an unbonding or unstaking period.
* Use the asset as collateral to borrow against it.
* Providing the staked asset as liquidity in exchanges and earning trading fees as well as staking rewards at the same time.

These are only a few examples of what LSTs can do. There are a variety of DeFi platforms out there where users can get creative with how to maximize the utility of their staked assets.

***

### Restaking & Types of Liquid Staking

{% tabs %}
{% tab title="Restaking" %}
Restaking refers to using already staked assets (or their derivatives) to secure additional networks or participate in other staking mechanisms, effectively “stacking” staking opportunities.

**Example:**

* EigenLayer or Symbiotic enable restaking of staked osETH through the [Chorus One ETH staking portal](/our-products/chorus-one-ethereum-staking) to secure new protocols known as AVS's (Actively Validated Services).

**Benefits:**

* Increased capital efficiency.
* Enhanced security for emerging networks and bootstrapping potential.

**Considerations:**

* However, in some cases this can lead to Increased risks since slashing could impact the same asset across multiple protocols.
  {% endtab %}

{% tab title="Liquid Staking Tokens (LSTs)" %}
LSTs are tokens that represent staked assets in a liquid form. They allow users to continue earning staking rewards while maintaining the flexibility to trade, transfer, or use the tokens in other DeFi applications.

**Use Case:**

* If you stake ETH on a liquid staking platform like the [Chorus One ETH staking portal](/our-products/chorus-one-ethereum-staking), you receive osETH, which can be used across certain DeFi protocols while your original ETH remains staked.
  * Alternatively, it can be restaked to a protocol like EigenLayer or Symbiotic.

**Benefits:**

* Liquidity for staked assets.
* Access to DeFi opportunities like lending, borrowing, and trading.
* Continued earning of staking rewards.
  {% endtab %}

{% tab title="Liquid Staking Derivatives (LSDs)" %}
LSDs are a subtype of LSTs that represent not only the staked asset but also the accumulated staking rewards.

This means the value of the LSD increases over time, reflecting both the staked amount and the rewards earned.

**Example:**

* With rETH from Rocket Pool, the token’s value grows as staking rewards are added, eliminating the need for separate reward distribution.

**Benefits:**

* Simplicity in managing staking rewards.
* This can be better suited for long-term holding in DeFi strategies.
* It can help reduce operational complexities for liquid staking platforms.
  {% endtab %}
  {% endtabs %}

***

Feel free to reach out to our Support Team if you would like any clarification.

{% hint style="info" %}
For direct support, please create a ticket on our [support platform](https://support.chorus.one/hc/en-us/requests/new).

A link for a support request can also be found along the top of this webpage as well as many other Chorus One resources including [Ethereum Staking Pool](https://opus.chorus.one/pool/stake/), [The Chorus One SDK](https://chorus-one.gitbook.io/sdk), and [our Blog](https://chorus.one/insights-category/blog).
{% endhint %}

***

<details>

<summary>About Chorus One</summary>

Chorus One is one of the largest institutional staking providers globally, operating infrastructure for over 60 Proof-of-Stake (PoS) networks, including Ethereum, Cosmos, Solana, Avalanche, Near, and others.

Since 2018, we have been at the forefront of the PoS industry, offering easy-to-use, enterprise-grade staking solutions, conducting industry-leading research, and investing in innovative protocols through Chorus One Ventures.

As an ISO 27001 certified provider, Chorus One also offers slashing and double-signing insurance to its institutional clients. For more information, visit [chorus.one](https://chorus.one/) or follow us on [LinkedIn](https://www.linkedin.com/company/chorus-one/), [X (formerly Twitter)](https://twitter.com/ChorusOne), and [Telegram](https://t.me/chorusone).

</details>


# StakeWise V3

A comprehensive overview of StakeWise V3

## **A brief introduction to StakeWise v3**

Jordan Sutcliffe, Head of Business Development at Stakewise, aptly coined StakeWise V3 as the ‘[Swiss army knife](https://www.youtube.com/watch?v=HA2f0XhRN_8\&t=7755s)’ for ETH staking, sparking a flurry of interest from ETH enthusiasts. During the unveiling, the team revealed that the new version opens the doors for anyone capable of running Ethereum validators to engage in liquid staking and receive delegations in a permissionless manner.

This is an approach that aims to welcome a broader range of participants, fostering control and driving decentralization within the Ethereum staking ecosystem.

#### StakeWise V3 achieves this by introducing the concept of layered staking, allowing users to:

1. Delegate ETH to a vault of the node operator(s) of their liking (1st layer)
2. Giving them the option to mint osETH to represent their stake (2nd layer)

This design enables anyone to join as a solo staker who can mint osETH tokens against their node, or delegate ETH across multiple nodes to counteract network concentration.

Notably, StakeWise v3 introduces a slashing-resistant staked ETH token, osETH, ensuring scalability without introducing systemic risk to the broader ecosystem.

## **The current state of Ethereum Staking, and why it had previously been an exclusive club**

Ethereum was conceived with the mission of building a permissionless, censorship-resistant and financially robust network for value exchange.

The transition to Proof of Stake (PoS) through the Merge aimed to democratize participation, shedding the hardware and compute costs of Proof of Work (PoW). A year on from the Merge, however, centralization remains one of Ethereum’s biggest challenges - ironically, drifting towards the paradox of its own mission statement.

Staking on Ethereum had previously mandated validators to lock up 32 ETH with the network. While this investment yields interest, any misstep or dishonest conduct by a validator can lead to the revocation of funds. Setting up a validator node to stake on the network can also be a complicated task, meaning financial penalties can result if things are set up improperly.

{% hint style="info" %}
To address this, liquid staking protocols emerged as intermediaries, enabling solo stakers and institutions to pool their ETH, collectively forming the 32 ETH required for a node.
{% endhint %}

This innovation democratized ETH staking, allowing nearly anyone to participate. Intermediaries assumed the operational responsibilities, handling the pooling, staking, and technical requirements, while taking a share of the rewards for their efforts.

### Why StakeWise V3?

The drawback of the pre-existing version of StakeWise and its counterparts is simple but crucial.

The absence of technical or capital requirements, the ability to temporarily exit from staking, and the increased efficiency of staked capital presented by liquid staking protocols resonate with depositors to an extent that it leads to a decrease in solo stakers (for example, individuals setting up ETH validators at home).

Over time, this decline can significantly impact Ethereum’s security and decentralization.

To address this, the StakeWise DAO introduced StakeWise V3, its latest version that allows anyone from solo stakers to established node operators to financial institutions to participate.

As a solo staker, one can seamlessly launch their own nodes, mint staked ETH (osETH) tokens against their nodes, or delegate any amount of ETH across multiple nodes to counteract network concentration.‍

## **The key components of StakeWise V3: Vaults and the osETH Token**

### ‍**Layer 1: Vaults**

At the heart of StakeWise V3 are ‘Vaults’ - a network of permissionless, non-custodial staking mini pools that anyone can launch on the [StakeWise platform](https://docs.stakewise.io/) and receive ETH delegations on their nodes.

{% hint style="info" %}
The Chorus One MEV Max Vault can be accessed on [StakeWise directly](https://app.stakewise.io/vault/mainnet/0xe6d8d8ac54461b1c5ed15740eee322043f696c08) or via the Chorus One staking portal at [opus.chorus.one/pool/stake](https://opus.chorus.one/pool/stake/).

For more on Chorus One Ethereum staking, see the [ETH Staking Overview](/our-products/chorus-one-ethereum-staking).

Operators interested in running their own vault can contact the Chorus One staking team at `StakingBOS@bitwiseinvestments.com`.
{% endhint %}

StakeWise vaults offer the user freedom to stake with whichever vault they want, choosing between vaults run by solo stakers, node operator companies, and groups of solo/commercial operators.

For every 32 ETH of deposits accumulated in a Vault, the Vault operator(s) registers an Ethereum validator in the Beacon Chain and starts staking. The staking rewards belong to the depositors, net of the staking fee charged by the Vault.

Importantly, each of these Vaults is completely unique to the configurations set up by its operator, meaning that the operator can fully customize its vault as per its own design, allowing users to pick a vault based on the features that best suit the depositor.

Essentially, Vaults are completely agnostic to the staking solutions that an operator wants to run - whatever client solutions, KYC features, MEV relays or DVT middleware that the entity wants to run are under their control.

This leads to a very diverse marketplace of staking solutions that users can shop around and choose from.

Moreover, Vault Operators can set their Vault to a private setting, allowing deposits only from addresses whitelisted by the Vault Operator.

This enables use cases like solo stakers depositing ETH into their own Vault and not accepting deposits from others. For instance, compliance-sensitive organizations can create a Vault to enable staking for only a limited number of KYC'd participants.

### **Layer 2: The osETH Token**

The osETH Token is a new type of *overcollateralized* ETH token introduced by v3, which is a liquid ERC-20 representation of staked assets that uses Vault Token(s) as collateral. It can be minted by anyone who has staked ETH into a Vault(s), or can be bought/sold on decentralized exchanges.

Importantly, osETH represents a new type of liquid-staked ETH token that has its value pegged to staked ETH 1:1, but that does not directly pass on the slashing losses to holders, **ensuring that all the staking rewards and penalties remain isolated to the individual Vault.**

To ensure this, V3 requires >1 ETH for every osETH that stakers in a Vault want to mint.

In the scenario where slashing does occur, there is always a reserve of ETH that absorbs the slashing losses before osETH holders are affected. This protects osETH holders from losing their principal, making osETH a safer option for staking.

Note that the stakers who *mint* osETH are [still exposed to the slashing risk](https://stakewise.medium.com/what-is-oseth-a-deep-dive-into-the-overcollateralized-staked-ether-token-of-stakewise-v3-part-1-37d14e28282a) of the Vaults in which they staked ETH, and excess collateralization makes sure that the other osETH holders are not affected.

## **The Use Cases of StakeWise**

<details>

<summary>For Solo Stakers</summary>

StakeWise V3 empowers solo stakers by allowing them to mint osETH tokens against their nodes, providing access to DeFi opportunities while maintaining a non-custodial setup.

Solo stakers can set up private vaults, mint osETH, and even earn additional revenue by hosting validators for other stakers.

Alternatively, public vaults enable solo stakers to accept delegations, maximize their score, and mint osETH based on received vault tokens.

</details>

<details>

<summary>For DeFi Users</summary>

StakeWise V3 caters to users seeking yields by providing osETH tokens, tradable in decentralized exchanges or minted within vaults.

osETH integrates slashing protection, and ensures that staked capital is not co-mingled across funds, thereby offering a less-risky, diverse marketplace for users to mint osETH and use it in DeFi, even allowing users to take advantage of boosted ETH staking.

</details>

<details>

<summary>For Institutions and Exchanges</summary>

Financial institutions typically prefer direct engagement with trusted staking service providers to ensure due diligence and favorable terms.

StakeWise V3 caters to this preference by enabling institutions and exchanges to create private vaults, allowing exclusive collaboration with chosen operators and staking clients.

Vault tokens from staking represent staked ETH, offering institutions the flexibility to enable liquidity and utility within their ecosystem.

Additionally, for broader access to DeFi markets, institutions can mint or permit customers to mint osETH tokens.

Institutions interested in launching a Private Vault with Chorus One can contact the staking team at `StakingBOS@bitwiseinvestments.com`.

</details>

<details>

<summary>For Commercial Node Operators</summary>

In StakeWise V3, operators, whether independent or collaborating with other entities, can establish vaults to accept delegations, allowing depositors to tokenize their staked ETH into osETH.

Operators can choose to keep vaults private or public, showcase strong performance, and enhance their vault Score by taking risk-reducing measures.

Chorus One operates an Ethereum staking offering built on StakeWise V3 — accessible as a public vault via the Chorus One staking portal at [opus.chorus.one/pool/stake](https://opus.chorus.one/pool/stake/) — providing individuals access to liquid staking on Chorus One's validator infrastructure.

Institutional clients also have the option of launching a Dedicated Vault operated by Chorus One, which can be private and ring-fenced or open and custom-branded.

Institutions interested in launching a Dedicated Vault can contact the Chorus One staking team at `StakingBOS@bitwiseinvestments.com`.

</details>

***

Feel free to reach out to our Support Team if you would like any clarification.

{% hint style="info" %}
For direct support, please create a ticket on our [support platform](https://support.chorus.one/hc/en-us/requests/new).

A link for a support request can also be found along the top of this webpage as well as many other Chorus One resources including [Ethereum Staking Pool](https://opus.chorus.one/pool/stake/), [The Chorus One SDK](https://chorus-one.gitbook.io/sdk), and [our Blog](https://chorus.one/insights-category/blog).
{% endhint %}

***

<details>

<summary>About Chorus One</summary>

Chorus One is one of the largest institutional staking providers globally, operating infrastructure for over 60 Proof-of-Stake (PoS) networks, including Ethereum, Cosmos, Solana, Avalanche, Near, and others.

Since 2018, we have been at the forefront of the PoS industry, offering easy-to-use, enterprise-grade staking solutions, conducting industry-leading research, and investing in innovative protocols through Chorus One Ventures.

As an ISO 27001 certified provider, Chorus One also offers slashing and double-signing insurance to its institutional clients. For more information, visit [chorus.one](https://chorus.one/) or follow us on [LinkedIn](https://www.linkedin.com/company/chorus-one/), [X (formerly Twitter)](https://twitter.com/ChorusOne), and [Telegram](https://t.me/chorusone).

</details>


# Ethereum Staking

ETH staking and restaking with Chorus One.

<figure><img src="/files/2z0kdyI0haJU0FLUBKRW" alt=""><figcaption></figcaption></figure>

## About ETH Staking with Chorus One

Chorus One operates Ethereum staking infrastructure for institutional clients and individual investors. ETH can be staked in any amount — including amounts not divisible by 32 ETH — via pooled staking powered by Stakewise V3, with the option to mint osETH and use it across the broader DeFi ecosystem.

The ETH staking interface is available via the public staking portal at [opus.chorus.one/pool/stake](https://opus.chorus.one/pool/stake/).

The underlying validator infrastructure — the [Vouch and Dirk](/our-products/chorus-one-ethereum-staking/vouch-and-dirk) open-source stack built by Attestant (now part of Chorus One) — is the same stack used by the Ethereum Foundation to operate its own staking program.

***

## Liquid Staking with Stakewise V3

<details>

<summary>What is Stakewise V3?</summary>

Stakewise V3 is a liquid staking protocol introduced by the Stakewise DAO that addresses stake centralization on Ethereum.

Traditional Ethereum validators require a 32 ETH minimum, significant technical infrastructure, and expose stakers to slashing risk. Stakewise V3 uses mini staking pools called "Vaults" that allow anyone to stake any amount of ETH, mint osETH (a liquid staking token), and participate in the broader DeFi ecosystem without meeting the 32 ETH threshold individually.

Vault operators customize their configuration independently, fostering a diverse marketplace of ETH staking solutions rather than consolidating stake into a few large operators.

For a deeper technical overview, see [A comprehensive guide to Stakewise V3](https://chorus.one/articles/a-comprehensive-guide-to-stakewise-v3).

</details>

<details>

<summary>How does liquid staking work?</summary>

In liquid staking, a user stakes their crypto with a liquid staking protocol and receives a derivative token in return — the token represents the staked amount plus accrued rewards (or penalties).

Unlike traditional staking, where assets are locked and illiquid, the derivative token can be traded, used as collateral, or deployed in DeFi protocols. This allows participation in network validation while retaining liquidity and the option to compound rewards elsewhere.

The tradeoff: liquid staking introduces smart contract risk that is not present in native staking, since rewards and principal are mediated by protocol contracts rather than directly held at the protocol level.

</details>

<details>

<summary>Supported Liquid Staking Tokens (LSTs)</summary>

```
osETH, wbETH, rETH, cbETH, stETH, oETH, ankrETH, swETH, ETHx, EIGEN
```

</details>

***

## Restaking and EigenLayer

Restaking, as defined by Vitalik Buterin, extends the utility of staked ETH beyond securing Ethereum itself. Staked ETH can be restaked to additional networks or applications, allowing those systems to use Ethereum's validator set and economic security without establishing their own.

**EigenLayer** implements restaking through Ethereum smart contracts. Stakers can opt in to restake their ETH (or liquid staking derivatives) to secure **Actively Validated Services (AVSs)** — additional applications built on top of Ethereum. AVSs gain security without bootstrapping their own validator network; restakers earn additional rewards for taking on the additional slashing conditions.

Supported LSTs can be restaked to EigenLayer directly through the Chorus One staking interface.

***

## Public versus Private Vaults

Chorus One operates both public pooled vaults (for general participation) and private tailored vaults (for institutional clients).

<details>

<summary><strong>Public Vaults</strong></summary>

Public vaults pool ETH from multiple participants into a shared vault operated by Chorus One. Any amount of ETH can be staked, and osETH can be minted against the stake.

Public vaults are accessible via [opus.chorus.one/pool/stake](https://opus.chorus.one/pool/stake/).

</details>

<details>

<summary><strong>Private Vaults</strong></summary>

Private vaults are dedicated, isolated vaults for institutional clients who require separation of their staked capital from the public pool. Private vault assets are not commingled with other vaults.

Institutional clients seeking a private vault can contact the Chorus One staking team at `StakingBOS@bitwiseinvestments.com`.

</details>

***

## Infrastructure: Vouch and Dirk

Chorus One' Ethereum validator infrastructure is built on **Vouch** and **Dirk** — open-source tools developed by Attestant (now part of Chorus One) and used in production by the Ethereum Foundation.

* **Vouch** is the validator orchestration layer. It connects to multiple beacon nodes simultaneously, uses pluggable strategies to select the best block proposals and attestations, and integrates MEV-boost natively.
* **Dirk** is the distributed key manager. It uses certificate-based access control, durable slashing protection, and threshold signing (Shamir Secret Sharing) to keep validator keys secure across multiple machines.

Together they enable multi-beacon-node resilience, zero-downtime operational upgrades, and cryptographic separation between signing logic and key custody.

**For a deeper overview, see** [**Vouch & Dirk: The Infrastructure Behind ETH Staking**](/our-products/chorus-one-ethereum-staking/vouch-and-dirk)**.**

***

## Institutional Integration — [The Chorus One SDK](https://chorus-one.gitbook.io/sdk)

Institutional clients integrating ETH staking into their own platforms can use the [Chorus One SDK](https://chorus-one.gitbook.io/sdk) — an all-in-one toolkit for building non-custodial staking flows. The SDK handles transaction construction, signing, and broadcast directly in the client's environment, supporting custom custody models including Fireblocks, Ledger, and browser wallets.

For institutional inquiries: `StakingBOS@bitwiseinvestments.com`

***

{% hint style="info" %}
**To use Chorus One ETH Staking, visit the staking portal at** [**opus.chorus.one/pool/stake**](https://opus.chorus.one/pool/stake/)

**For a step-by-step walkthrough, see Staking & Restaking ETH**
{% endhint %}


# Vouch & Dirk: The Infrastructure Behind ETH Staking

An introduction to Vouch and Dirk — the open-source Ethereum validator infrastructure that powers Chorus One' institutional staking.

## Overview

Chorus One' Ethereum staking operations — including the infrastructure behind the Ethereum Foundation's \~70,000 ETH staking program — run on two open-source tools built by Attestant (now part of Chorus One): **Vouch** and **Dirk**.

Both are Apache-2.0 licensed and used in production by the Ethereum Foundation itself, making them one of the most battle-tested institutional Ethereum staking stacks available.

***

## What Problem Do They Solve?

Traditional Ethereum validator setups have two structural weaknesses:

1. **Single points of failure** — one beacon node, one validator client, one key store. If any component fails, validators miss duties and forfeit rewards.
2. **Keys stored alongside signing logic** — validator signing keys typically live inside the same process as the validator client. A compromise of that process exposes the keys.

Vouch and Dirk address these as a pair:

* **Vouch** handles **orchestration** — communicating with multiple beacon nodes, deciding what to sign and when.
* **Dirk** handles **signing** — holding the keys in a separate, hardened, distributed system.

***

## Vouch: The Validator Orchestration Layer

Vouch is a standalone Ethereum consensus-layer validator client. Unlike bundled clients (Prysm, Lighthouse, Teku, Nimbus) that ship the validator client together with a beacon node, Vouch is **decoupled**. It connects to multiple beacon nodes simultaneously and performs validator duties on their behalf.

### Multi-Node Availability

Vouch maintains connections to multiple beacon nodes *at the same time* — not as primary/backup, but all concurrently. If any beacon node goes down, Vouch continues operating using the remaining nodes. This eliminates the classic single-beacon-node failure mode.

### Client Diversity

Vouch can use different beacon nodes for different purposes. This is particularly important for client diversity: if one consensus client has a supermajority and ships a bug, validators can be configured to exclude that client when determining what to attest to — reducing the risk of cascading attestation errors.

### Pluggable Strategies

Rather than hardcoding decision logic, Vouch uses **strategies** — configurable modules that define how to pick the best block proposal, attestation data, or MEV builder bid. For example, the `best` strategy for block proposals fetches candidates from all connected beacon nodes and selects the highest-value block, maximizing validator rewards.

### MEV-Boost Integration

Vouch includes native support for MEV-boost via its block-relay service, enabling participation in the builder auction market for additional block rewards.

### Multi-Instance Operation

Multiple Vouch instances can run simultaneously — safely. Combined with Dirk's slashing protection (below), this enables zero-downtime upgrades: operators can upgrade Vouch instances one at a time without missing validator duties.

***

## Dirk: The Distributed Key Manager

Dirk is the signing backend. It holds the validator private keys and performs signing operations — but only for authorized callers, and only if doing so won't result in a slashable offense.

### Certificate-Based Access Control

Every client that requests a signature must authenticate with a TLS client certificate. Dirk checks the certificate against a permissions config specifying exactly which validator keys each client is allowed to use. The default is deny-everything; permissions are explicitly granted. A compromised or misconfigured client can only access what it's been authorized for.

### Slashing Protection

Every signing request passes through a validation check **before** the key is used. This prevents:

* Signing two different blocks for the same slot (double block proposal)
* Signing conflicting attestations for the same epoch (surround vote / double vote)

Dirk durably records each signature to disk before producing it. The added latency is small (tens of milliseconds) but eliminates the risk of accidental double-signing — including when multiple Vouch instances try to sign the same duty.

### Threshold Signing

Instead of one Dirk instance holding one full key, keys can be split across multiple Dirk instances using **Shamir Secret Sharing**. In a 3-of-5 configuration:

* The key is split into 5 shares distributed across 5 Dirk instances
* Any 3 instances can collaborate to produce a valid signature
* No single instance holds the full key
* 2 instances can be down or compromised without affecting operations
* An attacker would need to compromise 3 separate instances to steal a key

This is how zero-downtime upgrades work: one Dirk instance at a time can be taken offline and upgraded while the remaining instances meet the signing threshold.

### Distributed Key Generation (DKG)

When threshold-signed keys are created, Dirk supports DKG — the keys are generated **collaboratively** across the Dirk instances. At no point during creation does any single machine hold the complete key. This eliminates the setup vulnerability where a compromised key-generation ceremony could expose the private key.

***

## How They Work Together

The flow for a single block proposal:

1. **Vouch's scheduler** detects a managed validator is selected as proposer for an upcoming slot.
2. **Vouch queries all connected beacon nodes** simultaneously for block proposal candidates.
3. **Strategy selects the best proposal** (scored by expected rewards).
4. **Vouch sends a signing request to Dirk** with the block to sign.
5. **Dirk verifies the certificate** — is this caller authorized for this validator?
6. **Dirk runs slashing protection** — has anything else been signed for this slot?
7. **Dirk signs the block** (using threshold signing if multi-instance) and returns the signature.
8. **Vouch submits the signed block** to all connected beacon nodes.

The full round-trip completes in a fraction of a 12-second slot.

***

## Why This Matters for Institutional Staking

The Vouch + Dirk stack provides three institutional-grade properties:

| Property                     | How It's Achieved                                                                                                            |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **High availability**        | Multi-beacon-node connections + multi-instance Vouch + threshold-signing Dirk — no single point of failure                   |
| **Cryptographic security**   | Keys held in separate signing process with certificate-based access; threshold signing means no machine holds a complete key |
| **Zero-downtime operations** | One component at a time can be upgraded or replaced without interrupting validator duties                                    |

These properties are table stakes for operating institutional-scale staking infrastructure — and they are prerequisites for the track record underlying Chorus One' Ethereum staking offering.

***

## Further Reading

* [Attestant blog: Introducing Vouch](https://www.attestant.io/posts/introducing-vouch/)
* [Attestant blog: Introducing Dirk](https://www.attestant.io/posts/introducing-dirk/)
* [Attestant blog: Helping client diversity](https://www.attestant.io/posts/helping-client-diversity/)
* [Attestant blog: Upgrading infrastructure without missing a beat](https://www.attestant.io/posts/upgrading-attestants-infrastructure-without-missing-a-beat/)
* [Vouch on GitHub](https://github.com/attestantio/vouch)
* [Dirk on GitHub](https://github.com/attestantio/dirk)


# Staking to ETH Vaults

How to stake any amount of ETH with Chorus One

<div data-full-width="false" data-with-frame="true"><figure><img src="/files/0jTCNcuombG3yasvsNkL" alt=""><figcaption></figcaption></figure></div>

## Summary

* In three simple steps you can stake any amount of ETH, mint osETH as a liquid staking token and deposit your osETH into Eigenlayer.
* Our Stakewise vault allows you to mint osETH, which is a liquid staking token (LST). The issued liquid staking token is overcollateralized, meaning the underlying assets in the vault are worth more than the osETH issued.
* For an introduction to Staking Vaults, their benefits for institutions, investors, and use cases, please visit our overview page: [Chorus One Ethereum Staking](/our-products/chorus-one-ethereum-staking)

***

## **How to stake**

First, access our staking experience:

1. Stake any amount of ETH via the [Earn Platform](https://staking.chorus.one/eth/stake)
2. Mint osETH from your staked ETH to be used in other DeFi using our [Ethereum Staking Pool app](https://opus.chorus.one/pool/stake/)

These methods are made as simple as possible to enhance your staking experience, and can be used as described below:

### ‍**Stake ETH**

**Step 1:** Connect your wallet on the page and choose a vault.

* You can choose the Chorus One MEV Max vault or the Chorus One Obol DV vault.

{% hint style="info" %}
You can hover over the "i" symbol next to each to view the vaults on Stakewise V3 and you can learn about the differences between each vault by checking the table menus below.
{% endhint %}

{% tabs %}
{% tab title="MEV Max" %}
Chorus One’s ground-breaking MEV research ensures the highest yields with top-tier security and enterprise-level infrastructure.

If you'd like to take a deep dive, Chorus One's pioneering MEV research led to the design of **Adagio** an in-house, optimized Ethereum MEV-boost client that increases our MEV rewards by optimizing the way we interact with the transaction supply chain.

* In a recent pilot with Adagio were able to generate 4.75% additional MEV rewards.
  {% endtab %}

{% tab title="Obol DV" %}
This vault represents a distributed validator cluster , using Obol's DV technology to run the validators across multiple nodes. As a staker, you can expect higher uptime, decreased slashing risk, and a meaningful contribution to the decentralization of the Ethereum network.

By staking with an Obol DV, you automatically participate in the Obol Contributions initiative, contributing 1% of staking rewards to the "1% for Decentralization" retroactive funding model. Your contributions will be tracked and recognized by Obol and can be viewed on our staking dApp.
{% endtab %}
{% endtabs %}

<figure><img src="/files/DUqlIqyCRrSt2y7IiV0J" alt="" width="375"><figcaption><p>Staking Vault Selection</p></figcaption></figure>

**Step 2:** Select how much ETH you wish to stake, enter the amount, and click '**Confirm and Stake**'

<figure><img src="/files/6vNDOvPr8y8CdjXz6e4n" alt="" width="375"><figcaption><p>Transaction Success Status</p></figcaption></figure>

{% hint style="success" %}
At this point, you're now staking your ETH!

However, if you want to restake your ETH in EigenLayer or Symbiotic, read on!
{% endhint %}

**Step 3 (Optional):** Mint osETH and deposit it into EigenLayer or Symbiotic.

Once deposited successfully, you can now mint your osETH in 1-click by clicking '**Mint osETH**' as shown in the screenshot above.

### **How to Restake your osETH or other supported Liquid Restaking Tokens (LRTs)**

You can bring your [supported liquid staking tokens](/our-products/chorus-one-ethereum-staking#supported-liquid-staking-tokens-lsts-can-be-seen-below) minted on any external platform and deposit them into EigenLayer through [Ethereum Staking Pool app](https://opus.chorus.one/pool/stake/)

**Step 1:** Go to the Ethereum Staking Pool page, select Restake and connect your wallet

**Step 2:** Select either EigenLayer or Symbiotic, (shown above) and then select your LRT (i.e. osETH) that you'd like to stake.

**Step 3:** Deposit your tokens into EigenLayer or Symbiotic.

{% hint style="success" %}
**That's it, you're all done!**

**You can navigate to the Dashboard on the sidebar at any time to review your staked balances.**
{% endhint %}

***

## **The ETH Staking SDK**

Our institutional customers may opt in to leverage the [Staking SDK](https://chorus-one.gitbook.io/sdk) to integrate ETH staking into their offerings, providing their customers with all the benefits of the Chorus One staking experience.

This allows our institutional client’s customers to benefit from all the features offered by ETH Staking Vaults, including no minimum ETH required to stake, top tier-MEV yields, high rewards, and direct restaking with EigenLayer and Symbiotic.

{% hint style="info" %}
For institutions interested in learning more about the Staking SDK, please get in touch with our team at <StakingBOS@bitwiseinvestments.com>
{% endhint %}


# Unstaking Ethereum

How to unstake ETH from Chorus One Pools, Eigenlayer and Symbiotic.

## How to **Unstake**

To unstake your staked position, go to the Unstake tab and enter the amount of ETH you would like to unstake and hit the '**Unstake'** button.

<figure><img src="/files/ZXpwUjSiJPWNVPTkv9sj" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
**Note:** If you minted osETH at any point any time against your staked position, you will have to burn that amount to unstake all your ETH.

If this applies for you, please skip down to the section:

* [#unstake-from-eigenlayer-or-symbiotic](#unstake-from-eigenlayer-or-symbiotic "mention")
  {% endhint %}

You will be prompted to sign the unstaking transaction in your wallet. Once you have done so, you will have successfully unstaked your position.

Once you unstake your ETH, it enters the withdrawal queue. You will see a progress bar right below the success message that lets you know the status of your withdrawable stake.

{% hint style="warning" %}
**Depending on the amount of ETH being unstaked the timelines can vary.**

For smaller delegations being unstaked, it should after a maximum of 8 days or sooner.

For larger delegations, this timelines can be increased depending on the exit queue and be up to 14 days or more.

* For any questions or concerns about unstaking timelines, please reach out to use at <supportBOS@bitwiseinvestments.com>
  {% endhint %}

Once your ETH becomes ready for withdrawal you can click the "Withdraw" button to claim the stake back into your wallet.

{% hint style="info" %}
You can come back to the Unstake tab at a later point and check the status of your withdrawal.
{% endhint %}

### How Long Does it Take to Unstake My ETH?

Unstaking your Ethereum from Ethereum Staking Pool will vary on a few factors, however, it can range from as short as 24 hours to 14+ days, most contingent on stake size.

* Larger delegations being unstaked are more likely to take longer.

The factors that may affect the unstaking time include how much ETH is liquid in the pool, activity in the exit queue, sweep delay, and most importantly the size of the ETH unstaking transaction being processed.

***

## **Unstake from Eigenlayer or Symbiotic**

To unstake your assets from Eigenlayer or Symbiotic go to the '**Unstake**' section under the '**Restaking Tab**'

{% hint style="warning" %}
If for any reason you find you cannot see your restaked assets for EigenLayer, please navigate to <https://app.eigenlayer.xyz/> and connect your wallet.

* You will be able to unstake from the EigenLayer interface directly.
* If you have any questions, please reach out to <supportBOS@bitwiseinvestments.com>
  {% endhint %}

<figure><img src="/files/TEOf7sx4kWR52fhPDCbW" alt="" width="341"><figcaption></figcaption></figure>

<figure><img src="/files/NxbyYnpUyu4PzuEnB3EO" alt=""><figcaption></figcaption></figure>

From this screen please select the LST you want to unstake and enter the amount.

* In the screenshot above we can see that 0.0090 stETH is restaked via EigenLayer.

<figure><img src="/files/bpzBq1uGpeAdzcAFpfgL" alt=""><figcaption></figcaption></figure>

To proceed, click on the '**Unstake**' button and sign the transaction in your wallet.

<figure><img src="/files/EtJFNKTCJLRhco8ejhRP" alt=""><figcaption><p>You'll see an in progress notification for a moment before it finalizes.</p></figcaption></figure>

{% hint style="success" %}
You have successfully unstaked!
{% endhint %}

### How Long Does it Take to Unstake from EigenLayer or Symbiotic?

Unstaking from EigenLayer takes 7 days for the funds to finalize while unstaking from Symbiotic takes 14 days.

* You can check the progress of your unstaking transactions by going to Ethereum Staking Pool dashboard.

<figure><img src="/files/FEngYA1s32rdKbROFV0N" alt=""><figcaption></figcaption></figure>

***

## The Chorus One SDK

Our institutional customers may opt in to leverage the [Chorus One SDK](https://chorus-one.gitbook.io/sdk) to integrate ETH staking into their offerings, providing their customers with all the benefits of Chorus One Staking seamlessly.

This allows our institutional client’s customers to benefit from all the features offered by Chorus One, including no minimum ETH required to stake, top tier-MEV yields, high rewards, and direct restaking with EigenLayer and Symbiotic.

{% hint style="info" %}
For institutions interested in learning more about the Chorus One SDK, please get in touch with our team at <StakingBOS@bitwiseinvestments.com>
{% endhint %}


# How Do I See My Rewards?

How to view your rewards data in Ethereum Staking Pool.

## Understanding the Dashboard in Ethereum Staking Pool

The dashboard view is your one stop shop to view all your staking activity in Ethereum Staking Pool.

To navigate there, use the left hand side panel and click on '**Dashboard**'

<figure><img src="/files/jyy5hnIp9khDZ7GttiLI" alt=""><figcaption><p>An example view of the Ethereum Staking Pool Dashboard.</p></figcaption></figure>

On the left you can see highlighted how to access the dashboard.

Along the top, highlighted in the pink boxes you can see how much your total stake is.

{% hint style="info" %}
You can select '**All Vaults**' (this is the default setting) or view your balances in the MEV Max or Obol DV vaults specifically.

* The same selection can be made for looking at your total osETH minted, highlighted in the upper-right box in the screenshot above.
  {% endhint %}

Below this, you can see your total restaked balance highlighted in the box near the middle of the screenshot.

* This will show you you what LRTs (Liquid Restaking Tokens) you have restaked.

{% hint style="success" %}
If you want to check on your Boosted ETH status, this will need to be done via the StakeWise interface to interact with the underlying Ethereum Staking Pool Vault.

To learn more, check out Boosted ETH Staking
{% endhint %}

***

## Viewing your Rewards Data

From the dashboard interface, you will see a line graph like the screenshot below.

<figure><img src="/files/8iNwVw1vWRK9WbvUavjr" alt=""><figcaption><p>Example of the Ethereum Staking Pool dashboard Historical Staking Rewards graph.</p></figcaption></figure>

You can hover your mouse cursor over the graph to see how many rewards you have accumulated over time.

{% hint style="info" %}
Using the box highlighted on the left, you can select which vault you want to see rewards data from. By default, all vaults will be selected.

To the right, you can click on '**Download CSV**' to download a file of all your rewards data to a CSV file.

* Note: The timestamps for each rewards cycle are from 00:00 UTC.
  {% endhint %}


# Using Fireblocks with Chorus One Staking

Everything you need to know to use Fireblocks with Chorus One Staking

<figure><img src="/files/e8NuGr62c4fLnbZoC9qu" alt=""><figcaption></figcaption></figure>

## Overview

In order to integrate Chorus One Staking with Fireblocks, we will be using the built in WalletConnect functionality to gather the information we need to connect your Fireblocks account to [Chorus One Ethereum Staking](/our-products/chorus-one-ethereum-staking).

As a brief overview, [WalletConnect](https://walletconnect.com/) is an open-source protocol that enables secure and decentralized connections between various blockchain wallets and dApps (decentralized applications). Users can interact with dApps like Ethereum Staking Pool from their mobile wallets to manage and execute transactions without exposing private keys.

[Fireblocks](https://www.fireblocks.com/) is a secure and enterprise-grade platform designed to manage digital assets and crypto transactions, providing solutions for securely transferring, storing, and issuing digital assets, with features like multi-party computation (MPC) and a network of trusted partners.

So how do we get these two interfaces to work together to integrate with Ethereum Staking Pool? Read on!

***

### Step 1: Connect to Ethereum Staking Pool via WalletConnect

When first landing on the Ethereum Staking Pool [page](https://opus.chorus.one/pool/stake/), click on the '**Connect wallet**' button in the upper-right hand side of your screen.

<figure><img src="/files/pGBvcYlB4WJwRQNvBhqv" alt=""><figcaption></figcaption></figure>

Next, you will be prompted with a connection method. In this case, we are choosing WalletConnect as illustrated below.

<figure><img src="/files/c61OSyk79PmXd6rszhIs" alt="" width="563"><figcaption></figcaption></figure>

You'll see a screen like the following:

<figure><img src="/files/ouzrtKPUzSWJX03wsnIj" alt="" width="357"><figcaption><p>Note we have two options here, the QR code, or the Fireblocks button.</p></figcaption></figure>

### Step 2: Choosing Your Connection Preference

From here, you'll have two options on how to proceed.

**1.)** Connect to your Fireblocks account via the Fireblocks button.

* This can be done via your web browser, however, signing transactions will still be done via Fireblocks on your mobile device.

**2.)** Connect to Ethereum Staking Pool via the Wallet Connect QR code from your Fireblocks account.

* This will require the use of a mobile device to access your Fireblocks account. Signing will also take place via your Fireblocks app on your mobile device.

{% hint style="info" %}
Either option is equally viable, it just comes down to which you prefer.

To connect directly via your Fireblocks account, please read on for [Option 1: Connecting via Fireblocks](#option-1-connecting-via-fireblocks).

Alternatively, to connect via QR code, skip ahead to [Option 2: Connecting via QR Code](#option-2-connecting-via-qr-code).
{% endhint %}

***

### Option 1: Connecting via Fireblocks

From the WalletConnect popup window we saw before, select the Fireblocks button to the right of the MetaMask and Ledger buttons.

<figure><img src="/files/PZVFAc12P0OUGR4xvD3i" alt="" width="351"><figcaption></figcaption></figure>

This will open a new browser tab where you will be prompted to first login to your Fireblocks account then connect your Fireblocks vault to Ethereum Staking Pool.

* You'll see a screen similar to the screenshot below:

<figure><img src="/files/ifT0YZ4D6i0IbbOKy44X" alt="" width="516"><figcaption><p>Illustration of connecting your Fireblocks vault to Ethereum Staking Pool.</p></figcaption></figure>

Click '**Connect vault**' and after some loading time has passed, this window will disappear and you will see something similar to the following in your Fireblocks dashboard.

<figure><img src="/files/9UsRMbX0yEs6AqIldUkp" alt="" width="563"><figcaption><p>You've successfully linked your Fireblocks account to Ethereum Staking Pool.</p></figcaption></figure>

Next, leave this window open and navigate back to the tab where you have Ethereum Staking Pool open in your browser.

Now you should see your wallet connected and you will be ready to stake using the Ethereum Staking Pool interface.

{% hint style="info" %}
When you finalize your transactions, you will need to sign via your Fireblocks app on your mobile device.
{% endhint %}

If you'd like a refresher on the staking steps for Ethereum Staking Pool, please see:

* How to stake with Ethereum Staking Pool

As you go through the staking process, you'll be able to check on the progress of the staking transactions via your Fireblocks account.

For example, you may see statuses such as:

```
Queued, Pending Signature, Confirming, Completed
```

Here's some examples of how this may look in your Fireblocks account.

![](/files/EiPz5vXQGVG7l5LKl3sV) ![](/files/7p5tY5GzNsSpbtdVxsjg)

{% hint style="success" %}
And you're all set!

You've successfully staked in Ethereum Staking Pool via your Fireblocks account.
{% endhint %}

***

### Option 2: Connecting via QR Code

First, open up your Fireblocks app on your mobile device and select the 'Scan' button. It can be seen just to the left of the gear icon, highlighted in the screenshot below.

* All transactions will be finalized and signed via your Fireblocks app on your mobile device.

<figure><img src="/files/dQP0w03AMxcPaf6FRL2D" alt="" width="375"><figcaption><p>Please select the button highlighted above to open the QR code scanner.</p></figcaption></figure>

{% hint style="info" %}
This will open up a scan function on your mobile device.

Use this to scan the WalletConnect QR code that is open in your browser.
{% endhint %}

Next, select the Fireblocks vault you wish to stake from.

<figure><img src="/files/SvEKEjYO1AGqOiteyfNT" alt="" width="375"><figcaption></figcaption></figure>

Once you've selected your vault, select '**Connect**'.

<figure><img src="/files/TBr7jRC9xunJjfLZWVAR" alt="" width="375"><figcaption><p>You can select a faster default fee, however, leaving it set to Medium is fine.</p></figcaption></figure>

You'll be prompted to confirm the connection. You can do so by pressing on '**Got it**'.

<figure><img src="/files/E2wxMib6nk5iVGOxWOBm" alt="" width="375"><figcaption><p>Final confirmation screen before processing the transaction.</p></figcaption></figure>

Now if you navigate back to Ethereum Staking Pool in your browser, you will be able to see your connected Fireblocks wallet.

You can proceed with staking as normal.

If you'd like a refresher on the staking steps for Ethereum Staking Pool, please see:

* How to stake with Ethereum Staking Pool

{% hint style="info" %}
As you go through the staking process, you'll be prompted to sign any transactions in your Fireblocks mobile app.

* Simply put, you'll initiate the staking transactions via Ethereum Staking Pool and sign them from your Fireblocks app.
  {% endhint %}

Here's a screenshot example shown below.

<figure><img src="/files/Vnhn7z2RpHZ38ygRxon0" alt="" width="375"><figcaption><p>Example of a transaction prompt from Ethereum Staking Pool in Fireblocks.</p></figcaption></figure>

Click on '**View**' to see the transaction details before you sign it.

<figure><img src="/files/weUWBiWjvSk5EwMI2itp" alt="" width="375"><figcaption><p>Here you can review the transaction before signing it.</p></figcaption></figure>

If all looks good, tap on '**Approve**' to sign and submit the transaction.

{% hint style="info" %}
You'll likely be prompted for your Fireblocks password or FaceID to approve the transaction.
{% endhint %}

After submitting it, you can view your Fireblocks dashboard from either your mobile or web browser interface to review your recent activity.

<figure><img src="/files/YuDrZgfH2HhKFGG0KC1M" alt="" width="563"><figcaption><p>Here you can review your recent activity.</p></figcaption></figure>

{% hint style="success" %}
And that's it!

You've successfully completed a transaction in Ethereum Staking Pool using Fireblocks in your mobile app.
{% endhint %}

***


# Ethereum Native Staking

Ethereum Proof-of-Stake processing of consensus and building a blockchain is enabled by validators who secure the network by proposing new blocks containing user transactions and attesting to blocks of other validators. For this work, validators are rewarded with ETH.

To create a validator, one needs to call deposit contract with transfer of a minimum amount of 32 ETH, bundling the transfer with a deposit dataset that includes the following:

* The validator's public key
* Withdrawal credentials
* The amount of ETH being deposited
* Network detail where validator will be running (Mainnet, Gnosis, etc)
* A signature proving ownership of the validator's private key

Chorus One Native Staking API for Ethereum provides functionality to generate this data on-demand. The Ethereum client instances corresponding to validators created with this API will be running in Chorus One infrastructure.

To start using API, read our [Integration Guide](/our-products/chorus-one-ethereum-native-staking/api-integration-guide) or jump straight to [API docs](https://native-staking.chorus.one/docs)


# API integration guide

## Staking

The **Native Staking API** aims to simplify the process of staking by providing a set of endpoints that users can use to generate the key material and the deposit data needed to stake on Ethereum.

The API documentation is available at [**API Reference**](https://native-staking.chorus.one/docs) and provides detailed information on the available endpoints and their usage.

### Authentication

Every API request requires authentication via a bearer token in the `X-API-TOKEN` header. Once requested through the [Support Request](https://support.chorus.one/hc/en-us/requests/new) page, our team will provide you with a unique token for your tenant. To obtain a token, please provide the below in the request:

* Tenant name
* Tenant description to Chorus One representative.

> **Important**: Store your API token securely. Lost tokens cannot be recovered by Chorus One, but we can generate new one upon request for you.

How to use the token in your requests:

```bash
curl --header "X-API-TOKEN: your-token-here" https://native-staking.chorus.one/...
```

### Integration

#### **1. Request a batch of validators with deposit data**

Pre-requisites:

* An authentication token received from Chorus One
* A withdrawal address that you control

> ⛔️ **Important**: Losing access to the withdrawal address will result in losing access to the staked funds.

The process of depositing validators managed by Chorus is shown on a diagram.

![Stake diagram](/files/GPza1LAspTMp0TQGlkju)

An example request to create a batch of 10 validators on the **Mainnet** network:

```http
export TOKEN="your token here"
export WITHDRAWAL_ADDRESS="your withdrawal address here"
export FEE_RECIPIENT_ADDRESS="your fee recipient address here"
export BATCH_ID="your batch id here"
curl https://native-staking.chorus.one/ethereum/mainnet/batches/new \
-H "X-API-TOKEN:$TOKEN" \
-H "Content-Type: application/json" \
-d '{"batch_id": "$BATCH_ID", "withdrawal_address": "$WITHDRAWAL_ADDRESS", "fee_recipient": "$FEE_RECIPIENT_ADDRESS", "number_of_validators": 10, "network": "mainnet"}'
```

> 📝 **Note**: Rate Limits & Quotas
>
> * Each tenant receives a specific summary validator quota, for the total number of validators that can be created across all batches. This is intended as a sanity check, to protect against rogue automation creating millions of validators.
> * Rate limiting prevents accidental quota exhaustion
> * Contact Chorus One representative for quota increases
> * Single batch request can not exceed 200 validators, if you need more, need to issue multiple batch requests

**What happens on the backend:**

* The request is validated and persisted in the database
* A separate process generates the key material and the `deposit_data` for every new batch of validators
* The `deposit_data` is saved in the database as it does not contain any sensitive information
* The key material is stored securely and will be used by the validators to perform their duties on the network

**What needs to happen on client** **side**:

* Once new batch request have been created, API will return UUID that represents particular validators batch in Chorus One backend. Client must save this UUID and use it in further requests that concern newly generated validators. `/batches` endpoint can be used to retrieve UUIDs for all past requests.

#### **2. Monitor status of the batch**

Pre-requisites:

* An authentication token
* Previously saved UUID of the batch

An example request to get the status of the batch:

```bash
export TOKEN="your token here"
export BATCH_ID="your batch id here"
export EPOCH="epoch number here" # optional, will be used to generate the signed exit message for the provided epoch.
# If not provided, the current epoch will be used.

curl https://native-staking.chorus.one/ethereum/mainnet/batches/$BATCH_ID?epoch=$EPOCH \
-H "X-API-TOKEN:$TOKEN"
```

**What happens on the backend:**

* The request is validated and the status of the batch is retrieved from the database
* If all `deposit_data` has been generated, the status will be `ready` and the response will include the `deposit_data` for each validator. The status of the validators will be `created` awaiting the be deposited.

Validator status field in API output will update as follows:

* Initially validators show status as `created` after `deposit_data` generation
* Once deposited, activated on the network and starting to receive rewards, validators will show status as `active`
* Exited validators will show status as `exited`

#### **3. Deposit the validators on the Ethereum network**

For this, the user needs to:

* Extract the `deposit_data` for each validator.

```js
const TOKEN = "your token here"
const BATCH_ID = "your batch id here"

const response = await fetch(`https://native-staking.chorus.one/ethereum/mainnet/batches/${BATCH_ID}`, {
  headers: {
    "X-API-TOKEN": TOKEN
  }
})
const json = await response.json()
// get all deposit_data from the response
const depositDataArray = json.validators.map(validator => validator.deposit_data);
```

* Use the `deposit_data` to deposit the validators on the Ethereum network:
  * using the the official [Ethereum Staking Launchpad](https://launchpad.ethereum.org/en/overview)

```js
// generate the `deposit_data-[timestamp].json` file
const fs = require('fs');
fs.writeFileSync(`deposit_data-${Date.now()}.json`, JSON.stringify(depositDataArray));
```

Upload the `deposit_data-[timestamp].json` file to the Ethereum Staking Launchpad and follow the instructions to complete the deposit.

* Using an audited batch deposit contract

#### Main risks and remediations:

* The withdrawal address must be secured and not treated as a hot wallet. Best practice is to use a multisig wallet contract for this purpose.
* The withdrawal address should be dedicated to the purpose of Ethereum staking.

## Unstaking

Once a validator has been deposited on the Ethereum network, it will start earning rewards. However, there are situations where the user might want to stop validating and withdraw the funds. The earlist time a validator can be withdrawn is after 256 epochs, which is approximately 27 hours after the validator has been activated.

To unstake a validator, the user needs to provide an exit message for the validator. The exit message is a signed message that proves the ownership of the validator and is used to withdraw the funds. The exit message is generated by the Native Staking API and can be requested by providing the batch ID and the epoch number for which the exit message is needed. Once the validator has been exited, the funds will be sent to the withdrawal address provided during the staking process.

The process of exiting validators managed by Chorus is shown on a diagram.

![Unstake diagram](/files/5fd5dYiCOOUNZkWK0X2b)

**Pre-requisites:**

* An authentication token
* Previously saved UUID of the batch
* An epoch number for which the exit message is needed (optional, if not provided, the current epoch will be used)
* Access to an Ethereum beacon node API that supports voluntary exit endpoint described [here](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit)

### Integration

1. Extract the `deposit_data` for each validator.

```js
const TOKEN = "your token here"
const BATCH_ID = "your batch id here"
const EXIT_EPOCH = "epoch number here" 

const response = await fetch(`https://native-staking.chorus.one/ethereum/mainnet/batches/${BATCH_ID}?epoch=${EXIT_EPOCH}`, {
  headers: {
    "X-API-TOKEN": TOKEN
  }
})
const json = await response.json()

const exitMessages = json.validators.map(validator => validator.exit_message);
```

2. Call the [voluntary\_exits](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit) endpoint of the Ethereum beacon node API to submit the exit message for the validator.

```js
 const BEACON_NODE_URL = "your beacon node url here"
 exitMessages.forEach(async exitMessage => {
   const response = await fetch(`${BEACON_NODE_URL}/eth/v1/beacon/pool/voluntary_exits`, {
     method: 'POST',
     headers: {
       'Content-Type': 'application/json'
     },
     body: JSON.stringify(exitMessage)
   })
   const json = await response.json()
   console.log(json)
 })
```

> Note📝 Exiting a validator takes time and it depends on the network conditions, such as the `churn limit` which is the maximum number of validators that can exit in a single epoch.

3. Monitor progress of validator exit by visiting the [Ethereum Beacon Chain Explorer](https://beaconcha.in/) and searching for the validator's public key, or using automated process that polls API of Ethereum beacon node for validator status progression.
4. Actual withdrawn funds will arrive to withdrawal address in few days after validator is exited.

#### Main risks and remediations:

* If someone gains access to your exit messages, they can force your validators to exit. While the funds will remain secure and will be sent to the withdrawal address, you risk losing potential staking rewards. This is significant because withdrawing existing validators and activating new ones is a time-consuming process.

## Further Reading:

* [Ethereum Staking Overview](https://ethereum.org/en/staking/)
* [Ethereum Staking Launchpad](https://launchpad.ethereum.org/en/overview)
* [Ethereum Rewards Overview](https://eth2book.info/capella/part2/incentives/rewards/)
* [Ethereum Rewards Deep Dive](https://hackmd.io/@potuz/HJGTPDz1n)


# Staking dApp

A ready-to-integrate, non-custodial staking dApp for institutions staking to their clients.

The staking dApp is a ready-to-integrate, non-custodial staking interface that institutions embed into their own products. Wallets, custodians, exchanges, and asset managers use it to give their clients access to staking across leading networks, without operating validators or building staking flows in-house.

For the end user the experience is simple: connect a wallet, choose an asset, and start earning rewards in a few clicks, with no custody hand-off. For the platform, integration is light: embed the dApp directly inside your app, or connect it over WalletConnect, with Bitwise engineering support from integration to launch.

It is also available as a standalone web app at [staking.chorus.one](https://staking.chorus.one/eth/stake).

<figure><img src="/files/ra7vXHC1W6ms6wsxOYW1" alt=""><figcaption><p>The staking dApp (test environment; all figures shown are test data)</p></figcaption></figure>

## Supported assets

The dApp currently supports staking for:

| Asset          | Network                | Delegation Location                                                                                                |
| -------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **ETH**        | Ethereum               | StakeWise V3 vault ([v3-core audits](https://github.com/stakewise/v3-core/tree/main/audits))                       |
| **SOL**        | Solana                 | Native staking ([Solana validator](https://solanabeach.io/validator/Chorus6Kis8tFHA7AowrPMcRJk3LbApHTYpgSNXzY5KE)) |
| **GRAM (TON)** | The Open Network (TON) | TON Pool ([ChorusOne/tonpool](https://github.com/ChorusOne/tonpool))                                               |

{% hint style="info" %}
The ETH and GRAM staking contracts are open source and independently audited; SOL uses native validator staking.
{% endhint %}

## Rewards, fees & timing

| Asset    | Reward rate (ARR) | Reward frequency                | Delegation time | Fee                       |
| -------- | ----------------- | ------------------------------- | --------------- | ------------------------- |
| **ETH**  | 2.62%             | Per epoch (\~6 min)             | Near-immediate  | 5% commission on rewards  |
| **SOL**  | 7.19%             | Per epoch (\~2–3 days)          | Up to 3 days    | 8% commission on rewards  |
| **GRAM** | 17.41%            | Per validation round (\~18 hrs) | Up to 18 hrs    | 20% commission on rewards |

On ETH, delegation is near-immediate: staking mints a share of the staking vault that begins accruing rewards right away, with no activation queue to wait through.

{% hint style="info" %}
Reward rates (ARR) are indicative and vary with network conditions. Figures shown are as of August 2026; live rates are always displayed in the dApp. Delegation time is how long after staking your position becomes active. Current network metrics are published at [onchain.bitwiseinvestments.com/staking](https://onchain.bitwiseinvestments.com/staking).
{% endhint %}

## Why integrate the staking dApp

### For your platform

* **Launch staking without building it.** Offer staking to your clients without operating validators or writing staking logic. The dApp handles transaction construction, signing, and broadcast, backed by institutional-grade infrastructure.
* **Two low-lift integration paths.** Embed the dApp directly inside your app, or connect it over WalletConnect, whichever suits your platform, with engineering support through integration and launch. See the [Integration guide](/our-products/staking-dapp/integration-guide).
* **Non-custodial by design.** Client transactions are signed in their own wallets and clear-signed for review, so signers see a human-readable view of exactly what they approve. The dApp never takes custody of client keys or assets.
* **Institutional-grade and secure.** Built on a validator stack securing billions in assets, with a non-custodial setup, ISO 27001 certification, and SOC 2 compliance.
* **One integration, multiple assets.** A single, consistent interface covers leading networks.
* **Reporting.** Detailed multi-network reporting for rewards, commissions, ARR, and CSV/Excel exports via the [Rewards Dashboard](/our-products/chorus-one-rewards).

### For your users

* **Stake in a few clicks.** Connect a wallet, choose an asset and amount, and approve in-wallet. No minimum on ETH; small minimums on SOL and GRAM.
* **Immediate rewards on ETH.** Depositing mints a share of the staking vault that starts earning right away, with no activation queue to wait through.
* **Bring your own wallet.** Use the wallet you already have, or stake straight from the platform's in-app wallet with automatic connection.
* **Transparent rewards.** Track staked balances and accrued rewards in real time in the dApp.

## How connecting works

There are two ways to use the dApp:

1. **Connect a wallet.** From the public web app, connect an injected wallet (MetaMask, Phantom, and others), WalletConnect, or a hardware wallet, then stake.
2. **Auto-connected wallet.** When the dApp is opened inside a supported host with an approved WalletProfile (for example an embedded wallet or custody platform), it connects to the active account automatically, with no wallet picker required. This is covered in the [Integration guide](/our-products/staking-dapp/integration-guide).

## Get started

* [**How to Stake**](/our-products/staking-dapp/how-to-stake): connect a wallet, choose an amount, and confirm the transaction.
* [**Unstaking & Withdrawing**](/our-products/staking-dapp/unstaking-and-withdrawing): unstake your position and withdraw your assets back to your wallet.
* [**Integration guide**](/our-products/staking-dapp/integration-guide): for partners who host the dApp inside their own wallet or custody platform.

{% hint style="info" %}
For institutional staking inquiries, contact the staking team at `StakingBOS@bitwiseinvestments.com`.
{% endhint %}


# How to Stake

How a staker connects a wallet, chooses an amount, and stakes.

Staking through the dApp takes three steps: the staker connects a wallet, enters an amount, and approves the transaction in their wallet. The flow is the same for ETH, SOL, and GRAM; only the wallet and network differ.

The dApp is at [staking.chorus.one](https://staking.chorus.one/eth/stake).

## Step 1: Connect a wallet

On the stake page, the staker selects **Connect Wallet** and chooses a wallet:

* For **ETH**, an Ethereum wallet (MetaMask, Phantom, WalletConnect, or a hardware wallet).
* For **SOL**, a Solana wallet.
* For **GRAM**, a TON-compatible wallet.

When the dApp runs inside a supported host with an approved WalletProfile (for example an embedded wallet or custody platform), it connects to the staker's active account automatically, skipping this step. See the [Integration guide](/our-products/staking-dapp/integration-guide) for details.

## Step 2: Enter the amount to stake

The staker selects the asset, enters the amount to stake, and reviews the details shown: estimated rewards and any network fees.

ETH has no minimum; SOL and GRAM have small minimum stake amounts, which the dApp displays before the staker confirms.

<figure><img src="/files/ra7vXHC1W6ms6wsxOYW1" alt=""><figcaption><p>The stake screen (test environment; all figures shown are test data)</p></figcaption></figure>

## Step 3: Approve the transaction

The staker selects **Stake** (or **Confirm and Stake**). Their wallet prompts them to review and sign the transaction; confirming it broadcasts the stake to the network.

Once the transaction is confirmed on-chain, the position is active and begins accruing rewards. The staker can review their staked balance and rewards in the dApp dashboard at any time.

For institutional stakers and platform partners, detailed multi-network reward reporting, historical data, and exports are available via the [Rewards Dashboard](/our-products/chorus-one-rewards).

{% hint style="success" %}
That completes a stake. For exiting a position later, see [Unstaking & Withdrawing](/our-products/staking-dapp/unstaking-and-withdrawing).
{% endhint %}

## Staking targets & audits

Each asset stakes to a published, verifiable target:

* **ETH: StakeWise V3 vault contracts.** Source and audit reports are published in the StakeWise V3 core repository: [github.com/stakewise/v3-core/audits](https://github.com/stakewise/v3-core/tree/main/audits).
* **SOL: native validator.** SOL is staked natively to our Solana validator, viewable on [Solana Beach](https://solanabeach.io/validator/Chorus6Kis8tFHA7AowrPMcRJk3LbApHTYpgSNXzY5KE).
* **GRAM: TON Pool.** Contract source and the 2025 Cantina audit report are published at [github.com/ChorusOne/tonpool](https://github.com/ChorusOne/tonpool).

{% hint style="info" %}
The live contract and validator addresses can also be verified against the **FAQ** section inside the dApp at [staking.chorus.one](https://staking.chorus.one/eth/stake) before interacting with them directly.
{% endhint %}


# Unstaking & Withdrawing

How a staker unstakes a position and withdraws ETH, SOL, or GRAM back to their wallet.

Unstaking returns a staker's assets to their wallet. It is a two-part process on every network: the staker first requests to unstake, then withdraws once the funds are available. As with staking, every transaction is signed in the staker's own wallet.

The dApp is at [staking.chorus.one](https://staking.chorus.one/eth/stake); the staker opens the dashboard for the asset they want to unstake.

## Step 1: Request unstake

The staker connects the wallet holding the staked position, selects the asset, and enters the amount to unstake. Selecting **Unstake** and approving the transaction in the wallet submits the request.

Depending on the network, the assets may enter a short exit or unbonding window before they can be withdrawn.

<figure><img src="/files/iHeZbDdHP153j8BJvH9S" alt=""><figcaption><p>Requesting an unstake (test environment; all figures shown are test data)</p></figcaption></figure>

Exit timing depends on each network's own unbonding/withdrawal mechanics and current conditions. As a guide:

| Asset    | Typical time to withdrawable                                                          |
| -------- | ------------------------------------------------------------------------------------- |
| **ETH**  | At least 24 hours, and up to the length of the network's active exit (unstake) queue. |
| **SOL**  | 2–3 days (one full epoch)                                                             |
| **GRAM** | Approximately 36 hours                                                                |

{% hint style="info" %}
The dApp shows the status of the request and when funds become available to withdraw.
{% endhint %}

## Step 2: Withdraw to the wallet

Once the unstake request has cleared and the funds are marked as available, the staker returns to the dApp, selects **Withdraw**, and approves the withdrawal transaction in the wallet.

The assets are then returned to the staker's connected wallet address.

{% hint style="success" %}
Once the withdrawal transaction confirms on-chain, the assets are back in the staker's wallet.
{% endhint %}

## Notes

* A staker can unstake any portion of a position; the full amount does not have to be exited at once.
* Rewards accrued up to the point of unstaking are included in the balance.
* When the dApp runs inside a supported host with an approved WalletProfile, the unstake and withdraw prompts are handled by the host's own signing UI. See the [Integration guide](/our-products/staking-dapp/integration-guide).


# Integration guide

How partners embed the staking dApp in their own product using an approved WalletProfile.

Partners can embed the Chorus One staking dApp directly inside their own product, such as a wallet, an institutional custody platform, or another host application, so their users stake without leaving that product. This is the **embedded dApp experience**: your app opens the standard staking dApp, makes the agreed wallet connection available to it, and an approved **WalletProfile** tailors how the dApp behaves for your integration.

This page explains how an embedded integration is activated and what it can configure. Before launch, work through [Validate and Deploy](/our-products/staking-dapp/integration-guide/validate-and-deploy).

{% hint style="info" %}
To discuss an embedded integration for your wallet or custody platform, contact the staking team at `StakingBOS@bitwiseinvestments.com`.
{% endhint %}

## Integration model

The embedded dApp experience supports two methods:

* **WebView (standard).** Your app opens the staking dApp at its normal URL in a full in-app view and makes the agreed wallet connection available to the page. This is the preferred method.
* **iframe (by exception).** Embedding the dApp inside a child frame is a non-preferred method and is assessed separately. It requires an approved wallet connection inside the child frame, an appropriate `frame-ancestors` policy, and joint testing for storage, permissions, sizing, and lifecycle behaviour. There is no generic iframe bridge or SDK.

In both methods the user keeps custody of their keys and approves every transaction in their own wallet.

## Activating an integration

An embedded integration is activated with an approved **WalletProfile**, passed as a parameter on the dApp URL:

```
https://staking.chorus.one/<application>/<action>?walletProfile=<profile-id>
```

`<application>` must be an approved application, such as `eth` or `sol`. The dApp rejects unknown, disabled, or application-incompatible profile IDs.

The selected profile is retained for that application across navigation and reloads within the same WebView. This persistence identifies the intended dApp experience; it does not persist a provider object or restore a wallet account on its own.

{% hint style="warning" %}
Do not expose profile IDs as an end-user setting. Chorus One supplies the approved entry URL during onboarding.
{% endhint %}

## What you can configure

A WalletProfile controls how the dApp behaves for your integration:

| Area              | Options                                                                                                             |
| ----------------- | ------------------------------------------------------------------------------------------------------------------- |
| Application scope | Restrict the profile to approved applications and, where agreed, actions.                                           |
| Wallet selection  | Use the public list; allowlist wallets; place one wallet first; or require one wallet exclusively.                  |
| Connection        | Manual connection, normal wallet-session restoration, or one approved eager connection attempt on page load.        |
| Wallet controls   | Independently enable or disable: wallet picker, wallet change, disconnect, address copy, and EVM network switching. |
| Staking target    | Allow normal target selection or use an approved fixed target.                                                      |
| Attribution       | Apply an approved partner attribution value where supported by the staking flow.                                    |

The dApp validates a profile before use: it must use known applications and wallet implementations; exclusive selection must name exactly one wallet; a preferred wallet must be included in the allowed list; and eager connection requires an approved wallet implementation.

## Connection and signing behaviour

The wallet remains the signing authority in every integration. The profile determines how the dApp connects:

* **Manual** waits for a user connection action.
* **Restore** uses the wallet library's normal persisted-session behaviour.
* **Eager** makes one connection attempt on page load; the dApp does not poll or retry. The host should ensure its provider is ready before the dApp's scripts run.

The dApp rediscovers injected wallet connections on each page load; it does not store injected provider objects.

For EVM integrations, the wallet should return EVM accounts for EVM account requests. Where an approved integration supports mixed account responses, the dApp may ignore non-EVM accounts and require the user to select an EVM account; the same filter applies to account-change events.

The profile does not change transaction construction, signing semantics, submission logic, or sponsorship.


# Validate and Deploy

What your integration must do, and how to validate it before launching an embedded staking dApp.

Use this checklist to build and validate an embedded staking dApp integration before launch. It complements the [Integration guide](/our-products/staking-dapp/integration-guide), which covers the integration model and WalletProfile configuration.

## Partner responsibilities

Before loading the dApp, your integration must:

1. Open the approved URL for the approved application and action.
2. Make the agreed wallet connection available in the WebView before, or around, initial dApp hydration.
3. Keep the account and network state accurate for the wallet connection.
4. Present wallet approval prompts and require the user to approve each transaction.
5. Test the integration in the target wallet environment before launch.

For EVM integrations, the wallet should return EVM accounts for EVM account requests. Where an approved integration supports mixed account responses, non-EVM accounts may be ignored and the user asked to select an EVM account.

## Validation and acceptance testing

Complete the following before launch:

1. Confirm the supplied profile URL selects the intended application and wallet experience.
2. Confirm the provider is available on first load and after a reload.
3. Confirm the allowed wallet list and every enabled wallet control match the agreed configuration.
4. Connect, stake, unstake, and withdraw using the target wallet environment.
5. Confirm the wallet displays the expected signing prompt and the dApp reports transaction status correctly.
6. Reload after activation and confirm the intended profile remains active.
7. For EVM, test account changes, network changes where enabled, and non-EVM-account handling where relevant.

{% hint style="info" %}
For help preparing or validating an integration, contact the staking team at `StakingBOS@bitwiseinvestments.com`.
{% endhint %}


# Rewards

Multi-network staking rewards reporting made simple.

**Overview**

The Chorus One Rewards is a powerful tool designed to simplify staking rewards reporting across 20+ blockchain networks. It provides granular, accurate, and multi-format data tailored for all kinds of institutions including Asset Management Firms, Custodians, Wallets, Exchanges etc. It is available as a fully functional UI where you can log-in and view your reports. In addition to that, Chorus One Rewards API can be used to integrate reporting capabilities into your own infrastructure.

#### **Who is it for?**

Chorus One Rewards is built for Finance Managers and Product Operations teams handling staking reconciliations, reporting, and audits. It is ideal for institutions looking for accurate and granular reporting.

{% hint style="info" %}

#### **Can users see a demo of the platform?**

Yes. Please contact your Chorus One representative for details or email us at <supportBOS@bitwiseinvestments.com> or <StakingBOS@bitwiseinvestments.com>.
{% endhint %}

***

## **Features and Capabilities**

Chorus One Rewards offers many benefits for users, allowing it to stand out as a unique accounting and reporting solution.

* Supports 20+ blockchain networks, including Ethereum, Solana, and Celestia.
* Provides daily reports with historical stake, ARR, commissions, and transaction events.
* Includes point-in-time USD values and an aggregate view of stake across chains.
* Features a simple, user-friendly interface and one-click Excel downloads.
* Easy integration using API

#### **What type of data does it provide?**

* Historical rewards and stake
* Transaction events (such as Delegate, Undelegate, Claim Rewards etc.)
* Daily (annualized) ARR
* Aggregated and chain-specific staking data.

#### **Will there be an API?**

Yes, reporting APIs are available to enable automated integrations for reconciliation and reporting.

#### **Can I export the data?**

Yes, we support data exports to to CSV and Excel formats, allowing you to filter by address, month, and more.

#### **Does the platform only support Chorus One delegators?**

Currently, yes! However, in the future, we will support any address, regardless of whether it’s staked with Chorus One or other validators.

#### **Is the data layout customizable?**

Yes, you can choose which columns to display and sort the data by date, amounts etc. as per your needs.

***

## **Usage and Scalability**

#### **How many addresses can I monitor using Chorus One Rewards?**

The platform is designed to scale, supporting hundreds of addresses.

{% hint style="info" %}
Right now it supports only the addresses that delegate to Chorus One but in the future your delegations to other validators will be enabled.
{% endhint %}

#### Does it support historical data?

Chorus One Rewards supports historical stake, rewards and transaction data. We have imposed the start date as of January 1st, 2024.

* In case, you need older snapshots, just let us know!

#### **Can I segregate rewards by activity type?**

At the moment, DeFi rewards are not visible. However, we are working towards showing rewards segregated by different types, including by MEV (e.g. on Ethereum) rewards.

#### **How accurate is the data provided?**

We employ multiple layers of data validation to ensure high data quality and accuracy.

#### **What is the pricing structure?**

If you stake with Chorus One, you automatically get access to Chorus One Rewards.

***

## Access Details

### **How to Login**

{% stepper %}
{% step %}
Share with us the email you would like to whitelist.
{% endstep %}

{% step %}
Login with that email.
{% endstep %}

{% step %}
You’ll receive a magic link.
{% endstep %}

{% step %}
You’re ready to log in!
{% endstep %}
{% endstepper %}

### Troubleshooting

<details>

<summary>How long is the link valid for?</summary>

The magic link will be valid for 72 hours.

However, once you login you will stay logged in even beyond 72 hours.

</details>

<details>

<summary>What do I do if I have questions?</summary>

Please reach out to us over Slack or email. We are always happy to help!

* Either contact your dedicated Chorus One representative or email us at <StakingBOS@bitwiseinvestments.com>

</details>

<details>

<summary>How do I report a bug?</summary>

Please reach out to your dedicated contact at Chorus One or reach out to us on Slack or via email at <StakingBOS@bitwiseinvestments.com>

</details>

## Network Coverage

### **Currently Supported Networks**

* Akash
* Aleo
* Axelar
* Celestia
* Cosmos
* dYdX
* Ethereum (Stakewise)
* Injective
* Oasis
* Osmosis
* Persistence
* Seda
* Sei
* Solana
* Ton

### Upcoming Networks

* Avalanche
* Polygon

***

## Further Questions?

For additional support, please contact your Chorus One representative or email us at <supportBOS@bitwiseinvestments.com> or <StakingBOS@bitwiseinvestments.com>

<details>

<summary>About Chorus One</summary>

Chorus One is one of the largest institutional staking providers globally, operating infrastructure for over 60 Proof-of-Stake (PoS) networks, including Ethereum, Cosmos, Solana, Avalanche, Near, and others.

Since 2018, we have been at the forefront of the PoS industry, offering easy-to-use, enterprise-grade staking solutions, conducting industry-leading research, and investing in innovative protocols through Chorus One Ventures.

As an ISO 27001 certified provider, Chorus One also offers slashing and double-signing insurance to its institutional clients. For more information, visit [chorus.one](https://chorus.one/) or follow us on [LinkedIn](https://www.linkedin.com/company/chorus-one/), [X (formerly Twitter)](https://twitter.com/ChorusOne), and [Telegram](https://t.me/chorusone).

</details>


# Widget

The Chorus One Widget is a ready to integrate product built on iFrame that can be easily embed into existing website or app, allowing the end users to connect wallet and start earning rewards with Chorus One.

The Widget is built for platforms that want to do more than just offer staking — it’s designed to deliver **trusted, institutional-grade staking and rewards** with a seamless user experience. Whether you are a wallet, custodian, asset management or trading platform, the widget gives you the tools to engage users, grow loyalty, and unlock monetization — all backed by one of the most established validators in the industry.

Unlike generic earn widgets, the Chorus One Widget combines **deep protocol expertise** with a **fully customizable interface**, allowing partners to offer staking solutions that align perfectly with their brand and user base.

With the Chorus One Widget, platforms can:

* **Launch staking without code**: Deliver new staking services instantly, without diverting engineering resources.
* **Integrate flexibly**: Deploy as a branded standalone dApp or embed seamlessly into existing web or mobile applications.
* **Offer a complete staking journey**: From discovering staking opportunities to connecting wallets, depositing assets and monitoring detailed, real-time reward analytics — all in one consistent, transparent experience.
* **Leverage proven security & credibility**: Chorus One secures billions in assets and partners with leading institutions — providing confidence and reliability your users can trust.

By partnering with Chorus One, platforms don’t just add staking — they gain access to **world-class infrastructure, deep ecosystem relationships, and the assurance of a specialist who has been at the forefront of staking since day one.**

### The Chorus One Widget Advantages

#### **Branded Staking Experience**

Use the Chorus One Widget Builder to fully align the staking interface with your brand. Apply your own colors, fonts, and logos to deliver a seamless, on-brand user experience.

#### Broad Compatibility

With support for multiple networks and a wide range of wallets, the Chorus One Widget unlocks diverse staking and yield options — giving your users seamless access to the best earning opportunities in one unified interface.

#### **Low/No-Code Integration**

Integrate staking functionality quickly, even without a dedicated engineering team. The Chorus One Widget is lightweight, framework-agnostic, and can be embedded into any platform — from enterprise systems to no-code tools.

{% hint style="info" %}
***Currently Supported Networks Through Widget:***

* *Ethereum*
* *Solana*
* *TON*
* *USDC (Coming Soon)*
* *Monad*
* *Akash*
* *Atom*
* *Axelar*
* *Band*
* *Celestia*
* *dYdX*
* *Kava*
* *Sei*
  {% endhint %}


# Customize and Deploy

**Tailor the staking experience to your brand.** The Chorus One Widget Builder lets you seamlessly apply your own design elements, colors, and style, so the earn section feels fully native to your platform and delivers a consistent, branded user journey.

### Access the Widget Builder

The Chorus One Widget Builder can be easily accessed at [widget.chorus.one](https://widget.chorus.one/)

### Customize

The left sidebar provides all customization options. Changes are applied in real time so you can preview how the Chorus One Widget will appear within your application.

**Accent Color**

* Customize the accent to match with your brand’s primary color.
* Color tones can be adjusted directly through a palette, enter a HEX value or RGB values

**Brand Logo**

* Displaying your own logo by updating the URL.
* Default: Leave the URL field empty to display no logo.

**Networks:**

* Select the desired networks you want to offer in your platform
* Default: All available networks will be shown to users

**Referrer Code (optional):**

* Enter an identifier to track reference across all networks

### Deploy with 1-Line Code

{% hint style="warning" %}
Prerequisite: Please contact Chorus One team at <StakingBOS@bitwiseinvestments.com> to whitelist your domain.
{% endhint %}

After customizing the widget to match your branding, you can simply copy the intergration code into your platform by embedding the widget URL inside an `<iframe>`. The widget is framework-agnostic and works seamlessly across any tech stack, including no-code platforms.

```
<iframe 
  src="https://widget-staging.chorus.one/eth/stake?primaryColor=%232a2d2d&bgColor=%23FFFFFF&textColor=%23000000"
  width="600" 
  height="900" 
  frameborder="0"
></iframe>
```


# Avalanche


# Overview

{% hint style="info" %}
The Avalanche blockchain, renowned for its rapid transaction processing, low fees, and eco-friendly architecture, utilizes a unique consensus protocol known as Avalanche Consensus. This protocol enables a high degree of decentralization and security, allowing validators to participate by staking AVAX, the network's native token.
{% endhint %}

Staking on the Avalanche network (AVAX) involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

The **Chorus One SDK** simplifies this process, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Avalanche using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Avalanche libraries such as `@avalabs/avalanchejs`. This compatibility ensures that you can seamlessly integrate these methods into your existing Avalanche projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on the Avalanche network using the Chorus One SDK, you will first need to initialize the SDK.

First, create an instance of the `AvalancheStaker` with the following configuration:

```javascript
import { AvalancheStaker } from '@chorus-one/avalanche'

const staker = new AvalancheStaker({
  rpcUrl: 'https://api.avax.network'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the Avalanche network RPC endpoint.

***

## Initializing the Staker

After configuring the `AvalancheStaker`, you can initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `AvalancheStaker` method provides the ability to build transactions for staking and transfer of AVAX tokens.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/avalanche/methods) section.

**Example of building a staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'P-fuji10uzff2f0u8hstlr5ywt2x4lactmn28c5y9uddv',
  validatorAddress: 'NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg',
  amount: '1' // 1 AVAX
})
```

***

## Getting the Validator Address provided by Chorus One

The `@chorus-one/avalanche` module includes a list of Chorus One validators for the Avalanche network.

You can use these addresses when building staking transactions.

```javascript
import { CHORUS_ONE_AVALANCHE_VALIDATORS } from '@chorus-one/avalanche'

const validatorAddress = CHORUS_ONE_AVALANCHE_VALIDATORS[0]
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Avalanche network.

To set up Fireblocks, you will need to provide the necessary API key, secret key, and vault ID:

```javascript
import { AvalancheStaker } from '@chorus-one/Avalanche'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'AVAXTEST',
  addressDerivationFn: AvalancheStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xe34600026d96051Cf9b8b9f3e2f51f1f3f3f3f3f',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txId } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txId, chain: 'P' })

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Avalanche network using the Avalanche Fuji testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods for `AvalancheStaker`, continue to the [Methods](/build-your-staking-dapp/avalanche/methods) section.

## Further Reading

* [AvalancheStaker API Reference](/api-reference/stakers/avalanche_src.avalanchestaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)

```
```


# Methods

This section provides an overview of the key methods available in the **Chorus One Avalanche Network SDK** for staking and transferring assets.

The Chorus One SDK supports various staking operations and inter-chain asset transfers. Below, we explore each method with practical examples to help you get started.

## buildStakeTx

### Description

The `buildStakeTx` method allows you to create a transaction for staking AVAX tokens with a validator.

Staking tokens involves locking them up to support the network's security and operations, and in return, you earn rewards.

### How to Use

To build a staking transaction, you will need to specify the amount to stake, the number of days for stake to be active, the delegator's address (your wallet), and the validator's address where you want to stake your AVAX tokens.

### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'P-avax10uzff2f0u8hstlr5ywt2x4lactmn28c5y9uddv',
  validatorAddress: 'NodeID-LkDLSLrAW1E7Sga1zng17L1AqrtkyWTGg',
  amount: '1', // 1 AVAX
  daysCount: 30 // Stake for 30 days
})
```

In this example, we're staking 1 AVAX with the specified validator for 30 days.

* [Read more in the API Reference](/api-reference/stakers/avalanche_src.avalanchestaker#buildstaketx)

***

## buildExportTx

### Description

The `buildExportTx` method helps you create a transaction to export assets to another Avalanche subnetwork.

This is the initial step in transferring tokens from one Avalanche subnetwork to another.

After issuing this export transaction, you will need to call `buildImportTx` on the destination subnetwork to complete the transfer.

### How to Use

To build an export transaction, you need to specify the source address (the address on the subnetwork from which the assets are being exported), the destination address (the address on the subnetwork to which the assets are being exported), and the amount to export.

### Example

```javascript
const addressSet = publicKeyToAddress(publicKey, 'avax')

const { tx } = await staker.buildExportTx({
  address: addressSet,
  srcChain: 'C',
  dstChain: 'P',
  amount: '1' // 1 AVAX
})
```

In the above example, we are exporting 1 AVAX from a specified source address on one subnetwork to a destination address on another subnetwork within the Avalanche network.

* [Read more in the API Reference](/api-reference/stakers/avalanche_src.avalanchestaker#buildexporttx)

***

## buildImportTx

### Description

The `buildImportTx` method allows you to create a transaction to import assets from another Avalanche subnetwork.

This method finalizes the transfer of tokens that were initially exported from a different subnetwork.

### How to Use

To build an import transaction, you need to specify the source address (the address on the subnetwork from which the assets are being imported) and the destination address (the address on the subnetwork to which the assets are being imported).

Typically, these addresses will be different to reflect the different subnetworks involved.

### Example

```javascript
const addressSet = publicKeyToAddress(publicKey, 'avax')

const { tx } = await staker.buildImportTx({
  address: addressSet,
  srcChain: 'C',
  dstChain: 'P'
})
```

In this example, we are importing AVAX from a specified source address on one subnetwork to a destination address on another subnetwork within the Avalanche network.

* [Read more in the API Reference](/api-reference/stakers/avalanche_src.avalanchestaker#buildimporttx)

***

## getStake

### Description

The `getStake` method retrieves the staking information for a specified delegator, including the amount of AVAX tokens currently staked with a specified validator.

### How to Use

To get staking information, you will need to provide the delegator's address (your wallet).

### Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: 'P-avax10uzff2f0u8hstlr5ywt2x4lactmn28c5y9uddv'
})
console.log(`Staked balance: ${balance}`)
```

In this example, we are retrieving the staked balance for a specified delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/avalanche_src.avalanchestaker#getstake)

***

## Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [AvalancheStaker API Reference](/api-reference/stakers/avalanche_src.avalanchestaker)

***

This guide aims to simplify the process of using the Chorus One Avalanche network SDK for staking and transferring assets.

* Please follow the provided examples to integrate these functionalities into your applications.


# Cosmos


# Overview

Staking on the Cosmos network involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The Cosmos network, renowned for its interoperability and modular framework, utilizes the Tendermint BFT consensus engine, enabling a diverse range of validators to secure the network and process transactions efficiently. This structure supports the seamless connection of various independent blockchains, allowing them to communicate and share data while maintaining their autonomy.
{% endhint %}

The **Chorus One SDK** simplifies this process, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Cosmos using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Cosmos libraries such as `@cosmjs/cosmwasm`. This compatibility ensures that you can seamlessly integrate these methods into your existing Cosmos projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on the Cosmos network using the Chorus One SDK, you will first need to initialize the SDK for Cosmos.

* **Note:** For testing purposes, we will use the Celestia testnet.

First, create an instance of `CosmosStaker` with the necessary configuration:

```javascript
import { CosmosStaker } from '@chorus-one/cosmos'

const staker = new CosmosStaker({
  rpcUrl: 'http://public-celestia-mocha4-consensus.numia.xyz',
  lcdUrl: 'https://api.celestia-mocha.com',
  bechPrefix: 'celestia',
  denom: 'utia',
  denomMultiplier: '1000000',
  gas: 250000,
  gasPrice: '0.4'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the Cosmos network RPC endpoint. This is where the SDK will connect to interact with the network. In this example, we are using a public endpoint for the Celestia testnet.
* **lcdUrl**: The URL of the Cosmos network LCD endpoint. This is where the SDK will connect to query the network for information such as account balances and transaction status.
* **bechPrefix**: The Bech32 prefix for addresses on the network. For Cosmos mainnet this would be `"cosmos"`, and for the Celestia testnet it is `"celestia"`
* **denom**: The denomination of the token used on the network. For the Celestia testnet, we use the micro-units of the native token - `"utia"`
* **denomMultiplier**: This parameter defines the scaling factor used to convert from the smallest unit of the network’s currency (`utia`) to its base unit (`TIA`).

  For the Celestia testnet, `1 TIA` is equal to `1,000,000 utia`, hence the multiplier is `1,000,000`. This value is used to convert the amount of tokens in transactions.
* **gas**: The maximum amount of gas to use for transactions. This value can be adjusted based on the complexity of the transactions.
* **gasPrice**: The price of gas in the **denom**(i.e `utia`) token of the network. This value determines the cost of executing transactions. The resulting maximum fee is calculated as `gas * gasPrice`.

  For determining the gas price, refer to the network's [chain registry](https://github.com/cosmos/chain-registry).
* **isEVM**: (Optional) A boolean flag indicating whether the network is an EVM-based chain. This is set to `false` by default.

## Initializing the Staker

After configuring the `CosmosStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `CosmosStaker` class provides methods to build transactions for staking, unstaking, redelegating, and withdrawing rewards.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/cosmos/methods) section.

**Example of building a staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'celestia1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'celestiavaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707',
  amount: '1' // 1 TIA
})
```

***

## Getting the Validator Address provided by Chorus One

The `@chorus-one/cosmos` module includes a list of Chorus One validators for the Cosmos networks, organized by bech32 prefixes. You can use these addresses when building transactions.

```javascript
import { CHORUS_ONE_COSMOS_VALIDATORS } from '@chorus-one/cosmos'

const validatorAddress = CHORUS_ONE_COSMOS_VALIDATORS.COSMOS
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const rawTx = await yourSigningClient.sign('celestia1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p', [tx], fee, 'Stake 1 TIA')

const signedTx = TxRaw.encode(rawTx).finish()
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

For detailed information on setting up and configuring these options, refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Cosmos network. To set up Fireblocks, provide the necessary API key, secret key, and vault ID:

```javascript
import { CosmosStaker } from '@chorus-one/cosmos'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'CELESTIA_TEST',
  addressDerivationFn: CosmosStaker.getAddressDerivationFn({
    bechPrefix: 'celestia'
  })
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: 'celestia1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  tx,
  memo: 'Staking 1 TIA'
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

***

## Auto-Generating a CosmosStaker Configuration

As we've previously covered, to initiate `CosmosStaker` you must first provide some basic data about the denomination, gas amount, and gas price.

However, in the Cosmos ecosystem, many of the networks don't have a market based gas pricing system such as Ethereum.

Instead, the user must calculate a fee with gas prices set as equal to or higher than what the network operators have set.

**This leaves the question:** *"How do you know what the current gas price is?"*

This can be tricky to determine, so members of the Cosmos community came up with [Chain Registry](https://github.com/cosmos/chain-registry/tree/master), which holds the most up to date data on the current network gas prices.

For your convenience, we have provided a `CosmosConfigurator` class which generates a network configuration based on the data from Chain Registry.

**An example of this can be seen below:**

```javascript
import { CosmosConfigurator, CosmosStaker } from '@chorus-one/cosmos'

const networkConfig = await CosmosConfigurator.genNetworkConfig('celestia')

const staker = new CosmosStaker({
  ...networkConfig
})
```

{% hint style="info" %}
Please note that [Chain Registry](https://github.com/cosmos/chain-registry/tree/master) is a community based repository.

While the data there is usually correct, there is a risk of inaccuracies. Therefore it is recommended that you verify the network configuration prior using it.

For instance you can check if the default fee `(gas * gasPrice)` does not exceed expected bounds.
{% endhint %}

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Cosmos network using the Celestia testnet, which included how to build staking transactions, sign, and broadcast them.

* To learn more about the available methods on `CosmosStaker` continue to the [Methods](/build-your-staking-dapp/cosmos/methods) section.

## Further Reading

* [CosmosStaker API Reference](/api-reference/stakers/cosmos_src.cosmosstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the Cosmos network.

The SDK supports a range of staking operations including staking, unstaking, redelegating, and withdrawing rewards. Below, we explore each method with practical examples to help you get started.

### buildStakeTx

#### Description

The `buildStakeTx` method helps you create a transaction for staking tokens with a validator. Staking tokens involves locking them up to support the network's security and operations, and in return you earn rewards.

#### How to Use

To build a staking transaction, you need to specify the amount to stake, the delegator's address (your wallet), and the validator's address where you want to stake your tokens.

#### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707',
  amount: '1' // 1 ATOM
})
```

In this example, we're staking 1 ATOM with a specified validator.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#buildstaketx)

***

### buildUnstakeTx

#### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator.

Unstaking involves withdrawing your staked tokens, during which they enter an unbonding period. On the Cosmos network, the unbonding period typically lasts 21 days, during which your tokens are not earning rewards and cannot be transferred.

After the unbonding period, the tokens become available in your wallet.

#### How to Use

To build an unstaking transaction, you need to provide the amount to unstake, the delegator's address, and the validator's address from where you want to withdraw your tokens.

#### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707',
  amount: '1' // 1 ATOM
})
```

Here, we're unstaking 1 ATOM from a specified validator.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#buildunstaketx)

***

### buildRedelegateTx

#### Description

The `buildRedelegateTx` method helps you create a transaction for redelegating tokens from one validator to another.

This is useful if you want to move your staked tokens to a different validator instantly instead of unstaking, waiting for the unbonding period to complete, then staking them with a different validator.

#### How to Use

To build a redelegation transaction, you need to specify the amount to redelegate, the delegator's address, the source validator's address, and the destination validator's address.

#### Example

```javascript
const { tx } = await staker.buildRedelegateTx({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorSrcAddress: 'cosmosvaloper1tnrq6ahy4g6g3foc5g3dgdj0sdfurfd5f4vz5e',
  validatorDstAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707',
  amount: '1' // 1 ATOM
})
```

In this example, we're moving 1 ATOM from one validator to another.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#buildredelegatetx)

***

### buildWithdrawRewardsTx

#### Description

The `buildWithdrawRewardsTx` method allows you to create a transaction for withdrawing staking rewards from a validator.

Staking rewards accumulate over time and you can withdraw them periodically.

#### How to Use

To build a rewards withdrawal transaction, you need to provide the delegator's address and the validator's address that you want to withdraw your rewards from.

#### Example

```javascript
const { tx } = await staker.buildWithdrawRewardsTx({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707'
})
```

Here, we're withdrawing rewards from a specified validator.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#buildwithdrawrewardstx)

***

### getStake

#### Description

The `getStake` method retrieves the staking information from a delegator.

* This includes the amount of tokens currently staked with a validator.

#### How to Use

To get staking information, you need to provide the delegator's address (your wallet), and optionally the validator's address. If the validator's address is not provided, the method returns rewards from all validators.

#### Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707'
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#getstake)

***

### getRewards

#### Description

The `getRewards` method fetches the rewards data accumulated for a delegator.

This shows the total rewards earned from staking with a specific validator.

#### How to Use

To get rewards data, you need to provide the delegator's (your wallet) address and optionally the validator's address. If the validator's address is not provided, the method returns rewards from all validators.

You can also specify denom to get rewards for a specific token, and denomMultiplier to get rewards in a specific format.

#### Example

```javascript
const { rewards } = await staker.getRewards({
  delegatorAddress: 'cosmos1x88j7vp2xnw3zec8ur3g4waxycyz7m0mahdv3p',
  validatorAddress: 'cosmosvaloper15urq2dtp9qce4fyc85m6upwm9xul3049e02707'
})
console.log(`Rewards: ${rewards}`)
```

Here, we're fetching the rewards earned by a delegator from a specific validator.

* [Read more in the API Reference](/api-reference/stakers/cosmos_src.cosmosstaker#getrewards)

***

### Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [CosmosStaker API Reference](/api-reference/stakers/cosmos_src.cosmosstaker)


# Ethereum


# Overview

Staking on the Ethereum network involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The Ethereum blockchain, renowned for its smart contract functionality and vibrant ecosystem, employs the Proof of Stake (PoS) consensus mechanism in its Ethereum 2.0 upgrade. This transition enhances scalability, security, and energy efficiency. By staking ETH, Ethereum's native token, validators maintain the network, secure the blockchain, and incentivize active participation, ensuring the network remains robust and efficient.
{% endhint %}

The **Chorus One SDK** simplifies the staking process on the Ethereum network, providing developers with the tools needed to build, sign, and broadcast staking transactions.

## Pick the Pool Technology

Before you start developing your staking application, you need to decide which pool technology you want to use. We recommend the Pooled Staking for most use cases, as it is easy to start using with no minimum ETH to stake. For large delegators, we support Native Staking as well through our SDK.

|                    | [Pooled Staking](/build-your-staking-dapp/ethereum/pooled_staking_overview) | [Native Staking](/build-your-staking-dapp/ethereum/native_staking_overview) |
| ------------------ | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Best for           | Most use cases                                                              | Large delegators                                                            |
| Delegators         | Unlimited                                                                   | 200 / batch                                                                 |
| Minimal Stake      | None                                                                        | 32 ETH per validator                                                        |
| Partial Withdrawal | ✅                                                                           | ❌ Must withdraw all funds                                                   |

Once you have chosen the pool technology, continue with the respective guide.

* [Pooled Staking Guide](/build-your-staking-dapp/ethereum/pooled_staking_overview)
* [Natie Staking](/build-your-staking-dapp/ethereum/native_staking_overview)


# Pooled Staking Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the Ethereum network.

The Chorus One SDK supports a range of staking operations including staking, unstaking, and withdrawing rewards. Below, we explore each method with practical examples to help you get started.

### buildStakeTx

#### Description

The `buildStakeTx` method helps you create a transaction for staking tokens with a validator on the Ethereum network. Staking tokens involves locking them up to support the network's security and operations, and in return, you earn rewards.

#### How to Use

To build a staking transaction, you need to specify the amount to stake, the delegator's address (your wallet), and the validator's address where you want to stake your tokens. Optionally, you can also specify a referrer address for tracking purposes.

{% hint style="info" %}
For more information on tracking and attributing staking transactions to specific sources, such as marketing campaigns or integration partners, refer to the [Delegation Tracking](/build-your-staking-dapp/ethereum/delegation-tracking) section.
{% endhint %}

#### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1', // 1 ETH
  referrer: '0xReferrerAddressHere' // Unique Ethereum address for tracking
})
```

In this example, we're staking 1 ETH with a specified validator.

***

### buildUnstakeTx

#### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator on the Ethereum network.

The unstake transaction effectively moves the user's assets into an unstake\
queue where they remain until they become eligible for withdrawal. This queue is\
a safeguard mechanism that ensures the liquidity and stability of the vault by\
managing the flow of assets. To check the status of these assets, use the`getUnstakeQueue` method.

{% hint style="warning" %}
To unstake your entire ETH amount, you may need to burn your osETH tokens first. Burning osETH reclaims the underlying staked ETH.
{% endhint %}

#### How to Use

To build an unstaking transaction, you need to provide the amount to unstake, the delegator's address, and the validator's address from where you want to withdraw your tokens.

#### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1' // 1 ETH
})
```

Here, we're unstaking 1 ETH from a specified validator.

***

### buildWithdrawTx

#### Description

The `buildWithdrawTx` method allows you to create a transaction for withdrawing your tokens that have been unstaked and are now eligible for withdrawal from the unstake queue.

This method is the final step in the unstaking process. Once assets in the\
unstake queue have reached a withdrawable state (as determined by the`getUnstakeQueue` method), the `buildWithdrawTx` method prepares the transaction\
data necessary for transferring these assets back into the user's wallet.

#### How to Use

To build a withdrawal transaction, you need to provide the delegator's address and the validator's address from where you want to withdraw your tokens. Optionally, you can specify position tickets if you want to withdraw specific assets.

#### Example

```javascript
const { tx } = await staker.buildWithdrawTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
```

Here, we're withdrawing assets from a specified validator.

***

### buildMintTx

#### Description

The `buildMintTx` method helps you create a transaction for minting shares (osETH) with a validator on the Ethereum network.

#### How to Use

To build a minting transaction, you need to specify the amount of osETH to mint, the delegator's address, and the validator's address where you want to mint your shares. Optionally, you can also specify a referrer address for tracking purposes.

{% hint style="info" %}
For more information on tracking and attributing minting transactions to specific sources, such as marketing campaigns or integration partners, refer to the [Delegation Tracking](/build-your-staking-dapp/ethereum/delegation-tracking) section.
{% endhint %}

#### Example

```javascript
const { tx } = await staker.buildMintTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1', // 1 osETH
  referrer: '0xReferrerAddressHere' // Unique Ethereum address for tracking
})
```

In this example, we're minting 1 osETH with a specified validator.

***

### buildBurnTx

#### Description

The `buildBurnTx` method helps you create a transaction for burning shares (osETH) with a validator on the Ethereum network.

#### How to Use

To build a burn transaction, you need to specify the amount of osETH to burn, the delegator's address, and the validator's address where you want to burn your shares.

#### Example

```javascript
const { tx } = await staker.buildBurnTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1' // 1 osETH
})
```

In this example, we're burning 1 osETH from a specified validator.

***

### getVault

#### Description

The `getVault` method retrieves the staking information for a specified validator. This includes the total value locked (TVL), annual percentage yield (APY), description, and logo.

#### How to Use

To get vault information, you need to provide the validator's address.

#### Example

```javascript
const { vault } = await staker.getVault({
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
console.log(`Vault info: ${JSON.stringify(vault)}`)
```

In this example, we're retrieving the vault information for a specified validator.

***

### getStake

#### Description

The `getStake` method retrieves the staking information for a specified delegator. This includes the current balance and the maximum amount that can be unstaked.

#### How to Use

To get staking information, you need to provide the delegator's address and the validator's address.

#### Example

```javascript
const { balance, maxUnstake } = await staker.getStake({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
console.log(`Staked balance: ${balance}, Max unstake: ${maxUnstake}`)
```

In this example, we're retrieving the staked balance and maximum unstake amount for a given delegator and validator.

***

### getRewardsHistory

#### Description

The `getRewardsHistory` method fetches the rewards data accumulated for a delegator over a specified time period.

#### How to Use

To get rewards history, you need to provide the delegator's address, the validator's address, and the start and end times for the data retrieval period.

#### Example

```javascript
const rewards = await staker.getRewardsHistory({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  startTime: 1672531200000, // Jan 1, 2023
  endTime: 1704067200000 // Jan 1, 2024
})
console.log(`Rewards history: ${JSON.stringify(rewards)}`)
```

In this example, we're fetching the rewards history for a delegator from a specific validator over a specified time period.

***

### getTxHistory

#### Description

The `getTxHistory` method retrieves the transaction history for a specified delegator.

#### How to Use

To get transaction history, you need to provide the delegator's address and the validator's address.

#### Example

```javascript
const txHistory = await staker.getTxHistory({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
console.log(`Transaction history: ${JSON.stringify(txHistory)}`)
```

In this example, we're retrieving the transaction history for a specified delegator and validator.

***

### getUnstakeQueue

#### Description

The `getUnstakeQueue` method retrieves the unstake queue for a specified delegator. This queue includes information about the current state of unstake requests.

After initiating an unstake request using the `buildUnstakeTx` method, assets\
are placed into an unstake queue.

The `getUnstakeQueue` method allows users to query the queue to check the\
current state of their unstake requests, including their positionTicket, the\
amount of assets that are withdrawable, and the total amount.

To prepare the transaction for withdrawing these assets, use the`buildWithdrawTx` method.

#### How to Use

To get the unstake queue, you need to provide the delegator's address and the validator's address.

#### Example

```javascript
const queue = await staker.getUnstakeQueue({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
console.log(`Unstake queue: ${JSON.stringify(queue)}`)
```

In this example, we're retrieving the unstake queue for a specified delegator and validator.

***

### getMint

#### Description

The `getMint` method retrieves the mint information for a specified delegator. This includes the current balance of minted shares (osETH) and the maximum amount that can be minted.

#### How to Use

To get mint information, you need to provide the delegator's address and the validator's address.

#### Example

```javascript
const { balance, maxMint } = await staker.getMint({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08'
})
console.log(`Mint balance: ${balance}, Max mint: ${maxMint}`)
```

In this example, we're retrieving the mint balance and maximum mint amount for a given delegator and validator.

***

### getMintHealth

#### Description

The `getMintHealth` method retrieves the health status of a mint position based on the amount of ETH staked and the amount of osETH minted.

{% hint style="info" %}
The position health parameter is used to monitor the value of minted osETH relative to the staked ETH value:

* **`healthy`**: Minted osETH ≤ 90% of staked ETH
* **`risky`**: Minted osETH > 91% but ≤ 92% of staked ETH

Changes in position health can result from discrepancies between Vault APY and osETH APY, higher fees, or inconsistent performance.

Unhealthy positions may lead to forced burning of osETH tokens.
{% endhint %}

#### How to Use

To get mint health, you need to provide the stake amount and the mint amount.

#### Example

```javascript
const { health } = await staker.getMintHealth({
  stakeAmount: '10', // 10 ETH
  mintAmount: '5' // 5 osETH
  validatorAddress: '0x...' // Vault address
})
console.log(`Mint health: ${health}`)
```

In this example, we're retrieving the mint health status based on the provided stake and mint amounts.

***

For more detailed information and additional methods, please refer to the official API reference:

* [Ethereum Staker API Reference](/api-reference/stakers/ethereum_src.ethereumstaker)


# Native Staking Methods (SDK)

This section provides an overview of the key methods available in the **Chorus One SDK** for **Native Staking** on the Ethereum network.

The Chorus One Native Staking SDK supports a range of staking operations including creating validator batches, retrieving batch status, exporting deposit data as well as building deposit transactions. Below, we will explore each method with practical examples to help you get started.

### createValidatorBatch

#### Description

The `createValidatorBatch` method creates a new batch of validators with each validator requiring a deposit to be made. The batch will generate deposit data that can be used to deposit validators on the Ethereum network.

#### How to Use

To create validators, you need to specify:

* **batchId** (required): A unique UUID for the batch
* **withdrawalAddress** (required): The withdrawal address or credentials
  * For standard validators: A regular Ethereum address (e.g., `0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30`)
  * For compounding validators: A 32-byte withdrawal credential in 0x02 format ([EIP-7251](https://eips.ethereum.org/EIPS/eip-7251))
    * Use the `toCompoundingCredentials()` utility function to convert your wallet address
    * Format: `0x02` + `00000000000000000000` (11 zero bytes) + your 20-byte wallet address (without 0x prefix)
    * Example: For wallet `0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30`, use `0x02000000000000000000000070aEe8a9099ebADB186C2D530F72CF5dC7FE6B30`
* **feeRecipientAddress** (required): The address that will receive MEV rewards
* **numberOfValidators** (required): Number of validators to create in the batch
* **isCompounding** (optional): Whether to create compounding validators (EIP-7251). Default is `false`
  * When `true`, withdrawal address must be a 32-byte credential starting with `0x02`
  * When `false`, withdrawal address must be a standard 20-byte Ethereum address
* **depositGweiPerValidator** (optional): The deposit amount in gwei per validator. Default is `32000000000` (32 ETH)

**Note**: A single batch request cannot exceed 200 validators. If you need more, please issue multiple batch requests.

#### Examples

**Creating standard validators (32 ETH each):**

```javascript
const result = await staker.createValidatorBatch({
  batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20',
  withdrawalAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  feeRecipientAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  numberOfValidators: 2
})
```

**Creating compounding validators (EIP-7251):**

```javascript
import { toCompoundingCredentials } from '@chorus-one/ethereum'

const walletAddress = '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30'
const withdrawalCredentials = toCompoundingCredentials(walletAddress)
// Returns: '0x02000000000000000000000070aEe8a9099ebADB186C2D530F72CF5dC7FE6B30'

const result = await staker.createValidatorBatch({
  batchId: '5ea33d98-c8e6-5f42-9d4b-14981fcd8c31',
  withdrawalAddress: withdrawalCredentials,
  feeRecipientAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  numberOfValidators: 1,
  isCompounding: true
})
```

**Creating compounding validator with custom deposit amount (64 ETH):**

```javascript
import { toCompoundingCredentials } from '@chorus-one/ethereum'

const result = await staker.createValidatorBatch({
  batchId: '6fb44e09-d9f7-6g53-0e5c-25092gde9d42',
  withdrawalAddress: toCompoundingCredentials('0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30'),
  feeRecipientAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  numberOfValidators: 1,
  isCompounding: true,
  depositGweiPerValidator: 64000000000n // 64 ETH
})
```

***

### getValidatorBatchStatus

#### Description

The `getValidatorBatchStatus` method retrieves the current status of a validator batch, including the deposit data for each validator when ready.

#### How to Use

To retrieve the status of a validator batch, you need to specify the batch id of the validator batch.

#### Example

```javascript
const batchData = await staker.getValidatorBatchStatus({
  batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20'
})
```

#### Response

The method returns a `BatchDetailsResponse` object with the following structure:

* **status**: Batch status - `'created'` (processing) or `'ready'` (deposit data available)
* **created**: Timestamp when the batch was created
* **is\_compounding**: Boolean indicating if validators are compounding (EIP-7251)
* **deposit\_gwei\_per\_validator**: Deposit amount in gwei per validator
* **validators**: Array of validator objects, each containing:
  * **status**: Validator status - `'created'`, `'active'`, or `'exited'`
  * **deposit\_data**: Deposit data object with fields like `pubkey`, `withdrawal_credentials`, `signature`, `deposit_data_root`, etc.

***

### listValidatorBatches

#### Description

The `listValidatorBatches` method retrieves all validator batches that have been created for the authenticated tenant. This method is useful for getting an overview of all your validator batches and their current status.

#### How to Use

This method doesn't require any parameters and returns a list of all validator batches associated with your API token.

#### Example

```javascript
const response = await staker.listValidatorBatches()
```

#### Response

The method returns a `ListBatchesResponse` object containing:

* **requests**: Array of batch items, each with:
  * **batch\_id**: Unique identifier for the batch
  * **created**: Timestamp when the batch was created
  * **status**: Batch status - `'created'` or `'ready'`
  * **is\_compounding**: Boolean indicating if validators are compounding (EIP-7251)
  * **deposit\_gwei\_per\_validator**: Deposit amount in gwei per validator

### Further Reading

* [Chorus One Ethereum Native Staking](https://kb.chorus.one/our-products/chorus-one-ethereum-native-staking)
* [Native Staking API Integration](https://kb.chorus.one/our-products/chorus-one-ethereum-native-staking/api-integration-guide)


# Native Staking Methods (API)

This section provides an overview of the key API endpoints available for Native Staking on the Ethereum network via the Bitwise Onchain Solutions Native Staking API. Dedicated ETH staking services are provided by Attestant Ltd (d/b/a Bitwise Onchain Solutions), the parent company of Bitwise Onchain Solutions AG (f/k/a Chorus One).

The Bitwise Onchain Solutions Native Staking API allows you to manage subaccounts, create validators, and monitor validator status through simple REST API calls. Below, we will explore each endpoint with practical examples to help you get started.

### Authentication

All API requests require a Bearer token in the `Authorization` header. You can obtain a token by reaching out to the Chorus One team. See [Tokens](#tokens) for the full token lifecycle.

**Base URLs:**

| Network         | Base URL                            |
| --------------- | ----------------------------------- |
| Mainnet         | `https://client.attestant.io`       |
| Testnet (Hoodi) | `https://client-hoodi.attestant.io` |

**Headers:**

```
Authorization: Bearer <your-api-token>
Content-Type: application/json
```

> Error responses (4xx/5xx) follow the [full OpenAPI specification](https://client.attestant.io/docs/#/). This page documents request shapes and successful responses only.

***

### Step-by-Step: How to Stake

The end-to-end flow to bring an Ethereum validator online via the Attestant API is six steps. Each step links to the endpoint reference below.

1. **(Optional) Choose MEV relays.** Call [List MEV Relays](#list-mev-relays) to retrieve relay IDs if you want to pin specific relays to your subaccount instead of accepting the defaults.
2. **Create a subaccount.** Call [Create Subaccount](#create-subaccount) with your fee recipient address and MEV relay preferences. The subaccount groups validators and holds their shared configuration. You can confirm the result with [Get Subaccount](#get-subaccount).
3. **Create validators.** Call [Create Validators](#create-validators), passing the subaccount name and a list of validator names. Attestant returns the BLS pubkey, withdrawal credentials, signature, and pre-built deposit transaction data for each validator.
4. **(Recommended) Verify the deposit data.** Decode the returned `transaction_data` and confirm it matches the other fields — see [Verifying Transaction Data](#verifying-transaction-data). For maximum trust, build the deposit call yourself using [Constructing Your Own Deposit Transaction](#constructing-your-own-deposit-transaction).
5. **Submit the deposit(s).** Send ETH to the deposit contract following [Depositing Validators](#depositing-validators) — either one batch transaction for multiple validators or one transaction per validator.
6. **Track activation.** Poll [Get Validator](#get-validator) (or [List Validators](#list-validators)) until each validator's `state` reaches `Active`. The state progresses `Awaiting deposit → Deposited → Awaiting activation → Active`.

Once a validator is `Active`, ongoing management — converting to compounding, consolidating, topping up, partial withdrawals, and full exits — is covered under [Lifecycle Operations](#lifecycle-operations). For background on `0x01` vs `0x02` (compounding) validators and the Pectra lifecycle, see [Compounding and Credential Types](#compounding-and-credential-types).

***

### Compounding and Credential Types

Every Ethereum validator has a **withdrawal credential** whose leading byte determines how its balance behaves. The remaining 20 bytes are the withdrawal address (the subaccount's `fee_recipient`); only the prefix differs between the two types.

| Prefix | Type                                                            | Max effective balance | Rewards                                                                             |
| ------ | --------------------------------------------------------------- | --------------------- | ----------------------------------------------------------------------------------- |
| `0x01` | Legacy (execution address)                                      | 32 ETH                | Skimmed automatically to the withdrawal address; balance above 32 ETH does not earn |
| `0x02` | Compounding ([Pectra](https://eips.ethereum.org/EIPS/eip-7251)) | 2048 ETH              | **Compound automatically** — they stay staked and keep earning                      |

A compounding (`0x02`) validator is the building block of the Pectra staking lifecycle:

* **Create** a `0x02` validator directly by passing `compounding: true` to [Create Validators](#create-validators), or start at 32 ETH and grow it with [Get Topup Transaction](#get-topup-transaction) (up to 2048 ETH).
* **Upgrade** an existing `0x01` validator in place with [Convert to Compounding](#convert-to-compounding) — keys, index, and balance are unchanged; only the credential prefix flips to `0x02`.
* **Consolidate** the stake of one validator into a `0x02` target with [Consolidate Validators](#consolidate-validators), collapsing several validators into one larger one.
* **Withdraw** part of the balance, or exit entirely, with [Get Withdrawal Transaction](#get-withdrawal-transaction) and [Get Exit Transaction](#get-exit-transaction). Withdrawals and exits include accrued rewards.

> **Note:** Separately claiming rewards on a legacy `0x01` validator is not supported — its rewards above 32 ETH are skimmed automatically by the protocol. Upgrade it to `0x02` to compound instead.

***

### List MEV Relays

`GET /v1/eth/mevrelays`

#### Description

Retrieves the Ethereum MEV relays that can be assigned to a subaccount. MEV relays configured on a subaccount are used by that subaccount's validators when proposing blocks.

#### How to Use

This method does not require any parameters.

#### Example

```bash
curl -X GET https://client.attestant.io/v1/eth/mevrelays \
  -H "Authorization: Bearer <your-api-token>"
```

#### Response

**Status: 200 OK**

```json
[
  {
    "id": "1234567890123456789",
    "name": "Relay Name",
    "description": "Relay description",
    "description_url": "https://example.com/relay"
  }
]
```

**Response Fields:**

* **id**: MEV relay ID. Use this value in `ethereum.mev_relays` when creating or updating a subaccount
* **name**: The relay name
* **description**: Description provided by the relay owner
* **description\_url**: URL with more information about the relay

**Note**: If no relays are available, the response is an empty array (`[]`).

***

### Subaccounts

A **subaccount** is an in-account grouping of validators that share configuration — fee recipient and MEV relay set. Every validator is assigned to exactly one subaccount, and an API token may be restricted to a single subaccount (see [Tokens](#tokens)).

The endpoints below let you create new subaccounts and inspect existing ones.

#### Create Subaccount

`POST /v1/accounts/subaccounts`

**Description**

Creates a new subaccount. A subaccount contains configuration for validators, such as the fee recipient address and MEV relay settings. You must create a subaccount before creating validators.

**How to Use**

**Request Body:**

* **name** (string, required): The subaccount name (e.g., `"My Subaccount"`)
* **ethereum** (object, required):
  * **fee\_recipient** (string, required): An EIP-55 checksummed Ethereum address. Receives MEV rewards and tips, **and** is used as the withdrawal address for every validator created in this subaccount (encoded into each validator's `withdrawal_credentials`).
  * **default\_mev\_relays** (boolean, optional): Use all available MEV relays. Default is `false`
  * **mev\_relays** (array, optional): Specific MEV relay IDs to use (see [List MEV Relays](#list-mev-relays))

**Example**

```bash
curl -X POST https://client.attestant.io/v1/accounts/subaccounts \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Subaccount",
    "ethereum": {
      "fee_recipient": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
      "default_mev_relays": true
    }
  }'
```

**Response**

**Status: 201 Created**

```json
{
  "name": "My Subaccount",
  "ethereum": {
    "fee_recipient": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
    "mev_relays": [{ "id": "1234567890123456789" }]
  }
}
```

**Response Fields:**

* **name**: The subaccount name
* **ethereum.fee\_recipient**: The configured fee recipient address
* **ethereum.mev\_relays** (optional): Array of assigned MEV relay objects, each with an `id` field. Only present when MEV relays have been configured for the subaccount; omitted otherwise

***

#### Get Subaccount

`GET /v1/accounts/subaccounts/{subaccount_id}`

**Description**

Retrieves information about a single subaccount, including its fee recipient and assigned MEV relays.

**How to Use**

**Path Parameters:**

* **subaccount\_id** (string, required): The customer-supplied subaccount name (e.g., `"My Subaccount"`). URL-encode any special characters.

**Example**

```bash
curl -X GET "https://client.attestant.io/v1/accounts/subaccounts/My%20Subaccount" \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

```json
{
  "name": "My Subaccount",
  "ethereum": {
    "fee_recipient": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
    "mev_relays": [{ "id": "1234567890123456789" }]
  }
}
```

**Response Fields:**

* **name**: The subaccount name
* **ethereum.fee\_recipient**: The configured fee recipient address
* **ethereum.mev\_relays** (optional): Array of assigned MEV relay objects, each with an `id` field. Only present when MEV relays have been configured for the subaccount; omitted otherwise

***

### Create Validators

`POST /v1/eth/validators`

#### Description

Creates one or more new validators. The created validators will each need a deposit before they are activated. Deposits can be made individually or for all validators within a single batch transaction using the [batch validator depositor contract](https://github.com/attestantio/batch-validator-depositor), which has been [audited by Dedaub](https://dedaub.com/audits/ethereum-foundation/ef-batch-validator-depositor-april-02-2025/). The returned information includes raw transaction data that can be used to submit deposits.

#### How to Use

**Request Body:**

* **subaccount** (string, required): The subaccount to assign the validators to (e.g., `"My Subaccount"`)
* **names** (string\[], required): Names for the validators (e.g., `["Validator #1", "Validator #2"]`)
* **amount** (string, optional): Deposit amount per validator. Must be a positive whole multiple of 1 ETH (e.g., `"32 ETH"`, `"64 ETH"`). Accepts `ETH`/`GWEI` units or bare-integer Wei. Defaults to 32 ETH; applied to all validators.
* **compounding** (boolean, optional): Whether to create compounding validators. Default is `false`

**Note**: A single request cannot exceed 100 validators. If you need more, please issue multiple requests.

#### Examples

**Creating standard validators (32 ETH each):**

```bash
curl -X POST https://client.attestant.io/v1/eth/validators \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "subaccount": "My Subaccount",
    "names": ["Validator #1", "Validator #2"]
  }'
```

**Creating compounding validators with custom amount:**

```bash
curl -X POST https://client.attestant.io/v1/eth/validators \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "subaccount": "My Subaccount",
    "names": ["Validator #1"],
    "amount": "64 ETH",
    "compounding": true
  }'
```

#### Response

**Status: 201 Created**

```json
{
  "validators": [
    {
      "id": "1234567890123456789",
      "pubkey": "0xaabbccdd00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabb",
      "name": "Validator #1",
      "amount": "32000000000",
      "withdrawal_credentials": "0x010000000000000000000000abcdef0123456789abcdef0123456789abcdef01",
      "deposit_message_root": "0xaabbccdd00112233445566778899aabbccddeeff00112233445566778899aabb",
      "deposit_data_root": "0x11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff",
      "fork_version": "0x10000910",
      "signature": "0xaabb...96_bytes_hex_encoded",
      "transaction_data": "0x22895118000000000000000000000000000000000000000000...",
      "version": "5"
    },
    {
      "id": "9876543210987654321",
      "pubkey": "0x112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff0011",
      "name": "Validator #2",
      "amount": "32000000000",
      "withdrawal_credentials": "0x010000000000000000000000abcdef0123456789abcdef0123456789abcdef01",
      "deposit_message_root": "0x22334455667788990011aabbccddeeff22334455667788990011aabbccddeeff",
      "deposit_data_root": "0x33445566778899001122aabbccddeeff33445566778899001122aabbccddeeff",
      "fork_version": "0x10000910",
      "signature": "0xccdd...96_bytes_hex_encoded",
      "transaction_data": "0x22895118000000000000000000000000000000000000000000...",
      "version": "5"
    }
  ],
  "batch_transactions": {
    "Attestant": "0xc09bb1db000000000000000000000000000000000000..."
  }
}
```

**Response Fields:**

* **validators**: Array of created validator objects, each containing:
  * **id**: Unique identifier for the validator
  * **pubkey**: The 48-byte BLS public key (hex-encoded). Returned as `public_key` in [List Validators](#list-validators) and [Get Validator](#get-validator) responses — same value, different field name
  * **name**: The name assigned to the validator
  * **amount**: The deposit amount in Gwei
  * **withdrawal\_credentials**: 32-byte withdrawal credentials (hex-encoded). The last 20 bytes are the withdrawal address, which is the subaccount's `fee_recipient` (see [Create Subaccount](#create-subaccount)).
  * **deposit\_message\_root**: Hash of the deposit message (hex-encoded)
  * **deposit\_data\_root**: Hash of the deposit data (hex-encoded)
  * **fork\_version**: Ethereum fork version used to generate the signature
  * **signature**: 96-byte BLS signature (hex-encoded)
  * **transaction\_data**: Raw transaction data that can be sent directly as part of the deposit transaction
  * **version**: Version of the transaction data format (currently `"5"`)
* **batch\_transactions**: Object mapping batch deposit contracts to their hex-encoded transaction data. Use the `Attestant` entry — its addresses are listed in [Depositing Validators](#depositing-validators).

***

### Depositing Validators

After creating validators, you must deposit ETH to activate them. There are two approaches:

#### Option A: Batch Deposit (recommended for multiple validators)

Use the `batch_transactions` field from the Create Validators response. Each entry contains pre-encoded transaction data for a batch deposit contract that can deposit all validators in a single transaction.

Send the hex data as a transaction to the [batch validator depositor contract](https://github.com/attestantio/batch-validator-depositor) ([audited by Dedaub](https://dedaub.com/audits/ethereum-foundation/ef-batch-validator-depositor-april-02-2025/)):

| Network | Batch Deposit Contract Address               |
| ------- | -------------------------------------------- |
| Mainnet | `0x16BF86Efb14FA03a3A207efC03Df5Ed29094a838` |
| Hoodi   | `0x9c2880C58e2F7bc7f1Bcbf0e0d220B8a3d6cc5a9` |

The transaction value must equal the sum of all validator deposits. For example, 2 validators at 32 ETH each requires sending 64 ETH.

#### Option B: Individual Deposits

Use the `transaction_data` field from each validator in the response. Send each as a separate transaction to the official Ethereum deposit contract:

| Network      | Deposit Contract Address                     |
| ------------ | -------------------------------------------- |
| All networks | `0x00000000219ab540356cBB839Cbe05303d7705Fa` |

The transaction value must equal the deposit amount for that validator (e.g., 32 ETH). The `transaction_data` is an ABI-encoded call to the deposit function:

```
deposit(bytes pubkey, bytes withdrawal_credentials, bytes signature, bytes32 deposit_data_root)
```

Function selector: `0x22895118`

***

### Verifying Transaction Data

Before signing any deposit transaction, you should decode and verify the `transaction_data` to ensure it was not tampered with in transit.

The `transaction_data` is an ABI-encoded call to `deposit(bytes,bytes,bytes,bytes32)` with function selector `0x22895118`. You can decode it and compare the values against the other fields in the response.

**Using Foundry's `cast`:**

```bash
cast calldata-decode \
  "deposit(bytes,bytes,bytes,bytes32)" \
  0x22895118000000000000000000000000...
```

This will output the decoded `pubkey`, `withdrawal_credentials`, `signature`, and `deposit_data_root`. Verify that each matches the corresponding field in the validator response.

**Using viem:**

```javascript
import { decodeFunctionData, parseAbi } from 'viem'

const depositAbi = parseAbi([
  'function deposit(bytes pubkey, bytes withdrawal_credentials, bytes signature, bytes32 deposit_data_root)'
])

const { args } = decodeFunctionData({
  abi: depositAbi,
  data: transactionData
})

const [pubkey, withdrawalCredentials, signature, depositDataRoot] = args
console.log('pubkey:', pubkey)
console.log('withdrawal_credentials:', withdrawalCredentials)
console.log('signature:', signature)
console.log('deposit_data_root:', depositDataRoot)
```

***

### Constructing Your Own Deposit Transaction

For an additional layer of trust, you can independently construct the deposit transaction using the response fields rather than relying on the pre-built `transaction_data`. This way, you control the entire encoding process.

#### Steps

1. Take `pubkey`, `withdrawal_credentials`, `signature`, and `deposit_data_root` from the validator response
2. ABI-encode a call to `deposit(bytes,bytes,bytes,bytes32)` with these values
3. Send the encoded data to the deposit contract with the correct ETH value

**Using Foundry's `cast`:**

```bash
cast calldata \
  "deposit(bytes,bytes,bytes,bytes32)" \
  <pubkey> \
  <withdrawal_credentials> \
  <signature> \
  <deposit_data_root>
```

**Using viem:**

```javascript
import { encodeFunctionData, parseAbi, parseEther } from 'viem'

const depositAbi = parseAbi([
  'function deposit(bytes pubkey, bytes withdrawal_credentials, bytes signature, bytes32 deposit_data_root)'
])

const data = encodeFunctionData({
  abi: depositAbi,
  functionName: 'deposit',
  args: [validator.pubkey, validator.withdrawal_credentials, validator.signature, validator.deposit_data_root]
})

// Send to deposit contract with correct ETH value
const tx = {
  to: '0x00000000219ab540356cBB839Cbe05303d7705Fa',
  data: data,
  value: parseEther('32')
}
```

#### Verifying the `deposit_data_root`

You can also independently recompute the `deposit_data_root` to verify the server has not manipulated it. The `deposit_data_root` is the SSZ hash tree root of the `DepositData` container:

```
DepositData {
  pubkey:                 BLSPubkey       (48 bytes)
  withdrawal_credentials: Bytes32         (32 bytes)
  amount:                 Gwei            (uint64)
  signature:              BLSSignature    (96 bytes)
}
```

The deposit contract itself also verifies this root on-chain — if the `deposit_data_root` does not match the other fields, the transaction will revert.

***

### List Validators

`GET /v1/eth/validators`

#### Description

Retrieves a list of validators. Each returned validator includes details about its configuration, current state, and balance. You can optionally filter validators by subaccount.

#### How to Use

**Query Parameters:**

* **subaccount** (string, optional): Filter validators by subaccount name. If not supplied, all validators visible to the calling token are returned.

**Note**: Called with an account-wide token and no `subaccount` filter, this endpoint returns every validator across every subaccount on the account. Use a subaccount-scoped token (see [Tokens](#tokens)) for customer-facing access.

#### Examples

**List all validators:**

```bash
curl -X GET https://client.attestant.io/v1/eth/validators \
  -H "Authorization: Bearer <your-api-token>"
```

**List validators for a specific subaccount:**

```bash
curl -X GET "https://client.attestant.io/v1/eth/validators?subaccount=My%20Subaccount" \
  -H "Authorization: Bearer <your-api-token>"
```

#### Response

**Status: 200 OK**

```json
{
  "validators": [
    {
      "id": "1234567890123456789",
      "public_key": "0xaabbccdd00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabb",
      "name": "Validator #1",
      "subaccount": "My Subaccount",
      "state": "Active",
      "withdrawal_credentials": "0x010000000000000000000000abcdef0123456789abcdef0123456789abcdef01",
      "balance": "32000506147000000000",
      "effective_balance": "32000000000000000000",
      "deposits": "32000000000000000000",
      "activation_timestamp": "1772558616",
      "timestamp": "1774021252"
    },
    {
      "id": "9876543210987654321",
      "public_key": "0x112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff0011",
      "name": "Validator #2",
      "subaccount": "My Subaccount",
      "state": "Awaiting deposit",
      "balance": "0",
      "deposits": "0",
      "timestamp": "1774021252"
    }
  ]
}
```

**Response Fields:**

* **validators**: Array of validator objects, each containing:
  * **id**: Unique identifier for the validator
  * **public\_key**: The 48-byte BLS public key of the validator (hex-encoded)
  * **name**: The name assigned to the validator
  * **subaccount**: The subaccount to which the validator belongs
  * **state**: The current state of the validator. Possible values:
    * `Unassigned` — Not yet assigned to a customer
    * `Awaiting deposit` — Assigned and awaiting a deposit on the execution chain
    * `Deposited` — Matched to a deposit, awaiting inclusion on the consensus chain
    * `Awaiting activation` — Included on the consensus chain, in the activation queue
    * `Active` — Currently validating
    * `Exited` — Exited and no longer active
  * **withdrawal\_credentials**: 32-byte withdrawal credentials (hex-encoded). Set once the validator's deposit has been included on the consensus chain. Always present on `Active`, `Awaiting activation`, and `Exited` validators; on `Deposited` validators it is present once the consensus chain has processed the deposit; absent on `Unassigned` and `Awaiting deposit`
  * **balance**: Current balance in Wei
  * **effective\_balance**: Current effective balance in Wei. Present on active validators
  * **deposits**: Total amount deposited from the execution chain in Wei
  * **activation\_timestamp**: Unix timestamp (seconds) when the validator became active. Present on `Active` and `Exited` validators
  * **timestamp**: Unix timestamp when the validator information was last updated

***

### Get Validator

`GET /v1/eth/validators/{validator_id}`

#### Description

Retrieves details about a single validator, including its configuration, current state, and balance.

#### How to Use

**Path Parameters:**

* **validator\_id** (string, required): Either the Attestant ID or the BLS public key of the validator (e.g., `"1385610059030986755"` or `"0xaabbccdd..."`).

#### Example

```bash
curl -X GET https://client.attestant.io/v1/eth/validators/1234567890123456789 \
  -H "Authorization: Bearer <your-api-token>"
```

#### Response

**Status: 200 OK**

```json
{
  "id": "1234567890123456789",
  "public_key": "0xaabbccdd00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabb",
  "name": "Validator #1",
  "subaccount": "My Subaccount",
  "state": "Active",
  "withdrawal_credentials": "0x010000000000000000000000abcdef0123456789abcdef0123456789abcdef01",
  "balance": "32000506147000000000",
  "effective_balance": "32000000000000000000",
  "deposits": "32000000000000000000",
  "activation_timestamp": "1772558616",
  "timestamp": "1774021252"
}
```

**Response Fields:**

* **id**: Unique identifier for the validator
* **public\_key**: The 48-byte BLS public key of the validator (hex-encoded)
* **name**: The name assigned to the validator
* **subaccount**: The subaccount to which the validator belongs
* **state**: The current state of the validator. See [List Validators](#list-validators) for the possible values
* **withdrawal\_credentials**: 32-byte withdrawal credentials (hex-encoded). Set once the validator's deposit has been included on the consensus chain. Always present on `Active`, `Awaiting activation`, and `Exited` validators; on `Deposited` validators it is present once the consensus chain has processed the deposit; absent on `Unassigned` and `Awaiting deposit`
* **balance**: Current balance in Wei
* **effective\_balance**: Current effective balance in Wei. Present on active validators
* **deposits**: Total amount deposited from the execution chain in Wei
* **activation\_timestamp**: Unix timestamp (seconds) when the validator became active. Present on `Active` and `Exited` validators
* **timestamp**: Unix timestamp when the validator information was last updated

***

### Lifecycle Operations

The endpoints below support the validator lifecycle after activation: converting to compounding, consolidating, topping up the balance, partial withdrawals, and exiting. They are all pure transaction builders — calling them has no Attestant-side or on-chain effect. Only signing and broadcasting the returned transaction(s) will affect state.

Execution-layer operations target one of the following contracts:

| Operation                            | Target                                                                 |
| ------------------------------------ | ---------------------------------------------------------------------- |
| Convert to compounding / Consolidate | EIP-7251 predeploy `0x0000BBdDc7CE488642fb579F8B00f3a590007251`        |
| Withdrawal                           | EIP-7002 predeploy `0x00000961Ef480Eb55e80D19ad83579A64c007002`        |
| Topup                                | Official deposit contract `0x00000000219ab540356cBB839Cbe05303d7705Fa` |

***

#### Convert to Compounding

`GET /v1/eth/validators/{validator_id}/compoundtransaction`

Requires a token with `assign` scope or higher.

**Description**

Upgrades a legacy `0x01` validator to a compounding `0x02` validator **in place**. The validator keeps its keys, consensus index, and balance — only the withdrawal-credential prefix changes from `0x01` to `0x02`, after which its rewards compound and it can grow up to 2048 ETH.

Under the hood this is an [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) **self-consolidation**: a consolidation request whose source and target are the same validator. The transaction targets the EIP-7251 consolidation request predeploy and must be signed by the validator's withdrawal address and broadcast to take effect.

The validator must be `Active` and currently have `0x01` credentials; otherwise the request fails with `412 Precondition Failed`.

**How to Use**

**Path Parameters:**

* **validator\_id** (string, required): The validator to upgrade (Attestant ID or BLS pubkey)

**Example**

```bash
curl -X GET https://client.attestant.io/v1/eth/validators/1234567890123456789/compoundtransaction \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

```json
{
  "transactions": [
    {
      "sender": "0xD4BB555d3B0D7fF17c606161B44E372689C14F4B",
      "contract_address": "0x0000BBdDc7CE488642fb579F8B00f3a590007251",
      "data": "0xaabbccdd…<48-byte pubkey>…aabbccdd…<same 48-byte pubkey>…",
      "value": "1001"
    }
  ]
}
```

**Response Fields:**

* **transactions**: Array with a single transaction to sign and broadcast. The entry contains:
  * **sender**: The withdrawal address that must sign and broadcast (the last 20 bytes of the validator's `withdrawal_credentials`)
  * **contract\_address**: The EIP-7251 consolidation request predeploy
  * **data**: 96-byte calldata — the validator's 48-byte BLS pubkey repeated twice (source == target)
  * **value**: Wei to send. Equals the current EIP-7251 request fee + safety bump (`fee/2`, clamped `[1000, 10⁹]` wei) to tolerate fee changes before inclusion. If the resulting fee would exceed `0.001 ETH` (`10¹⁵` wei), the request is rejected.

***

#### Consolidate Validators

`POST /v1/eth/validators/{validator_id}/consolidatetransaction`

Requires a token with `assign` scope or higher.

**Description**

Generates an [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) consolidation request that moves the **source** validator's stake into a **target** validator, merging them into one larger compounding validator. The transaction targets the EIP-7251 consolidation request predeploy and must be signed by the source validator's withdrawal address and broadcast to take effect.

Requirements:

* The **source** validator (path `validator_id`) must be `Active` and have `0x01` or `0x02` credentials. It may be one of your own validators, or — by passing its BLS pubkey — an external validator that shares the same withdrawal address.
* The **target** validator (`target_validator`) must be one of your `Active` validators and already be compounding (`0x02`).

If either validator is in an unsuitable state or has the wrong credential type, the request fails with `412 Precondition Failed`.

> Consolidating a validator into itself (source == target) is exactly the `0x01` → `0x02` upgrade — for that case prefer the simpler [Convert to Compounding](#convert-to-compounding) endpoint.

**How to Use**

**Path Parameters:**

* **validator\_id** (string, required): The **source** validator whose stake is moved (Attestant ID or BLS pubkey)

**Request Body:**

* **target\_validator** (string, required): The **target** validator that receives the stake (Attestant ID or BLS pubkey). Must be an active compounding (`0x02`) validator on your account.

**Example**

```bash
curl -X POST https://client.attestant.io/v1/eth/validators/1234567890123456789/consolidatetransaction \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "target_validator": "9876543210987654321"
  }'
```

**Response**

**Status: 200 OK**

```json
{
  "transactions": [
    {
      "sender": "0xD4BB555d3B0D7fF17c606161B44E372689C14F4B",
      "contract_address": "0x0000BBdDc7CE488642fb579F8B00f3a590007251",
      "data": "0xaabbccdd…<48-byte source pubkey>…112233…<48-byte target pubkey>…",
      "value": "1001"
    }
  ]
}
```

**Response Fields:**

* **transactions**: Array with a single transaction to sign and broadcast. The entry contains:
  * **sender**: The source validator's withdrawal address, which must sign and broadcast
  * **contract\_address**: The EIP-7251 consolidation request predeploy
  * **data**: 96-byte calldata — the 48-byte source pubkey followed by the 48-byte target pubkey
  * **value**: Wei to send. Equals the current EIP-7251 request fee + safety bump (`fee/2`, clamped `[1000, 10⁹]` wei). If the resulting fee would exceed `0.001 ETH` (`10¹⁵` wei), the request is rejected.

**Note**: Once the request is processed on the consensus chain, the source validator's balance is moved into the target and the source is exited. Both validators must be active when the request is made.

***

#### Get Topup Transaction

`POST /v1/eth/validators/{validator_id}/topuptransaction`

**Description**

Generates a deposit transaction that increases the balance of an active compounding (`0x02`) validator. The transaction targets the standard Ethereum deposit contract.

The returned transaction must be signed and broadcast to take effect.

**How to Use**

**Path Parameters:**

* **validator\_id** (string, required): The validator to top up (Attestant ID or BLS pubkey)

**Request Body:**

* **amount** (string, required): The amount to top up (e.g., `"1 ETH"`, `"32000000000 GWEI"`, or bare-integer Wei). Use whole-Gwei increments — sub-Gwei precision is silently truncated from the signed deposit data.

**Example**

```bash
curl -X POST https://client.attestant.io/v1/eth/validators/1234567890123456789/topuptransaction \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1 ETH"
  }'
```

**Response**

**Status: 200 OK**

```json
{
  "transactions": [
    {
      "contract_address": "0x00000000219ab540356cBB839Cbe05303d7705Fa",
      "data": "0x22895118...",
      "value": "1000000000000000000"
    }
  ]
}
```

**Response Fields:**

* **transactions**: Array of transactions to sign and broadcast. Each entry contains:
  * **contract\_address**: The official Ethereum deposit contract
  * **data**: ABI-encoded `deposit(bytes,bytes,bytes,bytes32)` call (selector `0x22895118`)
  * **value**: Wei to send (matches the requested amount; `1 ETH` = `"1000000000000000000"`)

**Note**: Unlike the EIP-7002 withdrawal builder, this response does not include a `sender` field — any address can broadcast a top-up deposit on behalf of the validator.

***

#### Get Withdrawal Transaction

`POST /v1/eth/validators/{validator_id}/withdrawaltransaction`

**Description**

Generates an EIP-7002 partial withdrawal request for an active compounding (`0x02`) validator. When broadcast, the requested amount is withdrawn from the validator's balance to the withdrawal address. The transaction targets the EIP-7002 withdrawal request predeploy.

The returned transaction must be signed by the withdrawal address and broadcast to take effect.

**How to Use**

**Path Parameters:**

* **validator\_id** (string, required): The validator (Attestant ID or BLS pubkey)

**Request Body:**

* **amount** (string, required): The amount to withdraw (e.g., `"1 ETH"`, `"500000000 GWEI"`, or bare-integer Wei). Use whole-Gwei increments — the on-chain request is encoded as uint64 Gwei, so sub-Gwei precision is silently truncated.

**Example**

```bash
curl -X POST https://client.attestant.io/v1/eth/validators/1234567890123456789/withdrawaltransaction \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1 ETH"
  }'
```

**Response**

**Status: 200 OK**

```json
{
  "transactions": [
    {
      "sender": "0xD4BB555d3B0D7fF17c606161B44E372689C14F4B",
      "contract_address": "0x00000961Ef480Eb55e80D19ad83579A64c007002",
      "data": "0xb5844292ad0e0a0c3c06425e5672c356a37aa2b58d24774817e19500a22703d5ff05a9e0af99054ff625cc51761c470f000000003b9aca00",
      "value": "1001"
    }
  ]
}
```

**Response Fields:**

* **transactions**: Array of transactions to sign and broadcast. Each entry contains:
  * **sender**: The withdrawal address that must sign and broadcast
  * **contract\_address**: The EIP-7002 withdrawal request predeploy
  * **data**: Hex-encoded calldata — 48-byte validator pubkey followed by 8-byte amount in Gwei (big-endian). For example, `000000003b9aca00` = 1,000,000,000 Gwei = 1 ETH
  * **value**: Wei to send. Equals on-chain fee + safety bump (`fee/2`, clamped `[1000, 10⁹]`) to tolerate fee changes before inclusion

***

#### Get Exit Transaction

`GET /v1/eth/validators/{validator_id}/exittransaction`

**Description**

Generates a BLS-signed voluntary exit message for an active validator. Attestant signs the message with the validator's consensus-layer key; the customer only needs to broadcast it to a beacon node to initiate the exit.

If a verified PGP key has been registered for the customer, the returned transaction will instead be encrypted with that key.

**How to Use**

**Path Parameters:**

* **validator\_id** (string, required): Either the Attestant ID or the BLS public key of the validator

**Example**

```bash
curl -X GET https://client.attestant.io/v1/eth/validators/1234567890123456789/exittransaction \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

```json
{
  "transaction": {
    "message": {
      "epoch": "96437",
      "validator_index": "1281812"
    },
    "signature": "0x8eb629978419232d8af4b516adb4bc9df342a0f7b5a70210d69d0947bdebbc6d8a4140addb3a011b27152853273733281063b0d700f3df61a12761b49a8e9de5ff8635f7eda9c782595d3ee1b8548ae6ec6a3ff1d48c3eea7ad9a3d741b040a8"
  }
}
```

**Response Fields:**

* **transaction.message.epoch**: The earliest epoch at which the exit takes effect
* **transaction.message.validator\_index**: The consensus-layer validator index
* **transaction.signature**: 96-byte BLS signature over the exit message (hex-encoded)
* **encrypted\_transaction** (alternative): If a verified PGP key is registered for the customer, this hex-encoded encrypted blob is returned instead of `transaction`. Decrypt with the customer's private PGP key before broadcasting.

***

### Tokens

The Bitwise Onchain Solutions account uses bearer tokens for API authentication. Each token carries a *scope* (which operations it permits) and may be restricted to a single [subaccount](#subaccounts) (limiting the data the token can read). Tokens are issued, listed, and revoked through the four endpoints below.

The token string itself is **returned only once**, in the `POST /v1/accounts/tokens` response — if it is lost it must be deleted and re-issued.

#### Scopes

| Scope       | Permitted operations                                                                                                      |
| ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| `read-only` | Read account state. GETs that generate a signed transaction or message require `assign` or higher                         |
| `assign`    | `read-only` + create validators and perform validator-lifecycle actions (generate transactions, initiate exits)           |
| `operate`   | `assign` + create and update subaccounts (fee recipient, MEV relays); issue lower-or-equal-scope tokens and revoke tokens |
| `all`       | Every API operation. Reserved for portal use; rejected when requested via this endpoint                                   |

#### Subaccount Scoping

A token MAY be restricted to a single subaccount by setting the `subaccount` field on creation. When set, the token can only read and act on data within that subaccount. When unset, the token is account-wide and can read every subaccount on the account.

***

#### List Tokens

`GET /v1/accounts/tokens`

**Description**

Returns metadata for every token on the account. The actual token string is never included.

**Example**

```bash
curl -X GET https://client.attestant.io/v1/accounts/tokens \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

```json
[
  {
    "id": "1234567890123456789",
    "name": "Customer 1 read-only",
    "subaccount": "Customer 1",
    "scope": "read-only",
    "created": "2026-05-22T06:13:34+0000",
    "expiry": "2027-05-22T06:13:33+0000"
  }
]
```

**Response Fields (per token):**

* **id**: Attestant identifier for the token
* **name**: The token name
* **subaccount** (optional): If present, the token is restricted to this subaccount. **If absent, the token is account-wide.**
* **scope**: One of `read-only`, `assign`, `operate`, `all`
* **created**: Creation timestamp (ISO 8601)
* **expiry** (optional): Expiration timestamp. **If absent, the token does not expire.**

***

#### Get Token

`GET /v1/accounts/tokens/{token_id}`

**Description**

Returns metadata for a single token. As with [List Tokens](#list-tokens), the actual token string is never returned.

**How to Use**

**Path Parameters:**

* **token\_id** (string, required): Numeric Attestant token ID (e.g., `"1904441549064766374"`).

**Example**

```bash
curl -X GET https://client.attestant.io/v1/accounts/tokens/1904441549064766374 \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

```json
{
  "id": "1904441549064766374",
  "name": "Customer 1 read-only",
  "subaccount": "Customer 1",
  "scope": "read-only",
  "created": "2026-05-22T06:22:26+0000",
  "expiry": "2027-01-01T00:00:00+0000"
}
```

Fields are identical to those in [List Tokens](#list-tokens).

***

#### Create Token

`POST /v1/accounts/tokens`

**Description**

Creates a new account token. The caller must hold a token with `scope: operate` or higher.

The returned `token` string is the secret to be stored or delivered to the consumer. **It is only returned in this response — it cannot be recovered from `GET /v1/accounts/tokens/{id}` afterwards.** If lost, the token must be deleted and re-issued.

**How to Use**

**Request Body:**

* **name** (string, required): Human-readable token name.
* **scope** (string, required): One of `read-only`, `assign`, `operate`, `all`. (`all` is reserved and may be rejected by the API even when listed in the enum.)
* **subaccount** (string, optional): Subaccount to restrict this token to. If omitted, the token is account-wide — see [Subaccount Scoping](#subaccount-scoping).
* **expiry** (string, optional): ISO 8601-formatted expiration timestamp (`YYYY-MM-DDTHH:MM:SS+ZZZZ`). If omitted, the token never expires.

**Example**

```bash
curl -X POST https://client.attestant.io/v1/accounts/tokens \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer 1 read-only",
    "scope": "read-only",
    "subaccount": "Customer 1",
    "expiry": "2027-01-01T00:00:00+0000"
  }'
```

**Response**

**Status: 201 Created**

```json
{
  "id": "1904444477120971689",
  "name": "Customer 1 read-only",
  "subaccount": "Customer 1",
  "token": "fd89e6a635be910a4f0d534491875994",
  "created": "2026-05-22T06:22:26+0000",
  "expiry": "2027-01-01T00:00:00+0000"
}
```

**Response Fields:**

* **id**: Attestant token ID — use this for subsequent `GET` and `DELETE` calls
* **name**: The token name
* **subaccount** (optional): Echoes the subaccount restriction if set
* **token**: **The secret bearer token.** Capture this immediately — it is not returned again
* **created**: Creation timestamp
* **expiry** (optional): Expiration timestamp if set

***

#### Delete Token

`DELETE /v1/accounts/tokens/{token_id}`

**Description**

Revokes an account token. Once revoked, the token is rejected on all subsequent calls. Use this to rotate tokens on a schedule, revoke compromised tokens, or decommission tokens when a customer offboards. The caller must hold a token with `scope: operate` or higher.

**How to Use**

**Path Parameters:**

* **token\_id** (string, required): Numeric Attestant token ID.

**Example**

```bash
curl -X DELETE https://client.attestant.io/v1/accounts/tokens/1904444477120971689 \
  -H "Authorization: Bearer <your-api-token>"
```

**Response**

**Status: 200 OK**

The response body is empty. After deletion, `GET /v1/accounts/tokens/{token_id}` for the same ID returns `404`.

***

#### Best Practices

1. **Always set `subaccount`** for customer-issued tokens. An unscoped token can read every other customer's data via unfiltered `GET /v1/eth/validators` and `POST /v1/financials/report`.
2. **Always set `expiry`.** A token with no expiry stays valid until it is explicitly deleted; rotate on a fixed cadence (e.g. 90 days).
3. **Use the lowest scope that works.** Most customer use cases (dashboards, monitoring) need only `read-only`. Customer-driven staking flows need `assign`. `operate` and `all` are administrator credentials.
4. **Capture the `token` string at creation.** It is only returned once; store it via the same mechanism you use for other secrets.
5. **Revoke promptly.** `DELETE /v1/accounts/tokens/{id}` is the only revocation path; do not rely on expiry-driven rotation alone when a customer offboards or a token is compromised.

***

### Further Reading

* [Full API Reference](https://client.attestant.io/docs/#/) — Complete OpenAPI documentation with all available endpoints


# Pooled Staking

Staking on the Ethereum network involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The Ethereum blockchain, renowned for its smart contract functionality and vibrant ecosystem, employs the Proof of Stake (PoS) consensus mechanism in its Ethereum 2.0 upgrade. This transition enhances scalability, security, and energy efficiency. By staking ETH, Ethereum's native token, validators maintain the network, secure the blockchain, and incentivize active participation, ensuring the network remains robust and efficient.
{% endhint %}

The **Chorus One SDK** simplifies the staking process on the Ethereum network, providing developers with the tools needed to build, sign, and broadcast staking transactions.

To enhance efficiency, the SDK leverages [Stakewise V3's](https://docs.stakewise.io/) audited and secure smart contracts. By utilizing a pooling solution, it allows multiple users to combine their stakes, making staking more accessible and beneficial for smaller stakeholders.

This guide will walk you through the fundamentals of staking on Ethereum using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Ethereum libraries such as `Ethers` and `viem`. This compatibility ensures that you can seamlessly integrate these methods into your existing Ethereum projects.
{% endhint %}

## Understanding Key Concepts

<details>

<summary>🏦 Pools: Collective Staking for Enhanced Rewards</summary>

A pool is where individual stakers combine their resources. This collective approach benefits those who may not have substantial resources or technical knowledge for individual staking. Pools increase the chances of earning rewards by aggregating the staking power of multiple participants. The Chorus One SDK offers a non-custodial pooling solution, enabling users to stake their assets while maintaining control and enjoying the benefits of pooled resources.

</details>

<details>

<summary>🏰 Vaults: Customized Staking Pools</summary>

Vaults are isolated staking pools offering a trustless, non-custodial process for ETH deposits, reward distribution, and withdrawals. These pools operate independently, using ETH deposits solely to launch validators for that particular Vault, ensuring any rewards or penalties are confined to it. They provide a customized staking experience enabling owners to define their staking fees, opt for a particular mix of operators, employ a unique MEV strategy and other capabilities. Governed entirely by smart contracts, each Vault caters to the specific needs of its depositors, maintaining the integrity and isolation of each staking experience.

</details>

<details>

<summary>🪙 Minting osETH: Creating Liquid Staking Tokens</summary>

Minting osETH involves converting staked ETH in Vaults into liquid staking tokens. This process enables stakers to utilize their assets in the DeFi ecosystem without losing staking rewards. By minting osETH, users can maintain liquidity and flexibility while contributing to network security. The amount of osETH that can be minted is determined by the staked ETH value, current exchange rate, and a 90% minting threshold set by the StakeWise DAO. This ensures that osETH remains overcollateralized, providing robust backing and value stability.

</details>

<details>

<summary>🔥 Burning osETH: Redeeming Staked ETH</summary>

Burning osETH is destroying osETH tokens to reclaim the underlying staked ETH. When users wish to unstake their ETH, they must return the minted osETH, which is then burned. This reduces the total supply of osETH and unlocks the corresponding staked ETH. During this process, a 5% commission on the rewards accumulated by osETH is automatically deducted, ensuring the integrity of the staking process. This novel commission structure helps maintain osETH’s value and ensures it remains fully backed by staked ETH.

</details>

<details>

<summary>📤 Unstaking: Reclaiming Your ETH</summary>

Unstaking allows users to withdraw their staked ETH from a Vault, stopping the accrual of staking rewards and regaining control over their assets. The process begins with the user initiating an unstaking request, which uses available unbonded ETH in the Vault to fulfill it. If there isn’t enough unbonded ETH, a sufficient number of Vault validators will be exited to provide the necessary ETH. This process can take time, so users are placed in an exit queue until the validators are exited. While in the exit queue, users continue to earn staking rewards. Once the exit is complete, users can claim their unstaked ETH at any time.

</details>

## Setting Up the Staker

To get started with staking on the Ethereum network using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes, we will use the Hoodi testnet.

First, create an instance of `EthereumStaker` with the necessary configuration:

```javascript
import { EthereumStaker } from '@chorus-one/ethereum'

const staker = new EthereumStaker({
  network: 'hoodi',
  rpcUrl: 'https://ethereum-hoodi-rpc.publicnode.com'
})
```

**Configuration Parameters**:

* **network**: The Ethereum network to connect to. It can be `mainnet` or `hoodi`.
* **rpcUrl**: (Optional) The URL of the Ethereum network RPC endpoint. This is where the SDK will connect to interact with the network. If not provided, the SDK will use the public RPC endpoint for the specified network.

***

## Initializing the Staker

After configuring the `EthereumStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker is set up, you can start building transactions for staking operations.

The `EthereumStaker` class provides methods to build transactions for staking, unstaking, merging and splitting stakes, and creating stake accounts.

* You can learn more about these methods in the [Methods](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/ethereum/methods.md) section.

**Example of building a staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1' // 1 ETH
})
```

{% hint style="info" %}
**Delegation Tracking**

For more information on tracking and attributing staking transactions to specific sources, such as marketing campaigns or integration partners, refer to the [Delegation Tracking](/build-your-staking-dapp/ethereum/delegation-tracking) section.
{% endhint %}

### Ensuring Correct Amount Format for Staking

The `amount` parameter must be a string representing the amount of ETH to deposit. For example, `'1'` represents 1 ETH.

If you have the amount as a `bigint`, convert it to a string using the `formatEther` function from `viem`. Example:

```typescript
import { formatEther } from 'viem'

const amountBigInt = 10000000000000000n // 0.01 ETH
const amountToStake = formatEther(amountBigInt)

console.log(amountToStake) // "0.01"
```

This ensures the `amountToStake` parameter is in the correct format for the staking transaction function.

***

## Getting the Validator Address provided by Chorus One

The `@chorus-one/ethereum` module includes a list of Chorus One validators for the Ethereum-compatible chains, organized by network(ethereum or hoodi) and vault type. You can use these addresses when building transactions.

### Vault Types

* **Max Vault (maxVault)**: This vault leverages Chorus One’s proprietary strategies to maximize staking rewards through innovative and evolving approaches. Historically, it has benefited from early adoption of Restaking and Looped Staking in collaboration with Stakewise. Chorus One continues to leverage in-house research to capture reward-enhancing opportunities as they arise, delivering maximum rewards to delegators.
* **Obol Distributed Validator Technology (obolDvVault)**: This vault uses [Obol's DVT](https://docs.obol.org/docs/int/Overview) to enhance resilience and decentralization of Ethereum staking by distributing validator duties across multiple nodes.

```javascript
import { CHORUS_ONE_ETHEREUM_VALIDATORS } from '@chorus-one/ethereum'

const validatorAddress = CHORUS_ONE_ETHEREUM_VALIDATORS.hoodi.maxVault
console.log(vaultAddress) // '0x95d0db03d59658e1af0d977ecfe142f178930ac5'
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```javascript
const signedTx = await yourWalletClient.signTransaction(tx)
```

When using your own signer, you will need to calculate the transaction fees yourself before signing.

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using wagmi/Viem for Signing" %}
By integrating wagmi, you can take advantage of its lightweight developer-friendly wallet client capabilities to sign transactions on the Ethereum network:

```javascript
import { useWalletClient } from 'wagmi'

const { data: walletClient } = useWalletClient()

// Prepare the transaction and estimate the gas fees
const request = await walletClient.prepareTransactionRequest(tx)

// Sign and broadcast the transaction
const hash = await walletClient.sendTransaction(request)
```

For more information please refer to the [Viem Documentation](https://viem.sh/)
{% endtab %}

{% tab title="Using Ethers for Signing" %}
By integrating Ethers, you can use its widely adopted and feature-rich library for signing transactions on the Ethereum network:

```javascript
import { BrowserProvider } from 'ethers'

const provider = new BrowserProvider(window.ethereum)
const signer = await provider.getSigner()

// Estimate gas fees
const feeData = await provider.getFeeData()
const gasLimit = await provider.estimateGas(tx)

// Sign and broadcast the transaction
const { hash } = await signer.sendTransaction({
  ...tx,
  // Optional: Set the gas limit and fees
  gasLimit: gasLimit,
  maxFeePerGas: feeData.maxFeePerGas,
  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
})
```

For more information please refer to the [Ethers Documentation](https://docs.ethers.org/)
{% endtab %}

{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Ethereum network. To set up Fireblocks, you will need to provide the necessary API key, secret key, and vault ID:

```javascript
import { EthereumStaker } from '@chorus-one/ethereum'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'ETH_TEST6',
  addressDerivationFn: EthereumStaker.getAddressDerivationFn()
})

await signer.init()

// Just sign the transaction
const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  tx,
  baseFeeMultiplier: 2, // Optional: Multiplier for the base fee per gas
  defaultPriorityFee: '2' // Optional: Override for the maxPriorityFeePerGas
})
```

#### Configuring Transaction Fees

When signing transactions, you can optionally configure the fees to manage cost and priority. The `fees` parameter allows you to specify a `baseFeeMultiplier` and a `defaultPriorityFee`.

* **`baseFeeMultiplier`**: (Optional) This multiplier helps manage fee fluctuations by adjusting the base fee per gas from the latest block. For example, if the `baseFeeMultiplier` is set to 2, the final `maxFeePerGas` will be 2 times the base fee. The default value is 1.2.
* **`defaultPriorityFee`**: (Optional) This value allows you to override the `maxPriorityFeePerGas` estimated by the RPC. You can specify a fixed value to ensure that your transaction has a certain priority. By default, the `maxPriorityFeePerGas` is calculated by the RPC.

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Ethereum network using the Hoodi testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `EthereumStaker` continue to the [Methods](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/ethereum/methods.md) section.

## Further Reading

* [EthereumStaker API Reference](/api-reference/stakers/ethereum_src.ethereumstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Native Staking

This section provides an overview of the key methods available in the **Chorus One SDK** for **Native Staking** on the Ethereum network.

The Chorus One Native Staking SDK supports a range of staking operations including creating validator batches, retrieving batch status, exporting deposit data, building deposit transactions, and submitting validator exits. Below, we will explore each method with practical examples to help you get started.

### Setting Up the Staker

To get started with staking on the Ethereum network using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes, we will use the Hoodi testnet.

First, create an instance of `EthereumStaker` with the necessary configuration:

```javascript
import { EthereumStaker } from '@chorus-one/ethereum'

const staker = new EthereumStaker({
  network: 'hoodi',
  rpcUrl: 'https://ethereum-hoodi-rpc.publicnode.com',
  nativeStakingApiToken: 'your-auth-token' // Get this from Chorus One
})
```

**Configuration Parameters**:

* **network**: The Ethereum network to connect to. It can be `mainnet` or `hoodi`.
* **rpcUrl**: (Optional) The URL of the Ethereum network RPC endpoint. This is where the SDK will connect to interact with the network. If not provided, the SDK will use the public RPC endpoint for the specified network.
* **nativeStakingApiToken**: Your authentication token for accessing the Chorus One Native Staking API. You can obtain this token by reaching out to our team

***

### Initializing the Staker

After configuring the `EthereumStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

### createValidatorBatch

#### Description

The `createValidatorBatch` method creates a new batch of validators with each validator requires 32 ETH to be deposited. The batch will generate deposit data that can be used to deposit validators on the Ethereum network.

#### How to Use

To create validators, you need to specify a UUID batch id, an Ethereum withdrawal address, a fee recipient address, the number of validators, and an authentication token received from our team.

**Note**: A single batch request can not exceed 200 validators, if you need more, please issue multiple batch requests.

#### Example

```javascript
const result = await staker.createValidatorBatch({
  batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20',
  withdrawalAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  feeRecipientAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  numberOfValidators: 2
})
```

In this example, we're staking 64 ETH with two validators in a batch.

***

### getValidatorBatchStatus

#### Description

The `getValidatorBatchStatus` method retrieves the current status of a validator batch, including the deposit data for each validator when ready.

#### How to Use

To retrieve the status of a validator batch, you need to specify the batch id of the validator batch.

#### Example

```javascript
const status = await staker.getValidatorBatchStatus({ batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20' })
```

***

### listValidatorBatches

#### Description

The `listValidatorBatches` method retrieves all validator batches that have been created for the authenticated tenant. This method is useful for getting an overview of all your validator batches and their current status.

#### How to Use

This method doesn't require any parameters and returns a list of all validator batches associated with your API token.

#### Example

```javascript
const batches = await staker.listValidatorBatches()
```

***

### exportDepositData

#### Description

The `exportDepositData` method retrieves the deposit data for a batch and formats it for use with the official Ethereum Staking Launchpad or other deposit tools.

#### How to Use

To export the deposit data for a batch, you need to provide the batch data object. This is typically obtained from `getValidatorBatchStatus` method.

#### Example

```javascript
// First get the batch data
const batchData = await staker.getValidatorBatchStatus({ batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20' })

// Then export the deposit data
const { depositData } = await staker.exportDepositData({ batchData })
```

***

### buildDepositTx

#### Description

The `buildDepositTx` method creates transactions for depositing validators to the Ethereum deposit contract. Each validator requires exactly 32 ETH to be deposited along with the deposit data.

#### How to Use

To build the deposit transaction for a batch, you need to provide the batch data object. This is typically obtained from `getValidatorBatchStatus` method.

#### Example

```javascript
// First get the batch data
const batchData = await staker.getValidatorBatchStatus({ batchId: '4da22c97-b7d5-4e31-8c3a-03870ebc7b20' })

// Then build the deposit transactions
const { transactions } = await staker.buildDepositTx({ batchData })
```

***

### buildValidatorExitTx

#### Description

The `buildValidatorExitTx` method creates a withdrawal request transaction for exiting validators from the Ethereum network based on [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002). This method triggers a full validator exit through the execution layer withdrawal credentials (0x01).

#### How to Use

To build the exit transaction for a validator, you need to provide the validator's public key. A validator can only exit if it is eligible to do so, which means it must have been active for at least 256 epochs.

**Parameters:**

* `validatorPubkey` (required): The validator's public key (48 bytes)
* `value` (optional): The amount of ETH to send with the transaction. Defaults to **1 wei** (the minimum valid fee)

#### Example

```javascript
const { tx } = await staker.buildValidatorExitTx({
  validatorPubkey: '8c3a5e3f4b2c1d6e7f8a9b0c1d2e3f4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f'
})
```

#### Understanding Withdrawal Request Fees

EIP-7002 implements a dynamic fee mechanism for withdrawal requests that grows **exponentially** based on the withdrawal queue length.

When the withdrawal queue is congested (many pending requests), this exponential calculation can result in extremely high fees (potentially thousands of ETH) see [fee analysis docs](https://eips.ethereum.org/assets/eip-7002/fee_analysis). However, for normal validator exits:

* **Most validator exits use 1 wei**: Since validators exit through the consensus layer, the minimum fee is typically sufficient
* **High fees only apply during congestion**: if there is a long queue of withdrawal requests, fees can rise significantly
* **You can calculate fees beforehand**: Use the `getWithdrawalQueue` utility (see below) if you need to check current fees

***

### getWithdrawalQueue

#### Description

The `getWithdrawalQueue` utility function allows you to query the current withdrawal request queue status and calculate the dynamic fee based on EIP-7002. This is useful if you want to inspect the current network conditions before building a validator exit transaction.

#### How to Use

The function requires an Ethereum public client (from viem) and a network configuration object.

**Returns:**

* `length`: The current number of pending withdrawal requests in the queue
* `fee`: The calculated fee in wei based on the current queue length

#### Example

```javascript
import { EthereumStaker, getWithdrawalQueue } from '@chorus-one/ethereum'

const staker = new EthereumStaker({
  network: 'mainnet',
  rpcUrl: 'https://ethereum-rpc.publicnode.com'
})
await staker.init()

// Get the withdrawal queue status
const queue = await getWithdrawalQueue(staker.connector.eth, staker.getNetworkConfig())

console.log(`Queue length: ${queue.length}`)
console.log(`Calculated fee: ${queue.fee} wei`)

const { tx } = await staker.buildValidatorExitTx({
  validatorPubkey: '8c3a5e3f4b2c1d6e7f8a9b0c1d2e3f4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f',
  value: queue.fee
})
```

***

### Further Reading

* [Chorus One Ethereum Native Staking](https://kb.chorus.one/our-products/chorus-one-ethereum-native-staking)
* [Native Staking API Integration](https://kb.chorus.one/our-products/chorus-one-ethereum-native-staking/api-integration-guide)


# Delegation Tracking

## Introduction

Delegation tracking enables businesses to precisely attribute staking activities to specific campaigns, partners, or sources.

Understanding the origin and impact of your staking transactions is important for maximizing marketing efforts and partnership strategies. With these insights into the performance of your marketing campaigns and partner engagements you can ensure that your resources are directed towards the most effective initiatives and generate accurate revenue reports.

## How It Works

This section will show you how to implement delegation tracking using the Chorus One SDK.

The `referrer` field in the SDK allows you to associate transactions with a specific Ethereum address, representing the source of the delegation or minting, such as a marketing campaign or integration partner.

Including this field as a parameter in both the `buildStakeTx` and `buildMintTx` methods provides detailed insights and accurate attribution of delegations and minting transactions tailored to your specific needs.

{% hint style="info" %}
To ensure precise tracking and management of transaction origins, it is important to use unique addresseses for different customers or campaigns.

It is advisable to generate a unique Ethereum address for each referrer or use your own Ethereum address to track transactions.
{% endhint %}

### Example Usage

Here's an example of how to use the `referrer` field when building a staking transaction:

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1', // 1 ETH
  referrer: '0xReferrerAddressHere' // Unique Ethereum address for tracking
})
```

And here is an example of how to use the `referrer` field when building a minting transaction:

```javascript
const { tx } = await staker.buildMintTx({
  delegatorAddress: '0x70aEe8a9099ebADB186C2D530F72CF5dC7FE6B30',
  validatorAddress: '0xe6d8d8ac54461b1c5ed15740eee322043f696c08',
  amount: '1', // 1 osETH
  referrer: '0xReferrerAddressHere' // Unique Ethereum address for tracking
})
```

## Benefits for Your Business

Leveraging delegation tracking via the Chorus One SDK ensures that your business remains at the forefront of industry developments and provides important benefits and insights for delegation activity such as:

**Accurate Reporting:**

* Delegation tracking ensures accurate revenue tracking to the right partners or campaigns and provides clear revenue reports for different referral sources.
* It allows evaluation of partner performance by tracking staking transaction volume, value, and measuring campaign success by analyzing which referrers generate the most delegations.
* Delegation tracking also ensures that all activities are documented and accountable, facilitating smoother audits, compliance, and financial reporting.
* Detailed delegation reports can be shared with clients as needed, providing them with insights into their holdings and fostering transparency.

**Strategic Planning:**

* Delegation tracking provides clear and detailed insights into delegation activities, enabling businesses to maintain transparency and build trust with stakeholders.
* Tracking customer behavior and preferences to improve engagement strategies and implement retention strategies for high-value customers based on delegation data.
* Access to real-time delegation data allows your business to make informed decisions, optimize strategies, and respond promptly to market changes.
* Historical delegation data can be analyzed to forecast trends and improve business strategy and long-term planning.

**Performance Monitoring:**

* By tracking delegations, businesses can identify high-performing assets and allocate resources more effectively to maximize returns.
* Continuous tracking of delegations helps in monitoring the performance of delegated assets, ensuring you can identify and address underperforming areas swiftly.
* Automated tracking reduces the need for manual monitoring, saving time and reducing errors.

## Conclusion

Using delegation tracking in the Chorus One SDK optimizes strategies and partnerships for your business by providing accurate attribution and insights into customer staking activity while also enabling precise revenue tracking.

This allows your business to stay competitive and allocate resources effectively as well as maintain accurate financial records and reporting.


# Hyperliquid


# Overview

The Chorus One SDK simplifies staking on **Hyperliquid**, a high-performance Layer 1 blockchain powered by the HyperBFT consensus algorithm. This SDK enables developers to build staking applications that interact with Hyperliquid's unique account model and delegated proof-of-stake system.

{% hint style="info" %}
Hyperliquid uses **HyperCore** for its staking infrastructure, featuring a dual-account model (spot and staking), instant delegation operations, and a time-weighted reward distribution system. The network employs **HyperBFT consensus** with validator jailing mechanisms to ensure network reliability.
{% endhint %}

## Understanding Hyperliquid Staking

### Account Model

Hyperliquid uses a dual-account structure similar to how USDC can be transferred between perpetuals and spot accounts:

* **Spot Account**: Your main trading and holding account for HYPE tokens
* **Staking Account**: A dedicated account for staking operations and delegations

**Transfer Characteristics:**

* **Spot → Staking**: Instant transfers (no waiting period)
* **Staking → Spot**: 7-day unstaking queue (maximum 5 pending withdrawals per address)

### Delegation System

Hyperliquid implements delegated proof-of-stake with the following characteristics:

**Delegation Mechanics:**

* **1-day lockup period** per validator delegation - Once you delegate tokens to a validator, you must wait 24 hours before you can undelegate those specific tokens. After the lockup expires, you can undelegate partially or fully at any time.
* Undelegation is **instant** (tokens return to staking account immediately, not to spot)
* You can delegate to multiple validators simultaneously
* Minimum validator self-delegation: **10,000 HYPE**

### Reward Mechanics

Hyperliquid's staking rewards follow an Ethereum-inspired model:

**Reward Formula:**

* Reward rate is inversely proportional to the square root of total HYPE staked
* Rewards come from the future emissions reserve

**Distribution Schedule:**

* Rewards **accrue every minute** based on validator performance
* **Distributed daily** to all delegators
* **Auto-compounded** to your delegated stake (no manual claiming required)
* Based on **minimum balance** held during each staking epoch

## Setting Up the Staker

To set up the Hyperliquid Staker, you need to specify the network chain:

```javascript
import { HyperliquidStaker } from '@chorus-one/hyperliquid'

const staker = new HyperliquidStaker({
  chain: 'Testnet' // or 'Mainnet'
})
```

**Configuration Options:**

* `chain`: `'Mainnet'` | `'Testnet'` (required)

The staker uses Hyperliquid's REST API endpoints (`/info` and `/exchange`) and doesn't require RPC connections or additional configuration.

## Getting the Validator Address provided by Chorus One

The `@chorus-one/hyperliquid` module includes the `CHORUS_ONE_HYPERLIQUID_VALIDATOR` constant, which contains the Chorus One mainnet validator address for building transactions.

```javascript
import { CHORUS_ONE_HYPERLIQUID_VALIDATOR } from '@chorus-one/hyperliquid'

const validatorAddress = CHORUS_ONE_HYPERLIQUID_VALIDATOR
```

## Building Transactions

Hyperliquid transactions use **EIP-712 typed data signing**, which differs from standard Ethereum transactions. The SDK provides a three-step workflow:

### Transaction Workflow

**1. Build the unsigned transaction:**

```javascript
const { tx } = await staker.buildSpotToStakingTx({
  amount: '100' // Amount in HYPE
})
```

The SDK automatically converts the amounts in HYPE to Hyperliquid's 8-decimal wei format internally.

**2. Sign the transaction:**

```javascript
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})
```

All Chorus One signers (Fireblocks, Local, etc.) work seamlessly with the Hyperliquid SDK.

**3. Broadcast the signed transaction:**

```javascript
const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Transaction hash:', txHash)
```

{% hint style="warning" %}
**Transaction Confirmation**: Hyperliquid's API doesn't provide transaction status queries. Use `getDelegatorHistory()` to verify that your transaction was successfully processed.
{% endhint %}

### Verifying Transaction Success

Since Hyperliquid doesn't support transaction status queries, verify using delegation history:

```javascript
// Wait a few seconds for transaction processing
await new Promise((resolve) => setTimeout(resolve, 1000))

// Check recent history
const history = await staker.getDelegatorHistory({
  delegatorAddress: '0xYourAddress'
})

const recentEvents = history.slice(0, 5)
console.log('Recent events:', recentEvents)
```

## Staking Workflow Example

Here's a complete workflow showing how to stake HYPE tokens to a validator:

```javascript
import { HyperliquidStaker } from '@chorus-one/hyperliquid'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'
import { CHORUS_ONE_HYPERLIQUID_VALIDATOR } from '@chorus-one/hyperliquid'

// 1. Setup
const staker = new HyperliquidStaker({ chain: 'Mainnet' })

const signer = new FireblocksSigner({...})
await signer.init()

const delegatorAddress = '0xYourAddress'
const validatorAddress = CHORUS_ONE_HYPERLIQUID_VALIDATOR

// 2. Check current balances
const spotBalances = await staker.getSpotBalances({
  delegatorAddress
})
const hypeBalance = spotBalances.balances.find(b => b.coin === 'HYPE')
console.log('Spot HYPE:', hypeBalance?.total)

const summary = await staker.getStakingSummary({ delegatorAddress })
console.log('Undelegated (staking account):', summary.undelegated)
console.log('Delegated to validators:', summary.delegated)

// 3. Transfer from Spot to Staking (instant)
const { tx: transferTx } = await staker.buildSpotToStakingTx({
  amount: '100'
})

const { signedTx: signedTransfer } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: transferTx
})

const { txHash: transferHash } = await staker.broadcast({
  signedTx: signedTransfer,
  delegatorAddress
})

console.log('Transfer hash:', transferHash)

// 4. Delegate to validator (1-day lockup starts)
const { tx: stakeTx } = await staker.buildStakeTx({
  validatorAddress,
  amount: '100'
})

const { signedTx: signedStake } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: stakeTx
})

const { txHash: stakeHash } = await staker.broadcast({
  signedTx: signedStake,
  delegatorAddress
})

console.log('Stake hash:', stakeHash)

// 5. Verify delegation
await new Promise(resolve => setTimeout(resolve, 1000))

const updatedSummary = await staker.getStakingSummary({ delegatorAddress })
console.log('Delegated amount:', updatedSummary.delegated)

// To see individual delegations, use getDelegations()
const delegations = await staker.getDelegations({ delegatorAddress })
console.log('Current delegations:', delegations)
```

## Common Operations

### Query Staking Information

```javascript
// Get complete staking summary
const summary = await staker.getStakingSummary({
  delegatorAddress: '0xYourAddress'
})

console.log('Delegated (staked to validators):', summary.delegated)
console.log('Undelegated (available in staking account):', summary.undelegated)
console.log('Total Pending Withdrawals:', summary.totalPendingWithdrawal)
console.log('Number of Pending Withdrawals:', summary.nPendingWithdrawals)

// Get staking rewards
const rewards = await staker.getDelegatorRewards({
  delegatorAddress: '0xYourAddress'
})

console.log('Rewards by validator:', rewards)
```

### Unstaking Flow

To move staked tokens back to your spot account (two steps required):

```javascript
// Step 1: Undelegate from validator (instant → staking account)
const { tx: unstakeTx } = await staker.buildUnstakeTx({
  validatorAddress: '0xValidatorAddress',
  amount: '50'
})

const { signedTx: signedUnstake } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: unstakeTx
})

await staker.broadcast({
  signedTx: signedUnstake,
  delegatorAddress
})

// Step 2: Withdraw from staking to spot (7-day queue)
const { tx: withdrawTx } = await staker.buildWithdrawFromStakingTx({
  amount: '50'
})

const { signedTx: signedWithdraw } = await staker.sign({
  signer,
  signerAddress: delegatorAddress,
  tx: withdrawTx
})

await staker.broadcast({
  signedTx: signedWithdraw,
  delegatorAddress
})

console.log('Withdrawal initiated - will complete in 7 days')
```

## Next Steps

* Explore detailed method documentation in [Methods](/build-your-staking-dapp/hyperliquid/methods)
* Review the [HyperliquidStaker API Reference](/api-reference/stakers/hyperliquid_src.hyperliquidstaker)
* Check out the example applications in the SDK repository

## Further Reading

* [Hyperliquid Staking Documentation](https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/staking)
* [Hyperliquid API Documentation](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api)


# Methods

This section provides detailed documentation for all methods available in the **HyperliquidStaker** class. Each method includes parameters, return values, and practical examples.

***

## buildSpotToStakingTx

Builds a transaction to transfer HYPE tokens from your spot account to your staking account. This transfer is instant and is the first step before you can delegate tokens to validators.

### Parameters

| Parameter | Type   | Required | Description                  |
| --------- | ------ | -------- | ---------------------------- |
| `amount`  | string | Yes      | Amount in HYPE (e.g., '100') |

### Response

```typescript
{
  tx: UnsignedTx // Transaction object for signing
}
```

### Example

```javascript
const { tx } = await staker.buildSpotToStakingTx({
  amount: '100' // Transfer 100 HYPE to staking account
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Transfer transaction hash:', txHash)
```

{% hint style="info" %}
Transfers from spot to staking are **instant**. Once confirmed, the balance immediately appears in your staking account.
{% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#deposit-into-staking)

***

## buildWithdrawFromStakingTx

Builds a transaction to transfer HYPE tokens from your staking account back to your spot account. Withdrawals enter a 7-day unstaking queue, and each address can have a maximum of 5 pending withdrawals.

### Parameters

| Parameter | Type   | Required | Description                 |
| --------- | ------ | -------- | --------------------------- |
| `amount`  | string | Yes      | Amount in HYPE (e.g., '50') |

### Response

```typescript
{
  tx: UnsignedTx // Transaction object for signing
}
```

### Example

```javascript
const { tx } = await staker.buildWithdrawFromStakingTx({
  amount: '50' // Withdraw 50 HYPE to spot account
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Withdrawal initiated, will complete in 7 days')
```

{% hint style="warning" %}
**Withdrawal Limits:**

* Each withdrawal takes exactly **7 days** from submission time
* Maximum of **5 pending withdrawals** per address
* You must have sufficient **unstaked balance** in your staking account (undelegate from validators first if needed)
  {% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#withdraw-from-staking)

***

## buildStakeTx

Builds a transaction to delegate (stake) HYPE tokens from your staking account to a validator. Each delegation has a 1-day lockup period before it can be undelegated.

### Parameters

| Parameter          | Type   | Required | Description                                                    |
| ------------------ | ------ | -------- | -------------------------------------------------------------- |
| `validatorAddress` | string | Yes      | Validator's address in 42-character hexadecimal format (0x...) |
| `amount`           | string | Yes      | Amount in HYPE (e.g., '100')                                   |

### Response

```typescript
{
  tx: UnsignedTx // Transaction object for signing
}
```

### Example

```javascript
const validatorAddress = '0xValidatorAddress'

const { tx } = await staker.buildStakeTx({
  validatorAddress,
  amount: '100' // Stake 100 HYPE to this validator
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Delegation transaction hash:', txHash)

// Verify delegation after a few seconds
await new Promise((resolve) => setTimeout(resolve, 3000))

const summary = await staker.getStakingSummary({
  delegatorAddress: '0xYourAddress'
})

const delegation = summary.delegations.find((d) => d.validatorAddress === validatorAddress)
console.log('Staked amount:', delegation?.amount)
```

{% hint style="info" %}
**Delegation Considerations:**

* Each delegation has a **1-day lockup** per validator
* You can delegate to **multiple validators** simultaneously
  {% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#delegate-or-undelegate-stake-from-validator)

***

## buildUnstakeTx

Builds a transaction to undelegate (unstake) HYPE tokens from a validator. Undelegation is instant - tokens immediately return to your staking account (not your spot account).

### Parameters

| Parameter          | Type   | Required | Description                                                    |
| ------------------ | ------ | -------- | -------------------------------------------------------------- |
| `validatorAddress` | string | Yes      | Validator's address in 42-character hexadecimal format (0x...) |
| `amount`           | string | Yes      | Amount in HYPE (e.g., '25')                                    |

### Response

```typescript
{
  tx: UnsignedTx // Transaction object for signing
}
```

### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  validatorAddress: '0xValidatorAddress',
  amount: '25' // Undelegate 25 HYPE from this validator
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Undelegation complete - tokens returned to staking account')
```

{% hint style="warning" %}
**Important:** Undelegation only moves HYPE back to your **staking account**, not your spot account. To move tokens to your spot account, you must also call `buildWithdrawFromStakingTx()` which has a 7-day waiting period.
{% endhint %}

**Complete Unstaking Flow:**

```javascript
// Step 1: Undelegate from validator (instant)
const { tx: unstakeTx } = await staker.buildUnstakeTx({
  validatorAddress: '0xValidatorAddress',
  amount: '25'
})

const { signedTx: signedUnstake } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx: unstakeTx
})

await staker.broadcast({
  signedTx: signedUnstake,
  delegatorAddress: '0xYourAddress'
})

// Step 2: Withdraw to spot account (7-day queue)
const { tx: withdrawTx } = await staker.buildWithdrawFromStakingTx({
  amount: '25'
})

const { signedTx: signedWithdraw } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx: withdrawTx
})

await staker.broadcast({
  signedTx: signedWithdraw,
  delegatorAddress: '0xYourAddress'
})
```

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#delegate-or-undelegate-stake-from-validator)

***

## getStakingSummary

Retrieves a summary of staking information for an address, including total delegated amount, undelegated balance in staking account, and pending withdrawals. This is a read-only operation with no gas costs.

### Parameters

| Parameter          | Type   | Required | Description              |
| ------------------ | ------ | -------- | ------------------------ |
| `delegatorAddress` | string | Yes      | Address to query (0x...) |

### Response

```typescript
{
  delegated: string // Total HYPE delegated to validators (string with 8 decimals)
  undelegated: string // HYPE available in staking account (string with 8 decimals)
  totalPendingWithdrawal: string // Total HYPE in 7-day withdrawal queue (string with 8 decimals)
  nPendingWithdrawals: number // Number of pending withdrawal requests (max 5)
}
```

### Example

```javascript
const summary = await staker.getStakingSummary({
  delegatorAddress: '0xYourAddress'
})

console.log('Delegated to validators:', summary.delegated, 'HYPE')
console.log('Available in staking account:', summary.undelegated, 'HYPE')
console.log('Pending withdrawals:', summary.totalPendingWithdrawal, 'HYPE')
console.log('Number of pending withdrawals:', summary.nPendingWithdrawals, '/ 5')

// Calculate total HYPE in staking system
const totalInStaking = (
  parseFloat(summary.delegated) +
  parseFloat(summary.undelegated) +
  parseFloat(summary.totalPendingWithdrawal)
).toFixed(8)

console.log('Total in staking system:', totalInStaking, 'HYPE')
```

{% hint style="info" %}
This method provides a high-level overview of your staking position. To see individual delegations by validator, use `getDelegations()`. Note that this doesn't include your spot account balance - use `getSpotBalances()` for that.
{% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-a-users-staking-summary)

***

## getDelegations

Retrieves all active delegations for an address, showing individual validator delegations with amounts and lockup status. This is a read-only operation with no gas costs.

### Parameters

| Parameter          | Type   | Required | Description              |
| ------------------ | ------ | -------- | ------------------------ |
| `delegatorAddress` | string | Yes      | Address to query (0x...) |

### Response

```typescript
Array<{
  validator: string // Validator's Ethereum address
  amount: string // Delegated amount (string with 8 decimals)
  lockedUntilTimestamp: number // Unix timestamp when delegation lock expires
}>
```

### Example

```javascript
const delegations = await staker.getDelegations({
  delegatorAddress: '0xYourAddress'
})

console.log('Active Delegations:')
delegations.forEach((delegation, index) => {
  console.log(`\nDelegation ${index + 1}:`)
  console.log(`  Validator: ${delegation.validator}`)
  console.log(`  Amount: ${delegation.amount} HYPE`)

  const lockExpiry = new Date(delegation.lockedUntilTimestamp * 1000)
  const isLocked = Date.now() < delegation.lockedUntilTimestamp * 1000

  console.log(`  Lock Status: ${isLocked ? 'Locked' : 'Unlocked'}`)
  console.log(`  Lock Expires: ${lockExpiry.toISOString()}`)
})

// Calculate total delegated
const totalDelegated = delegations.reduce((sum, d) => {
  return sum + parseFloat(d.amount)
}, 0)

console.log(`\nTotal Delegated: ${totalDelegated.toFixed(8)} HYPE`)
```

{% hint style="info" %}
**Lockup Status**: Each delegation has a `lockedUntilTimestamp`. If the current time is before this timestamp, you must wait before undelegating. After the lockup expires, you can undelegate any amount at any time.
{% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-a-users-staking-delegations)

***

## getSpotBalances

Retrieves spot account balances for all tokens, including HYPE and USDC. This is a read-only operation with no gas costs.

### Parameters

| Parameter          | Type   | Required | Description              |
| ------------------ | ------ | -------- | ------------------------ |
| `delegatorAddress` | string | Yes      | Address to query (0x...) |

### Response

```typescript
{
  balances: Array<{
    coin: string // Token symbol ('HYPE', 'USDC', etc.)
    hold: string // Amount held in open orders
    total: string // Total balance including held amounts
  }>
}
```

### Example

```javascript
const { balances } = await staker.getSpotBalances({
  delegatorAddress: '0xYourAddress'
})

// Find HYPE balance
const hypeBalance = balances.find((b) => b.coin === 'HYPE')
if (hypeBalance) {
  console.log('HYPE Total:', hypeBalance.total)
  console.log('HYPE In Orders:', hypeBalance.hold)
  console.log('HYPE Available:', (parseFloat(hypeBalance.total) - parseFloat(hypeBalance.hold)).toFixed(8))
}

// Find USDC balance
const usdcBalance = balances.find((b) => b.coin === 'USDC')
if (usdcBalance) {
  console.log('USDC Balance:', usdcBalance.total)
}

// Display all balances
console.log('\nAll Balances:')
balances.forEach((balance) => {
  console.log(`${balance.coin}: ${balance.total}`)
})
```

{% hint style="info" %}
The `hold` field represents tokens locked in open trading orders. To calculate available balance for transfers, subtract `hold` from `total`.
{% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-a-users-token-balances)

***

## getDelegatorRewards

Retrieves staking rewards history for a delegator. This is a read-only operation with no gas costs.

### Parameters

| Parameter          | Type   | Required | Description              |
| ------------------ | ------ | -------- | ------------------------ |
| `delegatorAddress` | string | Yes      | Address to query (0x...) |

### Response

```typescript
Array<{
  time: number // Unix timestamp of reward
  source: 'delegation' | 'commission' // Source of reward
  totalAmount: string // Total reward amount (string with 8 decimals)
}>
```

### Example

```javascript
const rewards = await staker.getDelegatorRewards({
  delegatorAddress: '0xYourAddress'
})

console.log('Staking Rewards History:')
rewards.slice(0, 10).forEach((reward, index) => {
  const date = new Date(reward.time * 1000)
  console.log(`\nReward ${index + 1}:`)
  console.log(`  Time: ${date.toISOString()}`)
  console.log(`  Source: ${reward.source}`)
  console.log(`  Amount: ${reward.totalAmount} HYPE`)
})

// Calculate total rewards
const totalRewards = rewards.reduce((sum, r) => {
  return sum + parseFloat(r.totalAmount)
}, 0)

console.log(`\nTotal Rewards: ${totalRewards.toFixed(8)} HYPE`)
```

{% hint style="info" %}
**Reward Distribution:**

* Rewards **accrue every minute** based on validator performance
* **Distributed daily** to all delegators
* **Auto-compounded** to your delegated stake (no manual claiming required)
* Based on **minimum balance** held during each staking epoch (100k rounds \~90 minutes)
  {% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-a-users-staking-rewards)

***

## getDelegatorHistory

Retrieves the complete delegation event history for an address. This method is essential for verifying transaction success since Hyperliquid doesn't provide transaction status queries.

### Parameters

| Parameter          | Type   | Required | Description              |
| ------------------ | ------ | -------- | ------------------------ |
| `delegatorAddress` | string | Yes      | Address to query (0x...) |

### Response

```typescript
Array<DelegationHistoryEvent> // Array of delegation events
```

### Example

```javascript
const history = await staker.getDelegatorHistory({
  delegatorAddress: '0xYourAddress'
})

console.log('Recent Delegation History:')
history.slice(0, 10).forEach((event, index) => {
  console.log(`Event ${index + 1}:`, event)
})

// Verify a recent transaction
const recentEvent = history[0]
console.log('Most recent event:', recentEvent)
```

**Verifying Transaction Success:**

```javascript
// After broadcasting a transaction
const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Transaction submitted:', txHash)

// Wait for processing
await new Promise((resolve) => setTimeout(resolve, 3000))

// Check history for confirmation
const history = await staker.getDelegatorHistory({
  delegatorAddress: '0xYourAddress'
})

const recentEvents = history.slice(0, 5)
console.log('Recent events:', recentEvents)

// You can check if your expected event appears in recent history
```

{% hint style="warning" %}
**Transaction Confirmation:** Hyperliquid's API doesn't provide transaction status queries by hash. Always use `getDelegatorHistory()` to verify that your transaction was successfully processed. Wait 2-3 seconds after broadcasting before checking history.
{% endhint %}

**Further Reading**

* [HyperliquidStaker API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-a-users-staking-history)

***

## sign

Signs an unsigned transaction using EIP-712 typed data signing. This method works with any Chorus One signer (Fireblocks, Local, etc.).

### Parameters

| Parameter       | Type       | Required | Description                                           |
| --------------- | ---------- | -------- | ----------------------------------------------------- |
| `signer`        | Signer     | Yes      | Signer instance (FireblocksSigner, LocalSigner, etc.) |
| `signerAddress` | string     | Yes      | Address performing the signature (0x...)              |
| `tx`            | UnsignedTx | Yes      | Transaction object from buildXxxTx methods            |

### Response

```typescript
{
  signedTx: string // Hex-encoded signature ready for broadcast
}
```

### Example

**Using Fireblocks Signer:**

```javascript
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret',
  apiKey: 'your-api-key',
  vaultName: 'your-vault',
  assetId: 'ETH',
  addressDerivationFn: HyperliquidStaker.getAddressDerivationFn()
})

await signer.init()

const { tx } = await staker.buildStakeTx({
  validatorAddress: '0xValidatorAddress',
  amount: '100'
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

console.log('Signed transaction:', signedTx)
```

**Using Local Signer:**

```javascript
import { LocalSigner } from '@chorus-one/signer-local'

const signer = new LocalSigner({
  privateKey: 'your-private-key',
  addressDerivationFn: HyperliquidStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})
```

{% hint style="info" %}
Hyperliquid uses **EIP-712 typed data signing**, not standard Ethereum transactions. The `sign()` method handles the EIP-712 formatting automatically.
{% endhint %}

**Further Reading**

* [Signer Documentation](/signers-explained/what-is-a-signer)

***

## broadcast

Broadcasts a signed transaction to the Hyperliquid network. Returns a transaction hash.

### Parameters

| Parameter          | Type   | Required | Description                                 |
| ------------------ | ------ | -------- | ------------------------------------------- |
| `signedTx`         | string | Yes      | Signed transaction from sign() method       |
| `delegatorAddress` | string | Yes      | Address that signed the transaction (0x...) |

### Response

```typescript
{
  txHash: string // Transaction hash
}
```

### Example

```javascript
const { tx } = await staker.buildSpotToStakingTx({
  amount: '100'
})

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xYourAddress',
  tx
})

const { txHash } = await staker.broadcast({
  signedTx,
  delegatorAddress: '0xYourAddress'
})

console.log('Transaction hash:', txHash)
```

**Further Reading**

* [HyperliquidStaker Exchange API Reference](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint)

***

**Complete Transaction Flow:**

```javascript
async function executeStakingTransaction(staker, signer, delegatorAddress) {
  // 1. Build transaction
  const { tx } = await staker.buildStakeTx({
    validatorAddress: '0xValidatorAddress',
    amount: '100'
  })

  // 2. Sign transaction
  const { signedTx } = await staker.sign({
    signer,
    signerAddress: delegatorAddress,
    tx
  })

  // 3. Broadcast transaction
  const { txHash } = await staker.broadcast({
    signedTx,
    delegatorAddress
  })

  console.log('Transaction broadcasted:', txHash)

  const summary = await staker.getStakingSummary({ delegatorAddress })
  console.log('Updated delegations:', summary.delegations)

  return txHash
}
```

**Error Handling:**

```javascript
try {
  const { txHash } = await staker.broadcast({
    signedTx,
    delegatorAddress: '0xYourAddress'
  })

  console.log('Success:', txHash)
} catch (error) {
  console.error('Broadcast failed:', error.message)

  // Common errors:
  // - Insufficient balance
  // - Stake in lockup period
  // - Invalid signature
  // - Network connectivity issues
  // - API rate limiting
}
```

**Further Reading**

* [Hyperliquid Documentation](https://hyperliquid.gitbook.io/hyperliquid-docs)


# Monad


# Overview

Staking on the Monad network involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
Monad is a high-performance EVM-compatible blockchain that uses a Proof of Stake (PoS) consensus mechanism. The network features native staking through a precompiled contract at address `0x0000000000000000000000000000000000001000`. By staking MON, Monad's native token, validators and delegators maintain the network, secure the blockchain, and earn rewards through an epoch-based system.
{% endhint %}

The **Chorus One SDK** simplifies the staking process on the Monad network, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Monad using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The Monad SDK is built on [viem](https://viem.sh), a modern TypeScript library for Ethereum interactions. This ensures type-safety and compatibility with the Ethereum ecosystem while leveraging Monad's native staking capabilities.
{% endhint %}

## Understanding Monad Staking

### Epoch System

Monad uses an epoch-based staking system with the following characteristics:

* An **epoch** is a range of rounds during which the validator set remains unchanged
* A **boundary block** marks the initial point of the end of an epoch
* The **epoch delay period** is the time between a boundary block and the start of the next epoch
* Stake changes only take effect at epoch boundaries

**Activation Timing:**

Staking operations (delegate, undelegate, compound) submitted:

* **Before the boundary block**: Changes activate in epoch **N+1**
* **During the epoch delay period** (after boundary block): Changes activate in epoch **N+2**

You can check the current timing by calling `getEpoch()`, which returns `inEpochDelayPeriod` boolean.

### Withdrawal System

When you undelegate tokens:

1. Create a **withdrawal request** with a unique ID (0-255)
2. Tokens become **inactive** in the validator set in epoch N+1 (before boundary) or N+2 (during epoch delay period)
3. Upon becoming inactive, the stake moves to a **pending state** for `WITHDRAWAL_DELAY` epochs (currently 1 epoch)
4. Once the delay period passes, call `withdraw()` to move the MON back to your account

You can have up to 256 concurrent withdrawal requests per (validator, delegator) tuple.

***

## Setting Up the Staker

To get started with staking on the Monad network using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes, we will use the Monad testnet.

First, create an instance of `MonadStaker` with the necessary configuration:

```javascript
import { MonadStaker } from '@chorus-one/monad'

const staker = new MonadStaker({
  rpcUrl: 'https://rpc-mainnet.monadinfra.com'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the Monad network RPC endpoint. This is where the SDK will connect to interact with the network.

***

## Initializing the Staker

After configuring the `MonadStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint, fetches the chain ID, and prepares the staker for building transactions.

***

## Getting the Validator ID provided by Chorus One

The `@chorus-one/monad` module includes the `CHORUS_ONE_MONAD_VALIDATORS` constant, which contains the Chorus One validator IDs for building transactions.

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet
```

***

## Building Transactions

Once the staker is set up, you can start building transactions for staking operations.

The `MonadStaker` class provides methods to build transactions for delegating, undelegating, claiming rewards, compounding rewards, and withdrawing.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/monad/methods) section.

**Example of building a delegation transaction:**

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildStakeTx({
  validatorId,
  amount: '1000' // 1000 MON
})
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWalletClient.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

For detailed information on setting up and configuring these options, refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Monad network. To set up Fireblocks, provide the necessary API key, secret key, and vault ID:

```javascript
import { MonadStaker } from '@chorus-one/monad'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'ETH',
  addressDerivationFn: MonadStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Monad network, which included how to build staking transactions, sign, broadcast, and query staking information.

* To learn more about the available methods on `MonadStaker` continue to the [Methods](/build-your-staking-dapp/monad/methods) section.

## Further Reading

* [MonadStaker API Reference](/api-reference/stakers/monad_src.monadstaker)
* [Monad Staking Documentation](https://docs.monad.xyz/developer-essentials/staking/staking-precompile)
* [Viem Documentation](https://viem.sh)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the Monad network.

The Chorus One SDK supports a range of staking operations including delegating, undelegating, claiming rewards, compounding rewards, and withdrawing. Below, we explore each method with practical examples to help you get started.

***

## buildStakeTx

### Description

The `buildStakeTx` method helps you create a transaction for delegating MON tokens to a validator. Delegating tokens involves locking them up to support the validator's operations, and in return you earn staking rewards.

The delegated stake becomes active:

* In epoch N+1 if the delegation is submitted **before the boundary block**
* In epoch N+2 if the delegation is submitted **during the epoch delay period** (after the boundary block)

### How to Use

To build a delegation transaction, you need to specify the validator ID and the amount of MON to delegate.

### Parameters

* **validatorId** (number): Unique identifier for the validator (0 to 2^64-1)
* **amount** (string): Amount to delegate in MON (e.g., "1000" for 1000 MON)

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

// You can use the Chorus One validator ID or specify your own
const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildStakeTx({
  validatorId,
  amount: '1000' // 1000 MON
})
```

In this example, we are delegating 1000 MON to the Chorus One validator. The MON tokens are sent with the transaction and will become active stake in the next epoch or the one after, depending on the current block position in the epoch.

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#buildstaketx)

***

## buildUnstakeTx

### Description

The `buildUnstakeTx` method allows you to create a transaction for undelegating tokens from a validator. This creates a **withdrawal request** that you can complete later using `buildWithdrawTx`.

Undelegating involves deactivating your staked tokens:

* The stake becomes **inactive** in the validator set in epoch N+1 (before boundary block) or N+2 (during epoch delay period)
* Upon becoming inactive, it enters a **pending state** for `WITHDRAWAL_DELAY` epochs (currently 1 epoch)
* After the delay, you can call `withdraw()` to receive your tokens

### How to Use

To build an undelegation transaction, you need to provide:

* Your delegator address
* The validator ID
* The amount to undelegate
* A withdrawal ID (0-255) to track this request

### Parameters

* **delegatorAddress** (Address): Your wallet address that will receive funds after withdrawal
* **validatorId** (number): Unique identifier for the validator
* **amount** (string): Amount to undelegate in MON
* **withdrawalId** (number): User-chosen ID (0-255) to track this withdrawal request

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  validatorId,
  amount: '500', // 500 MON
  withdrawalId: 0 // Use ID 0 to track this withdrawal
})
```

Here, we're undelegating 500 MON from the Chorus One validator and tracking it with withdrawal ID 0.

{% hint style="warning" %}
**Withdrawal IDs**: You can have up to 256 concurrent withdrawal requests per (validator, delegator) pair. Make sure the withdrawal ID you choose is not already in use. After you complete a withdrawal, the ID becomes available for reuse.
{% endhint %}

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#buildunstaketx)

***

## buildWithdrawTx

### Description

The `buildWithdrawTx` method allows you to complete a withdrawal by claiming your undelegated tokens back to your wallet.

You can only withdraw after the withdrawal delay period has passed (current epoch > withdrawal epoch + withdraw delay).

### How to Use

To build a withdrawal transaction, you need to provide the same validator ID and withdrawal ID you used when undelegating.

### Parameters

* **delegatorAddress** (Address): Your wallet address that will receive the funds
* **validatorId** (number): Unique identifier for the validator you undelegated from
* **withdrawalId** (number): The same ID (0-255) you used when calling undelegate

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildWithdrawTx({
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  validatorId,
  withdrawalId: 0
})
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#buildwithdrawtx)

***

## buildCompoundTx

### Description

The `buildCompoundTx` method allows you to convert your accumulated rewards into additional stake (auto-restaking). This increases your total stake and future reward rate.

The compounded rewards follow the same activation timing as regular delegation:

* Epoch N+1 if submitted before the boundary block
* Epoch N+2 if submitted during the epoch delay period

### How to Use

To build a compound transaction, provide your delegator address and the validator ID.

### Parameters

* **delegatorAddress** (Address): Your wallet address
* **validatorId** (number): Unique identifier for the validator to compound rewards for

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildCompoundTx({
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  validatorId
})
```

{% hint style="info" %}
**Validation**: The SDK validates that you have unclaimed rewards > 0 before building the transaction.
{% endhint %}

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#buildcompoundtx)

***

## buildClaimRewardsTx

### Description

The `buildClaimRewardsTx` method allows you to claim your accumulated staking rewards and send them to your wallet as liquid MON tokens.

Rewards are available immediately after the transaction is confirmed.

### How to Use

To build a claim rewards transaction, provide your delegator address and the validator ID.

### Parameters

* **delegatorAddress** (Address): Your wallet address that will receive the rewards
* **validatorId** (number): Unique identifier for the validator to claim rewards from

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const { tx } = await staker.buildClaimRewardsTx({
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  validatorId
})
```

Here, we claim all available rewards and send them to the wallet address.

{% hint style="info" %}
**Validation**: The SDK validates that you have unclaimed rewards > 0 before building the transaction.
{% endhint %}

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#buildclaimrewardstx)

***

## getDelegator

### Description

The `getDelegator` method retrieves complete information about your delegation to a specific validator.

This is a read-only method that doesn't cost gas.

### How to Use

Provide the validator ID and your delegator address to query your staking information.

### Parameters

* **validatorId** (number): Unique identifier for the validator
* **delegatorAddress** (Address): Your wallet address

### Returns

Returns the delegator's `DelInfo` with the following fields:

* **stake** (bigint): Currently active stake earning rewards right now (in wei)
* **unclaimedRewards** (bigint): Rewards available to claim or compound (in wei)
* **deltaStake** (bigint): Pending stake activating at deltaEpoch (in wei)
* **nextDeltaStake** (bigint): Pending stake activating at nextDeltaEpoch (in wei)
* **deltaEpoch** (bigint): Epoch number when deltaStake becomes active
* **nextDeltaEpoch** (bigint): Epoch number when nextDeltaStake becomes active
* **accRewardPerToken** (bigint): Internal accounting value

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const delegatorInfo = await staker.getDelegator({
  validatorId,
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'
})
```

{% hint style="info" %}
**Understanding Pending Stakes**: The two pending slots (`deltaStake` and `nextDeltaStake`) exist because Monad has a boundary block system. Stakes submitted before the boundary activate in epoch N+1 (deltaStake), while stakes submitted after the boundary activate in epoch N+2 (nextDeltaStake).
{% endhint %}

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#getdelegator)

***

## getWithdrawalRequest

### Description

The `getWithdrawalRequest` method retrieves information about a specific withdrawal request.

Use this to check if your undelegated tokens are ready to withdraw.

### How to Use

Provide the validator ID, your delegator address, and the withdrawal ID you used when undelegating.

### Parameters

* **validatorId** (number): Unique identifier for the validator you undelegated from
* **delegatorAddress** (Address): Your wallet address
* **withdrawalId** (number): The ID (0-255) you assigned when calling undelegate

### Returns

Returns the pending `WithdrawalRequest` with:

* **withdrawalAmount** (bigint): Amount in wei that will be returned when you call withdraw (0 if no request exists)
* **withdrawEpoch** (bigint): Epoch when undelegate stake deactivates
* **accRewardPerToken** (bigint): Internal accounting value

### Example

```javascript
import { CHORUS_ONE_MONAD_VALIDATORS } from '@chorus-one/monad'

const validatorId = CHORUS_ONE_MONAD_VALIDATORS.mainnet

const withdrawalRequest = await staker.getWithdrawalRequest({
  validatorId,
  delegatorAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  withdrawalId: 0
})
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#getwithdrawalrequest)

***

## getEpoch

### Description

The `getEpoch` method retrieves current epoch information from the Monad network.

This is useful for understanding when your stake changes will activate and when withdrawals will be ready.

### How to Use

No parameters needed - just call the method.

### Returns

Returns an `EpochInfo` object with:

* **epoch** (bigint): Current epoch number
* **inEpochDelayPeriod** (boolean): Whether we're in the epoch delay period (after the boundary block)

### Understanding inEpochDelayPeriod

* **false**: Before the boundary block → stake changes activate in epoch N+1
* **true**: During the epoch delay period (after boundary block) → stake changes activate in epoch N+2

The **epoch delay period** is the time between the boundary block and the start of the next epoch.

### Example

```javascript
const { epoch, inEpochDelayPeriod } = await staker.getEpoch()
```

{% hint style="info" %}
**Note**: Epochs are measured in consensus rounds, not blocks. Rounds increment even when block proposals timeout, so epoch duration can vary based on network conditions.
{% endhint %}

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#getepoch)

***

## sign

### Description

The `sign` method signs a transaction using the provided signer (e.g., Fireblocks, local mnemonic).

### How to Use

To sign a transaction, you need to provide a signer instance, the signer's address, and the transaction object from any `build*Tx` method.

### Parameters

* **signer** (Signer): A signer instance (e.g., `FireblocksSigner`, `LocalSigner`)
* **signerAddress** (Address): The address of the signer
* **tx** (Transaction): The transaction to sign (from any `build*Tx` method)
* **baseFeeMultiplier** (number, optional): Multiplier applied to the base fee per gas from the latest block to determine `maxFeePerGas`. Defaults to `1.2`.
* **defaultPriorityFee** (string, optional): Overrides the `maxPriorityFeePerGas` estimated by the RPC.

### Example

```javascript
const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
  tx
})
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#sign)

***

## broadcast

### Description

The `broadcast` method broadcasts a signed transaction to the Monad network.

### How to Use

Pass the signed transaction hex string returned by the `sign` method.

### Parameters

* **signedTx** (Hex): The signed transaction to broadcast

### Example

```javascript
const { txHash } = await staker.broadcast({ signedTx })

console.log('Transaction hash:', txHash)
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#broadcast)

***

## getTxStatus

### Description

The `getTxStatus` method retrieves the status of a transaction using the transaction hash.

### How to Use

Provide the transaction hash received from the `broadcast` method.

### Parameters

* **txHash** (Hex): The transaction hash to query

### Returns

Returns the transaction status including:

* **status** (string): Transaction status (`'success'`, `'failure'`, or `'unknown'`)
* **receipt** (object): The full transaction receipt (when available)

### Example

```javascript
const txStatus = await staker.getTxStatus({ txHash })

console.log('Transaction status:', txStatus.status)
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#gettxstatus)

***

## getAddressDerivationFn

### Description

The `getAddressDerivationFn` is a **static** method used to derive an address from a public key. It is used for signer initialization with `FireblocksSigner` or `LocalSigner`.

### How to Use

Call the static method on the `MonadStaker` class and pass it to your signer's `addressDerivationFn` parameter.

### Example

```javascript
import { MonadStaker } from '@chorus-one/monad'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret',
  apiKey: 'your-api-key',
  vaultName: 'your-vault',
  assetId: 'ETH',
  addressDerivationFn: MonadStaker.getAddressDerivationFn()
})

await signer.init()
```

* [Read more in the API Reference](/api-reference/stakers/monad_src.monadstaker#getaddressderivationfn)

***

## Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [MonadStaker API Reference](/api-reference/stakers/monad_src.monadstaker)
* [Monad Staking Documentation](https://docs.monad.xyz/developer-essentials/staking/staking-precompile)


# NEAR


# Overview

Staking on the NEAR blockchain involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The NEAR blockchain, known for its scalability, low transaction fees, and developer-friendly environment, employs a Proof-of-Stake (PoS) consensus mechanism, which allows validators and delegators to participate in maintaining the network.
{% endhint %}

The **Chorus One SDK** simplifies this process, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on NEAR using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular NEAR libraries such as `near-api-js`. This compatibility ensures that you can seamlessly integrate these methods into your existing NEAR projects.
{% endhint %}

### Setting Up the Staker

To get started with staking on the NEAR network using the Chorus One SDK, you will first need to initialize the SDK for NEAR.

* (For testing purposes, we will use the NEAR testnet).

First, create an instance of `NearStaker` with the necessary configuration:

```javascript
import { NearStaker } from '@chorus-one/near'

const staker = new NearStaker({
  networkId: 'testnet',
  rpcUrl: 'https://rpc.testnet.near.org'
})
```

**Configuration Parameters**:

* **networkId**: The network ID of the NEAR network (e.g., `mainnet`, `testnet`)
* **rpcUrl**: The URL of the NEAR network RPC endpoint
* **denomMultiplier**: (Optional) This parameter defines the scaling factor used to convert from the smallest unit of the network’s currency (`yoctoNear`) to its base unit (`NEAR`).

  For the NEAR mainnet, `1 NEAR` is equal to `1,000,000,000 yoctoNear`, hence the multiplier is `1,000,000,000`. This value is used to convert the amount of tokens in transactions.
* **gas**: (Optional) The maximum amount of gas to use for transactions. This value can be adjusted based on the complexity of the transactions.

***

### Initializing the Staker

After configuring the `NearStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

### Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `NearStaker` class provides methods to build transactions for staking, unstaking, and withdrawing rewards.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/near/methods) section.

**Example of building a staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'your.near',
  validatorAddress: 'chorusone.pool.f863973.m0',
  amount: '1' // 1 NEAR
})
```

***

### Getting the Validator Address provided by Chorus One

The `@chorus-one/near` module includes the `CHORUS_ONE_NEAR_VALIDATOR` constant, which contains the Chorus One validator address for building transactions.

```javascript
import { CHORUS_ONE_NEAR_VALIDATOR } from '@chorus-one/near'

const validatorAddress = CHORUS_ONE_NEAR_VALIDATOR
```

***

### Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the NEAR network. To set up Fireblocks, provide the necessary API key, secret key, and vault ID:

```javascript
import { NearStaker } from '@chorus-one/near'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'NEAR_TEST',
  addressDerivationFn: NearStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: 'your.near',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

### Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const {
  transaction: { hash: txHash }
} = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({
  address: 'your.near',
  txHash
})

console.log(status) // 'success'
```

***

### Next Steps

In this section you learned how to set up the Chorus One SDK for the NEAR network using the NEAR testnet, which included how to build staking transactions and sign/broadcast them.

* To learn more about the available methods on `NearStaker`, continue to the [Methods](/build-your-staking-dapp/near/methods) section.

### Further Reading

* [NEARStaker API Reference](/api-reference/stakers/near_src.nearstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)

```
```


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the NEAR network.

The SDK supports various staking operations including staking, unstaking, withdrawing, and retrieving staking information. Below, we explore each method with practical examples to help you get started.

***

### buildStakeTx

#### Description

The `buildStakeTx` method helps you create a transaction for staking tokens with a validator. Staking tokens involves locking them up to support the network's security and operations, and in return you earn rewards.

#### How to Use

To build a staking transaction, you will need to specify the amount to stake, the delegator's address (your wallet), and validator's address where you want to stake your tokens.

#### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: 'your.near',
  validatorAddress: 'chorusone.poolv1.near',
  amount: '1' // 1 NEAR
})
```

In this example, we're staking 1 NEAR with a specified validator.

* [Read more in the API Reference](/api-reference/stakers/near_src.nearstaker#buildstaketx)

***

### buildUnstakeTx

#### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator.

Unstaking involves withdrawing your staked tokens, which then enter a waiting period (typically 2-3 days) before they become available for withdrawal.

#### How to Use

To build an unstaking transaction, you will need to provide the amount to unstake, the delegator's address (your wallet), and validator's address you want to withdraw your tokens from.

#### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: 'your.near',
  validatorAddress: 'chorusone.poolv1.near',
  amount: '1' // 1 NEAR
})
```

Here, we're unstaking 1 NEAR from a specified validator.

* [Read more in the API Reference](/api-reference/stakers/near_src.nearstaker#buildunstaketx)

***

### buildWithdrawTx

#### Description

The `buildWithdrawTx` method allows you to create a transaction for withdrawing previously unstaked tokens.

After the unstaking period has finished, the tokens become available as your "unstaked balance" and must be explicitly withdrawn in order to be returned to your wallet.

#### How to Use

To build a withdrawal transaction, you will need to specify the amount to withdraw, the delegator's address (your wallet), and validator's address.

* If you do not specify the amount the entire unstaked balance will be withdrawn.

#### Example

```javascript
const { tx } = await staker.buildWithdrawTx({
  amount: '1', // 1 NEAR
  validatorAddress: 'chorusone.poolv1.near'
})
```

Here, we're withdrawing 1 NEAR from a specified validator.

* [Read more in the API Reference](/api-reference/stakers/near_src.nearstaker#buildwithdrawtx)

***

### getStake

#### Description

The `getStake` method retrieves the staking information for a delegator. This includes the amount of tokens currently staked with a validator.

#### How to Use

To get staking information, you need to provide the delegator's address (your wallet), and optionally the validator's address. If the validator's address is not provided, the method returns rewards from all validators.

#### Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: 'your.near',
  validatorAddress: 'chorusone.poolv1.near'
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given validator.

* [Read more in the API Reference](/api-reference/stakers/near_src.nearstaker#getstake)

***

### Further Reading

For more detailed information and additional methods please refer to the official API reference:

* [NearStaker API Reference](/api-reference/stakers/near_src.nearstaker)


# Polkadot (Substrate)


# Overview

Staking using Substrate Network SDK on networks like Polkadot and Kusama involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The Substrate blockchain framework is known for its flexibility and modularity, which allows developers to create custom blockchains for specific needs. It supports various consensus mechanisms, including Proof-of-Stake (PoS) and Proof-of-Work (PoW), giving developers options for setting up their governance models and security protocols.
{% endhint %}

The **Chorus One SDK** simplifies this process, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Substrate using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Substrate libraries such as `@polkadot/api`. This compatibility ensures that you can seamlessly integrate these methods into your existing Substrate projects.
{% endhint %}

### Setting Up the Staker

To get started with staking on the Substrate network using the Chorus One SDK, you will first need to initialize the SDK for Substrate.

* **Note:** For testing purposes, we will use the Westend testnet.

First, create an instance of `SubstrateStaker` with the necessary configuration:

```javascript
import { SubstrateStaker, RewardDestination } from '@chorus-one/substrate'

const staker = new SubstrateStaker({
  rpcUrl: 'wss://westend-rpc.polkadot.io',
  rewardDestination: RewardDestination.STASH
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the Substrate network RPC endpoint
* **rewardDestination**: This parameter defines the reward destination for staking rewards. The options are `RewardDestination.STASH` or `RewardDestination.STAKED`.
  * `RewardDestination.STASH`: Rewards are added to the stash account.
  * `RewardDestination.CONTROLLER`: Rewards are added to the controller account.
* **fee**: (Optional) The fee to be paid for each transaction.
* **indexerUrl**: (Optional) The URL of the Substrate network indexer. It is required for fetching the transaction status.

***

### Initializing the Staker

After configuring the `SubstrateStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

### Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `SubstrateStaker` class provides methods to build transactions for staking, unstaking, and withdrawing rewards.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/polkadot-substrate/methods) section.

**Example of building a staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  amount: '1' // 1 WND
})
```

***

### Getting the Validator Address provided by Chorus One

The `@chorus-one/substrate` module includes a list of Chorus One validators for the Substrate networks. You can use these addresses when building transactions.

```javascript
import { CHORUS_ONE_SUBSTRATE_VALIDATORS } from '@chorus-one/substrate'

const validatorAddresses = CHORUS_ONE_SUBSTRATE_VALIDATORS.POLKADOT
```

***

### Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Substrate network. To set up Fireblocks, provide the necessary API key, secret key, and vault ID:

```javascript
import { SubstrateStaker } from '@chorus-one/substrate'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'WND',
  addressDerivationFn: SubstrateStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '5CavrskYZHeLxTwERikgZDCZPmhpsM7oXZQmL6rkNryDD8FwN',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

### Broadcasting the Transaction

After signing the transaction, you need broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

### Closing the Connection

After completing the staking operations, close the connection to the Substrate network:

```javascript
await staker.close()
```

***

### Next Steps

In this section you learned how to set up the Chorus One SDK for the Substrate network using the Substrate testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `SubstrateStaker`, continue to the [Methods](/build-your-staking-dapp/polkadot-substrate/methods) section.

### Further Reading

* [SubstrateStaker API Reference](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/classes/avalanche_src.SubstrateStaker.md)
* [What is a Signer?](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/signers-explained/what-is-a-signer.md)


# Methods

This section provides an overview of the key methods available in the **Substrate Network SDK** for staking on networks like Polkadot. The SDK supports various staking operations, including staking, nominating validators, unstaking, withdrawing funds, and bonding extra tokens. Below, we explore each method with practical examples to help you get started.

### buildStakeTx

#### Description

The `buildStakeTx` method helps you create a transaction for staking tokens with a validator. Staking tokens involves locking them up to support the network's security and operations, and in return, you earn rewards.

#### How to Use

To build a staking transaction, you need to specify the amount to stake.

#### Example

```javascript
const { tx } = await staker.buildStakeTx({
  amount: '1' // 1 DOT
})
```

In this example, we're staking 1 DOT with a specified validator.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#buildstaketx)

***

### buildNominateTx

#### Description

The `buildNominateTx` method allows you to create a transaction to nominate a validator. Nominating validators allows you to delegate your staked tokens to trusted validators.

#### How to Use

To build a nomination transaction, you need to specify the validator's address.

#### Example

```javascript
const { tx } = await staker.buildNominateTx({
  validatorAddresses: ['16XF84j2wQ9wjkqRM2Y8ceCaw8dQu7t3ve9P9XbBj5kaRZxY']
})
```

In this example, we're nominating a list of validators.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#buildnominatetx)

***

### buildUnstakeTx

#### Description

The `buildUnstakeTx` method helps you create a transaction for unstaking tokens. Unstaking involves withdrawing your staked tokens, which typically undergo a bonding period before they can be fully withdrawn.

#### How to Use

To build an unstaking transaction, you need to specify the amount to unstake.

#### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  amount: '1' // 1 DOT
})
```

In this example, we're unstaking 1 DOT.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#buildunstaketx)

***

### buildWithdrawTx

#### Description

The `buildWithdrawTx` method allows you to create a transaction to withdraw all unstaked funds from the validator contract. This transaction is used to move your tokens back to your wallet after they have been unstaked and the bonding period has completed.

#### How to Use

To build a withdrawal transaction, you do not need to provide any parameters.

#### Example

```javascript
const { tx } = await staker.buildWithdrawTx()
```

In this example, we're withdrawing all unstaked funds.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#buildwithdrawtx)

***

### buildBondExtraTx

#### Description

The `buildBondExtraTx` method helps you create a transaction to delegate additional tokens to a validator. This is useful if you want to increase your stake without creating a new staking transaction.

#### How to Use

To build a bond extra transaction, you need to specify the amount to bond.

#### Example

```javascript
const { tx } = await staker.buildBondExtraTx({
  amount: '1' // 1 DOT
})
```

In this example, we're bonding an additional 1 DOT to the current stake.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#buildbondextratx)

***

### getStake

#### Description

The `getStake` method retrieves the staking information for a specified delegator. This includes the amount of tokens currently staked with a validator.

#### How to Use

To get staking information, you need to provide the delegator's address (your wallet), and optionally the validator's address. If the validator's address is not provided, the method returns rewards from all validators.

You can also specify the status of the nomination ('active' or 'total'). Active nominations are those that are currently actively used to secure the network and earn rewards, while total nominations include all nominations made by the delegator. Default is 'active'.

#### Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: '5CavrskYZHeLxTwERikgZDCZPmhpsM7oXZQmL6rkNryDD8FwN',
  validatorAddress: '16XF84j2wQ9wjkqRM2Y8ceCaw8dQu7t3ve9P9XbBj5kaRZxY'
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/substrate_src.substratestaker#getstake)

***

### Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [SubstrateStaker API Reference](/api-reference/stakers/substrate_src.substratestaker)


# Polygon


# Overview

{% hint style="info" %}
Polygon PoS is a decentralized Ethereum scaling solution that uses a Proof-of-Stake consensus mechanism. Validators stake POL tokens on the Ethereum mainnet to secure the network and earn rewards. Staking on Polygon involves delegating POL tokens to validators through ValidatorShare contracts deployed on Ethereum L1.
{% endhint %}

Staking on the Polygon network (POL) involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

The **Chorus One SDK** simplifies this process, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Polygon using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Ethereum libraries such as `viem`. This compatibility ensures that you can seamlessly integrate these methods into your existing Ethereum and Polygon projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on the Polygon network using the Chorus One SDK, you will first need to initialize the SDK.

First, create an instance of the `PolygonStaker` with the following configuration:

```javascript
import { PolygonStaker } from '@chorus-one/polygon'

const staker = new PolygonStaker({
  network: 'mainnet',
  rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY'
})
```

**Configuration Parameters**:

* **network**: The network to use (`'mainnet'` for Ethereum L1 or `'testnet'` for Sepolia L1)
* **rpcUrl**: (Optional) The URL of the Ethereum network RPC endpoint

***

## Initializing the Staker

After configuring the `PolygonStaker`, you can initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

{% hint style="info" %}
**Note**: The `init` method is optional for `PolygonStaker` and is kept for backward compatibility with other SDK stakers. You can start building transactions immediately after creating the staker instance.
{% endhint %}

***

## Building Transactions

Once the staker is set up, you can start building transactions for staking operations.

The `PolygonStaker` provides methods to build transactions for staking, unstaking, withdrawing, claiming rewards, and compounding rewards.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/polygon/methods) section.

**Example of building a staking transaction:**

```javascript
import { CHORUS_ONE_POLYGON_VALIDATORS } from '@chorus-one/polygon'

const delegatorAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
const validatorShareAddress = CHORUS_ONE_POLYGON_VALIDATORS.mainnet

const { tx } = await staker.buildStakeTx({
  delegatorAddress,
  validatorShareAddress,
  amount: '1', // 1 POL
  slippageBps: 50 // 0.5% slippage tolerance
})
```

{% hint style="warning" %}
**Token Approval Required**

Before staking, you must approve the StakeManager contract to spend your POL tokens. Use `buildApproveTx()` to create an approval transaction.
{% endhint %}

{% hint style="info" %}
**Auto-Claim of Rewards**

Both staking and unstaking operations automatically claim any pending rewards in the same transaction. The Polygon ValidatorShare contract internally calls `_withdrawAndTransferReward` before executing the stake or unstake. Your pending rewards are transferred to your wallet and the reward counter resets to 0.
{% endhint %}

***

## Getting the Validator Address provided by Chorus One

The `@chorus-one/polygon` module includes Chorus One validator addresses for the Polygon network.

You can use these addresses when building staking transactions.

```javascript
import { CHORUS_ONE_POLYGON_VALIDATORS } from '@chorus-one/polygon'

const validatorShareAddress = CHORUS_ONE_POLYGON_VALIDATORS.mainnet
// or for testnet:
const testnetValidator = CHORUS_ONE_POLYGON_VALIDATORS.testnet
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Polygon network.

To set up Fireblocks, you will need to provide the necessary API key, secret key, and vault ID:

```javascript
import { PolygonStaker } from '@chorus-one/polygon'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({...})
await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Polygon network, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods for `PolygonStaker`, continue to the [Methods](/build-your-staking-dapp/polygon/methods) section.

## Further Reading

* [PolygonStaker API Reference](/api-reference/stakers/polygon_src.polygonstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Methods

This section provides an overview of the key methods available in the **Chorus One Polygon SDK** for staking operations.

The Chorus One SDK supports various staking operations including delegating, undelegating, withdrawing, claiming rewards, and compounding. Below, we explore each method with practical examples to help you get started.

## buildApproveTx

### Description

The `buildApproveTx` method creates a transaction to approve the StakeManager contract to spend POL tokens on behalf of the delegator.

This approval must be executed before staking if the current allowance is insufficient.

### How to Use

To build an approval transaction, you need to specify the amount of POL tokens to approve. You can pass `"max"` for unlimited approval.

### Example

```javascript
const { tx } = await staker.buildApproveTx({
  amount: '1000' // Approve 1000 POL
})

// Or for unlimited approval:
const { tx: unlimitedTx } = await staker.buildApproveTx({
  amount: 'max'
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildapprovetx)

***

## buildStakeTx

### Description

The `buildStakeTx` method allows you to create a transaction for staking (delegating) POL tokens with a validator.

Staking tokens involves delegating them to a validator via their ValidatorShare contract, supporting the network's security, and in return, you earn rewards.

> **Note:** Staking automatically claims any pending rewards in the same transaction. The ValidatorShare contract calls `_withdrawAndTransferReward` before executing the stake, so pending rewards are transferred to your wallet and the reward counter resets to 0.

### How to Use

To build a staking transaction, you will need to specify:

* **delegatorAddress**: The delegator's Ethereum address
* **validatorShareAddress**: The validator's ValidatorShare contract address
* **amount**: The amount to stake in POL
* **slippageBps**: Slippage tolerance in basis points (e.g., 50 = 0.5%). Used to calculate minSharesToMint automatically. Exactly one of `slippageBps` or `minSharesToMint` must be provided (not both, no default).
* **minSharesToMint**: Minimum validator shares to receive for slippage protection. Exactly one of `slippageBps` or `minSharesToMint` must be provided (not both, no default).

> **Why is slippage required?** Polygon uses a share-based delegation model where the exchange rate between POL and validator shares fluctuates. The slippage parameter protects against unfavorable rate changes between transaction submission and execution. This is a requirement of the ValidatorShare contract itself.

* **referrer**: (Optional) Custom referrer string for tracking. Defaults to `'sdk-chorusone-staking'`.

### Example

```javascript
import { CHORUS_ONE_POLYGON_VALIDATORS } from '@chorus-one/polygon'

// Using slippageBps for automatic slippage calculation
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  amount: '100', // 100 POL
  slippageBps: 50 // 0.5% slippage tolerance
})

// Or using minSharesToMint directly
const { tx: txDirect } = await staker.buildStakeTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  amount: '100',
  minSharesToMint: 99n * 10n ** 18n
})
```

In this example, we're staking 100 POL with the Chorus One validator.

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildstaketx)

***

## buildUnstakeTx

### Description

The `buildUnstakeTx` method creates a transaction to unstake POL tokens from a validator.

After unstaking, there is an unbonding period of approximately 80 checkpoints (around 3-4 days) before the tokens can be withdrawn.

> **Note:** Unstaking automatically claims any pending rewards in the same transaction. The ValidatorShare contract calls `_withdrawAndTransferReward` before executing the unstake, so pending rewards are transferred to your wallet and the reward counter resets to 0.

### How to Use

To build an unstaking transaction, you need to specify:

* **delegatorAddress**: The address of the delegator
* **validatorShareAddress**: The validator's ValidatorShare contract address
* **amount**: The amount of POL to unstake
* **slippageBps**: Slippage tolerance in basis points (e.g., 50 = 0.5%). Used to calculate maximumSharesToBurn automatically. Exactly one of `slippageBps` or `maximumSharesToBurn` must be provided (not both, no default).
* **maximumSharesToBurn**: Maximum validator shares willing to burn for slippage protection. Exactly one of `slippageBps` or `maximumSharesToBurn` must be provided (not both, no default).

> **Why is slippage required?** Polygon uses a share-based delegation model where the exchange rate between POL and validator shares fluctuates. The slippage parameter protects against unfavorable rate changes between transaction submission and execution. This is a requirement of the ValidatorShare contract itself.

* **referrer**: (Optional) Custom referrer string for tracking. Defaults to `'sdk-chorusone-staking'`.

### Example

```javascript
// Using slippageBps for automatic slippage calculation
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  amount: '50', // 50 POL
  slippageBps: 50 // 0.5% slippage tolerance
})

// Or using maximumSharesToBurn directly
const { tx: txDirect } = await staker.buildUnstakeTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  amount: '50',
  maximumSharesToBurn: 51n * 10n ** 18n
})
```

In this example, we are creating an unbond request to unstake 50 POL.

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildunstaketx)

***

## buildWithdrawTx

### Description

The `buildWithdrawTx` method creates a transaction to claim unstaked POL tokens after the unbonding period has elapsed.

You can use `getUnbond()` to check if the unbonding period is complete and `getUnbondNonce()` to get the latest unbond nonce.

### Understanding Unbond Nonces

Each unstake operation creates a **separate unbond request** with its own nonce. Unbonds are NOT batched together.

* Nonces are incremental per delegator, starting from 1
* First unstake = nonce 1, second unstake = nonce 2, etc.
* Each unbond has its own 80-checkpoint countdown
* Withdrawals must be done separately for each nonce

**Example scenario:**

* Day 1: Unstake 100 POL → creates unbond nonce 1 (withdrawable \~Day 4)
* Day 2: Unstake 50 POL → creates unbond nonce 2 (withdrawable \~Day 5)
* Day 4: You can withdraw nonce 1, but nonce 2 is still locked
* Day 5: Now you can withdraw nonce 2

### How to Use

To build a withdrawal transaction, you need to specify the delegator's address, the validator's ValidatorShare contract address, and the specific unbond nonce to withdraw.

### Example

```javascript
// Get the latest unbond nonce
const latestNonce = await staker.getUnbondNonce({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})

// Withdraw a specific unbond (e.g., the latest one)
const { tx } = await staker.buildWithdrawTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  unbondNonce: latestNonce
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildwithdrawtx)

***

## buildClaimRewardsTx

### Description

The `buildClaimRewardsTx` method creates a transaction to claim accumulated delegation rewards.

The rewards are sent directly to the delegator's wallet.

### How to Use

To build a claim rewards transaction, you need to specify:

* **delegatorAddress**: The delegator's address that will receive the rewards
* **validatorShareAddress**: The validator's ValidatorShare contract address
* **referrer**: (Optional) Custom referrer string for tracking. Defaults to `'sdk-chorusone-staking'`.

### Example

```javascript
const { tx } = await staker.buildClaimRewardsTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildclaimrewardstx)

***

## buildCompoundTx

### Description

The `buildCompoundTx` method creates a transaction to compound (restake) accumulated rewards.

This restakes your rewards back into the validator, increasing your delegation without requiring new tokens.

### How to Use

To build a compound transaction, you need to specify:

* **delegatorAddress**: The delegator's address
* **validatorShareAddress**: The validator's ValidatorShare contract address
* **referrer**: (Optional) Custom referrer string for tracking. Defaults to `'sdk-chorusone-staking'`.

### Example

```javascript
const { tx } = await staker.buildCompoundTx({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#buildcompoundtx)

***

## getStake

### Description

The `getStake` method retrieves the staking information for a specified delegator, including the amount of POL tokens currently staked with a specified validator.

Returns:

* `balance`: Total staked amount formatted in POL
* `shares`: Total shares held by the delegator
* `exchangeRate`: Current exchange rate between shares and POL

### How to Use

To get staking information, you will need to provide the delegator's address and the validator's ValidatorShare contract address.

### Example

```javascript
const { balance, shares, exchangeRate } = await staker.getStake({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})

console.log(`Staked balance: ${balance} POL`)
console.log(`Shares held: ${shares}`)
console.log(`Exchange rate: ${exchangeRate}`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getstake)

***

## getLiquidRewards

### Description

The `getLiquidRewards` method retrieves the pending rewards available to claim for a delegator.

### How to Use

To get pending rewards, you will need to provide the delegator's address and the validator's ValidatorShare contract address.

### Example

```javascript
const rewards = await staker.getLiquidRewards({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})

console.log(`Pending rewards: ${rewards} POL`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getliquidrewards)

***

## getUnbondNonce

### Description

The `getUnbondNonce` method retrieves the latest unbond nonce for a delegator.

The nonce represents the total number of unstake operations performed by the delegator. Each unstake creates a new unbond request with an incrementing nonce (starting from 1).

For example, if `getUnbondNonce()` returns `3n`, the delegator has performed 3 unstake operations, with unbonds stored at nonces 1, 2, and 3.

### How to Use

To get the unbond nonce, you will need to provide the delegator's address and the validator's ValidatorShare contract address.

### Example

```javascript
const latestNonce = await staker.getUnbondNonce({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})

console.log(`Total unstake operations: ${latestNonce}`)
// To check all unbonds, iterate from 1 to latestNonce
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getunbondnonce)

***

## getUnbond

### Description

The `getUnbond` method retrieves information about a specific unbond request.

Returns:

* `amount`: The amount pending withdrawal in POL.
* `isWithdrawable`: Whether the unbond can be withdrawn now.
* `shares`: The shares amount pending withdrawal. Returns `0n` if the unbond has already been withdrawn or doesn't exist.
* `withdrawEpoch`: The epoch when the unbond was created. The unbond becomes claimable at `withdrawEpoch + withdrawalDelay`.

### How to Use

To get unbond information, you will need to provide the delegator's address, the validator's ValidatorShare contract address, and the specific unbond nonce to query.

### Example

```javascript
const unbond = await staker.getUnbond({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  unbondNonce: 1n
})

if (unbond.shares === 0n) {
  console.log('Unbond already withdrawn or does not exist')
} else if (unbond.isWithdrawable) {
  console.log(`Ready to withdraw ${unbond.amount} POL!`)
} else {
  console.log(`${unbond.amount} POL pending, not yet withdrawable`)
}
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getunbond)

***

## getUnbonds

### Description

The `getUnbonds` method retrieves unbond request information for multiple nonces efficiently in a single RPC call.

This is more efficient than calling `getUnbond()` multiple times when you need to check several unbond requests.

### How to Use

To get multiple unbond information, provide the delegator's address, the validator's ValidatorShare contract address, and an array of unbond nonces to query.

### Example

```javascript
// Get the latest nonce first
const latestNonce = await staker.getUnbondNonce({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet
})

// Fetch all unbonds at once
const nonces = Array.from({ length: Number(latestNonce) }, (_, i) => BigInt(i + 1))
const unbonds = await staker.getUnbonds({
  delegatorAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  validatorShareAddress: CHORUS_ONE_POLYGON_VALIDATORS.mainnet,
  unbondNonces: nonces
})

unbonds.forEach((unbond, i) => {
  if (unbond.shares > 0n) {
    console.log(`Unbond ${i + 1}: ${unbond.amount} POL, withdrawable: ${unbond.isWithdrawable}`)
  }
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getunbonds)

***

## getEpoch

### Description

The `getEpoch` method retrieves the current checkpoint epoch from the StakeManager contract.

This can be used in combination with `getWithdrawalDelay()` to check if an unbonding period has elapsed.

### How to Use

Call the method without any parameters to get the current epoch.

### Example

```javascript
const currentEpoch = await staker.getEpoch()

console.log(`Current epoch: ${currentEpoch}`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getepoch)

***

## getWithdrawalDelay

### Description

The `getWithdrawalDelay` method retrieves the withdrawal delay from the StakeManager contract.

The withdrawal delay is the number of epochs that must pass after an unbond request before the funds can be withdrawn (\~80 checkpoints, approximately 3-4 days).

### How to Use

Call the method without any parameters to get the withdrawal delay.

### Example

```javascript
const withdrawalDelay = await staker.getWithdrawalDelay()

console.log(`Withdrawal delay: ${withdrawalDelay} epochs`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getwithdrawaldelay)

***

## getAllowance

### Description

The `getAllowance` method retrieves the current POL token allowance for the StakeManager contract.

Use this to check if approval is needed before staking.

### How to Use

To get the allowance, provide the token owner's address.

### Example

```javascript
const allowance = await staker.getAllowance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')

console.log(`Current allowance: ${allowance} POL`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getallowance)

***

## getExchangeRatePrecision

### Description

The `getExchangeRatePrecision` method retrieves the exchange rate precision for a validator.

Foundation validators (ID < 8) use a precision of `100`, while all other validators use `10^29`. This is relevant when performing manual share/amount calculations.

### How to Use

Provide the validator's ValidatorShare contract address.

### Example

```javascript
const precision = await staker.getExchangeRatePrecision(CHORUS_ONE_POLYGON_VALIDATORS.mainnet)

console.log(`Exchange rate precision: ${precision}`)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#getexchangerateprecision)

***

## sign

### Description

The `sign` method signs a transaction using the provided signer (e.g., Fireblocks, local mnemonic).

### How to Use

To sign a transaction, you need to specify:

* **signer**: A signer instance (e.g., `FireblocksSigner`, `LocalSigner`)
* **signerAddress**: The address of the signer
* **tx**: The transaction to sign (from any `build*Tx` method)
* **baseFeeMultiplier**: (Optional) Multiplier applied to the base fee per gas from the latest block to determine `maxFeePerGas`. Defaults to `1.2`.
* **defaultPriorityFee**: (Optional) Overrides the `maxPriorityFeePerGas` estimated by the RPC, specified in ETH (e.g., `'0.000000001'` for 1 gwei).

### Example

```javascript
const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  tx,
  baseFeeMultiplier: 1.5, // 1.5x base fee for faster inclusion
  defaultPriorityFee: '0.000000002' // 2 gwei priority fee
})
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#sign)

***

## broadcast

### Description

The `broadcast` method broadcasts a signed transaction to the Polygon network.

### How to Use

Pass the signed transaction hex string returned by the `sign` method.

### Parameters

* **signedTx** (Hex): The signed transaction to broadcast

### Example

```javascript
const { txHash } = await staker.broadcast({ signedTx })

console.log('Transaction hash:', txHash)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#broadcast)

***

## getTxStatus

### Description

The `getTxStatus` method retrieves the status of a transaction using the transaction hash.

### How to Use

Provide the transaction hash received from the `broadcast` method.

### Parameters

* **txHash** (Hex): The transaction hash to query

### Returns

Returns the transaction status including:

* **status** (string): Transaction status (`'success'`, `'failure'`, or `'unknown'`)
* **receipt** (object): The full transaction receipt (when available)

### Example

```javascript
const txStatus = await staker.getTxStatus({ txHash })

console.log('Transaction status:', txStatus.status)
```

* [Read more in the API Reference](/api-reference/stakers/polygon_src.polygonstaker#gettxstatus)

***

## Exported Constants

The `@chorus-one/polygon` package exports the following constants:

| Constant                        | Description                                                          |
| ------------------------------- | -------------------------------------------------------------------- |
| `CHORUS_ONE_POLYGON_VALIDATORS` | Chorus One ValidatorShare contract addresses for mainnet and testnet |
| `NETWORK_CONTRACTS`             | StakeManager and staking token contract addresses per network        |
| `VALIDATOR_SHARE_ABI`           | ABI for the ValidatorShare contract                                  |
| `STAKE_MANAGER_ABI`             | ABI for the StakeManager contract                                    |
| `EXCHANGE_RATE_PRECISION`       | Exchange rate precision for foundation validators (`100n`)           |
| `EXCHANGE_RATE_HIGH_PRECISION`  | Exchange rate precision for non-foundation validators (`10n ** 29n`) |

***

## Exported Types

The following TypeScript types are exported:

| Type                   | Description                                                                                       |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| `PolygonNetworkConfig` | Configuration for initializing `PolygonStaker` (`network`, `rpcUrl`)                              |
| `Transaction`          | Transaction object returned by `build*Tx` methods (`to`, `data`, `value`)                         |
| `PolygonTxStatus`      | Transaction status from `getTxStatus` (`status`, `receipt`)                                       |
| `StakeInfo`            | Staking info from `getStake` (`balance`, `shares`, `exchangeRate`)                                |
| `UnbondInfo`           | Unbond info from `getUnbond`/`getUnbonds` (`amount`, `isWithdrawable`, `shares`, `withdrawEpoch`) |
| `PolygonNetworks`      | Network type: `'mainnet'` or `'testnet'`                                                          |
| `NetworkContracts`     | Contract addresses type (`stakeManagerAddress`, `stakingTokenAddress`)                            |

***

## Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [PolygonStaker API Reference](/api-reference/stakers/polygon_src.polygonstaker)

***

This guide aims to simplify the process of using the Chorus One Polygon SDK for staking operations.

* Please follow the provided examples to integrate these functionalities into your applications.


# Solana


# Overview

Staking on the Solana network involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
The Solana blockchain, distinguished by its high throughput and low latency, leverages the Proof of History (PoH) mechanism combined with the Tower BFT consensus algorithm. This innovative structure allows for fast transaction processing and scalability without compromising security. By staking SOL, Solana's native token, validators maintain the network, secure the blockchain, and incentivize active participation, ensuring the network remains robust and efficient.
{% endhint %}

The **Chorus One SDK** simplifies the staking process on the Solana network, providing developers with the tools needed to build, sign, and broadcast staking transactions.

This guide will walk you through the fundamentals of staking on Solana using the Chorus One SDK.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular Solana libraries such as `@solana/web3.js`. This compatibility ensures that you can seamlessly integrate these methods into your existing Solana projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on the Solana network using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes, we will use the Solana testnet.

First, create an instance of `SolanaStaker` with the necessary configuration:

```javascript
import { SolanaStaker } from '@chorus-one/solana'

const staker = new SolanaStaker({
  rpcUrl: 'https://api.testnet.solana.com'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the Solana network RPC endpoint. This is where the SDK will connect to interact with the network. In this example, we are using a public endpoint for the Solana testnet.

***

## Initializing the Staker

After configuring the `SolanaStaker`, initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker is set up, you can start building transactions for staking operations.

The `SolanaStaker` class provides methods to build transactions for staking, unstaking, merging and splitting stakes, and creating stake accounts.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/solana/methods) section.

**Example of building a staking transaction:**

```javascript
const { tx, stakeAccountAddress } = await staker.buildStakeTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  validatorAddress: 'Chorus6Kis8tFHA7AowrPMcRJk3LbApHTYpgSNXzY5KE',
  amount: '1' // 1 SOL
})
```

Optionally you can specify the stake account address by passing the `stakeAccountAddress` argument. If it is not provided, the SDK will create a new stake account for you and return the address.

{% hint style="info" %}
On the Solana network, a stake account lets you delegate tokens to validators to earn rewards. Unlike a wallet account, which is limited, a stake account can handle the token delegation.
{% endhint %}

***

## Getting the Validator Address provided by Chorus One

The `@chorus-one/solana` module includes the `CHORUS_ONE_SOLANA_VALIDATOR` constant, which contains the Chorus One validator address for building transactions.

```javascript
import { CHORUS_ONE_SOLANA_VALIDATOR } from '@chorus-one/solana'

const validatorAddress = CHORUS_ONE_SOLANA_VALIDATOR
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks, you can leverage its robust security features to sign transactions on the Solana network. To set up Fireblocks, you will need to provide the necessary API key, secret key, and vault ID:

```javascript
import { SolanaStaker } from '@chorus-one/solana'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'SOL_TEST',
  addressDerivationFn: SolanaStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const { txHash } = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({ txHash })

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the Solana network using the Solana testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `SolanaStaker` continue to the [Methods](/build-your-staking-dapp/solana/methods) section.

## Further Reading

* [SolanaStaker API Reference](/api-reference/stakers/solana_src.solanastaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the Solana network.

The Chorus One SDK supports a range of staking operations including staking, unstaking, and withdrawing rewards. Below, we explore each method with practical examples to help you get started.

### buildStakeTx

#### Description

The `buildStakeTx` method helps you create a transaction for staking tokens with a validator. Staking tokens involves locking them up to support the network's security and operations, and in return you earn rewards.

#### How to Use

To build a staking transaction, you need to specify the amount to stake, the stake owner's address (your wallet), and the validator's address where you want to stake your tokens.

#### Example

```javascript
import { CHORUS_ONE_SOLANA_VALIDATOR } from '@chorus-one/solana'

const { tx } = await staker.buildStakeTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  validatorAddress: CHORUS_ONE_SOLANA_VALIDATOR,
  amount: '1' // 1 SOL
})
```

In this example, we are staking 1 SOL with a specified validator. The Solana [Stake Account](https://solana.com/docs/economics/staking/stake-accounts) is created automatically, unless you pass the `stakeAccountAddress` argument.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildstaketx)

***

### buildUnstakeTx

#### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator.

Unstaking involves deactivating your staked tokens, during which they enter an unbonding period. On the Solana network, the unbonding period typically lasts for one epoch, which is approximately 2.5 days. However, the exact duration can vary depending on when the unstaking request is made within the current epoch. During this period, your tokens are not earning rewards and cannot be transferred, as they are in the process of being released from staking.

After the unbonding period, the tokens will become available to withdraw.

#### How to Use

To build an unstaking transaction, you need to provide the stake account and it's owner (your wallet address).

#### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  stakeAccountAddress: 'HJRL5PTpvwxmt796M7xDavRbPkjN28iGPVBkJn9y6rYE'
})
```

Here, we're unstaking all the SOL on the stake account.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildunstaketx)

***

### buildWithdrawStakeTx

#### Description

The `buildWithdrawStakeTx` method allows you to create a transaction to withdraw the unbonded stake from a Solana staking account.

#### How to Use

To build a stake withdrawal transaction, you need to provide the stake account and it's owner address (your wallet address).

#### Example

```javascript
const { tx } = await staker.buildWithdrawStakeTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  stakeAccountAddress: 'HJRL5PTpvwxmt796M7xDavRbPkjN28iGPVBkJn9y6rYE'
})
```

Here, we are withdrawing all SOL from a stake account to the wallet owner's address.

To withdraw a specific amount pass the `amount` argument.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildwithdrawstaketx)

***

### buildCreateStakeAccountTx

#### Description

The `buildCreateStakeAccountTx` method allows you to create a new Solana [Stake Account](https://solana.com/docs/economics/staking/stake-accounts).

#### How to Use

To build a new create staking account transaction, you will need to provide the owner address (your wallet) and the amount of SOL to transfer.

#### Example

```javascript
const { tx } = await staker.buildCreateStakeAccountTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  amount: '1' // 1 SOL
})
```

Here, we are creating a new staking account with a balance of 1 SOL, which is being transfered from the owner's address (your wallet).

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildcreatestakeaccounttx)

***

### buildMergeStakesTx

#### Description

The `buildMergeStakesTx` method allows you to combine two stake accounts into one.

#### How to Use

To build a merge stakes transaction, you will need to provide the owner address (your wallet), the stake account source address, and the destination where the funds will be transferred to.

#### Example

```javascript
const { tx } = await staker.buildMergeStakesTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  sourceAddress: 'HJRL5PTpvwxmt796M7xDavRbPkjN28iGPVBkJn9y6rYE',
  destinationAddress: '...'
})
```

Here, we are merging a source account stake into a different destination account. Please note, after this transaction, the source account will cease to exist.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildmergestakestx)

***

### buildSplitStakeTx

#### Description

The `buildSplitStakeTx` method allows you to split one stake account into two separate accounts.

#### How to Use

To build a split stake transaction, you will need to provide the owner's address (your wallet), the stake account address that is in use, and the amount of SOL you wish to split and transfer to new stake account.

#### Example

```javascript
const { tx } = await staker.buildSplitStakeTx({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  stakeAccountAddress: 'HJRL5PTpvwxmt796M7xDavRbPkjN28iGPVBkJn9y6rYE',
  amount: '1' // 1 SOL
})
```

Here, we are substracting 1 SOL from the source stake account and transferring into a newly created stake account.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#buildsplitstaketx)

***

### getStake

#### Description

The `getStake` method retrieves the staking information from a delegator.

* This includes the amount of tokens currently staked with a validator.

#### How to Use

To get staking information, you need to provide the owner's address (your wallet), and optionally the validator's address. If the validator's address is not provided, the method returns balance from all validators.

You can also specify the state of the stake accounts. Default is 'delegated'.

#### Example

```javascript
import { CHORUS_ONE_SOLANA_VALIDATOR } from '@chorus-one/solana'

const { balance } = await staker.getStake({
  ownerAddress: '3Ps2hwsgGMSuqxAwjcGJHiEpMsSTZcxrCGprHgxWkfma',
  validatorAddress: CHORUS_ONE_SOLANA_VALIDATOR
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given owner and validator.

* [Read more in the API Reference](/api-reference/stakers/solana_src.solanastaker#getstake)

***

### Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [SolanaStaker API Reference](/api-reference/stakers/solana_src.solanastaker)


# TON


# Overview

Staking on TON (Telegram Open Network) involves locking up tokens to support the network's security and operations. In return, stakers earn rewards.

{% hint style="info" %}
Toncoin (TON) the native cryptocurrency of the TON blockchain, excels in scalability, fast transaction speeds, and minimal fees. By utilizing the Byzantine Fault Tolerance consensus algorithm, TON ensures high security and decentralization. Validators maintain the network by staking Toncoin, which in turn, secures the blockchain and incentivizes participation.
{% endhint %}

The **Chorus One SDK** simplifies this process by providing developers with the tools needed to build, sign, and broadcast staking transactions.

## Pick the Pool Technology

Before you start developing your staking application, you need to decide which pool technology you want to use. We recommend the **TON Pool** for most use cases, as it is easy to start using, it supports an unlimited number of delegators, and it's minimal stake is only 10 TON.

However, if you have specific requirements, you can choose the **Nominator** or **Single Nominator** pool.

|                    | [TON Pool](/build-your-staking-dapp/ton/ton-pool/overview) | [Nominator](/build-your-staking-dapp/ton/nominator/overview) | [Single Nominator](/build-your-staking-dapp/ton/single-nominator/overview) |
| ------------------ | ---------------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
| Recommended        | ✅                                                          |                                                              |                                                                            |
| Best for           | Most use cases                                             | Large delegators                                             | Single delegators                                                          |
| Delegators         | Unlimited                                                  | 40 Max                                                       | 1                                                                          |
| Minimal Stake      | 10 TON                                                     | 10,000 TON                                                   | 400,000 TON                                                                |
| Partial Withdrawal | ✅                                                          | ❌ Must withdraw all funds                                    | ✅                                                                          |
| Pool creation      | ✅ Not needed                                               | ❌ Per request                                                | ❌ Per request                                                              |

Once you have chosen the pool technology, continue with the respective guide.

* [TON Pool Guide](/build-your-staking-dapp/ton/ton-pool/overview)
* [Nominator Pool Guide](/build-your-staking-dapp/ton/nominator/overview)
* [Single Nominator Pool Guide](/build-your-staking-dapp/ton/single-nominator/overview)

## Further Reading

* [Why to Stake on TON](https://chorus.one/articles/first-look-exploring-standout-innovations-in-the-ton-ecosystem)
* [How Staking Works on TON](https://chorus.one/articles/ton-series-2-the-mechanisms-of-staking-ton)


# TON Pool


# Overview

The **TON Pool** is the most accessible and flexible staking solution, designed for users of all sizes with a low minimum stake of just 10 TON. It supports unlimited delegators, automates staking management, and offers partial withdrawals for convenience. Easy to use and scalable, it's the go-to option for most staking needs.

The **Chorus One SDK** simplifies this process by providing developers with the tools needed to build, sign, and broadcast staking transactions.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular TON libraries such as `@ton/ton`. This compatibility ensures that you can seamlessly integrate these methods into your existing TON projects.
{% endhint %}

## Understanding Key Concepts

### Battle-Tested TON Whales Contracts

The **TON Pool** is powered by [TON Whales contracts](https://tonwhales.com/), a robust and proven technology that has operated reliably in the TON ecosystem for several years. These contracts have been tested extensively in real-world conditions, providing a solid foundation for secure and efficient staking operations.

![](/files/m5ie51xINFXRAe31me3O)

{% hint style="info" %}
**Architecture Overview**

To learn more about the architecture of the TON Pool and the underlying TON Whales contracts, refer to the [Architecture](/build-your-staking-dapp/ton/ton-pool/architecture) section.
{% endhint %}

## Two Validator Pool Addresses

To ensure uninterrupted network participation, TON Pool utilizes two validator pool addresses: one for odd cycles and another for even cycles. These pools alternate between cycles to enable seamless staking and validation without downtime. This design ensures continuous operation and smooth participation in the TON blockchain’s validation process.

When using the **Chorus One SDK**, you must provide a pair of validator addresses (odd and even) when configuring your staking transactions. This ensures your staked assets are properly integrated into the network’s alternating validation mechanism.

## Setting Up the Staker

To get started with staking on TON using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes we will be using the TON testnet.

First, create an instance of `TonPoolStaker` with the following configuration:

```javascript
import { TonPoolStaker } from '@chorus-one/ton'

const staker = new TonPoolStaker({
  rpcUrl: 'https://testnet.toncenter.com/api/v2/jsonRPC'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the TON RPC endpoint. This is where the SDK will connect to interact with the network. In this example, we are using a public endpoint for the testnet.

***

## Initializing the Staker

After configuring the `TonPoolStaker`, you can initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `TonPoolStaker` class provides methods to build transactions for staking, unstaking, and wallet deployment.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/ton/ton-pool/methods) section.

**Example of building a single nominator pool staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  validatorAddressPair: [
    'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F',
    'kQCltujow9Sq3ZVPPU6CYGfqwDxYwjlmFGZ1Wt0bAYebio4o'
  ],
  amount: '2', // 2 TON
})
```

***

## Getting the Validators Pair Address provided by Chorus One

The `@chorus-one/ton` module includes Chorus One validator pairs for the chains, organized by network(mainnet or testnet). You can use these addresses when building transactions.

```javascript
import { CHORUS_ONE_TON_VALIDATORS } from '@chorus-one/ton'

const validatorAddressPair = CHORUS_ONE_TON_VALIDATORS.testnet.tonPoolPair
console.log(vaultAddressPair)
// [
//    'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F',
//    'kQCltujow9Sq3ZVPPU6CYGfqwDxYwjlmFGZ1Wt0bAYebio4o'
// ]
```

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/signers-explained/what-is-a-signer.md) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks you can leverage its robust security features to sign transactions on the TON network. To set up Fireblocks, you must provide the necessary API key, secret key, and vault ID.

Example shown below:

```javascript
import { TonPoolStaker } from '@chorus-one/TON'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'TON_TEST',
  addressDerivationFn: TonPoolStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const txHash = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({
  address: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  txHash
})

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the TON network using the TON testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `TonPoolStaker`, continue to the [Methods](/build-your-staking-dapp/ton/ton-pool/methods) section.

## Further Reading

* [TON Pool Architecture](/build-your-staking-dapp/ton/ton-pool/architecture)
* [TonPoolStaker API Reference](/api-reference/stakers/ton_src.tonpoolstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the TON Network via the **TON Pool** contract.

The Chorus One SDK supports various staking operations including staking, unstaking, withdrawing, and retrieving staking information.

Below, we explore each method with practical examples to help you get started.

***

## buildStakeTx

### Description

The `buildStakeTx` method creates a staking transaction for the TON Pool contract. This method uses a two-pool solution and automatically selects the best pool for staking.

Staking tokens supports the network's operations and earns rewards for the delegator.

### How to Use

To build a staking transaction, you need to provide the validator address pair, and the staking amount (in TON). Optionally, you can also specify a referrer address for tracking purposes, and a Unix timestamp indicating when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildStakeTx({
  validatorAddressPair: [
    'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F',
    'kQCltujow9Sq3ZVPPU6CYGfqwDxYwjlmFGZ1Wt0bAYebio4o'
  ],
  amount: '2', // 2 TON
  validUntil: Math.floor(Date.now() / 1000) + 3600, // Optional, expires in 1 hour
  referrer: 'Telegram' // Optional, unique referrer string for tracking
})
```

In the example above, we stake 2 TON using a validator address pair with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonpoolstaker#buildstaketx)

***

## buildUnstakeTx

### Description

The `buildUnstakeTx` method creates a transaction for unstaking tokens from the TON Pool contract.

Unstaking involves removing your staked tokens from a validator, which may be subject to fees and a withdrawal waiting period.

### How to Use

To build an unstaking transaction, you need to provide the validator's address, the amount to unstake (in TON), and optionally, a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  validatorAddress: 'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F',
  amount: '1', // 1 TON
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

In this example, we are unstaking 1 TON from the specified validator with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonpoolstaker#buildunstaketx)

***

## getStake

### Description

The `getStake` method retrieves staking information for a specific delegator (your wallet) on the TON Pool contract.

* This includes details such as the staked amount, pending deposits, pending withdrawals, and available withdrawal balance.

### How to Use

To retrieve staking information, you need to provide the delegator's address (your wallet) and the validator's address.

### Example

```javascript
const stakeInfo = await staker.getStake({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F'
})
console.log('Staking Info:', stakeInfo)
```

In this example, we retrieve staking information, including balances and pending deposits, for the given delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonpoolstaker#getstake)

***

## getPoolParams

### Description

The `getPoolParams` method retrieves staking parameters for a specified validator, including information such as minimum stake, deposit fees, withdrawal fees, pool fees, and receipt price.

### How to Use

To get the pool parameters, you need to provide the validator's address.

### Example

```javascript
const poolParams = await staker.getPoolParams({
  validatorAddress: 'kQAHBakDk_E7qLlNQZxJDsqj_ruyAFpqarw85tO-c03fK26F'
})
console.log('Pool Parameters:', poolParams)
```

In this example, we retrieve the pool parameters for a given validator, such as fees and minimum stake requirements.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonpoolstaker#getpoolparams)

***

## Further Reading

For more detailed information and additional methods, please refer to the official API reference:

* [TON SDK API Reference](/api-reference/stakers/ton_src.tonpoolstaker)


# Architecture

**TON Pool** provides efficient staking solution on the TON blockchain by utilizing the two-queue smart contract system from the [TON Whales](https://tonwhales.com/) project. By using two queues, the TON Pool ensures optimal resource use and enables 100% validator efficiency (With a single queue, double the number of validators would be needed).

To support these smart contracts, **TON Pool** employs a set of controllers that run directly on the node. These include the **Pool Controller** for managing customer interactions, the **Election Controller** for validator participation, and the **Validator Controller** for secure key management. Together, they enable efficient staking and ensure secure, reliable performance across each validation cycle.

![](/files/m5ie51xINFXRAe31me3O)

## Controllers

The solution includes several key components for managing staking workflows:

* **Pool controller**: Responsible for accepting stakes and withdrawals from customers.
* **Election controller**: Responsible for participating in validator elections to get our validators into the top 100 validator list. This controller interacts with the Validator Controller to secure the necessary public keys.
* **Validator controller**: Responsible for generating new key pairs for each election and integrating with the TON validator software on each individual validator.

The **Pool** and **Election controllers** can be run together in the same binary, this makes it easier to accept stakes and withdrawals before we start participating in an election.

## Validators

Validators, as full nodes, automatically start validating when their public key is included in the current validator set. This information is retrieved from the Elector contract or Chain Config. The pool and election controllers run independently of the validators.

The [validation cycle](https://tonscan.com/validation) is split into **odd** and **even** cycles. Each cycle has four phases:

* **Election**: 6-7 hours
* **Delay**: 2-3 hours
* **Validation**: 18 hours
* **Hold**: 9 hours (overlaps with the Election phase of the next cycle)

## Workflows

**TON Pool** includes four main workflows using the TON Whales Pool contract:

1. **Staking**: Customers deposit TON to the pool contract.
2. **Unstaking**: Customers withdraw TON from the pool contract.
3. **Stake Submission**: Validator bids are sent to participate in the upcoming election.
4. **Stake Retrieval**: Previous bids and rewards are reclaimed from the last validation cycle.

### Staking

1. A customer submits a stake message to the Pool contract through the **TON Pool** frontend, which adds the deposited TON as a pending stake.
2. At the start of the next election cycle, when the pool unlocks, the controller processes the pending stake. Only one contract can accept new stakes during each cycle, determined by alternating between contracts.

* The controller first checks both contracts’ statuses to identify which one has ProxyStakeAt set to 0, indicating it can accept stakes.
* It then verifies if there are pending deposits for this contract. If so, the pool contract processes these deposits by sending an acceptance message.

![](/files/ywT9AwwFEYyesgT5yRT3)

### Unstaking

1. **Unstake Request**: Customers initiate an unstake request through a **TON Pool** frontend.

* If the contract is **unlocked**, customers receive their full stake immediately.
* If the contract is **locked**, they receive as much of their stake as possible based on the available balance in the Pending Stake. Any remaining amount is added as a pending request.

2. **Processing Pending Withdrawals**: The controller processes any pending withdrawals at the start of the next election cycle.
3. **Final Withdrawal**: Once processed, customers can retrieve any remaining stake by sending another withdrawal request.

![](/files/czqVqZlhpUwYIYJ0H4H0)

### Stake Submission

This process occurs every other cycle for each **TON Pool** contract.

1. The Validator Controller generates validator keys for the next election.
2. The Election Controller creates and sends an election bid to the Pool contract.
3. The Pool contract processes and forwards the bid to the proxy contract, locking the pool.
4. The Proxy contract submits the bid to the Elector contract.
5. The Elector contract approves or rejects the bid
6. The Elector contract updates the Config contract with the new validator set after elections.

![](/files/rp3fQaiPV1D50e9cgpSK)

### Stake Retrieval

This process also occurs every other cycle for each **TON Pool** contract.

1. The Election Controller sends a recover stake message to the Pool contract.
2. The Pool contract relays this message to the Elector contract through the proxy.
3. The Elector contract returns the stake and rewards to the pool through the proxy.

![](/files/b5BaqW6zSVk0ZxEtfkuY)

## Efficient On-Chain Operations

To optimize gas costs, all main operations are consolidated to occur once per election cycle:

* Stake and withdrawal actions are processed once per election cycle.
* Election bids (stake bids) are placed once per cycle.
* This approach includes tracking the long-term ADNL key for election bids and generating election keys once per cycle.
* Stake and reward retrieval are also conducted once per cycle.

## Further Reading

* [TON Docs](https://docs.ton.org/develop/overview)
* [TON Whales contract](https://github.com/tonwhales/ton-nominators/)
* [FunC standard library](https://docs.ton.org/develop/func/stdlib)
* [TVM exit codes](https://docs.ton.org/learn/tvm-instructions/tvm-exit-codes)
* [TL-B (Type Language - Binary) definitions](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb)
* [TON Elector contract](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/elector-code.fc)
* [TON Config](https://tonviewer.com/config)
* [Validation Cycle Live](https://tonscan.com/validation)


# Nominator


# Overview

The **Nominator Pool** is ideal for groups looking to pool resources and stake collectively. It allows up to 40 users to combine their holdings, with a collective minimum of 400,000 TON (at least 10,000 TON per user). Rewards are automatically distributed proportionally, making it a convenient and efficient option for shared staking.

The **Chorus One SDK** simplifies this process by providing developers with the tools needed to build, sign, and broadcast staking transactions.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular TON libraries such as `@ton/ton`. This compatibility ensures that you can seamlessly integrate these methods into your existing TON projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on TON using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes we will be using the TON testnet.

First, create an instance of `TonNominatorPoolStaker` with the following configuration:

```javascript
import { TonNominatorPoolStaker } from '@chorus-one/ton'

const staker = new TonNominatorPoolStaker({
  rpcUrl: 'https://testnet.toncenter.com/api/v2/jsonRPC'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the TON RPC endpoint. This is where the SDK will connect to interact with the network. In this example, we are using a public endpoint for the testnet.

***

## Initializing the Staker

After configuring the `TonNominatorPoolStaker`, you can initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `TonNominatorPoolStaker` class provides methods to build transactions for staking, unstaking, and wallet deployment.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/ton/nominator/methods) section.

**Example of building a nominator pool staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  amount: '1', // 1 TON
})
```

***

## Getting the Validator Address provided by Chorus One

To be eligible for the validator election process, validators need a minimum stake of 400,000 TON locked in the validator contract:

Due to above requirements we deploy the TON Validator contract upon client request. If you'd like to stake TON with Chorus One, please contact us at <staking@chorus.one>

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/signers-explained/what-is-a-signer.md) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks you can leverage its robust security features to sign transactions on the TON network. To set up Fireblocks, you must provide the necessary API key, secret key, and vault ID.

Example shown below:

```javascript
import { TonNominatorPoolStaker } from '@chorus-one/TON'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'TON_TEST',
  addressDerivationFn: TonNominatorPoolStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](/signers-explained/fireblocks)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const txHash = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({
  address: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  txHash
})

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the TON network using the TON testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `TonNominatorPoolStaker`, continue to the [Methods](/build-your-staking-dapp/ton/nominator/methods) section.

## Further Reading

* [TonNominatorPoolStaker API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker)
* [What is a Signer?](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/signers-explained/what-is-a-signer.md)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the TON Network via the **Nominator Pool** contract.

The Chorus One SDK supports various staking operations including staking, unstaking, withdrawing, and retrieving staking information.

Below, we explore each method with practical examples to help you get started.

***

## buildStakeTx

### Description

The `buildStakeTx` method helps you create a transaction for staking TON tokens with a validator using the Nominator Pool contract.

Staking tokens involves locking them up to support the network's security and operations, and in return, you earn rewards.

### How to Use

To build a staking transaction, you will need to specify the amount to stake, the delegator's address (your wallet), and the validator's address where you want to stake your tokens.

* Optionally, you can provide a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  amount: '1', // 1 TON
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

In the above example, we're staking 1 TON with a specified validator with an optional expiration time.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker#buildstaketx)

***

## buildUnstakeTx

### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator using the Nominator Pool contract.

Unstaking involves withdrawing your staked tokens, which then enter a waiting period before they become available for withdrawal.

### How to Use

To build an unstaking transaction, you will need to provide the delegator's address (your wallet), and the validator's address from which you want to withdraw your tokens.

* Optionally, you can provide a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

In the above example, we are unstaking all staked TON from a specified validator, with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker#buildunstaketx)

***

## buildDeployWalletTx

### Description

The `buildDeployWalletTx` method allows you to create a transaction for deploying a wallet contract to a specified address.

### How to Use

To build a wallet deployment transaction, you will need to specify the address you wish to deploy the wallet contract to, and optionally, a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildDeployWalletTx({
  address: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

Here we can see we are deploying a wallet contract to a specified address, with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker#builddeploywallettx)

***

## getPoolContractNominators

### Description

The `getPoolContractNominators` method retrieves the active nominators for a specified Nominator Pool contract.

* This includes information on the nominators who have staked tokens with a specific validator.

### How to Use

To get this information, you will need to provide the validator's address.

### Example

```javascript
const { nominators } = await staker.getPoolContractNominators({
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP'
})
console.log(`Active nominators: ${nominators}`)
```

In this example, we are retrieving the active nominators for the specified validator.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker#getpoolcontractnominators)

***

## getStake

## Description

The `getStake` method retrieves the staking information from a delegator.

* This includes the amount of tokens currently staked with a validator.

## How to Use

To get staking information, you need to provide the delegator's address (your wallet) and the validator's address.

## Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker#getstake)

***

## Further Reading

For more detailed information and additional methods please refer to the official API reference:

* [TON Nominator Pool SDK API Reference](/api-reference/stakers/ton_src.tonnominatorpoolstaker)


# Single Nominator


# Overview

The **Single Nominator Pool** is a secure staking solution designed for large holders (minimum 400,000 TON) who value full control over their assets. By removing the need for multiple nominators, it minimizes the attack surface and enhances security. This pool is tailored for solo stakers, offering partial withdrawals and a straightforward, independent staking experience.

The **Chorus One SDK** simplifies staking process by providing developers with the tools needed to build, sign, and broadcast staking transactions.

{% hint style="info" %}
**Compatibility Notice**

The methods provided in this documentation are compatible with popular TON libraries such as `@ton/ton`. This compatibility ensures that you can seamlessly integrate these methods into your existing TON projects.
{% endhint %}

## Setting Up the Staker

To get started with staking on TON using the Chorus One SDK, you will first need to initialize the SDK.

* **Note:** For testing purposes we will be using the TON testnet.

First, create an instance of `TonSingleNominatorPoolStaker` with the following configuration:

```javascript
import { TonSingleNominatorPoolStaker } from '@chorus-one/ton'

const staker = new TonSingleNominatorPoolStaker({
  rpcUrl: 'https://testnet.toncenter.com/api/v2/jsonRPC'
})
```

**Configuration Parameters**:

* **rpcUrl**: The URL of the TON RPC endpoint. This is where the SDK will connect to interact with the network. In this example, we are using a public endpoint for the testnet.

***

## Initializing the Staker

After configuring the `TonSingleNominatorPoolStaker`, you can initialize it to prepare for staking operations.

This can be done via the following input:

```javascript
await staker.init()
```

The `init` method establishes a connection with the configured RPC endpoint and prepares the staker for operations such as building and broadcasting transactions.

***

## Building Transactions

Once the staker and signer are set up, you can start building transactions for staking operations.

The `TonSingleNominatorPoolStaker` class provides methods to build transactions for staking, unstaking, and wallet deployment.

* You can learn more about these methods in the [Methods](/build-your-staking-dapp/ton/single-nominator/methods) section.

**Example of building a nominator pool staking transaction:**

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  amount: '1', // 1 TON
})
```

***

## Getting the Validator Address provided by Chorus One

To be eligible for the validator election process, validators need a minimum stake of 400,000 TON locked in the validator contract:

Due to above requirements we deploy the TON Validator contract upon client request. If you'd like to stake TON with Chorus One, please contact us at <staking@chorus.one>

***

## Signing the Transaction

Once the transaction is built, you can sign that transaction using your own signing solution e.g.:

```js
const signedTx = await yourWallet.signTransaction(tx)
```

Additionally, you can use the Chorus One SDK to sign transactions using Fireblocks, mnemonic or other methods.

* For detailed information on setting up and configuring these options, please refer to the [What is a Signer?](/signers-explained/what-is-a-signer) section.

{% tabs %}
{% tab title="Using Fireblocks for Signing" %}
By integrating Fireblocks you can leverage its robust security features to sign transactions on the TON network. To set up Fireblocks, you must provide the necessary API key, secret key, and vault ID.

Example shown below:

```javascript
import { TonSingleNominatorPoolStaker } from '@chorus-one/TON'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'TON_TEST',
  addressDerivationFn: TonSingleNominatorPoolStaker.getAddressDerivationFn()
})

await signer.init()

const { signedTx } = await staker.sign({
  signer,
  signerAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  tx
})
```

For more information please refer to the [Signing with Fireblocks](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/build-your-staking-dapp/signers-explained/fireblocks.md)
{% endtab %}
{% endtabs %}

***

## Broadcasting the Transaction

After signing the transaction, you will need to broadcast it to the network. You can do this using the `broadcast` method:

```javascript
const txHash = await staker.broadcast({ signedTx })
```

And now you can track the transaction status:

```javascript
const { status, receipt } = await staker.getTxStatus({
  address: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  txHash
})

console.log(status) // 'success'
```

***

## Next Steps

In this section you learned how to set up the Chorus One SDK for the TON network using the TON testnet, which included how to build staking transactions, sign, broadcast, and track them.

* To learn more about the available methods on `TonSingleNominatorPoolStaker`, continue to the [Methods](/build-your-staking-dapp/ton/single-nominator/methods) section.

## Further Reading

* [TonSingleNominatorPoolStaker API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker)
* [What is a Signer?](/signers-explained/what-is-a-signer)


# Methods

This section provides an overview of the key methods available in the **Chorus One SDK** for staking on the TON Network via the **Single Nominator Pool** contract.

The Chorus One SDK supports various staking operations including staking, unstaking, withdrawing, and retrieving staking information.

Below, we explore each method with practical examples to help you get started.

***

## buildStakeTx

### Description

The `buildStakeTx` method helps you create a transaction for staking TON tokens with a validator using the Single Nominator Pool contract.

{% hint style="info" %}
The Single Nominator Pool contract accepts only one delegator. Usually the contract is deployed by a network operator like Chorus One on demand, because there is a significant amount of stake required to get into a validator set.

The benefit of Single Pool contract is that a nominator can do partial stake withdraws. Which is not possible with Nominator Pool contract.
{% endhint %}

Staking tokens involves locking them up to support the network's security and operations, and in return, you earn rewards.

### How to Use

To build a staking transaction, you will need to specify the amount to stake, the delegator's address (your wallet), and the validator's address where you want to stake your tokens.

* Optionally, you can provide a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildStakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  amount: '1', // 1 TON
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

In the above example, we're staking 1 TON with a specified validator with an optional expiration time.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker#buildstaketx)

***

## buildUnstakeTx

### Description

The `buildUnstakeTx` method allows you to create a transaction for unstaking tokens from a validator using the Single Nominator Pool contract.

Unstaking involves withdrawing your staked tokens, which then enter a waiting period before they become available for withdrawal.

### How to Use

To build an unstaking transaction, you will need to provide the delegator's address (your wallet), amount and the validator's address from which you want to withdraw your tokens.

* Optionally, you can provide a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildUnstakeTx({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
  amount: '1', // 1 TON
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

In the above example, we are unstaking 1 TON from a specified validator, with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker#buildunstaketx)

***

## buildDeployWalletTx

### Description

The `buildDeployWalletTx` method allows you to create a transaction for deploying a wallet contract to a specified address.

### How to Use

To build a wallet deployment transaction, you will need to specify the address you wish to deploy the wallet contract to, and optionally, a Unix timestamp for when the transaction expires.

### Example

```javascript
const { tx } = await staker.buildDeployWalletTx({
  address: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validUntil: Math.floor(Date.now() / 1000) + 3600 // Optional, expires in 1 hour
})
```

Here we can see we are deploying a wallet contract to a specified address, with an optional expiration time of 1 hour.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker#builddeploywallettx)

***

## getPoolContractNominators

### Description

The `getPoolContractNominators` method retrieves the active nominators for a specified Single Nominator Pool contract.

* This includes information on the nominators who have staked tokens with a specific validator.

### How to Use

To get this information, you will need to provide the validator's address.

### Example

```javascript
const { nominators } = await staker.getPoolContractNominators({
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP'
})
console.log(`Active nominators: ${nominators}`)
```

In this example, we are retrieving the active nominators for the specified validator.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker#getpoolcontractnominators)

***

## getStake

## Description

The `getStake` method retrieves the staking information from a delegator.

* This includes the amount of tokens currently staked with a validator.

## How to Use

To get staking information, you need to provide the delegator's address (your wallet) and the validator's address.

## Example

```javascript
const { balance } = await staker.getStake({
  delegatorAddress: '0QDsF87nkTYgkvu1z5xveCEGTRnZmEVaVT0gdxoeyaNvmoCr',
  validatorAddress: 'Ef9rkkVM0xr4rKZZMAfBkXU0U8qMnkTmqbUhYRNBvRt5knxP',
})
console.log(`Staked balance: ${balance}`)
```

In this example, we're retrieving the staked balance for a given delegator and validator.

* [Read more in the API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker#getstake)

***

## Further Reading

For more detailed information and additional methods please refer to the official API reference:

* [TON SDK API Reference](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker)


# Prerequisites

### Introduction

We'll delve into the practical use of the **Chorus One SDK** for key operations like staking, unstaking, minting, burning and querying details.This tutorial is a hands-on approach to understanding and leveraging the SDK's capabilities.

**By the end of this tutorial, you will learn how to do the following:**

* Learn about staking and vaults
* Fetch and display vault details such as TVL, APY, description, and balance
* Stake to and deposit to a vault
* Unstake from and withdraw from a vault
* Mint the liquid staking token osETH
* Burn osETH to unlock staked ETH
* Fetch and display vault transaction history
* Retrieve and display rewards history
* Build a simple Staking dApp that connects to MetaMask using wagmi

#### Understanding the Project Base

The Chorus One SDK Example is a React-based project that utilizes Vite as a bundler and leverages React Query for data management. The code is developed in TypeScript, offering type safety and an enhanced development experience. This setup provides a robust framework for integrating the Chorus One SDK.

#### Recommended Knowledge

While an in-depth understanding of all the technologies used is beneficial, it is not necessary to follow this guide. However, we recommend familiarity with the following:

* **Node.js (version 18) and npm (version 8)**: Essential tools for installing dependencies and running the project.
* **MetaMask**: A popular browser extension for interacting with the Ethereum blockchain, crucial for testing our decentralized application (dApp).
* **Basic Understanding of Ethereum and Smart Contracts**: Knowledge of how Ethereum works and the functionality of smart contracts is advantageous.
* **JavaScript Proficiency**: As the primary language of our project, comfort with JavaScript is important.
* **Familiarity with Ethereum Libraries**: Understanding libraries like wagmi, ethers, web3 and viem will be helpful, as they are key in managing wallet interactions and blockchain operations. In this guide, we particularly use wagmi and viem.

#### Wallet Connection

It's important to note that the Chorus One SDK does not inherently provide wallet connection functionality. For this, we will leverage the wagmi library, which excels at managing wallet interactions and blockchain operations.

* You can learn more about wagmi [here](https://wagmi.sh).

#### Network Configuration

The SDK is compatible with the Ethereum mainnet and Hoodi testnet. For the purposes of this tutorial, we use Hoodi, allowing for safe experimentation without risking real assets.

* More information about it can be found [here](https://github.com/eth-clients/hoodi).

Ensure that you configure your MetaMask wallet to connect to the Hoodi network as instructed in the guide. Alternatively, you can use the Ethereum mainnet network, but remember to adjust the network settings in the code accordingly.

With these prerequisites, you'll be well-equipped to begin building your staking dApp with the Chorus One SDK. Let's embark on this journey of blockchain development!

### Next Steps

Now that you have a good understanding of the foundation, you are ready to install the Chorus One SDK.

Please follow the instructions in the [Installation and Setup](/ethereum-tutorial/1-installation-and-setup) section to set up the SDK and prepare your development environment.


# 1. Installation and Setup

### Installation

To begin integrating the Chorus One SDK into your project, the first step is to add the library to the application. You can use your favorite package manager, including npm, yarn, pnpm or bun. For simplicity, we will use npm.

**In the project's root directory, run the following command:**

```bash
npm install @chorus-one/ethereum
```

Once the SDK is installed, the next step is to import it into your codebase and initialize it.

**Here's how you can do this:**

```javascript
import { EthereumStaker } from '@chorus-one/ethereum'

const staker = new EthereumStaker({
  network: 'hoodi'
})

await staker.init()
```

In the above snippet, we import the `EthereumStaker` from the `@chorus-one/ethereum` package, and we create a new `EthereumStaker` instance for hoodi network. After that, we initialize the staker by calling the `init` method.

{% hint style="success" %}
With these steps, the Chorus One SDK is successfully integrated and initialized in our project.
{% endhint %}

### Using Vaults with Chorus One SDK

The Chorus One SDK offers two primary ways to engage with vaults for Ethereum staking:

1. Using predefined default vaults provided by Chorus One
2. Configuring your own custom vaults.

Below is a guide on how to leverage each option.

#### Option 1: Accessing Default Vault Address

The Chorus One SDK has a predefined list of default vault addresses for each supported network. These vaults are Chorus One nodes, optimized for immediate use without additional setup.

To access these default vault addresses, you can use the `CHORUS_ONE_ETHEREUM_VALIDATORS` constant. This is particularly useful if you do not have specific vault addresses or prefer a quick setup.

{% hint style="info" %}

#### Vault Types

* **Max Vault (maxVault)**: This vault leverages Chorus One’s proprietary strategies to maximize staking rewards through innovative and evolving approaches. Historically, it has benefited from early adoption of Restaking and Looped Staking in collaboration with Stakewise. Chorus One continues to leverage in-house research to capture reward-enhancing opportunities as they arise, delivering maximum rewards to delegators.
* **Obol Distributed Validator Technology (obolDvVault)**: This vault uses [Obol's DVT](https://docs.obol.org/docs/int/Overview) to enhance resilience and decentralization of Ethereum staking by distributing validator duties across multiple nodes.
  {% endhint %}

**You can retrieve the default vault by running:**

```javascript
import { CHORUS_ONE_ETHEREUM_VALIDATORS } from '@chorus-one/ethereum'

const validatorAddress = CHORUS_ONE_ETHEREUM_VALIDATORS.ethereum.maxVault

console.log(vaultAddress) // '0x95d0db03d59658e1af0d977ecfe142f178930ac5'
```

#### Option 2: Using Custom Vault Addresses

The Chorus One SDK supports this flexibility if you prefer to use custom vaults and have specific vault addresses for your project. You can configure these addresses as part of your setup, enabling you to work with vaults of your choice.

## Integrating the wagmi Library

We will use wagmi and web3modal libraries to connect with Ethereum wallets, allowing users to interact with blockchain applications. This is an essential step, particularly because the Chorus One SDK does not provide wallet connection functionality.

The SDK relies on your application to manage an existing wallet connection. You can choose any library for this purpose, and the SDK will still function correctly.

For detailed instructions on installing and using wagmi and web3modal, please visit their respective websites: [wagmi](https://wagmi.sh) and [web3modal](https://docs.walletconnect.com/web3modal/about).

### Configuring wagmi in Your Application

To integrate wagmi into your project, we'll start by configuring it within your main application component. This involves wrapping your application in the `WagmiProvider` component, which is responsible for providing the necessary context for wagmi's functionality.

**Here's how you can do this:**

```javascript
import { WagmiProvider } from 'wagmi'
// Import the default wagmi configuration
import { config } from './config/wagmi'
import { Main } from './components/Main'

function App() {
  return (
    <WagmiProvider config={config}>
      <Main />
    </WagmiProvider>
  )
}

export default App
```

In the above code, we import `WagmiProvider` and wrap your main application component (`<Main />`). This setup ensures that all components within `<Main />` have access to wagmi's features.

In addition, we need to set up a WalletConnect project and use the `projectId` in the wagmi config. You can get your `projectId` by creating a new project on the [WalletConnect website](https://cloud.walletconnect.com).

* This step is necessary for the configuration file.

### Utilizing wagmi Hooks for Wallet Interactions

[Wagmi](https://wagmi.sh) provides a variety of hooks that make it simple to interact with user wallets and perform blockchain transactions. These hooks simplify the process of integrating web3 functionalities into your application.

**Let's look at how we can use some of these hooks:**

```javascript
import { useAccount, useWalletClient, usePublicClient } from 'wagmi'

// Retrieve the user's wallet address
const { address } = useAccount()

// Obtain a client to query public blockchain data
const publicClient = usePublicClient()

// Use the walletClient hook to execute transactions
const { data: walletClient } = useWalletClient()
```

In this example, `useAccount` is used to obtain the user's wallet address; the `usePublicClient` hook provides a client for querying public blockchain data. Finally, the `useWalletClient` hook provides a client for executing transactions, enabling interactions with the blockchain.

### Next Steps

In this section, we integrated the wagmi library into your project and configured it within your main application component.

To continue with the tutorial, let's move on to the next section: [Fetching Vault Details](/ethereum-tutorial/2-fetching-vault-details), where we will learn how to fetch and display details about the vault using the Chorus One SDK.


# 2. Fetching Vault Details

### Overview

In this section, we will explore how to fetch and display vault details using the Chorus One SDK.

This process involves initializing the SDK, fetching the vault details, and presenting them in a user-friendly format.

### Initializing the SDK and Fetching Vault Details

First, we start by initializing the SDK like we did previously. Then, we use the `getVault` method to fetch details about the vaults.

**Here’s a snippet illustrating this process:**

```javascript
import { EthereumStaker, CHORUS_ONE_ETHEREUM_VALIDATORS } from '@chorus-one/ethereum'

const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

const validatorAddress = CHORUS_ONE_ETHEREUM_VALIDATORS.ethereum.maxVault
// Alternatively, you can define vaults yourself:
// const vault = '0x...';

// Note: The getVault method accepts an array of vault addresses.
const vault = await staker.getVault({ validatorAddress })

console.log(vault)
// {
//   address: "0x95d0db03d59658e1af0d977ecfe142f178930ac5",
//   name: "Chorus One Test Wallet",
//   description: "Test wallet for Chorus",
//   logoUrl: "https://storage.stakewise.io/dxepxhzxsrqs.png",
//   tvl: 5600841037682025178745n,
//   apy: "3.98146836137682602839366230181093629",
// }
```

The `Vault` object returned by `getVault` contains the following parameters:

* **`address` (Hex)**: The hexadecimal address of the Vault.
* **`name` (string)**: A human-readable identifier for the Vault.
* **`description` (string)**: A description of the Vault.
* **`logoUrl` (string)**: The URL of the Vault’s logo for UI display.
* **`tvl` (bigint)**: The total value of assets locked in the Vault, expressed in wei.
* **`apy` (string)**: The average yield percentage derived from historical data.

### Displaying Vault Details as a Table

Now, let’s display these vault details in a table format in the UI.

```javascript
import { formatEther } from 'viem';
import { Vault } from '@chorus-one/ethereum';

const Vault = ({ vaultDetails }: { vaultDetails: Vault[] }) => {
   return (
     <table>
        <thead>
           <tr>
             <th>Vault name</th>
             <th>Description</th>
             <th>APY</th>
             <th>TVL</th>
           </tr>
        </thead>
        <tbody>
           {vaultDetails.map((vault: Vault) => (
             <tr key={vault.name}>
                <td>{vault.name}</td>
                <td>{vault.description}</td>
                <td>{vault.apy * 100} %</td>
                <td>{vault.tvl} ETH</td>
             </tr>
           ))}
        </tbody>
     </table>
   );
};
```

Once rendered, the vault details will be displayed in an informative table on the screen, showcasing key information such as vault name, APY, and balances in user-friendly format:

![Vault details](/files/Bt0vvtSC85NjC2P4FH4t)

### Next Steps

In this section, we learned how to fetch and display details of a vault using the Chorus One SDK. To continue exploring the functionality of the SDK, you can proceed to the next section: [Staking](/ethereum-tutorial/3-staking).


# 3. Staking

### Overview

Staking is a core functionality of the **Chorus One SDK**, enabling users to lock their ETH to support network operations and earn rewards.

This section will cover how to integrate staking into your application by creating a form which submits the transaction.

### The Form Component

We will start by creating a basic form which consist of an input field for the amount to be staked and a button to submit the transaction.

**Below is an implementation of this form in React:**

```typescript
import React, { useState } from 'react';
import { useAccount, useBalance } from 'wagmi';

export const FormComponent = ({ onSubmit }) => {
   const { address } = useAccount();
   const { data: balance } = useBalance({
     address,
   });
   const [inputValue, setInputValue] = useState('');

   return (
     <div>
        <form onSubmit={(e) => {
           e.preventDefault();
           onSubmit(inputValue);
           setInputValue('');
        }}>
           <input
             type="text"
             placeholder="ETH amount"
             onChange={(e) => setInputValue(e.target.value)}
             value={inputValue}
           />
           <span>ETH</span>
           <div>Available to stake: {balance?.formatted} ETH</div>
           <button type="submit">Submit</button>
        </form>
     </div>
   );
};
```

This form component uses the `useAccount` and `useBalance` hooks from `wagmi` to manage user account details and balance information. The `onSubmit` prop is a function that handles the actual staking process, which you can define in your application logic.

This simple yet effective form provides the basic functionality to integrate staking into your Ethereum-based application.

![Stake form](/files/RA81iJchX9ctQoyqaFMr)

### Writing the Staking Transaction Function

Now, we will focus on the main operation of our application: submitting a staking transaction.

**Below is a representative snippet of the function:**

```typescript
const stake = async ({
  userAddress, // Comes from wagmi
  walletClient, // Comes from wagmi
  network, // Networks.Hoodi
  vault, // Vault address (can be provided by getDefaultVaults(...))
  amountToStake // Amount of ETH to deposit as string
}: {
  userAddress: Hex
  walletClient: ReturnType<typeof useWalletClient>['data']
  network: Networks
  vault: Hex
  amountToStake: string
}): Promise<Hex> => {
  const staker = new EthereumStaker({ network: 'hoodi' })
  await staker.init()

  const validatorAddress = CHORUS_ONE_ETHEREUM_VALIDATORS.ethereum.maxVault

  const { tx: stakeTx } = await staker.buildStakeTx({
    delegatorAddress: userAddress,
    validatorAddress,
    amount: amountToStake // Passed as string, e.g. '1' - 1 ETH
  })

  console.log(stakeTx)
  // {
  //   to: "0x...",
  //   data: "0x...",
  //   value: 10000000000000000n
  // }

  const request = await walletClient.prepareTransactionRequest(stakeTx)

  await walletClient.sendTransaction(request)
}
```

{% hint style="info" %}
**Delegation Tracking**

If you would like to learn how to track and attribute staking transactions to specific sources, such as marketing campaigns or integration partners, refer to the [Delegation Tracking](/build-your-staking-dapp/ethereum/delegation-tracking) section.
{% endhint %}

The `Transaction` object returned by `buildStakeTransaction` includes the following parameters:

* **`to` (Hex)**: The address of the contract to interact with(the vault address).
* **`data` (Hex)**: A contract hashed method call with encoded arguments (the transformation of the method call into this encoded and hashed form is handled by the `encodeFunctionData` method from the viem library).
* **`value` (bigint)**: The amount of ETH being used in the transaction. In this case, it's the amount being staked.

#### Ensuring Correct Amount Format for Staking

The `amountToStake` parameter must be a string representing the amount of ETH to deposit. For example, `'1'` represents 1 ETH.

If you have the amount as a `bigint`, convert it to a string using the `formatEther` function from `viem`. Example:

```typescript
import { formatEther } from 'viem'

const amountBigInt = 10000000000000000n // 0.01 ETH
const amountToStake = formatEther(amountBigInt)

console.log(amountToStake) // "0.01"
```

This ensures the `amountToStake` parameter is in the correct format for the staking transaction function.

{% hint style="info" %}
**Configuring Fees**

We utilize here the Ethereum Improvement Proposal 1559 (EIP-1559) transaction type. With EIP-1559, users specify two types of fees:

* **`maxFeePerGas`**: The maximum fee per gas the user is willing to pay. This includes the base fee and the priority fee.
* **`maxPriorityFeePerGas`**: Also known as the tip, this incentivizes miners to prioritize the transaction.

The network determines the actual fee based on the current demand for block space and the transaction's priority. To estimate the gas required for the transaction, we use the `prepareTransactionRequest` method from the `viem`'s wallet client.

For detailed information on configuring fees, please refer to the [Viem Documentation](https://viem.sh/docs/chains/fees).
{% endhint %}

### Next Steps

Having integrated the basic staking functionality into your application, you're now ready to expand its capabilities.

To continue exploring our application's functionality, you can proceed to the next section: [Unstaking](/ethereum-tutorial/4-unstaking).


# 4. Unstaking

### Table of Contents

### Overview

With the Chorus One SDK, users can unstake their ETH from a Vault, regaining asset control. Users are placed in an exit queue where they continue to earn rewards, and then they can claim the staked ETH.

This section covers the entire process, from unstaking request initiation to handling the exit queue and withdrawing your ETH.

{% hint style="info" %}
We will use the same form as we did for staking for simplicity. This form allows users to input the amount of ETH and submit.

Please refer to the [Staking Functionality](/ethereum-tutorial/3-staking) section for more details.
{% endhint %}

### Determining Unstaking Limits

To begin, we need to establish the maximum amount that the user is permitted to unstake. This is achieved by invoking the `getStake` method on the `EthereumStaker` instance.

**Here's how you can implement it:**

```typescript
const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

const { maxUnstake } = await staker.getStake({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(maxUnstake) // '1' - 1 ETH

if (amountToUnstake > maxUnstake) {
  // The user is trying to unstake more than they can
  throw new Error('Unstaking amount exceeds the limit')
}
```

{% hint style="warning" %}
To unstake your entire ETH amount, you may need to burn your osETH tokens first. Burning osETH reclaims the underlying staked ETH. For detailed steps, see the [Burning osETH section](/ethereum-tutorial/6-burning-os-eth).
{% endhint %}

### Sending the Unstake Transaction

Once you've determined the maximum unstakeable amount, you can proceed to build and send the unstake transaction.

**The following example demonstrates how to use the `buildUnstakeTx` method:**

```typescript
const { tx: unstakeTx } = await staker.buildUnstakeTx({
  delegatorAddress: userAddress,
  validatorAddress,
  amount: amountToUnstake // Passed as string, e.g. '1' - 1 ETH
})

const request = await walletClient.prepareTransactionRequest(unstakeTx)
await walletClient.sendTransaction(request)
```

After initiating an unstake request, assets are placed into an unstake queue before being withdrawn. This is a safeguard to ensure the liquidity and stability of the vault. The duration an asset remains in the queue is contingent upon the validator's policies and the state of the vault.

### Fetching the Unstake Queue

To view the current state of your assets within the unstake queue, you'll need to query the queue for your specific vault.

**This can be accomplished with the following command:**

```typescript
const unstakeQueue = await staker.getUnstakeQueueForVault({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(unstakeQueue)
// [
//   {
//     positionTicket: '200565792007826595508',
//     timestamp: 1632960000000,
//     isWithdrawable: false,
//     totalAmount: '1',
//     withdrawableAmount: '0',
//     withdrawalTimestamp: 1735689600,
//   }
// ]
```

Here, `validatorAddress` refers to the address the vault, and `userAddress` is the wallets address. The returned `unstakeQueue` contains an array of objects, each representing an item within the queue. These objects are structured as follows:

* **`positionTicket`(string)**: A unique identifier for the queue item.
* **`timestamp` (number)**: The timestamp of the queue item's creation.
* **`isWithdrawable` (boolean)**: A flag indicating whether the assets are ready to be withdrawn.
* **`totalAmount` (string)**: The total amount of assets in the queue item, in ETH.
* **`withdrawableAmount` (string)**: The portion of assets, in ETH, that can be withdrawn.
* **`withdrawalTimestamp` (number | undefined)**: The Unix timestamp when withdrawal becomes available. `undefined` if not yet processed, `0` if ready to claim.

Once assets within the unstake queue reach a withdrawable state, users can initiate the withdrawal process to transfer them back into their wallets. This is done through the `buildWithdrawTx` method, which prepares the transaction necessary for withdrawing the specified assets.

### Preparing the Withdrawal Transaction

To withdraw assets, you'll need to identify which queue items are ready to be withdrawn. This is achieved by filtering the items in your unstake queue to include only those marked as `isWithdrawable`.

**The following example demonstrates how to prepare the withdrawal transaction:**

```typescript
const { tx: withdrawTx } = await staker.buildWithdrawTx({
  delegatorAddress: userAddress,
  validatorAddress,
  positionTickets: unstakeQueue.filter((item) => item.isWithdrawable).map((item) => item.positionTicket)
})
```

If you wish to withdraw all assets, you don't need to pass the `positionTickets` parameter. The SDK will automatically withdraw all assets marked as `isWithdrawable`.

In this snippet, `unstakeQueue` represents the queue items you've retrieved earlier. By filtering for `isWithdrawable` items, you ensure that only assets eligible for withdrawal are included in the transaction.

### Sending the Withdrawal Transaction

After preparing the withdrawal transaction, the next step is to send it to the blockchain.

**This process is similar to other transactions and can be done using the following code:**

```typescript
const request = await walletClient.prepareTransactionRequest(stakeTx)
await walletClient.sendTransaction(request)
```

{% hint style="success" %}
Once the transaction is successfully sent and confirmed, the specified assets are transferred from the unstake queue to your wallet. Depending on your needs and strategy, you can withdraw a portion or all of your withdrawable assets.
{% endhint %}

### Next Steps

In this section, we learned about the functionality for unstaking in the Chorus One SDK, covering both the initiation of unstaking and the process of managing assets within the unstake queue.

Now, you are ready to move on to the next section — [Minting osETH](/ethereum-tutorial/5-minting-os-eth).


# 5. Minting osETH

### Overview

Minting liquid staking tokens (osETH) allows users to maintain liquidity while staking their ETH.

In this section, we will guide you through checking minting limits, assessing vault health, and building and submitting minting transactions.

### Checking Minting Limits

Before minting, we need to check the maximum amount of shares that can be minted.

**This can be done using the** `getMint` **method:**

```typescript
const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

const { maxMint } = await staker.getMaxMintForVault({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(maxMint) // '1' - 1 ETH

if (maxMint < amountToMint) {
  // The user is trying to mint more than they can
  throw new Error('Minting amount exceeds the limit')
}
```

### Calculating Health Factor for Minting

After confirming the minting limits, the next step is to assess the health factor of the vault. This involves evaluating the vault's health given the amount of shares the user intends to mint.

**Use the** `getMintHealth` **method:**

```typescript
// Get the current amount of staked assets
const { balance: stakeAmount } = await staker.getStake({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(stakeAmount) // '3' - 3 ETH

const { balance: mintAmount } = await staker.getMaxMintForVault({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(mintAmount) // '1' - 1 ETH

const nextMintAmount = mintAmount + amountToMint

const nextHealth = await staker.getMintHealth({
  stakeAmount,
  mintAmount: nextMintAmount
})

console.log(nextHealth) // 'healthy'

if (nextHealth !== 'healthy') {
  // The vault will be unhealthy after minting
  throw new Error('Vault will be unhealthy after minting')
}
```

The `getMintHealth` method calculates the vault's health factor based on the current and intended minting amounts, ensuring the vault remains in a healthy state post-minting.

{% hint style="info" %}
The position health parameter is used to monitor the value of minted osETH relative to the staked ETH value:

* **`healthy`**: Minted osETH ≤ 90% of staked ETH
* **`moderate`**: Minted osETH > 90% but ≤ 91% of staked ETH
* **`risky`**: Minted osETH > 91% but ≤ 92% of staked ETH
* **`unhealthy`**: Minted osETH > 92% of staked ETH

Changes in position health can result from discrepancies between Vault APY and osETH APY, higher fees, inconsistent performance, or MEV theft.

Unhealthy positions may lead to forced burning of osETH tokens.
{% endhint %}

### Executing the Minting Transaction

If the minting limits and health factors are within acceptable ranges, you can proceed to minting the shares.

**To illustrate this, we use the `buildMintTx` method in the following example:**

```typescript
const { tx: mintTx } = await staker.buildMintTx({
  delegatorAddress: userAddress,
  validatorAddress,
  amount: amountToMint // Passed as string, e.g. '1' - 1 ETH
})

const request = await walletClient.prepareTransactionRequest(unstakeTx)
await walletClient.sendTransaction(request)
```

### Next Steps

In this section, we covered the essential steps for minting osETH tokens, including checking minting limits, calculating the health factor, and executing the minting transaction.

To continue exploring the capabilities of your application, proceed to the next section: [Burning osETH](/ethereum-tutorial/6-burning-os-eth).


# 6. Burning osETH

### Overview

In this section, we will cover the process of burning osETH tokens using the Chorus One SDK. Burning osETH is essential for redeeming your staked ETH, allowing you to unlock and unstake your assets from the Vault.

We will guide you through determining the maximum amount of osETH you can burn, preparing the burn transaction, and executing it on the blockchain.

### Determining Maximum Burnable osETH

First, we need to determine the maximum amount of osETH that can be burned. This is done by calling the `getMint` method on the `EthereumStaker` instance.

**Here's a snippet illustrating this process:**

```typescript
const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

const { balance: mintAmount } = await staker.getMaxMintForVault({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(mintAmount) // '1' - 1 ETH

if (amountToBurn > mintAmount) {
  // The user is trying to burn more than they can
  throw new Error('Burning amount exceeds the limit')
}
```

### Executing the Burning Transaction

After determining the maximum amount of osETH that can be burned, proceed to build and send the burn transaction.

**Here's how you can implement this with the `buildBurnTx` method:**

```typescript
const { tx: burnTx } = await staker.buildBurnTx({
  delegatorAddress: userAddress,
  validatorAddress,
  amount: amountToBurn // Passed as string, e.g. '1' - 1 ETH
})

const request = await walletClient.prepareTransactionRequest(unstakeTx)
await walletClient.sendTransaction(request)
```

### Next Steps

Now that you have learned how to burn osETH tokens, you are ready to dive deeper into the Chorus One SDK's capabilities. Proceed to the next section to explore [Transaction History](/ethereum-tutorial/7-transaction-history).


# 7. Transaction History

### Overview

Tracking the transaction history of your vaults is important for accountability and to understand user staking, unstaking, minting, and other activities. With the Chorus One SDK, you can fetch detailed transaction history which includes up to 1,000 transactions associated with a given vault.

This section will guide you through fetching and displaying this transaction history.

### Initializing the Staker and Fetching Transaction History

To start, we need to initialize the `EthereumStaker` in the same manner as we did previously. Then, we'll use the `getTxHistory` method provided by the SDK to retrieve the transaction history.

**Here's how you can write the code snippet for this process:**

```typescript
const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

const txHistory = await staker.getTxHistory({
  delegatorAddress: userAddress,
  validatorAddress
})

console.log(txHistory)
// [
//   {
//     timestamp: 1632960000000,
//     type: 'Deposited',
//     amount: '1',
//     txHash: '0x...'
//   }
// ]
```

The `getTxHistory` method returns an array of transaction objects. Each of these objects contains details about individual transactions.

**Here's a breakdown of the parameters in a `VaultTransaction` object:**

* **`timestamp` (number)**: The timestamp of the transaction.
* **`type` (VaultActionType)**: The type of transaction, which can be `Deposit`, `Redeem`, etc.
* **`amount` (string)**: The amount of Ethereum transacted.
* **`txHash` (Hex)**: The unique hash identifier of the transaction.

{% hint style="info" %}
The `VaultActionType` union includes the following types of transactions:**`Redeemed`**, **`Deposited`**, **`VaultCreated`**, **`OsTokenMinted`**, **`OsTokenBurned`**, **`OsTokenRedeemed`**, **`OsTokenLiquidated`**, **`ExitedAssetsClaimed`**, **`Migrated`**
{% endhint %}

### Displaying Transaction History

After fetching the transaction history, we will display it in a structured table format.

**Here's the code snippet for the transaction history table:**

```typescript
import { formatEther } from 'viem';

const Transactions = ({ transactions }) => {
  return (
    <table>
      <thead>
        <tr>
          <th>Transaction Type</th>
          <th>Transaction Hash</th>
          <th>Amount</th>
          <th>Date</th>
        </tr>
      </thead>
      <tbody>
        {transactions.map((transaction, index) => {
          const { vault } = transaction;
          const type = transaction.type ?? 'No Type';
          const date = transaction.timestamp
            ? new Date(transaction.timestamp).toLocaleDateString()
            : 'No Date';
          const hash = transaction.txHash;

          return (
            <tr key={index}>
              <td>{type}</td>
              <td>
                <a href={`https://hoodi.etherscan.io/tx/${hash}`}>{hash}</a>
              </td>
              <td>{transaction.amount} ETH</td>
              <td>{date}</td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
};
```

The `Transactions` component function takes an array of transaction objects and renders them in a table. Each transaction's details, including the vault name, address, transaction type, hash, amount, and date, are neatly displayed. Transaction hashes are linked to Etherscan for easy tracking.

**Once rendered, the transaction history will be displayed in an informative table on the screen:**

![Transaction history](/files/DTJ9EqwWu8EljWYua5cl)

### Next Steps

In this section, we learned how to fetch transaction history using the `getTransactionsHistory` method and displayed it in a structured table format.

Next, we will fetch the vault rewards history and draw its chart. Please proceed to the [Rewards History](/ethereum-tutorial/8-rewards-history) section to continue.


# 8. Rewards History

### Overview

In this section, we'll explore the process of fetching and visualizing rewards history using the Chorus One SDK. Visualizing reward data helps users gain insights into their earnings over time and make informed decisions about their staking activities.

We will guide you through fetching the necessary data, and presenting it in a user-friendly chart.

### Initializing the Pool and Fetching Rewards History

As with our previous tasks, we begin by initializing `EthereumStaker`. Then, we'll use the `getRewardsHistory` method to gather the rewards history.

**Below is a sample code snippet for fetching rewards history:**

```typescript
const staker = new EthereumStaker({ network: 'hoodi' })
await staker.init()

// Setting the date range: from 1 month ago to today
const from = new Date()
from.setMonth(from.getMonth() - 1)
const to = new Date()

const rewardsHistory = await staker.getRewardsHistory({
  startTime: from.getTime(),
  endTime: to.getTime(),
  delegatorAddress: userAddress,
  validatorAddress
})
```

The `getRewardsHistory` method requires an object with the following parameters:

* **`startTime` (number)**: The start time in milliseconds.
* **`endTime` (number)**: The end time in milliseconds.
* **`delegatorAddress` (Hex)**: The user address for which to retrieve rewards history.
* **`validatorAddress` (Hex)**: The vault address from which to retrieve rewards history.

The method returns an array of `RewardsDataPoint` objects, each containing:

* **`timestamp` (number)**: The timestamp of the rewards transaction.
* **`amount` (string)**: The amount of rewards received in ETH.

### Visualizing Rewards Data with a Chart

We will use a chart to provide a visual representation of the rewards. We have chosen to use [Recharts](https://recharts.org), a composable library built on React components for this guide. However, feel free to use any other charting library that suits your needs.

**First, we'll transform the rewards history data into a format suitable for Recharts:**

```typescript
const chartData = rewardsHistory.map((point) => {
  return {
    date: new Date(point.timestamp).toDateString(),
    amount: Number(point.amount)
  }
})
```

In this transformation, each rewards data point is converted into an object with `date` and `amount` properties, where `date` is a string representation of the date, and `amount` is the reward amount in Ether.

**Here's the code snippet for creating a line chart with our rewards data:**

```typescript
import { LineChart, Line, XAxis, YAxis } from 'recharts';

type ChartDataPoint = {
    amount: number;
    date: string;
};

const RewardsChart = ({ data }: { data: ChartDataPoint[] }) => {
    return (
        <LineChart width={700} height={300} data={data}>
            <XAxis dataKey="date" />
            <YAxis />
            <Line type="monotone" dataKey="amount" />
        </LineChart>
    );
};
```

In this snippet, we import the necessary components from Recharts and define the `RewardsChart` component. This component takes an array of `ChartDataPoint` objects and renders them in a LineChart.

The `XAxis` and `YAxis` components provide the chart's axises, while the `Line` component plots the transaction amounts over time.

### Chart Representation on the Screen

Once rendered, the line chart provides a clear view of reward history over time.

![Rewards chart](/files/S3wUWYnZHoH7YFIaNRp1)

## Wrapping Up

Throughout this guide, we explored the powerful capabilities of the Chorus One SDK, unlocking its potential for various key operations.

We started by setting up the SDK and quickly moved into practical tasks like fetching and displaying vault details. From there we explored staking and showing how to lock ETH seamlessly and earn rewards.

Next, we covered the process of minting osETH tokens to maintain liquidity and the essential steps to burn osETH tokens and reclaim your staked ETH.

Our step-by-step instructions made unstaking your ETH and navigating the exit queue a breeze, highlighting the user-friendly nature of the Chorus One SDK.

We also covered how to track transaction history for a given vault, giving you clear insights into all your staking, unstaking, and other activities.

Lastly, we wrapped up by visualizing the rewards history, helping you understand the benefits accrued from the vault.

By the end of this guide, you should feel confident in leveraging the Chorus One SDK to enhance your Ethereum-based applications. Happy staking! 📥

{% hint style="info" %}
For more detailed information on the Chorus One SDK, visit the [API Documentation](/api-reference/stakers/ethereum_src.ethereumstaker) to explore all available methods and their usage.
{% endhint %}


# What is a Signer?

A signer in the context of the **Chorus One SDK** is an essential component responsible for managing cryptographic signing operations.

It handles the creation of digital signatures that verify the authenticity and integrity of transactions or messages, utilizing raw signing with the Elliptic Curve Digital Signature Algorithm (ECDSA).

### Supported Signers

The Chorus One SDK provides built-in support for two primary types of signers:

1. **Fireblocks Signer**
   * Integrates with the Fireblocks platform, leveraging secure multi-party computation (MPC) for signing operations.
   * This is ideal for enterprise use cases where enhanced security and compliance are paramount.
2. **Local Signer**
   * Uses a provided private key to sign transactions locally.
   * Suitable for individual developers or smaller projects where simplicity and direct control are prioritized.
3. **Ledger Cosmos Signer**
   * Utilizes a Ledger device to sign transactions for Cosmos SDK-based networks.
   * Ideal for users who prefer hardware wallets for enhanced security.
4. **Keplr Signer**
   * Integrates with the Keplr wallet extension to sign transactions for Cosmos SDK-based networks.
   * Suitable for web-based wallet interfaces.

### Custom Signers

The flexible design of the Chorus One SDK allows developers to implement their own custom signers.

By conforming to the `Signer` interface, you can integrate various signing mechanisms, whether they involve hardware wallets, custom cryptographic algorithms, or third-party services.

### Example Usage

Below is an example of how a signer is used in conjunction with the Cosmos blockchain within the Chorus One SDK:

```javascript
import { SolanaStaker } from '@chorus-one/solana'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'ATOM',
  addressDerivationFn: SolanaStaker.getAddressDerivationFn()
})

await signer.init()

// Use staker to sign a transaction
const { signedTx } = await staker.sign({
  signer
  ...
})
```

By abstracting the signing logic the Chorus One SDK ensures that staking operations remain secure and developer-friendly, regardless of the underlying blockchain or signing method.

This modular and flexible approach allows seamless integration and customization, enabling developers to select or create the most suitable signer for their specific use case.

### Next Steps

We learned about the role of signers in blockchain transactions and how the Chorus One SDK uses raw signing with ECDSA.

We also explored the built-in support for Fireblocks and Local signers and the flexibility to implement custom signers.

To continue, explore the following guides below:

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Signing with Fireblocks</strong></td><td></td><td><a href="/pages/oVDiCvJA4zbMfDBV4ygN">/pages/oVDiCvJA4zbMfDBV4ygN</a></td></tr><tr><td><strong>Signing with a Mnemonic</strong></td><td></td><td><a href="/pages/9MaA1XeEdbKNbLor6yTw">/pages/9MaA1XeEdbKNbLor6yTw</a></td></tr><tr><td><strong>Implementing a Custom Signer</strong></td><td></td><td><a href="/pages/qyPeGJtTJOcwzWIQ7HBp">/pages/qyPeGJtTJOcwzWIQ7HBp</a></td></tr><tr><td><strong>Signing with a Browser Extension Wallet</strong></td><td></td><td><a href="/pages/nO0YRpq3lqNHR88Du8UA">/pages/nO0YRpq3lqNHR88Du8UA</a></td></tr><tr><td><strong>Signing with a Ledger Device</strong></td><td></td><td><a href="/pages/RIk2IOMlOOtDlMJ90yiI">/pages/RIk2IOMlOOtDlMJ90yiI</a></td></tr></tbody></table>

### Further Reading

* [Elliptic Curve Digital Signature Algorithm (ECDSA)](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)
* [RFC 6979: Deterministic Usage of DSA and ECDSA](https://tools.ietf.org/html/rfc6979)


# Signing with Fireblocks

The `FireblocksSigner` in the **Chorus One SDK** is a specialized implementation of the `Signer` interface that integrates with the Fireblocks platform.

Fireblocks is known for its advanced security features, including multi-party computation (MPC) and secure wallet infrastructure, making it an ideal choice for enterprises requiring robust security and compliance.

### Obtaining Fireblocks Credentials

Before initializing the `FireblocksSigner`, you will need to acquire the necessary credentials from Fireblocks.

* This includes the `apiSecretKey`, `apiKey`, `vaultName`, and `assetId`.

Let's explain a bit more about what those are below:

* **apiSecretKey**: Fireblocks API Secret key. Generate this by creating an RSA key file as described in the [Fireblocks Quickstart Guide](https://developers.fireblocks.com/docs/quickstart#step-1-generate-a-csr-file).
* **apiKey**: Fireblocks API Key. Obtain this from the Fireblocks platform as detailed in the [Fireblocks Quickstart Guide](https://developers.fireblocks.com/docs/quickstart#step-2-create-an-api-key).
* **vaultName**: The name of the Fireblocks vault where the assets are stored.
* **assetId**: The identifier for the asset you intend to manage. You can get this from the Fireblocks platform.
* **addressDerivationFn**: A function that derives the address from the public key, implementing the `AddressDerivationFn` type and provided by Staker classes as static methods, e.g. `SolanaStaker.getAddressDerivationFn`, `NearStaker.getAddressDerivationFn`, etc.

```typescript
type AddressDerivationFn = (publicKey: Uint8Array, hdPath: string) => Array<string>
```

{% hint style="info" %}
Address derivation processes across different blockchains typically involve a combination of elliptic curve cryptography (like `secp256k1` used in Ethereum, Cosmos, and Avalanche’s C-Chain, and `ed25519` used in NEAR) and specific cryptographic transformations such as hashing (Keccak-256 for Ethereum, SHA-256 for Cosmos, and various for Avalanche depending on the chain), truncating, and encoding (Bech32 for Cosmos and Avalanche, Base58 for NEAR).
{% endhint %}

### Setting Up the FireblocksSigner

With your credentials ready, you can now configure and initialize the FireblocksSigner:

```javascript
import { SolanaStaker } from '@chorus-one/solana'
import { FireblocksSigner } from '@chorus-one/signer-fireblocks'

const signer = new FireblocksSigner({
  apiSecretKey: 'your-api-secret-key',
  apiKey: 'your-api-key',
  vaultName: 'your-vault-name',
  assetId: 'SOL',
  addressDerivationFn: SolanaStaker.getAddressDerivationFn()
})

await signer.init()
```

### Ethereum Contract Call Signing

The `contractCall` method on `FireblocksSigner` enables secure Ethereum smart contract interactions via Fireblocks, supporting both native and pooled staking flows.

#### How `contractCall` Works

`contractCall` submits your contract call as a Fireblocks transaction and manages the signing and execution process end-to-end:

```javascript
const result = await signer.contractCall({
  to: '0x...',                        // Contract address
  value: BigInt('32000000000000000000'), // Amount in wei
  data: '0x...',                      // Encoded contract call data
  gas: BigInt(21000),                 // Gas limit
  maxFeePerGas: BigInt(20000000000),  // EIP-1559 max fee per gas
  maxPriorityFeePerGas: BigInt(2000000000), // EIP-1559 priority fee
  gasPrice: BigInt(20000000000),      // Legacy gas price
  note: 'Ethereum validator deposit'   // Optional note
})
```

#### Under the Hood

* **Creates Fireblocks Transaction**: Builds a transaction with `CONTRACT_CALL` operation, placing your contract call data in `extraParameters.contractCallData`.
* **Polls for Status**: Continuously checks Fireblocks for transaction completion or failure.
* **Returns Status**: Responds with:
  * `status`: 'success' or 'failure'
  * `receipt`: Full Fireblocks transaction details
  * `reason`: Error description if failed

#### Error States

Possible failure statuses include:

* `BLOCKED`: Blocked by Fireblocks policy
* `FAILED`: Execution failed
* `CANCELLED`: Transaction cancelled
* `REJECTED`: Rejected by policy
* `TIMEOUT`: Transaction exceeded allowed time (configurable via `timeout` parameter)

### Further Reading

* [Fireblocks Documentation](https://developers.fireblocks.com/)
* [FireblocksSigner API Reference](/api-reference/signers/signer_fireblocks_src.fireblockssigner)


# Signing with a Mnemonic

The `LocalSigner` in the **Chorus One SDK** is a specialized implementation of the `Signer` interface that utilizes a BIP39 mnemonic for signing operations.

This signer is ideal for local environments where you need a straightforward and secure method to generate and manage cryptographic keys from mnemonic phrases.

### Obtaining the Mnemonic and HD Path

Before initializing the `LocalSigner` you will need to prepare a BIP39 mnemonic and define the hierarchical deterministic (HD) path for key derivation.

Let's look at what these two key concepts are below:

* **mnemonic**: A string containing your BIP39 mnemonic phrase. This should be stored securely and kept private as it controls access to all addresses derived from it.
* **hdPath**: The BIP39 address derivation path, which is used to derive the specific key pair needed for signing. Commonly, this path follows the format `m/44'/60'/0'/0/0` for Ethereum-compatible addresses.
* **addressDerivationFn**: A function that derives the address from the public key, implementing the `AddressDerivationFn` type and provided by Staker classes as static methods, e.g. `SolanaStaker.getAddressDerivationFn`, `NearStaker.getAddressDerivationFn`, etc.

```typescript
type AddressDerivationFn = (publicKey: Uint8Array, hdPath: string) => Promise<Array<string>>
```

{% hint style="info" %}
Address derivation processes across different blockchains typically involve a combination of elliptic curve cryptography (like `secp256k1` used in Ethereum, Cosmos, and Avalanche’s C-Chain, and `ed25519` used in NEAR) and specific cryptographic transformations such as hashing (Keccak-256 for Ethereum, SHA-256 for Cosmos, and various for Avalanche depending on the chain), truncating, and encoding (Bech32 for Cosmos and Avalanche, Base58 for NEAR).
{% endhint %}

### Setting Up the LocalSigner

With your mnemonic and HD path ready, you can now configure and initialize the LocalSigner:

```javascript
import { SolanaStaker } from '@chorus-one/solana'
import { LocalSigner } from '@chorus-one/signer-local'
import { KeyType } from '@chorus-one/signer'

const signer = new LocalSigner({
  mnemonic: 'your-mnemonic-phrase',
  accounts: [{ hdPath: 'your-hd-path' }],
  keyType: KeyType.ED25519,
  addressDerivationFn: SolanaStaker.getAddressDerivationFn()
})

await signer.init()
```

### Further Reading

* [BIP39 Mnemonic Code](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
* [BIP32 HD Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
* [LocalSigner API Reference](/api-reference/signers/signer_local_src.localsigner)


# Signing with a Ledger Device

[Ledger Hardware Wallet](https://www.ledger.com/) is one of the most popular hardware wallet solutions on the market. It enables you to sign transactions on vast variety of blockchain networks through what the Ledger ecosystem calls`apps`.

The Ledger apps are installed on the device through the [Ledger Live](https://www.ledger.com/ledger-live) management software. The user than interacts with them through a variety of software wallet interfaces, such as the web-based browser extensions [Metamask](https://metamask.io/), [Keplr](https://www.keplr.app/) or [Phantom](https://phantom.app/) wallet.

To help illustrate how this process works, let's visualize the signing process on Ledger when using MetaMask as an example.

It would look like this:

```
javascript sign request -> metamask -> ledger app -> ledger device
```

## Signing with a Ledger App

If you're developing a node.js application that doesn't run in a browser environment, you might want to interact with a Ledger device but not be able to use a browser extension as illustrated above.

What to do then?

Don't worry, we got you covered. With the Chorus One SDK you can skip the browser extension entirely and sign your transaction directly as illustrated below:

```
node.js sign request -> ledger app -> ledger device
```

To do this, you will need to implement a new `Signer` that utilizes the desired Ledger app.

You can find all the supported Ledger apps here:

> [https://github.com/LedgerHQ](https://github.com/LedgerHQ/app-cosmos)

## Cosmos Ledger Signer

With the initial Chorus One SDK we released a `signer-ledger-cosmos` reference signer for Cosmos SDK based networks.

With that you can sign transactions for networks such as Cosmos Hub, Celestia, Osmosis and others using your Ledger device.

Here is an example of how to set up and and use the signer:

```javascript
import { LedgerCosmosSigner } from '@chorus-one/signer-ledger-cosmos'

const signer = new LedgerCosmosSigner({
  accounts: [{ hdPath: "m/44'/118'/0'/0/0" }],
  bechPrefix: networkConfig.bechPrefix
})
await signer.init()
```

Behind the scenes, the signer utilizes the `@ledgerhq/hw-app-cosmos` library to interact with the Ledger device.

For instance:

```javascript
import Cosmos from '@ledgerhq/hw-app-cosmos'

const app = new Cosmos(transport)
const { signature, return_code } = await app.sign(account.hdPath, signerData.message)
```

As you can see the Ledger app consumes the same data (hashed message) as the Fireblocks or Mnemonic signer.

* The returned signature is then attached to the unsigned transaction and broadcast to the network.

## How to Support other Ledger Apps?

If you wish us to support another network with Ledger, you can implement the signer on your own and send us a pull request.

As you can see from the reference Cosmos app example, it's not that complicated!

Alternatively, you can open an issue on the Github Repository.


# Signing with a Browser Extension Wallet

The flexible `Signer` abstraction enables the use of vast variety of signers, such as browser extension wallets like [Keplr](https://www.keplr.app/), [Metamask](https://metamask.io/), or [Phantom](https://phantom.app/).\
\
However, unlike the raw signers like `FireblocksSigner` or `LocalSigner`, the wallet extension may require complex data.

To recall, a raw signer will require you to pass only the the hashed message in order to generate a relevant signature to the key type.

Browser-based wallets implement their own API, and we can't ever know what that API is exactly.

However, we can predict the basic data the wallet will need. For example, an unsigned transaction, sender, receiver address, and amount.

* With that data any wallet should be able to sign your transaction regardless the specifics.

All `Staker` classes pass down data to the signer. In this case, this includes a set of "what-we-believe-to-be-required" data so that the signer can craft the request to the wallet extension.

**For example:**

```javascript
export interface CosmosSigningData {
  signDoc: StdSignDoc
}

const signDoc: StdSignDoc = { ... }
const data: CosmosSigningData = { signDoc }
const { sig } = await signer.sign(signerAddress, { message, data }, { note })
```

Here, the `CosmosStaker` will pass to the signer the `CosmosSigningData` with an unsigned network specific object of `StdSignDoc` down to the signer along with the hashed `message`.

* Your signer can then use either one of those, even though only one is necessary.

## Keplr Wallet Browser Extension

[Keplr](https://www.keplr.app/) is a popular browser extension for managing Cosmos-based blockchain accounts.

If you're developing a web dApp and you would like to quickly build & sign a transaction in your application we've got you covered!

```javascript
import { KeplrSigner } from '@chorus-one/signer-keplr'

const signer = new KeplrSigner({
  signer: window.keplr,
  chainId: netoworkConfig.chainId
})

await signer.init()
```

As you can see, the initialization is easy. The only extra thing you need to provide is the handle to the [Keplr wallet extension interface](https://docs.keplr.app/api/). In here, it is `window.keplr`

Once the implementation is done, the signer consumes the `CosmosSigningData` as follows:

```javascript
async sign (
  signerAddress: string,
  signerData: SignerData,
  _options: { note?: string }
): Promise<{ sig: Signature; pk: Uint8Array }> {
  const { signDoc }: CosmosSigningData = signerData.data
  const signingResponse = await this.signer.signAmino(
    signDoc.chain_id,
    signerAddress,
    signDoc
  )
}
```

## How to Support other Browser Extension Wallets?

If the Chorus One SDK does not support the web wallet of your choice, feel free to implement one on your own using the example described in this guide.

Alternatively, feel free to open a Github Issue.


# Implementing a Custom Signer

The **Chorus One SDK** provides flexibility for developers to implement custom signers tailored to their specific requirements.

A custom signer can be integrated by conforming to the `Signer` interface, which ensures compatibility with the SDK's transaction management processes.

It utilizes raw signing with the Elliptic Curve Digital Signature Algorithm (ECDSA).

## Signer Interface

To create a custom signer, you will first need to implement the `Signer` interface, provided by `@chorus-one/signer` ([📦 npm package](https://www.npmjs.com/package/@chorus-one/signer))

* This interface defines three essential methods: `sign`, `getPublicKey`, and `init`.

Here is the interface definition for a signer in TypeScript:

```typescript
interface Signer {
  sign: (
    signerAddress: string,
    signerData: SignerData,
    options: { note?: string }
  ) => Promise<{ sig: Signature; pk: Uint8Array }>
  getPublicKey: (address: string) => Promise<Uint8Array>
  init: () => Promise<void>
}
```

***

## Method Descriptions

1. **sign**(`signerAddress`: `string`, `signerData`: `SignerData`, `options?`: `{ note?: string }`): `Promise`<{ `sig`: `Signature`, `pk`: `Uint8Array` }>

A `Signer` represents a single private key, multiple (BIP-44) addresses signer. The `signerAddress` defines the private key used to sign `SigningData` that comes in two flavors:

1. `message` - `sha256` serialized transaction data. Use this for raw `secp256k1` signing
2. `data` - flexible network specific data passed from `Staker`. Use this with web wallets (e.g Keplr Wallet) that don't expose raw signing, but instead require blockchain specific objects, such as `SignDoc` for Cosmos networks

Optional `note` can be used by underlying signer for troubleshooting purposes.

It returns a Promise that resolves to an object containing:

* `sig`: The signature, adhering to the `Signature` interface.
* `pk`: The public key as a `Uint8Array`.

2. **getPublicKey**(`address`: `string`): `Promise`<`Uint8Array`>\`

This retrieves the public key associated with the signer address.

It returns a Promise that resolves to a `Uint8Array` representing the public key.

3. **init**(): `Promise`<`void`>

This initializes the signer, performing any necessary setup or configuration.

It returns a Promise that resolves once the initialization is complete.

***

## Signature Interface

The `Signature` interface defines the structure of the signature object returned by the `sign` method:

```typescript
interface Signature {
  fullSig: string
  r?: string
  s?: string
  v?: number
}
```

### Properties:

* **fullSig**: A string representing the complete signature, often a concatenation of the `r` and `s` values.
* **r**: (Optional) A hexadecimal string representing the first part of the ECDSA signature.
* **s**: (Optional) A hexadecimal string representing the second part of the ECDSA signature.
* **v**: (Optional) An integer representing the recovery id, which is used in some blockchains to recover the public key from the signature. **This value can be either 0 or 1.**

{% hint style="info" %}

#### Raw Signing

Raw signing is the process of generating a cryptographic signature directly from the transaction data, without any additional formatting.

In the context of ECDSA, the signature consists of two components: ( r ) and ( s ).

* The recovery id ( v ) is used to recover the public key from the signature.

The ECDSA algorithm is widely used in various security protocols and standards due to its strong security properties and efficiency.

It relies on the mathematics of elliptic curves, which provide a high level of security with relatively small key sizes compared to other cryptographic algorithms.

* You can find more information about ECDSA at [RFC 6979](https://tools.ietf.org/html/rfc6979).
  {% endhint %}

***

## Example: Custom Signer Implementation

Below is an example of a custom signer implementation using a simple signing mechanism:

```typescript
import { Signer, Signature, SignerData } from '@chorus-one/signer'

class CustomSigner implements Signer {
  private privateKey: Uint8Array
  private publicKey: Uint8Array

  constructor(privateKey: Uint8Array) {
    this.privateKey = privateKey
    this.publicKey = this.computePublicKey(privateKey)
  }

  async init(): Promise<void> {
    // Perform any necessary initialization here
    return Promise.resolve()
  }

  async sign(
    signerAddress: string,
    signerData: SignerData,
    options?: { note?: string }
  ): Promise<{ sig: Signature; pk: Uint8Array }> {
    const { r, s, v, fullSig } = this.createSignature(signerData.message)
    return Promise.resolve({
      sig: { fullSig, r, s, v },
      pk: this.publicKey
    })
  }

  async getPublicKey(): Promise<Uint8Array> {
    return Promise.resolve(this.publicKey)
  }

  private computePublicKey(privateKey: Uint8Array): Uint8Array {
    // Implement the logic to compute the public key from the private key
    return new Uint8Array() // Placeholder
  }

  private createSignature(content: string): Signature {
    // Implement the logic to create an ECDSA signature from the content
    const r = 'r_value' // Placeholder
    const s = 's_value' // Placeholder
    const v = 1 // Placeholder
    const fullSig = r + s // Placeholder
    return { r, s, v, fullSig }
  }
}
```

***

## Integrating the Custom Signer

Once you have implemented the custom signer, you can then integrate it with the Chorus One SDK just like any other signer:

```javascript
const signer = new CustomSigner(yourPrivateKey)

await signer.init()

const { signedTx } = await staker.sign({
  signer
  ...
})
```

***

## Further Reading

* [Elliptic Curve Digital Signature Algorithm (ECDSA)](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)
* [RFC 6979: Deterministic Usage of DSA and ECDSA](https://tools.ietf.org/html/rfc6979)


# Stakers


# AvalancheStaker

This class provides the functionality to stake, import, and export assets on the Avalanche network.

It also provides the ability to retrieve staking information and rewards for a delegator.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildStakeTx](#buildstaketx)
* [buildExportTx](#buildexporttx)
* [buildImportTx](#buildimporttx)
* [getStake](#getstake)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new AvalancheStaker**(`params`): [`AvalancheStaker`](/api-reference/stakers/avalanche_src.avalanchestaker)

This creates a new AvalancheStaker instance.

#### Parameters

| Name                      | Type             | Description                                                                                                                 |
| ------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`         | Initialization parameters                                                                                                   |
| `params.rpcUrl`           | `string`         | RPC URL (e.g. <https://api.avax.network>)                                                                                   |
| `params.hrp?`             | `string`         | (Optional) Address prefix (e.g. avax)                                                                                       |
| `params.asset?`           | `AvalancheAsset` | (Optional) Asset ID used for transactions (e.g. staking)                                                                    |
| `params.fee?`             | `AvalancheFee`   | (Optional) The fee used to pay for the transaction processing                                                               |
| `params.denomMultiplier?` | `string`         | (Optional) Multiplier to convert the base coin unit to its smallest subunit (e.g., `1000000000` for 1 AVAX = 1000000 nAVAX) |

#### Returns

[`AvalancheStaker`](/api-reference/stakers/avalanche_src.avalanchestaker)

An instance of AvalancheStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(`params`): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name          | Type     | Description                           |
| ------------- | -------- | ------------------------------------- |
| `params`      | `Object` | Parameters for the address derivation |
| `params.hrp?` | `string` | Address prefix (e.g. avax)            |

#### Returns

`fn`

Returns an array containing the derived C, P, X and Ethereum addresses.

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the AvalancheStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the AvalancheStaker instance has been initialized.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a staking (delegation) transaction.

#### Parameters

| Name                      | Type     | Description                                  |
| ------------------------- | -------- | -------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction      |
| `params.delegatorAddress` | `string` | The delegator (wallet) address to stake from |
| `params.validatorAddress` | `string` | The validator address to stake to            |
| `params.amount`           | `string` | The amount to stake, specified in `AVAX`     |
| `params.daysCount`        | `number` | The number of days to stake for              |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Avalanche staking transaction.

***

### buildExportTx

▸ **buildExportTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to export assets to another chain.

This is the first step of the transferring tokens from one chain to another. After the export transaction is issued on the source chain, call `buildImportTx` to finalize the transfer.

#### Parameters

| Name              | Type                  | Description                                                                |
| ----------------- | --------------------- | -------------------------------------------------------------------------- |
| `params`          | `Object`              | Parameters for building the transaction                                    |
| `params.address`  | `AvalancheAddressSet` | The source address to export from and the destination address to export to |
| `params.srcChain` | `string`              | The source chain to export from e.g. 'C', 'P'                              |
| `params.dstChain` | `string`              | The destination chain to export to e.g. 'C', 'P'                           |
| `params.amount`   | `string`              | The amount to export, specified in `AVAX`                                  |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Avalanche export transaction.

***

### buildImportTx

▸ **buildImportTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to import assets from another chain.

This is the last step of the transferring tokens from one chain to another.

Call `buildExportTx` on the source chain first, then call this method to finalize the transfer.

#### Parameters

| Name              | Type                  | Description                                                                |
| ----------------- | --------------------- | -------------------------------------------------------------------------- |
| `params`          | `Object`              | Parameters for building the transaction                                    |
| `params.address`  | `AvalancheAddressSet` | The source address to import from and the destination address to import to |
| `params.srcChain` | `string`              | The source chain to import from e.g. 'C', 'P'                              |
| `params.dstChain` | `string`              | The destination chain to import to e.g. 'C', 'P'                           |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Avalanche import transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                      | Type     | Description                    |
| ------------------------- | -------- | ------------------------------ |
| `params`                  | `Object` | Parameters for the request     |
| `params.delegatorAddress` | `string` | The delegator (wallet) address |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `SignedTx` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type         | Description                        |
| ---------------------- | ------------ | ---------------------------------- |
| `params`               | `Object`     | Parameters for the signing process |
| `params.signer`        | `Signer`     | Signer instance                    |
| `params.signerAddress` | `string`     | The address of the signer          |
| `params.tx`            | `UnsignedTx` | The transaction to sign            |

#### Returns

`Promise`<{ `signedTx`: `SignedTx` }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`IssueTxResponse`>

This method is used to broadcast a signed transaction to the Avalanche network.

#### Parameters

| Name              | Type       | Description                                                  |
| ----------------- | ---------- | ------------------------------------------------------------ |
| `params`          | `Object`   | Parameters for the broadcast                                 |
| `params.signedTx` | `SignedTx` | The signed transaction to be broadcasted                     |
| `params.dstChain` | `string`   | The destination chain for the transaction - 'C', 'P', or 'X' |

#### Returns

`Promise`<`IssueTxResponse`>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`AvalancheTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name           | Type     | Description                                                       |
| -------------- | -------- | ----------------------------------------------------------------- |
| `params`       | `Object` | Parameters for the transaction status request                     |
| `params.txId`  | `string` | The transaction hash to query                                     |
| `params.chain` | `string` | The chain to query the transaction status from - 'C', 'P', or 'X' |

#### Returns

`Promise`<`AvalancheTxStatus`>

A promise that resolves to an object containing the transaction status.


# CosmosStaker

This class provides the functionality to stake, unstake, redelegate, and withdraw rewards for Cosmos-based blockchains.

It also provides the ability to retrieve staking information and rewards for a delegator.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildRedelegateTx](#buildredelegatetx)
* [buildWithdrawRewardsTx](#buildwithdrawrewardstx)
* [getStake](#getstake)
* [getUnbondingStake](#getunbondingstake)
* [getBalance](#getbalance)
* [getRewards](#getrewards)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new CosmosStaker**(`params`): [`CosmosStaker`](/api-reference/stakers/cosmos_src.cosmosstaker)

This creates a new CosmosStaker instance.

#### Parameters

| Name                     | Type                 | Description                                                                                                                                      |
| ------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `params`                 | `Object`             | Initialization parameters                                                                                                                        |
| `params.rpcUrl`          | `string`             | RPC URL (e.g. <https://celestia.chorus.one:443>) Please note that `:port` is required                                                            |
| `params.lcdUrl`          | `string`             | LCD URL (e.g. <https://celestia-lcd.chorus.one:443>) Please note that `:port` is required                                                        |
| `params.bechPrefix`      | `string`             | Address prefix (e.g. celestia)                                                                                                                   |
| `params.denom`           | `string`             | Coin denom (e.g `utia`)                                                                                                                          |
| `params.denomMultiplier` | `string`             | Multiplier to convert the base coin unit to its smallest subunit (e.g., `1000000` for 1 TIA = 1000000 utia)                                      |
| `params.gas`             | `number` \| `"auto"` | Default TX gas (e.g 200000). If set to "auto", the gas will be automatically estimated via RPC node.                                             |
| `params.gasPrice`        | `string`             | Gas price (e.g "0.4") See: [Chain registry - Celestia](https://github.com/cosmos/chain-registry/blob/master/celestia/chain.json)                 |
| `params.extraGas?`       | `number`             | (Optional) Additional "buffer" gas to be added to the gas limit (sometimes the gas estimation is not accurate, so this is a way to add a buffer) |
| `params.fee?`            | `string`             | (Optional) Override with a fixed fee (e.g "5000" for "5000 uatom" or "0.005 ATOM")                                                               |
| `params.isEVM?`          | `boolean`            | (Optional) Use different address derivation logic for EVM compatible chains (e.g. evmos, zetachain)                                              |

#### Returns

[`CosmosStaker`](/api-reference/stakers/cosmos_src.cosmosstaker)

An instance of CosmosStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(`params`): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                | Type      | Description                                                                                         |
| ------------------- | --------- | --------------------------------------------------------------------------------------------------- |
| `params`            | `Object`  | Parameters for the address derivation                                                               |
| `params.bechPrefix` | `string`  | Address prefix (e.g. celestia)                                                                      |
| `params.isEVM?`     | `boolean` | (Optional) Use different address derivation logic for EVM compatible chains (e.g. evmos, zetachain) |

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the CosmosStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the CosmosStaker instance has been initialized.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `EncodeObject` }>

Builds a staking (delegation) transaction.

#### Parameters

| Name                      | Type     | Description                                                                                                     |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                                                                         |
| `params.delegatorAddress` | `string` | The delegator (wallet) address to stake from                                                                    |
| `params.validatorAddress` | `string` | The validator address to stake to                                                                               |
| `params.amount`           | `string` | The amount to stake, specified in base units of the native token (e.g. `ATOM` for Cosmos or `TIA` for Celestia) |

#### Returns

`Promise`<{ `tx`: `EncodeObject` }>

Returns a promise that resolves to a Cosmos staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `EncodeObject` }>

Builds an unstaking (undelegate) transaction.

#### Parameters

| Name                      | Type     | Description                                                                                                       |
| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                                                                           |
| `params.delegatorAddress` | `string` | The delegator (wallet) address that is unstaking                                                                  |
| `params.validatorAddress` | `string` | The validator address to unstake from                                                                             |
| `params.amount`           | `string` | The amount to unstake, specified in base units of the native token (e.g. `ATOM` for Cosmos or `TIA` for Celestia) |

#### Returns

`Promise`<{ `tx`: `EncodeObject` }>

Returns a promise that resolves to a Cosmos unstaking transaction.

***

### buildRedelegateTx

▸ **buildRedelegateTx**(`params`): `Promise`<{ `tx`: `EncodeObject` }>

Builds a redelegation transaction.

* This allows a wallet to redelegate staked assets to a different validator without unstaking.

#### Parameters

| Name                         | Type     | Description                                                                                                          |
| ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| `params`                     | `Object` | Parameters for building the transaction                                                                              |
| `params.delegatorAddress`    | `string` | The delegator (wallet) address                                                                                       |
| `params.validatorSrcAddress` | `string` | The source validator address to redelegate from                                                                      |
| `params.validatorDstAddress` | `string` | The destination validator address to redelgate to                                                                    |
| `params.amount`              | `string` | The amount to redelegate, specified in base units of the native token (e.g. `ATOM` for Cosmos or `TIA` for Celestia) |

#### Returns

`Promise`<{ `tx`: `EncodeObject` }>

Returns a promise that resolves to a Cosmos redelegation transaction.

***

### buildWithdrawRewardsTx

▸ **buildWithdrawRewardsTx**(`params`): `Promise`<{ `tx`: `EncodeObject` }>

Builds a withdraw (claim) rewards transaction.

#### Parameters

| Name                      | Type     | Description                                            |
| ------------------------- | -------- | ------------------------------------------------------ |
| `params`                  | `Object` | Parameters for building the transaction                |
| `params.delegatorAddress` | `string` | The delegator (wallet) address                         |
| `params.validatorAddress` | `string` | The validator address to withdraw (claim) rewards from |

#### Returns

`Promise`<{ `tx`: `EncodeObject` }>

Returns a promise that resolves to a Cosmos withdraw (claim) rewards transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staked balance for a specified delegator.

#### Parameters

| Name                       | Type     | Description                                                         |
| -------------------------- | -------- | ------------------------------------------------------------------- |
| `params`                   | `Object` | Parameters for the request                                          |
| `params.delegatorAddress`  | `string` | The delegator (wallet) address                                      |
| `params.validatorAddress?` | `string` | (Optional) The validator address to gather staking information from |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### getUnbondingStake

▸ **getUnbondingStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the unbonding balance for a specified delegator.

#### Parameters

| Name                       | Type     | Description                                                         |
| -------------------------- | -------- | ------------------------------------------------------------------- |
| `params`                   | `Object` | Parameters for the request                                          |
| `params.delegatorAddress`  | `string` | The delegator (wallet) address                                      |
| `params.validatorAddress?` | `string` | (Optional) The validator address to gather staking information from |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the unbonding information for the specified delegator.

***

### getBalance

▸ **getBalance**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the delegator's available balance.

#### Parameters

| Name                      | Type     | Description                    |
| ------------------------- | -------- | ------------------------------ |
| `params`                  | `Object` | Parameters for the request     |
| `params.delegatorAddress` | `string` | The delegator (wallet) address |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the available balance for the specified delegator.

***

### getRewards

▸ **getRewards**(`params`): `Promise`<{ `rewards`: `string` }>

Retrieves the rewards data for a specified delegator.

#### Parameters

| Name                       | Type     | Description                                                                            |
| -------------------------- | -------- | -------------------------------------------------------------------------------------- |
| `params`                   | `Object` | Parameters for the request                                                             |
| `params.delegatorAddress`  | `string` | The delegator (wallet) address                                                         |
| `params.validatorAddress?` | `string` | The validator address to gather rewards data from                                      |
| `params.denom?`            | `string` | (Optional) The rewards coin denominator (default is the network denom)                 |
| `params.denomMultiplier?`  | `string` | (Optional) The rewards coin denom multiplier (default is the network denom multiplier) |

#### Returns

`Promise`<{ `rewards`: `string` }>

Returns a promise that resolves to the rewards data for the specified delegator.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `Uint8Array` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type           | Description                                      |
| ---------------------- | -------------- | ------------------------------------------------ |
| `params`               | `Object`       | Parameters for the signing process               |
| `params.signer`        | `Signer`       | Signer instance                                  |
| `params.signerAddress` | `string`       | The address of the signer                        |
| `params.tx`            | `EncodeObject` | The transaction to sign                          |
| `params.memo?`         | `string`       | An optional memo to include with the transaction |

#### Returns

`Promise`<{ `signedTx`: `Uint8Array` }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`DeliverTxResponse`>

This method is used to broadcast a signed transaction to the Cosmos network.

#### Parameters

| Name              | Type         | Description                              |
| ----------------- | ------------ | ---------------------------------------- |
| `params`          | `Object`     | Parameters for the broadcast             |
| `params.signedTx` | `Uint8Array` | The signed transaction to be broadcasted |

#### Returns

`Promise`<`DeliverTxResponse`>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`CosmosTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type     | Description                                   |
| --------------- | -------- | --------------------------------------------- |
| `params`        | `Object` | Parameters for the transaction status request |
| `params.txHash` | `string` | The transaction hash to query                 |

#### Returns

`Promise`<`CosmosTxStatus`>

A promise that resolves to an object containing the transaction status.


# EthereumStaker

This class provides the functionality to stake, unstake, and withdraw for Ethereum network.

It also provides the ability to retrieve staking information and rewards for an account.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildWithdrawTx](#buildwithdrawtx)
* [buildMintTx](#buildminttx)
* [buildBurnTx](#buildburntx)
* [getVault](#getvault)
* [getStake](#getstake)
* [getRewardsHistory](#getrewardshistory)
* [getTxHistory](#gettxhistory)
* [getUnstakeQueue](#getunstakequeue)
* [getMint](#getmint)
* [getMintHealth](#getminthealth)
* [createValidatorBatch](#createvalidatorbatch)
* [listValidatorBatches](#listvalidatorbatches)
* [getValidatorBatchStatus](#getvalidatorbatchstatus)
* [exportDepositData](#exportdepositdata)
* [buildDepositTx](#builddeposittx)
* [buildValidatorExitTx](#buildvalidatorexittx)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new EthereumStaker**(`params`): [`EthereumStaker`](/api-reference/stakers/ethereum_src.ethereumstaker)

Creates an EthereumStaker instance.

#### Parameters

| Name                            | Type       | Description                                                                                               |
| ------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------- |
| `params`                        | `Object`   | Initialization configuration                                                                              |
| `params.network`                | `Networks` | The network to connect to                                                                                 |
| `params.rpcUrl?`                | `string`   | (Optional) The URL of the RPC endpoint. If not provided, the public RPC URL for the network will be used. |
| `params.nativeStakingApiToken?` | `string`   | (Optional) API token for native staking operations. Required for native staking methods.                  |

#### Returns

[`EthereumStaker`](/api-reference/stakers/ethereum_src.ethereumstaker)

An instance of EthereumStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`): `Promise`<`string`\[]>

**Parameters**

| Name        | Type         |
| ----------- | ------------ |
| `publicKey` | `Uint8Array` |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the EthereumStaker instance and connects to the Ethereum network.

#### Returns

`Promise`<`void`>

A promise which resolves once the EthereumStaker instance has been initialized.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds a staking transaction.

#### Parameters

| Name                      | Type            | Description                                                                                                                                                                                                                                    |
| ------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                                                                                                                                                                        |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address to stake from                                                                                                                                                                                                   |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to stake with                                                                                                                                                                                                    |
| `params.amount`           | `string`        | The amount to stake, specified in `ETH`. E.g. "1" - 1 ETH                                                                                                                                                                                      |
| `params.referrer?`        | \`0x${string}\` | (Optional) The address of the referrer. This is used to track the origin of transactions, providing insights into which sources or campaigns are driving activity. This can be useful for analytics and optimizing user acquisition strategies |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to an Ethereum staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds an unstaking transaction.

The unstake transaction effectively moves the user's assets into an unstake queue where they remain until they become eligible for withdrawal. This queue is a safeguard mechanism that ensures the liquidity and stability of the vault by managing the flow of assets. To check the status of these assets, use the `getUnstakeQueue` method.

#### Parameters

| Name                      | Type            | Description                                                 |
| ------------------------- | --------------- | ----------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                     |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address that is unstaking            |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to unstake from               |
| `params.amount`           | `string`        | The amount to unstake, specified in `ETH`. E.g. "1" - 1 ETH |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to an Ethereum unstaking transaction.

***

### buildWithdrawTx

▸ **buildWithdrawTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds a withdrawal transaction.

This method is the final step in the unstaking process. Once assets in the unstake queue have reached a withdrawable state (as determined by the `getUnstakeQueue` method), the `buildWithdrawTx` method prepares the transaction data necessary for transferring these assets back into the user's wallet.

#### Parameters

| Name                      | Type            | Description                                                                                                                              |
| ------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                                                                  |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                                                                                           |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to withdraw from                                                                                           |
| `params.positionTickets?` | `string`\[]     | (Optional) An array of position tickets to withdraw. If not provided, all withdrawable assets will be withdrawn. (see `getUnstakeQueue`) |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to an Ethereum withdrawal transaction.

***

### buildMintTx

▸ **buildMintTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds a mint transaction.

#### Parameters

| Name                      | Type            | Description                                                                                                                                                                                                                                    |
| ------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                                                                                                                                                                        |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                                                                                                                                                                                                 |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to mint shares for                                                                                                                                                                                               |
| `params.amount`           | `string`        | The amount to mint, specified in `osETH`. E.g. "1" - 1 osETH                                                                                                                                                                                   |
| `params.referrer?`        | \`0x${string}\` | (Optional) The address of the referrer. This is used to track the origin of transactions, providing insights into which sources or campaigns are driving activity. This can be useful for analytics and optimizing user acquisition strategies |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to an Ethereum mint transaction.

***

### buildBurnTx

▸ **buildBurnTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds a burn transaction.

#### Parameters

| Name                      | Type            | Description                                                  |
| ------------------------- | --------------- | ------------------------------------------------------------ |
| `params`                  | `Object`        | Parameters for building the transaction                      |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                               |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to burn shares from            |
| `params.amount`           | `string`        | The amount to burn, specified in `osETH`. E.g. "1" - 1 osETH |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to an Ethereum burn transaction.

***

### getVault

▸ **getVault**(`params`): `Promise`<{ `vault`: [`Vault`](/api-reference/types/ethereum/ethereum_src.vault) }>

Retrieves the staking information for a specified vault, including TVL, APY, description, logo.

#### Parameters

| Name                      | Type            | Description                   |
| ------------------------- | --------------- | ----------------------------- |
| `params`                  | `Object`        | Parameters for the request    |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address |

#### Returns

`Promise`<{ `vault`: [`Vault`](/api-reference/types/ethereum/ethereum_src.vault) }>

Returns a promise that resolves to the staking information for the specified vault.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` ; `maxUnstake`: `string` }>

Retrieves the staking information for a specified delegator.

The staking information includes the current balance and the maximum amount that can be unstaked.

#### Parameters

| Name                      | Type            | Description                                                      |
| ------------------------- | --------------- | ---------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for the request                                       |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                   |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to gather staking information from |

#### Returns

`Promise`<{ `balance`: `string` ; `maxUnstake`: `string` }>

Returns a promise that resolves to the staking information for the delegator.

***

### getRewardsHistory

▸ **getRewardsHistory**(`params`): `Promise`<{ `timestamp`: `number` = item.timestamp; `amount`: `string` ; `totalRewards`: `string` ; `dailyRewards`: `string` }\[]>

Retrieves the rewards history for a specified delegator.

#### Parameters

| Name                      | Type            | Description                                                               |
| ------------------------- | --------------- | ------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for the request                                                |
| `params.startTime`        | `number`        | The start time of the rewards data to retrieve, specified in milliseconds |
| `params.endTime`          | `number`        | The end time of the rewards data to retrieve, specified in milliseconds   |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                            |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to gather rewards data from                 |

#### Returns

`Promise`<{ `timestamp`: `number` = item.timestamp; `amount`: `string` ; `totalRewards`: `string` ; `dailyRewards`: `string` }\[]>

Returns a promise that resolves to the rewards data for the specified delegator.

***

### getTxHistory

▸ **getTxHistory**(`params`): `Promise`<{ `timestamp`: `number` ; `type`: `VaultActionType` = item.type; `amount`: `string` ; `txHash`: `string` }\[]>

Retrieves the transaction history for a specified delegator.

#### Parameters

| Name                      | Type            | Description                                                   |
| ------------------------- | --------------- | ------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for the request                                    |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to gather transaction data from |

#### Returns

`Promise`<{ `timestamp`: `number` ; `type`: `VaultActionType` = item.type; `amount`: `string` ; `txHash`: `string` }\[]>

Returns a promise that resolves to the transaction history for the specified delegator.

***

### getUnstakeQueue

▸ **getUnstakeQueue**(`params`): `Promise`<{ `positionTicket`: `string` ; `exitQueueIndex`: `string` ; `timestamp`: `number` = item.timestamp; `isWithdrawable`: `boolean` = item.isWithdrawable; `totalAmount`: `string` ; `withdrawableAmount`: `string` ; `withdrawalTimestamp`: `number` = item.withdrawalTimestamp }\[]>

Retrieves the unstake queue for a specified delegator.

After initiating an unstake request using the `buildUnstakeTx` method, assets are placed into an unstake queue.

The `getUnstakeQueue` method allows users to query the queue to check the current state of their unstake requests, including their positionTicket, the amount of assets that are withdrawable, and the total amount.

To prepare the transaction for withdrawing these assets, use the `buildWithdrawTx` method.

#### Parameters

| Name                      | Type            | Description                                                    |
| ------------------------- | --------------- | -------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for the request                                     |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                                 |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to gather the unstake queue from |

#### Returns

`Promise`<{ `positionTicket`: `string` ; `exitQueueIndex`: `string` ; `timestamp`: `number` = item.timestamp; `isWithdrawable`: `boolean` = item.isWithdrawable; `totalAmount`: `string` ; `withdrawableAmount`: `string` ; `withdrawalTimestamp`: `number` = item.withdrawalTimestamp }\[]>

Returns a promise that resolves to the unstake queue for the specified delegator.

***

### getMint

▸ **getMint**(`params`): `Promise`<{ `balance`: `string` ; `maxMint`: `string` }>

Retrieves the mint information for a specified delegator.

The mint information includes the current balance of minted `osETH` and the maximum amount of that can be minted.

#### Parameters

| Name                      | Type            | Description                                            |
| ------------------------- | --------------- | ------------------------------------------------------ |
| `params`                  | `Object`        | Parameters for the request                             |
| `params.delegatorAddress` | \`0x${string}\` | The delegator (wallet) address                         |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address to gather mint data from |

#### Returns

`Promise`<{ `balance`: `string` ; `maxMint`: `string` }>

Returns a promise that resolves to the mint information

***

### getMintHealth

▸ **getMintHealth**(`params`): `Promise`<{ `health`: `"healthy"` | `"risky"` }>

Retrieves the mint health for a specified stake and mint amount.

Position health tracks the value of osETH minted by stakers relative to the value of their ETH stake in the vault. Healthy positions have minted osETH that is well-collateralized by staked ETH. As the proportion of minted osETH increases relative to staked ETH, position health deteriorates.

Factors affecting position health include yield discrepancies (APY) between the vault and osETH, which can result from:

* Differences in fee structures.
* Variations in attestation performance.
* The ratio of unbounded ETH to the vault's total value locked (TVL).
* Delays in validator activation on the Beacon Chain.
* Losses due to maximal extractable value (MEV) strategies.

Risky positions may enter redemption processes, while positions deemed unhealthy are subject to liquidation.

#### Parameters

| Name                      | Type            | Description                   |
| ------------------------- | --------------- | ----------------------------- |
| `params`                  | `Object`        | Parameters for the request    |
| `params.stakeAmount`      | `string`        | The amount of ETH staked      |
| `params.mintAmount`       | `string`        | The amount of osETH minted    |
| `params.validatorAddress` | \`0x${string}\` | The validator (vault) address |

#### Returns

`Promise`<{ `health`: `"healthy"` | `"risky"` }>

Returns a promise that resolves to the mint health status('healthy' | 'risky' )

***

### createValidatorBatch

▸ **createValidatorBatch**(`params`): `Promise`<`CreateBatchResponse`>

Creates a batch of validators for native Ethereum staking.

This method creates a new batch of validators using the Chorus One Native Staking API. Each validator requires 32 ETH to be deposited. The batch will generate deposit data that can be used to deposit validators on the Ethereum network.

#### Parameters

| Name                              | Type            | Description                                                                                                                |
| --------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `params`                          | `Object`        | Parameters for creating the validator batch                                                                                |
| `params.batchId`                  | `string`        | Unique identifier for the batch                                                                                            |
| `params.withdrawalAddress`        | \`0x${string}\` | The withdrawal address that will control the staked funds.Must be 0x02 compounding credentials for compounding validators. |
| `params.feeRecipientAddress`      | \`0x${string}\` | The address that will receive MEV rewards                                                                                  |
| `params.numberOfValidators`       | `number`        | Number of validators to create (each requires 32 ETH)                                                                      |
| `params.isCompounding?`           | `boolean`       | (Optional) Whether to create compounding validators (0x02 withdrawal credentials). Default is false.                       |
| `params.depositGweiPerValidator?` | `bigint`        | (Optional) The deposit in gwei per validator. Default is 32000000000 gwei i.e. 32ETH.                                      |

#### Returns

`Promise`<`CreateBatchResponse`>

Returns a promise that resolves to the batch creation response.

***

### listValidatorBatches

▸ **listValidatorBatches**(): `Promise`<`ListBatchesResponse`>

Lists all validator batches for the authenticated tenant.

This method retrieves all validator batches that have been created for the current tenant.

#### Returns

`Promise`<`ListBatchesResponse`>

Returns a promise that resolves to an array of validator batches.

***

### getValidatorBatchStatus

▸ **getValidatorBatchStatus**(`params`): `Promise`<`BatchDetailsResponse`>

Gets the status of a validator batch.

This method retrieves the current status of a validator batch, including the deposit data for each validator when ready.

#### Parameters

| Name             | Type     | Description                         |
| ---------------- | -------- | ----------------------------------- |
| `params`         | `Object` | Parameters for getting batch status |
| `params.batchId` | `string` | The batch identifier                |

#### Returns

`Promise`<`BatchDetailsResponse`>

Returns a promise that resolves to the batch information.

***

### exportDepositData

▸ **exportDepositData**(`params`): `Promise`<{ `depositData`: `BatchDetailsDepositData`\[] }>

Exports deposit data in the format required by the Ethereum Staking Launchpad.

This method the deposit data for each validator in the batch, which can be used to deposit validators with the oficial Ethereum Staking Launchpad or other depositing tools.

#### Parameters

| Name               | Type                   | Description                           |
| ------------------ | ---------------------- | ------------------------------------- |
| `params`           | `Object`               | Parameters for exporting deposit data |
| `params.batchData` | `BatchDetailsResponse` | Pre-fetched batch of validators       |

#### Returns

`Promise`<{ `depositData`: `BatchDetailsDepositData`\[] }>

Returns a promise that resolves to an array of deposit data objects.

***

### buildDepositTx

▸ **buildDepositTx**(`params`): `Promise`<{ `transactions`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction)\[] }>

Builds deposit transactions for native Ethereum staking.

This method creates transactions for depositing validators to the Ethereum deposit contract. Each validator requires exactly 32 ETH to be deposited along with the deposit data.

#### Parameters

| Name               | Type                   | Description                                  |
| ------------------ | ---------------------- | -------------------------------------------- |
| `params`           | `Object`               | Parameters for building deposit transactions |
| `params.batchData` | `BatchDetailsResponse` | Pre-fetched batch of validators              |

#### Returns

`Promise`<{ `transactions`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction)\[] }>

Returns a promise that resolves to an array of deposit transactions.

***

### buildValidatorExitTx

▸ **buildValidatorExitTx**(`params`): `Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Builds a withdrawal request transaction for a validator based on EIP-7002.

This method creates a transaction that triggers a full validator exit through the execution layer withdrawal credentials (0x01) as specified in EIP-7002.

#### Parameters

| Name                     | Type     | Description                                                                  |
| ------------------------ | -------- | ---------------------------------------------------------------------------- |
| `params`                 | `Object` | Parameters for building the withdrawal transaction                           |
| `params.validatorPubkey` | `string` | The validator public key (48 bytes)                                          |
| `params.value?`          | `bigint` | (Optional) The amount of ETH to send with the transaction. Default is 1 wei. |

#### Returns

`Promise`<{ `tx`: [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) }>

Returns a promise that resolves to a withdrawal transaction.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: \`0x${string}\` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                         | Type                                                                    | Description                                                                                                                                                                                             |
| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                     | `Object`                                                                | Parameters for the signing process                                                                                                                                                                      |
| `params.signer`              | `Signer`                                                                | A signer instance.                                                                                                                                                                                      |
| `params.signerAddress`       | \`0x${string}\`                                                         | The address of the signer                                                                                                                                                                               |
| `params.tx`                  | [`Transaction`](/api-reference/types/ethereum/ethereum_src.transaction) | The transaction to sign                                                                                                                                                                                 |
| `params.baseFeeMultiplier?`  | `number`                                                                | (Optional) The multiplier for fees, which is used to manage fee fluctuations, is applied to the base fee per gas from the latest block to determine the final `maxFeePerGas`. The default value is 1.2. |
| `params.defaultPriorityFee?` | `string`                                                                | (Optional) This overrides the the `maxPriorityFeePerGas` estimated by the RPC.                                                                                                                          |

#### Returns

`Promise`<{ `signedTx`: \`0x${string}\` }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: \`0x${string}\` }>

Broadcasts a signed transaction to the network.

#### Parameters

| Name              | Type            | Description                          |
| ----------------- | --------------- | ------------------------------------ |
| `params`          | `Object`        | Parameters for the broadcast process |
| `params.signedTx` | \`0x${string}\` | The signed transaction to broadcast  |

#### Returns

`Promise`<{ `txHash`: \`0x${string}\` }>

A promise that resolves to the final execution outcome of the broadcast transaction.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`EthereumTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type            | Description                                   |
| --------------- | --------------- | --------------------------------------------- |
| `params`        | `Object`        | Parameters for the transaction status request |
| `params.txHash` | \`0x${string}\` | The transaction hash to query                 |

#### Returns

`Promise`<`EthereumTxStatus`>

A promise that resolves to an object containing the transaction status.


# HyperliquidStaker

HyperliquidStaker - TypeScript SDK for Hyperliquid staking operations

This class provides the functionality to stake, delegate, and manage staking on Hyperliquid. It uses the Hyperliquid REST API for both read and write operations, with EIP-712 signing for transactions.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [getStakingSummary](#getstakingsummary)
* [getDelegations](#getdelegations)
* [getDelegatorRewards](#getdelegatorrewards)
* [getDelegatorHistory](#getdelegatorhistory)
* [getSpotBalances](#getspotbalances)
* [buildSpotToStakingTx](#buildspottostakingtx)
* [buildWithdrawFromStakingTx](#buildwithdrawfromstakingtx)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [sign](#sign)
* [broadcast](#broadcast)

## Constructors

### constructor

• **new HyperliquidStaker**(`«destructured»`): [`HyperliquidStaker`](/api-reference/stakers/hyperliquid_src.hyperliquidstaker)

Creates a HyperliquidStaker instance.

chain - The Hyperliquid chain to use ('Mainnet' or 'Testnet')

#### Parameters

| Name             | Type               |
| ---------------- | ------------------ |
| `«destructured»` | `Object`           |
| › `chain`        | `HyperliquidChain` |

#### Returns

[`HyperliquidStaker`](/api-reference/stakers/hyperliquid_src.hyperliquidstaker)

An instance of HyperliquidStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address with '0x' prefix.

▸ (`publicKey`): `Promise`<`string`\[]>

**Parameters**

| Name        | Type         |
| ----------- | ------------ |
| `publicKey` | `Uint8Array` |

**Returns**

`Promise`<`string`\[]>

***

### getStakingSummary

▸ **getStakingSummary**(`params`): `Promise`<{ `delegated?`: `string` ; `undelegated?`: `string` ; `totalPendingWithdrawal?`: `string` ; `nPendingWithdrawals?`: `number` }>

Gets the staking summary for a delegator.

#### Parameters

| Name                      | Type     | Description             |
| ------------------------- | -------- | ----------------------- |
| `params`                  | `Object` | Query parameters        |
| `params.delegatorAddress` | `string` | The delegator's address |

#### Returns

`Promise`<{ `delegated?`: `string` ; `undelegated?`: `string` ; `totalPendingWithdrawal?`: `string` ; `nPendingWithdrawals?`: `number` }>

A promise that resolves to the delegator's staking summary, including delegated and undelegated amounts

***

### getDelegations

▸ **getDelegations**(`params`): `Promise`<{ `amount?`: `string` ; `validator?`: `string` ; `lockedUntilTimestamp?`: `number` }\[]>

Gets all active delegations for a delegator.

#### Parameters

| Name                      | Type     | Description             |
| ------------------------- | -------- | ----------------------- |
| `params`                  | `Object` | Query parameters        |
| `params.delegatorAddress` | `string` | The delegator's address |

#### Returns

`Promise`<{ `amount?`: `string` ; `validator?`: `string` ; `lockedUntilTimestamp?`: `number` }\[]>

A promise that resolves to an array of active delegations

***

### getDelegatorRewards

▸ **getDelegatorRewards**(`params`): `Promise`<{ `totalAmount?`: `string` ; `source?`: `"delegation"` | `"commission"` ; `time?`: `number` }\[]>

Gets the staking rewards history for a delegator.

#### Parameters

| Name                      | Type     | Description             |
| ------------------------- | -------- | ----------------------- |
| `params`                  | `Object` | Query parameters        |
| `params.delegatorAddress` | `string` | The delegator's address |

#### Returns

`Promise`<{ `totalAmount?`: `string` ; `source?`: `"delegation"` | `"commission"` ; `time?`: `number` }\[]>

A promise that resolves to an array of staking rewards

***

### getDelegatorHistory

▸ **getDelegatorHistory**(`params`): `Promise`<{ `hash?`: `string` ; `time?`: `number` ; `delta?`: { `delegate?`: { `amount?`: `string` ; `validator?`: `string` ; `isUndelegate?`: `boolean` } } | { `cDeposit?`: { `amount?`: `string` } } | { `withdrawal?`: { `amount?`: `string` ; `phase?`: `string` } } }\[]>

Gets the delegation history for a delegator.

#### Parameters

| Name                      | Type     | Description             |
| ------------------------- | -------- | ----------------------- |
| `params`                  | `Object` | Query parameters        |
| `params.delegatorAddress` | `string` | The delegator's address |

#### Returns

`Promise`<{ `hash?`: `string` ; `time?`: `number` ; `delta?`: { `delegate?`: { `amount?`: `string` ; `validator?`: `string` ; `isUndelegate?`: `boolean` } } | { `cDeposit?`: { `amount?`: `string` } } | { `withdrawal?`: { `amount?`: `string` ; `phase?`: `string` } } }\[]>

A promise that resolves to an array of delegation history events

***

### getSpotBalances

▸ **getSpotBalances**(`params`): `Promise`<{ `balances`: { `total?`: `string` ; `coin?`: `string` ; `token?`: `number` ; `hold?`: `string` ; `entryNtl?`: `string` }\[] }>

Gets the spot account balances for a user.

#### Parameters

| Name                      | Type     | Description        |
| ------------------------- | -------- | ------------------ |
| `params`                  | `Object` | Query parameters   |
| `params.delegatorAddress` | `string` | The user's address |

#### Returns

`Promise`<{ `balances`: { `total?`: `string` ; `coin?`: `string` ; `token?`: `number` ; `hold?`: `string` ; `entryNtl?`: `string` }\[] }>

A promise that resolves to an array of spot balances for different assets(e.g. HYPE, USDC)

***

### buildSpotToStakingTx

▸ **buildSpotToStakingTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to move tokens from spot account to staking balance.

#### Parameters

| Name            | Type     | Description                             |
| --------------- | -------- | --------------------------------------- |
| `params`        | `Object` | Transaction parameters                  |
| `params.amount` | `string` | Amount to deposit in HYPE (e.g., "1.5") |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a DepositToStakingAction

***

### buildWithdrawFromStakingTx

▸ **buildWithdrawFromStakingTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to withdraw tokens from staking balance to spot account. Note: Withdrawals go through a 7-day unstaking queue.

#### Parameters

| Name            | Type     | Description                                |
| --------------- | -------- | ------------------------------------------ |
| `params`        | `Object` | Transaction parameters                     |
| `params.amount` | `string` | Amount to withdraw in tokens (e.g., "1.5") |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a WithdrawFromStakingAction

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to delegate tokens to a validator. Note: Delegations have a 1-day lockup period per validator.

#### Parameters

| Name                      | Type            | Description                                                                                 |
| ------------------------- | --------------- | ------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Transaction parameters                                                                      |
| `params.validatorAddress` | \`0x${string}\` | Address in 42-character hexadecimal format; e.g. 0x0000000000000000000000000000000000000000 |
| `params.amount`           | `string`        | Amount to delegate in HYPE (e.g., "1.5")                                                    |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a DelegateAction

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to undelegate tokens from a validator. Note: Undelegations have a 1-day lockup period.

#### Parameters

| Name                      | Type            | Description                                                                                 |
| ------------------------- | --------------- | ------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Transaction parameters                                                                      |
| `params.validatorAddress` | \`0x${string}\` | Address in 42-character hexadecimal format; e.g. 0x0000000000000000000000000000000000000000 |
| `params.amount`           | `string`        | Amount to undelegate in HYPE (e.g., "1.5")                                                  |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a DelegateAction

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `string` }>

Signs a transaction using EIP-712 structured data signing.

#### Parameters

| Name                   | Type         | Description               |
| ---------------------- | ------------ | ------------------------- |
| `params`               | `Object`     | Signing parameters        |
| `params.signer`        | `Signer`     | The signer instance       |
| `params.signerAddress` | `string`     | The address of the signer |
| `params.tx`            | `UnsignedTx` | The unsigned transaction  |

#### Returns

`Promise`<{ `signedTx`: `string` }>

A promise that resolves to the signed transaction

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: `string` }>

Broadcasts a signed transaction to the Hyperliquid network.

Uses a request queue to ensure transactions are sent sequentially, preventing network-level race conditions that could cause out-of-order nonce errors.

#### Parameters

| Name                      | Type            | Description                          |
| ------------------------- | --------------- | ------------------------------------ |
| `params`                  | `Object`        | Broadcasting parameters              |
| `params.signedTx`         | `string`        | The signed transaction (JSON string) |
| `params.delegatorAddress` | \`0x${string}\` | -                                    |

#### Returns

`Promise`<{ `txHash`: `string` }>

A promise that resolves to the transaction hash


# MonadStaker

MonadStaker - TypeScript SDK for Monad blockchain staking operations

This class provides the functionality to stake, unstake, compound rewards, claim rewards, and withdraw for Monad blockchain.

Built with viem for type-safety and modern patterns.

***

**⚠️ EIP-2930 Access List Compatibility Warning**

All transaction builders include an EIP-2930 access list for referrer tracking by default. Some wallets (e.g., Phantom) do not support EIP-2930 access lists and will fail during gas estimation with `InvalidInputRpcError` or `InvalidParamsRpcError`.

If you need to support these wallets, implement a fallback that retries without the access list:

**`Example`**

```typescript
import { BaseError, InvalidInputRpcError, InvalidParamsRpcError } from 'viem'

const shouldRetryWithoutAccessList = (error: unknown): boolean => {
  const matches = (err: unknown) =>
    err instanceof InvalidInputRpcError || err instanceof InvalidParamsRpcError
  if (error instanceof BaseError) {
    return Boolean(error.walk(matches))
  }
  return false
}

const sendTransaction = async (tx: Transaction) => {
  try {
    return await walletClient.sendTransaction(tx)
  } catch (err) {
    if (tx.accessList && shouldRetryWithoutAccessList(err)) {
      const { accessList: _omit, ...fallbackTx } = tx
      return await walletClient.sendTransaction(fallbackTx)
    }
    throw err
  }
}
```

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildWithdrawTx](#buildwithdrawtx)
* [buildCompoundTx](#buildcompoundtx)
* [buildClaimRewardsTx](#buildclaimrewardstx)
* [getDelegator](#getdelegator)
* [getWithdrawalRequest](#getwithdrawalrequest)
* [getEpoch](#getepoch)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new MonadStaker**(`params`): [`MonadStaker`](/api-reference/stakers/monad_src.monadstaker)

Creates a MonadStaker instance

#### Parameters

| Name            | Type     | Description                               |
| --------------- | -------- | ----------------------------------------- |
| `params`        | `Object` | Initialization configuration              |
| `params.rpcUrl` | `string` | The URL of the Monad network RPC endpoint |

#### Returns

[`MonadStaker`](/api-reference/stakers/monad_src.monadstaker)

An instance of MonadStaker

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`): `Promise`<`string`\[]>

**Parameters**

| Name        | Type         |
| ----------- | ------------ |
| `publicKey` | `Uint8Array` |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the MonadStaker instance and connects to the blockchain

#### Returns

`Promise`<`void`>

A promise which resolves once the MonadStaker instance has been initialized

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a staking transaction

Stake becomes active in epoch n+1 (if before boundary block) or epoch n+2 (if after).

#### Parameters

| Name                 | Type            | Description                                                                                           |
| -------------------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| `params`             | `Object`        | Parameters for building the transaction                                                               |
| `params.validatorId` | `number`        | Unique identifier (uint64) for the validator. Assigned when validator joined the network.             |
| `params.amount`      | `string`        | The amount to stake in MON (will be converted to wei internally)                                      |
| `params.referrer?`   | \`0x${string}\` | (Optional) Custom 32-byte hex string for tracking. If not provided, uses default Chorus One encoding. |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a Monad staking transaction

**`Remarks`**

The returned transaction includes an EIP-2930 access list for referrer tracking. Some wallets (e.g., Phantom) do not support this. See the class documentation for a fallback pattern.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds an unstaking transaction

Creates a withdrawal request to unstake tokens from a validator. Stake becomes inactive in epoch n+1 or n+2, then moves to pending state for WITHDRAWAL\_DELAY epochs (1 epoch). After delay, call buildWithdrawTx() to claim funds back to your wallet.

#### Parameters

| Name                      | Type            | Description                                                                                                                                                               |
| ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                                                                                                   |
| `params.delegatorAddress` | \`0x${string}\` | The delegator's address that will receive funds after withdrawal                                                                                                          |
| `params.validatorId`      | `number`        | Unique identifier for the validator to unstake from                                                                                                                       |
| `params.amount`           | `string`        | The amount to unstake in MON (will be converted to wei internally)                                                                                                        |
| `params.withdrawalId`     | `number`        | User-chosen ID (0-255) to track this withdrawal request. Allows up to 256 concurrent withdrawals per (validator,delegator) tuple. Can be reused after calling withdraw(). |
| `params.referrer?`        | \`0x${string}\` | (Optional) Custom 32-byte hex string for tracking. If not provided, uses default Chorus One encoding.                                                                     |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a Monad unstaking transaction

***

### buildWithdrawTx

▸ **buildWithdrawTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a withdraw transaction

Completes an unstaking by claiming the tokens back to your wallet. Can only be executed once current epoch >= withdrawEpoch (check via getWithdrawalRequest).

#### Parameters

| Name                      | Type            | Description                                                                                                                 |
| ------------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                                                     |
| `params.delegatorAddress` | \`0x${string}\` | The delegator's address that will receive the funds                                                                         |
| `params.validatorId`      | `number`        | Unique identifier for the validator you unstaked from                                                                       |
| `params.withdrawalId`     | `number`        | The same ID (0-255) you used when calling buildUnstakeTx. After successful withdrawal, this ID becomes available for reuse. |
| `params.referrer?`        | \`0x${string}\` | (Optional) Custom 32-byte hex string for tracking. If not provided, uses default Chorus One encoding.                       |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a Monad withdrawal transaction

***

### buildCompoundTx

▸ **buildCompoundTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a compound rewards transaction

Converts accumulated unclaimedRewards into additional stake (auto-restaking). The compounded amount becomes active in epoch n+1 or n+2 (same timing as staking).

#### Parameters

| Name                      | Type            | Description                                                                                           |
| ------------------------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                               |
| `params.delegatorAddress` | \`0x${string}\` | The delegator's address                                                                               |
| `params.validatorId`      | `number`        | Unique identifier for the validator to compound rewards for                                           |
| `params.referrer?`        | \`0x${string}\` | (Optional) Custom 32-byte hex string for tracking. If not provided, uses default Chorus One encoding. |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a Monad compound transaction

***

### buildClaimRewardsTx

▸ **buildClaimRewardsTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a claim rewards transaction

Claims accumulated unclaimedRewards and sends them to your wallet (not auto-restaked like compound). Rewards are available immediately after the transaction.

#### Parameters

| Name                      | Type            | Description                                                                                           |
| ------------------------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for building the transaction                                                               |
| `params.delegatorAddress` | \`0x${string}\` | The delegator's address that will receive the rewards                                                 |
| `params.validatorId`      | `number`        | Unique identifier for the validator to claim rewards from                                             |
| `params.referrer?`        | \`0x${string}\` | (Optional) Custom 32-byte hex string for tracking. If not provided, uses default Chorus One encoding. |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a Monad claim rewards transaction

***

### getDelegator

▸ **getDelegator**(`params`): `Promise`<`DelegatorInfo`>

Retrieves delegator information for a specific validator

#### Parameters

| Name                      | Type            | Description                                |
| ------------------------- | --------------- | ------------------------------------------ |
| `params`                  | `Object`        | Parameters for the query                   |
| `params.validatorId`      | `number`        | Unique identifier for the validator        |
| `params.delegatorAddress` | \`0x${string}\` | Ethereum address of the delegator to query |

#### Returns

`Promise`<`DelegatorInfo`>

Promise resolving to delegator information including:

* stake: Currently active stake earning rewards right now (in wei). Does NOT include pending activations.
* accRewardPerToken: Last checked accumulator value (internal accounting, multiplied by 1e36)
* unclaimedRewards: Rewards earned but not yet claimed or compounded (in wei)
* deltaStake: Pending stake activating at deltaEpoch (submitted before boundary block, in wei)
* nextDeltaStake: Pending stake activating at nextDeltaEpoch (submitted after boundary block, in wei)
* deltaEpoch: Epoch number when deltaStake becomes active
* nextDeltaEpoch: Epoch number when nextDeltaStake becomes active

Note: Two pending slots exist because stakes before boundary block activate in epoch n+1 (deltaStake), while stakes after boundary block activate in epoch n+2 (nextDeltaStake).

***

### getWithdrawalRequest

▸ **getWithdrawalRequest**(`params`): `Promise`<`WithdrawalRequestInfo`>

Retrieves withdrawal request information

Use this to check if your unstaked tokens are ready to withdraw.

#### Parameters

| Name                      | Type            | Description                                             |
| ------------------------- | --------------- | ------------------------------------------------------- |
| `params`                  | `Object`        | Parameters for the query                                |
| `params.validatorId`      | `number`        | Unique identifier for the validator you unstaked from   |
| `params.delegatorAddress` | \`0x${string}\` | Address that initiated the unstaking                    |
| `params.withdrawalId`     | `number`        | The ID (0-255) you assigned when calling buildUnstakeTx |

#### Returns

`Promise`<`WithdrawalRequestInfo`>

Promise resolving to withdrawal information:

* withdrawalAmount: Amount in wei that will be returned when you call withdraw (0 if no request exists)
* accRewardPerToken: Validator's accumulator value when unstaking was initiated (used for reward calculations)
* withdrawEpoch: Epoch number when funds become withdrawable. Compare with current epoch from getEpoch() to check if ready.

To check if withdrawable: currentEpoch >= withdrawEpoch (get currentEpoch via getEpoch())

***

### getEpoch

▸ **getEpoch**(): `Promise`<`EpochInfo`>

Retrieves current epoch information

#### Returns

`Promise`<`EpochInfo`>

Promise resolving to epoch timing information:

* epoch: Current consensus epoch number. An epoch is \~5.5 hours on mainnet (50,000 blocks) during which the validator set remains unchanged.
* inEpochDelayPeriod: Boolean indicating if we're past the "boundary block" (the last 10% of blocks in an epoch). false = stake changes activate in epoch n+1 true = stake changes activate in epoch n+2

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: \`0x${string}\` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                         | Type            | Description                                                                                                                                                                                            |
| ---------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `params`                     | `Object`        | Parameters for the signing process                                                                                                                                                                     |
| `params.signer`              | `Signer`        | A signer instance                                                                                                                                                                                      |
| `params.signerAddress`       | \`0x${string}\` | The address of the signer                                                                                                                                                                              |
| `params.tx`                  | `Transaction`   | The transaction to sign                                                                                                                                                                                |
| `params.baseFeeMultiplier?`  | `number`        | (Optional) The multiplier for fees, which is used to manage fee fluctuations, is applied to the base fee per gas from the latest block to determine the final `maxFeePerGas`. The default value is 1.2 |
| `params.defaultPriorityFee?` | `string`        | (Optional) This overrides the `maxPriorityFeePerGas` estimated by the RPC                                                                                                                              |

#### Returns

`Promise`<{ `signedTx`: \`0x${string}\` }>

A promise that resolves to an object containing the signed transaction

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: \`0x${string}\` }>

Broadcasts a signed transaction to the network.

#### Parameters

| Name              | Type            | Description                          |
| ----------------- | --------------- | ------------------------------------ |
| `params`          | `Object`        | Parameters for the broadcast process |
| `params.signedTx` | \`0x${string}\` | The signed transaction to broadcast  |

#### Returns

`Promise`<{ `txHash`: \`0x${string}\` }>

A promise that resolves to the transaction hash

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`MonadTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type            | Description                                   |
| --------------- | --------------- | --------------------------------------------- |
| `params`        | `Object`        | Parameters for the transaction status request |
| `params.txHash` | \`0x${string}\` | The transaction hash to query                 |

#### Returns

`Promise`<`MonadTxStatus`>

A promise that resolves to an object containing the transaction status


# NearStaker

This class provides the functionality to stake, unstake, and withdraw for NEAR-based blockchains.

It also provides the ability to retrieve staking information for an account.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildWithdrawTx](#buildwithdrawtx)
* [getStake](#getstake)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new NearStaker**(`params`): [`NearStaker`](/api-reference/stakers/near_src.nearstaker)

Creates a NearStaker instance.

#### Parameters

| Name                      | Type      | Description                                                                                                                                                                  |
| ------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                  | `Object`  | Initialization configuration                                                                                                                                                 |
| `params.networkId`        | `string`  | The network ID of the NEAR network (e.g., `mainnet`, `testnet`)                                                                                                              |
| `params.rpcUrl`           | `string`  | The URL of the NEAR network RPC endpoint                                                                                                                                     |
| `params.denomMultiplier?` | `string`  | Multiplier to convert the base coin unit to its smallest subunit (e.g., `10^24` for 1 NEAR = 1000000000000000000000000 yoctoNear)                                            |
| `params.resolveAddress?`  | `boolean` | Converts human-readable NEAR account ID (e.g. `alice.near`) to public key. Enable this option if signer requires the public key but you only expect names from NEAR registry |
| `params.gas?`             | `string`  | Amount of gas to be sent with the function calls (e.g "30000000000000" yoctoNear)                                                                                            |

#### Returns

[`NearStaker`](/api-reference/stakers/near_src.nearstaker)

An instance of NearStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the NearStaker instance and connects to the Near network.

#### Returns

`Promise`<`void`>

A promise which resolves once the NearStaker instance has been initialized.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a staking transaction.

#### Parameters

| Name                      | Type     | Description                                  |
| ------------------------- | -------- | -------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction      |
| `params.delegatorAddress` | `string` | The delegator (wallet) address to stake from |
| `params.validatorAddress` | `string` | The validator address to stake with          |
| `params.amount`           | `string` | The amount to stake, specified in `NEAR`     |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a NEAR staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds an unstaking transaction.

#### Parameters

| Name                      | Type     | Description                                      |
| ------------------------- | -------- | ------------------------------------------------ |
| `params`                  | `Object` | Parameters for building the transaction          |
| `params.delegatorAddress` | `string` | The delegator (wallet) address that is unstaking |
| `params.validatorAddress` | `string` | The validator address to unstake from            |
| `params.amount`           | `string` | The amount to unstake, specified in `NEAR`       |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a NEAR unstaking transaction.

***

### buildWithdrawTx

▸ **buildWithdrawTx**(`params`): `Promise`<{ `tx`: `Transaction` }>

Builds a withdrawal transaction.

**The amount to be withdrawn must be previously unstaked.**

* If the amount is not specified, all the available unstaked amount will be withdrawn.

#### Parameters

| Name                      | Type     | Description                                 |
| ------------------------- | -------- | ------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction     |
| `params.delegatorAddress` | `string` | The delegator (wallet) address              |
| `params.validatorAddress` | `string` | The validator address to withdraw from      |
| `params.amount`           | `string` | The amount to withdraw, specified in `NEAR` |

#### Returns

`Promise`<{ `tx`: `Transaction` }>

Returns a promise that resolves to a NEAR withdrawal transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                       | Type     | Description                                                         |
| -------------------------- | -------- | ------------------------------------------------------------------- |
| `params`                   | `Object` | Parameters for the request                                          |
| `params.delegatorAddress`  | `string` | The delegator (wallet) address                                      |
| `params.validatorAddress?` | `string` | (Optional) The validator address to gather staking information from |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `SignedTransaction` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type          | Description                        |
| ---------------------- | ------------- | ---------------------------------- |
| `params`               | `Object`      | Parameters for the signing process |
| `params.signer`        | `Signer`      | A signer instance.                 |
| `params.signerAddress` | `string`      | The address of the signer          |
| `params.tx`            | `Transaction` | The transaction to sign            |

#### Returns

`Promise`<{ `signedTx`: `SignedTransaction` }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`FinalExecutionOutcome`>

Broadcasts a signed transaction to the network.

#### Parameters

| Name              | Type                | Description                          |
| ----------------- | ------------------- | ------------------------------------ |
| `params`          | `Object`            | Parameters for the broadcast process |
| `params.signedTx` | `SignedTransaction` | The signed transaction to broadcast  |

#### Returns

`Promise`<`FinalExecutionOutcome`>

A promise that resolves to the final execution outcome of the broadcast transaction.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`NearTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name             | Type     | Description                                   |
| ---------------- | -------- | --------------------------------------------- |
| `params`         | `Object` | Parameters for the transaction status request |
| `params.txHash`  | `string` | The transaction hash to query                 |
| `params.address` | `string` | The NEAR account that signed the transaction  |

#### Returns

`Promise`<`NearTxStatus`>

A promise that resolves to an object containing the transaction status.


# PolygonStaker

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildApproveTx](#buildapprovetx)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildWithdrawTx](#buildwithdrawtx)
* [buildClaimRewardsTx](#buildclaimrewardstx)
* [buildCompoundTx](#buildcompoundtx)
* [getStake](#getstake)
* [getUnbondNonce](#getunbondnonce)
* [getUnbond](#getunbond)
* [getUnbonds](#getunbonds)
* [getLiquidRewards](#getliquidrewards)
* [getAllowance](#getallowance)
* [getEpoch](#getepoch)
* [getWithdrawalDelay](#getwithdrawaldelay)
* [getExchangeRatePrecision](#getexchangerateprecision)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new PolygonStaker**(`params`): [`PolygonStaker`](/api-reference/stakers/polygon_src.polygonstaker)

Creates a PolygonStaker instance

#### Parameters

| Name     | Type                                                                                                                                     | Description                  |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `params` | [`PolygonNetworkConfig`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.PolygonNetworkConfig.md) | Initialization configuration |

#### Returns

[`PolygonStaker`](/api-reference/stakers/polygon_src.polygonstaker)

An instance of PolygonStaker

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`): `Promise`<`string`\[]>

**Parameters**

| Name        | Type         |
| ----------- | ------------ |
| `publicKey` | `Uint8Array` |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

#### Returns

`Promise`<`void`>

**`Deprecated`**

No longer required. Kept for backward compatibility.

***

### buildApproveTx

▸ **buildApproveTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds a token approval transaction

Approves the StakeManager contract to spend POL tokens on behalf of the delegator. This must be called before staking if the current allowance is insufficient.

#### Parameters

| Name            | Type     | Description                                                                                            |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `params`        | `Object` | Parameters for building the transaction                                                                |
| `params.amount` | `string` | The amount to approve in POL (will be converted to wei internally). Pass "max" for unlimited approval. |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to an approval transaction

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds a staking (delegation) transaction

Delegates POL tokens to a validator via their ValidatorShare contract. Requires prior token approval to the StakeManager contract.

#### Parameters

| Name                           | Type            | Description                                                                                                                                                                         |
| ------------------------------ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                       | `Object`        | Parameters for building the transaction                                                                                                                                             |
| `params.delegatorAddress`      | \`0x${string}\` | The delegator's Ethereum address                                                                                                                                                    |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address                                                                                                                                     |
| `params.amount`                | `string`        | The amount to stake in POL                                                                                                                                                          |
| `params.slippageBps?`          | `number`        | Slippage tolerance in basis points (e.g., 50 = 0.5%). Used to calculate minSharesToMint. Exactly one of `slippageBps` or `minSharesToMint` must be provided (not both, no default). |
| `params.minSharesToMint?`      | `bigint`        | Minimum validator shares to receive. Exactly one of `slippageBps` or `minSharesToMint` must be provided (not both, no default).                                                     |
| `params.referrer?`             | `string`        | (Optional) Custom referrer string for tracking. If not provided, uses 'sdk-chorusone-staking'.                                                                                      |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to a Polygon staking transaction

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds an unstaking transaction

Creates an unbond request to unstake POL tokens from a validator. After the unbonding period (\~80 checkpoints, approximately 3-4 days), call buildWithdrawTx() to claim funds.

#### Parameters

| Name                           | Type            | Description                                                                                                                                                                                 |
| ------------------------------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                       | `Object`        | Parameters for building the transaction                                                                                                                                                     |
| `params.delegatorAddress`      | \`0x${string}\` | The delegator's address                                                                                                                                                                     |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address                                                                                                                                             |
| `params.amount`                | `string`        | The amount to unstake in POL (will be converted to wei internally)                                                                                                                          |
| `params.slippageBps?`          | `number`        | Slippage tolerance in basis points (e.g., 50 = 0.5%). Used to calculate maximumSharesToBurn. Exactly one of `slippageBps` or `maximumSharesToBurn` must be provided (not both, no default). |
| `params.maximumSharesToBurn?`  | `bigint`        | Maximum validator shares willing to burn. Exactly one of `slippageBps` or `maximumSharesToBurn` must be provided (not both, no default).                                                    |
| `params.referrer?`             | `string`        | (Optional) Custom referrer string for tracking. If not provided, uses 'sdk-chorusone-staking'.                                                                                              |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to a Polygon unstaking transaction

***

### buildWithdrawTx

▸ **buildWithdrawTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds a withdraw transaction

Claims unstaked POL tokens after the unbonding period has elapsed. Use getUnbond() to check if the unbonding period is complete.

Note: Each unstake creates a separate unbond with its own nonce (1, 2, 3, etc.). Withdrawals must be done per-nonce. To withdraw all pending unbonds, iterate through nonces from 1 to getUnbondNonce() and withdraw each eligible one.

#### Parameters

| Name                           | Type            | Description                                         |
| ------------------------------ | --------------- | --------------------------------------------------- |
| `params`                       | `Object`        | Parameters for building the transaction             |
| `params.delegatorAddress`      | \`0x${string}\` | The delegator's address that will receive the funds |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address     |
| `params.unbondNonce`           | `bigint`        | The specific unbond nonce to withdraw               |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to a Polygon withdrawal transaction

***

### buildClaimRewardsTx

▸ **buildClaimRewardsTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds a claim rewards transaction

Claims accumulated delegation rewards and sends them to the delegator's wallet.

#### Parameters

| Name                           | Type            | Description                                                                                    |
| ------------------------------ | --------------- | ---------------------------------------------------------------------------------------------- |
| `params`                       | `Object`        | Parameters for building the transaction                                                        |
| `params.delegatorAddress`      | \`0x${string}\` | The delegator's address that will receive the rewards                                          |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address                                                |
| `params.referrer?`             | `string`        | (Optional) Custom referrer string for tracking. If not provided, uses 'sdk-chorusone-staking'. |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to a Polygon claim rewards transaction

***

### buildCompoundTx

▸ **buildCompoundTx**(`params`): `Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Builds a compound (restake) rewards transaction

Restakes accumulated rewards back into the validator, increasing delegation without new tokens.

#### Parameters

| Name                           | Type            | Description                                                                                    |
| ------------------------------ | --------------- | ---------------------------------------------------------------------------------------------- |
| `params`                       | `Object`        | Parameters for building the transaction                                                        |
| `params.delegatorAddress`      | \`0x${string}\` | The delegator's address                                                                        |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address                                                |
| `params.referrer?`             | `string`        | (Optional) Custom referrer string for tracking. If not provided, uses 'sdk-chorusone-staking'. |

#### Returns

`Promise`<{ `tx`: [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) }>

Returns a promise that resolves to a Polygon compound transaction

***

### getStake

▸ **getStake**(`params`): `Promise`<[`StakeInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.StakeInfo.md)>

Retrieves the delegator's staking information for a specific validator

#### Parameters

| Name                           | Type            | Description                                     |
| ------------------------------ | --------------- | ----------------------------------------------- |
| `params`                       | `Object`        | Parameters for the query                        |
| `params.delegatorAddress`      | \`0x${string}\` | Ethereum address of the delegator               |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address |

#### Returns

`Promise`<[`StakeInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.StakeInfo.md)>

Promise resolving to stake information:

* balance: Total staked amount formatted in POL
* shares: Total shares held by the delegator
* exchangeRate: Current exchange rate between shares and POL

***

### getUnbondNonce

▸ **getUnbondNonce**(`params`): `Promise`<`bigint`>

Retrieves the latest unbond nonce for a delegator

Each unstake operation creates a new unbond request with an incrementing nonce. Nonces start at 1 and increment with each unstake. Note: a nonce having existed does not mean it is still pending — claimed unbonds are deleted, but the counter is never decremented.

#### Parameters

| Name                           | Type            | Description                                     |
| ------------------------------ | --------------- | ----------------------------------------------- |
| `params`                       | `Object`        | Parameters for the query                        |
| `params.delegatorAddress`      | \`0x${string}\` | Ethereum address of the delegator               |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address |

#### Returns

`Promise`<`bigint`>

Promise resolving to the latest unbond nonce (0n if no unstakes performed)

***

### getUnbond

▸ **getUnbond**(`params`): `Promise`<[`UnbondInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.UnbondInfo.md)>

Retrieves unbond request information for a specific nonce

Use this to check the status of individual unbond requests. For fetching multiple unbonds efficiently, use getUnbonds() instead.

#### Parameters

| Name                           | Type            | Description                                        |
| ------------------------------ | --------------- | -------------------------------------------------- |
| `params`                       | `Object`        | Parameters for the query                           |
| `params.delegatorAddress`      | \`0x${string}\` | Ethereum address of the delegator                  |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address    |
| `params.unbondNonce`           | `bigint`        | The specific unbond nonce to query (1, 2, 3, etc.) |

#### Returns

`Promise`<[`UnbondInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.UnbondInfo.md)>

Promise resolving to unbond information:

* amount: Amount pending unbonding in POL
* isWithdrawable: Whether the unbond can be withdrawn now
* shares: Shares amount pending unbonding (0n if already withdrawn or doesn't exist)
* withdrawEpoch: Epoch number when the unbond started

***

### getUnbonds

▸ **getUnbonds**(`params`): `Promise`<[`UnbondInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.UnbondInfo.md)\[]>

Retrieves unbond request information for multiple nonces efficiently

This method batches all contract reads into a single RPC call, making it much more efficient than calling getUnbond() multiple times.

#### Parameters

| Name                           | Type            | Description                                     |
| ------------------------------ | --------------- | ----------------------------------------------- |
| `params`                       | `Object`        | Parameters for the query                        |
| `params.delegatorAddress`      | \`0x${string}\` | Ethereum address of the delegator               |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address |
| `params.unbondNonces`          | `bigint`\[]     | Array of unbond nonces to query (1, 2, 3, etc.) |

#### Returns

`Promise`<[`UnbondInfo`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.UnbondInfo.md)\[]>

Promise resolving to array of unbond information (same order as input nonces)

***

### getLiquidRewards

▸ **getLiquidRewards**(`params`): `Promise`<`string`>

Retrieves pending liquid rewards for a delegator

#### Parameters

| Name                           | Type            | Description                                     |
| ------------------------------ | --------------- | ----------------------------------------------- |
| `params`                       | `Object`        | Parameters for the query                        |
| `params.delegatorAddress`      | \`0x${string}\` | Ethereum address of the delegator               |
| `params.validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address |

#### Returns

`Promise`<`string`>

Promise resolving to the pending rewards in POL

***

### getAllowance

▸ **getAllowance**(`ownerAddress`): `Promise`<`string`>

Retrieves the current POL allowance for the StakeManager contract

#### Parameters

| Name           | Type            | Description               |
| -------------- | --------------- | ------------------------- |
| `ownerAddress` | \`0x${string}\` | The token owner's address |

#### Returns

`Promise`<`string`>

Promise resolving to the current allowance in POL

***

### getEpoch

▸ **getEpoch**(): `Promise`<`bigint`>

Retrieves the current checkpoint epoch from the StakeManager

#### Returns

`Promise`<`bigint`>

Promise resolving to the current epoch number

***

### getWithdrawalDelay

▸ **getWithdrawalDelay**(): `Promise`<`bigint`>

Retrieves the withdrawal delay from the StakeManager

The withdrawal delay is the number of epochs that must pass after an unbond request before the funds can be withdrawn (\~80 checkpoints, approximately 3-4 days).

#### Returns

`Promise`<`bigint`>

Promise resolving to the withdrawal delay in epochs

***

### getExchangeRatePrecision

▸ **getExchangeRatePrecision**(`validatorShareAddress`): `Promise`<`bigint`>

Retrieves the exchange rate precision for a validator

Foundation validators (ID < 8) use precision of 100, others use 10^29.

#### Parameters

| Name                    | Type            | Description                                     |
| ----------------------- | --------------- | ----------------------------------------------- |
| `validatorShareAddress` | \`0x${string}\` | The validator's ValidatorShare contract address |

#### Returns

`Promise`<`bigint`>

Promise resolving to the precision constant

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: \`0x${string}\` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                         | Type                                                                                                                   | Description                                                                                                                                                                                            |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `params`                     | `Object`                                                                                                               | Parameters for the signing process                                                                                                                                                                     |
| `params.signer`              | `Signer`                                                                                                               | A signer instance                                                                                                                                                                                      |
| `params.signerAddress`       | \`0x${string}\`                                                                                                        | The address of the signer                                                                                                                                                                              |
| `params.tx`                  | [`Transaction`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.Transaction.md) | The transaction to sign                                                                                                                                                                                |
| `params.baseFeeMultiplier?`  | `number`                                                                                                               | (Optional) The multiplier for fees, which is used to manage fee fluctuations, is applied to the base fee per gas from the latest block to determine the final `maxFeePerGas`. The default value is 1.2 |
| `params.defaultPriorityFee?` | `string`                                                                                                               | (Optional) This overrides the `maxPriorityFeePerGas` estimated by the RPC                                                                                                                              |

#### Returns

`Promise`<{ `signedTx`: \`0x${string}\` }>

A promise that resolves to an object containing the signed transaction

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: \`0x${string}\` }>

Broadcasts a signed transaction to the network.

#### Parameters

| Name              | Type            | Description                          |
| ----------------- | --------------- | ------------------------------------ |
| `params`          | `Object`        | Parameters for the broadcast process |
| `params.signedTx` | \`0x${string}\` | The signed transaction to broadcast  |

#### Returns

`Promise`<{ `txHash`: \`0x${string}\` }>

A promise that resolves to the transaction hash

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<[`PolygonTxStatus`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.PolygonTxStatus.md)>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type            | Description                                   |
| --------------- | --------------- | --------------------------------------------- |
| `params`        | `Object`        | Parameters for the transaction status request |
| `params.txHash` | \`0x${string}\` | The transaction hash to query                 |

#### Returns

`Promise`<[`PolygonTxStatus`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/polygon_src.PolygonTxStatus.md)>

A promise that resolves to an object containing the transaction status


# SolanaStaker

This class provides the functionality to stake, unstake, and withdraw for Solana blockchains.

It also provides the ability to retrieve staking information and rewards for an account.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [buildCreateStakeAccountTx](#buildcreatestakeaccounttx)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [buildPartialUnstakeTx](#buildpartialunstaketx)
* [buildWithdrawStakeTx](#buildwithdrawstaketx)
* [buildMergeStakesTx](#buildmergestakestx)
* [buildSplitStakeTx](#buildsplitstaketx)
* [getStake](#getstake)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)
* [getStakeAccounts](#getstakeaccounts)

## Constructors

### constructor

• **new SolanaStaker**(`params`): [`SolanaStaker`](/api-reference/stakers/solana_src.solanastaker)

Creates a SolanaStaker instance.

#### Parameters

| Name                 | Type         | Description                                                                                      |
| -------------------- | ------------ | ------------------------------------------------------------------------------------------------ |
| `params`             | `Object`     | Initialization configuration                                                                     |
| `params.rpcUrl`      | `string`     | The URL of the SOLANA network RPC endpoint                                                       |
| `params.commitment?` | `Commitment` | (Optional) The level of commitment desired when querying the blockchain. Default is 'confirmed'. |

#### Returns

[`SolanaStaker`](/api-reference/stakers/solana_src.solanastaker)

An instance of SolanaStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the SolanaStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the SolanaStaker instance has been initialized.

***

### buildCreateStakeAccountTx

▸ **buildCreateStakeAccountTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Builds a new stake account transaction.

#### Parameters

| Name                  | Type     | Description                             |
| --------------------- | -------- | --------------------------------------- |
| `params`              | `Object` | Parameters for building the transaction |
| `params.ownerAddress` | `string` | The stake account owner's address       |
| `params.amount`       | `string` | The amount to stake, specified in `SOL` |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Returns a promise that resolves to new stake account transaction.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Builds a staking transaction.

#### Parameters

| Name                          | Type     | Description                                                                                                    |
| ----------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `params`                      | `Object` | Parameters for building the transaction                                                                        |
| `params.ownerAddress`         | `string` | The stake account owner's address                                                                              |
| `params.validatorAddress`     | `string` | The validatiors vote account address to delegate the stake to                                                  |
| `params.stakeAccountAddress?` | `string` | The stake account address to delegate from. If not provided, a new stake account will be created.              |
| `params.amount?`              | `string` | The amount to stake, specified in `SOL`. If `stakeAccountAddress` is not provided, this parameter is required. |
| `params.referrer?`            | `string` | (Optional) A custom tracking reference. If not provided, the default tracking reference will be used.          |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Returns a promise that resolves to a SOLANA staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` }>

Builds an unstaking transaction.

#### Parameters

| Name                         | Type     | Description                                                                                           |
| ---------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `params`                     | `Object` | Parameters for building the transaction                                                               |
| `params.ownerAddress`        | `string` | The stake account owner's address                                                                     |
| `params.stakeAccountAddress` | `string` | The stake account address to deactivate                                                               |
| `params.referrer?`           | `string` | (Optional) A custom tracking reference. If not provided, the default tracking reference will be used. |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` }>

Returns a promise that resolves to a SOLANA unstaking transaction.

***

### buildPartialUnstakeTx

▸ **buildPartialUnstakeTx**(`params`): `Promise`<{ `transactions`: `SolanaTransaction`\[] ; `accounts`: `StakeAccount`\[] }>

Builds a partial unstake transaction.

This method allows for unstaking a specific amount from multiple stake accounts. It will split the stake accounts if necessary to achieve the desired unstake amount.

#### Parameters

| Name                  | Type     | Description                                                                                           |
| --------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `params`              | `Object` | Parameters for building the transaction                                                               |
| `params.ownerAddress` | `string` | The stake account owner's address                                                                     |
| `params.amount`       | `string` | The amount to unstake, specified in `SOL`                                                             |
| `params.referrer?`    | `string` | (Optional) A custom tracking reference. If not provided, the default tracking reference will be used. |

#### Returns

`Promise`<{ `transactions`: `SolanaTransaction`\[] ; `accounts`: `StakeAccount`\[] }>

Returns a promise that resolves to an array of SOLANA transactions for partial unstaking and the affected stake accounts.

***

### buildWithdrawStakeTx

▸ **buildWithdrawStakeTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` }>

Builds a withdraw stake transaction.

#### Parameters

| Name                         | Type     | Description                                                                                             |
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `params`                     | `Object` | Parameters for building the transaction                                                                 |
| `params.ownerAddress`        | `string` | The stake account owner's address                                                                       |
| `params.stakeAccountAddress` | `string` | The stake account address to withdraw funds from                                                        |
| `params.amount?`             | `string` | The amount to withdraw, specified in `SOL`. If not provided, the entire stake amount will be withdrawn. |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` }>

Returns a promise that resolves to a SOLANA withdraw stake transaction.

***

### buildMergeStakesTx

▸ **buildMergeStakesTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` }>

Builds a merge stake transaction.

Please note there are conditions for merging stake accounts: <https://docs.solana.com/staking/stake-accounts#merging-stake-accounts>

#### Parameters

| Name                        | Type     | Description                                   |
| --------------------------- | -------- | --------------------------------------------- |
| `params`                    | `Object` | Parameters for building the transaction       |
| `params.ownerAddress`       | `string` | The stake account owner's address             |
| `params.sourceAddress`      | `string` | The stake account address to merge funds from |
| `params.destinationAddress` | `string` | The stake account address to merge funds to   |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` }>

Returns a promise that resolves to a SOLANA merge stake transaction.

***

### buildSplitStakeTx

▸ **buildSplitStakeTx**(`params`): `Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Builds a split stake transaction.

#### Parameters

| Name                         | Type     | Description                                                                                |
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `params`                     | `Object` | Parameters for building the transaction                                                    |
| `params.ownerAddress`        | `string` | The stake account owner's address                                                          |
| `params.stakeAccountAddress` | `string` | The stake account address to split funds from                                              |
| `params.amount`              | `string` | The amount to transfer from stakeAccountAddress to new staking account, specified in `SOL` |

#### Returns

`Promise`<{ `tx`: `SolanaTransaction` ; `stakeAccountAddress`: `string` }>

Returns a promise that resolves to a SOLANA split stake transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                       | Type                                                            | Description                                                            |
| -------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `params`                   | `Object`                                                        | Parameters for the request                                             |
| `params.ownerAddress`      | `string`                                                        | The stake account owner's address                                      |
| `params.validatorAddress?` | `string`                                                        | (Optional) The validator address to gather staking information from    |
| `params.state?`            | `"delegated"` \| `"undelegated"` \| `"deactivating"` \| `"all"` | (Optional) The stake account state to filter by (default: 'delegated') |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `VersionedTransaction` }>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type                | Description                        |
| ---------------------- | ------------------- | ---------------------------------- |
| `params`               | `Object`            | Parameters for the signing process |
| `params.signer`        | `Signer`            | A signer instance.                 |
| `params.signerAddress` | `string`            | The address of the signer          |
| `params.tx`            | `SolanaTransaction` | The transaction to sign            |

#### Returns

`Promise`<{ `signedTx`: `VersionedTransaction` }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: `string` ; `slot`: `number` ; `error`: `any` }>

Broadcasts a signed transaction to the network.

#### Parameters

| Name              | Type                   | Description                          |
| ----------------- | ---------------------- | ------------------------------------ |
| `params`          | `Object`               | Parameters for the broadcast process |
| `params.signedTx` | `VersionedTransaction` | The signed transaction to broadcast  |

#### Returns

`Promise`<{ `txHash`: `string` ; `slot`: `number` ; `error`: `any` }>

A promise that resolves to the final execution outcome of the broadcast transaction.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`SolanaTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type     | Description                                   |
| --------------- | -------- | --------------------------------------------- |
| `params`        | `Object` | Parameters for the transaction status request |
| `params.txHash` | `string` | The transaction hash to query                 |

#### Returns

`Promise`<`SolanaTxStatus`>

A promise that resolves to an object containing the transaction status.

***

### getStakeAccounts

▸ **getStakeAccounts**(`params`): `Promise`<{ `accounts`: `StakeAccount`\[] }>

Retrieves the stake accounts associated with an owner address.

#### Parameters

| Name                       | Type      | Description                                                                          |
| -------------------------- | --------- | ------------------------------------------------------------------------------------ |
| `params`                   | `Object`  | Parameters for the broadcast process                                                 |
| `params.ownerAddress`      | `string`  | The stake account owner's address                                                    |
| `params.validatorAddress?` | `string`  | (Optional) The validator address to filter the stake accounts by                     |
| `params.withStates?`       | `boolean` | (Optional) If true, the state of the stake account will be included in the response  |
| `params.withMacroDenom?`   | `boolean` | (Optional) If true, the stake account balance will be returned in `SOL` denomination |

#### Returns

`Promise`<{ `accounts`: `StakeAccount`\[] }>

A promise that resolves to stake account list.


# SubstrateStaker

This class provides the functionality to stake, nominate, unbond, and withdraw funds for a Substrate-based blockchains.

It also provides the ability to retrieve staking information and rewards for a delegator.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [init](#init)
* [close](#close)
* [buildStakeTx](#buildstaketx)
* [buildNominateTx](#buildnominatetx)
* [buildUnstakeTx](#buildunstaketx)
* [buildWithdrawTx](#buildwithdrawtx)
* [buildBondExtraTx](#buildbondextratx)
* [getStake](#getstake)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new SubstrateStaker**(`params`): [`SubstrateStaker`](/api-reference/stakers/substrate_src.substratestaker)

This creates a new SubstrateStaker instance.

#### Parameters

| Name                       | Type                                                                                                             | Description                                                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `params`                   | `Object`                                                                                                         | Initialization parameters                                                                                                            |
| `params.rpcUrl`            | `string`                                                                                                         | RPC URL (e.g. wss\://rpc.polkadot.io)                                                                                                |
| `params.rewardDestination` | [`RewardDestination`](/api-reference/types/polkadot-substrate/substrate_src.rewarddestination)                   | Reward destination (e.g., RewardDestination.STASH or RewardDestination.CONTROLLER)                                                   |
| `params.denomMultiplier?`  | `string`                                                                                                         | (Optional) Multiplier to convert the base coin unit to its smallest subunit (e.g., `1000000000000` for 1 DOT = 1000000000000 Planck) |
| `params.fee?`              | `SubstrateFee`                                                                                                   | (Optional) Transaction fee (e.g. '0.001' for 0.001 DOT)                                                                              |
| `params.indexer?`          | [`Indexer`](https://github.com/ChorusOne/chorus-one-sdk/blob/main/book/docs/interfaces/substrate_src.Indexer.md) | (Optional) Indexer instance to supplement missing node RPC features                                                                  |

#### Returns

[`SubstrateStaker`](/api-reference/stakers/substrate_src.substratestaker)

An instance of SusbstrateStaker.

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Returns

`fn`

Returns an array containing the derived address.

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the SubstrateStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the Staker instance has been initialized.

***

### close

▸ **close**(): `Promise`<`void`>

Closes the SubstrateStaker instance and disconnects from the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the Staker instance has been closed.

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a staking (delegation) transaction.

#### Parameters

| Name            | Type     | Description                                                                                |
| --------------- | -------- | ------------------------------------------------------------------------------------------ |
| `params`        | `Object` | Parameters for building the transaction                                                    |
| `params.amount` | `string` | The amount to stake, specified in base units of the native token (e.g. `DOT` for Polkadot) |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Polkadot staking transaction.

***

### buildNominateTx

▸ **buildNominateTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a nomination transaction - allows the user to pick trusted validators to delegate to.

#### Parameters

| Name                        | Type        | Description                                    |
| --------------------------- | ----------- | ---------------------------------------------- |
| `params`                    | `Object`    | Parameters for building the transaction        |
| `params.validatorAddresses` | `string`\[] | The list of validator addresses to nominate to |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Substrate nomination transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds an unstaking (undelegation) transaction.

#### Parameters

| Name            | Type     | Description                                                                                  |
| --------------- | -------- | -------------------------------------------------------------------------------------------- |
| `params`        | `Object` | Parameters for building the transaction                                                      |
| `params.amount` | `string` | The amount to unstake, specified in base units of the native token (e.g. `DOT` for Polkadot) |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Substrate unstaking transaction.

***

### buildWithdrawTx

▸ **buildWithdrawTx**(): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to withdraw all unstaked funds from the validator contract.

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Substrate withdraw transaction.

***

### buildBondExtraTx

▸ **buildBondExtraTx**(`params`): `Promise`<{ `tx`: `UnsignedTx` }>

Builds a transaction to delegate more tokens to a validator.

#### Parameters

| Name            | Type     | Description                                                                                |
| --------------- | -------- | ------------------------------------------------------------------------------------------ |
| `params`        | `Object` | Parameters for building the transaction                                                    |
| `params.amount` | `string` | The amount to stake, specified in base units of the native token (e.g. `DOT` for Polkadot) |

#### Returns

`Promise`<{ `tx`: `UnsignedTx` }>

Returns a promise that resolves to a Substrate bond extra transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                       | Type                    | Description                                                              |
| -------------------------- | ----------------------- | ------------------------------------------------------------------------ |
| `params`                   | `Object`                | Parameters for the request                                               |
| `params.delegatorAddress`  | `string`                | The delegator (wallet) address                                           |
| `params.validatorAddress?` | `string`                | (Optional) The validator address to assert the delegator is staking with |
| `params.status?`           | `"active"` \| `"total"` | (Optional) The status of nomination (default: 'active')                  |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### sign

▸ **sign**(`params`): `Promise`<{ `signedTx`: `GenericExtrinsic`<`AnyTuple`> }>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type         | Description                                                   |
| ---------------------- | ------------ | ------------------------------------------------------------- |
| `params`               | `Object`     | Parameters for the signing process                            |
| `params.signer`        | `Signer`     | Signer instance                                               |
| `params.signerAddress` | `string`     | The address of the signer                                     |
| `params.tx`            | `UnsignedTx` | The transaction to sign                                       |
| `params.blocks?`       | `number`     | (Optional) The number of blocks until the transaction expires |

#### Returns

`Promise`<{ `signedTx`: `GenericExtrinsic`<`AnyTuple`> }>

A promise that resolves to an object containing the signed transaction.

***

### broadcast

▸ **broadcast**(`params`): `Promise`<{ `txHash`: `string` ; `status`: `ExtrinsicStatus` }>

This method is used to broadcast a signed transaction to the Substrate network.

#### Parameters

| Name              | Type                           | Description                              |
| ----------------- | ------------------------------ | ---------------------------------------- |
| `params`          | `Object`                       | Parameters for the broadcast             |
| `params.signedTx` | `GenericExtrinsic`<`AnyTuple`> | The signed transaction to be broadcasted |

#### Returns

`Promise`<{ `txHash`: `string` ; `status`: `ExtrinsicStatus` }>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`SubstrateTxStatus`>

Retrieves the status of a transaction using the transaction hash.

#### Parameters

| Name            | Type     | Description                                   |
| --------------- | -------- | --------------------------------------------- |
| `params`        | `Object` | Parameters for the transaction status request |
| `params.txHash` | `string` | The transaction hash to query                 |

#### Returns

`Promise`<`SubstrateTxStatus`>

A promise that resolves to an object containing the transaction status.


# TonPoolStaker

## Hierarchy

* `TonBaseStaker`

  ↳ **`TonPoolStaker`**

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [calculateUnstakePoolAmount](#calculateunstakepoolamount)
* [getAddressDerivationFn](#getaddressderivationfn)
* [getMnemonicToSeedFn](#getmnemonictoseedfn)
* [getSeedToKeypairFn](#getseedtokeypairfn)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [getStake](#getstake)
* [getPoolParams](#getpoolparams)
* [getTxStatus](#gettxstatus)
* [getElectionMinStake](#getelectionminstake)
* [getPoolStatus](#getpoolstatus)
* [getPastElections](#getpastelections)
* [init](#init)
* [buildDeployWalletTx](#builddeploywallettx)
* [sign](#sign)
* [broadcast](#broadcast)

## Constructors

### constructor

• **new TonPoolStaker**(`params`): [`TonPoolStaker`](/api-reference/stakers/ton_src.tonpoolstaker)

This creates a new TonStaker instance.

#### Parameters

| Name                                     | Type                                                                                  | Description                                                                      |
| ---------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `params`                                 | `Object`                                                                              | Initialization parameters                                                        |
| `params.rpcUrl`                          | `string`                                                                              | RPC URL (e.g. <https://toncenter.com/api/v2/jsonRPC>)                            |
| `params.allowSeamlessWalletDeployment?`  | `boolean`                                                                             | (Optional) If enabled, the wallet contract is deployed automatically when needed |
| `params.allowTransferToInactiveAccount?` | `boolean`                                                                             | (Optional) Allow token transfers to inactive accounts                            |
| `params.minimumExistentialBalance?`      | `string`                                                                              | (Optional) The amount of TON to keep in the wallet                               |
| `params.addressDerivationConfig?`        | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | (Optional) TON address derivation configuration                                  |

#### Returns

[`TonPoolStaker`](/api-reference/stakers/ton_src.tonpoolstaker)

An instance of TonStaker.

#### Inherited from

TonBaseStaker.constructor

## Methods

### calculateUnstakePoolAmount

▸ **calculateUnstakePoolAmount**(`amount`, `minElectionStake`, `«destructured»`, `«destructured»`, `«destructured»`, `«destructured»`): \[`bigint`, `bigint`]

Calculates optimal unstake amounts from two pools. Tries strategies in order: keep both active → keep one active → deactivate both

TODO: Add transaction simulation to catch false negatives thrown by SDK in case of bugs in calculation logic. Consider adding anonymous telemetry/logging.

TODO: Add `getValidUnstakeRanges()` method to help integrators validate amounts upfront by knowing the valid amounts to unstake.

#### Parameters

| Name               | Type                  |
| ------------------ | --------------------- |
| `amount`           | `bigint`              |
| `minElectionStake` | `bigint`              |
| `«destructured»`   | \[`bigint`, `bigint`] |
| `«destructured»`   | \[`bigint`, `bigint`] |
| `«destructured»`   | \[`bigint`, `bigint`] |
| `«destructured»`   | \[`bigint`, `bigint`] |

#### Returns

\[`bigint`, `bigint`]

***

### getAddressDerivationFn

▸ **getAddressDerivationFn**(`params?`): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                           |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------- |
| `params?`                        | `Object`                                                                              | Parameters for the address derivation |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration  |

#### Returns

`fn`

Returns a single address derived from the public key

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

#### Inherited from

TonBaseStaker.getAddressDerivationFn

***

### getMnemonicToSeedFn

▸ **getMnemonicToSeedFn**(`params?`): (`mnemonic`: `string`, `password?`: `string`) => `Promise`<`Uint8Array`>

This **static** method is used to convert BIP39 mnemonic to seed. In TON network the seed is used as a private key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a seed derived from the mnemonic

▸ (`mnemonic`, `password?`): `Promise`<`Uint8Array`>

**Parameters**

| Name        | Type     |
| ----------- | -------- |
| `mnemonic`  | `string` |
| `password?` | `string` |

**Returns**

`Promise`<`Uint8Array`>

#### Inherited from

TonBaseStaker.getMnemonicToSeedFn

***

### getSeedToKeypairFn

▸ **getSeedToKeypairFn**(`params?`): (`seed`: `Uint8Array`, `hdPath?`: `string`) => `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

This **static** method is used to convert a seed to a keypair. Note that TON network doesn't use BIP44 HD Path for address derivation.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a public and private keypair derived from the seed

▸ (`seed`, `hdPath?`): `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

**Parameters**

| Name      | Type         |
| --------- | ------------ |
| `seed`    | `Uint8Array` |
| `hdPath?` | `string`     |

**Returns**

`Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

#### Inherited from

TonBaseStaker.getSeedToKeypairFn

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a staking transaction for TON Pool contract. It uses 2 pool solution, and picks the best pool to stake to automatically.

#### Parameters

| Name                          | Type                                    | Description                                                                                                                                                                                                                                                                                 |
| ----------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params`                      | `Object`                                | Parameters for building the transaction                                                                                                                                                                                                                                                     |
| `params.delegatorAddress`     | `string`                                | The delegator address                                                                                                                                                                                                                                                                       |
| `params.validatorAddressPair` | \[`string`, `string`]                   | The validator address pair to stake to                                                                                                                                                                                                                                                      |
| `params.amount`               | `string`                                | The amount to stake, specified in `TON`                                                                                                                                                                                                                                                     |
| `params.preferredStrategy?`   | `"split"` \| `"single"` \| `"balanced"` | (Optional) The stake allocation strategy. Default is `balanced`. \* `balanced` - automatically balances the stake between the two pools based on the current pool balances and user stakes \* `split` - splits the stake evenly between the two pools \* `single` - stakes to a single pool |
| `params.referrer?`            | `string`                                | (Optional) The address of the referrer. This is used to track the origin of transactions, providing insights into which sources or campaigns are driving activity. This can be useful for analytics and optimizing user acquisition strategies                                              |
| `params.validUntil?`          | `number`                                | (Optional) The Unix timestamp when the transaction expires                                                                                                                                                                                                                                  |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**<`T`>(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds an unstaking transaction for TON Pool contract.

#### Type parameters

| Name | Type                        |
| ---- | --------------------------- |
| `T`  | extends `boolean` = `false` |

#### Parameters

| Name                                 | Type                                                  | Description                                                                                                           |
| ------------------------------------ | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `params`                             | `Object`                                              | Parameters for building the transaction                                                                               |
| `params.delegatorAddress`            | `string`                                              | The delegator address                                                                                                 |
| `params.validatorAddressPair`        | \[`string`, `string`]                                 | The validator address pair to unstake from                                                                            |
| `params.amount`                      | `T` extends `true` ? \[`string`, `string`] : `string` | The amount to unstake, specified in `TON`. When disableStatefulCalculation is true, must be a tuple \[string, string] |
| `params.disableStatefulCalculation?` | `T`                                                   | (Optional) Disables stateful calculation where validator and user stake is taken into account                         |
| `params.validUntil?`                 | `number`                                              | (Optional) The Unix timestamp when the transaction expires                                                            |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool unstaking transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` ; `pendingDeposit`: `string` ; `pendingWithdraw`: `string` ; `withdraw`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                      | Type     | Description                                                         |
| ------------------------- | -------- | ------------------------------------------------------------------- |
| `params`                  | `Object` | Parameters for the request                                          |
| `params.delegatorAddress` | `string` | The delegator (wallet) address                                      |
| `params.validatorAddress` | `string` | (Optional) The validator address to gather staking information from |

#### Returns

`Promise`<{ `balance`: `string` ; `pendingDeposit`: `string` ; `pendingWithdraw`: `string` ; `withdraw`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### getPoolParams

▸ **getPoolParams**(`params`): `Promise`<{ `minStake`: `string` ; `depositFee`: `string` ; `withdrawFee`: `string` ; `poolFee`: `string` ; `receiptPrice`: `string` }>

Retrieves the staking information for a specified pool, including minStake and fees information.

#### Parameters

| Name                      | Type     | Description                   |
| ------------------------- | -------- | ----------------------------- |
| `params`                  | `Object` | Parameters for the request    |
| `params.validatorAddress` | `string` | The validator (vault) address |

#### Returns

`Promise`<{ `minStake`: `string` ; `depositFee`: `string` ; `withdrawFee`: `string` ; `poolFee`: `string` ; `receiptPrice`: `string` }>

Returns a promise that resolves to the staking information for the specified pool.

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`TonTxStatus`>

Retrieves the status of a transaction using the transaction hash.

This method is intended to check for transactions made recently (within limit) and not for historical transactions.

#### Parameters

| Name             | Type     | Description                                            |
| ---------------- | -------- | ------------------------------------------------------ |
| `params`         | `Object` | Parameters for the transaction status request          |
| `params.address` | `string` | The account address to query                           |
| `params.txHash`  | `string` | The transaction hash to query                          |
| `params.limit?`  | `number` | (Optional) The maximum number of transactions to fetch |

#### Returns

`Promise`<`TonTxStatus`>

A promise that resolves to an object containing the transaction status.

#### Overrides

TonBaseStaker.getTxStatus

***

### getElectionMinStake

▸ **getElectionMinStake**(): `Promise`<`bigint`>

#### Returns

`Promise`<`bigint`>

***

### getPoolStatus

▸ **getPoolStatus**(`validatorAddress`): `Promise`<`PoolStatus`>

#### Parameters

| Name               | Type     |
| ------------------ | -------- |
| `validatorAddress` | `string` |

#### Returns

`Promise`<`PoolStatus`>

***

### getPastElections

▸ **getPastElections**(`electorContractAddress`): `Promise`<`Election`\[]>

#### Parameters

| Name                     | Type     |
| ------------------------ | -------- |
| `electorContractAddress` | `string` |

#### Returns

`Promise`<`Election`\[]>

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the TonStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the TonStaker instance has been initialized.

#### Inherited from

TonBaseStaker.init

***

### buildDeployWalletTx

▸ **buildDeployWalletTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a wallet deployment transaction

#### Parameters

| Name                 | Type     | Description                                                |
| -------------------- | -------- | ---------------------------------------------------------- |
| `params`             | `Object` | Parameters for building the transaction                    |
| `params.address`     | `string` | The address to deploy the wallet contract to               |
| `params.validUntil?` | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON wallet deployment transaction.

#### Inherited from

TonBaseStaker.buildDeployWalletTx

***

### sign

▸ **sign**(`params`): `Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type                                                        | Description                        |
| ---------------------- | ----------------------------------------------------------- | ---------------------------------- |
| `params`               | `Object`                                                    | Parameters for the signing process |
| `params.signer`        | `Signer`                                                    | Signer instance                    |
| `params.signerAddress` | `string`                                                    | The address of the signer          |
| `params.tx`            | [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) | The transaction to sign            |

#### Returns

`Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

A promise that resolves to an object containing the signed transaction.

#### Inherited from

TonBaseStaker.sign

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`string`>

This method is used to broadcast a signed transaction to the TON network.

#### Parameters

| Name              | Type                                                    | Description                              |
| ----------------- | ------------------------------------------------------- | ---------------------------------------- |
| `params`          | `Object`                                                | Parameters for the broadcast             |
| `params.signedTx` | [`SignedTx`](/api-reference/types/ton/ton_src.signedtx) | The signed transaction to be broadcasted |

#### Returns

`Promise`<`string`>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

#### Inherited from

TonBaseStaker.broadcast


# TonNominatorPoolStaker

## Hierarchy

* `TonBaseStaker`

  ↳ **`TonNominatorPoolStaker`**

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [getMnemonicToSeedFn](#getmnemonictoseedfn)
* [getSeedToKeypairFn](#getseedtokeypairfn)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [getStake](#getstake)
* [getPoolContractNominators](#getpoolcontractnominators)
* [init](#init)
* [buildDeployWalletTx](#builddeploywallettx)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new TonNominatorPoolStaker**(`params`): [`TonNominatorPoolStaker`](/api-reference/stakers/ton_src.tonnominatorpoolstaker)

This creates a new TonStaker instance.

#### Parameters

| Name                                     | Type                                                                                  | Description                                                                      |
| ---------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `params`                                 | `Object`                                                                              | Initialization parameters                                                        |
| `params.rpcUrl`                          | `string`                                                                              | RPC URL (e.g. <https://toncenter.com/api/v2/jsonRPC>)                            |
| `params.allowSeamlessWalletDeployment?`  | `boolean`                                                                             | (Optional) If enabled, the wallet contract is deployed automatically when needed |
| `params.allowTransferToInactiveAccount?` | `boolean`                                                                             | (Optional) Allow token transfers to inactive accounts                            |
| `params.minimumExistentialBalance?`      | `string`                                                                              | (Optional) The amount of TON to keep in the wallet                               |
| `params.addressDerivationConfig?`        | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | (Optional) TON address derivation configuration                                  |

#### Returns

[`TonNominatorPoolStaker`](/api-reference/stakers/ton_src.tonnominatorpoolstaker)

An instance of TonStaker.

#### Inherited from

TonBaseStaker.constructor

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(`params?`): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                           |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------- |
| `params?`                        | `Object`                                                                              | Parameters for the address derivation |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration  |

#### Returns

`fn`

Returns a single address derived from the public key

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

#### Inherited from

TonBaseStaker.getAddressDerivationFn

***

### getMnemonicToSeedFn

▸ **getMnemonicToSeedFn**(`params?`): (`mnemonic`: `string`, `password?`: `string`) => `Promise`<`Uint8Array`>

This **static** method is used to convert BIP39 mnemonic to seed. In TON network the seed is used as a private key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a seed derived from the mnemonic

▸ (`mnemonic`, `password?`): `Promise`<`Uint8Array`>

**Parameters**

| Name        | Type     |
| ----------- | -------- |
| `mnemonic`  | `string` |
| `password?` | `string` |

**Returns**

`Promise`<`Uint8Array`>

#### Inherited from

TonBaseStaker.getMnemonicToSeedFn

***

### getSeedToKeypairFn

▸ **getSeedToKeypairFn**(`params?`): (`seed`: `Uint8Array`, `hdPath?`: `string`) => `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

This **static** method is used to convert a seed to a keypair. Note that TON network doesn't use BIP44 HD Path for address derivation.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a public and private keypair derived from the seed

▸ (`seed`, `hdPath?`): `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

**Parameters**

| Name      | Type         |
| --------- | ------------ |
| `seed`    | `Uint8Array` |
| `hdPath?` | `string`     |

**Returns**

`Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

#### Inherited from

TonBaseStaker.getSeedToKeypairFn

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a staking (delegation) transaction for Nominator Pool contract. For more information see: <https://github.com/ton-blockchain/nominator-pool>

#### Parameters

| Name                      | Type     | Description                                                |
| ------------------------- | -------- | ---------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                    |
| `params.delegatorAddress` | `string` | The delegator address to stake from                        |
| `params.validatorAddress` | `string` | The validator address to stake to                          |
| `params.amount`           | `string` | The amount to stake, specified in `TON`                    |
| `params.validUntil?`      | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds an unstaking (withdraw nominator) transaction for Nominator Pool contract. For more information see: <https://github.com/ton-blockchain/nominator-pool>

#### Parameters

| Name                      | Type     | Description                                                |
| ------------------------- | -------- | ---------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                    |
| `params.delegatorAddress` | `string` | The delegator address                                      |
| `params.validatorAddress` | `string` | The validator address to unstake from                      |
| `params.validUntil?`      | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool unstaking transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                      | Type     | Description                                       |
| ------------------------- | -------- | ------------------------------------------------- |
| `params`                  | `Object` | Parameters for the request                        |
| `params.delegatorAddress` | `string` | The delegator (wallet) address                    |
| `params.validatorAddress` | `string` | The validator address to gather rewards data from |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### getPoolContractNominators

▸ **getPoolContractNominators**(`params`): `Promise`<{ `nominators`: [`NominatorInfo`](/api-reference/types/ton/ton_src.nominatorinfo)\[] }>

Retrieves the active nominators for a Nominator Pool contract. For more information see: <https://github.com/ton-blockchain/nominator-pool>

#### Parameters

| Name                      | Type     | Description                                       |
| ------------------------- | -------- | ------------------------------------------------- |
| `params`                  | `Object` | Parameters for the request                        |
| `params.validatorAddress` | `string` | The validator address to gather rewards data from |

#### Returns

`Promise`<{ `nominators`: [`NominatorInfo`](/api-reference/types/ton/ton_src.nominatorinfo)\[] }>

Returns a promise that resolves to the nominator data for the validator address.

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the TonStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the TonStaker instance has been initialized.

#### Inherited from

TonBaseStaker.init

***

### buildDeployWalletTx

▸ **buildDeployWalletTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a wallet deployment transaction

#### Parameters

| Name                 | Type     | Description                                                |
| -------------------- | -------- | ---------------------------------------------------------- |
| `params`             | `Object` | Parameters for building the transaction                    |
| `params.address`     | `string` | The address to deploy the wallet contract to               |
| `params.validUntil?` | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON wallet deployment transaction.

#### Inherited from

TonBaseStaker.buildDeployWalletTx

***

### sign

▸ **sign**(`params`): `Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type                                                        | Description                        |
| ---------------------- | ----------------------------------------------------------- | ---------------------------------- |
| `params`               | `Object`                                                    | Parameters for the signing process |
| `params.signer`        | `Signer`                                                    | Signer instance                    |
| `params.signerAddress` | `string`                                                    | The address of the signer          |
| `params.tx`            | [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) | The transaction to sign            |

#### Returns

`Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

A promise that resolves to an object containing the signed transaction.

#### Inherited from

TonBaseStaker.sign

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`string`>

This method is used to broadcast a signed transaction to the TON network.

#### Parameters

| Name              | Type                                                    | Description                              |
| ----------------- | ------------------------------------------------------- | ---------------------------------------- |
| `params`          | `Object`                                                | Parameters for the broadcast             |
| `params.signedTx` | [`SignedTx`](/api-reference/types/ton/ton_src.signedtx) | The signed transaction to be broadcasted |

#### Returns

`Promise`<`string`>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

#### Inherited from

TonBaseStaker.broadcast

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`TonTxStatus`>

Retrieves the status of a transaction using the transaction hash.

This method is intended to check for transactions made recently (within limit) and not for historical transactions.

#### Parameters

| Name             | Type     | Description                                            |
| ---------------- | -------- | ------------------------------------------------------ |
| `params`         | `Object` | Parameters for the transaction status request          |
| `params.address` | `string` | The account address to query                           |
| `params.txHash`  | `string` | The transaction hash to query                          |
| `params.limit?`  | `number` | (Optional) The maximum number of transactions to fetch |

#### Returns

`Promise`<`TonTxStatus`>

A promise that resolves to an object containing the transaction status.

#### Inherited from

TonBaseStaker.getTxStatus


# TonSingleNominatorPoolStaker

## Hierarchy

* `TonBaseStaker`

  ↳ **`TonSingleNominatorPoolStaker`**

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [getAddressDerivationFn](#getaddressderivationfn)
* [getMnemonicToSeedFn](#getmnemonictoseedfn)
* [getSeedToKeypairFn](#getseedtokeypairfn)
* [buildStakeTx](#buildstaketx)
* [buildUnstakeTx](#buildunstaketx)
* [getStake](#getstake)
* [getPoolContractNominators](#getpoolcontractnominators)
* [init](#init)
* [buildDeployWalletTx](#builddeploywallettx)
* [sign](#sign)
* [broadcast](#broadcast)
* [getTxStatus](#gettxstatus)

## Constructors

### constructor

• **new TonSingleNominatorPoolStaker**(`params`): [`TonSingleNominatorPoolStaker`](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker)

This creates a new TonStaker instance.

#### Parameters

| Name                                     | Type                                                                                  | Description                                                                      |
| ---------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `params`                                 | `Object`                                                                              | Initialization parameters                                                        |
| `params.rpcUrl`                          | `string`                                                                              | RPC URL (e.g. <https://toncenter.com/api/v2/jsonRPC>)                            |
| `params.allowSeamlessWalletDeployment?`  | `boolean`                                                                             | (Optional) If enabled, the wallet contract is deployed automatically when needed |
| `params.allowTransferToInactiveAccount?` | `boolean`                                                                             | (Optional) Allow token transfers to inactive accounts                            |
| `params.minimumExistentialBalance?`      | `string`                                                                              | (Optional) The amount of TON to keep in the wallet                               |
| `params.addressDerivationConfig?`        | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | (Optional) TON address derivation configuration                                  |

#### Returns

[`TonSingleNominatorPoolStaker`](/api-reference/stakers/ton_src.tonsinglenominatorpoolstaker)

An instance of TonStaker.

#### Inherited from

TonBaseStaker.constructor

## Methods

### getAddressDerivationFn

▸ **getAddressDerivationFn**(`params?`): (`publicKey`: `Uint8Array`, `_derivationPath`: `string`) => `Promise`<`string`\[]>

This **static** method is used to derive an address from a public key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                           |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------- |
| `params?`                        | `Object`                                                                              | Parameters for the address derivation |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration  |

#### Returns

`fn`

Returns a single address derived from the public key

▸ (`publicKey`, `_derivationPath`): `Promise`<`string`\[]>

**Parameters**

| Name              | Type         |
| ----------------- | ------------ |
| `publicKey`       | `Uint8Array` |
| `_derivationPath` | `string`     |

**Returns**

`Promise`<`string`\[]>

#### Inherited from

TonBaseStaker.getAddressDerivationFn

***

### getMnemonicToSeedFn

▸ **getMnemonicToSeedFn**(`params?`): (`mnemonic`: `string`, `password?`: `string`) => `Promise`<`Uint8Array`>

This **static** method is used to convert BIP39 mnemonic to seed. In TON network the seed is used as a private key.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a seed derived from the mnemonic

▸ (`mnemonic`, `password?`): `Promise`<`Uint8Array`>

**Parameters**

| Name        | Type     |
| ----------- | -------- |
| `mnemonic`  | `string` |
| `password?` | `string` |

**Returns**

`Promise`<`Uint8Array`>

#### Inherited from

TonBaseStaker.getMnemonicToSeedFn

***

### getSeedToKeypairFn

▸ **getSeedToKeypairFn**(`params?`): (`seed`: `Uint8Array`, `hdPath?`: `string`) => `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

This **static** method is used to convert a seed to a keypair. Note that TON network doesn't use BIP44 HD Path for address derivation.

It can be used for signer initialization, e.g. `FireblocksSigner` or `LocalSigner`.

#### Parameters

| Name                             | Type                                                                                  | Description                          |
| -------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------ |
| `params?`                        | `Object`                                                                              | -                                    |
| `params.addressDerivationConfig` | [`AddressDerivationConfig`](/api-reference/types/ton/ton_src.addressderivationconfig) | TON address derivation configuration |

#### Returns

`fn`

Returns a public and private keypair derived from the seed

▸ (`seed`, `hdPath?`): `Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

**Parameters**

| Name      | Type         |
| --------- | ------------ |
| `seed`    | `Uint8Array` |
| `hdPath?` | `string`     |

**Returns**

`Promise`<{ `publicKey`: `Uint8Array` ; `privateKey`: `Uint8Array` }>

#### Inherited from

TonBaseStaker.getSeedToKeypairFn

***

### buildStakeTx

▸ **buildStakeTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a staking (delegation) transaction for Single Nominator Pool contract. For more information see: <https://github.com/orbs-network/single-nominator/tree/main>

#### Parameters

| Name                      | Type     | Description                                                |
| ------------------------- | -------- | ---------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                    |
| `params.delegatorAddress` | `string` | The delegator address to stake from                        |
| `params.validatorAddress` | `string` | The validator address to stake to                          |
| `params.amount`           | `string` | The amount to stake, specified in `TON`                    |
| `params.validUntil?`      | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool staking transaction.

***

### buildUnstakeTx

▸ **buildUnstakeTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a unstaking (withdraw nominator) transaction for Single Nominator Pool contract. For more information see: <https://github.com/orbs-network/single-nominator/tree/main>

#### Parameters

| Name                      | Type     | Description                                                |
| ------------------------- | -------- | ---------------------------------------------------------- |
| `params`                  | `Object` | Parameters for building the transaction                    |
| `params.delegatorAddress` | `string` | The delegator address                                      |
| `params.validatorAddress` | `string` | The validator address to unstake from                      |
| `params.amount`           | `string` | The amount to unstake, specified in `TON`                  |
| `params.validUntil?`      | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON nominator pool unstaking transaction.

***

### getStake

▸ **getStake**(`params`): `Promise`<{ `balance`: `string` }>

Retrieves the staking information for a specified delegator.

#### Parameters

| Name                      | Type     | Description                                       |
| ------------------------- | -------- | ------------------------------------------------- |
| `params`                  | `Object` | Parameters for the request                        |
| `params.delegatorAddress` | `string` | The delegator (wallet) address                    |
| `params.validatorAddress` | `string` | The validator address to gather rewards data from |

#### Returns

`Promise`<{ `balance`: `string` }>

Returns a promise that resolves to the staking information for the specified delegator.

***

### getPoolContractNominators

▸ **getPoolContractNominators**(`params`): `Promise`<{ `nominators`: [`NominatorInfo`](/api-reference/types/ton/ton_src.nominatorinfo)\[] }>

Retrieves the active nominators for a Nominator Pool contract. For more information see: <https://github.com/ton-blockchain/nominator-pool>

#### Parameters

| Name                      | Type     | Description                                       |
| ------------------------- | -------- | ------------------------------------------------- |
| `params`                  | `Object` | Parameters for the request                        |
| `params.validatorAddress` | `string` | The validator address to gather rewards data from |

#### Returns

`Promise`<{ `nominators`: [`NominatorInfo`](/api-reference/types/ton/ton_src.nominatorinfo)\[] }>

Returns a promise that resolves to the nominator data for the validator address.

***

### init

▸ **init**(): `Promise`<`void`>

Initializes the TonStaker instance and connects to the blockchain.

#### Returns

`Promise`<`void`>

A promise which resolves once the TonStaker instance has been initialized.

#### Inherited from

TonBaseStaker.init

***

### buildDeployWalletTx

▸ **buildDeployWalletTx**(`params`): `Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Builds a wallet deployment transaction

#### Parameters

| Name                 | Type     | Description                                                |
| -------------------- | -------- | ---------------------------------------------------------- |
| `params`             | `Object` | Parameters for building the transaction                    |
| `params.address`     | `string` | The address to deploy the wallet contract to               |
| `params.validUntil?` | `number` | (Optional) The Unix timestamp when the transaction expires |

#### Returns

`Promise`<{ `tx`: [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) }>

Returns a promise that resolves to a TON wallet deployment transaction.

#### Inherited from

TonBaseStaker.buildDeployWalletTx

***

### sign

▸ **sign**(`params`): `Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

Signs a transaction using the provided signer.

#### Parameters

| Name                   | Type                                                        | Description                        |
| ---------------------- | ----------------------------------------------------------- | ---------------------------------- |
| `params`               | `Object`                                                    | Parameters for the signing process |
| `params.signer`        | `Signer`                                                    | Signer instance                    |
| `params.signerAddress` | `string`                                                    | The address of the signer          |
| `params.tx`            | [`UnsignedTx`](/api-reference/types/ton/ton_src.unsignedtx) | The transaction to sign            |

#### Returns

`Promise`<[`SignedTx`](/api-reference/types/ton/ton_src.signedtx)>

A promise that resolves to an object containing the signed transaction.

#### Inherited from

TonBaseStaker.sign

***

### broadcast

▸ **broadcast**(`params`): `Promise`<`string`>

This method is used to broadcast a signed transaction to the TON network.

#### Parameters

| Name              | Type                                                    | Description                              |
| ----------------- | ------------------------------------------------------- | ---------------------------------------- |
| `params`          | `Object`                                                | Parameters for the broadcast             |
| `params.signedTx` | [`SignedTx`](/api-reference/types/ton/ton_src.signedtx) | The signed transaction to be broadcasted |

#### Returns

`Promise`<`string`>

Returns a promise that resolves to the response of the transaction that was broadcast to the network.

#### Inherited from

TonBaseStaker.broadcast

***

### getTxStatus

▸ **getTxStatus**(`params`): `Promise`<`TonTxStatus`>

Retrieves the status of a transaction using the transaction hash.

This method is intended to check for transactions made recently (within limit) and not for historical transactions.

#### Parameters

| Name             | Type     | Description                                            |
| ---------------- | -------- | ------------------------------------------------------ |
| `params`         | `Object` | Parameters for the transaction status request          |
| `params.address` | `string` | The account address to query                           |
| `params.txHash`  | `string` | The transaction hash to query                          |
| `params.limit?`  | `number` | (Optional) The maximum number of transactions to fetch |

#### Returns

`Promise`<`TonTxStatus`>

A promise that resolves to an object containing the transaction status.

#### Inherited from

TonBaseStaker.getTxStatus


# Signers


# FireblocksSigner

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [init](#init)
* [sign](#sign)
* [contractCall](#contractcall)
* [getPublicKey](#getpublickey)

## Constructors

### constructor

• **new FireblocksSigner**(`params`): [`FireblocksSigner`](/api-reference/signers/signer_fireblocks_src.fireblockssigner)

Constructs a new FireblocksSigner.

#### Parameters

| Name                         | Type                  | Description                                                                                                             |
| ---------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `params`                     | `Object`              | The parameters required to initialize the FireblocksSigner                                                              |
| `params.apiSecretKey`        | `string`              | Fireblocks API Secret key                                                                                               |
| `params.apiKey`              | `string`              | Fireblocks API Key                                                                                                      |
| `params.vaultName`           | `string`              | The name of the Fireblocks vault where the assets are stored                                                            |
| `params.assetId`             | `string`              | The identifier for the asset you intend to manage                                                                       |
| `params.addressDerivationFn` | `AddressDerivationFn` | A function that derives the address from the public key                                                                 |
| `params.timeout?`            | `number`              | (Optional) The maximum time (in ms) to wait for the Fireblocks API sign request to complete                             |
| `params.pollInterval?`       | `number`              | (Optional) The interval (in ms) at which the signer polls the Fireblocks API to check if the sign request has completed |
| `params.apiUrl?`             | `string`              | (Optional) The URL of the Fireblocks API, defaults to `https://api.fireblocks.io`                                       |
| `params.logger?`             | `Logger`              | (Optional) A logger to use for logging messages, i.e `console`                                                          |

#### Returns

[`FireblocksSigner`](/api-reference/signers/signer_fireblocks_src.fireblockssigner)

A new instance of FireblocksSigner.

## Methods

### init

▸ **init**(): `Promise`<`void`>

Initializes the signer, performing any necessary setup or configuration.

#### Returns

`Promise`<`void`>

A promise that resolves once the initialization is complete.

***

### sign

▸ **sign**(`signerAddress`, `signerData`, `options?`): `Promise`<{ `sig`: `Signature` ; `pk`: `Uint8Array` }>

Signs the provided data using the private key associated with the signer's address.

#### Parameters

| Name            | Type         | Description                                                      |
| --------------- | ------------ | ---------------------------------------------------------------- |
| `signerAddress` | `string`     | The address of the signer                                        |
| `signerData`    | `SignerData` | The data to be signed, which can be a raw message or custom data |
| `options?`      | `Object`     | Additional options                                               |
| `options.note?` | `string`     | An optional note to include with the transaction                 |

#### Returns

`Promise`<{ `sig`: `Signature` ; `pk`: `Uint8Array` }>

A promise that resolves to an object containing the signature and public key.

***

### contractCall

▸ **contractCall**(`params`): `Promise`<`FireblocksTxStatus`>

Signs an Ethereum contract call transaction using Fireblocks.

#### Parameters

| Name                          | Type            | Description                                    |
| ----------------------------- | --------------- | ---------------------------------------------- |
| `params`                      | `Object`        | Parameters for the contract call               |
| `params.to`                   | \`0x${string}\` | The destination contract address               |
| `params.value?`               | `bigint`        | The amount to send in wei (optional)           |
| `params.data`                 | \`0x${string}\` | The contract call data                         |
| `params.gas`                  | `bigint`        | -                                              |
| `params.maxFeePerGas`         | `bigint`        | Maximum fee per gas in wei (optional)          |
| `params.maxPriorityFeePerGas` | `bigint`        | Maximum priority fee per gas in wei (optional) |
| `params.gasPrice`             | `bigint`        | -                                              |
| `params.note?`                | `string`        | Optional note for the transaction              |

#### Returns

`Promise`<`FireblocksTxStatus`>

A promise that resolves to the transaction response from Fireblocks.

***

### getPublicKey

▸ **getPublicKey**(`address`): `Promise`<`Uint8Array`>

Retrieves the public key associated with the signer's address.

#### Parameters

| Name      | Type     | Description               |
| --------- | -------- | ------------------------- |
| `address` | `string` | The address of the signer |

#### Returns

`Promise`<`Uint8Array`>

A promise that resolves to a Uint8Array representing the public key.


# LocalSigner

The LocalSigner in the Chorus One SDK is a specialized implementation of the Signer interface that utilizes a `BIP39` mnemonic for signing operations.

This signer is ideal for local environments where you need a straightforward and secure method to generate and manage cryptographic keys from mnemonic phrases.

## Table of contents

### Constructors

* [constructor](#constructor)

### Methods

* [init](#init)
* [sign](#sign)
* [getPublicKey](#getpublickey)

## Constructors

### constructor

• **new LocalSigner**(`params`): [`LocalSigner`](/api-reference/signers/signer_local_src.localsigner)

Constructs a new LocalSigner.

#### Parameters

| Name                         | Type                      | Description                                                       |
| ---------------------------- | ------------------------- | ----------------------------------------------------------------- |
| `params`                     | `Object`                  | The parameters required to initialize the LocalSigner             |
| `params.mnemonic`            | `string`                  | A string containing your `BIP39` mnemonic phrase                  |
| `params.accounts`            | \[{ `hdPath`: `string` }] | An array of account objects, each containing an HD path           |
| `params.keyType`             | `KeyType`                 | An enum specifying the signing key type (e.g. SECP256K1, ED25519) |
| `params.addressDerivationFn` | `AddressDerivationFn`     | A function that derives the address from the public key           |
| `params.mnemonicToSeedFn?`   | `MnemonicToSeedFn`        | -                                                                 |
| `params.seedToKeypairFn?`    | `SeedToKeypairFn`         | -                                                                 |
| `params.logger?`             | `Logger`                  | (Optional) A logger to use for logging messages, i.e `console`    |

#### Returns

[`LocalSigner`](/api-reference/signers/signer_local_src.localsigner)

A new instance of LocalSigner.

## Methods

### init

▸ **init**(): `Promise`<`void`>

Initializes the signer, performing any necessary setup or configuration.

#### Returns

`Promise`<`void`>

A promise that resolves once the initialization is complete.

***

### sign

▸ **sign**(`signerAddress`, `signerData`): `Promise`<{ `sig`: `Signature` ; `pk`: `Uint8Array` }>

Signs the provided data using the private key associated with the signer's address.

#### Parameters

| Name            | Type         | Description                                                      |
| --------------- | ------------ | ---------------------------------------------------------------- |
| `signerAddress` | `string`     | The address of the signer                                        |
| `signerData`    | `SignerData` | The data to be signed, which can be a raw message or custom data |

#### Returns

`Promise`<{ `sig`: `Signature` ; `pk`: `Uint8Array` }>

A promise that resolves to an object containing the signature and public key.

***

### getPublicKey

▸ **getPublicKey**(`address`): `Promise`<`Uint8Array`>

Retrieves the public key associated with the signer's address.

#### Parameters

| Name      | Type     | Description               |
| --------- | -------- | ------------------------- |
| `address` | `string` | The address of the signer |

#### Returns

`Promise`<`Uint8Array`>

A promise that resolves to a Uint8Array representing the public key.


# Types


# Ethereum




---

[Next Page](/llms-full.txt/1)

