mirror of
https://github.com/grassrootseconomics/cic-custodial.git
synced 2026-05-27 21:47:55 +02:00
refactor (store): consolidate all pg store related actions
* All postgres related functions now live in internal/store. * Updated queries.sql file to match struct order (readibility) * Moved keystore -> store * Moved queries -> store * Removed pkg/postgres
This commit is contained in:
@@ -22,7 +22,7 @@ func HandleAccountCreate(cu *custodial.Custodial) func(echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
id, err := cu.Keystore.WriteKeyPair(c.Request().Context(), generatedKeyPair)
|
||||
id, err := cu.Store.WriteKeyPair(c.Request().Context(), generatedKeyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func HandleSignTransfer(cu *custodial.Custodial) func(echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
accountActive, gasQuota, err := cu.PgStore.GetAccountStatusByAddress(c.Request().Context(), req.From)
|
||||
accountActive, gasQuota, err := cu.Store.GetAccountStatus(c.Request().Context(), req.From)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func HandleTrackTx(cu *custodial.Custodial) func(echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
txs, err := cu.PgStore.GetTxStatusByTrackingId(c.Request().Context(), txStatusRequest.TrackingId)
|
||||
txs, err := cu.Store.GetTxStatus(c.Request().Context(), txStatusRequest.TrackingId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func HandleTrackTx(cu *custodial.Custodial) func(echo.Context) error {
|
||||
return c.JSON(http.StatusOK, OkResp{
|
||||
Ok: true,
|
||||
Result: H{
|
||||
"transactions": txs,
|
||||
"transaction": txs,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,16 +3,15 @@ package custodial
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"time"
|
||||
|
||||
"github.com/bsm/redislock"
|
||||
"github.com/celo-org/celo-blockchain/common"
|
||||
eth_crypto "github.com/celo-org/celo-blockchain/crypto"
|
||||
"github.com/grassrootseconomics/celoutils"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/keystore"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/nonce"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/util"
|
||||
"github.com/grassrootseconomics/w3-celo-patch"
|
||||
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
||||
"github.com/labstack/gommon/log"
|
||||
@@ -22,10 +21,9 @@ import (
|
||||
type (
|
||||
Opts struct {
|
||||
CeloProvider *celoutils.Provider
|
||||
Keystore keystore.Keystore
|
||||
LockProvider *redislock.Client
|
||||
Noncestore nonce.Noncestore
|
||||
PgStore store.Store
|
||||
Store store.Store
|
||||
RedisClient *redis.Client
|
||||
RegistryAddress string
|
||||
SystemPrivateKey string
|
||||
@@ -36,10 +34,9 @@ type (
|
||||
Custodial struct {
|
||||
Abis map[string]*w3.Func
|
||||
CeloProvider *celoutils.Provider
|
||||
Keystore keystore.Keystore
|
||||
LockProvider *redislock.Client
|
||||
Noncestore nonce.Noncestore
|
||||
PgStore store.Store
|
||||
Store store.Store
|
||||
RedisClient *redis.Client
|
||||
RegistryMap map[string]common.Address
|
||||
SystemPrivateKey *ecdsa.PrivateKey
|
||||
@@ -49,7 +46,7 @@ type (
|
||||
)
|
||||
|
||||
func NewCustodial(o Opts) (*Custodial, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), util.SLATimeout)
|
||||
defer cancel()
|
||||
|
||||
registryMap, err := o.CeloProvider.RegistryMap(ctx, celoutils.HexToAddress(o.RegistryAddress))
|
||||
@@ -86,10 +83,9 @@ func NewCustodial(o Opts) (*Custodial, error) {
|
||||
return &Custodial{
|
||||
Abis: initAbis(),
|
||||
CeloProvider: o.CeloProvider,
|
||||
Keystore: o.Keystore,
|
||||
LockProvider: o.LockProvider,
|
||||
Noncestore: o.Noncestore,
|
||||
PgStore: o.PgStore,
|
||||
Store: o.Store,
|
||||
RedisClient: o.RedisClient,
|
||||
RegistryMap: registryMap,
|
||||
SystemPrivateKey: privateKey,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package keystore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/keypair"
|
||||
)
|
||||
|
||||
// Keystore defines how keypairs should be stored and accessed from a storage backend.
|
||||
type Keystore interface {
|
||||
WriteKeyPair(context.Context, keypair.Key) (uint, error)
|
||||
LoadPrivateKey(context.Context, string) (*ecdsa.PrivateKey, error)
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package keystore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
eth_crypto "github.com/celo-org/celo-blockchain/crypto"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/queries"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/keypair"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type (
|
||||
Opts struct {
|
||||
PostgresPool *pgxpool.Pool
|
||||
Queries *queries.Queries
|
||||
}
|
||||
|
||||
PostgresKeystore struct {
|
||||
db *pgxpool.Pool
|
||||
queries *queries.Queries
|
||||
}
|
||||
)
|
||||
|
||||
func NewPostgresKeytore(o Opts) Keystore {
|
||||
return &PostgresKeystore{
|
||||
db: o.PostgresPool,
|
||||
queries: o.Queries,
|
||||
}
|
||||
}
|
||||
|
||||
// WriteKeyPair inserts a keypair into the db and returns the linked id.
|
||||
func (ks *PostgresKeystore) WriteKeyPair(ctx context.Context, keypair keypair.Key) (uint, error) {
|
||||
var (
|
||||
id uint
|
||||
)
|
||||
|
||||
if err := ks.db.QueryRow(ctx, ks.queries.WriteKeyPair, keypair.Public, keypair.Private).Scan(&id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// LoadPrivateKey loads a private key as a crypto primitive for direct use. An id is used to search for the private key.
|
||||
func (ks *PostgresKeystore) LoadPrivateKey(ctx context.Context, publicKey string) (*ecdsa.PrivateKey, error) {
|
||||
var (
|
||||
privateKeyString string
|
||||
)
|
||||
|
||||
if err := ks.db.QueryRow(ctx, ks.queries.LoadKeyPair, publicKey).Scan(&privateKeyString); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privateKey, err := eth_crypto.HexToECDSA(privateKeyString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package queries
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/knadh/goyesql/v2"
|
||||
)
|
||||
|
||||
type Queries struct {
|
||||
// Keystore
|
||||
WriteKeyPair string `query:"write-key-pair"`
|
||||
LoadKeyPair string `query:"load-key-pair"`
|
||||
// Store
|
||||
CreateOTX string `query:"create-otx"`
|
||||
CreateDispatchStatus string `query:"create-dispatch-status"`
|
||||
ActivateAccount string `query:"activate-account"`
|
||||
UpdateChainStatus string `query:"update-chain-status"`
|
||||
GetTxStatusByTrackingId string `query:"get-tx-status-by-tracking-id"`
|
||||
GetAccountActivationQuorum string `query:"get-account-activation-quorum"`
|
||||
GetAccountStatus string `query:"get-account-status-by-address"`
|
||||
DecrGasQuota string `query:"decr-gas-quota"`
|
||||
ResetGasQuota string `query:"reset-gas-quota"`
|
||||
}
|
||||
|
||||
func LoadQueries(q goyesql.Queries) (*Queries, error) {
|
||||
loadedQueries := &Queries{}
|
||||
|
||||
if err := goyesql.ScanToStruct(loadedQueries, q, nil); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan queries %v", err)
|
||||
}
|
||||
|
||||
return loadedQueries, nil
|
||||
}
|
||||
@@ -4,32 +4,48 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func (s *PostgresStore) GetAccountStatusByAddress(ctx context.Context, publicAddress string) (bool, int, error) {
|
||||
func (s *PgStore) ActivateAccount(
|
||||
ctx context.Context,
|
||||
publicAddress string,
|
||||
) error {
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.ActivateAccount,
|
||||
publicAddress,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PgStore) GetAccountStatus(
|
||||
ctx context.Context,
|
||||
publicAddress string,
|
||||
) (bool, int, error) {
|
||||
var (
|
||||
accountActive bool
|
||||
gasQuota int
|
||||
)
|
||||
|
||||
if err := s.db.QueryRow(ctx, s.queries.GetAccountStatus, publicAddress).Scan(&accountActive, &gasQuota); err != nil {
|
||||
if err := s.db.QueryRow(
|
||||
ctx,
|
||||
s.queries.GetAccountStatus,
|
||||
publicAddress,
|
||||
).Scan(
|
||||
&accountActive,
|
||||
&gasQuota,
|
||||
); err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
|
||||
return accountActive, gasQuota, nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) GetAccountActivationQuorum(ctx context.Context, trackingId string) (int, error) {
|
||||
var (
|
||||
quorum int
|
||||
)
|
||||
|
||||
if err := s.db.QueryRow(ctx, s.queries.GetAccountActivationQuorum, trackingId).Scan(&quorum); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return quorum, nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) DecrGasQuota(ctx context.Context, publicAddress string) error {
|
||||
func (s *PgStore) DecrGasQuota(
|
||||
ctx context.Context,
|
||||
publicAddress string,
|
||||
) error {
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.DecrGasQuota,
|
||||
@@ -41,7 +57,10 @@ func (s *PostgresStore) DecrGasQuota(ctx context.Context, publicAddress string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) ResetGasQuota(ctx context.Context, publicAddress string) error {
|
||||
func (s *PgStore) ResetGasQuota(
|
||||
ctx context.Context,
|
||||
publicAddress string,
|
||||
) error {
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.ResetGasQuota,
|
||||
@@ -52,15 +71,3 @@ func (s *PostgresStore) ResetGasQuota(ctx context.Context, publicAddress string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) ActivateAccount(ctx context.Context, publicAddress string) error {
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.ActivateAccount,
|
||||
publicAddress,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
53
internal/store/keystore.go
Normal file
53
internal/store/keystore.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
eth_crypto "github.com/celo-org/celo-blockchain/crypto"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/keypair"
|
||||
)
|
||||
|
||||
func (s *PgStore) WriteKeyPair(
|
||||
ctx context.Context,
|
||||
keypair keypair.Key,
|
||||
) (uint, error) {
|
||||
var (
|
||||
id uint
|
||||
)
|
||||
|
||||
if err := s.db.QueryRow(
|
||||
ctx,
|
||||
s.queries.WriteKeyPair,
|
||||
keypair.Public,
|
||||
keypair.Private,
|
||||
).Scan(&id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (s *PgStore) LoadPrivateKey(
|
||||
ctx context.Context,
|
||||
publicKey string,
|
||||
) (*ecdsa.PrivateKey, error) {
|
||||
var (
|
||||
privateKeyString string
|
||||
)
|
||||
|
||||
if err := s.db.QueryRow(
|
||||
ctx,
|
||||
s.queries.LoadKeyPair,
|
||||
publicKey,
|
||||
).Scan(&privateKeyString); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privateKey, err := eth_crypto.HexToECDSA(privateKeyString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
@@ -2,21 +2,39 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/georgysavva/scany/v2/pgxscan"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||
)
|
||||
|
||||
type TxStatus struct {
|
||||
Type string `db:"type" json:"txType"`
|
||||
TxHash string `db:"tx_hash" json:"txHash"`
|
||||
TransferValue uint64 `db:"transfer_value" json:"transferValue"`
|
||||
CreatedAt time.Time `db:"created_at" json:"createdAt"`
|
||||
Status string `db:"status" json:"status"`
|
||||
}
|
||||
type (
|
||||
Otx struct {
|
||||
TrackingId string
|
||||
Type enum.OtxType
|
||||
RawTx string
|
||||
TxHash string
|
||||
From string
|
||||
Data string
|
||||
GasLimit uint64
|
||||
TransferValue uint64
|
||||
GasPrice *big.Int
|
||||
Nonce uint64
|
||||
}
|
||||
txStatus struct {
|
||||
CreatedAt time.Time `db:"created_at" json:"createdAt"`
|
||||
Status string `db:"status" json:"status"`
|
||||
TransferValue uint64 `db:"transfer_value" json:"transferValue"`
|
||||
TxHash string `db:"tx_hash" json:"txHash"`
|
||||
Type string `db:"type" json:"txType"`
|
||||
}
|
||||
)
|
||||
|
||||
func (s *PostgresStore) CreateOtx(ctx context.Context, otx OTX) (uint, error) {
|
||||
func (s *PgStore) CreateOtx(
|
||||
ctx context.Context,
|
||||
otx Otx,
|
||||
) (uint, error) {
|
||||
var (
|
||||
id uint
|
||||
)
|
||||
@@ -34,37 +52,52 @@ func (s *PostgresStore) CreateOtx(ctx context.Context, otx OTX) (uint, error) {
|
||||
otx.GasLimit,
|
||||
otx.TransferValue,
|
||||
otx.Nonce,
|
||||
).Scan(&id); err != nil {
|
||||
).Scan(
|
||||
&id,
|
||||
); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) GetTxStatusByTrackingId(ctx context.Context, trackingId string) ([]*TxStatus, error) {
|
||||
func (s *PgStore) GetTxStatus(
|
||||
ctx context.Context,
|
||||
trackingId string,
|
||||
) (txStatus, error) {
|
||||
var (
|
||||
txs []*TxStatus
|
||||
tx txStatus
|
||||
)
|
||||
|
||||
if err := pgxscan.Select(
|
||||
rows, err := s.db.Query(
|
||||
ctx,
|
||||
s.db,
|
||||
&txs,
|
||||
s.queries.GetTxStatusByTrackingId,
|
||||
trackingId,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
)
|
||||
if err != nil {
|
||||
return tx, err
|
||||
}
|
||||
|
||||
return txs, nil
|
||||
if err := pgxscan.ScanOne(
|
||||
&tx,
|
||||
rows,
|
||||
); err != nil {
|
||||
return tx, err
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error {
|
||||
func (s *PgStore) CreateDispatchStatus(
|
||||
ctx context.Context,
|
||||
otxId uint,
|
||||
otxStatus enum.OtxStatus,
|
||||
) error {
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.CreateDispatchStatus,
|
||||
dispatch.OtxId,
|
||||
dispatch.Status,
|
||||
otxId,
|
||||
otxStatus,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,21 +105,26 @@ func (s *PostgresStore) CreateDispatchStatus(ctx context.Context, dispatch Dispa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PostgresStore) UpdateOtxStatusFromChainEvent(ctx context.Context, chainEvent MinimalTxInfo) error {
|
||||
func (s *PgStore) UpdateDispatchStatus(
|
||||
ctx context.Context,
|
||||
txSuccess bool,
|
||||
txHash string,
|
||||
txBlock uint64,
|
||||
) error {
|
||||
var (
|
||||
status = enum.SUCCESS
|
||||
)
|
||||
|
||||
if !chainEvent.Success {
|
||||
if !txSuccess {
|
||||
status = enum.REVERTED
|
||||
}
|
||||
|
||||
if _, err := s.db.Exec(
|
||||
ctx,
|
||||
s.queries.UpdateChainStatus,
|
||||
chainEvent.TxHash,
|
||||
s.queries.UpdateDispatchStatus,
|
||||
txHash,
|
||||
status,
|
||||
chainEvent.Block,
|
||||
txBlock,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/queries"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type (
|
||||
Opts struct {
|
||||
PostgresPool *pgxpool.Pool
|
||||
Queries *queries.Queries
|
||||
}
|
||||
|
||||
PostgresStore struct {
|
||||
db *pgxpool.Pool
|
||||
queries *queries.Queries
|
||||
}
|
||||
)
|
||||
|
||||
func NewPostgresStore(o Opts) Store {
|
||||
return &PostgresStore{
|
||||
db: o.PostgresPool,
|
||||
queries: o.Queries,
|
||||
}
|
||||
}
|
||||
@@ -2,49 +2,127 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/keypair"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/util"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/jackc/tern/v2/migrate"
|
||||
"github.com/knadh/goyesql/v2"
|
||||
)
|
||||
|
||||
type (
|
||||
MinimalTxInfo struct {
|
||||
Block uint64 `json:"block"`
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
ContractAddress string `json:"contractAddress"`
|
||||
Success bool `json:"success"`
|
||||
TxHash string `json:"transactionHash"`
|
||||
TxIndex uint `json:"transactionIndex"`
|
||||
Value uint64 `json:"value"`
|
||||
}
|
||||
OTX struct {
|
||||
TrackingId string
|
||||
Type enum.OtxType
|
||||
RawTx string
|
||||
TxHash string
|
||||
From string
|
||||
Data string
|
||||
GasLimit uint64
|
||||
TransferValue uint64
|
||||
GasPrice *big.Int
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
DispatchStatus struct {
|
||||
OtxId uint
|
||||
Status enum.OtxStatus
|
||||
}
|
||||
|
||||
Store interface {
|
||||
CreateOtx(ctx context.Context, otx OTX) (id uint, err error)
|
||||
CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error
|
||||
GetTxStatusByTrackingId(ctx context.Context, trackingId string) ([]*TxStatus, error)
|
||||
UpdateOtxStatusFromChainEvent(ctx context.Context, chainEvent MinimalTxInfo) error
|
||||
GetAccountStatusByAddress(ctx context.Context, publicAddress string) (bool, int, error)
|
||||
GetAccountActivationQuorum(ctx context.Context, trackingId string) (int, error)
|
||||
DecrGasQuota(ctx context.Context, publicAddress string) error
|
||||
ResetGasQuota(ctx context.Context, publicAddress string) error
|
||||
ActivateAccount(ctx context.Context, publicAddress string) error
|
||||
// Keypair related actions.
|
||||
LoadPrivateKey(context.Context, string) (*ecdsa.PrivateKey, error)
|
||||
WriteKeyPair(context.Context, keypair.Key) (uint, error)
|
||||
// Otx related actions.
|
||||
CreateOtx(context.Context, Otx) (uint, error)
|
||||
GetTxStatus(context.Context, string) (txStatus, error)
|
||||
CreateDispatchStatus(context.Context, uint, enum.OtxStatus) error
|
||||
UpdateDispatchStatus(context.Context, bool, string, uint64) error
|
||||
// Account related actions.
|
||||
ActivateAccount(context.Context, string) error
|
||||
GetAccountStatus(context.Context, string) (bool, int, error)
|
||||
// Gas quota related actions.
|
||||
DecrGasQuota(context.Context, string) error
|
||||
ResetGasQuota(context.Context, string) error
|
||||
}
|
||||
|
||||
Opts struct {
|
||||
DSN string
|
||||
MigrationsFolderPath string
|
||||
QueriesFolderPath string
|
||||
}
|
||||
|
||||
PgStore struct {
|
||||
db *pgxpool.Pool
|
||||
queries *queries
|
||||
}
|
||||
|
||||
queries struct {
|
||||
// Keystore related queries.
|
||||
WriteKeyPair string `query:"write-key-pair"`
|
||||
LoadKeyPair string `query:"load-key-pair"`
|
||||
// Otx related queries.
|
||||
CreateOTX string `query:"create-otx"`
|
||||
GetTxStatusByTrackingId string `query:"get-tx-status-by-tracking-id"`
|
||||
CreateDispatchStatus string `query:"create-dispatch-status"`
|
||||
UpdateDispatchStatus string `query:"update-dispatch-status"`
|
||||
// Account related queries.
|
||||
ActivateAccount string `query:"activate-account"`
|
||||
GetAccountStatus string `query:"get-account-status-by-address"`
|
||||
DecrGasQuota string `query:"decr-gas-quota"`
|
||||
ResetGasQuota string `query:"reset-gas-quota"`
|
||||
}
|
||||
)
|
||||
|
||||
func NewPgStore(o Opts) (Store, error) {
|
||||
parsedConfig, err := pgxpool.ParseConfig(o.DSN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbPool, err := pgxpool.NewWithConfig(context.Background(), parsedConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queries, err := loadQueries(o.QueriesFolderPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := runMigrations(context.Background(), dbPool, o.MigrationsFolderPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PgStore{
|
||||
db: dbPool,
|
||||
queries: queries,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadQueries(queriesPath string) (*queries, error) {
|
||||
parsedQueries, err := goyesql.ParseFile(queriesPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loadedQueries := &queries{}
|
||||
|
||||
if err := goyesql.ScanToStruct(loadedQueries, parsedQueries, nil); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan queries %v", err)
|
||||
}
|
||||
|
||||
return loadedQueries, nil
|
||||
}
|
||||
|
||||
func runMigrations(ctx context.Context, dbPool *pgxpool.Pool, migrationsPath string) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, util.SLATimeout)
|
||||
defer cancel()
|
||||
|
||||
conn, err := dbPool.Acquire(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Release()
|
||||
|
||||
migrator, err := migrate.NewMigrator(ctx, conn.Conn(), "schema_version")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := migrator.LoadMigrations(os.DirFS(migrationsPath)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := migrator.Migrate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
retryRequeueInterval = 2 * time.Second
|
||||
retryRequeueInterval = 1 * time.Second
|
||||
)
|
||||
|
||||
type TaskerServerOpts struct {
|
||||
|
||||
@@ -35,7 +35,7 @@ func AccountRefillGasProcessor(cu *custodial.Custodial) func(context.Context, *a
|
||||
return err
|
||||
}
|
||||
|
||||
_, gasQuota, err := cu.PgStore.GetAccountStatusByAddress(ctx, payload.PublicKey)
|
||||
_, gasQuota, err := cu.Store.GetAccountStatus(ctx, payload.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func AccountRefillGasProcessor(cu *custodial.Custodial) func(context.Context, *a
|
||||
return err
|
||||
}
|
||||
|
||||
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||
id, err := cu.Store.CreateOtx(ctx, store.Otx{
|
||||
TrackingId: payload.TrackingId,
|
||||
Type: enum.REFILL_GAS,
|
||||
RawTx: hexutil.Encode(rawTx),
|
||||
|
||||
@@ -82,7 +82,7 @@ func AccountRegisterOnChainProcessor(cu *custodial.Custodial) func(context.Conte
|
||||
return err
|
||||
}
|
||||
|
||||
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||
id, err := cu.Store.CreateOtx(ctx, store.Otx{
|
||||
TrackingId: payload.TrackingId,
|
||||
Type: enum.ACCOUNT_REGISTER,
|
||||
RawTx: hexutil.Encode(rawTx),
|
||||
@@ -96,7 +96,7 @@ func AccountRegisterOnChainProcessor(cu *custodial.Custodial) func(context.Conte
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
disptachJobPayload, err := json.Marshal(TxPayload{
|
||||
OtxId: id,
|
||||
Tx: builtTx,
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/celo-org/celo-blockchain/core/types"
|
||||
"github.com/grassrootseconomics/celoutils"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/custodial"
|
||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
||||
"github.com/hibiken/asynq"
|
||||
@@ -24,41 +23,37 @@ func DispatchTx(cu *custodial.Custodial) func(context.Context, *asynq.Task) erro
|
||||
return func(ctx context.Context, t *asynq.Task) error {
|
||||
var (
|
||||
payload TxPayload
|
||||
dispatchStatus store.DispatchStatus
|
||||
dispathchTx common.Hash
|
||||
dispatchStatus enum.OtxStatus = enum.IN_NETWORK
|
||||
)
|
||||
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dispatchStatus.OtxId = payload.OtxId
|
||||
|
||||
if err := cu.CeloProvider.Client.CallCtx(
|
||||
ctx,
|
||||
eth.SendTx(payload.Tx).Returns(&dispathchTx),
|
||||
); err != nil {
|
||||
switch err.Error() {
|
||||
case celoutils.ErrGasPriceLow:
|
||||
dispatchStatus.Status = enum.FAIL_LOW_GAS_PRICE
|
||||
dispatchStatus = enum.FAIL_LOW_GAS_PRICE
|
||||
case celoutils.ErrInsufficientGas:
|
||||
dispatchStatus.Status = enum.FAIL_NO_GAS
|
||||
dispatchStatus = enum.FAIL_NO_GAS
|
||||
case celoutils.ErrNonceLow:
|
||||
dispatchStatus.Status = enum.FAIL_LOW_NONCE
|
||||
dispatchStatus = enum.FAIL_LOW_NONCE
|
||||
default:
|
||||
dispatchStatus.Status = enum.FAIL_UNKNOWN_RPC_ERROR
|
||||
dispatchStatus = enum.FAIL_UNKNOWN_RPC_ERROR
|
||||
}
|
||||
|
||||
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
||||
if err := cu.Store.CreateDispatchStatus(ctx, payload.OtxId, dispatchStatus); err != nil {
|
||||
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
||||
}
|
||||
|
||||
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
||||
}
|
||||
|
||||
dispatchStatus.Status = enum.IN_NETWORK
|
||||
|
||||
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
||||
if err := cu.Store.CreateDispatchStatus(ctx, payload.OtxId, dispatchStatus); err != nil {
|
||||
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func SignTransfer(cu *custodial.Custodial) func(context.Context, *asynq.Task) er
|
||||
}
|
||||
defer lock.Release(ctx)
|
||||
|
||||
key, err := cu.Keystore.LoadPrivateKey(ctx, payload.From)
|
||||
key, err := cu.Store.LoadPrivateKey(ctx, payload.From)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func SignTransfer(cu *custodial.Custodial) func(context.Context, *asynq.Task) er
|
||||
return err
|
||||
}
|
||||
|
||||
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||
id, err := cu.Store.CreateOtx(ctx, store.Otx{
|
||||
TrackingId: payload.TrackingId,
|
||||
Type: enum.TRANSFER_VOUCHER,
|
||||
RawTx: hexutil.Encode(rawTx),
|
||||
@@ -105,7 +105,7 @@ func SignTransfer(cu *custodial.Custodial) func(context.Context, *asynq.Task) er
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cu.PgStore.DecrGasQuota(ctx, payload.From); err != nil {
|
||||
if err := cu.Store.DecrGasQuota(ctx, payload.From); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user