Delegation & Staking
Manage delegation contracts, validator nodes, and staking operations on MultiversX.
Overview
The DelegationController provides an API for:
- Validator Operations - Create delegation contracts, manage validator nodes
- Delegator Operations - Stake, unstake, claim rewards
- Contract Management - Configure fees, caps, and metadata
DelegationController
import 'package:abidock_mvx/abidock_mvx.dart';
final controller = DelegationController(
chainId: const ChainId.mainnet(),
gasLimitEstimator: GasEstimator(networkProvider: provider),
);
Validator Operations
Create Delegation Contract
Create a new staking provider contract:
final account = await Account.fromPem('validator.pem');
final accountInfo = await provider.getAccount(account.address);
final input = NewDelegationContractInput(
totalDelegationCap: BigInt.from(10000000) * BigInt.from(10).pow(18), // 10M EGLD cap
serviceFee: BigInt.from(1000), // 10% fee (10000 = 100%)
amount: Balance.fromEgld(1250), // 1250 EGLD initial stake
);
final tx = await controller.createTransactionForNewDelegationContract(
account,
accountInfo.nonce,
input,
);
final hash = await provider.sendTransaction(tx);
print('Delegation contract created: $hash');
Minimum Requirements
- Minimum 1250 EGLD to create a delegation contract
- Service fee is in basis points (1000 = 10%, 10000 = 100%)
Add Validator Nodes
Add BLS keys to your delegation contract:
// Load validator keys
final validatorKey = ValidatorSecretKey.fromPem('validator_key.pem');
// Sign the delegation contract address
final signedMessage = validatorKey.sign(delegationContract.publicKeyBytes);
final input = AddNodesInput(
delegationContract: delegationContract,
publicKeys: [validatorKey.publicKey],
signedMessages: [signedMessage],
);
final tx = await controller.createTransactionForAddingNodes(
account,
accountInfo.nonce,
input,
);
Stake Nodes
Activate validator nodes for consensus:
final input = ManageNodesInput(
delegationContract: delegationContract,
publicKeys: [validatorPublicKey1, validatorPublicKey2],
);
final tx = await controller.createTransactionForStakingNodes(
account,
accountInfo.nonce,
input,
);
Unstake Nodes
Remove nodes from active validation:
final input = ManageNodesInput(
delegationContract: delegationContract,
publicKeys: [validatorPublicKey],
);
final tx = await controller.createTransactionForUnstakingNodes(
account,
accountInfo.nonce,
input,
);
Unbond Nodes
Complete unbonding after unstaking period:
final input = ManageNodesInput(
delegationContract: delegationContract,
publicKeys: [validatorPublicKey],
);
final tx = await controller.createTransactionForUnbondingNodes(
account,
accountInfo.nonce,
input,
);
Remove Nodes
Remove validator keys from contract:
final input = ManageNodesInput(
delegationContract: delegationContract,
publicKeys: [validatorPublicKey],
);
final tx = await controller.createTransactionForRemovingNodes(
account,
accountInfo.nonce,
input,
);
Unjail Nodes
Unjail slashed validator nodes:
final input = UnjailingNodesInput(
delegationContract: delegationContract,
publicKeys: [jailedValidatorKey],
amount: Balance.fromEgld(2.5), // Unjail fee
);
final tx = await controller.createTransactionForUnjailingNodes(
account,
accountInfo.nonce,
input,
);
Contract Configuration
Change Service Fee
final input = ChangeServiceFeeInput(
delegationContract: delegationContract,
serviceFee: BigInt.from(1500), // Change to 15%
);
final tx = await controller.createTransactionForChangingServiceFee(
account,
accountInfo.nonce,
input,
);
Modify Delegation Cap
final input = ModifyDelegationCapInput(
delegationContract: delegationContract,
delegationCap: BigInt.from(5000000) * BigInt.from(10).pow(18), // 5M EGLD
);
final tx = await controller.createTransactionForModifyingDelegationCap(
account,
accountInfo.nonce,
input,
);
Set Metadata
final input = SetMetadataInput(
delegationContract: delegationContract,
name: 'My Staking Provider',
website: 'https://mystaking.com',
identifier: 'mystaking',
);
final tx = await controller.createTransactionForSettingMetadata(
account,
accountInfo.nonce,
input,
);
Automatic Activation
Enable/disable automatic node activation:
final input = ManageDelegationContractInput(
delegationContract: delegationContract,
);
// Enable
final enableTx = await controller.createTransactionForSettingAutomaticActivation(
account,
accountInfo.nonce,
input,
);
// Disable
final disableTx = await controller.createTransactionForUnsettingAutomaticActivation(
account,
accountInfo.nonce,
input,
);
Cap Check on Redelegate
Control whether delegation cap applies to reward redelegation:
final input = ManageDelegationContractInput(
delegationContract: delegationContract,
);
// Enable cap check
final enableTx = await controller.createTransactionForSettingCapCheckOnRedelegateRewards(
account,
accountInfo.nonce,
input,
);
// Disable cap check
final disableTx = await controller.createTransactionForUnsettingCapCheckOnRedelegateRewards(
account,
accountInfo.nonce,
input,
);
Delegator Operations
Delegate EGLD
Stake EGLD with a staking provider:
final input = DelegateInput(
delegationContract: Address.fromBech32('erd1qqqqqqqqqqqqqpgq...'),
amount: Balance.fromEgld(100), // Delegate 100 EGLD
);
final tx = await controller.createTransactionForDelegating(
account,
accountInfo.nonce,
input,
);
final hash = await provider.sendTransaction(tx);
print('Delegated: $hash');
Undelegate EGLD
Initiate unstaking (10-day unbonding period):
final input = UndelegateInput(
delegationContract: delegationContract,
amount: Balance.fromEgld(50), // Undelegate 50 EGLD
);
final tx = await controller.createTransactionForUndelegating(
account,
accountInfo.nonce,
input,
);
Withdraw Funds
Claim unbonded EGLD after unbonding period:
final input = WithdrawInput(
delegationContract: delegationContract,
);
final tx = await controller.createTransactionForWithdrawing(
account,
accountInfo.nonce,
input,
);
Claim Rewards
Claim accumulated staking rewards:
final input = WithdrawInput(
delegationContract: delegationContract,
);
final tx = await controller.createTransactionForClaimingRewards(
account,
accountInfo.nonce,
input,
);
Redelegate Rewards
Automatically restake rewards:
final input = WithdrawInput(
delegationContract: delegationContract,
);
final tx = await controller.createTransactionForRedelegatingRewards(
account,
accountInfo.nonce,
input,
);
Parsing Outcomes
Use DelegationOutcomeParser to extract results:
final parser = DelegationOutcomeParser();
// Parse delegation contract creation
final tx = await provider.getTransaction(hash);
final results = parser.parseCreateNewDelegationContract(tx);
for (final result in results) {
print('Contract address: ${result.contractAddress}');
}
Complete Example
import 'package:abidock_mvx/abidock_mvx.dart';
void main() async {
final provider = GatewayNetworkProvider.mainnet();
final account = await Account.fromMnemonic('your mnemonic...');
final controller = DelegationController(
chainId: const ChainId.mainnet(),
gasLimitEstimator: GasEstimator(networkProvider: provider),
);
// Get account info
final accountInfo = await provider.getAccount(account.address);
// Choose a staking provider
final stakingProvider = Address.fromBech32('erd1qqqqqqqqqqqqqpgq...');
// Delegate 100 EGLD
final delegateTx = await controller.createTransactionForDelegating(
account,
accountInfo.nonce,
DelegateInput(
delegationContract: stakingProvider,
amount: Balance.fromEgld(100),
),
);
final hash = await provider.sendTransaction(delegateTx);
print('Delegated: $hash');
// Wait for rewards to accumulate...
// Claim rewards
final claimTx = await controller.createTransactionForClaimingRewards(
account,
accountInfo.nonce.increment(),
WithdrawInput(delegationContract: stakingProvider),
);
await provider.sendTransaction(claimTx);
print('Rewards claimed!');
}
Service Fee Reference
| Fee (basis points) | Percentage |
|---|---|
| 500 | 5% |
| 1000 | 10% |
| 1500 | 15% |
| 2000 | 20% |
| 10000 | 100% |
Important Notes
- Unbonding Period - Undelegated funds have a 10-day unbonding period
- Minimum Stake - Check provider's minimum delegation requirement
- Rewards - Rewards accumulate continuously and can be claimed anytime
- Validator Keys - Keep validator secret keys secure and backed up
- Slashing - Jailed nodes require unjail fee and may lose rewards