mirror of
https://github.com/grassrootseconomics/cic-custodial.git
synced 2024-12-22 17:57:32 +01:00
Mohammed Sohail
0e5db7f06f
Useful for rebuilding the nonce cache automatically. * uses otx_sign as the first source * can fallback to chain nonce value of the 1st source is corrupted
131 lines
3.4 KiB
Go
131 lines
3.4 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"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 (
|
|
Store interface {
|
|
// 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)
|
|
GetNextNonce(context.Context, string) (uint64, 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"`
|
|
GetNextNonce string `query:"get-next-nonce"`
|
|
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
|
|
}
|