treasury.gno
4.20 Kb · 146 lines
1package treasury
2
3import (
4 "chain/banker"
5
6 "gno.land/p/nt/grc20/v0"
7 t "gno.land/p/nt/treasury/v0"
8
9 "gno.land/r/gov/dao"
10 "gno.land/r/nt/grc20reg/v0"
11)
12
13var (
14 treasury *t.Treasury
15 tokenKeys = []string{
16 // TODO: Add the default GRC20 tokens we want to support here.
17 }
18)
19
20func init(cur realm) {
21 // Define a token lister for the GRC20Banker.
22 // For now, GovDAO uses a static list of tokens.
23 grc20Lister := func() map[string]*grc20.Token {
24 // Get the GRC20 tokens from the registry.
25 tokens := map[string]*grc20.Token{}
26 for _, key := range tokenKeys {
27 // Get the token by its key.
28 token := grc20reg.Get(key)
29 if token != nil {
30 tokens[key] = token
31 }
32 }
33
34 return tokens
35 }
36
37 // Init the treasury bankers.
38 coinsBanker, err := t.NewCoinsBankerWithOwner(cur.Address(), banker.NewBanker(banker.BankerTypeRealmSend, cur))
39 if err != nil {
40 panic("failed to create CoinsBanker: " + err.Error())
41 }
42 grc20Banker, err := t.NewGRC20BankerWithOwner(cur.Address(), grc20Lister)
43 if err != nil {
44 panic("failed to create GRC20Banker: " + err.Error())
45 }
46 bankers := []t.Banker{
47 coinsBanker,
48 grc20Banker,
49 }
50
51 // Create the treasury instance with the bankers. cur.PkgPath() is
52 // captured for render-link construction (See full history → /r/gov/dao/treasury/v0:.../history).
53 treasury, err = t.New(bankers, cur.PkgPath())
54 if err != nil {
55 panic("failed to create treasury: " + err.Error())
56 }
57}
58
59// SetTokenKeys sets the GRC20 token registry keys that the treasury will use.
60func SetTokenKeys(cur realm, keys []string) {
61 // Crossing function, so cur is a live minted cur and this is redundant
62 // today; kept to match the documented rule that caller identity is
63 // derived from cur.Previous() only under an IsCurrent() guard.
64 if !cur.IsCurrent() {
65 panic("realm value is not the caller's live cur")
66 }
67 caller := cur.Previous().PkgPath()
68
69 // Check if the caller realm is allowed to set token keys.
70 if !dao.InAllowedDAOs(caller) {
71 panic("this Realm is not allowed to send payment: " + caller)
72 }
73
74 // Copied, not aliased: the grc20Lister closure re-reads tokenKeys on every
75 // Balances() and every GRC20 payment, so storing the caller's array as
76 // given would leave it a permanent write handle on this realm's token set.
77 tokenKeys = make([]string, len(keys))
78 copy(tokenKeys, keys)
79}
80
81// Send sends a payment using the treasury instance.
82func Send(cur realm, payment t.Payment) {
83 // See SetTokenKeys: redundant under the crossing-function guarantee, kept
84 // for conformance with the IsCurrent()-before-Previous() rule.
85 if !cur.IsCurrent() {
86 panic("realm value is not the caller's live cur")
87 }
88 caller := cur.Previous().PkgPath()
89
90 // Check if the caller realm is allowed to send payments.
91 if !dao.InAllowedDAOs(caller) {
92 panic("this Realm is not allowed to send payment: " + caller)
93 }
94
95 // Send the payment using the treasury instance. cur is this realm's
96 // captured cur — passes IsCurrent inside Banker.Send and matches the
97 // banker's owner (this realm's address) registered at init.
98 if err := treasury.Send(0, cur, payment); err != nil {
99 panic(err)
100 }
101}
102
103// History returns the payment history sent by the banker with the given ID.
104// Payments are paginated, with the most recent payments first.
105func History(bankerID string, pageNumber int, pageSize int) []t.Payment {
106 history, err := treasury.History(bankerID, pageNumber, pageSize)
107 if err != nil {
108 panic("failed to get history: " + err.Error())
109 }
110
111 return history
112}
113
114// Balances returns the balances of the banker with the given ID.
115func Balances(bankerID string) []t.Balance {
116 balances, err := treasury.Balances(bankerID)
117 if err != nil {
118 panic("failed to get balances: " + err.Error())
119 }
120
121 return balances
122}
123
124// Address returns the address of the banker with the given ID.
125func Address(bankerID string) string {
126 addr, err := treasury.Address(bankerID)
127 if err != nil {
128 panic("failed to get address: " + err.Error())
129 }
130
131 return addr
132}
133
134// HasBanker checks if a banker with the given ID is registered.
135func HasBanker(bankerID string) bool {
136 return treasury.HasBanker(bankerID)
137}
138
139// ListBankerIDs returns a list of all registered banker IDs.
140func ListBankerIDs() []string {
141 return treasury.ListBankerIDs()
142}
143
144func Render(path string) string {
145 return treasury.Render(path)
146}