Skip to content

Commit

Permalink
refactor: address TODOs PE-7339
Browse files Browse the repository at this point in the history
  • Loading branch information
fedellen committed Dec 20, 2024
1 parent 469ef84 commit bb2e1a8
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 65 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,6 @@ dependencies = {

### Deployment

TODO:
Merging to develop or main will evolve the devnet or testnet contract to the next version. The script managing the logic is located at `tools/evolve.mjs`, which uses aoconnect to perform an `Eval` action. The deployment process is automated using Github Actions.

[contract whitepaper]: https://ar.io/whitepaper
15 changes: 14 additions & 1 deletion src/ao_event.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
local utils = require("utils")
local json = require("json")

-- Factory function for creating an "AOEvent"
--- @class AOEvent
--- @field data table<string, any> The data table holding the event fields.
--- @field sampleRate number|nil Optional sample rate.
--- @field addField fun(self: AOEvent, key: string, value: any): AOEvent Adds a single field to the event.
--- @field addFields fun(self: AOEvent, fields: table<string, any>): AOEvent Adds multiple fields to the event.
--- @field addFieldsIfExist fun(self: AOEvent, table: table<string, any>, fields: table<string>): AOEvent Adds specific fields if they exist in the given table.
--- @field addFieldsWithPrefixIfExist fun(self: AOEvent, srcTable: table<string, any>, prefix: string, fields: table<string>): AOEvent
--- Adds fields with a prefix if they exist in the source table.
--- @field printEvent fun(self: AOEvent): nil Prints the event in JSON format.
--- @field toJSON fun(self: AOEvent): string Converts the event to a JSON string.

--- Factory function for creating an "AOEvent"
--- @param initialData table<string, any> Optional initial data to populate the event with.
--- @returns AOEvent
local function AOEvent(initialData)
local event = {
sampleRate = nil, -- Optional sample rate
Expand Down
8 changes: 6 additions & 2 deletions src/ario_event.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
local AOEvent = require("ao_event")
local utils = require("utils")

-- TODO: RENAME TO ARIOEvent
-- Convenience factory function for prepopulating analytic and msg fields into AOEvents
--- @alias ARIOEvent AOEvent

--- Convenience factory function for pre populating analytic and msg fields into AOEvents
--- @param msg table
--- @param initialData table<string, any> Optional initial data to populate the event with.
--- @returns ARIOEvent
local function ARIOEvent(msg, initialData)
local event = AOEvent({
Cron = msg.Cron or false,
Expand Down
2 changes: 0 additions & 2 deletions src/arns.lua
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,6 @@ end

function arns.getProcessIdForRecord(name)
local record = arns.getRecord(name)
-- TODO: Could assert for type safety -- but on pruneState flow, the record does not exist
-- assert(record, "Name is not registered: " .. name)
return record ~= nil and record.processId or nil
end

Expand Down
2 changes: 2 additions & 0 deletions src/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ constants.maximumRewardRate = 0.001
constants.minimumRewardRate = 0.0005
constants.rewardDecayStartEpoch = 365
constants.rewardDecayLastEpoch = 547
constants.observerRewardRatio = 0.1
constants.gatewayOperatorRewardRatio = 0.9

-- GAR
constants.DEFAULT_UNDERNAME_COUNT = 10
Expand Down
12 changes: 6 additions & 6 deletions src/epochs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,9 @@ end
--- @param timestamp number The timestamp
--- @return number # The epoch index
function epochs.getEpochIndexForTimestamp(timestamp)
--- TODO: is this conversion still necessary? Confirm timestamps from the SU are unix and milliseconds and remove this
local timestampInMS = utils.checkAndConvertTimestampToMs(timestamp)
local epochZeroStartTimestamp = epochs.getSettings().epochZeroStartTimestamp
local epochLengthMs = epochs.getSettings().durationMs
local epochIndex = math.floor((timestampInMS - epochZeroStartTimestamp) / epochLengthMs)
local epochIndex = math.floor((timestamp - epochZeroStartTimestamp) / epochLengthMs)
return epochIndex
end

Expand Down Expand Up @@ -526,9 +524,11 @@ function epochs.computeTotalEligibleRewardsForEpoch(epochIndex, prescribedObserv
local protocolBalance = balances.getBalance(ao.id)
local rewardRate = epochs.getRewardRateForEpoch(epochIndex)
local totalEligibleRewards = math.floor(protocolBalance * rewardRate)
local eligibleGatewayReward = math.floor(totalEligibleRewards * 0.90 / #activeGatewayAddresses) -- TODO: make these setting variables
local eligibleObserverReward =
math.floor(totalEligibleRewards * 0.10 / utils.lengthOfTable(prescribedObserversLookup)) -- TODO: make these setting variables
local eligibleGatewayReward =
math.floor(totalEligibleRewards * constants.gatewayOperatorRewardRatio / #activeGatewayAddresses)
local eligibleObserverReward = math.floor(
totalEligibleRewards * constants.observerRewardRatio / utils.lengthOfTable(prescribedObserversLookup)
)
-- compute for each gateway what their potential rewards are and for their delegates
local potentialRewards = {}
-- use ipairs as activeGatewayAddresses is an array
Expand Down
1 change: 0 additions & 1 deletion src/gar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,6 @@ function planMinimumStakesDrawdown(fundingPlan, stakingProfile)
end
end

-- TODO: return event-worthy data
--- Reduces all balances and creates withdraw stakes as prescribed by the funding plan
--- @param fundingPlan table The funding plan to apply
--- @param msgId string The current message ID
Expand Down
37 changes: 17 additions & 20 deletions src/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ local ActionMap = {
--- ArNS
Record = "Record",
Records = "Records",
BuyRecord = "Buy-Record", -- TODO: standardize these as `Buy-Name` or `Upgrade-Record`
UpgradeName = "Upgrade-Name", -- TODO: may be more aligned to `Upgrade-Record`
BuyRecord = "Buy-Record", -- TODO: standardize these as `Buy-Name`
BuyName = "Buy-Name", -- TODO: standardize these as `Buy-Name`
UpgradeName = "Upgrade-Name",
ExtendLease = "Extend-Lease",
IncreaseUndernameLimit = "Increase-Undername-Limit",
ReassignName = "Reassign-Name",
Expand Down Expand Up @@ -158,7 +159,7 @@ local function adjustSuppliesForFundingPlan(fundingPlan, rewardForInitiator)
LastKnownCirculatingSupply = LastKnownCirculatingSupply - fundingPlan.balance + rewardForInitiator
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
--- @param result BuyRecordResult|RecordInteractionResult|CreatePrimaryNameResult|PrimaryNameRequestApproval
local function addResultFundingPlanFields(ioEvent, result)
ioEvent:addFieldsWithPrefixIfExist(result.fundingPlan, "FP-", { "balance" })
Expand Down Expand Up @@ -200,7 +201,7 @@ local function addResultFundingPlanFields(ioEvent, result)
adjustSuppliesForFundingPlan(result.fundingPlan, result.returnedName and result.returnedName.rewardForInitiator)
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
---@param result RecordInteractionResult|BuyRecordResult
local function addRecordResultFields(ioEvent, result)
ioEvent:addFieldsIfExist(result, {
Expand Down Expand Up @@ -323,7 +324,7 @@ local function addPruneGatewaysResult(ioEvent, pruneGatewaysResult)
end
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
local function addNextPruneTimestampsData(ioEvent)
ioEvent:addField("Next-Returned-Names-Prune-Timestamp", arns.nextReturnedNamesPruneTimestamp())
ioEvent:addField("Next-Epochs-Prune-Timestamp", epochs.nextEpochsPruneTimestamp())
Expand All @@ -334,7 +335,7 @@ local function addNextPruneTimestampsData(ioEvent)
ioEvent:addField("Next-Primary-Names-Prune-Timestamp", primaryNames.nextPrimaryNamesPruneTimestamp())
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
--- @param prunedStateResult PruneStateResult
local function addNextPruneTimestampsResults(ioEvent, prunedStateResult)
--- @type PrunedGatewaysResult
Expand Down Expand Up @@ -368,13 +369,13 @@ local function assertValidFundFrom(fundFrom)
assert(validFundFrom[fundFrom], "Invalid fund from type. Must be one of: any, balance, stakes")
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
local function addPrimaryNameCounts(ioEvent)
ioEvent:addField("Total-Primary-Names", utils.lengthOfTable(primaryNames.getUnsafePrimaryNames()))
ioEvent:addField("Total-Primary-Name-Requests", utils.lengthOfTable(primaryNames.getUnsafePrimaryNameRequests()))
end

--- @param ioEvent IOEvent
--- @param ioEvent ARIOEvent
--- @param primaryNameResult CreatePrimaryNameResult|PrimaryNameRequestApproval
local function addPrimaryNameRequestData(ioEvent, primaryNameResult)
ioEvent:addFieldsIfExist(primaryNameResult, { "baseNameOwner" })
Expand Down Expand Up @@ -408,15 +409,13 @@ local function updateLastKnownMessage(msg)
end
end

--- @alias IOEvent table -- TODO: Type this

--- @class ParsedMessage
--- @field Id string
--- @field Action string
--- @field From string
--- @field Timestamp Timestamp
--- @field Tags table<string, any>
--- @field ioEvent IOEvent
--- @field ioEvent ARIOEvent
--- @field Cast boolean?
--- @field reply? fun(response: any)

Expand All @@ -429,7 +428,7 @@ local function addEventingHandler(handlerName, pattern, handleFn, critical, prin
critical = critical or false
printEvent = printEvent == nil and true or printEvent
Handlers.add(handlerName, pattern, function(msg)
-- add an IOEvent to the message if it doesn't exist
-- add an ARIOEvent to the message if it doesn't exist
msg.ioEvent = msg.ioEvent or ARIOEvent(msg)
-- global handler for all eventing errors, so we can log them and send a notice to the sender for non critical errors and discard the memory on critical errors
local status, resultOrError = eventingPcall(msg.ioEvent, function(error)
Expand Down Expand Up @@ -785,7 +784,7 @@ addEventingHandler(ActionMap.IncreaseVault, utils.hasMatchingTag("Action", Actio
})
end)

addEventingHandler(ActionMap.BuyRecord, utils.hasMatchingTag("Action", ActionMap.BuyRecord), function(msg)
local function buyName(msg)
local name = msg.Tags.Name and string.lower(msg.Tags.Name) or nil
local purchaseType = msg.Tags["Purchase-Type"] and string.lower(msg.Tags["Purchase-Type"]) or "lease"
local years = msg.Tags.Years or nil
Expand Down Expand Up @@ -856,7 +855,10 @@ addEventingHandler(ActionMap.BuyRecord, utils.hasMatchingTag("Action", ActionMap
}),
})
end
end)
end

addEventingHandler(ActionMap.BuyRecord, utils.hasMatchingTag("Action", ActionMap.BuyRecord), buyName)
addEventingHandler("buyName", utils.hasMatchingTag("Action", ActionMap.BuyName), buyName)

addEventingHandler("upgradeName", utils.hasMatchingTag("Action", ActionMap.UpgradeName), function(msg)
local fundFrom = msg.Tags["Fund-From"]
Expand Down Expand Up @@ -1048,8 +1050,6 @@ addEventingHandler(
)

addEventingHandler(ActionMap.JoinNetwork, utils.hasMatchingTag("Action", ActionMap.JoinNetwork), function(msg)
-- TODO: add assertions on all the provided input, although the joinNetwork function will throw an error if the input is invalid

local updatedSettings = {
label = msg.Tags.Label,
note = msg.Tags.Note,
Expand Down Expand Up @@ -1444,7 +1444,6 @@ addEventingHandler(
end
)

-- TODO: Update the UpdateGatewaySettings handler to consider replacing the allowedDelegates list
addEventingHandler(
ActionMap.UpdateGatewaySettings,
utils.hasMatchingTag("Action", ActionMap.UpdateGatewaySettings),
Expand Down Expand Up @@ -1490,7 +1489,6 @@ addEventingHandler(
or msg.Tags["Auto-Stake"] == "true",
}

-- TODO: we could standardize this on our prepended handler to inject and ensure formatted addresses and converted values
local observerAddress = msg.Tags["Observer-Address"] or unsafeGateway.observerAddress
local result = gar.updateGatewaySettings(
msg.From,
Expand Down Expand Up @@ -1732,7 +1730,7 @@ addEventingHandler("distribute", utils.hasMatchingTag("Action", "Tick"), functio
msg.ioEvent:addField("Prescribed-Observers", prescribedObserverAddresses)
end
if #newDemandFactors > 0 then
msg.ioEvent:addField("New-Demand-Factors", newDemandFactors, ";")
msg.ioEvent:addField("New-Demand-Factors", newDemandFactors)
end
if #newPruneGatewaysResults > 0 then
-- Reduce the prune gateways results and then track changes
Expand Down Expand Up @@ -2078,7 +2076,6 @@ addEventingHandler("releaseName", utils.hasMatchingTag("Action", ActionMap.Relea
assert(record, "Record not found")
assert(record.type == "permabuy", "Only permabuy names can be released")
assert(record.processId == processId, "Process-Id mismatch")
-- TODO: throw an error here instead of allowing release and force removal of primary names? I tend to favor the protection for primary name owners.
assert(
#primaryNames.getPrimaryNamesForBaseName(name) == 0,
"Primary names are associated with this name. They must be removed before releasing the name."
Expand Down
6 changes: 2 additions & 4 deletions src/primary_names.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ local arns = require("arns")
local balances = require("balances")
local utils = require("utils")
local gar = require("gar")
local constants = require("constants")
local primaryNames = {}

-- TODO: Figure out how to modulate this according to market conditions since it's actual spending
local ONE_WEEK_IN_MS = 604800000

--- @alias WalletAddress string
--- @alias ArNSName string

Expand Down Expand Up @@ -101,7 +99,7 @@ function primaryNames.createPrimaryNameRequest(name, initiator, timestamp, msgId
local request = {
name = name,
startTimestamp = timestamp,
endTimestamp = timestamp + ONE_WEEK_IN_MS,
endTimestamp = timestamp + constants.oneWeekMs,
}

--- if the initiator is base name owner, then just set the primary name and return
Expand Down
28 changes: 0 additions & 28 deletions src/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -514,34 +514,6 @@ function utils.splitAndTrimString(input, delimiter)
return tokens
end

--- Checks if a timestamp is an integer and converts it to milliseconds if it is in seconds
--- @param timestamp number The timestamp to check and convert
--- @return number timestampInMs - the timestamp in milliseconds
function utils.checkAndConvertTimestampToMs(timestamp)
-- Check if the timestamp is an integer
assert(type(timestamp) == "number", "Timestamp must be a number")
assert(utils.isInteger(timestamp), "Timestamp must be an integer")

-- Define the plausible range for Unix timestamps in seconds
local min_timestamp = 0
local max_timestamp = 4102444800 -- Corresponds to 2100-01-01

if timestamp >= min_timestamp and timestamp <= max_timestamp then
-- The timestamp is already in seconds, convert it to milliseconds
return timestamp * 1000
end

-- If the timestamp is outside the range for seconds, check for milliseconds
local min_timestamp_ms = min_timestamp * 1000
local max_timestamp_ms = max_timestamp * 1000

if timestamp >= min_timestamp_ms and timestamp <= max_timestamp_ms then
return timestamp
end

error("Timestamp is out of range")
end

function utils.reduce(tbl, fn, init)
local acc = init
local i = 1
Expand Down

0 comments on commit bb2e1a8

Please sign in to comment.