← Back to Realms

Realm

gno.land/r/moul/x/daily/erc1155/v0

Overview

Realm Path
gno.land/r/moul/x/daily/erc1155/v0
Exported Functions
5
State Entries
2
Source Files
2
Total Package Entries
13

Exported Functions

5 exported functions

State

2 state entries

Source Code

FILES
erc1155.gno
go
1// Package erc1155 is an idiomatic gno.land port of the Solidity ERC-1155
2// multi-token standard. A single realm tracks many distinct token ids, each
3// with its own fungible balances. Balances are keyed by (owner, id) in an
4// avl.Tree so Render can iterate deterministically.
5package erc1155
6
7import (
8	"strconv"
9	"strings"
10
11	"chain"
12	"chain/runtime/unsafe"
13
14	"gno.land/p/nt/avl/v0"
15)
16
17// balances maps "<owner>:<id>" -> uint64 amount.
18var balances avl.Tree
19
20// supply maps "<id>" -> uint64 total minted for that id.
21var supply avl.Tree
22
23func balKey(owner address, id int) string {
24	return owner.String() + ":" + strconv.Itoa(id)
25}
26
27func supKey(id int) string {
28	return strconv.Itoa(id)
29}
30
31func getBalance(owner address, id int) uint64 {
32	k := balKey(owner, id)
33	if !balances.Has(k) {
34		return 0
35	}
36	return balances.Get(k).(uint64)
37}
38
39func setBalance(owner address, id int, amount uint64) {
40	k := balKey(owner, id)
41	if amount == 0 {
42		balances.Remove(k)
43		return
44	}
45	balances.Set(k, amount)
46}
47
48func getSupply(id int) uint64 {
49	k := supKey(id)
50	if !supply.Has(k) {
51		return 0
52	}
53	return supply.Get(k).(uint64)
54}
55
56// Mint creates `amount` units of token `id` and credits them to `to`.
57func Mint(cur realm, to address, id int, amount uint64) {
58	if !to.IsValid() {
59		panic("erc1155: mint to invalid address")
60	}
61	if amount == 0 {
62		panic("erc1155: mint amount must be > 0")
63	}
64	setBalance(to, id, getBalance(to, id)+amount)
65	supply.Set(supKey(id), getSupply(id)+amount)
66
67	operator := unsafe.PreviousRealm().Address()
68	chain.Emit("Mint",
69		"operator", operator.String(),
70		"to", to.String(),
71		"id", strconv.Itoa(id),
72		"amount", strconv.FormatUint(amount, 10),
73	)
74}
75
76// TransferSingle moves `amount` of token `id` from the caller to `to`.
77func TransferSingle(cur realm, to address, id int, amount uint64) {
78	if !to.IsValid() {
79		panic("erc1155: transfer to invalid address")
80	}
81	if amount == 0 {
82		panic("erc1155: transfer amount must be > 0")
83	}
84	from := unsafe.PreviousRealm().Address()
85	fromBal := getBalance(from, id)
86	if fromBal < amount {
87		panic("erc1155: insufficient balance")
88	}
89	setBalance(from, id, fromBal-amount)
90	setBalance(to, id, getBalance(to, id)+amount)
91
92	chain.Emit("TransferSingle",
93		"from", from.String(),
94		"to", to.String(),
95		"id", strconv.Itoa(id),
96		"amount", strconv.FormatUint(amount, 10),
97	)
98}
99
100// BalanceOf returns the amount of token `id` held by `owner`.
101func BalanceOf(owner address, id int) uint64 {
102	return getBalance(owner, id)
103}
104
105// TotalSupply returns the total amount minted of token `id`.
106func TotalSupply(id int) uint64 {
107	return getSupply(id)
108}
109
110// Render prints a balances table and a per-id supply table.
111func Render(path string) string {
112	var b strings.Builder
113	b.WriteString("# ERC-1155 Multi-Token\n\n")
114	b.WriteString("A single realm holding many fungible token ids. ")
115	b.WriteString("Balances are keyed by `(owner, id)`.\n\n")
116
117	b.WriteString("## Balances\n\n")
118	if balances.Size() == 0 {
119		b.WriteString("_No balances yet. Call `Mint` to create tokens._\n\n")
120	} else {
121		b.WriteString("| Owner | ID | Amount |\n")
122		b.WriteString("|---|---|---|\n")
123		balances.Iterate("", "", func(key string, value interface{}) bool {
124			owner, id := splitBalKey(key)
125			b.WriteString("| `" + owner + "` | " + id + " | " +
126				strconv.FormatUint(value.(uint64), 10) + " |\n")
127			return false
128		})
129		b.WriteString("\n")
130	}
131
132	b.WriteString("## Supply per ID\n\n")
133	if supply.Size() == 0 {
134		b.WriteString("_No tokens minted._\n")
135	} else {
136		b.WriteString("| ID | Total Supply |\n")
137		b.WriteString("|---|---|\n")
138		supply.Iterate("", "", func(key string, value interface{}) bool {
139			b.WriteString("| " + key + " | " +
140				strconv.FormatUint(value.(uint64), 10) + " |\n")
141			return false
142		})
143	}
144
145	return b.String()
146}
147
148// splitBalKey splits a "<owner>:<id>" balance key. The owner (a bech32
149// address) contains no ':', so the id is the substring after the last ':'.
150func splitBalKey(key string) (owner, id string) {
151	i := strings.LastIndex(key, ":")
152	if i < 0 {
153		return key, ""
154	}
155	return key[:i], key[i+1:]
156}
157

Raw Package Data

Raw JSON data