Staking API Tutorials
View an example showing how to use Blockdaemon Polygon Staking API.
MATIC Upgraded to POL
As of September 4th, 2024, POL will replace MATIC as the gas and staking token on Polygon PoS (Proof of Stake) and Polygon zkEVM.
Here’s what you need to know:
- MATIC Stakers: No action is required. All staked MATIC will be converted to POL.
- MATIC Holders on the Polygon PoS network: No action is required. Your tokens will be automatically migrated 1:1 to POL.
- MATIC Holders on the Ethereum network or Polygon zkEVM: You’ll need to migrate your tokens. For more details, please refer to the migration guide here.
- To stake POL: You'll need to sign the bootstrap transaction. If you want to stake or unstake MATIC without migrating to POL, call the Staking API with
MATIC
as the token type.
In this section you will find a TypeScript example showing how to use the Polygon Staking API.
import { ethers } from "hardhat";
import { BigNumber, BigNumberish } from "ethers";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { TransactionRequest, TransactionResponse } from "@ethersproject/abstract-provider";
import axios from "axios";
// +--------+
// | Config |
// +--------+
const BOSS_APIKEY = "local-key";
// +------+
// | Misc |
// +------+
async function send(signer: SignerWithAddress, to: string, data: string): Promise<TransactionResponse> {
const tx: TransactionRequest = {
to: to,
from: signer.address,
data: data,
gasLimit: 1048576,
gasPrice: ethers.utils.parseUnits("32", "gwei"),
};
const response: TransactionResponse = await signer.sendTransaction(tx);
await response.wait(1);
return response;
}
interface Payload {
wallet_address: string;
amount?: BigNumberish;
unbond_nonces?: number[];
}
async function post(endpoint: string, payload: Payload): Promise<any> {
const { BOSSURL, CUSTOMER } = process.env;
const url = `${BOSSURL}/mainnet/${endpoint}`
if (payload.amount !== undefined) {
payload.amount = BigNumber.from(payload.amount).toString();
}
const response = await axios.post(url, payload, {
headers: {
"X-Client-ID": CUSTOMER,
"Accept": "application/json",
"Content-Type": "application/json",
"X-API-Key": BOSS_APIKEY
},
}).catch((reason: any) => console.log("error:", reason?.response?.data));
if (response instanceof Object) {
return response.data.polygon;
}
throw new Error();
}
// +-----------------------------+
// | Staking Reporting + Polygon |
// +-----------------------------+
export async function bootstrap(signer: SignerWithAddress): Promise<TransactionResponse> {
const data = await post("bootstrapping-intents", {
wallet_address: signer.address
});
return send(signer, data.to, data.unsigned_transaction);
}
export async function delegate(
signer: SignerWithAddress,
amount: BigNumberish,
): Promise<TransactionResponse> {
const data = await post("stake-intents", {
wallet_address: signer.address,
amount: amount
});
return send(signer, data.to, data.unsigned_transaction);
}
export async function unbond(
signer: SignerWithAddress,
amount: BigNumberish,
): Promise<TransactionResponse> {
const data = await post("deactivation-intents", {
wallet_address: signer.address,
amount: amount
});
return send(signer, data.to, data.unsigned_transaction);
}
export async function unstake(
signer: SignerWithAddress,
nonce: number,
): Promise<TransactionResponse> {
const data = await post("withdrawal-intents", {
wallet_address: signer.address,
unbond_nonces: [nonce],
});
return send(signer, data[0].to, data[0].unsigned_transaction);
}
export async function restake(signer: SignerWithAddress): Promise<TransactionResponse> {
const data = await post("rewards/restake-intents", {
wallet_address: signer.address
});
return send(signer, data.to, data.unsigned_transaction);
}
export async function withdrawReward(signer: SignerWithAddress): Promise<TransactionResponse> {
const data = await post("rewards/withdrawal-intents", {
wallet_address: signer.address
});
return send(signer, data.to, data.unsigned_transaction);
}
// +------+
// | Main |
// +------+
async function main() {
const signer = await ethers.getSigners().then((xs: SignerWithAddress[]) => xs[0]);
// [X] Bootstrap my newly made account.
await bootstrap(signer);
// [X] Delegate 10 POLs.
await delegate(signer, ethers.utils.parseEther("10"));
// [X] Unbond 5 of them.
await unbond(signer, ethers.utils.parseEther("5"));
// [X] After the withdrawal period, we could unstake like this:
// await unstake(/signer/ signer, /nonce/ 1);
//
// Please check GET /deactivation-intents for available nonces.
// [X] After enough rewards, we can either restake or withdraw:
// await restake(signer);
// await withdrawReward(signer);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
👋 Need Help?
Contact us through email or our support page for any issues, bugs, or assistance you may need.
Updated 10 days ago