This document provides a comprehensive overview of the LP (liqudity tokens) or token Standard by the Arflash Protocol. ArFlash protocol is dependent on this token standard.
Parameters Overview
Balances:
A table maintaining user balances. If not initialized, it is created automatically.
Allowances:
A table used for managing the allowances given by token holders. It initializes itself if absent.
Name:
The name of the token. Defaults to 'TOKENNAME' if not correctly defined.
Symbol (Ticker):
Represents the tick symbol of the token. Defaults to 'COIN' if not set appropriately.
Denomination:
Specifies the number of token units constituting a single whole unit for display. It defaults to 10.
Logo:
A URL linking to the token's logo image. It defaults to an empty string if not specified.
🗨️Info
local json = require('json')
if not Balances then Balances = {} end
if not Allowances then Allowances = {} end
if Name ~= 'TOKENNAME' then Name = 'TOKENNAME' end
-- Symbol
if Ticker ~= 'COIN' then Ticker = 'COIN' end
-- The number of the token that should be treated as a single unit when quantities and balances are displayed to users.
if Denomination ~= 10 then Denomination = 10 end
-- lOGO link
if not Logo then Logo = '' end
Check the balance of a specific account or the sender's account.
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
local targetAccount = msg.Tags.Target or msg.From
ao.send({
Target = msg.From,
Tags = { Target = targetAccount, Balance = bal, Ticker = Ticker, Data = json.encode(tonumber(bal)) }
})
end)
Check the balance of a specific account or the sender's account.
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
-- Debit-Notice message template, that is sent to the Sender of the transfer
local debitNotice = {
Target = msg.From,
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
}
-- 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
}
-- 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
ao.send(debitNotice)
ao.send(creditNotice)
end
else
ao.send({
Target = msg.Tags.From,
Tags = { Action = 'Transfer-Error', ['Message-Id'] = msg.Id, Error = 'Insufficient Balance!' }
})
end
end)
Transfer tokens from an owner's account to a recipient's account using the allowance system.
Handlers.add('transferFrom', Handlers.utils.hasMatchingTag('Action', 'TransferFrom'), function(msg)
assert(type(msg.Tags.from) == 'string', 'From is required!')
assert(type(msg.Tags.to) == 'string', 'To is required!')
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
-- Convert quantity to number
local from = msg.Tags.from
local to = msg.Tags.to
local qty = tonumber(msg.Tags.Quantity)
assert(qty ~= nil, 'Quantity must be a valid number!')
assert(qty > 0, 'Quantity must be greater than zero!')
-- Ensure balances and allowances tables exist
if not Balances[from] then Balances[from] = 0 end
if not Balances[to] then Balances[to] = 0 end
if not Allowances[from] then Allowances[from] = {} end
-- Check allowance and balances
local allowance = Allowances[from][msg.From] or 0
assert(allowance >= qty, 'Allowance exceeded!')
assert(Balances[from] >= qty, 'Insufficient Balance!')
-- Perform transfer
Balances[from] = Balances[from] - qty
Balances[to] = Balances[to] + qty
Allowances[from][msg.From] = allowance - qty
-- Send success notifications
ao.send({
Target = msg.From,
Tags = {
Action = 'TransferFrom-Notice',
From = from,
To = to,
Quantity = tostring(qty)
}
})
ao.send({
Target = from,
Tags = {
Action = 'Debit-Notice',
To = to,
Quantity = tostring(qty),
Data = "Your tokens were transferred to " .. to
}
})
ao.send({
Target = to,
Tags = {
Action = 'Credit-Notice',
From = from,
Quantity = tostring(qty),
Data = "You received tokens from " .. from
}
})
end)
Transfer tokens on behalf of an owner using the allowance.