Skip to content

Commit

Permalink
Merge branch 'develop' into PE-6941-add-description-and-keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
dtfiedler authored Oct 16, 2024
2 parents e43ac33 + a6b3506 commit 252c766
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 39 deletions.
27 changes: 2 additions & 25 deletions spec/ant_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,13 @@ local json = require("src.common.json")

local fake_address = "1111111111111111111111111111111111111111111"

_G.ao = {
send = function()
return true
end,
id = "test",
}
_G.Balances = { [fake_address] = 1 }
_G.Records = {}
_G.Controllers = { fake_address }
_G.Name = "Arweave Name Token"
_G.Ticker = "ANT"
_G.Description = "ANT's Description"
_G.Keywords = { "KEYWORD-1", "KEYWORD-2", "KEYWORD-3" }
_G.Logo = "LOGO"
_G.Denomination = 1

os.clock = function()
return 0
end

local originalState = {
name = "Arweave Name Token",
ticker = "ANT",
description = "ANT's description",
keywords = { "KEYWORD-1", "KEYWORD-2", "KEYWORD-3" },
controllers = { fake_address },
records = { ["@"] = { transactionId = "test", ttlSeconds = 900 } },
records = { ["@"] = { transactionId = fake_address, ttlSeconds = 900 } },
balances = { [fake_address] = 1 },
owner = fake_address,
}
Expand All @@ -46,12 +26,9 @@ describe("Arweave Name Token", function()
_G.Ticker = "ANT"
_G.Description = "ANT's description"
_G.Keywords = { "KEYWORD-1", "KEYWORD-2", "KEYWORD-3" }
_G.Denomination = 1
end)

setup(function() end)

teardown(function() end)

it("Initializes the state of the process", function()
initialize.initializeANTState(json.encode(originalState)) -- happy

Expand Down
28 changes: 28 additions & 0 deletions spec/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,31 @@ describe("utils.camelCase", function()
assert.are.equal(utils.camelCase(""), "")
end)
end)

describe("utils.validateArweaveId", function()
it("should throw an error for invalid Arweave IDs", function()
local invalid, error = pcall(utils.validateArweaveId, "invalid-arweave-id-123")
assert.is_false(invalid)
assert.is_not_nil(error)
end)

it("should not throw an error for a valid Arweave ID", function()
local valid, error = pcall(utils.validateArweaveId, "0E7Ai_rEQ326_vLtgB81XHViFsLlcwQNqlT9ap24uQI")
assert.is_true(valid)
assert.is_nil(error)
end)
end)

describe("utils.validateUndername", function()
it("should throw an error for invalid undernames", function()
local invalid, error = pcall(utils.validateUndername, "_invalid_undername_")
assert.is_false(invalid)
assert.is_not_nil(error)
end)

it("should not throw an error for a valid undername", function()
local valid, error = pcall(utils.validateUndername, "valid-undername-123")
assert.is_true(valid)
assert.is_nil(error)
end)
end)
4 changes: 0 additions & 4 deletions src/common/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ local constants = {}

constants.MAX_UNDERNAME_LENGTH = 61
constants.UNDERNAME_DOES_NOT_EXIST_MESSAGE = "Name does not exist in the ANT!"
constants.UNDERNAME_REGEXP = "^(?:@|[a-zA-Z0-9][a-zA-Z0-9-_]{0,"
.. (constants.MAX_UNDERNAME_LENGTH - 2)
.. "}[a-zA-Z0-9])$"
constants.ARWEAVE_ID_REGEXP = "^[a-zA-Z0-9-_]{43}$"
constants.INVALID_ARWEAVE_ID_MESSAGE = "Invalid Arweave ID"
constants.MIN_TTL_SECONDS = 900
constants.MAX_TTL_SECONDS = 3600
Expand Down
33 changes: 33 additions & 0 deletions src/common/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ function ant.init()
Records = "Records",
State = "State",
Evolve = "Evolve",
-- IO Network Contract Handlers
ReleaseName = "Release-Name",
}

local TokenSpecActionMap = {
Expand Down Expand Up @@ -525,6 +527,37 @@ function ant.init()
SourceCodeTxId = srcCodeTxId
end
)

-- IO Network Contract Handlers
Handlers.add(camel(ActionMap.ReleaseName), utils.hasMatchingTag("Action", ActionMap.ReleaseName), function(msg)
local assertHasPermission, permissionErr = pcall(utils.validateOwner, msg.From)
if assertHasPermission == false then
return ao.send({
Target = msg.From,
Action = "Invalid-Release-Name-Notice",
Data = permissionErr,
Error = "Release-Name-Error",
})
end

local name = string.lower(msg.Tags["Name"])
local ioProcess = msg.Tags["IO-Process-Id"]

-- send the release message to the provided IO Process Id
ao.send({
Target = ioProcess,
Action = "Release-Name-Notice",
Initiator = msg.From,
Name = name,
})

ao.send({
Target = msg.From,
Action = "Release-Name-Notice",
Initiator = msg.From,
Name = name,
})
end)
end

return ant
20 changes: 13 additions & 7 deletions src/common/utils.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- the majority of this file came from https://github.com/permaweb/aos/blob/main/process/utils.lua

local constants = require(".common.constants")
local json = require("json")
local json = require(".common.json")
local utils = { _version = "0.0.1" }

local function isArray(table)
Expand Down Expand Up @@ -197,20 +197,26 @@ function utils.reply(msg)
Handlers.utils.reply(msg)
end

-- NOTE: lua 5.3 has limited regex support, particularly for lookaheads and negative lookaheads or use of {n}
function utils.validateUndername(name)
local valid = string.match(name, constants.UNDERNAME_REGEXP) == nil
assert(valid ~= false, constants.UNDERNAME_DOES_NOT_EXIST_MESSAGE)
local validLength = #name <= constants.MAX_UNDERNAME_LENGTH
local validRegex = string.match(name, "^@$") ~= nil
or string.match(name, "^[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]$") ~= nil
local valid = validLength and validRegex
assert(valid, constants.UNDERNAME_DOES_NOT_EXIST_MESSAGE)
end

function utils.validateArweaveId(id)
local valid = string.match(id, constants.ARWEAVE_ID_REGEXP) == nil

assert(valid == true, constants.INVALID_ARWEAVE_ID_MESSAGE)
-- the provided id matches the regex, and is not nil
local validLength = #id == 43
local validChars = string.match(id, "^[a-zA-Z0-9_-]+$") ~= nil
local valid = validLength and validChars
assert(valid, constants.INVALID_ARWEAVE_ID_MESSAGE)
end

function utils.validateTTLSeconds(ttl)
local valid = type(ttl) == "number" and ttl >= constants.MIN_TTL_SECONDS and ttl <= constants.MAX_TTL_SECONDS
return assert(valid ~= false, constants.INVALID_TTL_MESSAGE)
assert(valid, constants.INVALID_TTL_MESSAGE)
end

function utils.validateOwner(caller)
Expand Down
1 change: 1 addition & 0 deletions test/info.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ describe('aos Info', async () => {
'setKeywords',
'initializeState',
'state',
'releaseName',
]);
});

Expand Down
93 changes: 93 additions & 0 deletions test/io.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createAntAosLoader } from './utils.mjs';
import { describe, it } from 'node:test';
import assert from 'node:assert';
import {
AO_LOADER_HANDLER_ENV,
DEFAULT_HANDLE_OPTIONS,
STUB_ADDRESS,
} from '../tools/constants.mjs';

describe('IO Network Updates', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();

async function handle(options = {}, mem = startMemory) {
return originalHandle(
mem,
{
...DEFAULT_HANDLE_OPTIONS,
...options,
},
AO_LOADER_HANDLER_ENV,
);
}

it('should send update to io network when a name is released', async () => {
const result = await handle({
Tags: [
{ name: 'Action', value: 'Release-Name' },
{ name: 'IO-Process-Id', value: 'io-process-id-'.padEnd(43, '1') },
{ name: 'Name', value: 'name' },
],
});

// two messages should be sent - one to the io process and one to the sender
assert(result.Messages?.length === 2, 'Expected two messages');

const message = result.Messages[0]?.Tags?.find(
(tag) => tag.name === 'Action' && tag.value === 'Release-Name-Notice',
);
assert(message, 'Release-Name-Notice message not found');

// ensure a message Target is the IO process id provided and the other is to the sender and both contain the initiator, name and process id
assert(
result.Messages.some(
(msg) =>
msg.Target === 'io-process-id-'.padEnd(43, '1') &&
msg.Tags.find(
(tag) => tag.name === 'Initiator' && tag.value === STUB_ADDRESS,
) &&
msg.Tags.find((tag) => tag.name === 'Name' && tag.value === 'name') &&
msg.Tags.find(
(tag) =>
tag.name === 'Action' && tag.value === 'Release-Name-Notice',
),
),
);

assert(
result.Messages.some(
(msg) =>
msg.Target === STUB_ADDRESS &&
msg.Tags.find(
(tag) => tag.name === 'Initiator' && tag.value === STUB_ADDRESS,
) &&
msg.Tags.find((tag) => tag.name === 'Name' && tag.value === 'name') &&
msg.Tags.find(
(tag) =>
tag.name === 'Action' && tag.value === 'Release-Name-Notice',
),
),
);
});

it('should send a release-name-error-notice if the sender is not the owner', async () => {
const result = await handle({
Tags: [
{ name: 'Action', value: 'Release-Name' },
{ name: 'IO-Process-Id', value: 'io-process-id' },
{ name: 'Name', value: 'name' },
],
From: 'not-owner',
Owner: 'not-owner',
});

// assert no other messages
assert(result.Messages?.length === 1, 'Expected only one message');

const error = result.Messages[0]?.Tags.find(
(tag) => tag.name === 'Error' && tag.value === 'Release-Name-Error',
);
assert(error, 'Release-Name-Error message not found');
});
});
2 changes: 1 addition & 1 deletion test/registry.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('Registry Updates', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();

const controllerAddress = 'controller-address'.padEnd(43, '0');
const controllerAddress = 'controller-address-'.padEnd(43, '0');

async function handle(options = {}, mem = startMemory) {
return originalHandle(
Expand Down
6 changes: 4 additions & 2 deletions tools/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const STUB_ADDRESS = ''.padEnd(43, '1');
const STUB_PROCESS_ID = 'process-id-'.padEnd(43, '1');
const STUB_ADDRESS = 'arweave-address-'.padEnd(43, '1');
/* ao READ-ONLY Env Variables */
const AO_LOADER_HANDLER_ENV = {
Process: {
Id: ''.padEnd(43, '1'),
Id: STUB_PROCESS_ID,
Owner: STUB_ADDRESS,
Tags: [
{ name: 'Authority', value: 'XXXXXX' },
Expand Down Expand Up @@ -86,6 +87,7 @@ export {
AO_LOADER_OPTIONS,
AO_LOADER_HANDLER_ENV,
STUB_ADDRESS,
STUB_PROCESS_ID,
DEFAULT_HANDLE_OPTIONS,
ANT_EVAL_OPTIONS,
};

0 comments on commit 252c766

Please sign in to comment.