PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/gnoswap/gnft

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
gnft
Namespace
gnoswap
Files
8 (README)(gnomod.toml)
Exported functions
17
Module
gno.land/r/gnoswap/gnft
gno
0.9

Files (8)

  • README.mdmarkdown
  • gnomod.tomltoml
  • assert.gnogno
  • doc.gnogno
  • errors.gnogno
  • gnft.gnogno
  • svg_generator.gnogno
  • utils.gnogno
  • svg_generator.gnogno
    1package gnft23import (4	b64 "encoding/base64"5	"errors"6	"math/rand"7	"strconv"8

    Functions

    • Approve(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}, approved string, tid string) interface {Error func() string}

    • BalanceOf(owner string) (int64, interface {Error func() string})

    • Burn(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}, tid string)

    • Exists(tid string) bool

    • GetApproved(tid string) (string, interface {Error func() string})

    • IsApprovedForAll(owner string, operator string) bool

    • Mint(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}, to string, tid string) string

    • MustOwnerOf(tid string) string

    • Name() string

    • OwnerOf(tid string) (string, interface {Error func() string})

    • Render(path string) string

    • SetApprovalForAll(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}, operator string, approved bool) interface {Error func() string}

    • SetTokenURI(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}, tid string, tURI string) (bool, interface {Error func() string})

    • Symbol() string

    • TokenURI(tid string) (string, interface {Error func() string})

    • TotalSupply() int64

    • TransferFrom(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}, from string, to string, tid string) interface {Error func() string}

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗

    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.

    "strings"
    9
    10 "gno.land/p/nt/grc721/v0"
    11 ufmt "gno.land/p/nt/ufmt/v0"
    12)
    13
    14// MUST BE IMMUTABLE, DO NOT MODIFY.
    15// SVG template structure:
    16// The template is split at variable insertion points for efficient string concatenation.
    17// Full template with placeholders (for reference):
    18//
    19// <svg width="135" height="135" viewBox="0 0 135 135" fill="none" xmlns="...">
    20// <g clip-path="url(#clip0_7698_56846)">
    21// <circle cx="67.5" cy="67.5" r="67.5" fill="url(#paint0_linear_7698_56846)"/>
    22// ... (path elements) ...
    23// </g>
    24// <defs>
    25// <linearGradient id="paint0_linear_7698_56846"
    26// x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" <-- variables
    27// gradientUnits="userSpaceOnUse">
    28// <stop stop-color="{color1}"/> <-- variable
    29// <stop offset="1" stop-color="{color2}"/> <-- variable
    30// </linearGradient>
    31// ...
    32// </defs>
    33// </svg>
    34
    35// svgTemplate holds pre-split template parts for efficient concatenation.
    36// Usage: svgTemplate[0] + clipID + svgTemplate[1] + paintID + ... + color2 + svgTemplate[10]
    37var svgTemplate = [11]string{
    38 // [0] SVG header and body (before clip-path id)
    39 `<svg width="135" height="135" viewBox="0 0 135 135" fill="none" xmlns="http://www.w3.org/2000/svg">
    40<g clip-path="url(#`,
    41 // [1] between clip-path id and fill id
    42 `)">
    43<circle cx="67.5" cy="67.5" r="67.5" fill="url(#`,
    44 // [2] between fill id and gradient id
    45 `)"/>
    46<path d="M51.2905 42.9449L66.4895 33L97 52.8061L81.8241 62.7425L51.2905 42.9449Z" fill="white"/>
    47<path d="M51.6055 67.5059L66.8044 57.561L97 77.0657L82.1046 87.1793L51.6055 67.5059Z" fill="white" fill-opacity="0.4"/>
    48<path d="M36.0464 81.7559L51.2905 71.811L81.7336 91.6547L66.4895 101.508L36.0464 81.7559Z" fill="white" fill-opacity="0.6"/>
    49<path d="M36.001 52.8055L51.2884 42.9177L51.2884 71.8145L36.001 81.779L36.001 52.8055Z" fill="white"/>
    50<path d="M82.1051 87.1797L97.0016 77.0662L97.0016 81.7029L81.7896 91.629L82.1051 87.1797Z" fill="white" fill-opacity="0.5"/>
    51</g>
    52<defs>
    53<linearGradient id="`,
    54 // [3] between gradient id and x1
    55 `" x1="`,
    56 // [4] between x1 and y1
    57 `" y1="`,
    58 // [5] between y1 and x2
    59 `" x2="`,
    60 // [6] between x2 and y2
    61 `" y2="`,
    62 // [7] between y2 and color1
    63 `" gradientUnits="userSpaceOnUse">
    64<stop stop-color="`,
    65 // [8] between color1 and color2
    66 `"/>
    67<stop offset="1" stop-color="`,
    68 // [9] between color2 and clipPath id
    69 `"/>
    70</linearGradient>
    71<clipPath id="`,
    72 // [10] SVG footer (after clipPath id)
    73 `">
    74<rect width="135" height="135" fill="white"/>
    75</clipPath>
    76</defs>
    77</svg>
    78`,
    79}
    80
    81// charset contains valid hex digits for color generation.
    82const charset = "0123456789ABCDEF"
    83
    84// Parameter range constants for gradient coordinates.
    85const (
    86 x1Min = 7
    87 x1Max = 13
    88 y1Min = 7
    89 y1Max = 13
    90 x2Min = 121
    91 x2Max = 126
    92 y2Min = 121
    93 y2Max = 126
    94
    95 x1Range = x1Max - x1Min + 1
    96 y1Range = y1Max - y1Min + 1
    97 x2Range = x2Max - x2Min + 1
    98 y2Range = y2Max - y2Min + 1
    99)
    100
    101// genImageParamsString generates random gradient parameters and returns them as a compact string.
    102// Format: "x1,y1,x2,y2,color1,color2" (e.g., "10,12,125,123,#AABBCC,#DDEEFF")
    103func genImageParamsString(r *rand.Rand) string {
    104 x1 := x1Min + r.Uint64N(x1Range)
    105 y1 := y1Min + r.Uint64N(y1Range)
    106 x2 := x2Min + r.Uint64N(x2Range)
    107 y2 := y2Min + r.Uint64N(y2Range)
    108
    109 var buf1 [7]byte
    110 var buf2 [7]byte
    111 buf1[0] = '#'
    112 buf2[0] = '#'
    113 for i := 1; i < 7; i++ {
    114 buf1[i] = charset[r.IntN(16)]
    115 buf2[i] = charset[r.IntN(16)]
    116 }
    117 color1 := string(buf1[:])
    118 color2 := string(buf2[:])
    119
    120 return strconv.Itoa(int(x1)) + "," + strconv.Itoa(int(y1)) + "," +
    121 strconv.Itoa(int(x2)) + "," + strconv.Itoa(int(y2)) + "," +
    122 color1 + "," + color2
    123}
    124
    125// ImageParams holds parsed and validated image parameters.
    126type ImageParams struct {
    127 x1, y1, x2, y2 int
    128 color1, color2 string
    129}
    130
    131// validateCoordinate checks if a coordinate value is within valid range.
    132// Returns error with details about which coordinate failed if out of range.
    133func validateCoordinate(value int, min int, max int, name string) error {
    134 if value < min || value > max {
    135 details := ufmt.Sprintf("%s=%d (expected range: [%d, %d])", name, value, min, max)
    136 return makeErrorWithDetails(errInvalidTokenParamsRange, details)
    137 }
    138 return nil
    139}
    140
    141// parseImageParams parses and validates parameters in one step.
    142// Returns parsed ImageParams pointer or error.
    143// Returns nil on error to avoid allocating zero-value struct.
    144// Expected format: "x1,y1,x2,y2,color1,color2"
    145func parseImageParams(s string) (*ImageParams, error) {
    146 parts := strings.Split(s, ",")
    147 if len(parts) != 6 {
    148 return nil, errors.New(errInvalidTokenParams)
    149 }
    150
    151 x1, err := strconv.Atoi(parts[0])
    152 if err != nil {
    153 return nil, errors.New(errInvalidTokenParams)
    154 }
    155
    156 y1, err := strconv.Atoi(parts[1])
    157 if err != nil {
    158 return nil, errors.New(errInvalidTokenParams)
    159 }
    160
    161 x2, err := strconv.Atoi(parts[2])
    162 if err != nil {
    163 return nil, errors.New(errInvalidTokenParams)
    164 }
    165
    166 y2, err := strconv.Atoi(parts[3])
    167 if err != nil {
    168 return nil, errors.New(errInvalidTokenParams)
    169 }
    170
    171 // Validate coordinate ranges with detailed error messages
    172 if err := validateCoordinate(x1, x1Min, x1Max, "x1"); err != nil {
    173 return nil, err
    174 }
    175 if err := validateCoordinate(y1, y1Min, y1Max, "y1"); err != nil {
    176 return nil, err
    177 }
    178 if err := validateCoordinate(x2, x2Min, x2Max, "x2"); err != nil {
    179 return nil, err
    180 }
    181 if err := validateCoordinate(y2, y2Min, y2Max, "y2"); err != nil {
    182 return nil, err
    183 }
    184
    185 color1 := parts[4]
    186 color2 := parts[5]
    187
    188 // Validate color format (#XXXXXX)
    189 if !isValidHexColor(color1) || !isValidHexColor(color2) {
    190 return nil, errors.New(errInvalidColorFormat)
    191 }
    192
    193 return &ImageParams{
    194 x1: x1,
    195 y1: y1,
    196 x2: x2,
    197 y2: y2,
    198 color1: color1,
    199 color2: color2,
    200 }, nil
    201}
    202
    203// generateImageURI converts parsed image parameters to a base64-encoded SVG image URI.
    204func (params ImageParams) generateImageURI(tid grc721.TokenID) string {
    205 svg := params.generateSVG(tid)
    206 sEnc := b64.StdEncoding.EncodeToString([]byte(svg))
    207
    208 return "data:image/svg+xml;base64," + sEnc
    209}
    210
    211// generateSVG generates SVG image from parsed and validated parameters.
    212func (params ImageParams) generateSVG(tid grc721.TokenID) string {
    213 suffix := svgIDSuffix(tid)
    214 paintID := "paint0_linear_" + suffix
    215 clipID := "clip0_" + suffix
    216 return svgTemplate[0] + clipID + svgTemplate[1] + paintID + svgTemplate[2] + paintID +
    217 svgTemplate[3] + strconv.Itoa(params.x1) + svgTemplate[4] + strconv.Itoa(params.y1) +
    218 svgTemplate[5] + strconv.Itoa(params.x2) + svgTemplate[6] + strconv.Itoa(params.y2) +
    219 svgTemplate[7] + params.color1 + svgTemplate[8] + params.color2 + svgTemplate[9] +
    220 clipID + svgTemplate[10]
    221}
    222
    223func svgIDSuffix(tid grc721.TokenID) string {
    224 return "gnft_" + string(tid)
    225}
    226
    227// isValidHexColor checks if a string is a valid hex color in #XXXXXX format.
    228func isValidHexColor(color string) bool {
    229 if len(color) != 7 || color[0] != '#' {
    230 return false
    231 }
    232
    233 for i := 1; i < 7; i++ {
    234 c := color[i]
    235
    236 isHex := (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')
    237 if !isHex {
    238 return false
    239 }
    240 }
    241
    242 return true
    243}
    244