Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
########################################################################

APP_SERVICE_RPC_URL="http://evmtestnet.confluxrpc.com"
# APP_SERVICE_RPC_REQUESTTIMEOUT=3s
APP_SERVICE_RPC_PRIVATEKEY="your_private_key_here"
APP_SERVICE_RPC_LOGENABLED=false

# APP_SERVICE_RPC_REQUESTTIMEOUT=3s
# APP_SERVICE_RPC_LOGENABLED=false

# Config delegated contract address to enable the AccountAbstract service, otherwise it will be disabled.
# APP_SERVICE_ACCOUNTABSTRACT_DELEGATEDCONTRACT="your_contract_hex40_address_here"


APP_SERVICE_GASTANK_ADDRESS="paymaster_contract_hex40_address_here"
# Config gas tank paymaster contract address to enable the GasTank service, otherwise it will be disabled.
# APP_SERVICE_GASTANK_ADDRESS="paymaster_contract_hex40_address_here"
# APP_SERVICE_GASTANK_SIGNATURETIMEOUT="5m"


Expand Down
27 changes: 15 additions & 12 deletions api/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ type Config struct {
func MustServe(config Config, services service.Services) {
api.MustServe(config.Config, func(router *gin.Engine) {
// set default rate limit config if not configured
config.RateLimit.Add(middleware.RateLimitTierFree, "overall", 10, 20)
config.RateLimit.Add(middleware.RateLimitTierFree, "overall", 5, 20)
// EIP-7702 tx
config.RateLimit.Add(middleware.RateLimitTierFree, "setAuth", 1, 5)
Comment thread
boqiu marked this conversation as resolved.
// gas tank
config.RateLimit.Add(middleware.RateLimitTierFree, "signUserOp", 1, 5)
// token pay
config.RateLimit.Add(middleware.RateLimitTierFree, "getPrice", 5, 10)
config.RateLimit.Add(middleware.RateLimitTierFree, "getPrice", 1, 5)
config.RateLimit.Add(middleware.RateLimitTierFree, "sponsor", 1, 5)
Comment thread
boqiu marked this conversation as resolved.

// rate limit by client real IP address
rateLimiters := middleware.NewRateLimitManager(config.RateLimit, middleware.DefaultRateLimitKeyExtractor)
rateLimiters := middleware.NewRateLimitManager(config.RateLimit)
go rateLimiters.ScheduleExpire()
router.Use(rateLimiters.Middleware("overall"))

Expand All @@ -48,23 +48,26 @@ func MustServe(config Config, services service.Services) {

api := router.Group("api")

aaController := NewAccountAbstractController(services)
gasTankController := NewGasTankController(services)
tokenPayController := NewTokenPayController(services)

// test client IP address
api.GET("/ip", middleware.Wrap(testClientIP))

// account abstract - auth
api.POST("/aa/auth", rateLimiters.Middleware("setAuth"), middleware.Metrics("api.aa.auth.send"), middleware.Wrap(aaController.SendAuth))
api.GET("/aa/auth/:txHash", middleware.Metrics("api.aa.auth.status"), middleware.Wrap(aaController.GetAuthStatus))
if services.AccountAbstract != nil {
aaController := NewAccountAbstractController(services)
api.POST("/aa/auth", rateLimiters.Middleware("setAuth"), middleware.Metrics("api.aa.auth.send"), middleware.Wrap(aaController.SendAuth))
api.GET("/aa/auth/:txHash", middleware.Metrics("api.aa.auth.status"), middleware.Wrap(aaController.GetAuthStatus))
}

// Gas tank
api.POST("/aa/gastank/prepare/credit", middleware.Metrics("api.aa.gastank.prepare.credit"), middleware.Wrap(gasTankController.PrepareCredit))
api.POST("/aa/gastank/prepare/refund", middleware.Metrics("api.aa.gastank.prepare.refund"), middleware.Wrap(gasTankController.PrepareRefund))
api.POST("/aa/gastank/sign", rateLimiters.Middleware("signUserOp"), middleware.Metrics("api.aa.gastank.signature"), middleware.Wrap(gasTankController.Sign))
if services.GasTank != nil {
gasTankController := NewGasTankController(services)
api.POST("/aa/gastank/prepare/credit", middleware.Metrics("api.aa.gastank.prepare.credit"), middleware.Wrap(gasTankController.PrepareCredit))
api.POST("/aa/gastank/prepare/refund", middleware.Metrics("api.aa.gastank.prepare.refund"), middleware.Wrap(gasTankController.PrepareRefund))
api.POST("/aa/gastank/sign", rateLimiters.Middleware("signUserOp"), middleware.Metrics("api.aa.gastank.signature"), middleware.Wrap(gasTankController.Sign))
}

// token pay
tokenPayController := NewTokenPayController(services)
api.GET("/tokenpay/config", middleware.Metrics("api.tokenpay.config"), middleware.Wrap(tokenPayController.Config))
api.GET("/tokenpay/price", rateLimiters.Middleware("getPrice"), middleware.Metrics("api.tokenpay.price"), middleware.Wrap(tokenPayController.GetETHPrice))
api.POST("/tokenpay/submit", rateLimiters.Middleware("sponsor"), middleware.Metrics("api.tokenpay.submit"), middleware.Wrap(tokenPayController.Submit))
Expand Down
33 changes: 18 additions & 15 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
type Config struct {
RPC struct {
URL string
RequestTimeout time.Duration `default:"3s"`
PrivateKey string
RequestTimeout time.Duration `default:"3s"`
LogEnabled bool
}

Expand All @@ -28,9 +28,9 @@ type Config struct {
}

type Services struct {
AccountAbstract *AccountAbstract
AccountAbstract *AccountAbstract // may be nil if the delegated contract address is not specified
PriceOracle *PriceOracle
GasTank *GasTankPaymaster
GasTank *GasTankPaymaster // may be nil if the gas tank paymaster is not specified
TokenPay *TokenPay
}

Expand Down Expand Up @@ -66,21 +66,24 @@ func New(config Config) (Services, error) {
return Services{}, errors.WithMessage(err, "Failed to create transaction sender")
}

aa := NewAccountAbstract(txSender, config.AccountAbstract.DelegatedContract)

priceOracle := NewPriceOracle(config.TokenPay.normalizedTokens)

gasTank, err := NewGasTankPaymaster(config.GasTank, priceOracle, client)
if err != nil {
return Services{}, errors.WithMessage(err, "Failed to create gas tank paymaster service")
services := Services{
PriceOracle: priceOracle,
TokenPay: NewTokenPay(config.TokenPay, txSender, priceOracle),
}

tokenPay := NewTokenPay(config.TokenPay, txSender, priceOracle)
// AccountAbstract service is optional, only create it if the delegated contract address is specified
if config.AccountAbstract.DelegatedContract != (common.Address{}) {
services.AccountAbstract = NewAccountAbstract(txSender, config.AccountAbstract.DelegatedContract)
}
Comment thread
boqiu marked this conversation as resolved.

// GasTankPaymaster service is optional, only create it if the gas tank paymaster address is specified
if config.GasTank.Address != (common.Address{}) {
if services.GasTank, err = NewGasTankPaymaster(config.GasTank, priceOracle, client); err != nil {
return Services{}, errors.WithMessage(err, "Failed to create gas tank paymaster service")
}
}

return Services{
AccountAbstract: aa,
PriceOracle: priceOracle,
GasTank: gasTank,
TokenPay: tokenPay,
}, nil
return services, nil
}
Loading