@startuml 'https://plantuml.com/sequence-diagram title: Delegating (currently undelegated funds delegator) participant "msgServer (staking)" participant "keeper (staking)" as keeper participant validator participant keeper.bankKeeper participant vestingAccount participant ctx.EventManager database store "msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator, tokenSrc := Unbonded) alt exchange rate is invalid (tokens in validator is 0) keeper --> "msgServer (staking)" : error end alt perform a new delegation keeper -> keeper : delegation := create delegation object keeper -> keeper : BeforeDelegationCreated hook note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go else delegation exists, more tokens being added keeper -> keeper : BeforeDelegationModified hook note left: withdraw current delegation rewards (and increment period) end alt delegating from an account (subtractTokens == true) keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule group DelegateCoinsFromAccountToModule function keeper.bankKeeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule keeper.bankKeeper -> keeper.bankKeeper : DelegateCoins group DelegateCoins function keeper.bankKeeper --> keeper.bankKeeper : Check the delegator has enough balances of all tokens delegated keeper.bankKeeper --> keeper.bankKeeper : Track delegation (register that it exists to keep track of it) alt validator is currently bonded keeper.bankKeeper --> store : Transfer tokens from delegator to BondedTokensPool. else validator is currently unbonded or unbonding keeper.bankKeeper --> store : Transfer tokens from delegator to NotBondedTokensPool. end group trackDelegation function keeper.bankKeeper -> keeper.bankKeeper : trackDelegation alt delegator is a vesting account keeper.bankKeeper -> vestingAccount : keep track of this delegation end end end end keeper <-- keeper.bankKeeper : nil (success) else moving tokens between pools (subtractTokens == false) alt delegator tokens are not bonded but validator is bonded keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(notBondedPool, bondedPool, coins) else delegator tokens are bonded but validator is not bonded keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(bondedPool, notBondedPool, coins) end group SendCoins function keeper.bankKeeper -> keeper.bankKeeper : SendCoins keeper.bankKeeper -> ctx.EventManager : Emit TransferEvent(to, from, amount) alt amount of spendable (balance - locked) coins too low keeper <-- keeper.bankKeeper : error end keeper.bankKeeper -> store : subtract balance from sender keeper.bankKeeper -> store : add balance to recipient end end keeper -> validator : AddTokensFromDel validator -> validator : calculate number of shares to issue note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) validator -> validator : add delegated tokens to validator keeper <-- validator : validator, addedShares keeper -> store : update validator state keeper -> keeper: calculate new validator's power note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18) alt validator is not jailed keeper -> store : update validator's power in power index note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. end keeper -> keeper : AfterDelegationModified hook note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. "msgServer (staking)" <-- keeper : newShares (ignored by Delegate function) "msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress) "msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress) "msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom) @enduml