1// Package seafish is the tradable person-versus-person sea.2// CommitMint pays 150 GNOT and the whole fee goes to the wallet that called Init.3// RevealMint, once the chain is at least two blocks later, rolls rarity and trait4// from sha256 of the caller, the commit height, that fixed height plus two, and the id.5// Waiting longer does not change the roll. The player does not pass trait, size, or rarity.6// The revealed fish is a GRC721 owned by that player. TokenURI is the https portrait.7// Swim stays off chain. Register locks at least 10 GNOT. Leave returns it after 5 seconds.8// Settle pays one covered stake: 80% winner, 10% liquidity, 10% team. Dust stays with the team.9// There is no machine fish and no FISH draw. A seated, staked, or healing fish cannot be10// listed or transferred. List, UpdatePrice, Cancel, and Buy are the Nomaq trade.11// Buy pays the ask, in full, to the seller. RegisterCollection publishes the slug on bazaarv5.12// fishsea, fishnft, gnofish, and fishlive stay as deployed. This package does not move them.13// seafish-1. The mint cap is 10000. One wallet still seats only one fish.14package seafish1516import (17 "chain"18 "chain/banker"19 "chain/runtime"20 "chain/runtime/unsafe"21 "crypto/sha256"22 "errors"23 "strconv"24 "time"2526 "gno.land/p/nt/grc721/enumerable/v0"27 "gno.land/p/nt/grc721/v0"28 "gno.land/p/nt/seqid/v0"29 factory "gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/bazaarv5"30)3132const (33 denom = "ugnot"34 mintFee int64 = 150_000_00035 stakeMin int64 = 10_000_00036 quietMs int64 = 5_00037 maxMint = 10_00038 maxAsk int64 = 100_000_000_000_00039 listCap = 5040 slug = "seafish"41 imageIPFS = "ipfs://bafybeifdmgbtq3nf7xuepvygotk6ulk4wo7xshsi2yr4xukglsdpzz7p2i/"42 imageHTTPS = "https://gateway.pinata.cloud/ipfs/bafybeifdmgbtq3nf7xuepvygotk6ulk4wo7xshsi2yr4xukglsdpzz7p2i/"43 cover = imageHTTPS + "common-fish.jpg"44)4546var (47 hpBase = [6]int{100, 122, 148, 178, 214, 256}48 biteBase = [6]int{24, 30, 37, 45, 54, 66}49 spdBase = [6]int{108, 104, 100, 96, 92, 88}50 species = [6]string{"Bubble", "Tideblade", "Abysswing", "Embermaw", "Aurelion", "Astravex"}51 rarities = [6]string{"common", "uncommon", "rare", "epic", "legendary", "mythic"}52 portrait = [6]string{"common-fish.jpg", "uncommon-fish.jpg", "race-fish.jpg", "epic-fish.jpg", "legendary-fish.jpg", "mythic-fish.jpg"}53 traits = [3]string{"swift", "fang", "hide"}54)5556type fish struct {57 owner address58 name string59 rarity string60 trait string61 file string62 bite int63 hpMax int64 hp int65 speed int66 pool int6467 bouts int68 commitH int6469 touched int6470 inSea bool71 revealed bool72 mustHeal bool73 seller address74 ask int6475 onSale bool76}7778var (79 inited bool80 market bool81 self address82 mintTo address83 lpSink address84 team address85 minted int86 shown int87 roster []fish88 token *grc721.Token89 ledger *grc721.PrivateLedger90 teller grc721.Teller91 indexed *enumerable.Enumerable92 seq seqid.ID93)9495// Init records the caller as the mint wallet, plus liquidity and team.96// Those three must be distinct. Call once, from an EOA, with no coins.97func Init(cur realm, lp, crew address) {98 if !cur.Previous().IsUserCall() {99 panic("seafish: eoa")100 }101 takeExact(0)102 caller := cur.Previous().Address()103 if inited || !caller.IsValid() || !lp.IsValid() || !crew.IsValid() || caller == lp || caller == crew || lp == crew {104 panic("seafish: init")105 }106 inited = true107 self = cur.Address()108 mintTo = caller109 lpSink = lp110 team = crew111 roster = []fish{{}}112 tok, led := grc721.NewToken("GnoFish Sea", "GSEA", seq.Next(), cur)113 token = tok114 ledger = led115 teller = led.CallerTeller()116 indexed, _ = enumerable.NewEnumerable(led)117 chain.Emit("Init", "mint", caller.String(), "lp", lp.String(), "team", crew.String())118}119120// CommitMint sells one unrevealed fish for 150 GNOT. The fee leaves this realm in the same call.121// The player owns the fish. The GRC721 is minted at RevealMint, when the portrait exists.122func CommitMint(cur realm) int {123 caller := gate(cur, mintFee)124 if minted >= maxMint || pending(caller) != 0 {125 panic("seafish: mint")126 }127 height := runtime.ChainHeight()128 if height < 1 {129 panic("seafish: mint")130 }131 id := grow()132 roster[id].owner = caller133 roster[id].commitH = height134 payMint(mintFee, cur)135 chain.Emit("Commit", "id", strconv.Itoa(id), "owner", caller.String())136 return id137}138139// RevealMint assigns rarity, trait, the species name, and the portrait.140// Entropy is the commit height plus two. The NFT is minted to the caller.141func RevealMint(cur realm, id int) {142 caller := gate(cur, 0)143 row := mustFish(id)144 entropyH := row.commitH + 2145 if row.owner != caller || row.revealed || runtime.ChainHeight() < entropyH {146 panic("seafish: reveal")147 }148 rarity, trait, bite, hp, speed := Roll(caller, row.commitH, entropyH, id)149 row.rarity = rarity150 row.trait = trait151 row.bite = bite152 row.hpMax = hp153 row.hp = hp154 row.speed = speed155 row.name = pickName(tierOf(rarity))156 row.file = portrait[tierOf(rarity)]157 row.revealed = true158 if err := ledger.Mint(caller, tidOf(id)); err != nil {159 panic("seafish: mint")160 }161 shown++162 chain.Emit("Reveal", "id", strconv.Itoa(id), "rarity", rarity, "trait", trait, "name", row.name, "file", row.file)163 noteSupply(cur)164}165166// Register seats one revealed fish the caller still owns. The attached coins are the stake.167// A listed fish, or a second fish from a wallet that is already seated, is refused.168func Register(cur realm, id int, stake int64) {169 caller := gate(cur, stake)170 row := mustFish(id)171 if stake < stakeMin || row.owner != caller || !row.revealed || row.inSea || row.mustHeal || row.onSale || row.pool != 0 || seated(caller) {172 panic("seafish: register")173 }174 row.pool = stake175 row.inSea = true176 row.touched = time.Now().UnixMilli()177 chain.Emit("Register", "id", strconv.Itoa(id), "stake", strconv.FormatInt(stake, 10))178}179180// Leave returns the seated stake once 5 seconds have passed since Register.181func Leave(cur realm, id int) {182 caller := gate(cur, 0)183 row := mustFish(id)184 if row.owner != caller || !row.inSea || time.Now().UnixMilli() < row.touched+quietMs {185 panic("seafish: leave")186 }187 stake := row.pool188 row.pool = 0189 row.inSea = false190 send(caller, stake, cur)191 chain.Emit("Leave", "id", strconv.Itoa(id), "stake", strconv.FormatInt(stake, 10))192}193194// Settle pays the smaller stake. The NFT stays. HP falls to 30% and must heal.195// The caller has to own the killer. This realm does not check who bit whom.196func Settle(cur realm, id int, target int) {197 caller := gate(cur, 0)198 if id == target {199 panic("seafish: settle")200 }201 atk := mustFish(id)202 vic := mustFish(target)203 if atk.owner != caller || !atk.inSea || !vic.inSea || atk.owner == vic.owner || atk.pool < stakeMin || vic.pool < stakeMin {204 panic("seafish: settle")205 }206 covered := atk.pool207 if vic.pool < covered {208 covered = vic.pool209 }210 excess := vic.pool - covered211 owner := vic.owner212 vic.pool = 0213 vic.inSea = false214 vic.mustHeal = true215 vic.hp = vic.hpMax * 30 / 100216 if vic.hp < 1 {217 vic.hp = 1218 }219 atk.bouts++220 vic.bouts++221 killer, lp, crew := splitKill(covered)222 send(atk.owner, killer, cur)223 send(lpSink, lp, cur)224 send(team, crew, cur)225 send(owner, excess, cur)226 chain.Emit("Kill", "id", strconv.Itoa(id), "target", strconv.Itoa(target), "covered", strconv.FormatInt(covered, 10))227}228229// Heal clears mustHeal outside the sea so Register, List, and Transfer can run again.230func Heal(cur realm, id int) {231 caller := gate(cur, 0)232 row := mustFish(id)233 if row.owner != caller || row.inSea || row.onSale || !row.mustHeal || !row.revealed {234 panic("seafish: heal")235 }236 row.mustHeal = false237 row.hp = row.hpMax238 chain.Emit("Heal", "id", strconv.Itoa(id))239}240241// Transfer moves a fish the caller owns. A seated, staked, healing, or listed fish stays put.242func Transfer(cur realm, to address, id int) {243 from := gate(cur, 0)244 move(cur, from, to, id)245}246247// TransferFrom moves a fish. The caller must own it or be approved for it.248func TransferFrom(cur realm, from, to address, id int) {249 gate(cur, 0)250 move(cur, from, to, id)251}252253// Approve lets to move this fish once. The caller must own it. The call sends no coins.254func Approve(cur realm, to address, id int) {255 gate(cur, 0)256 if err := teller.Approve(0, cur, to, tidOf(id)); err != nil {257 panic("seafish: approve")258 }259}260261// SetApprovalForAll lets operator move every fish of the caller, or revokes it.262func SetApprovalForAll(cur realm, operator address, approved bool) {263 gate(cur, 0)264 if err := teller.SetApprovalForAll(0, cur, operator, approved); err != nil {265 panic("seafish: approve")266 }267}268269// List escrows the fish to this realm and puts it on sale. The caller sends no coins.270// Refused while the fish is seated, still holds a stake, or must heal.271func List(cur realm, id int, priceUgnot int64) {272 caller := gate(cur, 0)273 row := mustFish(id)274 if priceUgnot <= 0 || priceUgnot > maxAsk || !row.revealed || row.onSale || row.owner != caller || busy(row) {275 panic("seafish: list")276 }277 ledgerMove(caller, caller, self, id)278 row.onSale = true279 row.seller = caller280 row.ask = priceUgnot281 row.owner = self282 chain.Emit("List", "id", strconv.Itoa(id), "seller", caller.String(), "price", strconv.FormatInt(priceUgnot, 10))283}284285// UpdatePrice changes the ask of a fish the caller is selling.286func UpdatePrice(cur realm, id int, priceUgnot int64) {287 caller := gate(cur, 0)288 row := mustFish(id)289 if priceUgnot <= 0 || priceUgnot > maxAsk || !row.onSale || row.seller != caller {290 panic("seafish: list")291 }292 row.ask = priceUgnot293 chain.Emit("List", "id", strconv.Itoa(id), "seller", caller.String(), "price", strconv.FormatInt(priceUgnot, 10))294}295296// Cancel returns a listed fish to its seller. The call sends no coins.297func Cancel(cur realm, id int) {298 caller := gate(cur, 0)299 row := mustFish(id)300 if !row.onSale || row.seller != caller {301 panic("seafish: list")302 }303 ledgerMove(self, self, caller, id)304 row.onSale = false305 row.owner = caller306 row.seller = address("")307 row.ask = 0308 chain.Emit("Cancel", "id", strconv.Itoa(id))309}310311// Buy pays the ask, in full, to the seller and gives the fish to the buyer.312func Buy(cur realm, id int) {313 if !cur.Previous().IsUserCall() {314 panic("seafish: eoa")315 }316 if !inited {317 panic("seafish: init")318 }319 row := mustFish(id)320 buyer := cur.Previous().Address()321 if !row.onSale || buyer == row.seller {322 panic("seafish: list")323 }324 price := row.ask325 seller := row.seller326 takeExact(price)327 ledgerMove(self, self, buyer, id)328 row.onSale = false329 row.owner = buyer330 row.seller = address("")331 row.ask = 0332 send(seller, price, cur)333 chain.Emit("Buy", "id", strconv.Itoa(id), "buyer", buyer.String(), "price", strconv.FormatInt(price, 10))334}335336// RegisterCollection publishes this realm on bazaarv5. The caller must be the Init wallet,337// the same wallet that reserved slug seafish, and must send no coins. Call it once, after Init.338func RegisterCollection(cur realm) {339 caller := gate(cur, 0)340 if caller != mintTo || market {341 panic("seafish: admin")342 }343 factory.Register(cross(cur), "GnoFish Sea", "GSEA", cover, maxMint, mintFee, 0)344 market = true345 factory.NoteMinted(cross(cur), shown)346}347348// Roll is the reveal hash. entropyH must be commitH+2. Trait adds 12%, half up.349func Roll(caller address, commitH int64, entropyH int64, id int) (rarity string, trait string, bite int, hp int, speed int) {350 if id < 1 || commitH < 1 || entropyH != commitH+2 {351 panic("seafish: roll")352 }353 raw := caller.String() + "|" + strconv.FormatInt(commitH, 10) + "|" + strconv.FormatInt(entropyH, 10) + "|" + strconv.Itoa(id)354 sum := sha256.Sum256([]byte(raw))355 n := (int(sum[0])<<8 | int(sum[1])) % 10000356 tier := 0357 if n == 0 {358 tier = 5359 } else if n < 4 {360 tier = 4361 } else if n < 14 {362 tier = 3363 } else if n < 54 {364 tier = 2365 } else if n < 254 {366 tier = 1367 }368 kind := int(sum[2]) % 3369 bite = biteBase[tier]370 hp = hpBase[tier]371 speed = spdBase[tier]372 if kind == 0 {373 speed = (speed*112 + 50) / 100374 } else if kind == 1 {375 bite = (bite*112 + 50) / 100376 } else {377 hp = (hp*112 + 50) / 100378 }379 return rarities[tier], traits[kind], bite, hp, speed380}381382func Realm() address { return self }383func MintTo() address { return mintTo }384func Liquidity() address { return lpSink }385func Team() address { return team }386func Version() string { return "seafish-1" }387func Name() string { return "GnoFish Sea" }388func GrcName() string { return Name() }389func Symbol() string { return "GSEA" }390func GrcSymbol() string { return Symbol() }391func MintPrice() int64 { return mintFee }392func StakeMin() int64 { return stakeMin }393func MaxMint() int { return maxMint }394func Minted() int { return minted }395func Shown() int { return shown }396func MarketOpen() bool { return market }397func Height() int64 { return runtime.ChainHeight() }398399func TraitOf(id int) string { return mustFish(id).trait }400func RarityOf(id int) string { return mustFish(id).rarity }401func SizeOf(id int) string {402 mustFish(id)403 return "medium"404}405func BoutsOf(id int) int { return mustFish(id).bouts }406func InMatch(id int) bool { return mustFish(id).inSea }407func PoolOf(id int) int64 { return mustFish(id).pool }408func Revealed(id int) bool { return mustFish(id).revealed }409func MustHeal(id int) bool { return mustFish(id).mustHeal }410func CommitOf(id int) int64 { return mustFish(id).commitH }411func HpOf(id int) int { return mustFish(id).hp }412func BiteOf(id int) int { return mustFish(id).bite }413func SpeedOf(id int) int { return mustFish(id).speed }414func NameOf(id int) string { return mustFish(id).name }415func Listed(id int) bool { return revealedFish(id).onSale }416func PriceOf(id int) int64 { return revealedFish(id).ask }417func ImageOf(id int) string { return imageHTTPS + revealedFish(id).file }418419func SellerOf(id int) string {420 row := revealedFish(id)421 if !row.seller.IsValid() {422 return ""423 }424 return row.seller.String()425}426427func ItemLine(id int) string {428 row := revealedFish(id)429 line := "Species:" + speciesOf(row.rarity) + ";Rarity:" + row.rarity + ";Trait:" + row.trait + ";Bite:" + strconv.Itoa(row.bite) + ";HP:" + strconv.Itoa(row.hp) + ";Speed:" + strconv.Itoa(row.speed)430 return strconv.Itoa(id) + "|" + row.name + "|" + row.owner.String() + "|" + SellerOf(id) + "|" + strconv.FormatInt(row.ask, 10) + "|" + strconv.FormatBool(row.onSale) + "|" + imageHTTPS + row.file + "|" + slug + "|" + row.rarity + "|" + line + "|true|-1"431}432433func ListOpen() string {434 if !inited {435 return ""436 }437 out := ""438 n := 0439 for id := 1; id <= minted && n < listCap; id++ {440 if !roster[id].onSale {441 continue442 }443 if out != "" {444 out += "\n"445 }446 out += ItemLine(id)447 n++448 }449 return out450}451452func TokensOf(owner address) string {453 if !inited || !owner.IsValid() {454 return ""455 }456 out := ""457 for id := 1; id <= minted; id++ {458 if roster[id].owner != owner {459 continue460 }461 if out != "" {462 out += ","463 }464 out += strconv.Itoa(id)465 }466 return out467}468469func Pending(owner string) int {470 who := address(owner)471 if !who.IsValid() {472 return 0473 }474 return pending(who)475}476477func OwnerOf(tid grc721.TokenID) (address, error) {478 if token == nil {479 return "", errors.New("seafish: init")480 }481 return token.OwnerOf(tid)482}483484func BalanceOf(addr address) (int64, error) {485 if token == nil {486 return 0, errors.New("seafish: init")487 }488 return token.BalanceOf(addr)489}490491func TotalSupply() int64 {492 if token == nil {493 return 0494 }495 return token.TotalSupply()496}497498func GetApproved(tid grc721.TokenID) (address, error) {499 if token == nil {500 return "", errors.New("seafish: init")501 }502 addr, err := token.GetApproved(tid)503 if err == grc721.ErrTokenIdNotApproved {504 return "", nil505 }506 return addr, err507}508509func IsApprovedForAll(owner, operator address) bool {510 if token == nil {511 return false512 }513 return token.IsApprovedForAll(owner, operator)514}515516func TokenByIndex(index int64) (grc721.TokenID, error) {517 if indexed == nil {518 return "", errors.New("seafish: init")519 }520 return indexed.TokenByIndex(index)521}522523func TokenOfOwnerByIndex(owner address, index int64) (grc721.TokenID, error) {524 if indexed == nil {525 return "", errors.New("seafish: init")526 }527 return indexed.TokenOfOwnerByIndex(owner, index)528}529530// TokenURI is the https image Adena puts in an img tag.531func TokenURI(tid grc721.TokenID) (string, error) {532 row, err := byToken(tid)533 if err != nil {534 return "", err535 }536 return imageHTTPS + row.file, nil537}538539// TokenMetadata is the JSON Adena reads. Attribute keys are traitType.540func TokenMetadata(tid grc721.TokenID) (string, error) {541 row, err := byToken(tid)542 if err != nil {543 return "", err544 }545 return `{"name":"` + row.name + `","description":"` + row.name + `, a ` + row.rarity + ` GnoFish.","image":"` + imageHTTPS + row.file + `","attributes":[` +546 attr("species", speciesOf(row.rarity)) + `,` +547 attr("rarity", row.rarity) + `,` +548 attr("trait", row.trait) + `,` +549 attr("bite", strconv.Itoa(row.bite)) + `,` +550 attr("hp", strconv.Itoa(row.hp)) + `,` +551 attr("speed", strconv.Itoa(row.speed)) + `,` +552 attr("ipfs", imageIPFS+row.file) + `]}`, nil553}554555func Render(path string) string {556 if path != "" {557 return "# GnoFish Sea\n\nUnknown path.\n"558 }559 return "# GnoFish Sea\n\nPerson versus person. The mint fee goes to the deploy wallet. A win pays 80% to the winner, 10% to liquidity, and 10% to the team. Portraits are https images. A seated fish cannot be listed.\n"560}561562func gate(cur realm, pay int64) address {563 if !cur.Previous().IsUserCall() {564 panic("seafish: eoa")565 }566 if !inited || self == address("") {567 panic("seafish: init")568 }569 takeExact(pay)570 return cur.Previous().Address()571}572573func payMint(fee int64, rlm realm) {574 send(mintTo, fee, rlm)575}576577func splitKill(covered int64) (killer int64, lp int64, crew int64) {578 killer = covered * 80 / 100579 lp = covered * 10 / 100580 crew = covered - killer - lp581 return582}583584func send(to address, amt int64, rlm realm) {585 if !rlm.IsCurrent() {586 panic("seafish: realm")587 }588 if amt == 0 {589 return590 }591 bk := banker.NewBanker(banker.BankerTypeRealmSend, rlm)592 bk.SendCoins(rlm.Address(), to, chain.Coins{{Denom: denom, Amount: amt}})593}594595func noteSupply(cur realm) {596 if !market {597 return598 }599 factory.NoteMinted(cross(cur), shown)600}601602func grow() int {603 if minted >= maxMint || len(roster) != minted+1 {604 panic("seafish: mint")605 }606 roster = append(roster, fish{})607 minted++608 return minted609}610611func mustFish(id int) *fish {612 if !inited || id < 1 || id > minted || id >= len(roster) {613 panic("seafish: fish")614 }615 return &roster[id]616}617618func revealedFish(id int) *fish {619 row := mustFish(id)620 if !row.revealed {621 panic("seafish: uri")622 }623 return row624}625626func pending(who address) int {627 for i := 1; i <= minted; i++ {628 if roster[i].owner == who && !roster[i].revealed {629 return i630 }631 }632 return 0633}634635func seated(who address) bool {636 for i := 1; i <= minted; i++ {637 if roster[i].owner == who && roster[i].inSea {638 return true639 }640 }641 return false642}643644func busy(row *fish) bool {645 return row.inSea || row.pool != 0 || row.mustHeal646}647648func pickName(tier int) string {649 base := species[tier]650 if !nameTaken(base) {651 return base652 }653 for n := 2; n <= maxMint; n++ {654 candidate := base + strconv.Itoa(n)655 if !nameTaken(candidate) {656 return candidate657 }658 }659 panic("seafish: name")660}661662func nameTaken(name string) bool {663 for i := 1; i <= minted; i++ {664 if roster[i].revealed && roster[i].name == name {665 return true666 }667 }668 return false669}670671func tierOf(rarity string) int {672 for i := 0; i < len(rarities); i++ {673 if rarities[i] == rarity {674 return i675 }676 }677 panic("seafish: roll")678}679680func move(cur realm, from, to address, id int) {681 row := mustFish(id)682 if row.onSale || !row.revealed || busy(row) || !to.IsValid() || to == from {683 panic("seafish: transfer")684 }685 if err := teller.TransferFrom(0, cur, from, to, tidOf(id)); err != nil {686 panic("seafish: transfer")687 }688 row.owner = to689}690691func ledgerMove(spender, from, to address, id int) {692 if err := ledger.TransferFrom(spender, from, to, tidOf(id)); err != nil {693 panic("seafish: transfer")694 }695}696697func tidOf(id int) grc721.TokenID {698 return grc721.TokenID(strconv.Itoa(id))699}700701func byToken(tid grc721.TokenID) (*fish, error) {702 if token == nil {703 return nil, errors.New("seafish: init")704 }705 if _, err := token.OwnerOf(tid); err != nil {706 return nil, err707 }708 id, err := strconv.Atoi(string(tid))709 if err != nil || id < 1 || id > minted || id >= len(roster) || !roster[id].revealed {710 return nil, errors.New("seafish: fish")711 }712 return &roster[id], nil713}714715func speciesOf(rarity string) string {716 for i := 0; i < len(rarities); i++ {717 if rarities[i] == rarity {718 return species[i]719 }720 }721 return ""722}723724func attr(key, value string) string {725 return `{"traitType":"` + key + `","value":"` + value + `"}`726}727728func takeExact(n int64) {729 sent := unsafe.OriginSend()730 if n == 0 {731 if len(sent) != 0 {732 panic("seafish: payment")733 }734 return735 }736 if len(sent) != 1 || sent[0].Denom != denom || sent[0].Amount != n {737 panic("seafish: payment")738 }739}740Approve(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, id int)
BalanceOf(addr string) (int64, interface {Error func() string})
BiteOf(id int) int
BoutsOf(id int) int
Buy(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}, id int)
Cancel(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}, id int)
CommitMint(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}) int
CommitOf(id int) int64
GetApproved(tid string) (string, interface {Error func() string})
GrcName() string
GrcSymbol() string
Heal(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}, id int)
Height() int64
HpOf(id int) int
ImageOf(id int) string
Init(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}, lp string, crew string)
InMatch(id int) bool
IsApprovedForAll(owner string, operator string) bool
ItemLine(id int) string
Leave(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}, id int)
Liquidity() string
List(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}, id int, priceUgnot int64)
Listed(id int) bool
ListOpen() string
MarketOpen() bool
MaxMint() int
Minted() int
MintPrice() int64
MintTo() string
MustHeal(id int) bool
Name() string
NameOf(id int) string
OwnerOf(tid string) (string, interface {Error func() string})
Pending(owner string) int
PoolOf(id int) int64
PriceOf(id int) int64
RarityOf(id int) string
Realm() string
Register(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}, id int, stake int64)
RegisterCollection(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})
Render(path string) string
Revealed(id int) bool
RevealMint(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}, id int)
Roll(caller string, commitH int64, entropyH int64, id int) (rarity string, trait string, bite int, hp int, speed int)
SellerOf(id int) 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)
Settle(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}, id int, target int)
Shown() int
SizeOf(id int) string
SpeedOf(id int) int
StakeMin() int64
Symbol() string
Team() string
TokenByIndex(index int64) (string, interface {Error func() string})
TokenMetadata(tid string) (string, interface {Error func() string})
TokenOfOwnerByIndex(owner string, index int64) (string, interface {Error func() string})
TokensOf(owner string) string
TokenURI(tid string) (string, interface {Error func() string})
TotalSupply() int64
TraitOf(id int) string
Transfer(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, id int)
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, id int)
UpdatePrice(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}, id int, priceUgnot int64)
Version() string
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
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.