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.

b58demo.gno

3.95 Kb · 132 lines
  1// Package b58demo is a small gnoweb demo of the Base58 codec provided by the
  2// [p/moul/x/daily/b58](/p/nym-moultest123/x/daily/b58/v0) library: it renders the alphabet,
  3// a gallery of worked examples, and an interactive hex → Base58 round-tripper.
  4//
  5// It contains no codec logic of its own — everything comes from `b58.Encode`,
  6// `b58.Decode` and `b58.Alphabet`.
  7package b58demo
  8
  9import (
 10	"encoding/hex"
 11	"strings"
 12
 13	"gno.land/p/nym-moultest123/x/daily/b58/v0"
 14)
 15
 16// Render produces the gnoweb Markdown view.
 17//
 18//   - "/"        → the alphabet + a small gallery of worked examples.
 19//   - "/<hex>"   → decode the hex input to bytes, show its Base58, and the
 20//     hex-encoded decoded round-trip to prove Encode/Decode are inverse.
 21func Render(path string) string {
 22	arg := strings.TrimPrefix(path, "/")
 23	arg = strings.TrimSpace(arg)
 24
 25	if arg == "" {
 26		return renderHome()
 27	}
 28	return renderHex(arg)
 29}
 30
 31func renderHome() string {
 32	var sb strings.Builder
 33	sb.WriteString("# Base58 (Bitcoin alphabet)\n\n")
 34	sb.WriteString("Demo of the [`p/moul/x/daily/b58`](/p/nym-moultest123/x/daily/b58/v0) library — ")
 35	sb.WriteString("base conversion from raw bytes (base-256) to base-58, using the ")
 36	sb.WriteString("Bitcoin alphabet (no `0`, `O`, `I`, `l`), pure byte-slice math, no `math/big`.\n\n")
 37
 38	sb.WriteString("## Alphabet\n\n")
 39	sb.WriteString("```\n")
 40	sb.WriteString(b58.Alphabet)
 41	sb.WriteString("\n```\n\n")
 42	sb.WriteString("58 characters, index 0…57.\n\n")
 43
 44	sb.WriteString("## Examples\n\n")
 45	sb.WriteString("| input (utf-8) | hex | Base58 |\n")
 46	sb.WriteString("|---|---|---|\n")
 47	examples := []string{"", "hello world", "gno.land", "Bitcoin"}
 48	for _, e := range examples {
 49		h := hex.EncodeToString([]byte(e))
 50		if h == "" {
 51			h = "(empty)"
 52		}
 53		label := e
 54		if label == "" {
 55			label = "(empty)"
 56		}
 57		sb.WriteString("| `" + label + "` | `" + h + "` | `" + b58.Encode([]byte(e)) + "` |\n")
 58	}
 59	sb.WriteString("\n")
 60
 61	sb.WriteString("Leading zero bytes → leading `1`s:\n\n")
 62	sb.WriteString("| bytes | Base58 |\n|---|---|\n")
 63	sb.WriteString("| `[0x00]` | `" + b58.Encode([]byte{0}) + "` |\n")
 64	sb.WriteString("| `[0x00 0x00 0x00]` | `" + b58.Encode([]byte{0, 0, 0}) + "` |\n\n")
 65
 66	sb.WriteString("## Try it\n\n")
 67	sb.WriteString("Append a hex string to the path to encode/round-trip it:\n\n")
 68	sb.WriteString("- `/68656c6c6f` — the bytes for \"hello\"\n")
 69	sb.WriteString("- `/00000000` — four zero bytes\n")
 70	sb.WriteString("- `/deadbeef`\n")
 71	return sb.String()
 72}
 73
 74func renderHex(arg string) string {
 75	var sb strings.Builder
 76	sb.WriteString("# Base58 — round-trip\n\n")
 77	sb.WriteString("[← alphabet & examples](/r/nym-moultest123/x/daily/b58demo/v0)\n\n")
 78
 79	raw, err := hex.DecodeString(arg)
 80	if err != nil {
 81		sb.WriteString("**Invalid hex input.**\n\n")
 82		sb.WriteString("`" + arg + "` is not a valid hex string. ")
 83		sb.WriteString("Provide an even number of hex digits, e.g. `/deadbeef`.\n")
 84		return sb.String()
 85	}
 86
 87	encoded := b58.Encode(raw)
 88	decoded := b58.Decode(encoded)
 89	roundTrip := hex.EncodeToString(decoded)
 90
 91	inHex := arg
 92	if inHex == "" {
 93		inHex = "(empty)"
 94	}
 95	outHex := roundTrip
 96	if outHex == "" {
 97		outHex = "(empty)"
 98	}
 99	enc := encoded
100	if enc == "" {
101		enc = "(empty)"
102	}
103
104	sb.WriteString("| step | value |\n|---|---|\n")
105	sb.WriteString("| hex input | `" + inHex + "` |\n")
106	sb.WriteString("| bytes | `" + byteList(raw) + "` |\n")
107	sb.WriteString("| **Base58** | `" + enc + "` |\n")
108	sb.WriteString("| decoded (hex) | `" + outHex + "` |\n\n")
109
110	if roundTrip == arg {
111		sb.WriteString("✓ Round-trip matches: `Decode(Encode(x)) == x`.\n")
112	} else {
113		sb.WriteString("✗ Round-trip mismatch.\n")
114	}
115	return sb.String()
116}
117
118// byteList renders a byte slice as a compact space-separated hex list.
119func byteList(b []byte) string {
120	if len(b) == 0 {
121		return "(none)"
122	}
123	const digits = "0123456789abcdef"
124	out := make([]byte, 0, len(b)*3)
125	for i, c := range b {
126		if i > 0 {
127			out = append(out, ' ')
128		}
129		out = append(out, digits[c>>4], digits[c&0x0f])
130	}
131	return string(out)
132}