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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

render.gno

7.33 Kb · 198 lines
  1package padv3
  2
  3import (
  4	"strconv"
  5	"strings"
  6
  7	ammmath "gno.land/p/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/gnomi/ammmathv2"
  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 := "# gnomi\n\n"
 42	out += "Meme launchpad - WUGNOT bonding curve -> remaining tokens + raised WUGNOT seed Gnoswap LP (auto-list).\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	if protocolAddr.IsValid() {
 49		out += ufmt.Sprintf("- Protocol treasury: `%s`\n", protocolAddr.String())
 50	}
 51	out += ufmt.Sprintf("- Protocol fees pending (claim/push): **%d** ugnot\n", protocolFees)
 52	out += ufmt.Sprintf("- Protocol fees paid (lifetime): **%d** ugnot\n\n", protocolFeesPaid)
 53	out += "## Markets\n\n"
 54	if launches.Size() == 0 {
 55		out += "_No launches yet. Call Create with name, symbol, uri and bond._\n"
 56		return out
 57	}
 58	launches.Iterate("", "", func(key string, value any) bool {
 59		l := value.(*Launch)
 60		st := "curve"
 61		if l.Status == StatusGraduated {
 62			st = "graduated"
 63		}
 64		out += ufmt.Sprintf("- [%s ($%s)](token/%s) - %s - raised %d ugnot - buyers %d\n",
 65			sanitize(l.Name), sanitize(l.Symbol), l.ID, st, l.RaisedUgnot, l.BuyerCount)
 66		return false
 67	})
 68	out += "\n[Help](help)\n"
 69	return out
 70}
 71
 72func renderToken(id string) string {
 73	id = sanitize(id)
 74	l, ok := launches.Get(id).(*Launch)
 75	if !ok {
 76		return "> [!WARNING]\n> Unknown launch " + id + "\n\n[Home](./)\n"
 77	}
 78	st := "bonding curve"
 79	if l.Status == StatusGraduated {
 80		st = "graduated pool (LP locked)"
 81	}
 82	out := ufmt.Sprintf("# %s ($%s)\n\n", sanitize(l.Name), sanitize(l.Symbol))
 83	out += ufmt.Sprintf("- **ID:** %s\n", l.ID)
 84	out += ufmt.Sprintf("- **Status:** %s\n", st)
 85	out += ufmt.Sprintf("- **Creator:** %s\n", l.Creator.String())
 86	if l.URI != "" {
 87		out += ufmt.Sprintf("- **URI:** %s\n", sanitize(l.URI))
 88	}
 89	out += ufmt.Sprintf("- **Unique buyers:** %d\n", l.BuyerCount)
 90	out += ufmt.Sprintf("- **Creator fees (claimable):** %d ugnot\n\n", l.CreatorFees)
 91
 92	if l.Status == StatusCurve {
 93		remaining := CurveSupply - l.RealSold
 94		pct := int64(0)
 95		if graduationThreshold() > 0 {
 96			pct = l.RaisedUgnot * 100 / graduationThreshold()
 97			if pct > 100 {
 98				pct = 100
 99			}
100		}
101		spot := ammmath.SpotPriceUgnotPerToken(l.VirtualUgnot, l.VirtualToken)
102		out += "## Bonding curve\n\n"
103		out += ufmt.Sprintf("- Raised: **%d** / %d ugnot (%d%%)\n", l.RaisedUgnot, graduationThreshold(), pct)
104		out += ufmt.Sprintf("- Tokens sold: **%d** / %d\n", l.RealSold, CurveSupply)
105		out += ufmt.Sprintf("- Remaining on curve: **%d**\n", remaining)
106		out += ufmt.Sprintf("- Spot (ugnot/token x1e6): **%d**\n", spot)
107		out += "\nProgress toward graduation:\n\n"
108		out += progressBar(pct) + "\n"
109	} else {
110		spot := ammmath.SpotPriceUgnotPerToken(l.PoolUgnot, l.PoolToken)
111		out += "## Liquidity (post-graduate)\n\n"
112		out += ufmt.Sprintf("- Raised capital (record): **%d** ugnot\n", l.PoolUgnot)
113		out += ufmt.Sprintf("- LP tokens (curve-spot sized): **%d**\n", l.PoolToken)
114		if l.LeftoverTokens > 0 {
115			out += ufmt.Sprintf("- Leftover on pad (not in LP): **%d**\n", l.LeftoverTokens)
116		}
117		out += ufmt.Sprintf("- Spot (ugnot/token x1e6): **%d**\n", spot)
118		if l.GnoswapListed {
119			out += ufmt.Sprintf("- **Gnoswap listed:** `%s`\n", sanitize(l.GnoswapPoolPath))
120			out += ufmt.Sprintf("- Position NFT id: **%d** (pad-owned, locked)\n", l.GnoswapPositionID)
121			out += ufmt.Sprintf("- Fee WUGNOT spent: **%d** | LP WUGNOT: **%d**\n", l.FeeWugnotSpent, l.LiqWugnotUsed)
122			out += "\n> [!NOTE]\n> Trade on Gnoswap router - pad SwapBuy/SwapSell disabled after auto-list.\n"
123		} else {
124			out += ufmt.Sprintf("- Gnoswap: %s\n", sanitize(l.GnoswapNote))
125			out += "\n> [!NOTE]\n> Internal CPMM. List: wugnot.Deposit -> Approve(pad) -> RetryListGnoswap (LP ugnot reimbursed; prefer GNS for fee).\n"
126			out += ufmt.Sprintf("- ListNeed: `%s`\n", listNeedOf(l))
127		}
128	}
129
130	out += "\n## Trade\n\n"
131	out += "Use wallet MsgCall (payable txs):\n\n"
132	if l.Status == StatusCurve {
133		out += ufmt.Sprintf("- Buy(id) with -send ugnot - id=%s\n", l.ID)
134		out += "- Sell(id, tokensIn)\n"
135		out += "- Graduate(id) when threshold met\n"
136	} else if l.GnoswapListed {
137		out += "- Trade on Gnoswap router (pad SwapBuy/Sell disabled)\n"
138		out += ufmt.Sprintf("- Pool: `%s`\n", sanitize(l.GnoswapPoolPath))
139	} else {
140		out += "- SwapBuy(id) with -send ugnot\n"
141		out += "- SwapSell(id, tokensIn)\n"
142		out += ufmt.Sprintf("- RetryListGnoswap(id) - auto-pull WUGNOT/GNS from caller if Approved - id=%s\n", l.ID)
143	}
144	out += "\n[Home](./) | [Help](help)\n"
145	return out
146}
147
148func progressBar(pct int64) string {
149	if pct < 0 {
150		pct = 0
151	}
152	if pct > 100 {
153		pct = 100
154	}
155	filled := int(pct / 5)
156	bar := "["
157	for i := 0; i < 20; i++ {
158		if i < filled {
159			bar += "#"
160		} else {
161			bar += "."
162		}
163	}
164	bar += "] " + strconv.FormatInt(pct, 10) + "%"
165	return bar
166}
167
168func renderHelp() string {
169	out := "# gnomi API\n\n"
170	out += "## Lifecycle\n\n"
171	out += "1. Init() - once; caller becomes protocol treasury\n"
172	out += "2. Create(name, symbol, uri) + bond from bond realm (promo/normal)\n"
173	out += "3. Buy(id, minTokensOut) / Sell(id, amount, minUgnotOut) - bonding curve\n"
174	out += "4. Auto or Graduate(id) at threshold\n"
175	out += "5. Graduate seeds remaining tokens + raised as liquidity\n"
176	out += "   -> auto Gnoswap CreatePool+Mint if pad has WUGNOT inventory\n"
177	out += "   -> else locked internal CPMM (SwapBuy/SwapSell)\n"
178	out += "6. Transfer / Approve / TransferFrom - GRC20\n"
179	out += "7. Fees:\n"
180	out += "   - Creator: ClaimCreatorFees(id) - only creator, **must claim**\n"
181	out += "   - Protocol: ClaimProtocolFees() (treasury) or PushProtocolFees() (anyone -> treasury)\n"
182	out += "   - TransferProtocol(newAddr) / WithdrawProtocolUgnot(amount) - treasury ops\n"
183	out += "   - Gnoswap CreatePool GNS fee goes to Gnoswap, not pad treasury\n\n"
184	out += "## Params (MVP)\n\n"
185	out += ufmt.Sprintf("- Total supply: %d\n", TotalSupply)
186	out += ufmt.Sprintf("- Curve sale: %d\n", CurveSupply)
187	out += ufmt.Sprintf("- LP tokens at grad: TotalSupply - RealSold (was PoolSeed=%d)\n", PoolSeed)
188	out += ufmt.Sprintf("- Graduation: %d ugnot\n", graduationThreshold())
189	out += ufmt.Sprintf("- Fee: %d BPS\n", FeeBPS)
190	out += ufmt.Sprintf("- Create bond (live): %d ugnot\n\n", requiredCreateBond())
191	out += "## Design\n\n"
192	out += "- Remaining tokens + raised GNOT -> liquidity at graduate\n"
193	out += "- Part of WUGNOT inventory swaps to GNS for CreatePool fee\n"
194	out += "- Permanent LP lock (pad holds Gnoswap position NFT)\n"
195	out += "- EOA + OriginSend payment guards\n\n"
196	out += "[Home](./)\n"
197	return out
198}