Source: https://github.com/icdevsorg/icrc86-mo · Package: https://mops.one/icrc86-mo · Spec: icrc86.md
mops add icrc86-mo
ICRC-86 domain claims for Motoko: claim a domain, get it approved — by an administrator, or
automatically by a DNS-over-HTTPS check for a TXT record at _icrc86.<domain> — and let any canister ask
who controls a namespace.
Lifted from the CycleShareLedger's DomainMixin with the fee made injectable, the automated approval path
added, and icrc86_namespace_look_up answering the spec's question (controllers of the most specific
claimed prefix).
src/canisters/registry.mo is the deployable domain registry, one per network. On the IC it is
qnodb-fiaaa-aaaao-qqdwq-cai, charging 5 XDR per claim to ICDevs.org
(p75el-ys2la-2xa6n-unek2-gtnwo-7zklx-25vdp-uepyz-qhdg7-pt2fi-bqe). Every other canister that needs "may this principal publish under
com.example.myapp?" asks it:
let reg : actor { icrc86_namespace_look_up : shared query ([[Text]]) -> async [?{ domain : [Text]; controllers : [Principal] }] }
= actor "qnodb-fiaaa-aaaao-qqdwq-cai";
switch ((await reg.icrc86_namespace_look_up([["com", "example", "myapp"]]))[0]) {
case (?r) { /* r.controllers may publish; r.domain is the claim that says so */ };
case null { /* nobody has claimed anything above it: refuse, and say how to claim */ };
};icrc86_claim_domain({ domain = ["com", "example"]; ... })— pays the claim fee (a deployment setting; 5 XDR on the IC registry) and returns#ValidationRequired { validation = "…" }.- Publish that code as a TXT record at
_icrc86.example.com. icrc86_approve_domain({ domain; validationCode })— the registry asks two resolvers (Cloudflare and Google by default) and approves iff both see the code.#ValidationPendingmeans "not there yet"; try again after propagation.icrc86_claim_domainagain with the code — the domain is yours, and every namespace beneath it resolves to you until someone claims deeper with your controllers' approval.
Controllers can be several principals (controllers on the claim), and any current controller
can replace the set with icrc86_update_controllers -- no fee, no re-validation, on the record.
import ICRC86 "mo:icrc86-mo/mixin";
persistent actor {
include ICRC86({
getOwner = func() : Principal = owner;
canisterId = Principal.fromActor(this);
feeXdrPermyriad = 50_000; // 5 XDR; 0 disables the fee
feeLedger = Principal.fromText("ryjl3-tyaaa-aaaaa-aaaba-cai");
feeRecipient = { owner = treasury; subaccount = null };
providers = null; // cloudflare + google
outcallCycles = null;
addRecord = null; // or your ICRC-3 ledger's add_record
});
};mixin/include compiles under moc 1.14.1 and moxzi alike.
mops test # the decisions: namespace resolution, DoH parsing, the quorum rule
MOC_WASM=… MOXZI_WASM=… node pic/icrc86.test.mjs # a real replica, DNS answered by the test
The replica test issues real outcalls and answers them: a matching TXT approves, a wrong value and NXDOMAIN leave the claim pending, two resolvers disagreeing approves nothing.