Skip to content

Commit

Permalink
update: fix typos, refactor folders structure
Browse files Browse the repository at this point in the history
  • Loading branch information
mhrynenko committed May 31, 2024
1 parent ebd6741 commit 59f5e40
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 191 deletions.
4 changes: 2 additions & 2 deletions internal/config/airdrop.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
const airdropYamlKey = "airdrop"

type AirdropConfiger interface {
AridropConfig() AirdropConfig
AirdropConfig() AirdropConfig
}

type AirdropConfig struct {
Expand All @@ -33,7 +33,7 @@ func NewAirdropConfiger(getter kv.Getter) AirdropConfiger {
}
}

func (v *airdrop) AridropConfig() AirdropConfig {
func (v *airdrop) AirdropConfig() AirdropConfig {
return v.once.Do(func() interface{} {
var result AirdropConfig

Expand Down
58 changes: 38 additions & 20 deletions internal/config/broadcaster.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ import (
const broadcasterYamlKey = "broadcaster"

type Broadcaster struct {
RPC *ethclient.Client
ChainID *big.Int
PrivateKey *ecdsa.PrivateKey
Address common.Address
QueryLimit uint64

nonce uint64
mut *sync.Mutex
RPC *ethclient.Client
ChainID *big.Int
PrivateKey *ecdsa.PrivateKey
Address common.Address
QueryLimit uint64
ERC20PermitTransfer common.Address

gasMultiplier float64
nonce uint64
mut *sync.Mutex
}

type Broadcasterer interface {
Expand All @@ -47,10 +49,12 @@ func NewBroadcaster(getter kv.Getter) Broadcasterer {
func (b *broadcasterer) Broadcaster() Broadcaster {
return b.once.Do(func() interface{} {
var cfg struct {
RPC *ethclient.Client `fig:"rpc,required"`
ChainID *big.Int `fig:"chain_id,required"`
QueryLimit uint64 `fig:"query_limit"`
SenderPrivateKey *ecdsa.PrivateKey `fig:"sender_private_key"`
RPC *ethclient.Client `fig:"rpc,required"`
ChainID *big.Int `fig:"chain_id,required"`
QueryLimit uint64 `fig:"query_limit"`
SenderPrivateKey *ecdsa.PrivateKey `fig:"sender_private_key"`
ERC20PermitTransfer common.Address `fig:"erc20_permit_transfer,required"`
GasMultiplier float64 `fig:"gas_multiplier"`
}

err := figure.
Expand All @@ -71,21 +75,28 @@ func (b *broadcasterer) Broadcaster() Broadcaster {
queryLimit = cfg.QueryLimit
}

gasMultiplier := float64(1)
if cfg.GasMultiplier > 0 {
gasMultiplier = cfg.GasMultiplier
}

address := crypto.PubkeyToAddress(cfg.SenderPrivateKey.PublicKey)
nonce, err := cfg.RPC.NonceAt(context.Background(), address, nil)
if err != nil {
panic(fmt.Errorf("failed to get nonce %w", err))
}

return Broadcaster{
RPC: cfg.RPC,
PrivateKey: cfg.SenderPrivateKey,
Address: address,
ChainID: cfg.ChainID,
QueryLimit: queryLimit,

nonce: nonce,
mut: &sync.Mutex{},
RPC: cfg.RPC,
PrivateKey: cfg.SenderPrivateKey,
Address: address,
ChainID: cfg.ChainID,
QueryLimit: queryLimit,
ERC20PermitTransfer: cfg.ERC20PermitTransfer,

gasMultiplier: gasMultiplier,
nonce: nonce,
mut: &sync.Mutex{},
}
}).(Broadcaster)
}
Expand Down Expand Up @@ -128,3 +139,10 @@ func (n *Broadcaster) ResetNonce(client *ethclient.Client) error {
n.nonce = nonce
return nil
}

func (n *Broadcaster) MultiplyGasPrice(gasPrice *big.Int) *big.Int {
var ONE = 1000000000 // ONE - One GWEI
mult := big.NewFloat(0).Mul(big.NewFloat(n.gasMultiplier), big.NewFloat(float64(ONE)))
gas, _ := big.NewFloat(0).Mul(big.NewFloat(0).SetInt(gasPrice), mult).Int(nil)
return big.NewInt(0).Div(gas, big.NewInt(int64(ONE)))
}
116 changes: 116 additions & 0 deletions internal/service/api/ctx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package api

import (
"context"
"net/http"

"github.com/rarimo/evm-airdrop-svc/contracts"
"github.com/rarimo/evm-airdrop-svc/internal/config"
"github.com/rarimo/evm-airdrop-svc/internal/data"
zk "github.com/rarimo/zkverifier-kit"
"gitlab.com/distributed_lab/logan/v3"
)

type ctxKey int

const (
logCtxKey ctxKey = iota
airdropsQCtxKey
airdropConfigCtxKey
verifierCtxKey
airdropParamsCtxKey
broadcasterCtxKey
erc20PermitCtxKey
erc20PermitTransferCtxKey
priceApiConfigCtxKey
)

func CtxLog(entry *logan.Entry) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, logCtxKey, entry)
}
}

func Log(r *http.Request) *logan.Entry {
return r.Context().Value(logCtxKey).(*logan.Entry)
}

func CtxAirdropsQ(q *data.AirdropsQ) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, airdropsQCtxKey, q)
}
}

func AirdropsQ(r *http.Request) *data.AirdropsQ {
return r.Context().Value(airdropsQCtxKey).(*data.AirdropsQ).New()
}

func CtxAirdropConfig(entry config.AirdropConfig) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, airdropConfigCtxKey, entry)
}
}

func AirdropConfig(r *http.Request) config.AirdropConfig {
return r.Context().Value(airdropConfigCtxKey).(config.AirdropConfig)
}

func CtxAirdropParams(params config.GlobalParams) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, airdropParamsCtxKey, params)
}
}

func AirdropParams(r *http.Request) config.GlobalParams {
return r.Context().Value(airdropParamsCtxKey).(config.GlobalParams)
}

func CtxVerifier(entry *zk.Verifier) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, verifierCtxKey, entry)
}
}

func Verifier(r *http.Request) *zk.Verifier {
return r.Context().Value(verifierCtxKey).(*zk.Verifier)
}

func Broadcaster(r *http.Request) config.Broadcaster {
return r.Context().Value(broadcasterCtxKey).(config.Broadcaster)
}

func CtxBroadcaster(entry config.Broadcaster) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, broadcasterCtxKey, entry)
}
}

func CtxERC20Permit(entry *contracts.ERC20Permit) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, erc20PermitCtxKey, entry)
}
}

func ERC20Permit(r *http.Request) *contracts.ERC20Permit {
return r.Context().Value(erc20PermitCtxKey).(*contracts.ERC20Permit)
}

func CtxERC20PermitTransfer(entry *contracts.ERC20TransferWithPermit) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, erc20PermitTransferCtxKey, entry)
}
}

func ERC20PermitTransfer(r *http.Request) *contracts.ERC20TransferWithPermit {
return r.Context().Value(erc20PermitTransferCtxKey).(*contracts.ERC20TransferWithPermit)
}

func CtxPriceApiConfig(entry config.PriceApiConfig) func(context.Context) context.Context {
return func(ctx context.Context) context.Context {
return context.WithValue(ctx, priceApiConfigCtxKey, entry)
}
}

func PriceApiConfig(r *http.Request) config.PriceApiConfig {
return r.Context().Value(priceApiConfigCtxKey).(config.PriceApiConfig)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"net/http"

"github.com/rarimo/evm-airdrop-svc/internal/data"
"github.com/rarimo/evm-airdrop-svc/internal/service/requests"
"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"
zk "github.com/rarimo/zkverifier-kit"
"github.com/rarimo/zkverifier-kit/identity"
"gitlab.com/distributed_lab/ape"
Expand All @@ -24,12 +26,12 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) {

nullifier := req.Data.Attributes.ZkProof.PubSignals[zk.Nullifier]

airdrop, err := AirdropsQ(r).
airdrop, err := api.AirdropsQ(r).
FilterByNullifier(nullifier).
FilterByStatuses(data.TxStatusCompleted, data.TxStatusPending, data.TxStatusInProgress).
Get()
if err != nil {
Log(r).WithError(err).Error("Failed to get airdrop by nullifier")
api.Log(r).WithError(err).Error("Failed to get airdrop by nullifier")
ape.RenderErr(w, problems.InternalError())
return
}
Expand All @@ -38,31 +40,31 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) {
return
}

err = Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithEthereumAddress(req.Data.Attributes.Address))
err = api.Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithEthereumAddress(req.Data.Attributes.Address))
if err != nil {
if errors.Is(err, identity.ErrContractCall) {
Log(r).WithError(err).Error("Failed to verify proof")
api.Log(r).WithError(err).Error("Failed to verify proof")
ape.RenderErr(w, problems.InternalError())
return
}

Log(r).WithError(err).Info("Invalid proof")
api.Log(r).WithError(err).Info("Invalid proof")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}

airdrop, err = AirdropsQ(r).Insert(data.Airdrop{
airdrop, err = api.AirdropsQ(r).Insert(data.Airdrop{
Nullifier: nullifier,
Address: req.Data.Attributes.Address,
Amount: AirdropAmount(r),
Amount: api.AirdropConfig(r).Amount.String(),
Status: data.TxStatusPending,
})
if err != nil {
Log(r).WithError(err).Errorf("Failed to insert airdrop")
api.Log(r).WithError(err).Errorf("Failed to insert airdrop")
ape.RenderErr(w, problems.InternalError())
return
}

w.WriteHeader(http.StatusCreated)
ape.Render(w, toAirdropResponse(*airdrop))
ape.Render(w, models.NewAirdropResponse(*airdrop))
}
13 changes: 13 additions & 0 deletions internal/service/api/handlers/get_airdrop_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package handlers

import (
"net/http"

"github.com/rarimo/evm-airdrop-svc/internal/service/api"
"github.com/rarimo/evm-airdrop-svc/internal/service/api/models"
"gitlab.com/distributed_lab/ape"
)

func GetAirdropParams(w http.ResponseWriter, r *http.Request) {
ape.Render(w, models.NewAirdropParams(api.AirdropParams(r)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"

"github.com/rarimo/evm-airdrop-svc/internal/data"
"github.com/rarimo/evm-airdrop-svc/internal/service/api"
"gitlab.com/distributed_lab/kit/pgdb"
)

Expand All @@ -20,7 +21,7 @@ func DBCloneMiddleware(db *pgdb.DB) func(http.Handler) http.Handler {
ctx := r.Context()

extenders := []ctxExtender{
CtxAirdropsQ(data.NewAirdropsQ(clone)),
api.CtxAirdropsQ(data.NewAirdropsQ(clone)),
}

for _, extender := range extenders {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/rarimo/evm-airdrop-svc/resources"
)

var ethAddrRegExp = regexp.MustCompile("^0x[0-9a-fA-F]{40}$")

func NewCreateAirdrop(r *http.Request) (req resources.CreateAirdropRequest, err error) {
if err = json.NewDecoder(r.Body).Decode(&req); err != nil {
return req, newDecodeError("body", err)
Expand All @@ -21,7 +23,7 @@ func NewCreateAirdrop(r *http.Request) (req resources.CreateAirdropRequest, err
"data/attributes/address": val.Validate(
attr.Address,
val.Required,
val.Match(regexp.MustCompile("^0x[0-9a-fA-F]{40}$")),
val.Match(ethAddrRegExp),
),
}.Filter()
}
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func Run(ctx context.Context, cfg *config.Config) {
log: log,
q: data.NewAirdropsQ(cfg.DB().Clone()),
Broadcaster: cfg.Broadcaster(),
AirdropConfig: cfg.AridropConfig(),
AirdropConfig: cfg.AirdropConfig(),
}

running.WithBackOff(ctx, r.log, "builtin-broadcaster", r.run, 5*time.Second, 5*time.Second, 5*time.Second)
Expand Down
Loading

0 comments on commit 59f5e40

Please sign in to comment.