New Validator Creation
For setting up validators, P2P.ORG has introduced a new simplified smart contract flow — validators created this way receive the 0x02
type of withdrawal credentials. Compared to the previous 0x01
type, this brings the following benefits:
- Flexible effective balance from 32 ETH up to 2048 ETH
- New staking options such as incremental top-ups and auto compounding
- Simplified flow with fewer steps and reduced manual deposit data handling
All changes are supported for both Ethereum and SSV staking APIs.
To upgrade to the 0x02
credentials type, you can either consolidate multiple existing validators into a single one or set up a new 0x02
-enabled validator by following the steps below:
- Prepare a proxy staking transaction.
- Sign and broadcast the transaction.
Request examples are provided using cURL.
Upgrade is just an optionFor clients currently using the
0x01
validator setup, all existing endpoints remain supported. If you need to create a new validator via the previous0x01
flow, refer to the guides for the Ethereum or SSV networks respectively.Upgrading to the
0x02
type of withdrawal credentials is not necessary, but only recommended for enhanced functionality.
1. Prepare Staking Proxy Transaction
This flow is supported for Ethereum Direct staking only and applies exclusively to validators using
0x02
type of withdrawal credentials.
Send a GET request to /api/v1/eth/staking/direct/p2p/deposit with the following query parameters specified: amount
, withdrawalAddress
, controllerAddress
and feeRecipientAddress
.
By calling this endpoint, you are receiving a fully constructed by Ethereum Smart Contract 3.1 transaction which is ready for signing and broadcasting.
Example request:
curl --request GET \
--url "https://api-test.p2p.org/api/v1/eth/staking/direct/p2p/deposit?amount=32&withdrawalAddress=0x8eB2277e54A2A7db9b7c0D9FA9B78dcB35f74866&controllerAddress=0x8eB2277e54A2A7db9b7c0D9FA9B78dcB35f74866&feeRecipientAddress=0x3202B5B0602274197CcB22B8c02CEC9539990c7c" \
--header 'Authorization: Bearer <token>'
amount
— total amount of ETH to deposit. Note that the maximum effective balance is 2048 ETH, so it is recommended specifying no more than 1920 ETH in order to save the opportunity to auto-compound the received rewards.amountPerValidator
— amount of tokens to stake in Gwei per validator.withdrawalAddress
— withdrawal address for the validators.controllerAddress
— controller address for the validators.feeRecipientAddress
— address that receives priority fees.
Example response:
{
"error": null,
"result": {
"serializeTx": "0x02f9025701808312c36c850727b59762839896809423be839a14cec3d6d716d904f09368bbf9c750eb8903782dace9d9000000b90224a49b131b0200000000000000000000008eb2277e54a2a7db9b7c0d9fa9b78dcb35f74866000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000003fcd8d9acac042095dfba53f4c40c74d19e2e9d9000000000000000000000000000000000000000000000000000000000000251c0000000000000000000000003202b5b0602274197ccb22b8c02cec9539990c7c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000e86b78000ed3b7b820ac6a39b46602356daee0602180fefa69a94774c3209a9f5ad1df42aa2c426b1494a39afc4ee79a528dca95807f5a1b518c8fb0a4df1be92b8a8b6e5f4fccf35f3975f9cf64aa92f4896f2553a5ba9fb0b13cabb25f21a2881f027d9703bfa57f45a514fff7bcc1b8020c2a3ab0581cfbb748dfe612a14acef40bc61de068cf3117e8227ab1315e0302f97e17d5b8948aa8071645b27ad74f669783d363fbc7e9dd58c01e535aff418b2fdbff56a55212e25efbc6b963bb048d98ecc1d03020f890bbf7518fd2463afb82ffdf452863268bdae4eae18d6108dce9ef803669f466000000000000000000000000000000000000000000000000c0",
"to": "0x23BE839a14cEc3D6D716D904f09368Bbf9c750eb",
"gasLimit": "10000000",
"data": "0xa49b131b0200000000000000000000008eb2277e54a2a7db9b7c0d9fa9b78dcb35f74866000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000003fcd8d9acac042095dfba53f4c40c74d19e2e9d9000000000000000000000000000000000000000000000000000000000000251c0000000000000000000000003202b5b0602274197ccb22b8c02cec9539990c7c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000e86b78000ed3b7b820ac6a39b46602356daee0602180fefa69a94774c3209a9f5ad1df42aa2c426b1494a39afc4ee79a528dca95807f5a1b518c8fb0a4df1be92b8a8b6e5f4fccf35f3975f9cf64aa92f4896f2553a5ba9fb0b13cabb25f21a2881f027d9703bfa57f45a514fff7bcc1b8020c2a3ab0581cfbb748dfe612a14acef40bc61de068cf3117e8227ab1315e0302f97e17d5b8948aa8071645b27ad74f669783d363fbc7e9dd58c01e535aff418b2fdbff56a55212e25efbc6b963bb048d98ecc1d03020f890bbf7518fd2463afb82ffdf452863268bdae4eae18d6108dce9ef803669f466000000000000000000000000000000000000000000000000",
"value": "64000000000000000000",
"chainId": 1,
"type": 2,
"maxFeePerGas": "30730983266",
"maxPriorityFeePerGas": "1229676",
"marker": "8bb5a5d4-145c-4a22-b792-3fd98565bdd0"
}
}
serializeTx
— serialized unsigned transaction.to
— recipient address for this transaction.gasLimit
— maximum gas limit for this block.data
— transaction data.value
— amount this transaction is sending in Wei.chainId
— chain ID this transaction is authorized on, as specified by EIP-155.type
— EIP-2718 type of this transaction envelope.maxFeePerGas
— maximum price per unit of gas this transaction will pay for the combined EIP-1559 block's base fee and this transaction's priority fee in Wei.maxPriorityFeePerGas
— price per unit of gas in Wei, which is added to the EIP-1559 block's base fee. This added fee is used to incentivize miners to prioritize this transaction.marker
— additional identifier of the deposit transaction. You can use it to search the deposits with Get List Deposits endpoint.
2. Sign and Broadcast Transaction
Prepare serializeTx
from the previous step and use the example code below to sign and broadcast the transaction to the Ethereum network:
require("dotenv").config();
const ethers = require("ethers");
async function signAndBroadcast() {
console.log("Started");
// Enter the serialized transaction
const rawTransaction = process.env.RAW_TRANSACTION;
// Enter the private key of the address used to transfer the stake amount
const privateKey = process.env.PRIVATE_KEY;
// Enter the selected RPC URL
const rpcURL = process.env.RPC_URL;
// Initialize the provider using the RPC URL
const provider = new ethers.providers.JsonRpcProvider(rpcURL);
// Initialize a new Wallet instance
const wallet = new ethers.Wallet(privateKey, provider);
// Parse the raw transaction
const tx = ethers.utils.parseTransaction(rawTransaction);
tx.nonce = await provider.getTransactionCount(wallet.address);
// Enter the max fee per gas and prirorty fee
tx.maxFeePerGas = ethers.utils.parseUnits(
process.env.MAX_FEE_PER_GAS_IN_GWEI,
"gwei"
);
tx.maxPriorityFeePerGas = ethers.utils.parseUnits(
process.env.MAX_PRIORITY_FEE_IN_GWEI,
"gwei"
);
// Sign the transaction
const signedTransaction = await wallet.signTransaction(tx);
// Send the signed transaction
const transactionResponse = await provider.sendTransaction(signedTransaction);
return transactionResponse;
}
signAndBroadcast()
.then((transactionResponse) => {
console.log(
"Transaction broadcasted, transaction hash:",
transactionResponse.hash
);
})
.catch((error) => {
console.error("Error:", error);
})
.finally(() => {
console.log("Finished");
});
After the transaction is processed in the chain's queue, the new validator with 0x02
type of withdrawal credentials will be set up.
3. Get List of Deposits
Check the list of validators created via your authentication token and their status by sending a GET request to /api/v1/eth/staking/direct/p2p/deposits.
Example request:
curl --request GET \
--url https://api.p2p.org/api/v1/eth/staking/ssv/p2p/deposits?limit=50&offset=0&type=withdrawalAddress&withdrawalAddress=0xe3bb3cc1fd44fced699e5eae6fbbc643a0fbcca0 \
--header 'accept: application/json' \
--header 'authorization: Bearer <token>'
limit
— number of resources that a single response page contains.offset
— number of resources to exclude from a response.type
— type of filter:withdrawalAddress
— withdrawal address for the validators.transactionHash
— hash of the deposit transaction.depositIds
— list of the deposit IDs.markers
— additional identifier of the deposit transaction.
Example response:
{
"error": null,
"result": {
"list": [
{
"deposit": {
"depositId": "",
"marker": "faee00fc-f282-43eb-a15f-27d2ed97479e",
"transactionHash": "",
"senderAddress": "",
"withdrawalAddress": "0xe3bb3cc1fd44fced699e5eae6fbbc643a0fbcca0",
"feeRecipientAddress": "",
"totalAmount": "",
"unprocessedAmount": "18273"
},
"validator": {
"pubkey": "0xcd5ff4fbeafeb6bcdc5dde3ba41d88638eb7b14e52ee3beaf0d32ae3abb303ff8814258ecaa49c5ed0bd7dd48bb0ca502ac89c0bcd36dc7b01a00b8db1e4adec",
"status": "unknown",
"amount": "1991",
"withdrawalCredentials": "...",
"signature": "...",
"depositMessageRoot": "...",
"depositDataRoot": "...",
"forkVersion": "10000910",
"depositCliVersion": "2.7.0",
"eth2NetworkName": "hoodi"
}
},
],
"limit": 50,
"offset": 0,
"totalCount": 17,
"totalAmount": "18273",
"unprocessedAmount": "18273",
"markers": [
{
"marker": "faee00fc-f282-43eb-a15f-27d2ed97479e",
"processStatus": "confirmed",
"address": ",,,",
"amount": "400",
"amountPerValidator": "40000000000",
"feeRecipientAddress": "..."
}
]
}
}
deposit
:depositId
— unique identifier for the deposit initiated by the user.marker
— unique identifier of the deposit transactiontransactionHash
— hash of the transaction associated with the user's validator deposit.senderAddress
— address used to interact with the SSV proxy smart contract and transfer the requested stake amount.withdrawalAddress
— withdrawal address for the validators.feeRecipientAddress
— the address that receives the fee recipient rewards.totalAmount
— total amount currently staked for the specified deposit ID.unprocessedAmount
— amount associated with validators that are not yet activated for the specified deposit ID
validator
:pubkey
— validator public key.status
— current status of the validatoramount
— amount of ETH, denominated in gwei, that is being deposited.
limit
— number of resources that a single response page contains.offset
— number of resources to exclude from a response.totalCount
— total number of validators relevant to the current request, based on applied filters.totalAmount
— total staked amount for the current request.unprocessedAmount
— cumulative staked amount across all validators that are not yet activated for the current request.markers
— Unique identifiers generated after creating a deposit request, tracking transactions and deposited funds.
Updated 2 days ago