synapsecns/sanguine

View on GitHub
agents/config/agent_config.go

Summary

Maintainability
A
1 hr
Test Coverage
package config

import (
    "context"
    "fmt"
    "os"
    "path/filepath"

    "github.com/synapsecns/sanguine/ethergo/signer/config"
    submitterConfig "github.com/synapsecns/sanguine/ethergo/submitter/config"

    "github.com/davecgh/go-spew/spew"
    "github.com/jftuga/ellipsis"
    "gopkg.in/yaml.v2"
)

// AgentConfig is used for configuring the guard.
type AgentConfig struct {
    // DBConfig is the database configuration.
    DBConfig DBConfig `yaml:"db_config"`
    // ScribeConfig is the scribe configuration.
    ScribeConfig ScribeConfig `yaml:"scribe_config"`
    // Domains stores all the domains
    Domains DomainConfigs `yaml:"domains"`
    // DomainID is the domain of the chain that this agent is assigned to.
    //     For Guards, it is 0 meaning all domains.
    //     For Notaries, it will be a specific domain greater than 0.
    DomainID uint32 `yaml:"domain_id"`
    // SummitDomainID is the domain of the chain that has the Summit contract (ie SYN chain).
    SummitDomainID uint32 `yaml:"summit_domain_id"`
    // UnbondedSigner contains the unbonded signer config for agents
    // (this is signer used to submit transactions)
    UnbondedSigner config.SignerConfig `yaml:"unbonded_signer"`
    // BondedSigner contains the bonded signer config for agents
    BondedSigner config.SignerConfig `yaml:"bonded_signer"`
    // RefreshIntervalSeconds is the refresh interval in seconds
    RefreshIntervalSeconds uint32 `yaml:"refresh_interval_seconds,omitempty"`
    // BaseOmnirpcURL is the base url for omnirpc.
    // The format is "https://omnirpc.url". Notice the lack of "confirmations" on the URL
    // in comparison to what `Scribe` uses.
    BaseOmnirpcURL string `yaml:"base_omnirpc_url"`
    // DBPrefix is the prefix for the tables in the database. This is only to be used with mysql.
    DBPrefix string `yaml:"db_prefix"`
    // SubmitterConfig is the config for the submitter.
    SubmitterConfig submitterConfig.Config `yaml:"submitter_config"`
    // MaxRetrySeconds is the maximum number of seconds to retry an RPC call (not a transaction).
    MaxRetrySeconds uint32 `yaml:"max_retry_seconds"`
}

// IsValid makes sure the config is valid. This is done by calling IsValid() on each
// submodule. If any method returns an error that is returned here and the entirety
// of IsValid returns false. Any warnings are logged by the submodules respective loggers.
func (a *AgentConfig) IsValid(ctx context.Context) (ok bool, err error) {
    if int64(a.RefreshIntervalSeconds) == int64(0) {
        return false, fmt.Errorf("refresh_interval_seconds cannot be 0")
    }

    if ok, err = a.Domains.IsValid(ctx); !ok {
        return false, err
    }

    if a.BaseOmnirpcURL == "" {
        return false, fmt.Errorf("rpc url cannot be empty")
    }

    hasAssignedDomain := (a.DomainID == uint32(0))
    hasSummitDomainID := false

    for _, cfg := range a.Domains {
        if !hasAssignedDomain {
            if cfg.DomainID == a.DomainID {
                hasAssignedDomain = true
            }
        }

        if !hasSummitDomainID {
            if cfg.DomainID == a.SummitDomainID {
                hasSummitDomainID = true
                if cfg.SummitAddress == "" {
                    return false, fmt.Errorf("field SummitAddress: %w", ErrRequiredField)
                }
            }
        }
    }

    return true, nil
}

// Encode gets the encoded config.yaml file.
func (a AgentConfig) Encode() ([]byte, error) {
    output, err := yaml.Marshal(&a)
    if err != nil {
        return nil, fmt.Errorf("could not unmarshall config %s: %w", ellipsis.Shorten(spew.Sdump(a), 20), err)
    }
    return output, nil
}

// DecodeAgentConfig parses in a config from a file.
func DecodeAgentConfig(filePath string) (a AgentConfig, err error) {
    input, err := os.ReadFile(filepath.Clean(filePath))
    if err != nil {
        return AgentConfig{}, fmt.Errorf("failed to read file: %w", err)
    }
    err = yaml.Unmarshal(input, &a)
    if err != nil {
        return AgentConfig{}, fmt.Errorf("could not unmarshall config %s: %w", ellipsis.Shorten(string(input), 30), err)
    }
    return a, nil
}