Module
Income
Distributes income to the holders of a denom and pays the claimable amounts attached to individual NFTs. It stores distribution state, never a schedule: the chain does not know a coupon calendar.
On-chain name: income · Consensus version 1
What the module owns
- Fungible balances use a reward-per-share accumulator. Funds go to a yield address, a single global index for the eligibility and reward pair moves, and a holder right becomes arithmetic against the balance.
- NFTs use an earmarked claimable. An administrator pushes a per-token amount and the claim is paid from the same yield address on the holder instruction.
- Accounting is lazy. There is no per-block sweep and no reward is lost because a holder did not claim.
- Every 10,000 blocks EndBlock checks that every yield pool holds at least the total unpaid liability for its reward denom, including holders who were never checkpointed and the active NFT earmarks.
- Caps: 1,000 streams and 50 NFT claims per message.
Key features
Reward-per-share for fungibles
Lazy accumulator: holders checkpoint when they send, claim, or checkpoint manually. No per-block iteration.
Per-NFT claimables
Admin pushes per-token amounts; holder claims on their schedule. Paid from the same yield pool.
Lazy, lossless accounting
No per-block sweep. A holder who never claims simply accumulates. No reward is ever lost to time.
Solvency invariant
Every 10,000 blocks EndBlock verifies yield pool ≥ total unpaid liability (including uncheckpointed holders and NFT earmarks).
Messages
- MsgCreateStream -- Create a fungible reward stream (yield address, reward denom, start/end).
- MsgFundStream -- Deposit reward funds into a stream's yield address.
- MsgCheckpoint / MsgBatchCheckpoint -- Advance holder's reward index to current global index.
- MsgClaimRewards / MsgBatchClaimRewards -- Claim accrued fungible rewards.
- MsgPushNFTclaimable -- Admin pushes per-NFT claimable amount (per-token, from yield address).
- MsgClaimNFTclaimable -- NFT holder claims their earmarked amount.
- MsgAddIncomeManager / MsgRemoveIncomeManager -- Admin management (gov or existing managers).
Queries
- Stream / Streams -- Stream configuration and state.
- HolderAccrual / HolderAccruals -- Holder's current accrued but unclaimed amount.
- NFTclaimable / NFTclaimables -- Earmarked claimables per token.
- YieldPool -- Current balance and unpaid liability of a yield pool.
- Params -- Module parameters (caps, solvency check interval).
Caps and limits
- Streams: ≤ 1,000
- NFT claims per message: ≤ 50
- Solvency check interval: every 10,000 blocks
- No per-block sweep -- lazy evaluation only
Integration guide
Distribute yield to holders
Push per-NFT claimables
Where the rules live
Income settles on every bank send -- it prepends its own send restriction so a holder's accrual is checkpointed against the pre-transfer balance. NFT market and Income both hook NFT burns: market refunds the seller deposit, Income releases the token's earmark back to the yield pool.