Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

list_venue.gno

4.87 Kb · 198 lines
  1package padv2
  2
  3import (
  4	"chain"
  5	"strconv"
  6	"strings"
  7
  8	"gno.land/p/nt/avl/v0"
  9)
 10
 11// ListVenue IDs (compile-time switch in tryListVenue). Adding a new DEX
 12// means a new case + adapter file and a new pad version — Gno cannot
 13// dynamically import by path string.
 14const (
 15	VenueGnoswap = "gnoswap"
 16	VenueZdex    = "zdex"
 17)
 18
 19// listVenueMeta is registry metadata (not a callable adapter).
 20type listVenueMeta struct {
 21	ID           string
 22	Label        string
 23	Enabled      bool
 24	FeeAssetHint string // e.g. "GNS" for CreatePool fee UX
 25}
 26
 27var (
 28	listVenues       avl.Tree // id -> *listVenueMeta
 29	defaultListVenue string
 30)
 31
 32func ensureListVenuesSeeded() {
 33	if listVenues.Size() > 0 {
 34		return
 35	}
 36	// Mainnet-first: zdex default (hub listable when adapter + realm live).
 37	// Gnoswap registered but disabled until mainnet router/pool exist — enable via SetListVenue.
 38	registerListVenue(VenueZdex, "zdex", true, "ugnot")
 39	registerListVenue(VenueGnoswap, "Gnoswap", false, "GNS")
 40	if defaultListVenue == "" {
 41		defaultListVenue = VenueZdex
 42	}
 43}
 44
 45func registerListVenue(id, label string, enabled bool, feeHint string) {
 46	id = strings.TrimSpace(strings.ToLower(id))
 47	if id == "" {
 48		return
 49	}
 50	label = strings.TrimSpace(label)
 51	if label == "" {
 52		label = id
 53	}
 54	listVenues.Set(id, &listVenueMeta{
 55		ID:           id,
 56		Label:        label,
 57		Enabled:      enabled,
 58		FeeAssetHint: strings.TrimSpace(feeHint),
 59	})
 60}
 61
 62func normalizeVenueID(venueId string) string {
 63	ensureListVenuesSeeded()
 64	v := strings.TrimSpace(strings.ToLower(venueId))
 65	if v == "" {
 66		if defaultListVenue != "" {
 67			return defaultListVenue
 68		}
 69		return VenueZdex
 70	}
 71	return v
 72}
 73
 74func venueEnabled(venueId string) bool {
 75	ensureListVenuesSeeded()
 76	id := normalizeVenueID(venueId)
 77	raw := listVenues.Get(id)
 78	if raw == nil {
 79		return false
 80	}
 81	m, ok := raw.(*listVenueMeta)
 82	return ok && m != nil && m.Enabled
 83}
 84
 85// DefaultListVenue returns the venue id used when callers pass "".
 86func DefaultListVenue() string {
 87	ensureListVenuesSeeded()
 88	if defaultListVenue == "" {
 89		return VenueZdex
 90	}
 91	return defaultListVenue
 92}
 93
 94// SetDefaultListVenue sets the default list venue (protocol only).
 95func SetDefaultListVenue(cur realm, venueId string) {
 96	requireProtocol(cur)
 97	ensureListVenuesSeeded()
 98	id := strings.TrimSpace(strings.ToLower(venueId))
 99	if id == "" {
100		panic("pad: empty venue")
101	}
102	if listVenues.Get(id) == nil {
103		panic("pad: unknown venue")
104	}
105	defaultListVenue = id
106	chain.Emit("SetDefaultListVenue", "venue", id)
107}
108
109// SetListVenue registers or updates venue metadata (protocol only).
110// Does not add compile-time dispatch — unknown ids stay non-listable until
111// tryListVenue gains a case in a future pad version.
112func SetListVenue(cur realm, id, label string, enabled bool, feeAssetHint string) {
113	requireProtocol(cur)
114	ensureListVenuesSeeded()
115	id = strings.TrimSpace(strings.ToLower(id))
116	if id == "" || len(id) > 32 {
117		panic("pad: invalid venue id")
118	}
119	for _, c := range id {
120		if !((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-') {
121			panic("pad: venue id charset")
122		}
123	}
124	registerListVenue(id, label, enabled, feeAssetHint)
125	chain.Emit("SetListVenue",
126		"id", id,
127		"label", strings.TrimSpace(label),
128		"enabled", strconv.FormatBool(enabled),
129		"feeHint", strings.TrimSpace(feeAssetHint),
130	)
131}
132
133// ListVenues returns newline-separated "id|label|enabled|feeHint" (enabled 0|1).
134func ListVenues() string {
135	ensureListVenuesSeeded()
136	out := ""
137	listVenues.Iterate("", "", func(key string, value any) bool {
138		m, ok := value.(*listVenueMeta)
139		if !ok || m == nil {
140			return false
141		}
142		en := "0"
143		if m.Enabled {
144			en = "1"
145		}
146		line := m.ID + "|" + m.Label + "|" + en + "|" + m.FeeAssetHint
147		if out != "" {
148			out += "\n"
149		}
150		out += line
151		return false
152	})
153	return out
154}
155
156// ListVenueOf returns the venue id used for a successful list (or "").
157func ListVenueOf(id string) string {
158	return mustLaunch(id).ListVenue
159}
160
161// resetListVenuesForTest clears venue registry (unit tests).
162func resetListVenuesForTest() {
163	listVenues = avl.Tree{}
164	defaultListVenue = ""
165}
166
167// tryListVenue dispatches to a compile-time adapter. Unknown / disabled
168// venues soft-fail with a note (no panic) so UI can show ListNeed guidance.
169func tryListVenue(cur realm, l *Launch, venueId string, raisedUgnot, liqTokens int64) bool {
170	ensureListVenuesSeeded()
171	id := normalizeVenueID(venueId)
172	if !venueEnabled(id) {
173		if l != nil {
174			l.GnoswapNote = "list skip: venue disabled or unknown: " + id
175		}
176		return false
177	}
178	switch id {
179	case VenueZdex:
180		ok := tryListOnZdex(cur, l, raisedUgnot, liqTokens)
181		if ok && l != nil {
182			l.ListVenue = VenueZdex
183		}
184		return ok
185	case VenueGnoswap:
186		ok := listOnGnoswapWithFunding(cur, l, raisedUgnot, liqTokens)
187		if ok && l != nil {
188			l.ListVenue = VenueGnoswap
189		}
190		return ok
191	default:
192		// Registered in metadata but no adapter case yet.
193		if l != nil {
194			l.GnoswapNote = "list skip: venue adapter not linked in this pad: " + id
195		}
196		return false
197	}
198}