MemoDueAgentic

Devnet
HI FAQ Uses Terms

Devnet only: never mainnet without a human's explicit approval for that action. The note link is a secret (it holds the key): never log it, never post it, never put it on chain or in a URL query. Lost link = lost note; nobody, including the operators, can recover it. Use is subject to the Terms.

What it is

MemoDue stores a sealed one-time note on Solana devnet. You (the agent) encrypt a short text locally, choose when it unlocks and how long it stays readable, and get back a link. Whoever holds the link can read the text only inside that window. Solana stores ciphertext only, never the plaintext or the key.

Quick start (CLI, about 5 minutes)

Assumes the agent tools are installed in ./memodue and you have a funded devnet keypair. Every command prints JSON and exits 1 on a refusal.

# 1. Configure (environment only; keypairs are never command arguments)
export MEMODUE_KEYPAIR="$HOME/.config/solana/agent-devnet.json"    # pays create (and reads, if no reader keypair)
export MEMODUE_PAGE="https://devnet.memodue.com/index.html"         # links point at the official site (recommended, see Config)
# optional: export MEMODUE_RPC_URL="https://<your devnet RPC>"     # your own devnet RPC (see Own RPC)
cd memodue

# 2. Price check (reads the on-chain fee table)
node agent/cli.mjs quote

# 3. Create: unlocks in 2 min, readable for 60 s after that. Link goes to a 0600 file, not stdout.
printf '%s' 'meet at 10:00' > note.txt
node agent/cli.mjs create --in 2m --readable 60s --text-file note.txt --link-out link.txt

# 4. Status (needs only the address; no key, no fee)
node agent/cli.mjs status <account from step 3>

# 5. Read after unlock (a Solana transaction paid by your wallet, about 0.00002 SOL)
node agent/cli.mjs read --link-file link.txt

# 6. Close to get the rent back: no CLI command yet, use the SDK snippet in "Close and rent"
# 7. Delete the link when you are done
rm -f link.txt note.txt

Before unlock, read returns {"ok": false, "phase": "waiting"} and pays nothing. After expiry it returns "phase": "expired" and pays nothing.

Prerequisites

NeedDetails
Node.js 20+The SDK, CLI and MCP server are plain ES modules.
Agent toolsThe agent/ folder of the MemoDue source plus npm install. See Get the tools.
Devnet keypairA Solana keypair file (JSON array of 64 numbers, as written by solana-keygen new -o <file>). Keep it outside any repo, mode 600. Pass its path in MEMODUE_KEYPAIR.
Devnet SOLCreator: create fee (0.01 SOL for an AGENT Tier 1 note today) + rent (about 0.0033 SOL for a short note) + transaction fees. Budget 0.02 SOL. Reader wallet: at least 0.0036 SOL balance (about 0.0035 SOL is held during a read and returned). Get devnet SOL from a devnet faucet, e.g. solana airdrop 1 --url devnet.
RPCDefault: the public https://api.devnet.solana.com. If that is rate-limited or unreachable from your host, set MEMODUE_RPC_URL to your own devnet RPC (rules and risks).
Network accessYour RPC, https://api.drand.sh (time-lock beacons). Arcium reads go through Solana transactions, so no extra host.

Get the tools

This website does not serve the agent tools: agent/sdk.mjs, agent/cli.mjs, agent/mcp.mjs and scripts/ are only in the MemoDue source repository, which is not public yet. Ask the operator for access. The browser modules this site serves (chain.js, gate-create.js, …) are the same code but expect a bundler or import map, not a plain Node install.

# with access to the source repository
git clone <MemoDue repository URL> memodue
cd memodue
npm install                     # @solana/web3.js, tlock-js (Node 20+)
node agent/cli.mjs quote        # smoke test: prints the AGENT Tier 1 fee as JSON

What is in agent/: sdk.mjs (Node SDK), cli.mjs (JSON command line), mcp.mjs (local MCP stdio server), rpc.mjs (own-RPC checks), lit-route.mjs (optional Lit route), README.md.

Config (environment variables, never tool arguments)

VariableUse
MEMODUE_KEYPAIRPath to the payer / creator keypair file. Required to create. Also pays Arcium reads when no reader keypair is set.
MEMODUE_READER_KEYPAIROptional reader wallet: pays Arcium reads. Required for reader-bound notes (created with --reader <wallet>).
MEMODUE_PAGEPage the returned link points at. Set it to https://devnet.memodue.com/index.html, the official site (also the built-in default of current tools; older copies default to a temporary host a human cannot open). https://memodue-devnet.onrender.com/index.html is the same site on the fallback host and also works. Any other host prints a warning: whoever serves the page a link opens sees the note key. The link always uses read.html in that page's folder.
MEMODUE_RPC_URLOptional: your own devnet RPC (Own RPC).
MEMODUE_GATE_CONFIGOptional JSON file overriding the gate settings. Not needed: without it the tools use the devnet Arcium gate this website uses.
MEMODUE_AGENT_LIT_KEYOptional: your own Lit usage key, only for --tier lit (Tiers).
MEMODUE_GATE_DEMO, MEMODUE_WRITERLocal demo / test stand-ins only. Leave unset for real devnet notes.

Create

CLI (flags: --tier tier1|arcium|lit|icp (default tier1), --in <duration> (default 5m) or --at <ISO time>, --readable <duration> (default 24h), --text "…" or --text-file f, --reader <wallet>, --max-fee <lamports> (the most you agree to pay as the create fee; default the fee table fee read at create time), --link-out f; durations like 90s, 30m, 2h, 1d):

node agent/cli.mjs create --in 30s --readable 60s --text-file note.txt --link-out link.txt

Example result (devnet, 2026-10-17; the link is written to link.txt, never printed):

{
  "account": "B1bPrsZW92H3JfihWYrSsd4V5YCc4p6DSdGDg8jZBGtM",
  "link": "(written to link.txt)",
  "tier": "tier1",
  "mode": "ARCIUM_GATED",
  "class": "AGENT",
  "unlockUnix": 1792206426,
  "expiryUnix": 1792206486,
  "clampedToCap": false,
  "signatures": ["4G2jWa9L…"]
}

SDK (run from the repository root):

import { createAgentNote, loadAgentGateConfig, loadKeypair } from "./agent/sdk.mjs";

const gateConfig = await loadAgentGateConfig();          // devnet Arcium Tier 1 by default
const payer = loadKeypair(process.env.MEMODUE_KEYPAIR);   // never a tool argument
const { account, link, unlockUnix, expiryUnix } = await createAgentNote({
  text: "meet at 10:00", payer, gateConfig,
  tier: "tier1",                 // default (Arcium). "lit" needs your own Lit key; "icp" is off
  unlockIn: "2h",                // or unlockAt: "2026-10-18T09:00:00Z"; Tier 1: at most 24 h after now
  readable: "24h",               // at least 60 s; expiry at most 48 h after now (longer is clamped)
  // rpcUrl: "https://…",        // optional, same rules as MEMODUE_RPC_URL
});
// link is SECRET: store it (e.g. a 0600 file) and hand it only to the reader.

Read

node agent/cli.mjs read --link-file link.txt
import { loadAgentGateConfig, loadKeypair, readNote } from "./agent/sdk.mjs";
const r = await readNote({ link, gateConfig: await loadAgentGateConfig(),
  payer: loadKeypair(process.env.MEMODUE_READER_KEYPAIR ?? process.env.MEMODUE_KEYPAIR) });
// never throws on a refusal:
// { ok: true, plaintext, mode: "ARCIUM_GATED", class: "AGENT", expiryUnix, gate: { costLamports, timing, signatures } }
// { ok: false, phase: "waiting" | "expired" | "closed-or-missing" | "needs-sol" | …, reason }

Close and get the rent back

A note holds rent (about 0.0033 SOL for a short note; rent for 110 bytes + ciphertext). Nothing closes a note automatically. The SDK, CLI and MCP server have no close command yet; close with creatorCloseSealedAccount from web/chain.js in the same repository:

import * as web3 from "@solana/web3.js";
import { loadKeypair } from "./agent/sdk.mjs";
import { connectAgentRpc } from "./agent/rpc.mjs";       // honours MEMODUE_RPC_URL, checks devnet genesis
import { creatorCloseSealedAccount } from "./web/chain.js";

const { connection } = await connectAgentRpc({ web3 });
const creator = loadKeypair(process.env.MEMODUE_KEYPAIR);
const { signature } = await creatorCloseSealedAccount({ web3, connection, creator, account });
process.exit(0);   // web3.js may keep sockets open; end one-shot scripts explicitly
WhoWhen (Solana clock)Gets
Creator (signs)from unlock (an unfinished write: any time; a finally taken-down note: at once)the note's lamports minus the tombstone rent; no tip
Anyone (keeper)from the note's expirythe close tip (tip stored in the note at create, 10,000 lamports by default); the creator still gets the rest

Tiers

TierStatus for agentsUnlockReadable untilWho pays a read
tier1 = arcium (default)On. Devnet gate 5HEfLzYwRBi3jAQFnUeF8L6HvD1VaFDFDUpSEt3zMi6R, Arcium cluster 456; same gate as the website.≤ 24 h after creating≥ 60 s after unlock, ≤ 48 h after creatingthe reader's wallet, ~20,623 lamports
litOptional, only with your own Lit usage key (MEMODUE_AGENT_LIT_KEY), scoped to MemoDue's action CIDs; never a master or wildcard key. MemoDue never ships or pays for a Lit key. Refused without one.≤ 24 h≤ 48 hyour Lit account
icp (Tier 2)Off until its gate is deployed (refused with gate-off).———

There is no Plain (ungated) tier for new notes (error 31 PLAIN_CREATE_RETIRED). The class (AGENT / HUMAN) is declared by the creator and priced, not verified.

Costs (devnet SOL)

ItemAmountPaid by / refunded?
Create fee, AGENT Tier 1 (Arcium)10,000,000 lamports (0.01 SOL) on 2026-10-17creator → treasury; never refunded. Set in the on-chain fee table (PDA 6CqA1DeaCwaYYP2JnJ4R1AVfJDjtw6Vp1eABAy8nN9H7) and can change: always run quote first (draftPrice: true means the table could not be read).
Note rent~3,322,320 lamports for a short note; more for longer textcreator; refunded on close minus the tombstone
Tombstone650,240 lamportstaken from the note's rent at close; never refunded
Arcium read~20,623 lamports per readreader's wallet; a refused read costs nothing
Read deposit~0.0035 SOL held during a readreader's wallet; returned in the same read flow (needs ≥ 0.0036 SOL balance)
Transaction fees~5,000 lamports per signature (plus a small priority fee)signer

Measured end to end (2026-10-17): create 13,332,320 lamports (fee + rent + tx), one read 20,623, close refund 2,667,080; net about 0.0107 SOL for one note read once.

Limits

LimitValueIf exceeded
Plaintext4096 UTF-8 bytesrefused before anything is sent
Unlock (Tier 1)in the future, ≤ 24 h after creating; rounded up to the next drand round (≤ 3 s later)refused (error 30 UNLOCK_TOO_FAR), nothing paid
Readable window≥ 60 s after unlockrefused (error 27 EXPIRY_INVALID), nothing paid
Expiry (Tier 1)≤ 48 h after creatingthe tools clamp it to the cap (clampedToCap: true); the program refuses a later one (error 28)
Clusterdevnet onlymainnet URLs and the mainnet genesis are refused

Errors your agent will see

phase / codeMeaningWhat to do
waitingbefore unlock (chain clock)wait until unlockUnix, retry; nothing was paid
expiredafter expiry; the gate no longer releases the keyfinal; close the note to get the rent back
closed-or-missingaccount not found (closed, or wrong address)final for gated notes
taken-down, suspendedmoderation takedown or gate suspensionno read; see the Terms
needs-walletno keypair configured for an Arcium readset MEMODUE_READER_KEYPAIR or MEMODUE_KEYPAIR
needs-solreader wallet below ~0.0036 SOLfund the reader wallet
needs-reader-walletnote is bound to one reader walletset that wallet as MEMODUE_READER_KEYPAIR
gate-refusedthe gate refused; gateError e.g. Locked, TakenDown, BindingMismatchread reason; Locked = retry later
gate-offtier not available (ICP, or Lit without your own key)use tier1
GatedCreateRefused (error.code)UNLOCK_TOO_FAR, EXPIRY_TOO_FAR, EXPIRY_INVALID, GATE_PAUSED, GATE_RETIRED, FEE_TABLE_MISSING, TOMBSTONED, PLAIN_CREATE_RETIRED, FEE_ABOVE_MAXfix the input or retry later; nothing was signed or paid (FEE_ABOVE_MAX: the fee went up after you read it; quote again)
SANCTIONS_MATCH / BlockedByProgramwallet on the sanctions list or an enforced on-chain blockliststop; do not work around it

Raw program error numbers: Program errors.

MCP server (local, stdio)

node agent/mcp.mjs speaks newline-delimited JSON-RPC (initialize, tools/list, tools/call, ping). It runs on your machine, so plaintext and keys stay there. Client config (Claude Desktop / Cursor style):

{
  "mcpServers": {
    "memodue": {
      "command": "node",
      "args": ["/absolute/path/to/memodue/agent/mcp.mjs"],
      "env": {
        "MEMODUE_KEYPAIR": "/home/me/.config/solana/agent-devnet.json",
        "MEMODUE_PAGE": "https://devnet.memodue.com/index.html"
      }
    }
  }
}
ToolArgumentsReturns
memodue_quotetier?, class? (agent)feeLamports, readCostLamports, caps, rules
memodue_create_gated_notetext, tier?, unlock_in? (5m) or unlock_at?, readable_for? (24h), reader?, max_fee_lamports? (decimal string; default the fee read at call time)account, link (SECRET), unlockUnix, expiryUnix, maxFeeLamports
memodue_note_statusaccountmode, class, times, takedown, phase
memodue_read_notelinkok + plaintext, or ok: false + phase
memodue_closeaccountclosed + refundedLamports + tombstone (creator only: MEMODUE_KEYPAIR must be the note's creator; the tombstone is never returned)

Refusals come back as results with ok: false, not as protocol errors. A keypair argument is rejected. There is no close tool yet (see Close and rent).

Own RPC (MEMODUE_RPC_URL)

Rules for an agent

  1. Devnet only. Mainnet needs explicit human approval for that specific action.
  2. Use the SDK, CLI or MCP server. If you must build transactions yourself, match codec.js and gate-core.js exactly.
  3. Never put plaintext, k1 or k2 in an instruction, account, log, memo, or URL query. The key goes in the fragment only.
  4. Treat the full link as a secret; hand it only to the intended reader.
  5. The create and close helpers screen wallets against the bundled sanctions list (sanctions.js, sanctions/solana.json, OFAC SDN Solana addresses) and throw a SanctionsRefusal (error.code === "SANCTIONS_MATCH") before building anything. Do not work around it.
  6. After the program upgrade the program itself refuses create and keeper close for a wallet flagged by an enforced blocklist (error 17), and every close whose rent would go to a flagged creator (error 22, frozen, not redirected); chain.js throws BlockedByProgram with neutral text. Do not work around it either.
  7. Never commit keypairs, .env files, RPC keys or secret keys.

Reference (protocol details)

Everything below is for developers building their own client or keeper. The tools above already handle it.

Network and fee config

Cluster
Solana devnet only
RPC
https://api.devnet.solana.com (this website uses only the public devnet RPC). Agent tools may use their own devnet RPC: see Own RPC.
Devnet genesis
EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG
Program id
GSmXLpt1f6EBMKTBtr3eVQy92FHARv4JKQfV1khUD16H
Legacy create fee
Loading current fee…
Read live from the on-chain fee config AWNG8sSVtCyBW4tws9NtB6ETgwoUw9BpYuAjoedNasqv. Hard cap 1000000000 (1 SOL). Charged only by the retired Plain initialize / begin. Not what an agent pays: gated (version 5) creates pay the fee table (Costs).
Fee config PDA
Seed fee_config under the program id. Create must pass this account.
Treasury
Taken from the fee config (bootstrap default GJgPDoCQuiDyKUzqQwYb1TaigdJT6akr72kbFqx8wFRz)
Fee authority
Dedicated keypair stored in the fee config. Only that signer can update the fee or treasury. Separate from the program upgrade authority, which appoints it at init (after the hardening upgrade only the upgrade authority can run init). Handover is two-step: the current authority proposes a key (opcode 12, pending-handover PDA ["handover", config]), the proposed key signs accept (13) and becomes the authority; the current authority can cancel (14). Nothing in the config changes until accept. Opcode 11 (one-transaction handover) is disabled and fails with error 13.
Rent
Separate from the fee. Reclaimable by the creator via close (except an older note created with the retired close-lock). After unlock + grace anyone may close; the closer gets the close tip and the creator gets the rest.
Close tip
Loading… Paid from the note's lamports to a non-creator closer. Default 10000, hard cap 100000 lamports (0.0001 SOL). Set by the fee authority.
Close grace
Loading… Minimum seconds after the unlock time before anyone may close. Default 900 (15 min), allowed 0 to 2592000 (30 days). Set by the fee authority. After the hardening upgrade, a version 4 note (82-byte header, allocated with snapshot_account_len) stores the tip and grace from its creation and ignores later changes; older version 3 notes follow the live value. New notes are version 5 (gated) and store them too.
Mainnet
Not deployed. The modules refuse mainnet URLs and the mainnet genesis hash.

Create on the wire (version 5)

Every new note names a gate. There is no Plain (ungated) create any more: the program refuses the old initialize / begin and a version 5 create with mode PLAIN (error 31, PLAIN_CREATE_RETIRED).

close (opcode 1)

A program cannot run on its own, so nothing closes a note automatically. Instead anyone, for example a keeper bot, may close a note once its unlock time plus the grace has passed, and is paid the close tip for it.

import { fetchCloseParams, keeperCloseSealedAccount } from "./chain.js";
import { keeperCloseState } from "./close-rule.js";
// state = { closable, reason: "locked" | "not-due" | "due", dueUnix, tipLamports }
const state = keeperCloseState(note, nowUnix, await fetchCloseParams({ web3, connection }));
if (state.closable) await keeperCloseSealedAccount({ web3, connection, closer, account });

A dry-run keeper that lists closable notes: node scripts/keeper.mjs in the source repository (add --send --keypair <path> to close them; devnet only).

Humans can do the same on due.html (Due notes): it reads every program account header with getProgramAccounts and an 82-byte dataSlice, fetches full data only for notes past unlock, applies the same keeperCloseState (per-note tip and grace for version 4), lists due notes most overdue first and the ones still in grace, and closes with keeperCloseSealedAccount. Logic without DOM or RPC is in due-core.js (classifyDueNotes).

Close helpers (web/chain.js)

import { creatorCloseSealedAccount, keeperCloseSealedAccount, openSealedAccount } from "./chain.js";

await creatorCloseSealedAccount({ web3, connection, creator, account }); // creator, from unlock (unfinished: any time); { signature, mode }
await keeperCloseSealedAccount({ web3, connection, closer, account });   // anyone, after unlock + grace, earns the tip
await openSealedAccount({ web3, connection, payer, account });           // optional attestation, after the round, anyone

Time lock (drand quicknet)

Chain hash
52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971
Genesis
unix 1692803367
Period
3 seconds
Relay
https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971
round(T)       = floor((T - 1692803367 + 2) / 3) + 1
publication(r) = 1692803367 + (r - 1) * 3

open (opcode 4)

Known hole

The program does not decrypt the tlock body and cannot prove it was locked to the stored round. A creator can store an undecryptable body and close after the round and take back the rent. This is documented. There is no penalty, because the chain cannot tell it apart from an honest open then close. (The opt-in close-lock that kept an account on chain for good is retired for new notes.)

Reading older Plain notes

Gated notes: use readNote (Read). Gated unlock and expiry are decided by the Solana blockchain clock (Clock sysvar unix_timestamp at SysvarC1ock11111111111111111111111111111111), not the agent's device clock. Read it with getAccountInfo, or retry on a before-unlock refusal (Locked / BeforeUnlock); gates apply no grace. Drand-timelocked plaintext still opens on its drand round, independent of that clock.

import { parseNoteUrl } from "./link.js";
import { connectDevnet, fetchSealedAccount } from "./chain.js";
import { openHybridNote } from "./tlock.js";

const { account, rawKey } = parseNoteUrl(link);
const { connection } = await connectDevnet(web3);
const note = await fetchSealedAccount({ web3, connection, account });
const result = await openHybridNote({
  ciphertext: note.ciphertext, iv: note.iv, rawKey,
  revealUnix: note.revealUnix, nowUnix: Math.floor(Date.now() / 1000),
});
// result.status is "sealed" (with secondsRemaining) or "revealed" (with plaintext)

Program errors

Custom errorNameMeaning
1ROUND_NOT_DUEopen, or a creator close of a finished note, before the round's publication time
2quicknet signature or witness does not verify
3NOT_OPENunsigned two-account close of a finished note before open (before PR 47 also the creator close)
4REFUND_NOT_DUEnon-creator close of an unfinished write before reveal_unix + 86400
5IDENTITY_MISMATCHfirst tlock stanza does not name the stored round or the quicknet chain hash
6CLOSE_LOCKEDclose of an older finished note whose close-lock was set (new notes cannot be locked)
7FEE_TOO_HIGHfee config init/update with create fee above 1 SOL (1_000_000_000 lamports)
8TIP_TOO_HIGHclose tip above 100_000 lamports
9GRACE_TOO_LONGclose grace above 2_592_000 seconds (30 days)
10CLOSE_NOT_DUEpermissionless close before reveal_unix + close_grace_secs
11CONFIG_NOT_MIGRATEDtip/grace update (opcode 10) on a version 1 fee config
12NOT_UPGRADE_AUTHORITYfee config init (opcode 7) not signed by the program's upgrade authority, or a wrong ProgramData account (hardening upgrade)
13–16owner handover13 direct handover disabled, 14 nothing pending, 15 not the proposed key, 16 stale proposal (also 14/15/16, and 13 for opcode 22, for the compliance authority handover)
17ADDRESS_BLOCKEDcreate by a creator, or keeper close by a closer, flagged by an enforced blocklist (on-chain blocklist upgrade)
18BLOCKLIST_ACCOUNTS_MISSINGcreate, creator close, keeper close or update_fee_config without the blocked PDA(s) and compliance config, or with wrong ones (old account layout)
19NOT_LIST_UPDATERset blocked (opcode 17) or list source (20) not signed by that list's updater
20NOT_COMPLIANCE_AUTHORITYlist change (16) or compliance handover propose/cancel (18, 21) not signed by the compliance authority (the fee authority has no compliance rights once the keys differ)
21LIST_IN_USEremoving or renaming a list that still flags wallets
22RECIPIENT_SANCTIONEDa close whose rent goes to a creator, or a fee update naming a treasury, flagged by an enforced blocklist; the lamports stay frozen in the note (on-chain blocklist upgrade)
23TAKEN_DOWNopen of a note under takedown (pending or final)
24TAKEDOWN_FINALa change to a note whose takedown is final
25GATE_RETIREDnew note in a retired gate mode
26GATE_PAUSEDnew note while that gate mode is paused
27EXPIRY_INVALIDexpiry less than 60 s after unlock
28EXPIRY_TOO_FARexpiry later than the tier cap (Tier 1: 48 h after creating)
29FEE_TABLE_MISSINGgated create without a priced fee table row
30UNLOCK_TOO_FARTier 1 unlock more than 24 h after creating
31PLAIN_CREATE_RETIREDa new note without a gate: the old initialize / begin (opcodes 0 and 2, always Plain) or a version 5 create with mode PLAIN. Every new note names a gate (Arcium, ICP or Lit). Existing Plain notes still read, open, close and expire (Plain-removal upgrade)
32TOMBSTONEDcreate at a note address that was closed before (its ["tomb", note] PDA holds lamports); make a new note
33FEE_ABOVE_MAXgated create with a max fee (flag 0x04) while the fee table charges more for its mode and class (for example a fee raise landed first); no create fee is taken. Quote again

Opcodes

OpcodeInstructionFee
0initialize, Plain (retired: error 31 after the Plain-removal upgrade; older transactions only)create fee
5initialize, close locked (retired; older transactions only)create fee
2begin, Plain (retired: error 31 after the Plain-removal upgrade; older transactions only)create fee
6begin, close locked (retired; older transactions only)create fee
3append (creator only)tx fee only
4open (anyone, after the round; optional)tx fee only
1close (creator; or anyone after unlock + grace)tx fee only; a non-creator closer earns the close tip
7init fee configtx fee only (creates the PDA, version 2; after the hardening upgrade the program's upgrade authority must sign)
8update fee config (fee, treasury)tx fee only (fee authority must sign)
9migrate fee config v1 → v2 (optional tip, grace)tx fee + rent for 16 bytes (fee authority signs and pays)
10update close tip and gracetx fee only (fee authority must sign)
11set fee authority (disabled: custom error 13, use 12 + 13)—
12propose fee authority (creates or overwrites the 74-byte handover PDA)tx fee + handover rent, returned on accept or cancel (current fee authority signs and pays)
13accept fee authority (sets it, closes the handover PDA)tx fee only (proposed key signs; rent back to the proposer)
14cancel fee authority proposaltx fee only (current fee authority signs; rent back to the proposer)
15init compliance config (747-byte PDA ["compliance", fee config]; authority = fee authority; slot 0 = manual override)tx fee + rent (fee authority signs and pays; it becomes the initial compliance authority)
16set list (slot, 8-byte id, updater, enabled; empty id removes an unused list)tx fee only (compliance authority signs)
17set blocked (slot, set/clear, wallet, 32-byte reason): sets or clears that list's bit in the 76-byte PDA ["blocked", wallet], closed when no bit is lefttx fee + PDA rent on the first flag, back to the signer on the last clear (list updater signs; the compliance authority may also clear)
18propose compliance authority (creates or overwrites the 74-byte PDA ["compliance-handover", compliance config]); accounts compliance config, compliance authority (w, signer), handover PDA (w), system programtx fee + handover rent, returned on accept or cancel (compliance authority signs and pays; the fee authority cannot)
19accept compliance authority; accounts compliance config (w), handover PDA (w), proposed (signer), proposer (w)tx fee only (proposed key signs; rent back to the proposer)
20set list source (slot, 32-byte source hash)tx fee only (list updater signs)
21cancel compliance authority proposal; accounts compliance config, compliance authority (signer), handover PDA (w), proposer (w)tx fee only (compliance authority signs; rent back to the proposer)
22set compliance authority (disabled: custom error 13, use 18 + 19)—

Fee config layout (version 2, 89 bytes, little-endian)

OffsetField
0version 2 (version 1 = 73 bytes, no tip or grace, reads as the defaults)
1create fee lamports, u64
9treasury pubkey, 32 bytes
41fee authority pubkey, 32 bytes
73close tip lamports, u64
81close grace seconds, u64

Account layout (version 3 and 4, little-endian)

OffsetField
0version 3 or 4
1state: 0 finished and sealed, 1 unfinished, 2 opened; bit 0x80 = close-lock (older notes only)
2reveal unix (round publication time), i64
10AES IV, 12 bytes
22creator pubkey, 32 bytes
54ciphertext length, u32
58quicknet round, u64
66version 3: tlock ciphertext (unarmored age file), 16 to 4608 bytes. Version 4: close tip lamports u64 at 66, close grace seconds u64 at 74, ciphertext from 82

Human UI

Pages: Create, Read, Due notes, FAQ, Uses, Authority, Upgrade, Compliance, Terms.