2023-02-15 08:05:43 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-03-02 16:46:02 +01:00
|
|
|
"context"
|
2023-02-15 08:05:43 +01:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/bsm/redislock"
|
2023-02-20 10:56:30 +01:00
|
|
|
"github.com/grassrootseconomics/celoutils"
|
2023-03-06 09:18:41 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/custodial"
|
2023-02-15 08:05:43 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/nonce"
|
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
2023-03-06 09:18:41 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/sub"
|
2023-02-15 08:05:43 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
|
|
|
"github.com/grassrootseconomics/cic-custodial/pkg/logg"
|
|
|
|
"github.com/grassrootseconomics/cic-custodial/pkg/redis"
|
|
|
|
"github.com/knadh/koanf/parsers/toml"
|
|
|
|
"github.com/knadh/koanf/providers/env"
|
|
|
|
"github.com/knadh/koanf/providers/file"
|
2023-03-01 12:19:57 +01:00
|
|
|
"github.com/knadh/koanf/v2"
|
2023-03-06 09:18:41 +01:00
|
|
|
"github.com/nats-io/nats.go"
|
2023-02-15 08:05:43 +01:00
|
|
|
"github.com/zerodha/logf"
|
|
|
|
)
|
|
|
|
|
2023-02-20 10:56:30 +01:00
|
|
|
// Load logger.
|
2023-03-02 16:46:02 +01:00
|
|
|
func initLogger() logf.Logger {
|
2023-03-01 12:19:57 +01:00
|
|
|
loggOpts := logg.LoggOpts{}
|
2023-02-20 10:56:30 +01:00
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
if debugFlag {
|
2023-03-01 12:19:57 +01:00
|
|
|
loggOpts.Color = true
|
2023-02-20 10:56:30 +01:00
|
|
|
loggOpts.Caller = true
|
|
|
|
loggOpts.Debug = true
|
|
|
|
}
|
|
|
|
|
|
|
|
return logg.NewLogg(loggOpts)
|
|
|
|
}
|
|
|
|
|
2023-02-15 08:05:43 +01:00
|
|
|
// Load config file.
|
2023-03-02 16:46:02 +01:00
|
|
|
func initConfig() *koanf.Koanf {
|
2023-02-15 08:05:43 +01:00
|
|
|
var (
|
|
|
|
ko = koanf.New(".")
|
|
|
|
)
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
confFile := file.Provider(confFlag)
|
2023-02-15 08:05:43 +01:00
|
|
|
if err := ko.Load(confFile, toml.Parser()); err != nil {
|
2023-03-06 09:18:41 +01:00
|
|
|
lo.Fatal("init: could not load config file", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-02 10:12:39 +01:00
|
|
|
if err := ko.Load(env.Provider("CUSTODIAL_", ".", func(s string) string {
|
2023-03-01 18:13:23 +01:00
|
|
|
return strings.ReplaceAll(strings.ToLower(
|
2023-03-02 10:12:39 +01:00
|
|
|
strings.TrimPrefix(s, "CUSTODIAL_")), "__", ".")
|
2023-02-15 08:05:43 +01:00
|
|
|
}), nil); err != nil {
|
2023-03-06 09:18:41 +01:00
|
|
|
lo.Fatal("init: could not override config from env vars", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
if debugFlag {
|
|
|
|
ko.Print()
|
|
|
|
}
|
2023-03-02 10:12:39 +01:00
|
|
|
|
2023-02-15 08:05:43 +01:00
|
|
|
return ko
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load Celo chain provider.
|
2023-03-02 16:46:02 +01:00
|
|
|
func initCeloProvider() *celoutils.Provider {
|
2023-02-20 10:56:30 +01:00
|
|
|
providerOpts := celoutils.ProviderOpts{
|
2023-02-15 08:05:43 +01:00
|
|
|
RpcEndpoint: ko.MustString("chain.rpc_endpoint"),
|
|
|
|
}
|
|
|
|
|
|
|
|
if ko.Bool("chain.testnet") {
|
2023-02-20 10:56:30 +01:00
|
|
|
providerOpts.ChainId = celoutils.TestnetChainId
|
2023-02-15 08:05:43 +01:00
|
|
|
} else {
|
2023-02-20 10:56:30 +01:00
|
|
|
providerOpts.ChainId = celoutils.MainnetChainId
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-02-20 10:56:30 +01:00
|
|
|
provider, err := celoutils.NewProvider(providerOpts)
|
2023-02-15 08:05:43 +01:00
|
|
|
if err != nil {
|
2023-03-02 16:46:02 +01:00
|
|
|
lo.Fatal("init: critical error loading chain provider", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
return provider
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Load separate redis connection for the tasker on a reserved db namespace.
|
2023-03-02 16:46:02 +01:00
|
|
|
func initAsynqRedisPool() *redis.RedisPool {
|
2023-02-15 08:05:43 +01:00
|
|
|
poolOpts := redis.RedisPoolOpts{
|
|
|
|
DSN: ko.MustString("asynq.dsn"),
|
|
|
|
MinIdleConns: ko.MustInt("redis.min_idle_conn"),
|
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
pool, err := redis.NewRedisPool(context.Background(), poolOpts)
|
2023-02-15 08:05:43 +01:00
|
|
|
if err != nil {
|
2023-03-02 16:46:02 +01:00
|
|
|
lo.Fatal("init: critical error connecting to asynq redis db", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
return pool
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Common redis connection on a different db namespace from the takser.
|
2023-03-02 16:46:02 +01:00
|
|
|
func initCommonRedisPool() *redis.RedisPool {
|
2023-02-15 08:05:43 +01:00
|
|
|
poolOpts := redis.RedisPoolOpts{
|
|
|
|
DSN: ko.MustString("redis.dsn"),
|
|
|
|
MinIdleConns: ko.MustInt("redis.min_idle_conn"),
|
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
pool, err := redis.NewRedisPool(context.Background(), poolOpts)
|
2023-02-15 08:05:43 +01:00
|
|
|
if err != nil {
|
2023-03-02 16:46:02 +01:00
|
|
|
lo.Fatal("init: critical error connecting to common redis db", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-02 16:46:02 +01:00
|
|
|
return pool
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Load redis backed noncestore.
|
2023-04-13 12:38:23 +02:00
|
|
|
func initRedisNoncestore(redisPool *redis.RedisPool, chainProvider *celoutils.Provider, store store.Store) nonce.Noncestore {
|
2023-02-15 08:05:43 +01:00
|
|
|
return nonce.NewRedisNoncestore(nonce.Opts{
|
2023-04-13 12:38:23 +02:00
|
|
|
ChainProvider: chainProvider,
|
|
|
|
RedisPool: redisPool,
|
|
|
|
Store: store,
|
2023-02-15 08:05:43 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load global lock provider.
|
|
|
|
func initLockProvider(redisPool redislock.RedisClient) *redislock.Client {
|
|
|
|
return redislock.New(redisPool)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load tasker client.
|
|
|
|
func initTaskerClient(redisPool *redis.RedisPool) *tasker.TaskerClient {
|
|
|
|
return tasker.NewTaskerClient(tasker.TaskerClientOpts{
|
2023-03-06 09:18:41 +01:00
|
|
|
RedisPool: redisPool,
|
2023-02-15 08:05:43 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-03-06 09:18:41 +01:00
|
|
|
// Load Postgres store.
|
2023-04-11 12:14:49 +02:00
|
|
|
func initPgStore() store.Store {
|
|
|
|
store, err := store.NewPgStore(store.Opts{
|
|
|
|
DSN: ko.MustString("postgres.dsn"),
|
|
|
|
MigrationsFolderPath: migrationsFolderFlag,
|
|
|
|
QueriesFolderPath: queriesFlag,
|
2023-02-15 08:05:43 +01:00
|
|
|
})
|
2023-04-11 12:14:49 +02:00
|
|
|
if err != nil {
|
|
|
|
lo.Fatal("init: critical error loading Postgres store", "error", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return store
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-06 09:18:41 +01:00
|
|
|
// Init JetStream context for both pub/sub.
|
|
|
|
func initJetStream() (*nats.Conn, nats.JetStreamContext) {
|
|
|
|
natsConn, err := nats.Connect(ko.MustString("jetstream.endpoint"))
|
|
|
|
if err != nil {
|
|
|
|
lo.Fatal("init: critical error connecting to NATS", "error", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
js, err := natsConn.JetStream()
|
|
|
|
if err != nil {
|
|
|
|
lo.Fatal("init: bad JetStream opts", "error", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return natsConn, js
|
|
|
|
}
|
|
|
|
|
|
|
|
func initSub(natsConn *nats.Conn, jsCtx nats.JetStreamContext, cu *custodial.Custodial) *sub.Sub {
|
|
|
|
sub, err := sub.NewSub(sub.SubOpts{
|
|
|
|
CustodialContainer: cu,
|
|
|
|
JsCtx: jsCtx,
|
|
|
|
Logg: lo,
|
|
|
|
NatsConn: natsConn,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
lo.Fatal("init: critical error bootstrapping sub", "error", err)
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
2023-03-06 09:18:41 +01:00
|
|
|
return sub
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|