Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}