Blueprints
Token Blueprint
The Token Blueprint is a predesigned template that helps you quickly build a token in `ao`. It is a great way to get started and can be customized to fit your needs.
Unpacking the Token Blueprint
- Balances: The
Balances
array is used to store the token balances of the participants. - Info Handler: The
info
handler allows processes to retrieve the token parameters, like Name, Ticker, Logo, and Denomination. - Balance Handler: The
balance
handler allows processes to retrieve the token balance of a participant. - Balances Handler: The
balances
handler allows processes to retrieve the token balances of all participants. - Transfer Handler: The
transfer
handler allows processes to send tokens to another participant. - Mint Handler: The
mint
handler allows processes to mint new tokens.
How To Use:
- Open your preferred text editor.
- Open the Terminal.
- Start your
aos
process. - Type in
.load-blueprint token
Verify the Blueprint is Loaded:
Type in Handlers.list
to see the newly loaded handlers.
What's in the Token Blueprint:
--[[
This module implements the ao Standard Token Specification.
Terms:
Sender: the wallet or Process that sent the Message
It will first initialize the internal state, and then attach handlers,
according to the ao Standard Token Spec API:
- Info(): return the token parameters, like Name, Ticker, Logo, and Denomination
- Balance(Target?: string): return the token balance of the Target. If Target is not provided, the Sender
is assumed to be the Target
- Balances(): return the token balance of all participants
- Transfer(Target: string, Quantity: number): if the Sender has a sufficient balance, send the specified Quantity
to the Target. It will also issue a Credit-Notice to the Target and a Debit-Notice to the Sender
- Mint(Quantity: number): if the Sender matches the Process Owner, then mint the desired Quantity of tokens, adding
them the Processes' balance
]]
--
local json = require('json')
--[[
Initialize State
ao.id is equal to the Process.Id
]]
--
if not Balances then Balances = { [ao.id] = 100000000000000 } end
if Name ~= 'Points Coin' then Name = 'Points Coin' end
if Ticker ~= 'Points' then Ticker = 'PNTS' end
if Denomination ~= 10 then Denomination = 10 end
if not Logo then Logo = 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY' end
--[[
Add handlers for each incoming Action defined by the ao Standard Token Specification
]]
--
--[[
Info
]]
--
Handlers.add('info', Handlers.utils.hasMatchingTag('Action', 'Info'), function(msg)
ao.send(
{ Target = msg.From, Tags = { Name = Name, Ticker = Ticker, Logo = Logo, Denomination = tostring(Denomination) } })
end)
--[[
Balance
]]
--
Handlers.add('balance', Handlers.utils.hasMatchingTag('Action', 'Balance'), function(msg)
local bal = '0'
-- If not Target is provided, then return the Senders balance
if (msg.Tags.Target and Balances[msg.Tags.Target]) then
bal = tostring(Balances[msg.Tags.Target])
elseif Balances[msg.From] then
bal = tostring(Balances[msg.From])
end
ao.send({
Target = msg.From,
Tags = { Target = msg.From, Balance = bal, Ticker = Ticker, Data = json.encode(tonumber(bal)) }
})
end)
--[[
Balances
]]
--
Handlers.add('balances', Handlers.utils.hasMatchingTag('Action', 'Balances'),
function(msg) ao.send({ Target = msg.From, Data = json.encode(Balances) }) end)
--[[
Transfer
]]
--
Handlers.add('transfer', Handlers.utils.hasMatchingTag('Action', 'Transfer'), function(msg)
assert(type(msg.Tags.Recipient) == 'string', 'Recipient is required!')
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
if not Balances[msg.From] then Balances[msg.From] = 0 end
if not Balances[msg.Tags.Recipient] then Balances[msg.Tags.Recipient] = 0 end
local qty = tonumber(msg.Tags.Quantity)
assert(type(qty) == 'number', 'qty must be number')
if Balances[msg.From] >= qty then
Balances[msg.From] = Balances[msg.From] - qty
Balances[msg.Tags.Recipient] = Balances[msg.Tags.Recipient] + qty
--[[
Only send the notifications to the Sender and Recipient
if the Cast tag is not set on the Transfer message
]]
--
if not msg.Tags.Cast then
-- Send Debit-Notice to the Sender
ao.send({
Target = msg.From,
Tags = { Action = 'Debit-Notice', Recipient = msg.Tags.Recipient, Quantity = tostring(qty) }
})
-- Send Credit-Notice to the Recipient
ao.send({
Target = msg.Tags.Recipient,
Tags = { Action = 'Credit-Notice', Sender = msg.From, Quantity = tostring(qty) }
})
end
else
ao.send({
Target = msg.Tags.From,
Tags = { Action = 'Transfer-Error', ['Message-Id'] = msg.Id, Error = 'Insufficient Balance!' }
})
end
end)
--[[
Mint
]]
--
Handlers.add('mint', Handlers.utils.hasMatchingTag('Action', 'Mint'), function(msg, env)
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
if msg.From == env.Process.Id then
-- Add tokens to the token pool, according to Quantity
local qty = tonumber(msg.Tags.Quantity)
Balances[env.Process.Id] = Balances[env.Process.Id] + qty
else
ao.send({
Target = msg.Tags.From,
Tags = {
Action = 'Mint-Error',
['Message-Id'] = msg.Id,
Error = 'Only the Process Owner can mint new ' .. Ticker .. ' tokens!'
}
})
end
end)