Staking is the process of locking up tokens or assets (NFTs) to a specific receiver, often to secure a network, participate in governance, or earn rewards. This guide provides a step-by-step walkthrough of the entire staking lifecycle using the OCAP Client, including creating a stake, revoking it, claiming the assets back, and slashing a stake for punitive reasons.
This process involves a few key methods:
stake(): To create a new stake.revokeStake(): To initiate the process of withdrawing your staked items.claimStake(): To finalize the withdrawal and return the items to your account.slashStake(): To allow authorized parties to penalize a staker.
How to Stake
To begin, you use the stake method to lock your tokens or assets. This action creates a new, unique stake address on the chain that holds your staked items and the rules governing them.
Parameters
- to
string(required) — The DID address of the account that will receive the stake. - assets
string[]— An array of asset addresses (NFTs) to be staked. - tokens
object[]— An array of token objects to be staked.- address
string(required) — The address of the token contract. - value
number(required) — The amount of tokens to stake.
- address
- wallet
WalletObject(required) — The wallet object of the staker. - locked
boolean(default:false) — A boolean indicating if the stake is locked upon creation. - slashers
string[]— An array of DID addresses permitted to slash this stake. Defaults to the receiver's address if not provided. - message
string— An optional note or message for the stake. - nonce
string— An optional nonce to ensure the stake address is unique.
Example
Staking Tokens and an Asset
// Assume 'client' is an initialized GraphQLClient instance
// and 'stakerWallet' is a valid wallet object.
const receiverAddress = 'z29d5852576b8a8b6f3a8b4b74a3f4a3e2e1d'; // The address of the stake receiver
async function createStake() {
try {
const [txHash, stakeAddress] = await client.stake({
to: receiverAddress,
tokens: [{
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E', // Address of the token to stake
value: 100, // Amount of tokens to stake
}],
assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'], // Address of the asset/NFT to stake
message: 'Staking for validator rewards',
wallet: stakerWallet,
});
console.log('Stake transaction sent:', txHash);
console.log('New stake address created:', stakeAddress);
return stakeAddress;
} catch (error) {
console.error('Error creating stake:', error);
}
}Return Value
The stake method returns a tuple containing the transaction hash and the newly created stakeAddress. This address is crucial for all future interactions with this specific stake, such as revoking or slashing.
How to Revoke a Stake
Revoking a stake is the process initiated by the staker to retrieve their locked tokens and assets. This transaction does not immediately return the funds; instead, it marks them as available for claiming, subject to any on-chain lock-up periods.
Parameters
- from
string(required) — The address of the stake to be revoked (obtained from the 'stake' call). - assets
string[]— An array of asset addresses to revoke from the stake. - tokens
object[]— An array of token objects to revoke.- address
string(required) — The address of the token contract. - value
number(required) — The amount of tokens to revoke.
- address
- wallet
WalletObject(required) — The staker's wallet object, which must be the original creator of the stake.
Example
Revoking a Stake
// Assume 'stakeAddress' is the address returned from the previous step
// and 'stakerWallet' is the same wallet used to create the stake.
async function revokeExistingStake(stakeAddress) {
try {
const revokeTxHash = await client.revokeStake({
from: stakeAddress,
tokens: [{
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
value: 100,
}],
assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'],
wallet: stakerWallet,
});
console.log('Revoke stake transaction sent:', revokeTxHash);
console.log('IMPORTANT: Save this hash to claim your stake later.');
return revokeTxHash;
} catch (error) {
console.error('Error revoking stake:', error);
}
}Return Value
This function returns the transaction hash of the revoke operation. This hash serves as evidence and is required for the final step of claiming the stake.
How to Claim a Revoked Stake
After a stake has been successfully revoked, the staker must send a claimStake transaction to move the tokens and assets back into their account. This finalizes the withdrawal process.
Parameters
- from
string(required) — The address of the stake. - evidence
string(required) — The transaction hash from the 'revokeStake' call, which serves as proof of revocation. - wallet
WalletObject(required) — The staker's wallet object.
Example
Claiming Staked Items
// Assume 'stakeAddress' and 'revokeTxHash' are from the previous steps,
// and 'stakerWallet' is the staker's wallet.
async function claimRevokedStake(stakeAddress, revokeTxHash) {
try {
const claimTxHash = await client.claimStake({
from: stakeAddress,
evidence: revokeTxHash,
wallet: stakerWallet,
});
console.log('Claim stake transaction sent:', claimTxHash);
console.log('Your tokens and assets have been returned to your account.');
} catch (error) {
console.error('Error claiming stake:', error);
}
}Return Value
The method returns the final transaction hash. Once this transaction is confirmed on the chain, the staked items are returned to the wallet's address.
How to Slash a Stake
Slashing is a punitive action that can be taken by a designated slasher (usually the stake receiver) against a staker. This typically happens if the staker violates certain rules. The slashed tokens or assets are removed from the stake and sent to a designated vault.
Parameters
- from
string(required) — The address of the stake to be slashed. - reason
string(required) — A mandatory message explaining why the slash is occurring. - assets
string[]— An array of asset addresses to be slashed from the stake. - tokens
object[]— An array of token objects to be slashed.- address
string(required) — The address of the token contract. - value
number(required) — The amount of tokens to slash.
- address
- wallet
WalletObject(required) — The wallet object of an authorized slasher.
Example
Slashing a Stake
// Assume 'stakeAddress' is the address of the stake to be slashed,
// and 'slasherWallet' is the wallet of an authorized slasher.
async function slashExistingStake(stakeAddress) {
try {
const slashTxHash = await client.slashStake({
from: stakeAddress,
reason: 'Validator missed signing 10 consecutive blocks.',
tokens: [{
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
value: 10, // Slashing 10 tokens as a penalty
}],
wallet: slasherWallet,
});
console.log('Slash stake transaction sent:', slashTxHash);
} catch (error) {
console.error('Error slashing stake:', error);
}
}Return Value
This method returns the transaction hash for the slashing operation.
Summary
You've now learned the complete lifecycle of staking on the OCAP blockchain: creating a stake with stake, retrieving funds with revokeStake and claimStake, and penalizing bad actors with slashStake. This powerful mechanism is fundamental to many decentralized applications.
To learn more about the items you can stake, see the Manage Tokens and Manage Assets (NFTs) guides.