agents/config/domain.go
package config
import (
"context"
"fmt"
"github.com/coinbase/rosetta-sdk-go/utils"
"github.com/richardwilkes/toolbox/collection"
)
// DomainConfigs contains a map of name->domain config.
type DomainConfigs map[string]DomainConfig
// IsValid validates the domain configs by asserting no two domains appear twice
// it also calls IsValid on each individual DomainConfig.
func (d DomainConfigs) IsValid(ctx context.Context) (ok bool, err error) {
intSet := collection.NewSet[uint32]()
for _, cfg := range d {
if intSet.Contains(cfg.DomainID) {
return false, fmt.Errorf("domain id %d appears twice: %w", cfg.DomainID, ErrInvalidDomainID)
}
ok, err = cfg.IsValid(ctx)
if !ok {
return false, err
}
intSet.Add(cfg.DomainID)
}
return true, nil
}
// DomainConfig defines the config for a specific domain.
type DomainConfig struct {
// DomainID is the domain of the chain
DomainID uint32 `yaml:"domain_id"`
// Type of the chain (e.g. evm)
Type string `yaml:"type"`
// RequiredConfirmations is the number of confirmations to way
RequiredConfirmations uint32 `yaml:"required_confirmations"`
// OriginAddress gets origin contract address
OriginAddress string `yaml:"origin_address"`
// SummitAddress contains the summit address (if present)
SummitAddress string `yaml:"summit_address"`
// DestinationAddress gets destination contract address
DestinationAddress string `yaml:"destination_address"`
// LightManagerAddress gets then light manager contract address
LightManagerAddress string `yaml:"light_manager_address"`
// BondingManagerAddress gets the bonding manager contract address
BondingManagerAddress string `yaml:"bonding_manager_address"`
// LightInboxAddress gets the light inbox contract address
LightInboxAddress string `yaml:"light_inbox_address"`
// InboxAddress gets the inbox contract address
InboxAddress string `yaml:"inbox_address"`
}
// IsValid validates the domain config.
func (d DomainConfig) IsValid(_ context.Context) (ok bool, err error) {
if !utils.ContainsString(chainTypeList, d.Type) {
return false, fmt.Errorf("invalid chain type %s, %w", d.Type, ErrInvalidChainType)
}
// TODO: this might require more significant checking against a list of presets (for london/non-london etc)
if d.DomainID == 0 {
return false, fmt.Errorf("%w: cannot be 0", ErrInvalidDomainID)
}
// TODO: we should defer to chain-specific config here for verification
if d.OriginAddress == "" {
return false, fmt.Errorf("field OriginAddress: %w", ErrRequiredField)
}
if d.DestinationAddress == "" {
return false, fmt.Errorf("field DestinationAddress: %w", ErrRequiredField)
}
if d.SummitAddress == "" {
if d.LightManagerAddress == "" {
return false, fmt.Errorf("field LightManagerAddress: %w", ErrRequiredField)
}
} else {
if d.BondingManagerAddress == "" {
return false, fmt.Errorf("field BondingManagerAddress: %w", ErrRequiredField)
}
}
return true, nil
}