The Aggregated Unstaking flow allows you to unstake ETH from multiple validators at once. You can use this flow either to broadcast PSETs or request validators to be exited On Demand. Review the difference in the guide.

Initialize Unstaking Flow

To initiate the aggregated staking process, create a new flow with a POST request to /api/v1/flows.

URL

https://api.figment.io/flows

Request

  • protocol* : string Protocol this flow operates on (ethereum).
  • network* : string Network this flow operates on (mainnet, holesky or goerli).
  • operation* : string The operation to perform (aggregated_unstaking).
{
  "protocol": "ethereum",
  "network": "holesky",
  "operation": "aggregated_unstaking"
}

Response

  • id : string ID of the newly created flow.
  • operation : string The operation to perform (aggregated_unstaking).
  • state : string The state of the flow (initialized).
  • actions : array An array of action objects containing the name, inputs, and validations for advancing the flow with each action.
    • perform_aggregated_unstake : Use this action to unstake your ETH from a maximum of 100 validators with a single request.
  • data: Data specific to this flow.
    • exits: array An array of validator exit objects. Empty at this step since no validators have exited.
    • estimated_principal_return_at: timestamp Estimate for when the validators' ETH will be returned to the withdrawal address. null at this step because no data has been submitted.
    • withdrawal_address: string Withdrawal address pertaining to all validators being exited in this flow.
    • amount: string Amount of ETH being unstaked. Divide by 32 to get number of validators being exited.
    • transactions: array Empty for this flow since no user transactions are required.
  • protocol: string Protocol this flow operates on (ethereum).
  • network: string Network this flow operates on (mainnet, holesky or goerli).
  • created_at: timestamp When you created the flow.
  • updated_at: timestamp Last time the flow was updated by either your action or on-chain updates. Equal to created_at at this point.
{
  "id": "404cfb10-cc3b-4c89-8b40-dff22643aec0",
  "operation": "aggregated_unstaking",
  "state": "initialized",
  "actions": [
    {
      "name": "perform_aggregated_unstake",
      "inputs": [
        {
          "name": "exits",
          "display": "Exits",
          "description": "",
          "type": "array_of_validator_exit_data",
          "validations": [
            {
              "type": "array",
              "options": {
                "allow_empty": true,
                "allow_duplicates": false
              }
            },
            {
              "type": "length",
              "options": {
                "maximum": 100,
                "message": "translation missing: en.workflows.v1.ethereum.aggregated_unstaking.create_aggregated_unstake_input.exceeded_max_validators"
              }
            },
            {
              "type": "array_of_objects",
              "options": {
                "merge_array_errors": true
              }
            }
          ],
          "array": true,
          "default_value": null,
          "element_type": "validator_exit_data",
          "inputs": [
            {
              "name": "validator_index",
              "display": "Validator Index",
              "description": "",
              "type": "integer",
              "validations": [],
              "array": false,
              "default_value": null
            },
            {
              "name": "epoch",
              "display": "Epoch",
              "description": "",
              "type": "integer",
              "validations": [],
              "array": false,
              "default_value": null
            },
            {
              "name": "signature",
              "display": "Signature",
              "description": "",
              "type": "hex",
              "validations": [],
              "array": false,
              "default_value": null
            }
          ]
        },
        {
          "name": "amount",
          "display": "Amount",
          "description": "",
          "type": "decimal",
          "validations": [],
          "array": false,
          "default_value": null
        },
        {
          "name": "withdrawal_address",
          "display": "Withdrawal Address",
          "description": "",
          "type": "string",
          "validations": [],
          "array": false,
          "default_value": null
        }
      ]
    }
  ],
  "data": {
    "exits": [],
    "estimated_principal_return_at": null,
    "withdrawal_address": null,
    "amount": null,
    "transactions": []
  },
  "protocol": "ethereum",
  "network": "holesky",
  "created_at": "2023-04-21T19:38:14.421Z",
  "updated_at": "2023-04-21T19:38:14.421Z"
}

Submit Unstaking Data (Option 1: On Demand Exit Transactions)

Use this section for submitted unstaking data if you wish to advance the flow with on demand demand exit transactions instead of broadcasting PSETs. PUT the URL to advance the flow and exit your validators.

URL

https://api.figment.io/flows/:id/next

Request

  • name* : string Name of the action to execute (perform_aggregated_unstake).
  • inputs* : object Data required to advance the flow.
    • withdrawal_address* : string All validators being exited must have this withdrawal address.
    • amount* : Amount of ETH to unstake. Must be a multiple of 32 less than or equal to 3200.
{
  "name": "perform_aggregated_unstake",
  "inputs": {
    "withdrawal_address": "0xB458D87418e6020260C92e18b11b64F1ed6fFF30",
    "amount": 3200
  }
}

Response

The aggregated unstaking flow will exit enough validators to unstake your full amount, provided that they all belong to the supplied withdrawal address. The flow state will become broadcasting until Figment manually approves the validator exits (within 24-72 business hours) when the flow's state will change to broadcasted. Refer to the guide Ethereum Validator Lifecycle for details.

  • id : string ID of the newly created flow.
  • operation : string The operation to perform (aggregated_unstaking).
  • state : string The state of the flow (broadcasting).
  • actions : array This array will only contain the wait action with an estimated_state_change_at.
    • wait : There are no more actions for you to take! We've received your request. Move to the final section to get updates in the flow.
  • data: Data specific to this flow.
    • exits: array An array of validator exit objects describing a SignedVoluntaryExit for each validator that will be exited.
      • validator_index: integer Unique index of the validator that describes how many validators entered the active set before it.
      • validator_pubkey: string Validator's public key.
      • epoch: integer Epoch when this SignedVoluntaryExit was submitted to the chain.
      • signature: string Signature from validator's private key for this SignedVoluntaryExit.
      • status: string Status of this SignedVoluntaryExit (broadcast_scheduled). Poll the flow status for further updates.
      • source: string Describes where the SignedVoluntaryExit comes from (internal).
    • estimated_principal_return_at: timestamp Estimate for when the validators' ETH will be returned to the withdrawal address.
    • withdrawal_address: string Withdrawal address pertaining to all validators being exited in this flow.
    • amount: string Amount of ETH being unstaked. Divide by 32 to get number of validators being exited.
    • transactions: array Empty for this flow since no user transactions are required.
  • protocol: string Protocol this flow operates on (ethereum).
  • network: string Network this flow operates on (mainnet, holesky or goerli).
  • created_at: timestamp When you created the flow.
  • updated_at: timestamp Last time the flow was updated by either your action or on-chain updates, such as a validator entering the exit queue, exiting the queue, or completing the withdrawal.

The timestamp estimated_principal_return_at indicates the (estimated) latest time for all validators to be withdrawn.

{
  "id": "535807ff-2ff7-4b1c-a887-bfc4fcc15ed2",
  "operation": "aggregated_unstaking",
  "state": "broadcasting",
  "actions": [
    {
      "name": "wait",
      "estimated_state_change_at": "2023-04-21T17:51:39.341Z",
      "inputs": []
    }
  ],
  "data": {
    "exits": [
      {
        "validator_index": null,
        "validator_pubkey": "aa4e2aa5322c4b5f2b2f735daa68a2b9b9e0bf1ede924abaef7f66f9d2aa6463b048a4da10bede2a1a5c3ec885044056",
        "epoch": null,
        "signature": null,
        "status": "broadcast_scheduled",
        "source": "internal"
      }
    ],
    "estimated_principal_return_at": null,
    "withdrawal_address": "0x3B41D9736eD9bfC15A87d8FBB69C616190AeD6C6",
    "amount": "32.0",
    "transactions": []
  },
  "protocol": "ethereum",
  "network": "holesky",
  "created_at": "2023-04-21T16:10:42.673Z",
  "updated_at": "2023-04-21T16:12:10.281Z"
}

Submit Unstaking Data (Option 2: Broadcasting PSETs)

Use this option if you have PSETs and wish to immediately broadcast them. PUT the URL to advance the flow, which will exit the specified validators.

URL

https://api.figment.io/flows/[:flow_id]/next

Request

  • name* :string Name of the action to execute (perform_aggregated_unstake).
  • inputs* : object.
    • exits* : array Array of PSETs.
      • validator_index* : number The validator's index as stated in the PSET.
      • epoch* : number Epoch as stated in the PSET.
      • signature* : string Signature as stated in the PSET.
{
  "name": "perform_aggregated_unstake",
  "inputs": {
    "exits": [
      {
        "epoch": 192304,
        "signature": "0xaaead310469833e582b40d9027e5dbde1dffd12a1b10f712e9ae87a85daa6bb0867f285c0dc07358c26c58f9537d083a0cd5c2113726aeb0ea798b310262306d90ce3ce4ec774ee02f3956e566383d77efef5dd39250a8b69895f3006cbbac80",
        "validator_index": 479261
    	}
  	]
  }
}

Response

  • id : string ID of the newly created flow.
  • operation : string The operation to perform (aggregated_unstaking).
  • state : string The state of the flow (broadcasting).
  • actions : array This array will only contain the wait action with an estimated_state_change_at.
    • wait : There are no more actions for you to take! We've received your request. Move to the final section to get updates in the flow.
  • data: Data specific to this flow.
    • exits: array An array of validator exit objects describing the PSETs you submitted.
      • validator_index: integer The validator's index as stated in the PSET.
      • validator_pubkey: string The validator's public key.
      • epoch: integer Epoch as stated in the PSET.
      • signature: string Signature as stated in the PSET.
      • status: string Status of this SignedVoluntaryExit (broadcasting). Poll the flow status for further updates.
      • source: string Describes where the SignedVoluntaryExit comes from (external).
    • estimated_principal_return_at: timestamp Estimate for when the validators' ETH will be returned to the withdrawal address.
    • withdrawal_address: string Withdrawal address is null in this case because there are no restrictions to how validators are exited in this option.
    • amount: string Amount of ETH being unstaked. Divide by 32 to get number of validators being exited.
    • transactions: array Empty for this flow since no user transactions are required.
  • protocol: string Protocol this flow operates on (ethereum).
  • network: string Network this flow operates on (mainnet, holesky or goerli).
  • created_at: timestamp When you created the flow.
  • updated_at: timestamp Last time the flow was updated by either your action or on-chain updates, such as a validator entering the exit queue, exiting the queue, or completing the withdrawal.
{
  "id": "2403c1df-6c8f-43c4-bf37-06797b9aa117",
  "operation": "aggregated_unstaking",
  "state": "broadcasting",
  "actions": [
    {
      "name": "wait",
      "estimated_state_change_at": "2023-07-27T02:10:32.142Z",
      "inputs": [

      ]
    }
  ],
  "data": {
    "exits": [
      {
        "validator_index": 479261,
        "validator_pubkey": null,
        "epoch": 192304,
        "signature": "0xaaead310469833e582b40d9027e5dbde1dffd12a1b10f712e9ae87a85daa6bb0867f285c0dc07358c26c58f9537d083a0cd5c2113726aeb0ea798b310262306d90ce3ce4ec774ee02f3956e566383d77efef5dd39250a8b69895f3006cbbac80",
        "status": "broadcasting",
        "source": "external"
      }
    ],
    "estimated_principal_return_at": "2023-08-04T08:13:36.423Z",
    "withdrawal_address": null,
    "amount": "32.0",
    "transactions": [

    ]
  },
  "protocol": "ethereum",
  "network": "holesky",
  "created_at": "2023-07-26T23:15:40.639Z",
  "updated_at": "2023-07-27T02:02:24.424Z"
}

Get Unstaking Flow

To get the current state of the existing flow, send a GET request to /flows/[:flow_id] using the flow ID from the previous step.

Request

  • None

Response

  • id : string ID of the flow.
  • operation : string The Staking API operation being performed by this flow.
  • state : string The current state of the flow. The flow state will move to exiting when the validators have joined the exit queue, withdrawing when the validators have left the exit queue and unstaked when all validators have been withdrawn.
  • actions : array It includes the name & inputs of all next possible actions.
  • data : object Flow & transaction data.
    • exits : array One object per validator being exited.
      • validator_index : The validator index number.
      • validator_pubkey : The validator's public key.
      • epoch : The epoch in which the SignedVoluntaryExit was generated, whether in a PSET or On Demand.
      • status : One of (broadcast_scheduled, broadcasting, broadcasted, exited_queue, or withdrawal_done) depending on the current status of the SignedVoluntaryExit being broadcasted.
      • source : Describes where the SignedVoluntaryExit came from. internal if using Option 1, external if using Option 2.
    • estimated_principal_return_at : Indicates the (estimated) latest time that all unstaked ETH will be swept to the withdrawal address. This is subject to change depending on the state of the cahin, and withdrawals can complete before or after this time.
    • withdrawal_address : The withdrawal address for validators being unstaked.
    • amount : A multiple of 32 ETH, maximum of 3200.
    • transactions : Since there are no transactions signed in this flow, this array will always be empty.
{
  "id": "4b4dbd07-27ed-45d9-940f-e74e94bf5664",
  "operation": "aggregated_unstaking",
  "state": "unstaked",
  "actions": [],
  "data": {
    "exits": [
      {
        "validator_index": null,
        "validator_pubkey": "a58c71cf8fdf116114afd9622a9087609a314766f25b9afea6a511522b50091ace55424143a19d41a73b39f9f07b2b58",
        "epoch": null,
        "signature": null,
        "status": "withdrawal_done",
        "source": "internal"
      }
    ],
    "estimated_principal_return_at": "2023-04-14T22:20:49.882Z",
    "withdrawal_address": "0x3b41d9736ed9bfc15a87d8fbb69c616190aed6c6",
    "amount": "32.0",
    "transactions": []
  },
  "protocol": "ethereum",
  "network": "holesky",
  "created_at": "2023-04-12T20:30:14.556Z",
  "updated_at": "2023-04-15T00:21:05.517Z"
}