Figment's Staking API increases the speed at which you can add new transfer and staking functionalities for many Proof-of-Stake (PoS) assets. The Staking API abstracts away all network-specific infrastructure and work to enable API interaction in the exact same way, regardless of network or the type of action being taken. It gets you to market faster, by reducing research and discovery work by weeks and the engineering time by months.

Using the Staking API's concepts of flows, actions, inputs and payloads, it is possible to build dynamic forms to collect data and guide users through each workflow without the need to hard code specifics for a given network. For non-ETH chains, stake with any validator on the network. For ETH, you still need to provision validators with each staking provider you use.

Staking API Core Concepts

Flows

The Staking API is based around the concept of a flow. A flow is a combination of a network, a chain and an operation. For example: Solana (network) + devnet (chain) + staking (operation)

A flow is made of multiple steps (states) and a specific set of actions to be completed to move between states

Each flow has a unique id to be used for querying and advancing the flow.

Actions

At each step in the flow, the Staking API's response contains a JSON object with each possible action that can be taken, including the action's name and the inputs for submitting that action.

In the example above ("Solana staking on devnet"), some SOL tokens first need to be held in a system account. After creating a flow, the reponse will contain two possible actions that can be taken to advance the flow to the next state:

  • create_stake_account (to create and fund a new account)
  • assign_stake_account (to use an existing inactive account)
{
  "id": "e2285668-f6ab-4b77-9e96-edbcca63cd24",
  "operation": "staking",
  "state": "initialized",
  "actions": [
    {
      "name": "assign_stake_account",
      // "inputs": [...]
    },
    {
      "name": "create_new_stake_account",
      // "inputs": [...]
    }
  ],

}

Inputs

Each action comes with a set of inputs that indicate what data needs to be collected and submitted to the advance to the next state.

In our example ("Solana staking on devnet"), let's assume we want to go with the create_stake_account action. The response of the request indicates that create_stake_account needs to be submitted with 4 input fields. It contains metadata for data type, display label, validations, etc that can be used for building a UI.

{
  "id": "e2285668-f6ab-4b77-9e96-edbcca63cd24",
  "operation": "staking",
  "state": "initialized",
  "actions": [
    {
      "name": "create_new_stake_account",
      "inputs": [
        {
          "name": "funding_account_pubkey",
          "display": "Stake Account Pubkey",
          "description": "",
          "type": "string",
          "validations": [
            {
              "type": "presence",
              "options": {}
            }
          ],
          "array": false,
          "default_value": null
        },
        {
          "name": "stake_authority_pubkey",
          // type, display, validations, etc
        },
        {
          "name": "withdraw_authority_pubkey",
          // type, display, validations, etc
        },
        {
          "name": "amount",
          // type, display, validations, etc
        }
      ]
    }
  ],
}

Payloads

For each step in a Flow where a transaction must be signed, the response from the Staking API includes a serialized transaction payload ready for signature. It is your responsibility to manage signing the transaction and submitting the signed Payload back to the Staking API for broadcasting to the network.

Webhooks

The Staking API utilizes webhooks to notify you of completed actions, reducing the need for manual polling. Every network supported by the Staking API uses the same API endpoints to create, modify, list or delete webhooks.

Decoding and Signing Transactions

We have published an npm package for decoding and signing Staking API transactions. Learn how to use it here: Signing Transactions with Figment's NPM Package

Advance a flow using a transaction hash

Figment's API provides the option for clients to use an existing solution to sign and broadcast transactions themselves, using a transaction hash from a completed transaction to advance the state of a flow and confirm the transaction on-chain — in lieu of providing a signed transaction payload.

This action is also available for other networks and flows. The following example uses a Polkadot bonding flow on the Westend testnet to illustrate the process.

Example: Polkadot

Polkadot delegation flows use the create_bonding_tx action to generate a transaction payload.
It is still possible to bond from a Stash account, completing this transaction without use of Figment's API.
In this case, we want to perform the bond transaction (including the signature) from the Polkadot.js Apps UI,
then complete the bonding flow with the Staking API by providing the transaction hash of the completed transaction.

The general form of this action is confirm_<action>_tx_by_hash.
Since we are performing a bonding transaction, the action name to use is confirm_bonding_tx_by_hash.

Using this action in a flow lets you supply a transaction hash to the API while the flow is in the <action>_tx_signature state.

In the case of Polkadot, the block number of the block which includes the transaction hash must also be specified.

{
  "id": "3ace9f6b-7298-4fc7-b780-f2c3ea521784",
  "state": "bonding_tx_signature",
  "actions": [
    ...
    {
      "name": "confirm_bonding_tx_by_hash",
      "inputs": [
        {
          "name": "hash",
          "display": "Hash",
          "description": "",
          "type": "string",
          "validations": [
            {
              "type": "presence",
              "options": {}
            }
          ],
          "array": false,
          "default_value": null
        },
        {
          "name": "block_number",
          "display": "Block Number",
          "description": "",
          "type": "integer",
          "validations": [],
          "array": false,
          "default_value": null
        }
      ]
    }
  ],
  ...
  "network_code": "polkadot",
  "chain_code": "westend",
  "created_at": "2023-01-20T22:10:26.800Z",
  "updated_at": "2023-01-20T22:28:19.348Z"
}

Usage

On Polkadot, the input for hash should be the Extrinsic Hash of the transaction, and the input for block
should be the block number in which that extrinsic occurred. Refer to a bonding transaction on the Subscan block explorer for an example of where to find this information.

For other networks, supply the hash of a confirmed transaction.

Code Examples

🚧

Important

Code examples provided as samples only and should not be used in production out of the box. Use at your own risk.

curl -X PUT 'https://polkadot-slate.figment.io/api/v1/flows/<flow_id>/next' \
-H 'Authorization: API-KEY' \
-H 'Content-Type: application/json' \
-d '{
    "name": "confirm_bonding_tx_by_hash",
    "inputs": {
        "hash": "0x53b66da426dca5386408f0a3cdc5300477dd7151c7459701e9dcbbf0fa0b07c8",
        "block_number": "14295923"
    }
}'
fetch(`https://polkadot-slate.figment.io/api/v1/flows/${FLOW_ID}/next`, {
  method: 'PUT',
  headers: {
    "Authorization" : "<API_KEY>",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "name": "confirm_bonding_tx_by_hash",
    "inputs": {
        "hash": "0x53b66da426dca5386408f0a3cdc5300477dd7151c7459701e9dcbbf0fa0b07c8",
        "block_number": "14295923"
    }
  });
});

📘

Note

The parameter block_number only applies to Polkadot. For other networks, only the hash is required.

Flow State

The action confirm_<action>_tx_by_hash updates the flow state, depending on whether the confirmed transaction hash can be found by the API.

  • When confirm_<action>_tx_by_hash succeeds, the flow state will reflect the successful action, the same as if a transaction payload had been signed and sent to the API.

  • In case confirm_<action>_tx_by_hash fails, the flow state will remain <action>_tx_signature, allowing for retries — the flow state does not become <action>_tx_broadcasting.

In the case of the example Polkadot bonding transaction, the state would be bonding_complete after a successful confirm_bonding_tx_by_hash action.

For comparison, an Ethereum staking flow state would be deposited after a successful confirm_deposit_tx_by_hash action.

Check the table below for a summary of flow states after confirm_<action>_tx_by_hash.

NetworkFlow(s)Final State
AvalancheStakingcompleted
CardanoStaking, Transfercompleted
CosmosStaking, Redelegate, Transfer, Claim Rewardscompleted
CosmosUnstaking unbonding during the unbonding period.
completed when successful.
EthereumStakingdeposited
EthereumUnstakingunstaked
EthereumAggregated Stakingactivating during the activation period.
active when successful.
EthereumAggregated Unstakingbroadcasting if awaiting manual Figment approval, or exiting while the validator(s) are in the exit queue.
unstaked when successful.
NEARStakingdelegated
NEARUnstakingcool_down during the unbonding period.
withdrawn after a successful withdrawal transaction.
NEARTransfertransferred
PolkadotStakingbonding_complete after a successful bonding transaction.
delegated after a successful nomination transaction.
PolkadotUnstakingdone after a successful chill transaction.
ready_to_withdraw after a successful unbond transaction.
done after a successful withdrawal transaction.
PolkadotAdd or Remove Proxyregistered after a successful add proxy transaction.
removed after a successful remove proxy transaction.
PolkadotTransfertransferred
PolygonStakingcreate_delegate_tx after a successful allowance transaction.
completed after a successful delegate transaction.
PolygonUnstakingunbonding during the unbonding period.
done after a successful claim transaction.
PolygonClaim Rewardsdone after a successful claim rewards transaction.
SolanaStakingstake_account after a stake account is created or assigned.
delegation_activating during the bonding period.
delegation_active after a successful delegation.
SolanaUnstakingcool_down during the deactivation period.
withdrawn after a successful withdrawal transaction.
SolanaTransfertransferred
SolanaMerge / Split Stake Accountcompleted