mirror of
https://github.com/grassrootseconomics/cic-custodial.git
synced 2024-11-21 13:56:47 +01:00
snapshot: 12-ebening
This commit is contained in:
parent
4f7909e4ee
commit
f2ba079232
@ -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)
|
||||||
|
10
config.toml
10
config.toml
@ -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"
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user