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/g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4/trialmint/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4 / trialmint
Files
2 (gnomod.toml)
Exported functions
12
Module
gno.land/r/g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4/trialmint/v1
gno
0.9

Files (2)

  • gnomod.tomltoml
  • v1.gnogno
v1.gnogno
1package trialmint23import (4	"chain"5	"chain/banker"6	"chain/runtime"7	unsaferealm "chain/runtime/unsafe"8	"crypto/sha256"9	"strings"1011	artpkg "gno.land/p/g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4/art3d"12	grc721 "gno.land/p/g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4/grc721v2"13	stable "gno.land/r/g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4/trialmint/stable"14	"gno.land/p/nt/seqid/v0"15	"gno.land/p/nt/ufmt/v0"16)1718var (19	collectionOwnerHere address = "g1wx60nkcp5lfsxmedeg7sfs47tzxkath05u63t4"2021	mintingOpen = true2223	maxMintsPerWallet int64 = 02425	nextID seqid.ID26)2728func MintAssembled(cur realm, to address) grc721.TokenID {29	if !mintingOpen {30		panic("minting is closed")31	}32	if maxMintsPerWallet > 0 && callerAddress() != collectionOwnerHere && stable.MintsByWallet(to) >= maxMintsPerWallet {33		panic(ufmt.Sprintf("wallet %s has already reached the %d-mint limit for this collection", to.String(), maxMintsPerWallet))34	}3536	caller := callerAddress()37	requiredPrice := stable.EffectivePrice(caller)38	if requiredPrice != 0 {39		runtime.AssertOriginCall()40		if !unsaferealm.PreviousRealm().IsUserCall() {41			panic("payment verification requires a direct user call")42		}43		got := unsaferealm.OriginSend().AmountOf("ugnot")44		if got != requiredPrice {45			panic(ufmt.Sprintf("payment required: exactly %d ugnot, got %d", requiredPrice, got))46		}47		b := banker.NewBanker(banker.BankerTypeRealmSend, cur)48		b.SendCoins(cur.Address(), stable.Owner(), chain.Coins{{Denom: "ugnot", Amount: got}})49	}5051	tp, comboKey := assembleUniqueTraits()5253	tid := grc721.TokenID(ufmt.Sprintf("%d", uint64(nextID)+1))54	stable.RecordMint(cross(cur), to, caller, tid, tp.Chain, tp.ShapeIdx, tp.ColorIdx, tp.Metal, tp.Active, comboKey, rarityTier(tp))5556	nextID.Next()5758	return tid59}6061type traitPreset struct {62	Chain    string63	ShapeIdx int64	ColorIdx int65	Metal    string66	Active   bool67}6869func traitComboKey(chainName string, shapeIdx, colorIdx int, metal string, active bool) string {70	return ufmt.Sprintf("%s|%d|%d|%s|%t", chainName, shapeIdx, colorIdx, metal, active)71}7273const activeProbability = 0.27475type prng struct {76	seed string77	n    int78}7980func newPRNG(seed string) *prng { return &prng{seed: seed} }8182func (p *prng) next() uint64 {83	p.n++84	material := ufmt.Sprintf("%s:%d", p.seed, p.n)85	sum := sha256.Sum256([]byte(material))86	var v uint6487	for i := 0; i < 8; i++ {88		v = v<<8 | uint64(sum[i])89	}90	return v91}9293func (p *prng) floatIn(lo, hi float64) float64 {94	frac := float64(p.next()%1000000) / 1000000.095	return lo + frac*(hi-lo)96}9798func (p *prng) intn(n int) int {99	if n <= 1 {100		return 0101	}102	return int(p.next() % uint64(n))103}104105func randomTraitPreset(attempt int) traitPreset {106	material := ufmt.Sprintf("assemble:%d:%d:%s:%d",107		runtime.ChainHeight(), uint64(nextID), callerAddress().String(), attempt)108	rnd := newPRNG(material)109110	chainName := chainRoster[rnd.intn(len(chainRoster))]111	stone := artpkg.StoneForChain(chainName)112	colorIdx := artpkg.PickColorIndex(stone, rnd.next())113	var shapeIdx int114	if stone == "Pearl" {115		shapeIdx = rnd.intn(len(artpkg.PearlShapeNames))116	} else {117		cuts := artpkg.CutsForStone(stone)118		shapeIdx = cuts[rnd.intn(len(cuts))]119	}120	metal := artpkg.MetalNames[rnd.intn(len(artpkg.MetalNames))]121	active := rnd.floatIn(0, 1) < activeProbability || artpkg.ChainAlwaysActive(chainName)122123	return traitPreset{Chain: chainName, ShapeIdx: shapeIdx, ColorIdx: colorIdx, Metal: metal, Active: active}124}125126const maxAssembleAttempts = 200127128func assembleUniqueTraits() (traitPreset, string) {129	for attempt := 0; attempt < maxAssembleAttempts; attempt++ {130		tp := randomTraitPreset(attempt)131		key := traitComboKey(tp.Chain, tp.ShapeIdx, tp.ColorIdx, tp.Metal, tp.Active)132		if stable.IsTraitComboAvailable(key) {133			return tp, key134		}135	}136	panic("could not find an unused trait combination after many attempts -- the collection may be fully minted")137}138139func IsTraitComboAvailable(chainName string, shapeIdx, colorIdx int, metal string, active bool) bool {140	key := traitComboKey(chainName, shapeIdx, colorIdx, metal, active)141	return stable.IsTraitComboAvailable(key)142}143144func MaxUniqueTraitCombos() int64 {145	var total int64146	for _, chainName := range chainRoster {147		stone := artpkg.StoneForChain(chainName)148		shapeCount := len(artpkg.CutsForStone(stone))149		if stone == "Pearl" {150			shapeCount = len(artpkg.PearlShapeNames)151		}152		states := int64(2) // active or sunset153		if artpkg.ChainAlwaysActive(chainName) {154			states = 1155		}156		total += int64(artpkg.ColorPaletteSize(stone)) * int64(shapeCount) * states157	}158	return total * int64(len(artpkg.MetalNames))159}160161func ComboProbability(chainName string, shapeIdx, colorIdx int, active bool) float64 {162	stone := artpkg.StoneForChain(chainName)163	same := 0164	for _, c := range chainRoster {165		if artpkg.StoneForChain(c) == stone {166			same++167		}168	}169	p := float64(same) / float64(len(chainRoster))170	if stone == "Pearl" {171		p /= float64(len(artpkg.PearlShapeNames))172	} else {173		p /= float64(len(artpkg.CutsForStone(stone)))174	}175	p *= artpkg.ColorProbability(stone, colorIdx)176	if !artpkg.ChainAlwaysActive(chainName) {177		if active {178			p *= activeProbability179		} else {180			p *= 1 - activeProbability181		}182	}183	return p184}185186var rarityTiers = []struct {187	name string188	maxP float64189}{190	{"Legendary", 0.000127233877},191	{"Epic", 0.000423465423},192	{"Rare", 0.000754985755},193	{"Uncommon", 0.00364957265},194}195196func rarityTier(tp traitPreset) string {197	p := ComboProbability(tp.Chain, tp.ShapeIdx, tp.ColorIdx, tp.Active)198	for _, t := range rarityTiers {199		if p <= t.maxP {200			return t.name201		}202	}203	return "Common"204}205206var chainRoster = []string{207	"TEST-1", "TEST-2", "TEST-3", "TEST-4", "TEST-5", "TEST-6", "TEST-7",208	"TEST-8", "TEST-9", "TEST-10", "TEST-11", "TEST-12", "TEST-13",209	"TOPAZ-1", "SAPPHIRE-1", "PEARL-1", "BETANET", "GNOLAND-1",210}211212func AddChain(cur realm, chainName string) {213	assertOwner()214	if chainName == "" {215		panic("chain name must not be empty")216	}217	for _, c := range chainRoster {218		if c == chainName {219			panic("chain already in the roster")220		}221	}222	chainRoster = append(chainRoster, chainName)223}224225func ChainRosterSize() int64 { return int64(len(chainRoster)) }226func ChainRosterCSV() string { return strings.Join(chainRoster, ";") }227228func callerAddress() address {229	return unsaferealm.PreviousRealm().Address()230}231232func assertOwner() {233	if callerAddress() != collectionOwnerHere {234		panic("unauthorized: caller is not the collection owner")235	}236}237238func MintingOpen() bool { return mintingOpen }239240func SetMintingOpen(cur realm, open bool) {241	assertOwner()242	mintingOpen = open243	stable.ReportMintingOpen(cross(cur), open)244}245246func MaxMintsPerWallet() int64 { return maxMintsPerWallet }247248func SetMaxMintsPerWallet(cur realm, max int64) {249	assertOwner()250	if max < 0 {251		panic("max must be non-negative (0 = unlimited)")252	}253	maxMintsPerWallet = max254	stable.ReportMaxMintsPerWallet(cross(cur), max)255}256257func MintsByWallet(owner address) int64 {258	return stable.MintsByWallet(owner)259}260

Functions

  • AddChain(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}, chainName string)

  • ChainRosterCSV() string

  • ChainRosterSize() int64

  • ComboProbability(chainName string, shapeIdx int, colorIdx int, active bool) float64

  • IsTraitComboAvailable(chainName string, shapeIdx int, colorIdx int, metal string, active bool) bool

  • MaxMintsPerWallet() int64

  • MaxUniqueTraitCombos() int64

  • MintAssembled(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) string

  • MintingOpen() bool

  • MintsByWallet(owner string) int64

  • SetMaxMintsPerWallet(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}, max int64)

  • SetMintingOpen(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}, open bool)

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

Rendered

RenderedRawgnoweb ↗

Render unavailable

rate limit exceeded — the render query is served by the Gnoland archive RPC.

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.