Search Apps Documentation Source Content File Folder Download Copy Actions Download

getters.gno

2.97 Kb · 93 lines
 1package memba_nft_market_v3_1
 2
 3// v3.1 — structured read getters.
 4//
 5// These let the frontend read listings and offers STRUCTURALLY (full addresses,
 6// deterministic format) instead of scraping the markdown Render(""), which truncated
 7// addresses and capped at 50 rows. Output is one record per line, pipe-delimited, so
 8// the client parses by split — no markdown regex, no truncation.
 9
10import (
11	"strings"
12
13	"chain/runtime/unsafe"
14)
15
16// MaxPageSize bounds a single page so a getter can never iterate unboundedly (a
17// gas/DoS surface). The frontend pages with offset/limit.
18const MaxPageSize = 100
19
20// MarketAddress returns this engine realm's own address — the operator a seller
21// approves on the collection (SetApprovalForAll) and the address the collection
22// registers via RegisterMarket. Exposed so the frontend and the deploy ceremony can
23// read the deterministic address directly instead of hardcoding it.
24func MarketAddress() string { return unsafe.CurrentRealm().Address().String() }
25
26// ListingsCount returns the number of active listings (for pagination).
27func ListingsCount() int { return len(listingOrder) }
28
29// GetListingsPage returns a page of active listings, one per line:
30//
31//	collectionID|tokenID|seller|price|createdBlk
32//
33// Addresses are FULL (never truncated). offset/limit window the insertion-ordered
34// listing set; limit is clamped to [1, MaxPageSize].
35func GetListingsPage(offset, limit int) string {
36	if offset < 0 {
37		offset = 0
38	}
39	if limit <= 0 || limit > MaxPageSize {
40		limit = MaxPageSize
41	}
42	n := len(listingOrder)
43	end := offset + limit
44	if end > n {
45		end = n
46	}
47
48	var sb strings.Builder
49	for i := offset; i < end; i++ {
50		v, ok := listings.Get(listingOrder[i])
51		if !ok {
52			continue
53		}
54		l := v.(*Listing)
55		sb.WriteString(l.CollectionID)
56		sb.WriteString("|")
57		sb.WriteString(l.TokenID)
58		sb.WriteString("|")
59		sb.WriteString(l.Seller.String())
60		sb.WriteString("|")
61		sb.WriteString(itoa(l.Price))
62		sb.WriteString("|")
63		sb.WriteString(itoa(l.CreatedBlk))
64		sb.WriteString("\n")
65	}
66	return sb.String()
67}
68
69// GetOffersForToken returns the active offers on one (collection, token), one per line:
70//
71//	buyer|amount|createdBlk
72//
73// It uses a PREFIX-RANGE scan over the offer tree — offerKey is "collection:token:buyer",
74// so the range ["collection:token:", "collection:token;") reads only this token's
75// offers, never a full-tree scan. This is the read that finally lets the frontend wire
76// accept-offer and show a token's offers (no offers getter existed before v3.1).
77func GetOffersForToken(collectionID, tokenID string) string {
78	start := collectionID + ":" + tokenID + ":"
79	end := collectionID + ":" + tokenID + ";" // ';' (0x3b) is the byte after ':' (0x3a)
80
81	var sb strings.Builder
82	offers.Iterate(start, end, func(_ string, v interface{}) bool {
83		o := v.(*Offer)
84		sb.WriteString(o.Buyer.String())
85		sb.WriteString("|")
86		sb.WriteString(itoa(o.Amount))
87		sb.WriteString("|")
88		sb.WriteString(itoa(o.CreatedBlk))
89		sb.WriteString("\n")
90		return false
91	})
92	return sb.String()
93}