mirror of
https://github.com/grassrootseconomics/cic-custodial.git
synced 2025-04-19 23:11:01 +02:00
refactor: remove action provider
* allows better control over accounting locking
This commit is contained in:
parent
fe40c0604d
commit
1bc8d65016
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -90,6 +91,8 @@ func initKeystore() keystore.Keystore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initNoncestore() noncestore.Noncestore {
|
func initNoncestore() noncestore.Noncestore {
|
||||||
|
var loadedNoncestore noncestore.Noncestore
|
||||||
|
|
||||||
switch provider := ko.MustString("noncestore.provider"); provider {
|
switch provider := ko.MustString("noncestore.provider"); provider {
|
||||||
case "redis":
|
case "redis":
|
||||||
redisNoncestore, err := redis_noncestore.NewRedisNoncestore(redis_noncestore.Opts{
|
redisNoncestore, err := redis_noncestore.NewRedisNoncestore(redis_noncestore.Opts{
|
||||||
@ -103,11 +106,22 @@ func initNoncestore() noncestore.Noncestore {
|
|||||||
lo.Fatal("initNoncestore", "error", err)
|
lo.Fatal("initNoncestore", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return redisNoncestore
|
loadedNoncestore = redisNoncestore
|
||||||
case "postgres":
|
case "postgres":
|
||||||
lo.Fatal("initNoncestore", "error", "not implemented")
|
lo.Fatal("initNoncestore", "error", "not implemented")
|
||||||
default:
|
default:
|
||||||
lo.Fatal("initNoncestore", "error", "no noncestore provider selected")
|
lo.Fatal("initNoncestore", "error", "no noncestore provider selected")
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
currentSystemNonce, err := loadedNoncestore.Peek(context.Background(), ko.MustString("admin.public"))
|
||||||
|
lo.Debug("initNoncestore: loaded (noncestore) system nonce", "nonce", currentSystemNonce)
|
||||||
|
if err != nil {
|
||||||
|
nonce, err := loadedNoncestore.SyncNetworkNonce(context.Background(), ko.MustString("admin.public"))
|
||||||
|
lo.Debug("initNoncestore: syncing system nonce", "nonce", nonce)
|
||||||
|
if err != nil {
|
||||||
|
lo.Fatal("initNonceStore", "error", "system account nonce sync failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadedNoncestore
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/actions"
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/api"
|
"github.com/grassrootseconomics/cic-custodial/internal/api"
|
||||||
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
tasker_server "github.com/grassrootseconomics/cic-custodial/internal/tasker/server"
|
tasker_server "github.com/grassrootseconomics/cic-custodial/internal/tasker/server"
|
||||||
@ -40,35 +39,32 @@ func main() {
|
|||||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
taskerClient = initTaskerClient()
|
taskerClient := initTaskerClient()
|
||||||
|
keystore := initKeystore()
|
||||||
|
noncestore := initNoncestore()
|
||||||
|
|
||||||
actionsProvider, err := actions.NewActionsProvider(actions.Opts{
|
httpServer = api.BootstrapHTTPServer(api.Opts{
|
||||||
|
Keystore: keystore,
|
||||||
|
TaskerClient: taskerClient,
|
||||||
|
})
|
||||||
|
|
||||||
|
taskerServer, err := tasker_server.NewTaskerServer(tasker_server.Opts{
|
||||||
SystemPublicKey: ko.MustString("admin.public"),
|
SystemPublicKey: ko.MustString("admin.public"),
|
||||||
SystemPrivateKey: ko.MustString("admin.key"),
|
SystemPrivateKey: ko.MustString("admin.key"),
|
||||||
ChainProvider: chainProvider,
|
ChainProvider: chainProvider,
|
||||||
Keystore: initKeystore(),
|
Keystore: keystore,
|
||||||
Noncestore: initNoncestore(),
|
Noncestore: noncestore,
|
||||||
Logger: lo,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
lo.Fatal("initActionsProvider", "err", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
httpServer = api.BootstrapHTTPServer(api.Opts{
|
|
||||||
ActionsProvider: actionsProvider,
|
|
||||||
TaskerClient: taskerClient,
|
|
||||||
})
|
|
||||||
|
|
||||||
taskerServer = tasker_server.NewTaskerServer(tasker_server.Opts{
|
|
||||||
ActionsProvider: actionsProvider,
|
|
||||||
TaskerClient: taskerClient,
|
TaskerClient: taskerClient,
|
||||||
RedisDSN: ko.MustString("redis.dsn"),
|
RedisDSN: ko.MustString("redis.dsn"),
|
||||||
Concurrency: 20,
|
|
||||||
Logger: lo,
|
|
||||||
RedisLockDB: 1,
|
RedisLockDB: 1,
|
||||||
RedisLockMinIdleConns: 3,
|
RedisLockMinIdleConns: 3,
|
||||||
RedisLockPoolSize: 6,
|
RedisLockPoolSize: 6,
|
||||||
|
Concurrency: 20,
|
||||||
|
Logger: lo,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
lo.Fatal("initTaskerServer", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
eth_crypto "github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/ethereum"
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/keystore"
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/noncestore"
|
|
||||||
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
|
||||||
"github.com/zerodha/logf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Actions interface {
|
|
||||||
CreateNewKeyPair(context.Context) (ethereum.Key, error)
|
|
||||||
ActivateCustodialAccount(context.Context, string) error
|
|
||||||
SetNewAccountNonce(context.Context, string) error
|
|
||||||
|
|
||||||
SignGiftGasTx(context.Context, string) (*types.Transaction, error)
|
|
||||||
SignTopUpGasTx(context.Context, string) (*types.Transaction, error)
|
|
||||||
SignGiftVouchertx(context.Context, string) (*types.Transaction, error)
|
|
||||||
|
|
||||||
DispatchSignedTx(context.Context, *types.Transaction) (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Opts struct {
|
|
||||||
SystemPublicKey string
|
|
||||||
SystemPrivateKey string
|
|
||||||
ChainProvider *chain.Provider
|
|
||||||
Keystore keystore.Keystore
|
|
||||||
Noncestore noncestore.Noncestore
|
|
||||||
Logger logf.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActionsProvider struct {
|
|
||||||
SystemPublicKey string
|
|
||||||
SystemPrivateKey *ecdsa.PrivateKey
|
|
||||||
ChainProvider *chain.Provider
|
|
||||||
Keystore keystore.Keystore
|
|
||||||
Noncestore noncestore.Noncestore
|
|
||||||
Lo logf.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewActionsProvider(o Opts) (*ActionsProvider, error) {
|
|
||||||
var _ Actions = (*ActionsProvider)(nil)
|
|
||||||
|
|
||||||
loadedPrivateKey, err := eth_crypto.HexToECDSA(o.SystemPrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = o.Noncestore.Peek(context.Background(), o.SystemPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
nonce, err := o.Noncestore.SyncNetworkNonce(context.Background(), o.SystemPublicKey)
|
|
||||||
o.Logger.Debug("actionsProvider: syncing system nonce", "nonce", nonce)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ActionsProvider{
|
|
||||||
SystemPublicKey: o.SystemPublicKey,
|
|
||||||
SystemPrivateKey: loadedPrivateKey,
|
|
||||||
ChainProvider: o.ChainProvider,
|
|
||||||
Keystore: o.Keystore,
|
|
||||||
Noncestore: o.Noncestore,
|
|
||||||
Lo: o.Logger,
|
|
||||||
}, nil
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/lmittmann/w3/module/eth"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) DispatchSignedTx(ctx context.Context, builtTx *types.Transaction) (string, error) {
|
|
||||||
var txHash common.Hash
|
|
||||||
|
|
||||||
if err := ap.ChainProvider.EthClient.CallCtx(
|
|
||||||
ctx,
|
|
||||||
eth.SendTx(builtTx).Returns(&txHash),
|
|
||||||
); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return txHash.String(), nil
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/ethereum"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) CreateNewKeyPair(ctx context.Context) (ethereum.Key, error) {
|
|
||||||
generatedKeyPair, err := ethereum.GenerateKeyPair()
|
|
||||||
if err != nil {
|
|
||||||
return ethereum.Key{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ap.Keystore.WriteKeyPair(ctx, generatedKeyPair); err != nil {
|
|
||||||
return ethereum.Key{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return generatedKeyPair, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) ActivateCustodialAccount(ctx context.Context, publicKey string) error {
|
|
||||||
if err := ap.Keystore.ActivateAccount(ctx, publicKey); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) SetNewAccountNonce(ctx context.Context, publicKey string) error {
|
|
||||||
if err := ap.Noncestore.SetNewAccountNonce(ctx, publicKey); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
|
||||||
"github.com/lmittmann/w3"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
initialGiftGasValue = 1000000
|
|
||||||
topupGiftGasValue = 500000
|
|
||||||
)
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) SignGiftGasTx(ctx context.Context, giftTo string) (*types.Transaction, error) {
|
|
||||||
nonce, err := ap.Noncestore.Acquire(ctx, ap.SystemPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
builtTx, err := ap.ChainProvider.BuildGasTransferTx(ap.SystemPrivateKey, chain.TransactionData{
|
|
||||||
To: w3.A(giftTo),
|
|
||||||
Nonce: nonce,
|
|
||||||
}, big.NewInt(initialGiftGasValue))
|
|
||||||
if err != nil {
|
|
||||||
return &types.Transaction{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return builtTx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) SignTopUpGasTx(ctx context.Context, giftTo string) (*types.Transaction, error) {
|
|
||||||
nonce, err := ap.Noncestore.Acquire(ctx, ap.SystemPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
builtTx, err := ap.ChainProvider.BuildGasTransferTx(ap.SystemPrivateKey, chain.TransactionData{
|
|
||||||
To: w3.A(giftTo),
|
|
||||||
Nonce: nonce,
|
|
||||||
}, big.NewInt(topupGiftGasValue))
|
|
||||||
if err != nil {
|
|
||||||
return &types.Transaction{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return builtTx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *ActionsProvider) SignGiftVouchertx(ctx context.Context, giftTo string) (*types.Transaction, error) {
|
|
||||||
return &types.Transaction{}, nil
|
|
||||||
}
|
|
@ -3,7 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/actions"
|
"github.com/grassrootseconomics/cic-custodial/internal/ethereum"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/internal/keystore"
|
||||||
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -15,15 +16,19 @@ type registrationResponse struct {
|
|||||||
|
|
||||||
func handleRegistration(c echo.Context) error {
|
func handleRegistration(c echo.Context) error {
|
||||||
var (
|
var (
|
||||||
ap = c.Get("actions").(*actions.ActionsProvider)
|
|
||||||
tc = c.Get("tasker_client").(*tasker_client.TaskerClient)
|
tc = c.Get("tasker_client").(*tasker_client.TaskerClient)
|
||||||
|
ks = c.Get("keystore").(keystore.Keystore)
|
||||||
)
|
)
|
||||||
|
|
||||||
generatedKeyPair, err := ap.CreateNewKeyPair(c.Request().Context())
|
generatedKeyPair, err := ethereum.GenerateKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "ERR_GEN_KEYPAIR")
|
return echo.NewHTTPError(http.StatusInternalServerError, "ERR_GEN_KEYPAIR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ks.WriteKeyPair(c.Request().Context(), generatedKeyPair); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "ERR_SAVE_KEYPAIR")
|
||||||
|
}
|
||||||
|
|
||||||
job, err := tc.CreateRegistrationTask(tasker_client.RegistrationPayload{
|
job, err := tc.CreateRegistrationTask(tasker_client.RegistrationPayload{
|
||||||
PublicKey: generatedKeyPair.Public,
|
PublicKey: generatedKeyPair.Public,
|
||||||
}, tasker_client.SetNewAccountNonceTask)
|
}, tasker_client.SetNewAccountNonceTask)
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/arl/statsviz"
|
"github.com/arl/statsviz"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/actions"
|
"github.com/grassrootseconomics/cic-custodial/internal/keystore"
|
||||||
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -14,7 +14,7 @@ type okResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
ActionsProvider *actions.ActionsProvider
|
Keystore keystore.Keystore
|
||||||
TaskerClient *tasker_client.TaskerClient
|
TaskerClient *tasker_client.TaskerClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ func BootstrapHTTPServer(o Opts) *echo.Echo {
|
|||||||
|
|
||||||
server.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
server.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
c.Set("actions", o.ActionsProvider)
|
c.Set("keystore", o.Keystore)
|
||||||
c.Set("tasker_client", o.TaskerClient)
|
c.Set("tasker_client", o.TaskerClient)
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
||||||
"github.com/lmittmann/w3"
|
"github.com/lmittmann/w3"
|
||||||
"github.com/lmittmann/w3/module/eth"
|
"github.com/lmittmann/w3/module/eth"
|
||||||
|
"github.com/zerodha/logf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Opts represents the Redis nonce store specific params
|
// Opts represents the Redis nonce store specific params
|
||||||
@ -17,12 +18,14 @@ type Opts struct {
|
|||||||
MinIdleConns int
|
MinIdleConns int
|
||||||
PoolSize int
|
PoolSize int
|
||||||
ChainProvider *chain.Provider
|
ChainProvider *chain.Provider
|
||||||
|
Lo logf.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedisNoncestore implements `noncestore.Noncestore`
|
// RedisNoncestore implements `noncestore.Noncestore`
|
||||||
type RedisNoncestore struct {
|
type RedisNoncestore struct {
|
||||||
chainProvider *chain.Provider
|
chainProvider *chain.Provider
|
||||||
redis *redis.Client
|
redis *redis.Client
|
||||||
|
lo logf.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRedisNoncestore(o Opts) (noncestore.Noncestore, error) {
|
func NewRedisNoncestore(o Opts) (noncestore.Noncestore, error) {
|
||||||
@ -40,6 +43,7 @@ func NewRedisNoncestore(o Opts) (noncestore.Noncestore, error) {
|
|||||||
return &RedisNoncestore{
|
return &RedisNoncestore{
|
||||||
redis: redisClient,
|
redis: redisClient,
|
||||||
chainProvider: o.ChainProvider,
|
chainProvider: o.ChainProvider,
|
||||||
|
lo: o.Lo,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +121,7 @@ func (ns *RedisNoncestore) SyncNetworkNonce(ctx context.Context, publicKey strin
|
|||||||
func (ns *RedisNoncestore) SetNewAccountNonce(ctx context.Context, publicKey string) error {
|
func (ns *RedisNoncestore) SetNewAccountNonce(ctx context.Context, publicKey string) error {
|
||||||
err := ns.redis.Set(ctx, publicKey, 0, 0).Err()
|
err := ns.redis.Set(ctx, publicKey, 0, 0).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
ns.lo.Error("noncestore", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,21 +5,26 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
|
"github.com/lmittmann/w3/module/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tp *TaskerProcessor) txDispatcher(ctx context.Context, t *asynq.Task) error {
|
func (tp *TaskerProcessor) txDispatcher(ctx context.Context, t *asynq.Task) error {
|
||||||
var (
|
var (
|
||||||
p client.TxPayload
|
p client.TxPayload
|
||||||
|
txHash common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := json.Unmarshal(t.Payload(), &p); err != nil {
|
if err := json.Unmarshal(t.Payload(), &p); err != nil {
|
||||||
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := tp.ActionsProvider.DispatchSignedTx(ctx, p.Tx)
|
if err := tp.ChainProvider.EthClient.CallCtx(
|
||||||
if err != nil {
|
ctx,
|
||||||
|
eth.SendTx(p.Tx).Returns(&txHash),
|
||||||
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,16 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
|
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
|
"github.com/lmittmann/w3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
initialGiftGasValue = 1000000
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tp *TaskerProcessor) setNewAccountNonce(ctx context.Context, t *asynq.Task) error {
|
func (tp *TaskerProcessor) setNewAccountNonce(ctx context.Context, t *asynq.Task) error {
|
||||||
@ -18,7 +25,7 @@ func (tp *TaskerProcessor) setNewAccountNonce(ctx context.Context, t *asynq.Task
|
|||||||
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tp.ActionsProvider.SetNewAccountNonce(ctx, p.PublicKey); err != nil {
|
if err := tp.Noncestore.SetNewAccountNonce(ctx, p.PublicKey); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,19 +46,27 @@ func (tp *TaskerProcessor) giftGasProcessor(ctx context.Context, t *asynq.Task)
|
|||||||
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
lock, err := tp.LockProvider.Obtain(ctx, tp.ActionsProvider.SystemPublicKey, LockTTL, nil)
|
lock, err := tp.LockProvider.Obtain(ctx, tp.SystemPublicKey, LockTTL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer lock.Release(ctx)
|
defer lock.Release(ctx)
|
||||||
|
|
||||||
signedTx, err := tp.ActionsProvider.SignGiftGasTx(ctx, p.PublicKey)
|
nonce, err := tp.Noncestore.Acquire(ctx, tp.SystemPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
builtTx, err := tp.ChainProvider.BuildGasTransferTx(tp.SystemPrivateKey, chain.TransactionData{
|
||||||
|
To: w3.A(p.PublicKey),
|
||||||
|
Nonce: nonce,
|
||||||
|
}, big.NewInt(initialGiftGasValue))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tp.TaskerClient.CreateTxDispatchTask(client.TxPayload{
|
_, err = tp.TaskerClient.CreateTxDispatchTask(client.TxPayload{
|
||||||
Tx: signedTx,
|
Tx: builtTx,
|
||||||
}, client.TxDispatchTask)
|
}, client.TxDispatchTask)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -74,7 +89,7 @@ func (tp *TaskerProcessor) activateAccountProcessor(ctx context.Context, t *asyn
|
|||||||
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tp.ActionsProvider.ActivateCustodialAccount(ctx, p.PublicKey); err != nil {
|
if err := tp.Keystore.ActivateAccount(ctx, p.PublicKey); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bsm/redislock"
|
"github.com/bsm/redislock"
|
||||||
|
eth_crypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/actions"
|
"github.com/grassrootseconomics/cic-custodial/internal/keystore"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/internal/noncestore"
|
||||||
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
tasker_client "github.com/grassrootseconomics/cic-custodial/internal/tasker/client"
|
||||||
|
"github.com/grassrootseconomics/cic-go-sdk/chain"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/zerodha/logf"
|
"github.com/zerodha/logf"
|
||||||
)
|
)
|
||||||
@ -16,7 +20,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
ActionsProvider *actions.ActionsProvider
|
SystemPublicKey string
|
||||||
|
SystemPrivateKey string
|
||||||
|
ChainProvider *chain.Provider
|
||||||
|
Keystore keystore.Keystore
|
||||||
|
Noncestore noncestore.Noncestore
|
||||||
TaskerClient *tasker_client.TaskerClient
|
TaskerClient *tasker_client.TaskerClient
|
||||||
RedisDSN string
|
RedisDSN string
|
||||||
RedisLockDB int
|
RedisLockDB int
|
||||||
@ -27,8 +35,12 @@ type Opts struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TaskerProcessor struct {
|
type TaskerProcessor struct {
|
||||||
|
SystemPublicKey string
|
||||||
|
SystemPrivateKey *ecdsa.PrivateKey
|
||||||
|
ChainProvider *chain.Provider
|
||||||
|
Noncestore noncestore.Noncestore
|
||||||
|
Keystore keystore.Keystore
|
||||||
LockProvider *redislock.Client
|
LockProvider *redislock.Client
|
||||||
ActionsProvider *actions.ActionsProvider
|
|
||||||
TaskerClient *tasker_client.TaskerClient
|
TaskerClient *tasker_client.TaskerClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +49,12 @@ type TaskerServer struct {
|
|||||||
Mux *asynq.ServeMux
|
Mux *asynq.ServeMux
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTaskerServer(o Opts) *TaskerServer {
|
func NewTaskerServer(o Opts) (*TaskerServer, error) {
|
||||||
|
loadedPrivateKey, err := eth_crypto.HexToECDSA(o.SystemPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
redisLockClient := redis.NewClient(&redis.Options{
|
redisLockClient := redis.NewClient(&redis.Options{
|
||||||
Addr: o.RedisDSN,
|
Addr: o.RedisDSN,
|
||||||
DB: o.RedisLockDB,
|
DB: o.RedisLockDB,
|
||||||
@ -46,7 +63,11 @@ func NewTaskerServer(o Opts) *TaskerServer {
|
|||||||
})
|
})
|
||||||
|
|
||||||
taskerProcessor := &TaskerProcessor{
|
taskerProcessor := &TaskerProcessor{
|
||||||
ActionsProvider: o.ActionsProvider,
|
SystemPublicKey: o.SystemPublicKey,
|
||||||
|
SystemPrivateKey: loadedPrivateKey,
|
||||||
|
ChainProvider: o.ChainProvider,
|
||||||
|
Noncestore: o.Noncestore,
|
||||||
|
Keystore: o.Keystore,
|
||||||
TaskerClient: o.TaskerClient,
|
TaskerClient: o.TaskerClient,
|
||||||
LockProvider: redislock.New(redisLockClient),
|
LockProvider: redislock.New(redisLockClient),
|
||||||
}
|
}
|
||||||
@ -85,5 +106,5 @@ func NewTaskerServer(o Opts) *TaskerServer {
|
|||||||
return &TaskerServer{
|
return &TaskerServer{
|
||||||
Server: asynqServer,
|
Server: asynqServer,
|
||||||
Mux: mux,
|
Mux: mux,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user