From e1abe37d0f5b929b5eaf70c041e27637800f146b Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Wed, 12 Jun 2024 22:07:53 +0300 Subject: [PATCH] add: get user balance endpoint --- internal/service/api/handlers/get_balance.go | 30 ++++++++++++++++++ internal/service/api/models/token.go | 21 +++++++++++++ internal/service/api/requests/get_balance.go | 32 ++++++++++++++++++++ internal/service/router.go | 4 +++ 4 files changed, 87 insertions(+) create mode 100644 internal/service/api/handlers/get_balance.go create mode 100644 internal/service/api/models/token.go create mode 100644 internal/service/api/requests/get_balance.go diff --git a/internal/service/api/handlers/get_balance.go b/internal/service/api/handlers/get_balance.go new file mode 100644 index 0000000..2135015 --- /dev/null +++ b/internal/service/api/handlers/get_balance.go @@ -0,0 +1,30 @@ +package handlers + +import ( + "net/http" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func GetBalance(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewGetBalanceRequest(r) + if err != nil { + api.Log(r).WithError(err).Error("failed to parse request") + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + balance, err := api.ERC20Permit(r).BalanceOf(&bind.CallOpts{}, req.Address) + if err != nil { + api.Log(r).WithError(err).Error("failed to get user balance") + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, models.NewBalanceResponse(req.Address.String(), balance)) +} diff --git a/internal/service/api/models/token.go b/internal/service/api/models/token.go new file mode 100644 index 0000000..d40a632 --- /dev/null +++ b/internal/service/api/models/token.go @@ -0,0 +1,21 @@ +package models + +import ( + "math/big" + + "github.com/rarimo/evm-airdrop-svc/resources" +) + +func NewBalanceResponse(addr string, amount *big.Int) resources.BalanceResponse { + return resources.BalanceResponse{ + Data: resources.Balance{ + Key: resources.Key{ + ID: addr, + Type: resources.TOKEN, + }, + Attributes: resources.BalanceAttributes{ + Amount: amount, + }, + }, + } +} diff --git a/internal/service/api/requests/get_balance.go b/internal/service/api/requests/get_balance.go new file mode 100644 index 0000000..5035e77 --- /dev/null +++ b/internal/service/api/requests/get_balance.go @@ -0,0 +1,32 @@ +package requests + +import ( + "net/http" + + "github.com/ethereum/go-ethereum/common" + validation "github.com/go-ozzo/ozzo-validation/v4" + "gitlab.com/distributed_lab/logan/v3/errors" + "gitlab.com/distributed_lab/urlval" +) + +type GetUserBalanceRequest struct { + Address common.Address `url:"address"` +} + +func NewGetBalanceRequest(r *http.Request) (GetUserBalanceRequest, error) { + var req GetUserBalanceRequest + + if err := urlval.Decode(r.URL.Query(), &req); err != nil { + return req, validation.Errors{ + "query": errors.Wrap(err, "failed to decode url"), + }.Filter() + } + + return req, req.validate() +} + +func (r *GetUserBalanceRequest) validate() error { + return validation.Errors{ + "/address": validation.Validate(r.Address, validation.Required), + }.Filter() +} diff --git a/internal/service/router.go b/internal/service/router.go index 5aab711..eec9519 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -55,6 +55,10 @@ func Run(ctx context.Context, cfg *config.Config) { r.Post("/permit-hash", handlers.BuildPermitHash) }) + + r.Route("/token", func(r chi.Router) { + r.Get("/balance", handlers.GetBalance) + }) }) cfg.Log().Info("Service started")