Example Simple Token
Security considerations
import { Contract, ContractParams } from "./types/contract.ts";
import { zUtils } from "./utils/zod.ts";
import { z } from "zod";
import { argsParsing } from "./utils/args-parsing.ts";
import { ExecutionError } from "./types/execution-error.ts";
export default class SimpleToken implements Contract {
activeOn = 850000;
private _alreadyMinted = false;
private _balances = new Map<string, bigint>();
mint({ metadata, args, eventLogger }: ContractParams) {
const schema = z.tuple([zUtils.bigint()]);
const [supply] = argsParsing(schema, args, "mint");
// safety check to make sure you can only mint once
if (this._alreadyMinted) throw new ExecutionError("mint: already minted");
// mint the tokens
this._balances.set(metadata.sender, supply);
// make sure you can only mint once
this._alreadyMinted = true;
eventLogger.log({
type: "MINT",
message: `${metadata.sender} minted ${supply}`,
});
}
transfer({ metadata, args, eventLogger }: ContractParams) {
const schema = z.tuple([z.string(), zUtils.bigint()]);
const [to, value] = argsParsing(schema, args, "transfer");
// must not send more than you have
const fromBalance = this._balances.get(metadata.sender) ?? 0n;
if (fromBalance < value) {
throw new ExecutionError("transfer: not enough balance");
}
// update balances
this._balances.set(metadata.sender, fromBalance - value);
const toBeforeBalance = this._balances.get(to) ?? 0n;
this._balances.set(to, toBeforeBalance + value);
eventLogger.log({
type: "TRANSFER",
message: `transferred from ${
metadata.sender
} to ${to} value ${value.toString()}`,
});
}
balance({ args }: ContractParams): bigint {
const schema = z.tuple([z.string()]);
const [from] = argsParsing(schema, args, "balance");
return this._balances.get(from) ?? 0n;
}
}
Properties
Mint
Transfer
Balance
Last updated