Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion integration-tests/txm/txm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

test_utils "github.com/smartcontractkit/chainlink-ton/deployment/utils"

commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/loop"
cldf_ton "github.com/smartcontractkit/chainlink-deployments-framework/chain/ton"
Expand Down Expand Up @@ -49,7 +50,7 @@ func TestTxmLocal(t *testing.T) {
require.NotNil(t, keystore)

config := txm.DefaultConfigSet
config.ConfirmPollSecs = 2
config.ConfirmPollInterval = commonconfig.MustNewDuration(2 * time.Second)

runTxmTest(t, logger, config, tonChain, keystore, 5)
}
Expand Down
19 changes: 15 additions & 4 deletions pkg/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (

"github.com/smartcontractkit/chainlink-common/pkg/config"
relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types"

"github.com/smartcontractkit/chainlink-ton/pkg/logpoller"
"github.com/smartcontractkit/chainlink-ton/pkg/txm"
)

type TOMLConfig struct {
Expand Down Expand Up @@ -36,25 +39,29 @@ func NewDecodedTOMLConfig(rawConfig string) (*TOMLConfig, error) {
return &TOMLConfig{}, fmt.Errorf("failed to decode config toml: %w:\n\t%s", err, rawConfig)
}

// Apply defaults before validation
cfg.SetDefaults()

if err := cfg.ValidateConfig(); err != nil {
return &TOMLConfig{}, fmt.Errorf("invalid ton config: %w", err)
}

if !cfg.IsEnabled() {
return &TOMLConfig{}, fmt.Errorf("cannot create new chain with ID %s: config is disabled", cfg.ChainID)
}

cfg.SetDefaults()
return &cfg, nil
}

func (c *TOMLConfig) SetDefaults() {
if c.TransactionManager == nil {
c.TransactionManager = DefaultConfigSet.TransactionManager
c.TransactionManager = &txm.Config{}
}
c.TransactionManager.ApplyDefaults()

if c.LogPoller == nil {
c.LogPoller = DefaultConfigSet.LogPoller
c.LogPoller = &logpoller.Config{}
}
c.LogPoller.ApplyDefaults()

// Set network name full defaults
if c.NetworkNameFull == "" {
Expand Down Expand Up @@ -90,6 +97,7 @@ func NodeStatus(n *Node, id string) (relaytypes.NodeStatus, error) {
}

func setFromChain(c, f *Chain) {
c.ClientTTL = f.ClientTTL
if f.TransactionManager != nil {
c.TransactionManager = f.TransactionManager
}
Expand All @@ -111,6 +119,9 @@ func (c *TOMLConfig) ValidateConfig() (err error) {
}
}

err = errors.Join(err, c.TransactionManager.ValidateConfig())
err = errors.Join(err, c.LogPoller.ValidateConfig())

return
}

Expand Down
144 changes: 102 additions & 42 deletions pkg/config/toml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ ChainID = '-3'
NetworkName = 'testnet'

[TransactionManager]
BroadcastChanSize = 200
SendRetryDelay = '5s'
CleanupIntervalMins = 15
BroadcastChanSize = 101
ConfirmPollInterval = '9s'
SendRetryDelay = '8s'
MaxSendRetryAttempts = 7
TxExpiration = '6h'
CleanupInterval = '15m'

[LogPoller]
PollPeriod = '10s'
PageSize = 50
BlockTime = '2500ms'
LogPollerStartingLookback = '1h'
BlockTime = '1200ms'

[[Nodes]]
Name = 'ton-testnet-1'
Expand All @@ -44,14 +48,18 @@ URL = 'http://localhost:8081'

// Verify config sections exist and key fields parse correctly
require.NotNil(t, cfg.TransactionManager)
assert.Equal(t, uint(200), cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, 5*time.Second, cfg.TransactionManager.SendRetryDelay.Duration())
assert.Equal(t, uint(15), cfg.TransactionManager.CleanupIntervalMins)
assert.Equal(t, uint(101), cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, 9*time.Second, cfg.TransactionManager.ConfirmPollInterval.Duration())
assert.Equal(t, 8*time.Second, cfg.TransactionManager.SendRetryDelay.Duration())
assert.Equal(t, uint(7), cfg.TransactionManager.MaxSendRetryAttempts)
assert.Equal(t, 6*time.Hour, cfg.TransactionManager.TxExpiration.Duration())
assert.Equal(t, 15*time.Minute, cfg.TransactionManager.CleanupInterval.Duration())

require.NotNil(t, cfg.LogPoller)
assert.Equal(t, uint32(50), cfg.LogPoller.PageSize)
assert.Equal(t, 10*time.Second, cfg.LogPoller.PollPeriod.Duration())
assert.Equal(t, 2500*time.Millisecond, cfg.LogPoller.BlockTime.Duration())
assert.Equal(t, 1*time.Hour, cfg.LogPoller.LogPollerStartingLookback.Duration())
assert.Equal(t, 1200*time.Millisecond, cfg.LogPoller.BlockTime.Duration())

require.Len(t, cfg.Nodes, 1)
assert.Equal(t, "ton-testnet-1", *cfg.Nodes[0].Name)
Expand All @@ -71,12 +79,23 @@ URL = 'http://localhost:8081'
cfg, err := NewDecodedTOMLConfig(tomlStr)
require.NoError(t, err)

// Missing sections should get full defaults
assert.Equal(t, DefaultConfigSet.TransactionManager, cfg.TransactionManager)
assert.Equal(t, DefaultConfigSet.LogPoller, cfg.LogPoller)
// Missing sections should get full defaults - verify field by field
require.NotNil(t, cfg.TransactionManager)
assert.Equal(t, txm.DefaultConfigSet.BroadcastChanSize, cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, txm.DefaultConfigSet.ConfirmPollInterval, cfg.TransactionManager.ConfirmPollInterval)
assert.Equal(t, txm.DefaultConfigSet.SendRetryDelay, cfg.TransactionManager.SendRetryDelay)
assert.Equal(t, txm.DefaultConfigSet.MaxSendRetryAttempts, cfg.TransactionManager.MaxSendRetryAttempts)
assert.Equal(t, txm.DefaultConfigSet.TxExpiration, cfg.TransactionManager.TxExpiration)
assert.Equal(t, txm.DefaultConfigSet.CleanupInterval, cfg.TransactionManager.CleanupInterval)

require.NotNil(t, cfg.LogPoller)
assert.Equal(t, logpoller.DefaultConfigSet.PollPeriod, cfg.LogPoller.PollPeriod)
assert.Equal(t, logpoller.DefaultConfigSet.PageSize, cfg.LogPoller.PageSize)
assert.Equal(t, logpoller.DefaultConfigSet.LogPollerStartingLookback, cfg.LogPoller.LogPollerStartingLookback)
assert.Equal(t, logpoller.DefaultConfigSet.BlockTime, cfg.LogPoller.BlockTime)
})

t.Run("partial configs get zero values", func(t *testing.T) {
t.Run("partial configs get field-by-field defaults", func(t *testing.T) {
tomlStr := `
Enabled = true
ChainID = '-3'
Expand All @@ -100,11 +119,16 @@ URL = 'http://localhost:8081'
assert.Equal(t, uint(300), cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, uint32(200), cfg.LogPoller.PageSize)

// Missing fields get zero values (Aptos behavior)
assert.Equal(t, uint(0), cfg.TransactionManager.ConfirmPollSecs)
assert.Equal(t, uint(0), cfg.TransactionManager.CleanupIntervalMins)
assert.Nil(t, cfg.TransactionManager.SendRetryDelay)
assert.False(t, cfg.TransactionManager.StickyNodeContextEnabled)
// Missing fields get defaults applied (field-by-field)
assert.Equal(t, txm.DefaultConfigSet.ConfirmPollInterval, cfg.TransactionManager.ConfirmPollInterval)
assert.Equal(t, txm.DefaultConfigSet.SendRetryDelay, cfg.TransactionManager.SendRetryDelay)
assert.Equal(t, txm.DefaultConfigSet.MaxSendRetryAttempts, cfg.TransactionManager.MaxSendRetryAttempts)
assert.Equal(t, txm.DefaultConfigSet.TxExpiration, cfg.TransactionManager.TxExpiration)
assert.Equal(t, txm.DefaultConfigSet.CleanupInterval, cfg.TransactionManager.CleanupInterval)

assert.Equal(t, logpoller.DefaultConfigSet.PollPeriod, cfg.LogPoller.PollPeriod)
assert.Equal(t, logpoller.DefaultConfigSet.LogPollerStartingLookback, cfg.LogPoller.LogPollerStartingLookback)
assert.Equal(t, logpoller.DefaultConfigSet.BlockTime, cfg.LogPoller.BlockTime)
})

t.Run("validation errors", func(t *testing.T) {
Expand All @@ -123,31 +147,67 @@ URL = 'http://localhost:8081'
}

func TestTOMLConfig_SetDefaults(t *testing.T) {
// Test nil configs get defaults
cfg := &TOMLConfig{NetworkName: "testnet"}
cfg.SetDefaults()

assert.Equal(t, DefaultConfigSet.TransactionManager, cfg.TransactionManager)
assert.Equal(t, DefaultConfigSet.LogPoller, cfg.LogPoller)
assert.Equal(t, "ton-testnet", cfg.NetworkNameFull)

// Test existing configs preserved
customTxm := &txm.Config{BroadcastChanSize: 999}
customLP := &logpoller.Config{PageSize: 777}

cfg2 := &TOMLConfig{
NetworkName: "mainnet",
NetworkNameFull: "custom-name",
Chain: Chain{
TransactionManager: customTxm,
LogPoller: customLP,
},
}
cfg2.SetDefaults()

assert.Equal(t, customTxm, cfg2.TransactionManager)
assert.Equal(t, customLP, cfg2.LogPoller)
assert.Equal(t, "custom-name", cfg2.NetworkNameFull)
t.Run("nil configs get full defaults", func(t *testing.T) {
cfg := &TOMLConfig{NetworkName: "testnet"}
cfg.SetDefaults()

// Verify all TransactionManager fields got defaults
require.NotNil(t, cfg.TransactionManager)
assert.Equal(t, txm.DefaultConfigSet.BroadcastChanSize, cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, txm.DefaultConfigSet.ConfirmPollInterval, cfg.TransactionManager.ConfirmPollInterval)
assert.Equal(t, txm.DefaultConfigSet.SendRetryDelay, cfg.TransactionManager.SendRetryDelay)
assert.Equal(t, txm.DefaultConfigSet.MaxSendRetryAttempts, cfg.TransactionManager.MaxSendRetryAttempts)
assert.Equal(t, txm.DefaultConfigSet.TxExpiration, cfg.TransactionManager.TxExpiration)
assert.Equal(t, txm.DefaultConfigSet.CleanupInterval, cfg.TransactionManager.CleanupInterval)

// Verify all LogPoller fields got defaults
require.NotNil(t, cfg.LogPoller)
assert.Equal(t, logpoller.DefaultConfigSet.PollPeriod, cfg.LogPoller.PollPeriod)
assert.Equal(t, logpoller.DefaultConfigSet.PageSize, cfg.LogPoller.PageSize)
assert.Equal(t, logpoller.DefaultConfigSet.LogPollerStartingLookback, cfg.LogPoller.LogPollerStartingLookback)
assert.Equal(t, logpoller.DefaultConfigSet.BlockTime, cfg.LogPoller.BlockTime)

assert.Equal(t, "ton-testnet", cfg.NetworkNameFull)
})

t.Run("partial configs get field-by-field defaults applied", func(t *testing.T) {
// Create configs with only some fields set
customTxm := &txm.Config{
BroadcastChanSize: 999,
SendRetryDelay: config.MustNewDuration(10 * time.Second),
}
customLP := &logpoller.Config{
PageSize: 777,
BlockTime: config.MustNewDuration(3 * time.Second),
}

cfg := &TOMLConfig{
NetworkName: "mainnet",
NetworkNameFull: "custom-name",
Chain: Chain{
TransactionManager: customTxm,
LogPoller: customLP,
},
}
cfg.SetDefaults()

// Verify custom values are preserved
assert.Equal(t, uint(999), cfg.TransactionManager.BroadcastChanSize)
assert.Equal(t, 10*time.Second, cfg.TransactionManager.SendRetryDelay.Duration())
assert.Equal(t, uint32(777), cfg.LogPoller.PageSize)
assert.Equal(t, 3*time.Second, cfg.LogPoller.BlockTime.Duration())

// Verify missing fields got defaults
assert.Equal(t, txm.DefaultConfigSet.ConfirmPollInterval, cfg.TransactionManager.ConfirmPollInterval)
assert.Equal(t, txm.DefaultConfigSet.MaxSendRetryAttempts, cfg.TransactionManager.MaxSendRetryAttempts)
assert.Equal(t, txm.DefaultConfigSet.TxExpiration, cfg.TransactionManager.TxExpiration)
assert.Equal(t, txm.DefaultConfigSet.CleanupInterval, cfg.TransactionManager.CleanupInterval)

assert.Equal(t, logpoller.DefaultConfigSet.PollPeriod, cfg.LogPoller.PollPeriod)
assert.Equal(t, logpoller.DefaultConfigSet.LogPollerStartingLookback, cfg.LogPoller.LogPollerStartingLookback)

assert.Equal(t, "custom-name", cfg.NetworkNameFull)
})
}

func TestSetFromChain(t *testing.T) {
Expand Down
22 changes: 22 additions & 0 deletions pkg/logpoller/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/config"
)

// Config holds the configuration for the log poller.
// NOTE: when adding new fields, please update ApplyDefaults, DefaultConfigSet, and ValidateConfig accordingly.
// Also check toml_test.go TestNewDecodedTOMLConfig() to ensure new fields are tested there.
type Config struct {
PollPeriod *config.Duration
PageSize uint32
Expand All @@ -19,3 +22,22 @@ var DefaultConfigSet = Config{
LogPollerStartingLookback: config.MustNewDuration(24 * time.Hour), // Look back 24 hours on startup
BlockTime: config.MustNewDuration(2500 * time.Millisecond), // TON block time is approximately 2.5 seconds (2500ms)
}

func (c *Config) ApplyDefaults() {
if c.PollPeriod == nil {
c.PollPeriod = DefaultConfigSet.PollPeriod
}
if c.PageSize == 0 {
c.PageSize = DefaultConfigSet.PageSize
}
if c.LogPollerStartingLookback == nil {
c.LogPollerStartingLookback = DefaultConfigSet.LogPollerStartingLookback
}
if c.BlockTime == nil {
c.BlockTime = DefaultConfigSet.BlockTime
}
}

func (c *Config) ValidateConfig() (err error) {
return nil
}
58 changes: 58 additions & 0 deletions pkg/logpoller/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package logpoller

import (
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/smartcontractkit/chainlink-common/pkg/config"
)

func TestConfig_ApplyDefaults(t *testing.T) {
t.Run("applies all defaults to empty config", func(t *testing.T) {
cfg := &Config{}
cfg.ApplyDefaults()

assert.Equal(t, DefaultConfigSet.PollPeriod, cfg.PollPeriod)
assert.Equal(t, DefaultConfigSet.PageSize, cfg.PageSize)
assert.Equal(t, DefaultConfigSet.LogPollerStartingLookback, cfg.LogPollerStartingLookback)
assert.Equal(t, DefaultConfigSet.BlockTime, cfg.BlockTime)
})

t.Run("preserves custom values and applies defaults to missing fields", func(t *testing.T) {
customPageSize := uint32(250)
customBlockTime := config.MustNewDuration(13 * time.Second)

cfg := &Config{
PageSize: customPageSize,
BlockTime: customBlockTime,
}
cfg.ApplyDefaults()

// Custom values
assert.Equal(t, customPageSize, cfg.PageSize)
assert.Equal(t, customBlockTime, cfg.BlockTime)

// Defaults
assert.Equal(t, DefaultConfigSet.PollPeriod, cfg.PollPeriod)
assert.Equal(t, DefaultConfigSet.LogPollerStartingLookback, cfg.LogPollerStartingLookback)
})

t.Run("all fields set - nothing should change", func(t *testing.T) {
customConfig := Config{
PollPeriod: config.MustNewDuration(1 * time.Second),
PageSize: 50,
LogPollerStartingLookback: config.MustNewDuration(48 * time.Hour),
BlockTime: config.MustNewDuration(1 * time.Second),
}

original := customConfig
customConfig.ApplyDefaults()

assert.Equal(t, original.PollPeriod, customConfig.PollPeriod)
assert.Equal(t, original.PageSize, customConfig.PageSize)
assert.Equal(t, original.LogPollerStartingLookback, customConfig.LogPollerStartingLookback)
assert.Equal(t, original.BlockTime, customConfig.BlockTime)
})
}
Loading
Loading