package block import ( "net/url" "gno.land/p/demo/tokens/grc1155" "gno.land/p/jeronimoalbi/pager" "gno.land/p/nt/ufmt" "gno.land/r/akkadia/admin" ) func Render(iUrl string) string { u, err := url.Parse(iUrl) if err != nil { return "404\n" } path := u.Path query := u.Query() switch { case path == "": return renderHome() case path == "blocks": return renderBlocksList(iUrl) case path == "block": return renderBlock(query.Get("id"), query.Get("page")) case path == "inventory": return renderInventory(query.Get("owner")) case path == "grc1155": return renderGRC1155(query.Get("id"), query.Get("owner")) default: return "404\n" } } func renderHome() string { output := `# Block Welcome to the Block management system on Akkadia. ## What is Block? Block is a GRC1155-based multi-token system where each block type represents a unique item in the game: * **GRC1155 Token**: Each block type is a fungible token with supply limits * **Mintable**: Users can mint blocks by paying the mint price * **Tradeable**: Blocks can be transferred between users * **Usable**: Blocks can be installed/uninstalled in chunks ## How Blocks Work 1. **System Blocks**: Admin creates system blocks (ID < 100000) 2. **User Blocks**: Users can create custom blocks (ID >= 100000) 3. **Minting**: Pay mint price to receive block tokens 4. **Usage**: Install blocks in chunks, uninstall to recover ## Config ` output += ufmt.Sprintf("* **List Limit**: %d\n", listLimit) output += ufmt.Sprintf("* **Creator BPS**: %d (%d.%02d%%)\n", creatorBPS, creatorBPS/100, creatorBPS%100) output += ` ## Stats ` output += ufmt.Sprintf("* **Total Blocks**: %d\n", blocks.Size()) output += ufmt.Sprintf("* **Next Block ID**: %d\n", nextBlockID) output += ` ## Quick Links * [Browse All Blocks](/r/akkadia/block:blocks) ## Search Block by ID ## Search Inventory by Owner ## Check GRC1155 Balance ` return output } // renderBlocksList renders a list of all blocks with pagination func renderBlocksList(iUrl string) string { output := `# All Blocks [← Home](/r/akkadia/block:) ` if blocks.Size() == 0 { output += "*No blocks created yet.*\n" return output } pages, err := pager.New(iUrl, blocks.Size(), pager.WithPageSize(10)) if err != nil { return output + "Invalid page" } // Get current page number for back links currentPage := (pages.Offset() / pages.PageSize()) + 1 blocks.IterateByOffset(pages.Offset(), pages.PageSize(), func(key string, value interface{}) bool { block := value.(map[string]string) blockID := block["id"] output += ufmt.Sprintf("### [%s - %s](/r/akkadia/block:block?id=%s&page=%d)\n\n", blockID, block["name"], blockID, currentPage) output += ufmt.Sprintf("* **Type**: %s\n", block["blockType"]) output += ufmt.Sprintf("* **Max Supply**: %s\n", block["maxSupply"]) output += ufmt.Sprintf("* **Mint Price**: %s ugnot\n", block["mintPrice"]) output += "\n---\n\n" return false }) if pages.HasPages() { output += pager.Picker(pages) } return output } func renderBlock(blockID string, page string) string { output := "# Block Detail\n\n" if page != "" { output += ufmt.Sprintf("[← Back to List](/r/akkadia/block:blocks?page=%s) | [View on Explorer](%s/m/explorer/block?id=%s)\n\n", page, admin.GetExplorerURL(), blockID) } else { output += ufmt.Sprintf("[← Home](/r/akkadia/block:) | [View on Explorer](%s/m/explorer/block?id=%s)\n\n", admin.GetExplorerURL(), blockID) } bid := stringToBlockID(blockID) blockIDKey := blockIDToKey(bid) propertiesVal, found := blocks.Get(blockIDKey) if !found { return output + "Block not found" } properties := propertiesVal.(map[string]string) textureURL := properties["textureURL"] previewURL := properties["previewURL"] output += ufmt.Sprintf("## %s\n\n", properties["name"]) output += `## Images ### Texture ||| ### Preview ` output += ufmt.Sprintf("![TextureURL](%s)\n\n|||\n\n![PreviewURL](%s192)\n", textureURL, previewURL) output += "\n\n" output += "## Properties\n\n" for key, value := range properties { if key == "mintPrice" || key == "usePrice" { output += ufmt.Sprintf("* **%s**: %s ugnot\n", key, value) } else if key == "installerBps" { bps := stringToBlockID(value) output += ufmt.Sprintf("* **%s**: %s (%d.%02d%%)\n", key, value, bps/100, bps%100) } else if key == "creator" { output += ufmt.Sprintf("* **%s**: %s [[View on Explorer](%s/m/explorer/player?address=%s)]\n", key, value, admin.GetExplorerURL(), value) } else if key == "textureURL" || key == "previewURL" { output += ufmt.Sprintf("* **%s**: [%s](%s)\n", key, value, value) } else { output += ufmt.Sprintf("* **%s**: %s\n", key, value) } } return output } func renderInventory(owner string) string { output := ufmt.Sprintf("# Inventory of %s\n\n", owner) output += "[← Home](/r/akkadia/block:)\n\n" if owner == "" { return output + "Owner address is required" } inventory := GetInventory(address(owner)) if len(inventory) == 0 { output += "*No blocks found for this owner.*\n" return output } output += ufmt.Sprintf("**Total Block Types**: %d\n\n", len(inventory)) output += "---\n\n" for _, item := range inventory { blockID := item["id"] balance := item["balance"] // Get block info bid := stringToBlockID(blockID) blockIDKey := blockIDToKey(bid) blockVal, found := blocks.Get(blockIDKey) if found { block := blockVal.(map[string]string) output += ufmt.Sprintf("### [%s - %s](/r/akkadia/block:block?id=%s)\n\n", blockID, block["name"], blockID) output += ufmt.Sprintf("* **Balance**: %s\n", balance) output += ufmt.Sprintf("* **Type**: %s\n", block["blockType"]) } else { output += ufmt.Sprintf("### %s\n\n", blockID) output += ufmt.Sprintf("* **Balance**: %s\n", balance) } output += "\n---\n\n" } return output } func renderGRC1155(blockID string, owner string) string { output := "# GRC1155 Balance\n\n" output += "[← Home](/r/akkadia/block:)\n\n" if blockID == "" || owner == "" { return output + "Block ID and owner address are required" } balance, err := token.BalanceOf(address(owner), grc1155.TokenID(blockID)) if err != nil { return output + "Error getting balance" } output += ufmt.Sprintf("* **Block ID**: %s\n", blockID) output += ufmt.Sprintf("* **Owner**: %s [[View on Explorer](%s/m/explorer/player?address=%s)]\n", owner, admin.GetExplorerURL(), owner) output += ufmt.Sprintf("* **Balance**: %d\n\n", balance) return output }