Sign and Broadcast Transaction

To complete any staking, withdrawal, or claim operation on Ethereum, you must sign and broadcast the unsigned transaction provided by the Pooled Staking API.

1. Retrieve an Unsigned Transaction

Use the relevant API endpoint (e.g., /staking/deposit, /staking/withdraw, /staking/claim) to obtain an unsigned transaction object:

{
  "result": {
    "unsignedTransaction": {
      "to": "0xba447498dc4c169f2b4f427b2c4d532320457e89",
      "data": "0xf9609f08...",
      "value": "10000000000000000"
    }
  }
}
  • to — Recipient (contract) address.
  • data — Transaction data payload (hexadecimal).
  • value — Amount of ETH to send (in Wei, as a string).

2. Sign the Transaction

Sign the unsigned transaction using your Ethereum private key.
You can use a variety of libraries and environments; here’s a reference implementation using ethers.js:

import { Wallet, providers, TransactionRequest } from "ethers";

// Example input values (replace with your data)
const PRIVATE_KEY = "<PRIVATE_KEY>";
const RPC_URL = "<ETHEREUM_RPC_URL>";

const unsignedTx: TransactionRequest = {
  to: "0xba447498dc4c169f2b4f427b2c4d532320457e89",
  data: "0xf9609f08...",
  value: "10000000000000000" // as string, convert if needed
};

async function signTransaction() {
  const provider = new providers.JsonRpcProvider(RPC_URL);
  const wallet = new Wallet(PRIVATE_KEY, provider);
  const tx = await wallet.populateTransaction(unsignedTx);
  // Optionally set gas/gasPrice here
  const signedTx = await wallet.signTransaction(tx);
  console.log(signedTx);
}

signTransaction();

How to run:

npm install [email protected]
node signTransaction.js
  • This script prints a raw signed transaction ready to broadcast.

3. Broadcast the Signed Transaction

Send the signed transaction to the Ethereum network using the Pooled Staking API by making a POST request to /api/v1/eth-pool/[network]/transaction/send endpoint.

Example request:

curl --request POST \
     --url https://api-test.p2p.org/api/v1/eth-pool/hoodi/transaction/send \
     --header 'Content-Type: application/json' \
     --header 'Authorization: Bearer <token>' \
     --data '{
       "signedTransaction": "0xf86b80...29a0eab2..."
     }'
  • signedTransaction — Raw signed Ethereum transaction (hexadecimal).

Example response:

{
  "result": {
    "network": "mainnet",
    "senderAddress": "0x092Af80778ff3c3D27Fd2744C39f6e9326d9AaEe",
    "transactionHash": "0x4fbe6e8a6e9ea1d0efc9ea9d4ef6b93714664b7b8a81d81080b24f8894ebc991",
    "status": "pending",
    "gas": {
      "gasLimit": "21000",
      "gasPrice": "32000000000",
      "used": "21000"
    },
    "createdAt": "2025-07-11T12:00:00.000Z"
  },
  "error": null
}
  • network — Ethereum network: mainnet or testnet.
  • senderAddress — Sender address for the transaction.
  • transactionHash — Hash of the transaction on Ethereum.
  • status — Transaction status: pending, success, or failed.
  • gas — Gas usage details for the transaction.
    • gasLimit — Maximum gas provided for the transaction.
    • gasPrice — Price per gas unit (in Wei).
    • used — Gas actually used.
    • createdAt — ISO 8601 timestamp when the transaction was accepted for broadcast.

What's Next?