From e3d81cfb5429765cb051f50a8e6d53c69b8b1b90 Mon Sep 17 00:00:00 2001 From: Milos Zivkovic Date: Sat, 16 Sep 2023 16:23:25 +0200 Subject: [PATCH] Tidy repo --- .github/CODEOWNERS | 4 ++ .github/dependabot.yml | 24 +++++++ .github/golangci.yaml | 124 ++++++++++++++++++++++++++++++++++ .github/workflows/lint.yaml | 18 +++++ .github/workflows/main.yaml | 14 ++++ .github/workflows/test.yaml | 32 +++++++++ .gitignore | 9 +++ Makefile | 13 ++++ cmd/faucet/main.go | 2 +- cmd/root/root.go | 14 ++-- config/config.go | 25 +++---- faucet.go | 3 +- go.mod | 2 +- go.sum | 14 ---- handler.go | 4 +- handler_test.go | 42 ++++++------ keyring/memory/memory.go | 8 +-- keyring/memory/memory_test.go | 4 +- mock_test.go | 2 +- prepare.go | 2 +- transfer.go | 12 ++-- types.go | 14 ++-- 22 files changed, 307 insertions(+), 79 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yml create mode 100644 .github/golangci.yaml create mode 100644 .github/workflows/lint.yaml create mode 100644 .github/workflows/main.yaml create mode 100644 .github/workflows/test.yaml create mode 100644 .gitignore create mode 100644 Makefile diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..b1d5a8e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# CODEOWNERS: https://help.github.com/articles/about-codeowners/ + +# Primary repo maintainers. +* @gnolang/tech-staff \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0c12aed --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,24 @@ +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + labels: + - "github_actions" + + # Maintain dependencies for top level Go modules + - package-ecosystem: gomod + directory: / + target-branch: "main" + schedule: + interval: weekly + labels: + - "dependencies" + open-pull-requests-limit: 10 + pull-request-branch-name: + separator: "-" + reviewers: + - "zivkovicmilos" \ No newline at end of file diff --git a/.github/golangci.yaml b/.github/golangci.yaml new file mode 100644 index 0000000..9fb9829 --- /dev/null +++ b/.github/golangci.yaml @@ -0,0 +1,124 @@ +run: + concurrency: 8 + timeout: 10m + issue-exit-code: 1 + tests: true + skip-dirs-use-default: true + modules-download-mode: readonly + allow-parallel-runners: false + go: "" + +output: + uniq-by-line: false + path-prefix: "" + sort-results: true + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + new: false + fix: false + exclude-rules: + - path: (.+)_test.go + linters: + - nilnil + - gosec + +linters: + fast: false + disable-all: true + enable: + - asasalint # Check for pass []any as any in variadic func(...any) + - asciicheck # Detects funky ASCII characters + - bidichk # Checks for dangerous unicode character sequences + - durationcheck # Check for two durations multiplied together + - errcheck # Forces to not skip error check + - exportloopref # Checks for pointers to enclosing loop variables + - gocritic # Bundles different linting checks + - godot # Checks for periods at the end of comments + - gomoddirectives # Allow or ban replace directives in go.mod + - gosimple # Code simplification + - govet # Official Go tool + - ineffassign # Detects when assignments to existing variables are not used + - nakedret # Finds naked/bare returns and requires change them + - nilerr # Requires explicit returns + - nilnil # Requires explicit returns + - promlinter # Lints Prometheus metrics names + - reassign # Checks that package variables are not reassigned + - revive # Drop-in replacement for golint + - tagliatelle # Checks struct tags + - tenv # Detects using os.Setenv instead of t.Setenv + - testableexamples # Checks if examples are testable (have expected output) + - unparam # Finds unused params + - usestdlibvars # Detects the possibility to use variables/constants from stdlib + - wastedassign # Finds wasted assignment statements + - loggercheck # Checks the odd number of key and value pairs for common logger libraries + - nestif # Finds deeply nested if statements + - nonamedreturns # Reports all named returns + - decorder # Check declaration order of types, consts, vars and funcs + - gocheckcompilerdirectives # Checks that compiler directive comments (//go:) are valid + - gochecknoinits # Checks for init methods + - whitespace # Tool for detection of leading and trailing whitespace + - wsl # Forces you to use empty lines + - unconvert # Unnecessary type conversions + - tparallel # Detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # Detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - stylecheck # Stylecheck is a replacement for golint + - prealloc # Finds slice declarations that could potentially be pre-allocated + - predeclared # Finds code that shadows one of Go's predeclared identifiers + - nolintlint # Ill-formed or insufficient nolint directives + - nlreturn # Checks for a new line before return and branch statements to increase code clarity + - misspell # Misspelled English words in comments + - makezero # Finds slice declarations with non-zero initial length + - lll # Long lines + - importas # Enforces consistent import aliases + - gosec # Security problems + - gofmt # Whether the code was gofmt-ed + - gofumpt # Stricter gofmt + - goimports # Unused imports + - goconst # Repeated strings that could be replaced by a constant + - dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f()) + - dupl # Code clone detection + - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13 + - unused # Checks Go code for unused constants, variables, functions and types + +linters-settings: + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - hugeParam + - rangeExprCopy + - rangeValCopy + - importShadow + - unnamedResult + errcheck: + check-type-assertions: false + check-blank: true + exclude-functions: + - io/ioutil.ReadFile + - io.Copy(*bytes.Buffer) + - io.Copy(os.Stdout) + nakedret: + max-func-lines: 1 + govet: + enable-all: true + gofmt: + simplify: true + goconst: + min-len: 3 + min-occurrences: 3 + godot: + scope: all + period: false + tagliatelle: + case: + use-field-name: true + rules: + json: goCamel + yaml: goCamel diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..8859a32 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,18 @@ +on: + workflow_call: + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 1.20.x + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Lint + uses: golangci/golangci-lint-action@v3 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..b11bba2 --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,14 @@ +on: + push: + branches: + - main + pull_request: + +jobs: + lint: + name: Go Linter + uses: ./.github/workflows/lint.yaml + + test: + name: Go Test + uses: ./.github/workflows/test.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..dea960b --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,32 @@ +on: + workflow_call: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 1.20.x + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Go test + run: go test -shuffle=on -coverprofile coverage.out -timeout 5m ./... + + test-with-race: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 1.20.x + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Go race test + run: go test -race -shuffle=on -timeout 5m ./... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c785ec8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# MacOS Leftovers +.DS_Store + +# Editor Leftovers +.vscode +.idea + +# Log files +*.log \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a79a092 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +.PHONY: lint +lint: + golangci-lint run --config .github/golangci.yaml + +.PHONY: gofumpt +gofumpt: + go install mvdan.cc/gofumpt@latest + gofumpt -l -w . + +.PHONY: fixalign +fixalign: + go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest + fieldalignment -fix $(filter-out $@,$(MAKECMDGOALS)) # the full package name (not path!) diff --git a/cmd/faucet/main.go b/cmd/faucet/main.go index 74d2ee2..0050e8b 100644 --- a/cmd/faucet/main.go +++ b/cmd/faucet/main.go @@ -1,4 +1,4 @@ -package faucet +package main import ( "context" diff --git a/cmd/root/root.go b/cmd/root/root.go index 0de1aec..48ac20b 100644 --- a/cmd/root/root.go +++ b/cmd/root/root.go @@ -26,17 +26,15 @@ const ( envPrefix = "GNO_FAUCET" ) -var ( - remoteRegex = regexp.MustCompile(`^https?:\/\/(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)(?![^<]*(?:<\/\w+>|\/?>))$`) -) +var remoteRegex = regexp.MustCompile(`^https?:\/\/(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)(?![^<]*(?:<\/\w+>|\/?>))$`) // faucetCfg wraps the faucet // root command configuration type faucetCfg struct { - config.Config - corsConfigPath string remote string + + config.Config } // New creates the root faucet command @@ -167,7 +165,7 @@ func (c *faucetCfg) exec(context.Context, []string) error { // Validate the remote URL // validate the remote address - if !remoteRegex.Match([]byte(c.remote)) { + if !remoteRegex.MatchString(c.remote) { return errors.New("invalid remote address") } @@ -202,8 +200,8 @@ func readCORSConfig(path string) (*config.CORS, error) { // Parse it var corsConfig config.CORS - err = toml.Unmarshal(content, &corsConfig) - if err != nil { + + if err := toml.Unmarshal(content, &corsConfig); err != nil { return nil, err } diff --git a/config/config.go b/config/config.go index c947289..e3316fd 100644 --- a/config/config.go +++ b/config/config.go @@ -14,8 +14,9 @@ const ( DefaultSendAmount = "1000000ugnot" DefaultGasFee = "1000000ugnot" DefaultGasWanted = "100000" - DefaultMnemonic = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" - DefaultNumAccounts = uint64(1) + //nolint:lll // Mnemonic is naturally long + DefaultMnemonic = "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" + DefaultNumAccounts = uint64(1) ) var ( @@ -36,6 +37,9 @@ var ( // Config defines the base-level Faucet configuration type Config struct { + // The associated CORS config, if any + CORSConfig *CORS `toml:"cors_config"` + // The address at which the faucet will be served. // Format should be: : ListenAddress string `toml:"listen_address"` @@ -46,10 +50,6 @@ type Config struct { // The mnemonic for the faucet Mnemonic string `toml:"mnemonic"` - // The number of faucet accounts, - // based on the mnemonic (account 0, index x) - NumAccounts uint64 `toml:"num_accounts"` - // The static send amount (native currency). // Format should be: ugnot SendAmount string `toml:"send_amount"` @@ -62,8 +62,9 @@ type Config struct { // Format should be: GasWanted string `toml:"gas_wanted"` - // The associated CORS config, if any - CORSConfig *CORS `toml:"cors_config"` + // The number of faucet accounts, + // based on the mnemonic (account 0, index x) + NumAccounts uint64 `toml:"num_accounts"` } // DefaultConfig returns the default faucet configuration @@ -83,7 +84,7 @@ func DefaultConfig() *Config { // ValidateConfig validates the faucet configuration func ValidateConfig(config *Config) error { // validate the listen address - if !listenAddressRegex.Match([]byte(config.ListenAddress)) { + if !listenAddressRegex.MatchString(config.ListenAddress) { return ErrInvalidListenAddress } @@ -93,17 +94,17 @@ func ValidateConfig(config *Config) error { } // validate the send amount - if !amountRegex.Match([]byte(config.SendAmount)) { + if !amountRegex.MatchString(config.SendAmount) { return ErrInvalidSendAmount } // validate the gas fee - if !amountRegex.Match([]byte(config.GasFee)) { + if !amountRegex.MatchString(config.GasFee) { return ErrInvalidGasFee } // validate the gas wanted - if !numberRegex.Match([]byte(config.GasWanted)) { + if !numberRegex.MatchString(config.GasWanted) { return ErrInvalidGasWanted } diff --git a/faucet.go b/faucet.go index 3c9d81c..7950d10 100644 --- a/faucet.go +++ b/faucet.go @@ -55,8 +55,8 @@ func NewFaucet( // Set the single default HTTP handler f.handlers = []Handler{ { - "/", f.defaultHTTPHandler, + "/", }, } @@ -71,6 +71,7 @@ func NewFaucet( } // Set the send amount + //nolint:errcheck // SendAmount is validated beforehand f.sendAmount, _ = std.ParseCoins(f.config.SendAmount) // Generate the in-memory keyring diff --git a/go.mod b/go.mod index 0de249e..883322b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/gnolang/faucet -go 1.21 +go 1.20 require ( github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2 diff --git a/go.sum b/go.sum index 761cc44..965f552 100644 --- a/go.sum +++ b/go.sum @@ -12,7 +12,6 @@ github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9Ur github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= @@ -40,13 +39,9 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2 h1:/j3GhCiNnE04Yc+zF+ouY7sZuopGwYx6R9NPipSVVLE= @@ -79,14 +74,12 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= -github.com/jaekwon/testify v1.6.1/go.mod h1:Oun0RXIHI7osufabQ60i4Lqkj0GXLbqI1I7kgzBNm1U= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= @@ -101,7 +94,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= @@ -110,14 +102,11 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -202,7 +191,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -228,14 +216,12 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/handler.go b/handler.go index 6bf27b7..101339f 100644 --- a/handler.go +++ b/handler.go @@ -17,9 +17,7 @@ const ( faucetSuccess = "successfully executed faucet transfer" ) -var ( - errInvalidBeneficiary = errors.New("invalid beneficiary address") -) +var errInvalidBeneficiary = errors.New("invalid beneficiary address") // defaultHTTPHandler is the default faucet transfer handler func (f *Faucet) defaultHTTPHandler(w http.ResponseWriter, r *http.Request) { diff --git a/handler_test.go b/handler_test.go index b924b12..0ee42f2 100644 --- a/handler_test.go +++ b/handler_test.go @@ -24,6 +24,7 @@ import ( "golang.org/x/sync/errgroup" ) +// decodeResponse decodes the JSON response func decodeResponse[T Response | Responses](t *testing.T, responseBody []byte) *T { t.Helper() @@ -52,15 +53,16 @@ func getFreePort(t *testing.T) int { return l.Addr().(*net.TCPAddr).Port } -func waitForServer(t *testing.T, URL string, timeout time.Duration) { +// waitForServer waits for the web server to start up +func waitForServer(t *testing.T, url string) { t.Helper() ch := make(chan bool) + go func() { for { - if _, err := http.Get(URL); err == nil { + if _, err := http.Get(url); err == nil { ch <- true - } time.Sleep(10 * time.Millisecond) @@ -70,7 +72,7 @@ func waitForServer(t *testing.T, URL string, timeout time.Duration) { select { case <-ch: return - case <-time.After(timeout): + case <-time.After(5 * time.Second): t.Fatalf("server wait timeout exceeded") } } @@ -111,25 +113,23 @@ func TestFaucet_Serve_ValidRequests(t *testing.T) { } testTable := []struct { - name string - expectedNumTxs int requestValidateFn func(response []byte) + name string request []byte + expectedNumTxs int }{ { - "single request", - 1, func(resp []byte) { response := decodeResponse[Response](t, resp) assert.Empty(t, response.Error) assert.Equal(t, faucetSuccess, response.Result) }, + "single request", encodedSingleValidRequest, + 1, }, { - "bulk request", - len(bulkValidRequests), func(resp []byte) { responses := decodeResponse[Responses](t, resp) require.Len(t, *responses, len(bulkValidRequests)) @@ -139,7 +139,9 @@ func TestFaucet_Serve_ValidRequests(t *testing.T) { assert.Equal(t, faucetSuccess, response.Result) } }, + "bulk request", encodedBulkValidRequests, + len(bulkValidRequests), }, } @@ -249,7 +251,7 @@ func TestFaucet_Serve_ValidRequests(t *testing.T) { url := getFaucetURL(f.config.ListenAddress) // Wait for the faucet to be started - waitForServer(t, url, time.Second*5) + waitForServer(t, url) // Execute the request respRaw, err := http.Post( @@ -326,25 +328,23 @@ func TestFaucet_Serve_InvalidRequests(t *testing.T) { } testTable := []struct { - name string - expectedNumTxs int requestValidateFn func(response []byte) + name string request []byte + expectedNumTxs int }{ { - "single request", - 1, func(resp []byte) { response := decodeResponse[Response](t, resp) assert.Contains(t, response.Error, errInvalidBeneficiary.Error()) assert.Equal(t, response.Result, unableToHandleRequest) }, + "single request", encodedSingleInvalidRequest, + 1, }, { - "bulk request", - len(bulkInvalidRequests), func(resp []byte) { responses := decodeResponse[Responses](t, resp) require.Len(t, *responses, len(bulkInvalidRequests)) @@ -354,7 +354,9 @@ func TestFaucet_Serve_InvalidRequests(t *testing.T) { assert.Equal(t, response.Result, unableToHandleRequest) } }, + "bulk request", encodedBulkInvalidRequests, + len(bulkInvalidRequests), }, } @@ -464,7 +466,7 @@ func TestFaucet_Serve_InvalidRequests(t *testing.T) { url := getFaucetURL(f.config.ListenAddress) // Wait for the faucet to be started - waitForServer(t, url, time.Second*5) + waitForServer(t, url) // Execute the request respRaw, err := http.Post( @@ -542,7 +544,7 @@ func TestFaucet_Serve_MalformedRequests(t *testing.T) { url := getFaucetURL(f.config.ListenAddress) // Wait for the faucet to be started - waitForServer(t, url, time.Second*5) + waitForServer(t, url) // Execute the request respRaw, err := http.Post( @@ -686,7 +688,7 @@ func TestFaucet_Serve_NoFundedAccounts(t *testing.T) { url := getFaucetURL(f.config.ListenAddress) // Wait for the faucet to be started - waitForServer(t, url, time.Second*5) + waitForServer(t, url) // Execute the request respRaw, err := http.Post( diff --git a/keyring/memory/memory.go b/keyring/memory/memory.go index 6b675f9..9374c38 100644 --- a/keyring/memory/memory.go +++ b/keyring/memory/memory.go @@ -9,8 +9,8 @@ import ( // Keyring is an in-memory keyring type Keyring struct { - addresses []crypto.Address keyMap map[crypto.Address]crypto.PrivKey + addresses []crypto.Address } // New initializes the keyring using the provided mnemonics @@ -21,8 +21,8 @@ func New(mnemonic string, numAccounts uint64) *Keyring { // Generate the seed seed := bip39.NewSeed(mnemonic, "") - for i := uint32(0); i < uint32(numAccounts); i++ { - key := generateKeyFromSeed(seed, i) + for i := uint64(0); i < numAccounts; i++ { + key := generateKeyFromSeed(seed, uint32(i)) address := key.PubKey().Address() addresses[i] = address @@ -52,7 +52,7 @@ func generateKeyFromSeed(seed []byte, index uint32) crypto.PrivKey { masterPriv, ch := hd.ComputeMastersFromSeed(seed) - // This derivation can never error out, since the path params + //nolint:errcheck // This derivation can never error out, since the path params // are always going to be valid derivedPriv, _ := hd.DerivePrivateKeyForPath(masterPriv, ch, pathParams.String()) diff --git a/keyring/memory/memory_test.go b/keyring/memory/memory_test.go index c7c5cf5..1b9aea3 100644 --- a/keyring/memory/memory_test.go +++ b/keyring/memory/memory_test.go @@ -9,6 +9,8 @@ import ( // generateTestMnemonic generates a new test BIP39 mnemonic using the provided entropy size func generateTestMnemonic(t *testing.T) string { + t.Helper() + // Generate the entropy seed entropySeed, err := bip39.NewEntropy(256) if err != nil { @@ -16,7 +18,7 @@ func generateTestMnemonic(t *testing.T) string { } // Generate the actual mnemonic - mnemonic, err := bip39.NewMnemonic(entropySeed[:]) + mnemonic, err := bip39.NewMnemonic(entropySeed) if err != nil { t.Fatal(err) } diff --git a/mock_test.go b/mock_test.go index b579465..db3dcc2 100644 --- a/mock_test.go +++ b/mock_test.go @@ -83,7 +83,7 @@ func (m *mockPubKey) Bytes() []byte { return nil } -func (m *mockPubKey) VerifyBytes(msg []byte, sig []byte) bool { +func (m *mockPubKey) VerifyBytes(msg, sig []byte) bool { if m.verifyFn != nil { return m.verifyFn(msg, sig) } diff --git a/prepare.go b/prepare.go index 81c1ca2..f314664 100644 --- a/prepare.go +++ b/prepare.go @@ -9,9 +9,9 @@ import ( // prepareCfg specifies the tx prepare configuration type prepareCfg struct { + sendAmount std.Coins // the amount to be sent fromAddress crypto.Address // the faucet address toAddress crypto.Address // the beneficiary address - sendAmount std.Coins // the amount to be sent } // prepareTransaction prepares the transaction for signing diff --git a/transfer.go b/transfer.go index 0a6ba10..94c4f46 100644 --- a/transfer.go +++ b/transfer.go @@ -7,9 +7,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -var ( - errNoFundedAccount = errors.New("no funded account found") -) +var errNoFundedAccount = errors.New("no funded account found") // transferFunds transfers funds to the given address func (f *Faucet) transferFunds(address crypto.Address) error { @@ -20,15 +18,15 @@ func (f *Faucet) transferFunds(address crypto.Address) error { } // Prepare the transaction - prepareCfg := prepareCfg{ + pCfg := prepareCfg{ fromAddress: fundAccount.GetAddress(), toAddress: address, sendAmount: f.sendAmount, } - tx := prepareTransaction(f.estimator, prepareCfg) + tx := prepareTransaction(f.estimator, pCfg) // Sign the transaction - signCfg := signCfg{ + sCfg := signCfg{ chainID: f.config.ChainID, accountNumber: fundAccount.GetAccountNumber(), sequence: fundAccount.GetSequence(), @@ -37,7 +35,7 @@ func (f *Faucet) transferFunds(address crypto.Address) error { if err := signTransaction( tx, f.keyring.GetKey(fundAccount.GetAddress()), - signCfg, + sCfg, ); err != nil { return err } diff --git a/types.go b/types.go index e405483..8967282 100644 --- a/types.go +++ b/types.go @@ -2,26 +2,30 @@ package faucet import "net/http" +const ( + jsonMimeType = "application/json" +) + +// Middleware is the faucet middleware func type Middleware func(next http.Handler) http.Handler +// Handler defines a faucet handler type Handler struct { - Pattern string HandlerFunc http.HandlerFunc + Pattern string } type Requests []Request +// Request is a single Faucet transfer request type Request struct { To string `json:"to"` } type Responses []Response +// Response is a single Faucet transfer response type Response struct { Result string `json:"result"` Error string `json:"error,omitempty"` } - -const ( - jsonMimeType = "application/json" -)