snapshot: 12-ebening

This commit is contained in:
Mohamed Sohail 2023-02-12 16:53:53 +03:00
parent 4f7909e4ee
commit f2ba079232
Signed by: kamikazechaser
GPG Key ID: 7DD45520C01CD85D
6 changed files with 58 additions and 60 deletions

View File

@ -1,9 +1,13 @@
package main package main
import ( import (
"errors"
"net/http"
"github.com/VictoriaMetrics/metrics" "github.com/VictoriaMetrics/metrics"
"github.com/go-playground/validator" "github.com/go-playground/validator"
"github.com/grassrootseconomics/cic-custodial/internal/api" "github.com/grassrootseconomics/cic-custodial/internal/api"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -14,6 +18,27 @@ func initApiServer(custodialContainer *custodial) *echo.Echo {
server.HideBanner = true server.HideBanner = true
server.HidePort = true server.HidePort = true
server.HTTPErrorHandler = func(err error, c echo.Context) {
// Handle asynq duplication errors across all api handlers.
if errors.Is(err, asynq.ErrTaskIDConflict) {
c.JSON(http.StatusForbidden, api.ErrResp{
Ok: false,
Code: api.DUPLICATE_ERROR,
Message: "Request with duplicate tracking id submitted.",
})
return
}
// Log internal server error for further investigation.
lo.Error("api:", "path", c.Path(), "err", err)
c.JSON(http.StatusInternalServerError, api.ErrResp{
Ok: false,
Code: api.INTERNAL_ERROR,
Message: "Internal server error.",
})
}
if ko.Bool("service.metrics") { if ko.Bool("service.metrics") {
server.GET("/metrics", func(c echo.Context) error { server.GET("/metrics", func(c echo.Context) error {
metrics.WritePrometheus(c.Response(), true) metrics.WritePrometheus(c.Response(), true)

View File

@ -9,8 +9,8 @@ metrics = true
[system] [system]
# The giftable token is a training voucher # The giftable token is a training voucher
# Every new user is given 5 DGFT # Every new user is given 5 DGFT
gas_faucet = "0x6dE38F79Cf455339e8141D15E208ba09eea634e1" gas_faucet = "0xA8b3Ffc715e85792FB361BDee9357B38D5A4a6cF"
giftable_token_address = "0x4091fc149522d5FE31d0970687078B1aE0625892" giftable_token_address = "0xdD4F5ea484F6b16f031eF7B98F3810365493BC20"
giftable_token_value = 5000000 giftable_token_value = 5000000
gas_refill_threshold = 100000000000000000 gas_refill_threshold = 100000000000000000
gas_refill_value = 100000000000000000 gas_refill_value = 100000000000000000
@ -18,12 +18,12 @@ gas_refill_value = 100000000000000000
giftable_gas_value = 2000000000000000000 giftable_gas_value = 2000000000000000000
# System private key # System private key
# Should always be toped up # Should always be toped up
private_key = "d87f322629cf071ccd3ddf17ab5e1abf098a25c4c5d791d7535d265379b2ae37" private_key = "bfa7222a7bea3bde312434abe819b14cf3bc8703ceaabb98a9e3a97ceb0b79fd"
lock_prefix = "lock:" lock_prefix = "lock:"
public_key = "0xe5ab7A5af1f28aA8E9658AC33a6ebF2a8641d948" public_key = "0x08eb3a90128D5874da54cf654fCfA88cEd1bb047"
token_decimals = 6 token_decimals = 6
token_transfer_gas_limit = 200000 token_transfer_gas_limit = 200000
account_index = "0x70138F458Fa56C034acb19E38d082843327F18A4" account_index = "0xdb2550ac5E52A54B6189FFAf17ECfF33AE190db9"
[chain] [chain]
rpc_endpoint = "http://192.168.0.101:8545" rpc_endpoint = "http://192.168.0.101:8545"

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/google/uuid"
"github.com/grassrootseconomics/cic-custodial/internal/keystore" "github.com/grassrootseconomics/cic-custodial/internal/keystore"
"github.com/grassrootseconomics/cic-custodial/internal/tasker" "github.com/grassrootseconomics/cic-custodial/internal/tasker"
"github.com/grassrootseconomics/cic-custodial/internal/tasker/task" "github.com/grassrootseconomics/cic-custodial/internal/tasker/task"
@ -13,76 +14,50 @@ import (
// CreateAccountHandler route. // CreateAccountHandler route.
// POST: /api/account/create // POST: /api/account/create
// JSON Body:
// trackingId -> Unique string
// Returns the public key. // Returns the public key.
func CreateAccountHandler( func CreateAccountHandler(
keystore keystore.Keystore, keystore keystore.Keystore,
taskerClient *tasker.TaskerClient, taskerClient *tasker.TaskerClient,
) func(echo.Context) error { ) func(echo.Context) error {
return func(c echo.Context) error { return func(c echo.Context) error {
var accountRequest struct { trackingId := uuid.NewString()
TrackingId string `json:"trackingId" validate:"required"`
}
if err := c.Bind(&accountRequest); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{
Ok: false,
Code: INTERNAL_ERROR,
})
}
if err := c.Validate(accountRequest); err != nil {
return err
}
generatedKeyPair, err := keypair.Generate() generatedKeyPair, err := keypair.Generate()
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
id, err := keystore.WriteKeyPair(c.Request().Context(), generatedKeyPair) id, err := keystore.WriteKeyPair(c.Request().Context(), generatedKeyPair)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
taskPayload, err := json.Marshal(task.AccountPayload{ taskPayload, err := json.Marshal(task.AccountPayload{
PublicKey: generatedKeyPair.Public, PublicKey: generatedKeyPair.Public,
TrackingId: accountRequest.TrackingId, TrackingId: trackingId,
}) })
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
_, err = taskerClient.CreateTask( _, err = taskerClient.CreateTask(
tasker.PrepareAccountTask, tasker.PrepareAccountTask,
tasker.DefaultPriority, tasker.DefaultPriority,
&tasker.Task{ &tasker.Task{
Id: accountRequest.TrackingId, Id: trackingId,
Payload: taskPayload, Payload: taskPayload,
}, },
) )
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
return c.JSON(http.StatusOK, okResp{ return c.JSON(http.StatusOK, OkResp{
Ok: true, Ok: true,
Result: H{ Result: H{
"publicKey": generatedKeyPair.Public, "publicKey": generatedKeyPair.Public,
"custodialId": id, "custodialId": id,
"trackingId": trackingId,
}, },
}) })
} }

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/google/uuid"
"github.com/grassrootseconomics/cic-custodial/internal/tasker" "github.com/grassrootseconomics/cic-custodial/internal/tasker"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -22,8 +23,9 @@ func SignTransferHandler(
taskerClient *tasker.TaskerClient, taskerClient *tasker.TaskerClient,
) func(echo.Context) error { ) func(echo.Context) error {
return func(c echo.Context) error { return func(c echo.Context) error {
trackingId := uuid.NewString()
var transferRequest struct { var transferRequest struct {
TrackingId string `json:"trackingId" validate:"required"`
From string `json:"from" validate:"required,eth_addr"` From string `json:"from" validate:"required,eth_addr"`
To string `json:"to" validate:"required,eth_addr"` To string `json:"to" validate:"required,eth_addr"`
VoucherAddress string `json:"voucherAddress" validate:"required,eth_addr"` VoucherAddress string `json:"voucherAddress" validate:"required,eth_addr"`
@ -31,10 +33,7 @@ func SignTransferHandler(
} }
if err := c.Bind(&transferRequest); err != nil { if err := c.Bind(&transferRequest); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
if err := c.Validate(transferRequest); err != nil { if err := c.Validate(transferRequest); err != nil {
@ -43,29 +42,26 @@ func SignTransferHandler(
taskPayload, err := json.Marshal(transferRequest) taskPayload, err := json.Marshal(transferRequest)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
_, err = taskerClient.CreateTask( _, err = taskerClient.CreateTask(
tasker.SignTransferTask, tasker.SignTransferTask,
tasker.HighPriority, tasker.HighPriority,
&tasker.Task{ &tasker.Task{
Id: transferRequest.TrackingId, Id: trackingId,
Payload: taskPayload, Payload: taskPayload,
}, },
) )
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, errResp{ return err
Ok: false,
Code: INTERNAL_ERROR,
})
} }
return c.JSON(http.StatusOK, okResp{ return c.JSON(http.StatusOK, OkResp{
Ok: true, Ok: true,
Result: H{
"trackingId": trackingId,
},
}) })
} }
} }

View File

@ -3,16 +3,18 @@ package api
const ( const (
INTERNAL_ERROR = "ERR_INTERNAL" INTERNAL_ERROR = "ERR_INTERNAL"
VALIDATION_ERROR = "ERR_VALIDATE" VALIDATION_ERROR = "ERR_VALIDATE"
DUPLICATE_ERROR = "ERR_DUPLICATE"
) )
type H map[string]any type H map[string]any
type okResp struct { type OkResp struct {
Ok bool `json:"ok"` Ok bool `json:"ok"`
Result H `json:"result"` Result H `json:"result"`
} }
type errResp struct { type ErrResp struct {
Ok bool `json:"ok"` Ok bool `json:"ok"`
Code string `json:"errorCode"` Code string `json:"errorCode"`
Message string `json:"message"`
} }

View File

@ -13,7 +13,7 @@ type Validator struct {
func (v *Validator) Validate(i interface{}) error { func (v *Validator) Validate(i interface{}) error {
if err := v.ValidatorProvider.Struct(i); err != nil { if err := v.ValidatorProvider.Struct(i); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, errResp{ return echo.NewHTTPError(http.StatusBadRequest, ErrResp{
Ok: false, Ok: false,
Code: VALIDATION_ERROR, Code: VALIDATION_ERROR,
}) })