Skip to content

Refactor controller #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,402 changes: 0 additions & 1,402 deletions controller.lua

This file was deleted.

403 changes: 403 additions & 0 deletions src/interactions/auctions.lua

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions src/interactions/gate.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
local mod = {}

-- Action: "Credit-Notice"
-- Refunds token transfers with an invalid action
---@type HandlerFunction
function mod.refundInvalidToken(msg)
ao.send({
Target = msg.From,
Action = "Transfer",
Quantity = msg.Tags.Quantity,
Recipient = msg.Tags.Sender,
["X-Action"] = "Refund",
["X-Refund-Reason"] = "This process does not accept the transferred token " .. msg.From
})
end

-- Sync current timestamp and block
---@type HandlerFunction
function mod.sync(msg)
Timestamp = msg.Timestamp
Block = msg["Block-Height"]
end

return mod
41 changes: 41 additions & 0 deletions src/interactions/info.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
local json = require "json"

local mod = {}

-- Action: "Info"
---@type HandlerFunction
function mod.info(msg)
msg.reply({
Name = "LiquidOps Controller",
Module = Module,
Oracle = Oracle,
["Max-Discount"] = tostring(MaxDiscount),
["Min-Discount"] = tostring(MinDiscount),
["Discount-Interval"] = tostring(DiscountInterval),
Data = json.encode(Tokens)
})
end

-- Action: "Get-Tokens"
---@type HandlerFunction
function mod.tokens(msg)
msg.reply({
Data = json.encode(Tokens)
})
end

-- Action: "Get-Oracle"
---@type HandlerFunction
function mod.oracle(msg)
msg.reply({ Oracle = Oracle })
end

-- Action: "Get-Queue"
---@type HandlerFunction
function mod.queue(msg)
msg.reply({
Data = json.encode(Queue)
})
end

return mod
197 changes: 197 additions & 0 deletions src/interactions/listing.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
local assertions = require ".utils.assertions"
local tokens = require ".utils.tokens"
local utils = require ".utils"
local json = require "json"

local mod = {}

-- Action: "List"
---@type HandlerFunction
function mod.list(msg)
-- token to be listed
local token = msg.Tags.Token

assert(
assertions.isAddress(token),
"Invalid token address"
)
assert(
utils.find(function (t) return t.id == token end, Tokens) == nil,
"Token already listed"
)

-- check configuration
local liquidationThreshold = tonumber(msg.Tags["Liquidation-Threshold"])
local collateralFactor = tonumber(msg.Tags["Collateral-Factor"])
local reserveFactor = tonumber(msg.Tags["Reserve-Factor"])
local baseRate = tonumber(msg.Tags["Base-Rate"])
local initRate = tonumber(msg.Tags["Init-Rate"])
local jumpRate = tonumber(msg.Tags["Jump-Rate"])
local cooldownPeriod = tonumber(msg.Tags["Cooldown-Period"])
local kinkParam = tonumber(msg.Tags["Kink-Param"])

assert(
collateralFactor ~= nil and type(collateralFactor) == "number",
"Invalid collateral factor"
)
assert(
collateralFactor // 1 == collateralFactor and collateralFactor >= 0 and collateralFactor <= 100,
"Collateral factor has to be a whole percentage between 0 and 100"
)
assert(
liquidationThreshold ~= nil and type(liquidationThreshold) == "number",
"Invalid liquidation threshold"
)
assert(
liquidationThreshold // 1 == liquidationThreshold and liquidationThreshold >= 0 and liquidationThreshold <= 100,
"Liquidation threshold has to be a whole percentage between 0 and 100"
)
assert(
liquidationThreshold > collateralFactor,
"Liquidation threshold must be greater than the collateral factor"
)
assert(
reserveFactor ~= nil and type(reserveFactor) == "number",
"Invalid reserve factor"
)
assert(
reserveFactor // 1 == reserveFactor and reserveFactor >= 0 and reserveFactor <= 100,
"Reserve factor has to be a whole percentage between 0 and 100"
)
assert(
baseRate ~= nil and assertions.isValidNumber(baseRate),
"Invalid base rate"
)
assert(
initRate ~= nil and assertions.isValidNumber(initRate),
"Invalid init rate"
)
assert(
jumpRate ~= nil and assertions.isValidNumber(jumpRate),
"Invalid jump rate"
)
assert(
assertions.isTokenQuantity(msg.Tags["Value-Limit"]),
"Invalid value limit"
)
assert(
cooldownPeriod ~= nil and assertions.isValidInteger(cooldownPeriod),
"Invalid cooldown period"
)
assert(
kinkParam ~= nil and type(kinkParam) == "number",
"Invalid kink parameter"
)
assert(
kinkParam // 1 == kinkParam and kinkParam >= 0 and kinkParam <= 100,
"Kink parameter has to be a whole percentage between 0 and 100"
)

-- check if token is supported
local supported, info = tokens.isSupported(token)

assert(supported, "Token not supported by the protocol")

-- spawn logo
local logo = msg.Tags.Logo or info.Tags.Logo

-- the oToken configuration
local config = {
Name = "LiquidOps " .. tostring(info.Tags.Name or info.Tags.Ticker or ""),
["Collateral-Id"] = token,
["Collateral-Ticker"] = info.Tags.Ticker,
["Collateral-Name"] = info.Tags.Name,
["Collateral-Denomination"] = info.Tags.Denomination,
["Collateral-Factor"] = msg.Tags["Collateral-Factor"],
["Liquidation-Threshold"] = tostring(liquidationThreshold),
["Reserve-Factor"] = tostring(reserveFactor),
["Base-Rate"] = msg.Tags["Base-Rate"],
["Init-Rate"] = msg.Tags["Init-Rate"],
["Jump-Rate"] = msg.Tags["Jump-Rate"],
["Kink-Param"] = msg.Tags["Kink-Param"],
["Value-Limit"] = msg.Tags["Value-Limit"],
["Cooldown-Period"] = msg.Tags["Cooldown-Period"],
Oracle = Oracle,
["Oracle-Delay-Tolerance"] = tostring(MaxOracleDelay),
Logo = logo,
Authority = ao.authorities[1],
Friends = json.encode(Tokens)
}

-- spawn new oToken process
local spawnResult = ao.spawn(Module, config).receive()
local spawnedID = spawnResult.Tags.Process

-- notify all other tokens
for _, t in ipairs(Tokens) do
if t.oToken ~= spawnedID then
ao.send({
Target = t.oToken,
Action = "Add-Friend",
Friend = spawnedID,
Token = token,
Ticker = info.Tags.Ticker,
Denomination = info.Tags.Denomination
})
end
end

-- add token to tokens list
table.insert(Tokens, {
id = token,
ticker = info.Tags.Ticker,
oToken = spawnedID,
denomination = tonumber(info.Tags.Denomination) or 0
})

msg.reply({
Action = "Token-Listed",
Token = token,
["Spawned-Id"] = spawnedID,
Data = json.encode(config)
})
end

-- Action: "Unlist"
---@type HandlerFunction
function mod.unlist(msg)
-- token to be removed
local token = msg.Tags.Token

assert(
assertions.isAddress(token),
"Invalid token address"
)

-- find token index
---@type integer|nil
local idx = utils.find(
function (t) return t.id == token end,
Tokens
)

assert(type(idx) == "number", "Token is not listed")

-- id of the oToken for this token
local oToken = Tokens[idx].oToken

-- unlist
table.remove(Tokens, idx)

-- notify all other oTokens
for _, t in ipairs(Tokens) do
ao.send({
Target = t.oToken,
Action = "Remove-Friend",
Friend = oToken
})
end

msg.reply({
Action = "Token-Unlisted",
Token = token,
["Removed-Id"] = oToken
})
end

return mod
88 changes: 88 additions & 0 deletions src/interactions/queue.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
local assertions = require ".utils.assertions"
local queue = require ".utils.queue"
local utils = require ".utils"
local json = require "json"

local mod = {}

-- A wrapper for patterns to validate if the message is coming
-- from an oToken or not
function mod.fromoToken(pattern)
return function (msg)
local match = utils.matchesSpec(msg, pattern)

if not match or match == 0 or match == "skip" then
return match
end

return utils.find(
function (t) return t.oToken == msg.From end,
Tokens
) ~= nil
end
end

-- Action: "Add-To-Queue"
---@type HandlerFunction
function mod.add(msg)
local user = msg.Tags.User

-- validate address
if not assertions.isAddress(user) then
return msg.reply({ Error = "Invalid user address" })
end

-- check if the user has already been added
if queue.isQueued(user) or UpdateInProgress then
return msg.reply({ Error = "User already queued" })
end

-- add to queue
queue.add(user, msg.From)

msg.reply({ ["Queued-User"] = user })
end

-- Action: "Remove-From-Queue"
---@type HandlerFunction
function mod.remove(msg)
local user = msg.Tags.User

-- validate address
if not assertions.isAddress(user) then
return msg.reply({ Error = "Invalid user address" })
end

-- try to remove the user from the queue
local res = queue.remove(user, msg.From)

if res ~= "removed" then
return msg.reply({
Error = res == "not_queued" and
"The user is not queued" or
"The user was queued from another origin"
})
end

-- reply with confirmation
msg.reply({ ["Unqueued-User"] = user })
end

-- Action: "Check-Queue-For"
---@type HandlerFunction
function mod.check(msg)
local user = msg.Tags.User

-- validate address
if not assertions.isAddress(user) then
return msg.reply({ ["In-Queue"] = "false" })
end

-- the user is queued if they're either in the collateral
-- or the liquidation queues
return msg.reply({
["In-Queue"] = json.encode(queue.isQueued(user) or UpdateInProgress)
})
end

return mod
Loading