Blueprints
Staking Blueprint
The Staking Blueprint is a predesigned template that helps you quickly build a staking system in ao
. It is a great way to get started and can be customized to fit your needs.
Prerequisites
The Staking Blueprint requires the Token Blueprint to be loaded, first.
Unpacking the Staking Blueprint
- Stakers: The
Stakers
array is used to store the staked tokens of the participants. - Unstaking: The
Unstaking
array is used to store the unstaking requests of the participants. - Stake Action Handler: The
stake
handler allows processes to stake tokens. When a process sends a message with the tagAction = "Stake"
, the handler will add the staked tokens to theStakers
array and send a message back to the process confirming the staking. - Unstake Action Handler: The
unstake
handler allows processes to unstake tokens. When a process sends a message with the tagAction = "Unstake"
, the handler will add the unstaking request to theUnstaking
array and send a message back to the process confirming the unstaking. - Finalization Handler: The
finalize
handler allows processes to finalize the staking process. When a process sends a message with the tagAction = "Finalize"
, the handler will process the unstaking requests and finalize the staking process.
How To Use:
- Open your preferred text editor.
- Open the Terminal.
- Start your
aos
process. - Type in
.load-blueprint staking
Verify the Blueprint is Loaded:
Type in Handlers.list
to see the newly loaded handlers.
What's in the Staking Blueprint:
Stakers = Stakers or {}
Unstaking = Unstaking or {}
-- Stake Action Handler
Handlers.stake = function(msg)
local quantity = tonumber(msg.Tags.Quantity)
local delay = tonumber(msg.Tags.UnstakeDelay)
local height = tonumber(msg['Block-Height'])
assert(Balances[msg.From] and Balances[msg.From] >= quantity, "Insufficient balance to stake")
Balances[msg.From] = Balances[msg.From] - quantity
Stakers[msg.From] = Stakers[msg.From] or {}
Stakers[msg.From].amount = (Stakers[msg.From].amount or 0) + quantity
Stakers[msg.From].unstake_at = height + delay
end
-- Unstake Action Handler
Handlers.unstake = function(msg)
local quantity = tonumber(msg.Tags.Quantity)
local stakerInfo = Stakers[msg.From]
assert(stakerInfo and stakerInfo.amount >= quantity, "Insufficient staked amount")
stakerInfo.amount = stakerInfo.amount - quantity
Unstaking[msg.From] = {
amount = quantity,
release_at = stakerInfo.unstake_at
}
end
-- Finalization Handler
local finalizationHandler = function(msg)
local currentHeight = tonumber(msg['Block-Height'])
-- Process unstaking
for address, unstakeInfo in pairs(Unstaking) do
if currentHeight >= unstakeInfo.release_at then
Balances[address] = (Balances[address] or 0) + unstakeInfo.amount
Unstaking[address] = nil
end
end
end
-- wrap function to continue handler flow
local function continue(fn)
return function (msg)
local result = fn(msg)
if (result) == -1 then
return 1
end
return result
end
end
-- Registering Handlers
Handlers.add("stake",
continue(Handlers.utils.hasMatchingTag("Action", "Stake")), Handlers.stake)
Handlers.add("unstake",
continue(Handlers.utils.hasMatchingTag("Action", "Unstake")), Handlers.unstake)
-- Finalization handler should be called for every message
Handlers.add("finalize", function (msg) return -1 end, finalizationHandler)