Skip to content

Commit

Permalink
Add support for realm faucet
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Sep 26, 2023
1 parent 977f568 commit df77543
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 7 deletions.
5 changes: 4 additions & 1 deletion faucet/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/gnolang/gnochess-faucet
go 1.20

require (
github.com/gnolang/faucet v0.0.0-20230916181707-934303e1b40d
github.com/gnolang/faucet v0.0.0-20230926204217-cdf94c5e2bb3
github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2
github.com/peterbourgon/ff/v3 v3.4.0
github.com/redis/go-redis/v9 v9.2.0
Expand All @@ -16,6 +16,8 @@ require (
github.com/btcsuite/btcd/btcutil v1.0.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger/v3 v3.2103.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand Down Expand Up @@ -45,5 +47,6 @@ require (
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
9 changes: 7 additions & 2 deletions faucet/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 87 additions & 4 deletions faucet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import (
"strconv"
"strings"
"syscall"
"time"

"github.com/gnolang/faucet"
"github.com/gnolang/faucet/client"
tm2Client "github.com/gnolang/faucet/client/http"
"github.com/gnolang/faucet/config"
"github.com/gnolang/faucet/estimate/static"
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
"github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/fftoml"
"github.com/redis/go-redis/v9"
Expand Down Expand Up @@ -61,6 +64,9 @@ type rootCfg struct {

redisURL string

tokenFundMethod string
tokenFundRealm string

allowedTokens stringArr // TODO temporary
}

Expand Down Expand Up @@ -180,6 +186,20 @@ func registerFlags(fs *flag.FlagSet, c *rootCfg) {
"redis connection string",
)

fs.StringVar(
&c.tokenFundRealm,
"token-fund-realm",
"",
"the path to the Realm that can fund the player",
)

fs.StringVar(
&c.tokenFundMethod,
"token-fund-method",
"",
"the Realm method that can fund the player",
)

// TODO temporary
fs.Var(
&c.allowedTokens,
Expand Down Expand Up @@ -221,20 +241,49 @@ func execMain(cfg *rootCfg) error {
// Create the client (HTTP)
cli := tm2Client.NewClient(cfg.remote)

// Prepare the middlewares
var middlewares []faucet.Middleware
// Prepare the faucet values
var (
middlewares []faucet.Middleware
prepareTxFn faucet.PrepareTxMessageFn
)

if len(cfg.allowedTokens) != 0 {
// TODO temporary for testing purpose without redis
// TODO temporary for testing purposes without redis
middlewares = append(middlewares, prepareTokenListMiddleware(cfg.allowedTokens))

// By default, for testing purposes, the transaction is a MsgSend
prepareTxFn = func(cfg faucet.PrepareCfg) std.Msg {
return bank.MsgSend{
FromAddress: cfg.FromAddress,
ToAddress: cfg.ToAddress,
Amount: cfg.SendAmount,
}
}
} else {
redisOpts, err := redis.ParseURL(cfg.redisURL)
if err != nil {
return err
}
redisClient := redis.NewClient(redisOpts)

// Prepare the middlewares
middlewares = append(middlewares, prepareTokenMiddleware(redisClient))

// Validate the realm values
if cfg.tokenFundMethod == "" {
return errors.New("invalid token Realm method supplied")
}

if cfg.tokenFundRealm == "" {
return errors.New("invalid token Realm path supplied")
}

// Prepare the tx message creation
prepareTxFn = prepareTxMessage(
redisClient,
cfg.tokenFundRealm,
cfg.tokenFundMethod,
)
}
// Call prepareFundMiddleware last to avoid funding users with invalid tokens
middlewares = append(middlewares, prepareFundMiddleware(cli, fundLimit))
Expand All @@ -247,6 +296,7 @@ func execMain(cfg *rootCfg) error {
faucet.WithLogger(newCommandLogger(logger)),
faucet.WithConfig(cfg.generateFaucetConfig()),
faucet.WithMiddlewares(middlewares),
faucet.WithPrepareTxMessageFn(prepareTxFn),
)
if err != nil {
return fmt.Errorf("unable to create faucet, %w", err)
Expand All @@ -262,6 +312,39 @@ func execMain(cfg *rootCfg) error {
return w.wait()
}

// prepareTxMessage returns the Realm fund call message creator.
// NOTE: This prepare method assumes the token was previously saved
// in the redis storage, through a middleware
func prepareTxMessage(redisClient *redis.Client, fundRealm, fundMethod string) faucet.PrepareTxMessageFn {
return func(cfg faucet.PrepareCfg) std.Msg {
var (
token string
err error

ctx, cancelFn = context.WithTimeout(context.Background(), time.Second*10)
)

defer cancelFn()

// Fetch the token from Redis
token, err = redisClient.HGet(ctx, "GNO:"+cfg.ToAddress.String(), "token").Result()
if err != nil {
// Invalid token request, pass it
// to the Realm as an empty value
token = ""
}

// Prepare the method call
return vm.MsgCall{
Caller: cfg.FromAddress,
PkgPath: fundRealm,
Func: fundMethod,
Args: []string{cfg.ToAddress.String(), token},
Send: cfg.SendAmount,
}
}
}

type cmdLogger struct {
logger *zap.Logger
}
Expand Down Expand Up @@ -499,7 +582,7 @@ func prepareTokenMiddleware(redisClient *redis.Client) faucet.Middleware {
http.Error(w, "Unable to read token email", http.StatusInternalServerError)
return
}
// Store gno adress, email and token, so they are retrievable via the
// Store gno address, email and token, so they are retrievable via the
// getEmail middleware.
err = redisClient.HSet(r.Context(), "GNO:"+request.To, "email", email, "token", token).Err()
if err != nil {
Expand Down

0 comments on commit df77543

Please sign in to comment.