🦁ArFlash Token Specification
Token Configuration Documentation
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
🖐️Handlers
Info Handler
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)
Usage :
Send({ Target = ao.id, Action = "Info" })
Retrieving Data
Inbox[#Inbox].Tags
Balance Handler
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.
Usage
Send({ Target = ao.id, Tags = { Action = "Balance", Target = 'wallet or processid' }})
Send({ Target = ao.id, Tags = { Action = "Balance" } })
Retrieving Data
Inbox[#Inbox].Tags
Balances Handler
Retrieve the balances of all accounts.
Handlers.add('balances', Handlers.utils.hasMatchingTag('Action', 'Balances'),
function(msg) ao.send({ Target = msg.From, Data = json.encode(Balances) }) end)
Usage :
Send({ Target = ao.id, Tags = { Action = "Balances" } })
Inbox[#Inbox].Data
Transfer Handler
Transfer tokens to another wallet or process ID.
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 to another wallet or process ID.
Send({ Target = ao.id, Tags = { Action = "Transfer", Recipient = 'another wallet or processid', Quantity = '10000' }})
Notifications:
Debit Notice to the sender:
{ Target = "sender_wallet_or_processid", Action = "Debit-Notice", Recipient = "recipient_wallet_or_processid", Quantity = "10000" }
Credit Notice to the recipient:
{ Target = "recipient_wallet_or_processid", Action = "Credit-Notice", Sender = "sender_wallet_or_processid", Quantity = "10000" }
Allowance Handler
Check the allowance set for a spender by the owner.
Handlers.add('allowance', Handlers.utils.hasMatchingTag('Action', 'Allowance'), function(msg)
local allowance = '0'
if Allowances[msg.From] and Allowances[msg.From][msg.Tags.Spender] then
allowance = tostring(Allowances[msg.From][msg.Tags.Spender])
end
ao.send({
Target = msg.From,
Tags = { Owner = msg.From, Spender = msg.Tags.Spender, Allowance = allowance }
})
end)
Check the allowance set for a spender by the owner.
Send({ Target = ao.id, Tags = { Action = "Allowance", Spender = 'spender wallet or processid' }})
Inbox[#Inbox].Tags.Allowance
Approve Handler
Set the allowance for a spender.
Handlers.add('approve', Handlers.utils.hasMatchingTag('Action', 'Approve'), function(msg)
assert(type(msg.Tags.Spender) == 'string', 'Spender is required!')
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
if not Allowances[msg.From] then Allowances[msg.From] = {} end
local qty = tonumber(msg.Tags.Quantity)
assert(type(qty) == 'number', 'qty must be number')
Allowances[msg.From][msg.Tags.Spender] = qty
ao.send({
Target = msg.From,
Tags = { Action = 'Approval', Spender = msg.Tags.Spender, Quantity = tostring(qty) }
})
end)
Send({ Target = ao.id, Tags = { Action = "Approve", Spender = 'spender wallet or processid', Quantity = '5000' }})
Inbox[#Inbox].Tags
TransferFrom handler
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.
Send({
Target = ao.id,
Tags = {
Action = "TransferFrom",
from = "from_wallet_or_processid",
to = "to_wallet_or_processid",
Quantity = "3000"
}
})
Minting Handler
Mint new tokens and add them to the sender's balance.
Handlers.add('mint', Handlers.utils.hasMatchingTag('Action', 'Mint'), function(msg)
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
local qty = tonumber(msg.Tags.Quantity)
assert(type(qty) == 'number', 'qty must be number')
if msg.From == env.Process.Id then
-- Add tokens to the token pool, according to Quantity
Balances[msg.From] = Balances[msg.From] + qty
ao.send({
Target = msg.From,
Tags = { Action = 'Mint-Notice', Quantity = tostring(qty), Balance = tostring(Balances[msg.From]) }
})
else
ao.send({
Target = msg.From,
Tags = { Action = 'Mint-Error', ['Message-Id'] = msg.Id, Error = 'Unauthorized minting attempt!' }
})
end
end)
Mint new tokens to the token pool.
Send({ Target = ao.id, Tags = { Action = "Mint", Quantity = "1000" } })
Burn Handler
Burn tokens from the sender's account.
Handlers.add('burn', Handlers.utils.hasMatchingTag('Action', 'Burn'), function(msg)
assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')
local qty = tonumber(msg.Tags.Quantity)
assert(type(qty) == 'number', 'qty must be number')
if msg.From == env.Process.Id then
if not Balances[msg.From] then Balances[msg.From] = 0 end
if Balances[msg.From] >= qty then
Balances[msg.From] = Balances[msg.From] - qty
ao.send({
Target = msg.From,
Tags = { Action = 'Burn-Notice', Quantity = tostring(qty), Balance = tostring(Balances[msg.From]) }
})
else
ao.send({
Target = msg.From,
Tags = { Action = 'Burn-Error', ['Message-Id'] = msg.Id, Error = 'Insufficient Balance!' }
})
end
else
ao.send({
Target = msg.From,
Tags = { Action = 'Burn-Error', ['Message-Id'] = msg.Id, Error = 'Unauthorized burning attempt!' }
})
end
end)
Send({ Target = ao.id, Tags = { Action = "Burn", Quantity = '2000' }})
Last updated
Was this helpful?