Skip to content

Commit

Permalink
fix(cookbook): update token blueprint code with latest version #191
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrain99 committed Sep 3, 2024
1 parent a2dcdc7 commit 2ad08e9
Showing 1 changed file with 114 additions and 47 deletions.
161 changes: 114 additions & 47 deletions src/guides/aos/blueprints/token.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The Token Blueprint is a predesigned template that helps you quickly build a tok

- **Mint Handler**: The `mint` handler allows processes to mint new tokens.

- **Total Supply Handler**: The `totalSupply` handler allows processes to retrieve the total supply of the token.

- **Burn Handler**: The `burn` handler allows processes to burn tokens.

### How To Use:

1. Open your preferred text editor.
Expand All @@ -31,7 +35,6 @@ Type in `Handlers.list` to see the newly loaded handlers.

```lua
local bint = require('.bint')(256)
local ao = require('ao')
--[[
This module implements the ao Standard Token Specification.
Expand All @@ -57,21 +60,43 @@ local ao = require('ao')
--
local json = require('json')

--[[
utils helper functions to remove the bint complexity.
]]
--


local utils = {
add = function(a, b)
return tostring(bint(a) + bint(b))
end,
subtract = function(a, b)
return tostring(bint(a) - bint(b))
end,
toBalanceValue = function(a)
return tostring(bint(a))
end,
toNumber = function(a)
return bint.tonumber(a)
end
}


--[[
Initialize State
ao.id is equal to the Process.Id
]]
--
if not Balances then Balances = { [ao.id] = tostring(bint(10000 * 1e12)) } end

if Name ~= 'Points Coin' then Name = 'Points Coin' end
Variant = "0.0.3"

if Ticker ~= 'Points' then Ticker = 'PNTS' end

if Denomination ~= 12 then Denomination = 12 end

if not Logo then Logo = 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY' end
-- token should be idempotent and not change previous state updates
Denomination = Denomination or 12
Balances = Balances or { [ao.id] = utils.toBalanceValue(10000 * 10 ^ Denomination) }
TotalSupply = TotalSupply or utils.toBalanceValue(10000 * 10 ^ Denomination)
Name = Name or 'Points Coin'
Ticker = Ticker or 'PNTS'
Logo = Logo or 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY'

--[[
Add handlers for each incoming Action defined by the ao Standard Token Specification
Expand All @@ -82,9 +107,8 @@ if not Logo then Logo = 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY' end
Info
]]
--
Handlers.add('info', Handlers.utils.hasMatchingTag('Action', 'Info'), function(msg)
ao.send({
Target = msg.From,
Handlers.add('info', "Info", function(msg)
msg.reply({
Name = Name,
Ticker = Ticker,
Logo = Logo,
Expand All @@ -96,21 +120,24 @@ end)
Balance
]]
--
Handlers.add('balance', Handlers.utils.hasMatchingTag('Action', 'Balance'), function(msg)
Handlers.add('balance', "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
-- If not Recipient is provided, then return the Senders balance
if (msg.Tags.Recipient) then
if (Balances[msg.Tags.Recipient]) then
bal = Balances[msg.Tags.Recipient]
end
elseif msg.Tags.Target and Balances[msg.Tags.Target] then
bal = Balances[msg.Tags.Target]
elseif Balances[msg.From] then
bal = Balances[msg.From]
end

ao.send({
Target = msg.From,
msg.reply({
Balance = bal,
Ticker = Ticker,
Account = msg.Tags.Target or msg.From,
Account = msg.Tags.Recipient or msg.From,
Data = bal
})
end)
Expand All @@ -119,53 +146,66 @@ end)
Balances
]]
--
Handlers.add('balances', Handlers.utils.hasMatchingTag('Action', 'Balances'),
function(msg) ao.send({ Target = msg.From, Data = json.encode(Balances) }) end)
Handlers.add('balances', "Balances",
function(msg) msg.reply({ Data = json.encode(Balances) }) end)

--[[
Transfer
]]
--
Handlers.add('transfer', Handlers.utils.hasMatchingTag('Action', 'Transfer'), function(msg)
Handlers.add('transfer', "Transfer", function(msg)
assert(type(msg.Recipient) == 'string', 'Recipient is required!')
assert(type(msg.Quantity) == 'string', 'Quantity is required!')
assert(bint.__lt(0, bint(msg.Quantity)), 'Quantity must be greater than 0')

if not Balances[msg.From] then Balances[msg.From] = "0" end
if not Balances[msg.Recipient] then Balances[msg.Recipient] = "0" end

local qty = bint(msg.Quantity)
local balance = bint(Balances[msg.From])
if bint.__le(qty, balance) then
Balances[msg.From] = tostring(bint.__sub(balance, qty))
Balances[msg.Recipient] = tostring(bint.__add(Balances[msg.Recipient], qty))
if bint(msg.Quantity) <= bint(Balances[msg.From]) then
Balances[msg.From] = utils.subtract(Balances[msg.From], msg.Quantity)
Balances[msg.Recipient] = utils.add(Balances[msg.Recipient], msg.Quantity)

--[[
Only send the notifications to the Sender and Recipient
if the Cast tag is not set on the Transfer message
]]
--
if not msg.Cast then
-- Send Debit-Notice to the Sender
ao.send({
Target = msg.From,
-- Debit-Notice message template, that is sent to the Sender of the transfer
local debitNotice = {
Action = 'Debit-Notice',
Recipient = msg.Recipient,
Quantity = tostring(qty),
Data = Colors.gray .. "You transferred " .. Colors.blue .. msg.Quantity .. Colors.gray .. " to " .. Colors.green .. msg.Recipient .. Colors.reset
})
-- Send Credit-Notice to the Recipient
ao.send({
Quantity = msg.Quantity,
Data = Colors.gray ..
"You transferred " ..
Colors.blue .. msg.Quantity .. Colors.gray .. " to " .. Colors.green .. msg.Recipient .. Colors.reset
}
-- Credit-Notice message template, that is sent to the Recipient of the transfer
local creditNotice = {
Target = msg.Recipient,
Action = 'Credit-Notice',
Sender = msg.From,
Quantity = tostring(qty),
Data = Colors.gray .. "You received " .. Colors.blue .. msg.Quantity .. Colors.gray .. " from " .. Colors.green .. msg.From .. Colors.reset
})
Quantity = msg.Quantity,
Data = Colors.gray ..
"You received " ..
Colors.blue .. msg.Quantity .. Colors.gray .. " from " .. Colors.green .. msg.From .. Colors.reset
}

-- Add forwarded tags to the credit and debit notice messages
for tagName, tagValue in pairs(msg) do
-- Tags beginning with "X-" are forwarded
if string.sub(tagName, 1, 2) == "X-" then
debitNotice[tagName] = tagValue
creditNotice[tagName] = tagValue
end
end

-- Send Debit-Notice and Credit-Notice
msg.reply(debitNotice)
Send(creditNotice)
end
else
ao.send({
Target = msg.From,
msg.reply({
Action = 'Transfer-Error',
['Message-Id'] = msg.Id,
Error = 'Insufficient Balance!'
Expand All @@ -177,27 +217,54 @@ end)
Mint
]]
--
Handlers.add('mint', Handlers.utils.hasMatchingTag('Action', 'Mint'), function (msg)
Handlers.add('mint', "Mint", function(msg)
assert(type(msg.Quantity) == 'string', 'Quantity is required!')
assert(bint.__lt(0, msg.Quantity), 'Quantity must be greater than zero!')
assert(bint(0) < bint(msg.Quantity), 'Quantity must be greater than zero!')

if not Balances[ao.id] then Balances[ao.id] = "0" end

if msg.From == ao.id then
-- Add tokens to the token pool, according to Quantity
Balances[msg.From] = tostring(bint.__add(Balances[Owner], msg.Quantity))
ao.send({
Target = msg.From,
Balances[msg.From] = utils.add(Balances[msg.From], msg.Quantity)
TotalSupply = utils.add(TotalSupply, msg.Quantity)
msg.reply({
Data = Colors.gray .. "Successfully minted " .. Colors.blue .. msg.Quantity .. Colors.reset
})
else
ao.send({
Target = msg.From,
msg.reply({
Action = 'Mint-Error',
['Message-Id'] = msg.Id,
Error = 'Only the Process Owner can mint new ' .. Ticker .. ' tokens!'
Error = 'Only the Process Id can mint new ' .. Ticker .. ' tokens!'
})
end
end)

--[[
Total Supply
]]
--
Handlers.add('totalSupply', "Total-Supply", function(msg)
assert(msg.From ~= ao.id, 'Cannot call Total-Supply from the same process!')

msg.reply({
Action = 'Total-Supply',
Data = TotalSupply,
Ticker = Ticker
})
end)

--[[
Burn
]] --
Handlers.add('burn', 'Burn', function(msg)
assert(type(msg.Quantity) == 'string', 'Quantity is required!')
assert(bint(msg.Quantity) <= bint(Balances[msg.From]), 'Quantity must be less than or equal to the current balance!')

Balances[msg.From] = utils.subtract(Balances[msg.From], msg.Quantity)
TotalSupply = utils.subtract(TotalSupply, msg.Quantity)

msg.reply({
Data = Colors.gray .. "Successfully burned " .. Colors.blue .. msg.Quantity .. Colors.reset
})
end)
```

0 comments on commit 2ad08e9

Please sign in to comment.