permamind
Version:
An MCP server that provides an immortal memory layer for AI agents and clients
251 lines (214 loc) • 7.41 kB
JavaScript
/**
* Simple Token Generator - Before Allocation Logic
* Creates basic AO tokens without complex allocation and minting strategies
* Reverts to simple approach that was working before allocation logic was added
*/
/**
* Generate simple token Lua script without complex allocation logic
* This is the simplified approach that was working before allocation complexity was added
*/
export function generateSimpleTokenLua(config) {
const { denomination = 12, description = "", logo = "", name, ticker, totalSupply, } = config;
return `
-- Simple Token: ${name} (${ticker})
-- Generated by Permamind Simple Token System (No Allocation Logic)
local json = require('json')
local bint = require('.bint')(256)
-- Token Configuration
Name = Name or "${name}"
Ticker = Ticker or "${ticker}"
Logo = Logo or "${logo}"
Description = Description or "${description}"
Denomination = Denomination or ${denomination}
-- Token State - Simple Approach
Balances = Balances or {}
TotalSupply = TotalSupply or "${totalSupply}"
Owner = Owner or ao.id
-- Allocate entire supply to owner (simple approach)
Balances[Owner] = TotalSupply
-- Utility Functions
local function hasBalance(address, amount)
local balance = bint(Balances[address] or "0")
return bint.__lt(bint(amount), balance) or bint.__eq(bint(amount), balance)
end
local function addBalance(address, amount)
local currentBalance = bint(Balances[address] or "0")
Balances[address] = tostring(bint.__add(currentBalance, bint(amount)))
end
local function subtractBalance(address, amount)
local currentBalance = bint(Balances[address] or "0")
Balances[address] = tostring(bint.__sub(currentBalance, bint(amount)))
end
-- Core Token Handlers
-- Get token information
Handlers.add('Info', Handlers.utils.hasMatchingTag('Action', 'Info'), function(msg)
ao.send({
Target = msg.From,
Data = json.encode({
Name = Name,
Ticker = Ticker,
Logo = Logo,
Description = Description,
Denomination = tostring(Denomination),
TotalSupply = TotalSupply,
Owner = Owner,
ProcessId = ao.id
})
})
end)
-- Get balance for an address
Handlers.add('Balance', Handlers.utils.hasMatchingTag('Action', 'Balance'), function(msg)
local target = msg.Tags.Target or msg.From
local balance = Balances[target] or "0"
ao.send({
Target = msg.From,
Data = json.encode({
Account = target,
Balance = balance,
Ticker = Ticker,
Data = balance
})
})
end)
-- Get all balances
Handlers.add('Balances', Handlers.utils.hasMatchingTag('Action', 'Balances'), function(msg)
ao.send({
Target = msg.From,
Data = json.encode(Balances)
})
end)
-- Transfer tokens
Handlers.add('Transfer', Handlers.utils.hasMatchingTag('Action', 'Transfer'), function(msg)
local recipient = msg.Tags.Recipient
local amount = msg.Tags.Quantity or msg.Tags.Amount
assert(recipient, 'Recipient is required')
assert(amount, 'Quantity is required')
assert(hasBalance(msg.From, amount), 'Insufficient balance')
subtractBalance(msg.From, amount)
addBalance(recipient, amount)
-- Send debit notice to sender
ao.send({
Target = msg.From,
Action = 'Debit-Notice',
Recipient = recipient,
Quantity = amount,
Data = "Transfer successful"
})
-- Send credit notice to recipient
ao.send({
Target = recipient,
Action = 'Credit-Notice',
Sender = msg.From,
Quantity = amount,
Data = "Transfer received"
})
end)
-- Mint tokens (owner only)
Handlers.add('Mint', Handlers.utils.hasMatchingTag('Action', 'Mint'), function(msg)
assert(msg.From == Owner, 'Only owner can mint tokens')
local recipient = msg.Tags.Recipient or msg.From
local amount = msg.Tags.Quantity or msg.Tags.Amount
assert(amount, 'Quantity is required')
addBalance(recipient, amount)
TotalSupply = tostring(bint.__add(bint(TotalSupply), bint(amount)))
ao.send({
Target = recipient,
Action = 'Credit-Notice',
Quantity = amount,
Data = "Tokens minted"
})
end)
-- Burn tokens
Handlers.add('Burn', Handlers.utils.hasMatchingTag('Action', 'Burn'), function(msg)
local amount = msg.Tags.Quantity or msg.Tags.Amount
assert(amount, 'Quantity is required')
assert(hasBalance(msg.From, amount), 'Insufficient balance')
subtractBalance(msg.From, amount)
TotalSupply = tostring(bint.__sub(bint(TotalSupply), bint(amount)))
ao.send({
Target = msg.From,
Action = 'Burn-Notice',
Quantity = amount,
Data = "Tokens burned successfully"
})
end)
-- Transfer ownership (current owner only)
Handlers.add('Transfer-Ownership', Handlers.utils.hasMatchingTag('Action', 'Transfer-Ownership'), function(msg)
assert(msg.From == Owner, 'Only owner can transfer ownership')
local newOwner = msg.Tags.NewOwner
assert(newOwner, 'NewOwner is required')
Owner = newOwner
ao.send({
Target = msg.From,
Data = "Ownership transferred to " .. newOwner
})
end)
-- Get token name
Handlers.add('Name', Handlers.utils.hasMatchingTag('Action', 'Name'), function(msg)
ao.send({
Target = msg.From,
Data = Name
})
end)
-- Get token symbol/ticker
Handlers.add('Symbol', Handlers.utils.hasMatchingTag('Action', 'Symbol'), function(msg)
ao.send({
Target = msg.From,
Data = Ticker
})
end)
-- Get token decimals
Handlers.add('Decimals', Handlers.utils.hasMatchingTag('Action', 'Decimals'), function(msg)
ao.send({
Target = msg.From,
Data = tostring(Denomination)
})
end)
-- Get total supply
Handlers.add('TotalSupply', Handlers.utils.hasMatchingTag('Action', 'TotalSupply'), function(msg)
ao.send({
Target = msg.From,
Data = TotalSupply
})
end)
-- Get owner address
Handlers.add('Owner', Handlers.utils.hasMatchingTag('Action', 'Owner'), function(msg)
ao.send({
Target = msg.From,
Data = Owner
})
end)
print("Simple Token " .. Name .. " (" .. Ticker .. ") initialized with " .. TotalSupply .. " tokens")
print("Owner: " .. Owner)
`;
}
/**
* Validate simple token configuration
*/
export function validateSimpleTokenConfig(config) {
const errors = [];
if (!config.name || config.name.trim().length === 0) {
errors.push("Token name is required");
}
if (!config.ticker || config.ticker.trim().length === 0) {
errors.push("Token ticker is required");
}
if (config.ticker && config.ticker.length > 10) {
errors.push("Token ticker must be 10 characters or less");
}
if (!config.totalSupply || config.totalSupply.trim().length === 0) {
errors.push("Total supply is required");
}
const supplyNum = parseFloat(config.totalSupply);
if (isNaN(supplyNum) || supplyNum <= 0) {
errors.push("Total supply must be a positive number");
}
if (config.denomination !== undefined &&
(config.denomination < 0 || config.denomination > 18)) {
errors.push("Denomination must be between 0 and 18");
}
return {
errors,
valid: errors.length === 0,
};
}