banker_grc20.gno
3.16 Kb · 130 lines
1package treasury
2
3import (
4 "chain/runtime"
5 "errors"
6 "strconv"
7
8 "gno.land/p/demo/tokens/grc20"
9 "gno.land/p/nt/ufmt/v0"
10)
11
12var (
13 ErrNoListerProvided = errors.New("no lister provided")
14 ErrGRC20TokenNotFound = errors.New("GRC20 token not found")
15)
16
17// GRC20Banker is a Banker that sends GRC20 tokens listed using a getter
18// set during initialization.
19type GRC20Banker struct {
20 owner address // The address of this GRC20 banker owner.
21 lister TokenListerFunc // Allows to list tokens from methods that require it.
22}
23
24// TokenListerFunc is a function type that returns a map of GRC20 tokens.
25type TokenListerFunc func() map[string]*grc20.Token
26
27var _ Banker = (*GRC20Banker)(nil)
28
29// ID implements Banker.
30func (GRC20Banker) ID() string {
31 return "GRC20"
32}
33
34// Send implements Banker.
35func (gb *GRC20Banker) Send(p Payment) error {
36 if runtime.CurrentRealm().Address() != gb.owner {
37 return ErrCurrentRealmIsNotOwner
38 }
39
40 payment, ok := p.(grc20Payment)
41 if !ok {
42 return ErrInvalidPaymentType
43 }
44
45 // Get the GRC20 tokens using the lister.
46 tokens := gb.lister()
47
48 // Look for the token corresponding to the payment tokenKey.
49 token, ok := tokens[payment.tokenKey]
50 if !ok {
51 return ufmt.Errorf("%v: %s", ErrGRC20TokenNotFound, payment.tokenKey)
52 }
53
54 // Send the token.
55 return token.RealmTeller().Transfer(payment.toAddress, payment.amount)
56}
57
58// Balances implements Banker.
59func (gb *GRC20Banker) Balances() []Balance {
60 // Get the GRC20 tokens from the lister.
61 tokens := gb.lister()
62
63 // Convert GRC20 tokens to []Balance.
64 var balances []Balance
65 for key, token := range tokens {
66 balances = append(balances, Balance{
67 Denom: key,
68 Amount: token.BalanceOf(gb.owner),
69 })
70 }
71 return balances
72}
73
74// Address implements Banker.
75func (gb *GRC20Banker) Address() string {
76 return gb.owner.String()
77}
78
79// NewGRC20Banker creates a new GRC20Banker with the current Realm's address
80// as the owner.
81func NewGRC20Banker(lister TokenListerFunc) (*GRC20Banker, error) {
82 owner := runtime.CurrentRealm().Address()
83
84 return NewGRC20BankerWithOwner(owner, lister)
85}
86
87// NewGRC20BankerWithOwner creates a new GRC20Banker with the given address.
88func NewGRC20BankerWithOwner(owner address, lister TokenListerFunc) (*GRC20Banker, error) {
89 if owner == "" {
90 return nil, ErrNoOwnerProvided
91 }
92
93 if lister == nil {
94 return nil, ErrNoListerProvided
95 }
96
97 return &GRC20Banker{
98 owner: owner,
99 lister: lister,
100 }, nil
101}
102
103// grc20Payment represents a payment that is issued by a GRC20Banker.
104type grc20Payment struct {
105 tokenKey string // The key associated with the GRC20 token.
106 amount int64 // The amount of token to send.
107 toAddress address // The recipient of the payment.
108}
109
110var _ Payment = (*grc20Payment)(nil)
111
112// BankerID implements Payment.
113func (grc20Payment) BankerID() string {
114 return GRC20Banker{}.ID()
115}
116
117// String implements Payment.
118func (gp grc20Payment) String() string {
119 amount := strconv.Itoa(int(gp.amount))
120 return amount + gp.tokenKey + " to " + gp.toAddress.String()
121}
122
123// NewGRC20Payment creates a new grc20Payment.
124func NewGRC20Payment(tokenKey string, amount int64, toAddress address) Payment {
125 return grc20Payment{
126 tokenKey: tokenKey,
127 amount: amount,
128 toAddress: toAddress,
129 }
130}