Minting Delegations
Minting delegations allow a delegate to instruct their validator node to automate the minting of rewards on behalf of an external party (the beneficiary) hosted on the same validator node. The delegate can be any party onboarded to the validator node’s wallet (e.g., the validator operator party, but other internal parties are also possible). This is useful to automate the reward collection for external parties.
Overview
A minting delegation grants a delegate party the authority to:
Mint reward coupons on behalf of a beneficiary party
Auto-merge amulets for the beneficiary (up to the configured limit)
The following reward coupon types may be minted through a delegation:
Note
To mint ValidatorRewardCoupon, the beneficiary must first create a ValidatorRight.
The delegation has the following key properties:
Property |
Description |
|---|---|
Beneficiary |
The external party on whose behalf minting is performed |
Delegate |
The internal party authorized to perform minting operations |
Expiration |
The time after which the delegation is no longer valid |
Amulet merge limit |
The number of amulets to keep after auto-merging |
Automation
When a minting delegation is active, the validator node runs automation
(MintingDelegationCollectRewardsTrigger) for the beneficiary party that periodically:
Checks for reward coupons owned by the beneficiary that are eligible for minting
Collects and mints these rewards on behalf of the beneficiary
Merges the beneficiary’s amulets when the count exceeds twice the configured merge limit
For the automation to run successfully, the following conditions must be met:
The delegate must be a party onboarded to the validator node’s wallet (e.g., the validator operator party, or another internal party with its own user account)
The delegation must not be expired
The beneficiary must be hosted on the validator node in at least observer mode
The beneficiary should not be onboarded to the wallet app, as otherwise the delegated automation contends with the built-in automation of the wallet app
The beneficiary must have reward coupons or amulets that need processing
Note that minting delegations count towards the max 200 Splice wallet parties limit.
The automation submits transactions as the delegate party. Transaction costs are paid from the validator node’s traffic balance.
Note
The amulet merge limit controls automatic consolidation of the beneficiary’s amulets: when the number of amulets exceeds twice the limit, the smallest amulets are merged to maintain exactly the configured number.
Managing Minting Delegations
The minting delegation workflow consists of the following steps:
Proposal Creation: The beneficiary creates a
MintingDelegationProposalspecifying the delegate, expiration date, and amulet merge limit. This is typically done via the Ledger API.Proposal Acceptance: The delegate reviews and accepts (or rejects) the proposal through the wallet UI. Upon acceptance, an active
MintingDelegationcontract is created.Withdrawal: When the delegation is no longer needed, the delegate can withdraw it through the wallet UI. This terminates the delegation and stops the automation from minting rewards for the beneficiary.
Using the Delegations Tab
Delegates can manage minting delegations through the Delegations tab in the wallet UI. This tab displays two sections:
Proposed Delegations
The Proposed section shows all pending MintingDelegationProposal contracts where
the current user is the designated delegate.
For each proposal, the delegate can:
Accept: Approve the delegation request. This creates an active minting delegation. If a delegation already exists for the same beneficiary, accepting a new proposal will replace the existing delegation.
Reject: Decline the delegation request. This archives the proposal.
Note
The Accept button is disabled if the beneficiary is not yet hosted on the validator node. The beneficiary must be hosted before a delegation can be accepted.
Active Delegations
The Active section shows all current MintingDelegation contracts where the current
user is the delegate.
For each active delegation, the delegate can:
Withdraw: Terminate the delegation. This archives the delegation contract and stops the automation from minting rewards for the beneficiary.
Replacing Delegations
When a delegate accepts a proposal for a beneficiary that already has an active delegation, a confirmation dialog will appear showing:
The current delegation’s Merge Threshold and Expiration values
The new proposal’s Merge Threshold and Expiration values
Accepting the proposal will automatically replace the existing delegation with the new one. This allows beneficiaries to update their delegation parameters (such as extending the expiration date) without the delegate having to manually withdraw the old delegation first.
Tip
To change a delegation’s expiration or amulet merge limit, the beneficiary should create a new proposal with the updated values. When the delegate accepts it, the existing delegation will be replaced.
Creating Proposals via Ledger API
External parties (beneficiaries) who wish to delegate minting to a delegate party
must create a MintingDelegationProposal contract. Since beneficiaries typically do not
have access to the wallet UI, they can create proposals programmatically using the
Canton Ledger API.
Prerequisites
Before creating a proposal, the beneficiary must have:
Hosting on the validator node: The beneficiary party must be hosted on the validator node where they want to delegate minting.
Ledger API access: Authenticated access to the validator’s Ledger API endpoint, including:
The Ledger API URL (e.g.,
https://<validator-host>:<port>)Valid authentication credentials (OAuth2 token or other configured auth method)
The beneficiary’s party ID
The delegate’s party ID: The delegate is typically the validator operator party, but could be another internal party on the validator node.
The DSO party ID: The DSO party ID for the network.
Example: Creating a Proposal
The MintingDelegationProposal contract contains a delegation field with the same
properties as described in the Overview section above (beneficiary, delegate, expiration,
and amulet merge limit), plus the DSO party ID.
All interaction works via the JSON Ledger API (see its OpenAPI definition). Check out the Authentication docs for more information on how to authenticate the requests.
To create the proposal, submit a create command via the Ledger API
command submission endpoint.
First, set up the required environment variables:
export LEDGER_API_URL="https://validator.example.com:5003"
export TOKEN="your-auth-token"
export BENEFICIARY_PARTY="beneficiary::1220abcd..."
export DELEGATE_PARTY="validator_operator::1220efgh..."
export DSO_PARTY="DSO::1220ijkl..."
export EXPIRES_AT="2025-12-31T23:59:59Z"
# This could be created by
# export EXPIRES_AT="$(date -u -d '+1 year' '+%Y-%m-%dT%H:%M:%SZ')"
export AMULET_MERGE_LIMIT=10
Then create the proposal using curl:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-raw '{
"commands": [
{
"CreateCommand": {
"templateId": "#splice-wallet:Splice.Wallet.MintingDelegation:MintingDelegationProposal",
"createArguments": {
"delegation": {
"beneficiary": "'"$BENEFICIARY_PARTY"'",
"delegate": "'"$DELEGATE_PARTY"'",
"dso": "'"$DSO_PARTY"'",
"expiresAt": "'"$EXPIRES_AT"'",
"amuletMergeLimit": '"$AMULET_MERGE_LIMIT"'
}
}
}
}
]
}' \
"$LEDGER_API_URL/v2/commands"
See the MintingDelegationProposal template source code for the complete Daml definition.
Monitoring Proposal Status
The beneficiary can monitor their proposal status by querying for active
MintingDelegationProposal contracts via the Ledger API’s
active contracts endpoint.
To query for pending proposals:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-raw '{
"filter": {
"filtersByParty": {
"'"$BENEFICIARY_PARTY"'": {
"filters": [
{
"inclusive": {
"templateFilters": [
{"templateId": "#splice-wallet:Splice.Wallet.MintingDelegation:MintingDelegationProposal"}
]
}
}
]
}
}
}
}' \
"$LEDGER_API_URL/v2/state/active-contracts"
Once accepted, query for the active MintingDelegation contract to confirm the
delegation is active:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-raw '{
"filter": {
"filtersByParty": {
"'"$BENEFICIARY_PARTY"'": {
"filters": [
{
"inclusive": {
"templateFilters": [
{"templateId": "#splice-wallet:Splice.Wallet.MintingDelegation:MintingDelegation"}
]
}
}
]
}
}
}
}' \
"$LEDGER_API_URL/v2/state/active-contracts"
Withdrawing a Proposal
If the beneficiary wants to withdraw their proposal before it is accepted or rejected,
they can exercise the MintingDelegationProposal_Withdraw choice on their proposal
contract via the Ledger API’s
exercise endpoint.
First, obtain the contract ID of the proposal from the active contracts query above, then exercise the withdrawal choice:
export PROPOSAL_CONTRACT_ID="00abcd1234..."
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data-raw '{
"commands": [
{
"ExerciseCommand": {
"templateId": "#splice-wallet:Splice.Wallet.MintingDelegation:MintingDelegationProposal",
"contractId": "'"$PROPOSAL_CONTRACT_ID"'",
"choice": "MintingDelegationProposal_Withdraw",
"choiceArgument": {}
}
}
]
}' \
"$LEDGER_API_URL/v2/commands"
Security Considerations
When managing minting delegations, delegates should consider:
Verify the beneficiary: Before accepting a delegation, ensure you recognize and trust the beneficiary party. The Party ID should match the expected party.
Traffic costs: Verify that the validator operator is willing to pay the cost of minting transactions from the validator node’s traffic balance.
Hosting status: Only accept delegations from hosted parties. The UI enforces this by disabling the Accept button for non-hosted beneficiaries.
Monitor active delegations: Periodically review active delegations and withdraw any that are no longer needed or authorized.
Comments