Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

v1 source realm

Package nsnft is the token, and only the token.

Overview

Package nsnft is the token, and only the token.

WHY THIS REALM EXISTS AT ALL.

A name here is a GRC-721. An external marketplace that wants to list one has to hard-code an address, and whatever address that is becomes the thing we can never move. Until now the interface was split: the READS lived on nsdata, which is permanent, and the WRITES — Approve, SetApprovalForAll, TransferFrom — lived on nslogic, which changed address three times in a single day. So the half an integrator needs in order to settle a sale was the half that kept moving, and the reads kept answering while it did, which is the worst way for it to break.

The fix is to pick ONE realm to freeze and make it the smallest, most boring one there is. That is this realm: an ownership ledger, the approval bookkeeping GRC-721 requires, the governance that decides who may mint, and nothing else. No prices, no expiry, no profiles, no policy — none of the things that will certainly need changing.

Everything with an opinion in it stays in the registry, which becomes replaceable BECAUSE ownership no longer lives there. A migration then moves records, not tokens: nobody's holdings are stranded and no listing anywhere goes stale, because the token contract never moved.

THE LEDGER IS THE CHAIN'S OWN gno.land/p/nt/grc721/v0, NOT A COPY.

chain.Emit stamps the package whose code emits, and wallets and indexers (Adena, the Onbloc indexer) accept only Transfer and NewToken events stamped gno.land/p/nt/grc721/v0. The first version of this realm minted on a vendored GRC-721 deployed under our own p/ path, so every event it would ever have emitted carried OUR path, and no wallet would ever have listed a single name — permanently, because events cannot be re-emitted and this realm cannot be replaced. The ledger object lives here, created once in init; only this realm holds its PrivateLedger, and no Teller is ever handed out (see the note on holds below).

THIS REALM HAS ITS OWN GOVERNANCE, AND THAT IS THE POINT.

It would be shorter to ask nsdata who the admin is. It would also re-couple this realm to the exact thing it exists to let us replace — nsnft would then depend on one nsdata forever and we would have moved the problem rather than solved it. So roles, trust and the timelock are local (governance.gno), and nsdata is not imported.

WHAT MAY BE CHANGED LATER AND WHAT MAY NOT.

May, slowly: which registries are trusted, the roles, the timelock, and which view realm draws the art. May, instantly: withdrawing a registry's trust or the art, which only ever removes a power. Through a trusted registry only: the hold bits on a token. May not: anything else. If this realm ever needs a new function, the design has failed and the honest answer is that it was not small enough to freeze.

Functions 43

func Approve

crossing Action
1func Approve(cur realm, to address, tid string)
source

Approve grants (or, to the empty address, withdraws) the per-token approval. Refused while the token is held: approvals do not pass through a ledger hook, so this is the one place the hold is checked.

func Burn

crossing Action
1func Burn(cur realm, tid string)
source

Burn destroys a token. Reachable only by a trusted registry, which calls it when a name lapses past its grace period and is reclaimed.

NOT reachable by the holder. A GRC-721 that lets an owner burn is correct for collectibles and wrong here: the token is a lease on a name, and destroying it would leave the registry holding a record for a name whose token no longer exists. Letting go of a name is letting it expire.

The hold and the epoch are cleared by the burn hook (holds.OnBurn), the per-token approval by the ledger itself.

func ClearRenderer

crossing Action
1func ClearRenderer(cur realm)
source

ClearRenderer withdraws the art at once, approval included, so the realm that drew it cannot simply register again: approving one takes the timelock. Admin, recovery or guardian.

func Epoch

Action
1func Epoch(tid string) int64
source

Epoch reports the ownership epoch of a token, or 0 for one that does not exist. See epochs.

func ExecutePending

crossing Action
1func ExecutePending(cur realm, kind string)
source

ExecutePending applies a matured change. Anyone may call it.

func ID

Action
1func ID() string
source

ID is the collection id wallets and indexers key on: "<this realm's path>.MNS.0000000".

func ListPending

Action
1func ListPending() string
source

ListPending names the kinds with a live pending change, comma-separated.

func LockBits

Action
1func LockBits(tid string) int
source

LockBits reports the current hold; 0 means free to move.

func Mint

crossing Action
1func Mint(cur realm, to address, tid string, lockBits int)
source

Mint creates a token, optionally already held in place.

`lockBits` is the hold it starts with — a free-tier name is minted locked so there is never an instant in which it could be approved and sold before the registry got round to locking it (nothing runs between the ledger write and the line that sets the bits). Zero for an ordinary paid name.

func ProposeAdminTransfer

crossing Action
1func ProposeAdminTransfer(cur realm, next address)
source

ProposeAdminTransfer rotates the admin after the timelock. Admin or recovery; when recovery proposes it, the admin cannot cancel it.

func ProposeRecoveryTransfer

crossing Action
1func ProposeRecoveryTransfer(cur realm, next address)
source

ProposeRecoveryTransfer rotates recovery after the timelock — twice the timelock when the admin proposes it. Admin or recovery; recovery can cancel either, so a stolen admin key cannot take it.

func ProposeRenderer

crossing Action
1func ProposeRenderer(cur realm, pkgPath string)
source

ProposeRenderer approves a view realm to draw the art, after the timelock. Admin only. The realm then registers itself (art.gno).

func ProposeTimelockDelay

crossing Action
1func ProposeTimelockDelay(cur realm, seconds int64)
source

ProposeTimelockDelay changes the timelock, after the current one. Admin only.

func ProposeTrust

crossing Action
1func ProposeTrust(cur realm, pkgPath string)
source

ProposeTrust starts trusting a registry, by package path, after the timelock. Admin only.

func RegisterRenderer

crossing Action
1func RegisterRenderer(cur realm, r Renderer)
source

RegisterRenderer is called BY the approved view realm, handing over the object that draws. Refused from anywhere else.

func Render

1func Render(path string) string
source

Render builds its string by concatenation rather than with ufmt.

NO DEPENDENCIES THIS REALM DOES NOT ABSOLUTELY NEED. It is meant to be deployed once and never replaced, so every import is a permanent commitment to somebody else's package. grc721/v0 (with avl and seqid, which it already depends on) is here because it IS the thing this realm is; a formatter, for one page of text, is not worth that.

func RevokeApproval

crossing Action
1func RevokeApproval(cur realm, tid string)
source

RevokeApproval withdraws a token's per-token approval.

grc721/v0 revokes by approving the empty address; this keeps the named entry point the site and tools already call, and allows it while the token is held — withdrawing a permission is the safe direction. The owner, or an operator acting for the owner, the same two callers Approve accepts.

func SafeTransferFrom

crossing Action
1func SafeTransferFrom(cur realm, from, to address, tid string)
source

SafeTransferFrom is kept for the standard signature. grc721/v0 has no receiver hook (gno has no contract-receiver registry to check), so it is TransferFrom — as the vendored version effectively was, its receiver check being a stub that always said yes.

func SetLock

crossing Action
1func SetLock(cur realm, tid string, bit int, on bool)
source

SetLock turns one hold bit on or off. Trusted registry only.

The registry decides what a bit means; this realm only guarantees that while any bit is set, nothing moves the token.

func TokenMetadata

Action
1func TokenMetadata(tid string) (string, error)
source

TokenMetadata is the token's metadata as a camelCase JSON string, the shape Adena reads. The image is not in it; that is TokenURI.

func TokenURI

Action
1func TokenURI(tid string) (string, error)
source

TokenURI is the token's image, as a data: URI, for a token that exists. A renderer that answers nothing gets the built-in card instead: an empty <img src> is a broken picture in every wallet.

func TransferFrom

crossing Action
1func TransferFrom(cur realm, from, to address, tid string)
source

TransferFrom carries NO expiry check, and that is a deliberate reversal of what nslogic once did.

Refusing to transfer an expired token is an anti-scam measure, and it belongs in the REGISTRY, not here: this realm does not know what expiry is and must not learn, because the moment it holds policy it stops being the small frozen thing it exists to be. The registry keeps the rule by refusing to RESOLVE an expired name. A buyer can still acquire a worthless token from a careless seller, which is true of every NFT on every chain, and the marketplace disclaimers say so.

The hold is checked here for a clear error and again by the ledger hook, which also moves the epoch.

func Trusted

Action
1func Trusted() string
source

Trusted lists every address that may mint or burn, comma-separated. nsdata compares this with its own address before adopting tokens, so the format is part of the contract: addresses only, no spaces.

func TrustedPath

Action
1func TrustedPath(registry address) string
source

TrustedPath reports the package path a registry was trusted as, or "".

func Untrust

crossing Action
1func Untrust(cur realm, registry address)
source

Untrust withdraws a registry's power to mint and burn, at once. Admin, recovery or guardian: removing a power is the safe direction, and a registry that has gone wrong must be stoppable in one transaction.

Types 1

type Renderer

interface
1type Renderer interface {
2	// TokenImage returns the image itself, as a data: URI.
3	TokenImage(tid string) string
4	// TokenMetadata returns the metadata as a JSON string: name,
5	// description, externalUrl, attributes [{traitType, value}].
6	TokenMetadata(tid string) string
7}
source

Renderer draws one token for wallets. Implemented by the view realm.

Dependencies

Source Files 4