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

planes source realm

v0 - Unaudited: This is an initial version that has not yet been formally audited. Use in production at your own risk.

Overview

v0 - Unaudited: This is an initial version that has not yet been formally audited. Use in production at your own risk.

Package planes is a collection of 777 plane NFTs that pilots fly in gnofly, a multiplayer plane game. It is a GRC721 token built on gno.land/p/nt/grc721/v0 with the royalty extension.

Every plane is drawn in a table committed with the realm (table.gno): a name, one of the nine models the game client draws, a pilot (none or a gnome), three colours, a tier and the colour of its laser, the shots every pilot sees it fire. The designs stay procedural in the client; the token stores only these traits. Id 777 is the super-gnome, a 1/1 that is a gnome flying like a superhero rather than a plane. The table is public; which ids a mint gets is drawn at random among the ones left, 1 to 7 per call (draw.gno).

Three kinds of callers write to it:

  • anyone mints the next plane with the price attached (Mint), transfers, approves and burns their planes (TransferFrom, Approve, SetApprovalForAll, Burn);
  • the admins of the game realm open and close the mint and tune its price, its per-wallet cap, the image URL and the royalty (SetMintOpen, SetPrice, SetMintCap, SetImageBase, SetRoyaltyBps);
  • nobody else: there is no reserve and no airdrop.

The realm keeps no roles and no money of its own. The admins are those of gno.land/r/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/game/v0, asked at the time of each call, and every mint is forwarded to its treasury in the same transaction. The royalty of a resale, 5% by default, names the treasury too.

Reads are plain functions meant for vm/qeval. The ones ending in JSON return a single string holding a JSON document. PlanesOf and OwnerOf are what the game server reads: ownership is the only on-chain fact of a plane, which one a pilot flies is picked in the game's hangar and checked against OwnerOf by the server. Render exposes the same data as markdown for gnoweb. The read side of the token and of its royalty extension is exported as Token and Royalties, for other realms. No metadata is stored per token: TokenMetadata and TokenURI are computed from the table and the image base on every read.

Storage is paid for at deploy, so the realm is kept small: the table is one string read in place, refusals are string constants, and the settings are read through CollectionJSON rather than one getter each.

Variables 1

var Token, Royalties

1var (
2	Token     *grc721.Token    // name, symbol, owners, balances, approvals
3	Royalties *royalty.Royalty // EIP-2981 royalty
4)
source

The read side of the collection, exported for other realms and for vm/qeval, as GRC721 tokens are on gno.land. Neither type has a mutator: a Token hands out tellers that act as the calling realm and go through the ledger's approval checks, Royalty only reads. There is no metadata extension: the traits are in the table, read with TokenMetadata(tid) and PlaneJSON(id), and the token URI, the image, is computed by TokenURI(tid).

Example
1planes.TokenMetadata("42")
2planes.Token.RealmTeller(0, cur).TransferFrom(0, cur, from, to, "42")

Functions 22

func Approve

crossing Action
1func Approve(cur realm, to address, id int64)
source

Approve lets to move plane id once. The caller must own it. An empty address revokes.

func BalanceOf

Action
1func BalanceOf(addr address) (int64, error)
source

BalanceOf returns how many planes addr owns.

func Burn

crossing Action
1func Burn(cur realm, id int64)
source

Burn destroys a plane. Only its owner can, and nobody can mint it again: the id stays out of circulation.

func CollectionJSON

Action
1func CollectionJSON() string
source

CollectionJSON returns the state of the collection as one JSON object:

Example
1{ "name": "gnofly planes", "symbol": "PLANE",
2  "supply": 777, "minted": 12, "burned": 0,
3  "price": 77000000, "open": true, "cap": 7,
4  "royaltyBps": 500, "treasury": "g1...",
5  "imageBase": "https://gnofly.xyz/nft/collections/planes/",
6  "tiers": { "common": { "supply": 500, "minted": 8 },
7             "rare": { "supply": 200, "minted": 3 },
8             "epic": { "supply": 70, "minted": 1 },
9             "legendary": { "supply": 7, "minted": 0 } } }

The output has no whitespace. "minted" counts every mint so far, burned planes included; "minted" minus "burned" is what exists.

func IsApprovedForAll

Action
1func IsApprovedForAll(owner, operator address) bool
source

IsApprovedForAll reports whether operator may move every plane of owner.

func Mint

crossing Action
1func Mint(cur realm, count int64) []int64
source

Mint mints count planes for the caller, 1 to 7 in one call, drawn at random among the ids not minted yet (draw.gno), and returns their ids in the order drawn. Exactly count times the price must be attached to the transaction (-send "<count*price>ugnot"); it is forwarded to the treasury of the game realm, in one send, before the call returns.

Each id comes out once, while the mint is open. A batch is minted whole or not at all: one that would take the caller over the per-wallet cap, or past the last plane, is refused with how many are left. It must be called directly by a user (maketx call): a call relayed by another realm or by a maketx run script is refused. That is also what keeps the draw fair: a contract could otherwise look at the ids it got and panic to draw again.

The caller pays the storage of their planes as a deposit on top of the price, given back on burn: the ledger entries only, the traits stay in the table (see the numbers in docs/spec.md, section 9.2).

func Minted

Action
1func Minted() int64
source

Minted returns how many planes were minted so far, burned ones included. Planes are drawn at random, so it says nothing of which ids. The settings (price, open, cap, image base, royalty) are read with CollectionJSON: every exported function costs storage at deploy, measured at about 650 bytes each, so there is no getter per setting.

func MintedJSON

Action
1func MintedJSON(offset, limit int64) string
source

MintedJSON returns who owns the minted planes among the ids offset+1 to offset+limit, as a JSON array in id order:

Example
1[{"id":3,"owner":"g1..."},{"id":42,"owner":""},...]

Ids not minted are left out; "owner" is "" for a burned plane. limit is capped at 200, so four calls (offsets 0, 200, 400, 600) cover the 777, whatever was minted: planes are drawn at random, minted ids are not a prefix. It is what the website's grid reads. An empty range is [].

func PlaneJSON

Action
1func PlaneJSON(id int64) string
source

PlaneJSON returns one plane as a JSON object, minted or not:

Example
1{ "id": 42, "name": "Storm Saint", "model": "delta", "pilot": "gnome",
2  "body": "#1e1b4b", "wing": "#1e293b", "accent": "#00f5ff", "tier": "epic",
3  "laser": "#39ff14", "image": "https://gnofly.xyz/nft/collections/planes/042.png", "owner": "g1..." }

The output has no whitespace. "owner" is "" for a plane not minted, or burned. An id outside 1 to 777 returns "". Which plane a pilot flies is not on-chain: the game server checks the owner when a pilot picks one.

func PlanesOf

Action
1func PlanesOf(addr address) string
source

PlanesOf returns the ids of the planes addr owns as a JSON array, in ascending order: [3,42,700]. It is [] for an address without planes.

func Render

1func Render(path string) string
source

Render returns the state of the collection as markdown, for gnoweb:

Example
1""               the collection: minted, price, tiers, the last mints
2"plane/<id>"     one plane: traits, owner
3"player/<addr>"  the planes of one address

Everything printed here is a row of the table, whose charset the tests pin, a setting validated when it was written, or an address the chain gave the realm. The two caller-supplied values, an id and an address, are printed only once parsed and found valid. Nothing needs markdown escaping. No images: the planes are drawn by the game and by the website.

func SetApprovalForAll

crossing Action
1func SetApprovalForAll(cur realm, operator address, approved bool)
source

SetApprovalForAll lets operator move every plane of the caller, or revokes it.

func SetImageBase

crossing Action
1func SetImageBase(cur realm, base string)
source

SetImageBase sets where the images and the metadata of the planes are served from: the image of plane 42 is <base>042.png and its token URI is <base>42.json. Admin only.

It applies at once to every plane: the URLs are computed on read, nothing is stored per token.

func SetMintCap

crossing Action
1func SetMintCap(cur realm, n int64)
source

SetMintCap sets how many planes one wallet may mint over its lifetime, from 1 to 777. Admin only. A wallet already over a lowered cap keeps its planes and mints no more.

func SetMintOpen

crossing Action
1func SetMintOpen(cur realm, open bool)
source

SetMintOpen opens or closes the mint. Admin only. The mint starts closed.

func SetPrice

crossing Action
1func SetPrice(cur realm, ugnot int64)
source

SetPrice sets what a mint costs, from 1 to 10000 GNOT. Admin only. It applies to the next mint.

func SetRoyaltyBps

crossing Action
1func SetRoyaltyBps(cur realm, bps int64)
source

SetRoyaltyBps sets the royalty of a resale, from 0 to 1000 basis points, and points it at the treasury of the game realm as it is now. Admin only.

The royalty is advisory, as EIP-2981 is: a marketplace reads RoyaltyInfo and pays it, the realm cannot enforce it on a transfer.

func TokenMetadata

Action
1func TokenMetadata(tid grc721.TokenID) (string, error)
source

TokenMetadata returns the metadata of a minted plane as JSON, built from the table on every read: the realm stores no metadata per token.

Example
1{"name":"Storm Saint","description":"Plane 42 of 777, ...",
2 "image":"https://gnofly.xyz/nft/collections/planes/042.png",
3 "attributes":[{"traitType":"model","value":"delta"}, ...]}

The keys are the ones Adena reads, traitType included.

func TokenURI

Action
1func TokenURI(tid grc721.TokenID) (string, error)
source

TokenURI returns the image of a minted plane, "<image base><nnn>.png": what a wallet shows (Adena puts it in an <img>). The metadata is TokenMetadata, or "<image base><id>.json" on the website. It is computed, not stored: a mint writes no URI.

func TransferFrom

crossing Action
1func TransferFrom(cur realm, from, to address, id int64)
source

TransferFrom moves plane id from one address to another. The caller must own it or be approved for it.

Imports 15

Source Files 11