Status: DRAFT-1
Targeting Network: ao.TN.1
This specification describes the necessary message handlers and functionality required for a standard ao token process. Implementations of this standard typically offer users the ability control a transferrable asset, whose scarcity is maintained by the process.
Each compliant process will likely implement a ledger of balances in order to encode ownership of the asset that the process represents. Compliant processes have a set of methods that allow for the modification of this ledger, typically with safe-guards to ensure the scarcity of ownership of the token represented by the process.
Additionally, this specification describes a 'subledger' process type which, when implemented, offers the ability to split move a number of the tokens from the parent into a child process that implements the same token interface specification. If the From-Module
of the subledger process is trusted by the participants, these subledgers can be used to transact in the 'source' token, without directly exchanging messages with it. This allows participants to use the tokens from a process, even if that process is congested. Optionally, if the participants trust the Module
a subledger process is running, they are able to treat balances across these processes as fungible. The result of this is that an arbitrary numbers of parallel processes โ and thus, transactions โ can be processed by a single token at any one time.
A specification-compliant token process responds to a number of different forms of messages, with each form specified in an Action
tag. The full set of Action
messages that the token must support are as follows:
Name | Description | Read-Only |
---|---|---|
Balance | get the balance of an identifer |
Image Not Showing
Possible Reasons
|
Balances | get a list of all ledger/account balances |
Image Not Showing
Possible Reasons
|
Transfer | send 1 or more units from the callers balance to one or move targets with the option to notify targets |
Image Not Showing
Possible Reasons
|
Register | spawn a sub-ledger process, if process is the root token |
Image Not Showing
Possible Reasons
|
Mint | if the ledger process is the root and you would like to increase token supply |
Image Not Showing
Possible Reasons
|
In the remainder of this section the tags necessary to spawn a compliant token process, along with the form of each of the Action
messages and their results is described.
Every compliant token process must carry the following immutable parameters upon its spawning message:
Tag | Description | Optional? |
---|---|---|
Name | The title of the token, as it should be displayed to users. |
Image Not Showing
Possible Reasons
|
Ticker | A suggested shortened name for the token, such that it can be referenced quickly. |
Image Not Showing
Possible Reasons
|
Logo | An image that applications may deserire to show next to the token, in order to make it quickly visually identifiable. |
Image Not Showing
Possible Reasons
|
Denomination | The number of the token that should be treated as a single unit when quantities and balances are displayed to users. |
Image Not Showing
Possible Reasons
|
Returns the balance of a target, if a target is not supplied then the balance of the sender of the message must be returned.
Example Action
message:
send({
Target = "TokenProcess",
Tags = {
Action = "Balance",
Target = "{IDENTIFIER}"
}
})
Example response message:
TODO
Returns the balance of all participants in the token.
send({
Target = "[TokenProcess Identifier]",
Tags = {
Action = "Balances",
Limit = 1000, # TODO: Is this necessary if the user is paying for the compute and response?
Cursor? = "BalanceIdentifer"
}
})
Example response message:
TODO
If the sender has a sufficient balance, send the Quantity
to the Target
, issuing a Credit-Notice
to the recipient and a Debit-Notice
to the sender. If the sender has an insufficient balance, fail and notify the sender.
send({
Target = "[TokenProcess Identifier]",
Tags = {
{ name = "Action", value = "transfer" },
{ name = "Recipient", value = "wallet" },
{ name = "Quantity", value = "100" }
}
})
If a successful transfer occurs a notification message should be sent if Cast
is not set.
ao.send({
Target = "[Recipient Address]",
Tags = {
Action = "Credit-Notice",
Quantity = "100"
}
})
Recipients will infer from the From-Process
tag of the message which tokens they have received.
TODO
Implementing a Mint
action gives the process a way of allowing valid participants to create new tokens.
In order to function appropriately, subledgers must implement the full messaging protocol of token contracts (excluding the Mint
action). Subledgers must also implement a number of additional
if not balances then
balances = {}
end
if not name then
name = "Fun Coin"
end
if not token then
token = "fun"
end
if not denomination then
denomination = 6
end
handlers.add(
"info",
handlers.utils.hasMatchingTag("Action", "Info"),
function (msg)
ao.Output = {
Name = name,
Token = token,
Denomination = denomination
}
end
)
handlers.add(
"balance",
handlers.utils.hasMatchingTag("Action", "Balance"),
balance
)
handlers.add(
"balances",
handlers.utils.hasMatchingTag("Action", "Balances"),
function (msg)
ao.Output = balances
end
)
handlers.add(
"transfer",
handlers.utils.hasMatchingTag("Action", "Transfer"),
transfer
)
function transfer(msg)
assert(msg.Tags.Target, 'Target is required!')
assert(msg.Tags.Quantity, 'Quantity is required!')
local qty = tonumber(msg.Tags.Quantity)
if balances[msg.From] > qty then
balances[msg.From] = balances[msg.From] - qty
balances[msg.Tags.Target] = balances[msg.Tags.Target] + qty
ao.send({
Target = msg.Tags.Target,
Tags = {
Action = "Credit-Notice",
Quantity = msg.Tags.Quantity
}
})
if not msg.Tags.Cast then
ao.send({
Target = msg.From,
Tags = {
Action = "Debit-Notice",
Quantity = msg.Tags.Quantity
}
})
end
end
end
function balance(msg)
local bal = balances[msg.Tags.Target]
if not bal then
bal = 0
end
ao.Output = {
Balance = bal,
Target = msg.Tags.Target
}
end