README.md
GNFT
GRC721-compatible NFT contract for GnoSwap LP positions.
Overview
GNFT represents each liquidity position as a unique NFT. It exposes ownership, transfer, approval, and metadata operations while generating compact SVG artwork for tokens whose URI is stored in GNFT's parameter format.
GNFT implements the position-NFT surface used by GnoSwap; it does not expose
every optional GRC721 extension. In particular, this package has no token
enumeration API and does not expose safeTransferFrom.
Core Features
Ownership and approvals
- Transfer, single-token approval, and operator approval
- Owner, balance, existence, and approval queries
- Staked tokens are locked to the staker contract
- Other transfers use the GRC721 owner and approval checks
Dynamic SVG generation
- Generated tokens store compact gradient parameters
- Parameters are rendered to SVG and returned as a base64-encoded data URI
- Rendering occurs on
TokenURIreads rather than storing the full SVG - A custom non-empty URI set with
SetTokenURIis returned unchanged when it is not in GNFT parameter format
Storage
- Compact parameter storage reduces per-token metadata size
- Template-based SVG generation avoids storing repeated markup
Key Functions
Mint
Mints a new NFT for an LP position. Only the position role may call it.
Parameters:
cur realm: Current realm contextto address: Recipient addresstid grc721.TokenID: Token ID to mint
Returns: grc721.TokenID
Burn
Burns an NFT when its position is closed. Only the position role may call it.
Parameters:
cur realm: Current realm contexttid grc721.TokenID: Token ID to burn
TransferFrom
Transfers NFT ownership.
Parameters:
cur realm: Current realm contextfrom address: Current ownerto address: New ownertid grc721.TokenID: Token ID to transfer
For a token held by the staker contract, only the staker can move it. For other tokens, the owner, token approval, or operator approval must authorize the transfer.
TokenURI
Returns metadata for a token. When the stored URI parses as GNFT image
parameters (x1,y1,x2,y2,color1,color2), GNFT renders those parameters as an
SVG and returns a base64-encoded data URI. A custom non-empty URI that is not in
that parameter format is returned unchanged.
Parameters:
tid grc721.TokenID: Token ID
Returns: Token URI string and an error when the token or metadata is missing
SetTokenURI
Sets a non-empty token URI. Only the position role may call it.
Parameters:
cur realm: Current realm contexttid grc721.TokenID: Token IDtURI string: Non-empty metadata URI
Approve
Approves an address to manage a specific token.
Parameters:
cur realm: Current realm contextapproved address: Address to approvetid grc721.TokenID: Token ID
SetApprovalForAll
Approves or revokes an operator for all tokens owned by the caller.
Parameters:
cur realm: Current realm contextoperator address: Operator addressapproved bool: Approval status
Queries
Name() string: Collection nameSymbol() string: Collection symbolTotalSupply() int64: Number of minted NFTsBalanceOf(owner address) (int64, error): Number of NFTs ownedOwnerOf(tid grc721.TokenID) (address, error): Current ownerMustOwnerOf(tid grc721.TokenID) address: Owner or panic on errorExists(tid grc721.TokenID) bool: Whether a token existsGetApproved(tid grc721.TokenID) (address, error): Token approvalIsApprovedForAll(owner, operator address) bool: Operator approval
SVG Generation
Parameter Format
Generated token URIs store compact parameters:
"x1,y1,x2,y2,#COLOR1,#COLOR2"
Example: "10,12,125,123,#FF5733,#33B5FF"
Parameter Ranges
x1: 7-13y1: 7-13x2: 121-126y2: 121-126- colors: 6-digit hex (
#RRGGBB)
Rendering Process
- Mint: Generate pseudo-random parameters and store them as a CSV string
- TokenURI: Parse the CSV, generate SVG, encode it as base64, and return a data URI
- Display: The browser decodes the data URI and renders the SVG
The parameters use time-seeded math/rand; this is pseudo-random artwork
generation, not a security or cryptographic randomness source.
Usage
These helpers illustrate calls from an integrating realm. mintExample and
burnExample require that realm to hold the position role; transferExample
requires the caller to satisfy the ownership/approval rules described above.
1import (
2 "gno.land/p/nt/grc721/v0"
3 "gno.land/r/gnoswap/gnft"
4)
5
6func mintExample(cur realm, owner address, tokenID grc721.TokenID) grc721.TokenID {
7 return gnft.Mint(cross(cur), owner, tokenID)
8}
9
10func metadataExample(tokenID grc721.TokenID) (string, error) {
11 return gnft.TokenURI(tokenID)
12}
13
14func transferExample(cur realm, from, to address, tokenID grc721.TokenID) error {
15 return gnft.TransferFrom(cross(cur), from, to, tokenID)
16}
17
18func burnExample(cur realm, tokenID grc721.TokenID) {
19 gnft.Burn(cross(cur), tokenID)
20}
Security and Access Control
Mint,SetTokenURI, andBurnrequire the position role- Staker-held tokens can only be moved by the staker contract
- Other transfers are checked by the owner/approval rules in the GRC721 ledger
- Token URI parameters are validated before generated artwork is rendered
- Generated artwork uses pseudo-random, time-seeded parameters and must not be treated as a source of secure randomness
Architecture
Dependencies
gno.land/p/nt/grc721/v0: GRC721 token and ledger implementationgno.land/p/nt/grc721/metadata/v0: Metadata storagegno.land/r/gnoswap/rbac/v1: Access controlgno.land/r/gnoswap/access/v1: Position-role authorization and role mirror
State Variables
token: GRC721 token metadata and supply stateledger: Ownership, transfer, and approval ledgermeta: Token URI metadatametaLedger: Metadata update ledger
Generated image tokens store compact parameters in metadata; the full SVG data
URI is generated when TokenURI is called.