diff --git a/.busted b/.busted index c838de1..9ce6381 100644 --- a/.busted +++ b/.busted @@ -1,14 +1,13 @@ print("Loading .busted configuration...") + return { - _all = { + default = { + root = "src", + pattern = "**/*_spec.lua$", + helper = "spec/setup.lua", verbose = true, coverage = true, output = "utfTerminal", jobs = 4, - }, - default = { - ROOT = {"ant"}, - pattern = "**/*_spec.lua$", - helper = "spec/setup.lua", } } diff --git a/.gitignore b/.gitignore index 3ae07f1..e0ad6f4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,9 @@ node_modules wallet.json .DS_Store luacov-html -.luacov *.gz luacov.stats.out process.wasm dist -publish-output.json \ No newline at end of file +publish-output.json +luarocks-3.9.1 \ No newline at end of file diff --git a/.luacov b/.luacov new file mode 100644 index 0000000..25206f9 --- /dev/null +++ b/.luacov @@ -0,0 +1,5 @@ +statsfile = 'coverage/luacov.stats.out'; +reportfile = 'coverage/luacov.report.out'; +deleteStatsFile = false; +include = { "src/" } +exclude = { "crypto", "json", "base64", "ao" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a1783..d9ae8cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Refactored handlers to use a util that codifies responses on calls. - Added documentation with luadoc types for improved linting. +- Records are now returned as an alphabetically sorted array of [{name, transactionId, ttlSeconds}] with the '@' record being the first. ### Fixed diff --git a/README.md b/README.md index 7173e0a..eb5a209 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,11 @@ This repository provides two flavours of ANT process module, AOS and a custom mo - [Handler Methods](#handler-methods) - [Read Methods](#read-methods) - [`Info`](#info) - - [`Get-Records`](#get-records) - - [`Get-Record`](#get-record) - - [`Get-Controllers`](#get-controllers) + - [`Total-Supply`](#total-supply) + - [`State`](#state) + - [`Records`](#records) + - [`Record`](#record) + - [`Controllers`](#controllers) - [`Balance`](#balance) - [`Balances`](#balances) - [Write methods](#write-methods) @@ -28,8 +30,9 @@ This repository provides two flavours of ANT process module, AOS and a custom mo - [`Set-Name`](#set-name) - [`Set-Ticker`](#set-ticker) - [`Set-Description`](#set-description) + - [`Set-Logo`](#set-logo) - [`Set-Keywords`](#set-keywords) - - [`Set-Controller`](#set-controller) + - [`Add-Controller`](#add-controller) - [`Remove-Controller`](#remove-controller) - [`Remove-Record`](#remove-record) - [`Release-Name`](#release-name) @@ -122,30 +125,60 @@ Retrieves the Name, Ticker, Total supply, Logo, Denomination, and Owner of the A | -------- | ------ | ------- | -------- | --------------------------------- | | Action | string | "Info" | true | Action tag for triggering handler | -#### `Get-Records` +#### `Total-Supply` + +Retrieves total supply of the ANT. + +| Tag Name | Type | Pattern | Required | Description | +| -------- | ------ | -------------- | -------- | --------------------------------- | +| Action | string | "Total-Supply" | true | Action tag for triggering handler | + +#### `State` + +Retrieves the entire state of the ANT, which includes: + +- Records +- Controllers +- Balances +- Owner +- Name +- Ticker +- Logo +- Description +- Keywords +- Denomination +- TotalSupply +- Initialized +- Source-Code-TX-ID + +| Tag Name | Type | Pattern | Required | Description | +| -------- | ------ | ------- | -------- | --------------------------------- | +| Action | string | "State" | true | Action tag for triggering handler | + +#### `Records` Retrieves all the records configured on the ANT -| Tag Name | Type | Pattern | Required | Description | -| -------- | ------ | ------------- | -------- | --------------------------------- | -| Action | string | "Get-Records" | true | Action tag for triggering handler | +| Tag Name | Type | Pattern | Required | Description | +| -------- | ------ | --------- | -------- | --------------------------------- | +| Action | string | "Records" | true | Action tag for triggering handler | -#### `Get-Record` +#### `Record` Retrieves and individual record by name. | Tag Name | Type | Pattern | Required | Description | | ---------- | ------ | ------------------------- | -------- | --------------------------------- | -| Action | string | "Get-Record" | true | Action tag for triggering handler | +| Action | string | "Record" | true | Action tag for triggering handler | | Sub-Domain | string | "^(?:[a-zA-Z0-9_-]+\|@)$" | true | Subdomain you which to read | -#### `Get-Controllers` +#### `Controllers` Retrieves all the controllers on the ANT. -| Tag Name | Type | Pattern | Required | Description | -| -------- | ------ | ----------------- | -------- | --------------------------------- | -| Action | string | "Get-Controllers" | true | Action tag for triggering handler | +| Tag Name | Type | Pattern | Required | Description | +| -------- | ------ | ------------- | -------- | --------------------------------- | +| Action | string | "Controllers" | true | Action tag for triggering handler | #### `Balance` @@ -213,6 +246,15 @@ Sets the description for the ANT. | Action | string | "Set-Description" | true | Action tag for triggering handler | | Description | string | Max 512 characters | true | New description for ANT. | +#### `Set-Logo` + +Sets the logo for the ANT. + +| Tag Name | Type | Pattern | Required | Description | +| -------- | ------ | --------------------- | -------- | --------------------------------- | +| Action | string | "Set-Logo" | true | Action tag for triggering handler | +| Logo | string | "^[a-zA-Z0-9_-]{43}$" | true | ID of new logo for ANT. | + #### `Set-Keywords` Sets the keywords for the ANT. @@ -222,13 +264,13 @@ Sets the keywords for the ANT. | Action | string | "Set-Keywords" | true | Action tag for triggering handler | | Keywords | table | "^[%w-_#@]+$", max 32 characters, max 16 keywords, min 1 keyword | true | New keywords for ANT. | -#### `Set-Controller` +#### `Add-Controller` Adds a new controller to the ANT. | Tag Name | Type | Pattern | Required | Description | | ---------- | ------ | --------------------- | -------- | --------------------------------- | -| Action | string | "Set-Controller" | true | Action tag for triggering handler | +| Action | string | "Add-Controller" | true | Action tag for triggering handler | | Controller | string | "^[a-zA-Z0-9_-]{43}$" | true | Address of the new controller. | #### `Remove-Controller` diff --git a/spec/ant_spec.lua b/spec/ant_spec.lua index 6d1f368..7ca7b00 100644 --- a/spec/ant_spec.lua +++ b/spec/ant_spec.lua @@ -83,6 +83,21 @@ describe("Arweave Name Token", function() assert.are.same(_G.Records["@"].ttlSeconds, 900) end) + it("gets all records", function() + _G.Records["zed"] = { + transactionId = string.rep("1", 43), + ttlSeconds = 3600, + } + _G.Records["@"] = { + transactionId = string.rep("1", 43), + ttlSeconds = 3600, + } + local recordEntries = records.getRecords() + + assert.are.same(recordEntries[1].name, "@") + assert.are.same(recordEntries[#recordEntries].name, "zed") + end) + it("removes a record", function() local name = "@" records.removeRecord(name) -- happy path diff --git a/src/common/main.lua b/src/common/main.lua index b3271f5..07ccae4 100644 --- a/src/common/main.lua +++ b/src/common/main.lua @@ -86,10 +86,10 @@ function ant.init() Balance = "Balance", Transfer = "Transfer", TotalSupply = "Total-Supply", - CreditNotice = "Credit-Notice", -- not implemented - Mint = "Mint", - Burn = "Burn", + -- CreditNotice = "Credit-Notice", + -- Mint = "Mint", + -- Burn = "Burn", } createActionHandler(TokenSpecActionMap.Transfer, function(msg) diff --git a/src/common/records.lua b/src/common/records.lua index ae325de..08e519b 100644 --- a/src/common/records.lua +++ b/src/common/records.lua @@ -50,9 +50,35 @@ function records.getRecord(name) end --- Get all records from the ANT ----@return table +---@alias RecordEntry { +--- name: string, +--- transactionId: string, +--- ttlSeconds: integer, +---} +---@return table The sorted records of the ANT function records.getRecords() - return Records + local antRecords = utils.deepCopy(Records) + assert(antRecords, "Failed to copy Records") + + ---@type table + local recordEntries = {} + + for undername, record in pairs(antRecords) do + local entry = record + entry.name = undername + table.insert(recordEntries, entry) + end + table.sort(recordEntries, function(a, b) + if a.name == "@" then + return true + end + if b.name == "@" then + return false + end + return a.name < b.name + end) + + return recordEntries end return records diff --git a/test/records.test.mjs b/test/records.test.mjs index 3298730..d34cb39 100644 --- a/test/records.test.mjs +++ b/test/records.test.mjs @@ -4,6 +4,7 @@ import assert from 'node:assert'; import { AO_LOADER_HANDLER_ENV, DEFAULT_HANDLE_OPTIONS, + STUB_ADDRESS, } from '../tools/constants.mjs'; describe('aos Records', async () => { @@ -21,14 +22,50 @@ describe('aos Records', async () => { ); } + async function setRecord( + { name, ttl = 3600, transactionId = STUB_ADDRESS }, + mem, + ) { + return handle( + { + Tags: [ + { name: 'Action', value: 'Set-Record' }, + { name: 'Sub-Domain', value: name }, + { name: 'TTL-Seconds', value: ttl }, + { name: 'Transaction-Id', value: transactionId }, + ], + }, + mem, + ); + } + + async function getRecords(mem) { + const res = await handle( + { + Tags: [{ name: 'Action', value: 'Records' }], + }, + mem, + ); + + return JSON.parse(res.Messages[0].Data); + } + it('should get the records of the ant', async () => { - const result = await handle({ - Tags: [{ name: 'Action', value: 'Records' }], - }); + const setRecordRes = await setRecord({ name: 'test-1' }); + const setRecordRes2 = await setRecord( + { name: 'test-2' }, + setRecordRes.Memory, + ); + const setRecordRes3 = await setRecord( + { name: 'test-3' }, + setRecordRes2.Memory, + ); - const records = JSON.parse(result.Messages[0].Data); + const records = await getRecords(setRecordRes3.Memory); assert(records); - assert(records['@']); + + assert.strictEqual(records[0].name, '@'); + assert.strictEqual(records.at(-1).name, 'test-3'); }); it('should get a singular record of the ant', async () => { @@ -62,7 +99,8 @@ describe('aos Records', async () => { setRecordResult.Memory, ); - const record = JSON.parse(recordsResult.Messages[0].Data)['@']; + const records = JSON.parse(recordsResult.Messages[0].Data); + const record = records[0]; assert(record.transactionId === ''.padEnd(43, '3')); assert(record.ttlSeconds === 3600); }); @@ -115,7 +153,8 @@ describe('aos Records', async () => { setRecordResult.Memory, ); - const record = JSON.parse(recordsResult.Messages[0].Data)['timmy']; + const records = JSON.parse(recordsResult.Messages[0].Data); + const record = records.find((r) => r.name == 'timmy'); assert(record.transactionId === ''.padEnd(43, '3')); assert(record.ttlSeconds === 3600); });