Luganodes Docs
TwitterLinkedInMedium
  • Luganodes
  • Native ETH Staking
    • Features
      • Stake
      • Portfolio
  • Custodians
    • Fireblocks
    • Ledger
  • Networks
    • Overview
    • Active Networks
      • Aptos
      • Archway
      • Avail
      • Avalanche
      • bitsCruch
      • Canto
      • Cardano
      • Chiliz
      • Composable Finance
      • Concordium
      • Cosmos
      • Covalent
      • dYdX
      • Eigen Layer
      • Ethereum
      • Elixir
      • Flare
      • Gitopia
      • Kava
      • Kroma
      • Kusama
      • Lukso
      • MultiversX
      • Namada
      • Near
      • Neutron
      • Noble
      • Persistence
      • Polkadot
      • Polygon
      • Radix
      • Ronin
      • River
      • Saga
      • Solana
      • Stride
      • Sui
      • Tenet
      • Tron
      • Ton
      • Vanar
      • Walrus
      • Zilliqa
  • Staking APIs
    • Overview
    • Ethereum
      • Staking Guide
      • Authentication
      • Node Provisioning APIs
      • Consolidation & Switch
      • Exits
      • FAQs
  • TOOLS
    • Hyperliquid
      • Hypermon Monitoring Tool
    • Flare
      • FTSOv2 Monitoring Tool
    • Solana
      • Solana Indexer
    • Berachain
      • Auto BGT Boost Tool
      • Berachain Indexer
Powered by GitBook
On this page
  • Via Intent
  • How voluntary exiting works
  • Request Luganodes to submit exits
  • Generate Exit Message
  • Via Withdrawal Address
  • Partial Exit Request
  • Types
  • Partial Exit Response Object
  • Result Object
  1. Staking APIs
  2. Ethereum

Exits

Learn how to initiate the validator unstaking process

PreviousConsolidation & SwitchNextFAQs

Last updated 2 days ago

Via Intent

How voluntary exiting works

To initiate unstaking, validators are required to perform a SignedVoluntaryExit transaction, where the transaction is signed using Luganodes' validator keys.

Exiting validators must submit a signed challenge with relevant validator information. Thereafter, the createAndSignChallenge function generates the necessary signature for the exit API request, relying on validator indexes (found in the Get Delegation object response) and the withdrawal address.

We have created a script to perform the aforementioned operations with ease.

Script to create a Signed Challenge

Note: controllerAddress can be used alternatively to the withdrawalAddress in the script below

// Install ethers package using a package manager (eg. NPM, YARN)
import {
  BaseWallet,
  SigningKey,
  hashMessage,
  hexlify,
  toUtf8Bytes,
} from 'ethers';

const createAndSignChallenge = async (
  validatorIndexes,
  privateKeyOfWithdrawalAdd,
  withdrawalAddress,
) => {
  const wallet = new BaseWallet(new SigningKey(privateKeyOfWithdrawalAdd));

  // challenge that needs to be signed
  const challenge = JSON.stringify(
    {
      intentToExit:
        'I am signing this message and requesting that Luganodes exit the following validators from the network',
      validatorIndexes, // REQUIRED: list of validator indexes
      date: Date.now().toString(), // optional, timestamp this was signed
      address: withdrawalAddress, // REQUIRED: the signing address
    },
    null,
    2,
  );
  const sign = wallet.signMessageSync(hashMessage(challenge));

  console.log('signature: ', sign);

  // packedChallenge
  const packedChallenge = hexlify(
    toUtf8Bytes(
      '\u0019Ethereum Signed Message:\n' +
        challenge.length.toString() +
        challenge,
    ),
  );
  console.log('packed_challenge', packedChallenge);
};

  
await createAndSignChallenge(
    validatorIndexes, //[0, 2]
    privateKeyOfWithdrawalAdd, 
    withdrawalAddress, 
  );

Request Luganodes to submit exits

POST /api/exit

Request Luganodes to exit a set of validators for a given withdrawal address. The list of validators comes from a challenge that must be signed with the withdrawal address. See the above code snippet for constructing the body for this method.

NOTE: If the challenge and signature check out, this submits the voluntary exits and will initiate the process for exiting validators. This method does not return the voluntary exits.

Headers

Name
Type
Description

api-key*

String

API Key provided by Luganodes

Query Parameters

Name
Type
Description

key*

String

The public address of the withdrawal key or the controller key to exit

Request Body

Name
Type
Description

challenge*

String

The packed challenge formed using above snippet

signature*

String

The packed signature formed using above snippet

{
  "message": "exit request is under processing for these validators",
  "validators": [
    {
      "pubKey": "0xa8b4286511612eccb9f5834f278300fd389d5490d2c53c7674826959a1e2113e8dad87cdc357da16f9461473d82bff73",
      "validatorIndex": 1123,
      "provisionId": "a62c7c43-faf7-4fd8-908e-1791c6d8c257"
    }
  ]
}
{
    "success": false,
    "status": 400,
    "message": "validators are already in one of the exit states"
}
// Example request body

{
    "signature":"0xba56185cea6b6f1bd9fc7bda51656a2136e19958d79718ff13c99cec82d36a9f5280784717a0579c5a7294a3778e7d0a00039b5a51d4e85cae25ebc14130dd691c",
    "challenge":"0x19457468657265756d205369676e6564204d6573736167653a0a3234347b0a202022696e74656e74546f45786974223a20224920616d207369676e696e672074686973206d65737361676520616e642072657175657374696e672074686174205374616b656420657869742074686520666f6c6c6f77696e672076616c696461746f72732066726f6d20746865206e6574776f726b222c0a20202276616c696461746f72496e6465786573223a205b0a20202020300a20205d2c0a20202264617465223a202231363838373137333039383136222c0a20202261646472657373223a2022307861303863364339653364304532384530453945663137634536373839396538453036353031644432220a7d"
}

Generate Exit Message

POST /api/exit/message

Request Luganodes to generate an exit message for a set of validators for a given withdrawal address. This message can be broadcasted over the network through an RPC call. The list of validators comes from a challenge that must be signed with the withdrawal address.

NOTE: This method requires the exit message to be broadcasted through an RPC call. If RPC response is "null", then the exit message has been successfully broadcasted.

Headers

Name
Type
Description

api-key*

String

API Key provided by Luganodes

Query Parameters

Name
Type
Description

key*

String

The public address of the withdrawal key or the controller key to exit

Request Body

Name
Type
Description

challenge*

String

The packed challenge formed using above snippet

signature*

String

The packed signature formed using above snippet

{
    "message": "Exit message(s) created",
    "result": {
        "validatorIndexes": [
            1792413
        ],
        "exitMessages": [
            {
                "message": {
                    "epoch": 0,
                    "validator_index": 1792413
                },
                "signature": "0x90415852edac40501f8c233149cf2c92d1604124c9cbb9b91b4beac0fac5a0d8376b75f0a3a6b7faede07af0dce1edf705bcdf3f9d1d8a124ca73d089ec777a3c15a033c4c8c13ffd9390da0cb1c511f881f0753e6afc724b922d33a76de2d6b"
            }
        ]
    },
    "page": 1,
    "per_page": 100,
    "total": 1,
    "pages": 1
}
// Example request body

{
    "signature":"0xba56185cea6b6f1bd9fc7bda51656a2136e19958d79718ff13c99cec82d36a9f5280784717a0579c5a7294a3778e7d0a00039b5a51d4e85cae25ebc14130dd691c",
    "challenge":"0x19457468657265756d205369676e6564204d6573736167653a0a3234347b0a202022696e74656e74546f45786974223a20224920616d207369676e696e672074686973206d65737361676520616e642072657175657374696e672074686174205374616b656420657869742074686520666f6c6c6f77696e672076616c696461746f72732066726f6d20746865206e6574776f726b222c0a20202276616c696461746f72496e6465786573223a205b0a20202020300a20205d2c0a20202264617465223a202231363838373137333039383136222c0a20202261646472657373223a2022307861303863364339653364304532384530453945663137634536373839396538453036353031644432220a7d"
}

Via Withdrawal Address

Partial Exit Request

POST /api/exit/partial

Client can call this API to generate an unsigned transaction to perform partial withdrawals. This unsigned transaction needs to be signed by the validator withdrawal address and broadcasted to the network.

Headers

Name
Type
Description

api-key*

String

API Key provided by Luganodes

Query Parameters

Name
Type
Description

key*

String

The public address of the withdrawal key or the controller key to exit

Request Body

Name
Type
Description

validatorPubKey*

String

Public address of validator

amountToWithdraw*

Number

Amount of stake to be withdrawn


    "message": "Partial exit transaction created",
    "result": {
        "validatorPubKey": "0x8e44dac3019bc8128a86b16c5e7012a4dc763718dc9a31e3b2df6c18bb72b7cf5a08cabd03fea42c9f1aa9d2f234c1f8",
        "amountToWithdraw": "1",
        "withdrawalAddress": "0x8C24B68141552e0844354B0b638031918CAAFaeB",
        "unsignedTx": "0x02f85083088bb0368403b0be13848360bf63830186a08001b8388e44dac3019bc8128a86b16c5e7012a4dc763718dc9a31e3b2df6c18bb72b7cf5a08cabd03fea42c9f1aa9d2f234c1f8000000003b9aca00c0",
        "partialExitRequestTrx": {
            "data": "0x8e44dac3019bc8128a86b16c5e7012a4dc763718dc9a31e3b2df6c18bb72b7cf5a08cabd03fea42c9f1aa9d2f234c1f8000000003b9aca00",
            "value": 1,
            "nonce": 54,
            "gasLimit": 100000,
            "maxFeePerGas": "2204155747",
            "maxPriorityFeePerGas": "61914643",
            "type": 2,
            "chainId": "560048"
        }
    }
}
// Example request body

{
    "validatorPubKey": "0x8e44dac3019bc8128a86b16c5e7012a4dc763718dc9a31e3b2df6c18bb72b7cf5a08cabd03fea42c9f1aa9d2f234c1f8",
    "amountToWithdraw": "1"
}

Types

Partial Exit Response Object

Property
Description
Type

message

Transaction generation status

String

result

Result Object

Object

Result Object

Property
Description
Type

validatorPubKey

Public address of validator

String

amountToWithdraw

Amount of stake to be withdrawn NOTE: Amount resulting in the validator's balance below 32 ETH is not allowed.

Object

unsignedTx

Unsigned transaction object which needs to be signed wiith the validator withdrawal address

String

withdrawalAddress

Withdrawal Address of validator

String

partialRequestTrx

Transaction Object

Object

Via Intent
How voluntary exiting works
Request Luganodes to submit exits
Generate an exit message
Via Wtihdrawal Address
Parital Exit Request
Sample Request
Types
Parital Exit Response Object