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

render.gno

5.53 Kb · 172 lines
  1package padv7
  2
  3import (
  4	"strconv"
  5	"strings"
  6
  7	"gno.land/p/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/gnomemepad/ammmath"
  8	"gno.land/p/nt/ufmt/v0"
  9)
 10
 11// Render provides on-chain discovery (gnoweb). Read-only by convention.
 12//
 13// Paths:
 14//
 15//	""              — home / list
 16//	token/{id}      — launch detail
 17//	help            — API help
 18func Render(path string) string {
 19	path = strings.Trim(path, "/")
 20	if path == "" {
 21		return renderHome()
 22	}
 23	if path == "help" {
 24		return renderHelp()
 25	}
 26	if strings.HasPrefix(path, "token/") {
 27		id := strings.TrimPrefix(path, "token/")
 28		return renderToken(id)
 29	}
 30	return "> [!WARNING]\n> Path not found: " + sanitize(path) + "\n"
 31}
 32
 33func sanitize(s string) string {
 34	s = strings.ReplaceAll(s, "`", "'")
 35	s = strings.ReplaceAll(s, "<", "")
 36	s = strings.ReplaceAll(s, ">", "")
 37	return s
 38}
 39
 40func renderHome() string {
 41	out := "# gnomemepad\n\n"
 42	out += "Self-contained meme launchpad on gno.land — bonding curve to locked CPMM (no external AMM).\n\n"
 43	if !inited {
 44		out += "> [!CAUTION]\n> Protocol not initialized. Call Init first.\n\n"
 45		return out
 46	}
 47	out += ufmt.Sprintf("- Launches: **%d**\n", launches.Size())
 48	out += ufmt.Sprintf("- Protocol fees accrued: **%d** ugnot\n\n", protocolFees)
 49	out += "## Markets\n\n"
 50	if launches.Size() == 0 {
 51		out += "_No launches yet. Call Create with name, symbol, uri and bond._\n"
 52		return out
 53	}
 54	launches.Iterate("", "", func(key string, value any) bool {
 55		l := value.(*Launch)
 56		st := "curve"
 57		if l.Status == StatusGraduated {
 58			st = "graduated"
 59		}
 60		out += ufmt.Sprintf("- [%s ($%s)](token/%s) — %s — raised %d ugnot — buyers %d\n",
 61			sanitize(l.Name), sanitize(l.Symbol), l.ID, st, l.RaisedUgnot, l.BuyerCount)
 62		return false
 63	})
 64	out += "\n[Help](help)\n"
 65	return out
 66}
 67
 68func renderToken(id string) string {
 69	id = sanitize(id)
 70	l, ok := launches.Get(id).(*Launch)
 71	if !ok {
 72		return "> [!WARNING]\n> Unknown launch " + id + "\n\n[Home](./)\n"
 73	}
 74	st := "bonding curve"
 75	if l.Status == StatusGraduated {
 76		st = "graduated pool (LP locked)"
 77	}
 78	out := ufmt.Sprintf("# %s ($%s)\n\n", sanitize(l.Name), sanitize(l.Symbol))
 79	out += ufmt.Sprintf("- **ID:** %s\n", l.ID)
 80	out += ufmt.Sprintf("- **Status:** %s\n", st)
 81	out += ufmt.Sprintf("- **Creator:** %s\n", l.Creator.String())
 82	if l.URI != "" {
 83		out += ufmt.Sprintf("- **URI:** %s\n", sanitize(l.URI))
 84	}
 85	out += ufmt.Sprintf("- **Unique buyers:** %d\n", l.BuyerCount)
 86	out += ufmt.Sprintf("- **Creator fees (claimable):** %d ugnot\n\n", l.CreatorFees)
 87
 88	if l.Status == StatusCurve {
 89		remaining := CurveSupply - l.RealSold
 90		pct := int64(0)
 91		if GraduationThreshold > 0 {
 92			pct = l.RaisedUgnot * 100 / GraduationThreshold
 93			if pct > 100 {
 94				pct = 100
 95			}
 96		}
 97		spot := ammmath.SpotPriceUgnotPerToken(l.VirtualUgnot, l.VirtualToken)
 98		out += "## Bonding curve\n\n"
 99		out += ufmt.Sprintf("- Raised: **%d** / %d ugnot (%d%%)\n", l.RaisedUgnot, GraduationThreshold, pct)
100		out += ufmt.Sprintf("- Tokens sold: **%d** / %d\n", l.RealSold, CurveSupply)
101		out += ufmt.Sprintf("- Remaining on curve: **%d**\n", remaining)
102		out += ufmt.Sprintf("- Spot (ugnot/token x1e6): **%d**\n", spot)
103		out += "\nProgress toward graduation:\n\n"
104		out += progressBar(pct) + "\n"
105	} else {
106		spot := ammmath.SpotPriceUgnotPerToken(l.PoolUgnot, l.PoolToken)
107		out += "## Locked pool\n\n"
108		out += ufmt.Sprintf("- Pool ugnot: **%d**\n", l.PoolUgnot)
109		out += ufmt.Sprintf("- Pool tokens: **%d**\n", l.PoolToken)
110		out += ufmt.Sprintf("- Spot (ugnot/token x1e6): **%d**\n", spot)
111		out += "\n> [!NOTE]\n> Liquidity is permanently locked — there is no remove-liquidity path.\n"
112	}
113
114	out += "\n## Trade\n\n"
115	out += "Use wallet MsgCall (payable txs):\n\n"
116	if l.Status == StatusCurve {
117		out += ufmt.Sprintf("- Buy(id) with -send ugnot — id=%s\n", l.ID)
118		out += "- Sell(id, tokensIn)\n"
119		out += "- Graduate(id) when threshold met\n"
120	} else {
121		out += "- SwapBuy(id) with -send ugnot\n"
122		out += "- SwapSell(id, tokensIn)\n"
123	}
124	out += "\n[Home](./) · [Help](help)\n"
125	return out
126}
127
128func progressBar(pct int64) string {
129	if pct < 0 {
130		pct = 0
131	}
132	if pct > 100 {
133		pct = 100
134	}
135	filled := int(pct / 5)
136	bar := "["
137	for i := 0; i < 20; i++ {
138		if i < filled {
139			bar += "#"
140		} else {
141			bar += "."
142		}
143	}
144	bar += "] " + strconv.FormatInt(pct, 10) + "%"
145	return bar
146}
147
148func renderHelp() string {
149	out := "# gnomemepad API\n\n"
150	out += "## Lifecycle\n\n"
151	out += "1. Init() — once; caller becomes protocol treasury\n"
152	out += "2. Create(name, symbol, uri) + CreateBondUgnot — fair launch\n"
153	out += "3. Buy(id, minTokensOut) / Sell(id, amount, minUgnotOut) — bonding curve\n"
154	out += "4. Auto or Graduate(id) at threshold\n"
155	out += "5. SwapBuy(id, minTokensOut) / SwapSell(id, amount, minUgnotOut) — locked CPMM\n"
156	out += "6. Transfer / Approve / TransferFrom — GRC20\n"
157	out += "7. ClaimCreatorFees(id) / ClaimProtocolFees() / TransferProtocol(newAddr)\n\n"
158	out += "## Params (MVP)\n\n"
159	out += ufmt.Sprintf("- Total supply: %d\n", TotalSupply)
160	out += ufmt.Sprintf("- Curve sale: %d\n", CurveSupply)
161	out += ufmt.Sprintf("- Pool seed: %d\n", PoolSeed)
162	out += ufmt.Sprintf("- Graduation: %d ugnot\n", GraduationThreshold)
163	out += ufmt.Sprintf("- Fee: %d BPS\n", FeeBPS)
164	out += ufmt.Sprintf("- Create bond: %d ugnot\n\n", CreateBondUgnot)
165	out += "## Design\n\n"
166	out += "- No external AMM — this realm is the market\n"
167	out += "- Permanent LP lock after graduation\n"
168	out += "- EOA + OriginSend payment guards\n"
169	out += "- Factory-managed token balances (GRC20 wrap optional later)\n\n"
170	out += "[Home](./)\n"
171	return out
172}