From b4aa78f2879a4e71bc99ec90ca961910915fc70a Mon Sep 17 00:00:00 2001 From: iczc Date: Tue, 6 Aug 2024 21:32:10 +0800 Subject: [PATCH] feat: support decimal payout amount --- cmd/server.go | 4 ++-- go.mod | 1 + go.sum | 2 ++ internal/chain/transaction.go | 6 ++++-- internal/chain/util.go | 9 ++++++--- internal/chain/util_test.go | 4 +++- internal/server/config.go | 4 ++-- internal/server/server.go | 4 ++-- 8 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cmd/server.go b/cmd/server.go index 72df9ff0..2b82277e 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -24,7 +24,7 @@ var ( proxyCntFlag = flag.Int("proxycount", 0, "Count of reverse proxies in front of the server") versionFlag = flag.Bool("version", false, "Print version number") - payoutFlag = flag.Int("faucet.amount", 1, "Number of Ethers to transfer per user request") + payoutFlag = flag.Float64("faucet.amount", 1, "Number of Ethers to transfer per user request") intervalFlag = flag.Int("faucet.minutes", 1440, "Number of minutes to wait between funding rounds") netnameFlag = flag.String("faucet.name", "testnet", "Network name to display on the frontend") symbolFlag = flag.String("faucet.symbol", "ETH", "Token symbol to display on the frontend") @@ -60,7 +60,7 @@ func Execute() { if err != nil { panic(fmt.Errorf("cannot connect to web3 provider: %w", err)) } - config := server.NewConfig(*netnameFlag, *symbolFlag, *httpPortFlag, *intervalFlag, *payoutFlag, *proxyCntFlag, *hcaptchaSiteKeyFlag, *hcaptchaSecretFlag) + config := server.NewConfig(*netnameFlag, *symbolFlag, *httpPortFlag, *intervalFlag, *proxyCntFlag, *payoutFlag, *hcaptchaSiteKeyFlag, *hcaptchaSecretFlag) go server.NewServer(txBuilder, config).Run() c := make(chan os.Signal, 1) diff --git a/go.mod b/go.mod index e964e556..4a2076ab 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/ethereum/go-ethereum v1.10.26 github.com/jellydator/ttlcache/v2 v2.11.1 github.com/kataras/hcaptcha v0.0.2 + github.com/shopspring/decimal v1.4.0 github.com/sirupsen/logrus v1.9.3 github.com/urfave/negroni v1.0.0 ) diff --git a/go.sum b/go.sum index 7b017ab0..2c30f51c 100644 --- a/go.sum +++ b/go.sum @@ -339,6 +339,8 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= diff --git a/internal/chain/transaction.go b/internal/chain/transaction.go index 112d4773..e9ff2b83 100644 --- a/internal/chain/transaction.go +++ b/internal/chain/transaction.go @@ -87,7 +87,6 @@ func (b *TxBuild) Transfer(ctx context.Context, to string, value *big.Int) (comm } if err = b.client.SendTransaction(ctx, signedTx); err != nil { - log.Error("failed to send tx", "tx hash", signedTx.Hash().String(), "err", err) if strings.Contains(strings.ToLower(err.Error()), "nonce") { b.refreshNonce(context.Background()) } @@ -145,7 +144,10 @@ func (b *TxBuild) getAndIncrementNonce() uint64 { func (b *TxBuild) refreshNonce(ctx context.Context) { nonce, err := b.client.PendingNonceAt(ctx, b.Sender()) if err != nil { - log.Error("failed to refresh nonce", "address", b.Sender(), "err", err) + log.WithFields(log.Fields{ + "address": b.Sender(), + "error": err, + }).Error("failed to refresh account nonce") return } diff --git a/internal/chain/util.go b/internal/chain/util.go index 1c57e4f2..8ead5eeb 100644 --- a/internal/chain/util.go +++ b/internal/chain/util.go @@ -4,11 +4,14 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" ) -func EtherToWei(amount int64) *big.Int { - ether := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - return new(big.Int).Mul(big.NewInt(amount), ether) +func EtherToWei(amount float64) *big.Int { + oneEther := decimal.NewFromFloat(1e18) + result := decimal.NewFromFloat(amount).Mul(oneEther) + wei, _ := new(big.Int).SetString(result.String(), 10) + return wei } func Has0xPrefix(str string) bool { diff --git a/internal/chain/util_test.go b/internal/chain/util_test.go index 0a68cafa..bec0a807 100644 --- a/internal/chain/util_test.go +++ b/internal/chain/util_test.go @@ -35,9 +35,11 @@ func TestIsValidAddress(t *testing.T) { func TestEtherToWei(t *testing.T) { tests := []struct { name string - amount int64 + amount float64 want *big.Int }{ + {name: "0.01ether", amount: 0.01, want: new(big.Int).Exp(big.NewInt(10), big.NewInt(16), nil)}, + {name: "0.1ether", amount: 0.1, want: new(big.Int).Exp(big.NewInt(10), big.NewInt(17), nil)}, {name: "1ether", amount: 1, want: new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)}, } for _, tt := range tests { diff --git a/internal/server/config.go b/internal/server/config.go index 514bcfd3..a7b4afed 100644 --- a/internal/server/config.go +++ b/internal/server/config.go @@ -5,13 +5,13 @@ type Config struct { symbol string httpPort int interval int - payout int + payout float64 proxyCount int hcaptchaSiteKey string hcaptchaSecret string } -func NewConfig(network, symbol string, httpPort, interval, payout, proxyCount int, hcaptchaSiteKey, hcaptchaSecret string) *Config { +func NewConfig(network, symbol string, httpPort, interval, proxyCount int, payout float64, hcaptchaSiteKey, hcaptchaSecret string) *Config { return &Config{ network: network, symbol: symbol, diff --git a/internal/server/server.go b/internal/server/server.go index 656f63cd..406fbcf0 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -55,7 +55,7 @@ func (s *Server) handleClaim() http.HandlerFunc { address, _ := readAddress(r) ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) defer cancel() - txHash, err := s.Transfer(ctx, address, chain.EtherToWei(int64(s.cfg.payout))) + txHash, err := s.Transfer(ctx, address, chain.EtherToWei(s.cfg.payout)) if err != nil { log.WithError(err).Error("Failed to send transaction") renderJSON(w, claimResponse{Message: err.Error()}, http.StatusInternalServerError) @@ -81,7 +81,7 @@ func (s *Server) handleInfo() http.HandlerFunc { Account: s.Sender().String(), Network: s.cfg.network, Symbol: s.cfg.symbol, - Payout: strconv.Itoa(s.cfg.payout), + Payout: strconv.FormatFloat(s.cfg.payout, 'f', -1, 64), HcaptchaSiteKey: s.cfg.hcaptchaSiteKey, }, http.StatusOK) }