Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ require (
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260423135514-5b1a7565a99c
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260423135514-5b1a7565a99c
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260326111235-8c09d1a4491f
github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3
github.com/smartcontractkit/chainlink-protos/svr v1.2.0
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e
github.com/smartcontractkit/libocr v0.0.0-20260130195252-6e18e2a30acc
Expand Down
4 changes: 2 additions & 2 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 13 additions & 7 deletions pkg/txm/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,20 @@ func (m *txmMetrics) EmitTxMessage(ctx context.Context, txHash common.Hash, from
toAddress = tx.ToAddress
}

var dualBroadcastParams *string
if meta != nil && meta.DualBroadcast != nil && *meta.DualBroadcast {
dualBroadcastParams = meta.DualBroadcastParams
}

message := &svrv1.TxMessage{
Hash: txHash.String(),
FromAddress: fromAddress.String(),
ToAddress: toAddress.String(),
Nonce: strconv.FormatUint(*tx.Nonce, 10),
CreatedAt: time.Now().UnixMicro(),
ChainId: m.chainID.String(),
FeedAddress: destAddress,
Hash: txHash.String(),
FromAddress: fromAddress.String(),
ToAddress: toAddress.String(),
Nonce: strconv.FormatUint(*tx.Nonce, 10),
CreatedAt: time.Now().UnixMicro(),
ChainId: m.chainID.String(),
FeedAddress: destAddress,
DualBroadcastParams: dualBroadcastParams,
}

messageBytes, err := proto.Marshal(message)
Expand Down
81 changes: 81 additions & 0 deletions pkg/txm/metrics_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package txm

import (
"encoding/json"
"strconv"
"testing"

Expand All @@ -11,6 +12,7 @@ import (

"github.com/smartcontractkit/chainlink-common/pkg/beholder/beholdertest"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
"github.com/smartcontractkit/chainlink-evm/pkg/testutils"
"github.com/smartcontractkit/chainlink-evm/pkg/txm/types"
svrv1 "github.com/smartcontractkit/chainlink-protos/svr/v1"
Expand Down Expand Up @@ -116,6 +118,85 @@ func TestEmitTxMessage(t *testing.T) {
assert.Equal(t, expectedChain.String(), actualMessage.ChainId)
assert.Equal(t, "", actualMessage.FeedAddress)
})

t.Run("populates dual_broadcast_params when tx is a dual-broadcast secondary tx", func(t *testing.T) {
// GIVEN
ctx := t.Context()
beholderTester := beholdertest.NewObserver(t)

toAddress := testutils.NewAddress()
fromAddress := testutils.NewAddress()
expectedNonce := uint64(7)
expectedChain := testutils.FixtureChainID
expectedParams := "hint=calldata&hint=logs&builder=flashbots"
isDualBroadcast := true

metaBytes, err := json.Marshal(types.TxMeta{
DualBroadcast: &isDualBroadcast,
DualBroadcastParams: &expectedParams,
})
require.NoError(t, err)
meta := sqlutil.JSON(metaBytes)

txmMetrics := NewTxmMetrics(logger.Test(t), expectedChain)

tx := &types.Transaction{
IsPurgeable: false,
FromAddress: fromAddress,
ToAddress: toAddress,
Nonce: &expectedNonce,
Meta: &meta,
}

// WHEN
err = txmMetrics.EmitTxMessage(ctx, common.Hash{}, fromAddress, tx)
require.NoError(t, err)

// THEN
messages := beholderTester.Messages(t)
assert.Len(t, messages, 1)

var actualMessage svrv1.TxMessage
err = proto.Unmarshal(messages[0].Body, &actualMessage)
require.NoError(t, err)

require.NotNil(t, actualMessage.DualBroadcastParams)
assert.Equal(t, expectedParams, *actualMessage.DualBroadcastParams)
})

t.Run("does not set dual_broadcast_params for a primary (non-dual-broadcast) tx", func(t *testing.T) {
// GIVEN
ctx := t.Context()
beholderTester := beholdertest.NewObserver(t)

toAddress := testutils.NewAddress()
fromAddress := testutils.NewAddress()
expectedNonce := uint64(3)
expectedChain := testutils.FixtureChainID

txmMetrics := NewTxmMetrics(logger.Test(t), expectedChain)

tx := &types.Transaction{
IsPurgeable: false,
FromAddress: fromAddress,
ToAddress: toAddress,
Nonce: &expectedNonce,
}

// WHEN
err := txmMetrics.EmitTxMessage(ctx, common.Hash{}, fromAddress, tx)
require.NoError(t, err)

// THEN
messages := beholderTester.Messages(t)
assert.Len(t, messages, 1)

var actualMessage svrv1.TxMessage
err = proto.Unmarshal(messages[0].Body, &actualMessage)
require.NoError(t, err)

assert.Nil(t, actualMessage.DualBroadcastParams)
})
}

func TestReachedMaxAttempts(t *testing.T) {
Expand Down
Loading