Skip to main content

Staking and Delegation

The Python SDK covers both sides of staking: operating a pool and delegating to one. The same workflow exists for the command line (concepts: pledge, cost per block, margin ratio, decommission key), Go, JavaScript (delegations only), and Rust.

The reward split: the staker receives cost_per_block + margin × (block_reward − cost_per_block); delegators share the remainder proportionally to their stake.

Creating a pool

from mintlayer.wallet import Amount, Client, CreatePoolParams

wc = Client("http://127.0.0.1:3034")

result = wc.create_stake_pool(
CreatePoolParams(
account=0,
amount=Amount(atoms="40000000000000"), # minimum pledge
cost_per_block=Amount(atoms="100000000"), # flat fee per block
margin_ratio_per_thousand="100", # 10% staker cut
decommission_address=decommission_addr,
# staker_address and vrf_public_key default to wallet-managed keys
)
)
print(f"tx id: {result.tx_id}")

margin_ratio_per_thousand is the staker's cut of block rewards expressed in thousandths as a string: "100" = 10%, "50" = 5%, "1000" = 100%. The pool ID can be predicted before broadcasting with wasm.get_pool_id.

Operating the pool

wc.start_staking(0)  # begin producing blocks

status = wc.get_staking_status(0) # Staking | NotStaking
wc.stop_staking(0) # stops production; the pool stays alive

pools = wc.list_owned_pools(0)
balance = wc.get_pool_balance(0, "mpool1...")

wc.decommission_stake_pool(
DecommissionParams(
account=0,
pool_id="mpool1...",
output_address=return_addr,
)
)

stop_staking pauses block production without touching delegations or staked funds; decommission_stake_pool shuts the pool down and returns the pledge to output_address after maturity. Delegators must withdraw separately.

Delegating

Create the delegation record first, then fund it (waiting for the creation transaction to confirm in between):

from mintlayer.wallet import Amount, CreateDelegationParams, DelegateParams

create_result = wc.create_delegation(
CreateDelegationParams(
account=0,
address=owner_addr, # address that can withdraw funds
pool_id="mpool1...",
)
)
print(f"delegation id: {create_result.delegation_id}")

wc.delegate_staking(
DelegateParams(
account=0,
amount=Amount(atoms="10000000000000"), # 100 ML
delegation_id=create_result.delegation_id,
)
)

Multiple delegate_staking transactions to the same delegation increase the stake. Withdrawals arrive after the consensus lock period:

from mintlayer.wallet import WithdrawParams

wc.withdraw_from_delegation(
WithdrawParams(
account=0,
address=recipient_addr,
amount=Amount(atoms="5000000000000"), # 50 ML
delegation_id="mdelg1...",
)
)

delegations = wc.list_delegations(0)

Reading state from the indexer

pool = idx.get_pool("mpool1...")
print(f"staker: {pool.staker_balance.decimal} delegations: {pool.delegations_balance.decimal}")

delegation = idx.get_delegation("mdelg1...")
print(f"next nonce: {delegation.next_nonce}")

Manual transaction building

The wasm module encodes pool and delegation outputs/inputs for full-custody flows: encode_output_create_stake_pool with encode_stake_pool_data, encode_output_delegate_staking, encode_input_for_withdraw_from_delegation (nonce from the indexer), and get_pool_id / get_delegation_id to predict ids from the inputs. See Staking in the SDK reference for the full encoders.