1package vault23import (4 "chain"5 "chain/runtime/unsafe"6 "strconv"7 "strings"89 "gno.land/p/nt/avl/v0"10)1112// vaults maps address string -> *avl.Tree (key string -> value string).13var vaults avl.Tree1415// vaultFor returns the caller's namespace tree, creating it if needed.16func vaultFor(owner address) *avl.Tree {17 k := owner.String()18 if v := vaults.Get(k); v != nil {19 return v.(*avl.Tree)20 }21 t := &avl.Tree{}22 vaults.Set(k, t)23 return t24}2526// Set stores value under key in the caller's own namespace.27func Set(cur realm, key string, value string) {28 if key == "" {29 panic("key must not be empty")30 }31 caller := unsafe.PreviousRealm().Address()32 t := vaultFor(caller)33 t.Set(key, value)34 chain.Emit("VaultSet", "owner", caller.String(), "key", key)35}3637// Delete removes key from the caller's own namespace.38func Delete(cur realm, key string) {39 caller := unsafe.PreviousRealm().Address()40 k := caller.String()41 v := vaults.Get(k)42 if v == nil {43 panic("no vault for caller")44 }45 t := v.(*avl.Tree)46 if _, removed := t.Remove(key); !removed {47 panic("key not found")48 }49 if t.Size() == 0 {50 vaults.Remove(k)51 }52 chain.Emit("VaultDelete", "owner", caller.String(), "key", key)53}5455// Render shows all vaults (root) or a single address's entries ("/<address>").56func Render(path string) string {57 p := strings.TrimPrefix(path, "/")58 if p == "" {59 return renderRoot()60 }61 return renderAddress(p)62}6364func renderRoot() string {65 var b strings.Builder66 b.WriteString("# Key-Value Vault\n\n")67 b.WriteString("A per-address key-value store. Each caller owns their own namespace; only the owner can mutate their entries.\n\n")68 if vaults.Size() == 0 {69 b.WriteString("_No vaults yet. Call `Set(cur, key, value)` to create one._\n")70 return b.String()71 }72 b.WriteString("## Vaults\n\n")73 b.WriteString("| Address | Entries |\n")74 b.WriteString("|---|---|\n")75 vaults.Iterate("", "", func(k string, v interface{}) bool {76 t := v.(*avl.Tree)77 b.WriteString("| [")78 b.WriteString(k)79 b.WriteString("](/r:")80 // link back into this realm's render for the address subpage81 b.WriteString(k)82 b.WriteString(") | ")83 b.WriteString(strconv.Itoa(t.Size()))84 b.WriteString(" |\n")85 return false86 })87 b.WriteString("\nView an address's entries at path `/<address>`.\n")88 return b.String()89}9091func renderAddress(addr string) string {92 var b strings.Builder93 b.WriteString("# Vault: ")94 b.WriteString(addr)95 b.WriteString("\n\n")96 v := vaults.Get(addr)97 if v == nil {98 b.WriteString("_No vault for this address._\n")99 return b.String()100 }101 t := v.(*avl.Tree)102 b.WriteString("| Key | Value |\n")103 b.WriteString("|---|---|\n")104 t.Iterate("", "", func(k string, val interface{}) bool {105 b.WriteString("| ")106 b.WriteString(k)107 b.WriteString(" | ")108 b.WriteString(val.(string))109 b.WriteString(" |\n")110 return false111 })112 b.WriteString("\nTotal entries: ")113 b.WriteString(strconv.Itoa(t.Size()))114 b.WriteString("\n")115 return b.String()116}117Delete(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, key string)
Render(path string) string
Set(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, key string, value string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.