Skip to content
Merged
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
61 changes: 61 additions & 0 deletions catalog/changesets/delete_address_ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package changesets

import (
"errors"
"fmt"

cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
cldfops "github.com/smartcontractkit/chainlink-deployments-framework/operations"

"github.com/smartcontractkit/cld-changesets/catalog/operations"
)

// DeleteAddressRefChangeset deletes address ref entries from the Catalog service.
type DeleteAddressRefChangeset struct{}

type DeleteAddressRefChangesetInput struct {
AddressRefKeys []cldfdatastore.AddressRefKey `json:"addressRefKeys"`
}

// VerifyPreconditions ensures the input is valid.
func (DeleteAddressRefChangeset) VerifyPreconditions(e cldf.Environment, input DeleteAddressRefChangesetInput) error {
if len(input.AddressRefKeys) == 0 {
return errors.New("missing address ref keys input")
}
if e.DataStore == nil {
return errors.New("missing datastore in environment")
}

for _, key := range input.AddressRefKeys {
_, err := e.DataStore.Addresses().Get(key)
if err != nil {
if errors.Is(err, cldfdatastore.ErrAddressRefNotFound) {
return fmt.Errorf("address ref entry for chain selector %v, type %v, version %v and qualifier %q does not exist",
key.ChainSelector(), key.Type(), key.Version(), key.Qualifier())
}

return fmt.Errorf("failed to retrieve address ref entry for chain selector %v, type %v, version %v and qualifier %q: %w",
key.ChainSelector(), key.Type(), key.Version(), key.Qualifier(), err)
}
}

return nil
}

// Apply executes the changeset, staging the address refs to be deleted from the Catalog service of local datastore files.
func (DeleteAddressRefChangeset) Apply(e cldf.Environment, input DeleteAddressRefChangesetInput) (cldf.ChangesetOutput, error) {
deps := operations.DeleteAddressRefDeps{DataStore: e.DataStore}
opInput := operations.DeleteAddressRefInput{AddressRefKeys: input.AddressRefKeys}

report, err := cldfops.ExecuteOperation(e.OperationsBundle, operations.DeleteAddressRefOp, deps, opInput)
out := cldf.ChangesetOutput{
DataStore: report.Output.DataStore,
Reports: []cldfops.Report[any, any]{report.ToGenericReport()},
}
if err != nil {
return out, err
}

return out, nil
}
121 changes: 121 additions & 0 deletions catalog/changesets/detele_address_ref_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package changesets

import (
"fmt"
"testing"

"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/require"

cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
cldfoperations "github.com/smartcontractkit/chainlink-deployments-framework/operations"
cldflogger "github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"
)

func TestDeleteAddressRefChangeset_VerifyPreconditions(t *testing.T) {
t.Parallel()

version := semver.MustParse("1.0.0")
addressRef1 := cldfdatastore.AddressRef{Address: "0x01", ChainSelector: 1234, Type: "MyContract", Version: version, Qualifier: "q1"}
addressRef2 := cldfdatastore.AddressRef{Address: "0x02", ChainSelector: 1234, Type: "MyContract", Version: version, Qualifier: "q1"}

tests := []struct {
name string
env cldf.Environment
input DeleteAddressRefChangesetInput
wantErr string
}{
{
name: "success: valid preconditions",
env: cldf.Environment{
DataStore: testDataStoreWithAddressRefs(t, addressRef1).Seal(),
},
input: DeleteAddressRefChangesetInput{
AddressRefKeys: []cldfdatastore.AddressRefKey{addressRef1.Key(), addressRef2.Key()},
},
},
{
name: "failure: missing datastore",
env: cldf.Environment{},
input: DeleteAddressRefChangesetInput{
AddressRefKeys: []cldfdatastore.AddressRefKey{addressRef1.Key(), addressRef2.Key()},
},
wantErr: "missing datastore in environment",
},
{
name: "failure: no address ref keys given",
env: cldf.Environment{
DataStore: cldfdatastore.NewMemoryDataStore().Seal(),
},
input: DeleteAddressRefChangesetInput{AddressRefKeys: []cldfdatastore.AddressRefKey{}},
wantErr: "missing address ref keys input",
},
{
name: "failure: address ref entry does not exist",
env: cldf.Environment{
DataStore: cldfdatastore.NewMemoryDataStore().Seal(),
},
input: DeleteAddressRefChangesetInput{AddressRefKeys: []cldfdatastore.AddressRefKey{addressRef2.Key()}},
wantErr: fmt.Sprintf("address ref entry for chain selector %v, type %v, version %v and qualifier %q does not exist", addressRef2.ChainSelector, addressRef2.Type, addressRef2.Version, addressRef2.Qualifier),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

err := DeleteAddressRefChangeset{}.VerifyPreconditions(tt.env, tt.input)
if tt.wantErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tt.wantErr)
}
})
}
}

func TestDeleteAddressRefChangeset_Apply(t *testing.T) {
t.Parallel()

version := semver.MustParse("1.0.0")
addressRef1 := cldfdatastore.AddressRef{Address: "0x01", ChainSelector: 1234, Type: "MyContract", Version: version, Qualifier: "q1"}
addressRef2 := cldfdatastore.AddressRef{Address: "0x02", ChainSelector: 5678, Type: "OtherContract", Version: version, Qualifier: "q2"}

tests := []struct {
name string
env cldf.Environment
input DeleteAddressRefChangesetInput
wantDeletedKeys []string
wantErr string
}{
{
name: "success: stages two address ref entries for deletion",
env: cldf.Environment{
DataStore: testDataStoreWithAddressRefs(t, addressRef1, addressRef2).Seal(),
OperationsBundle: cldfoperations.NewBundle(t.Context, cldflogger.Test(t), cldfoperations.NewMemoryReporter()),
},
input: DeleteAddressRefChangesetInput{
AddressRefKeys: []cldfdatastore.AddressRefKey{addressRef1.Key(), addressRef2.Key()},
},
wantDeletedKeys: []string{addressRef1.Key().String(), addressRef2.Key().String()},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

got, err := DeleteAddressRefChangeset{}.Apply(tt.env, tt.input)

if tt.wantErr == "" {
require.NoError(t, err)
require.Len(t, got.Reports, 1)
memDS := got.DataStore.(*cldfdatastore.MemoryDataStore)
require.ElementsMatch(t, tt.wantDeletedKeys, memDS.AddressRefStore.DeletedRemoteKeys)
} else {
require.ErrorContains(t, err, tt.wantErr)
}
})
}
}
49 changes: 49 additions & 0 deletions catalog/operations/delete_address_ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package operations

import (
"fmt"

"github.com/Masterminds/semver/v3"
cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldfops "github.com/smartcontractkit/chainlink-deployments-framework/operations"
)

// DeleteAddressRefDeps holds non-serializable dependencies for the DeleteAddressRefOp operation.
type DeleteAddressRefDeps struct {
DataStore cldfdatastore.DataStore
}

// DeleteAddressRefInput is the serializable input of a DeleteAddressRefOp invocation.
type DeleteAddressRefInput struct {
AddressRefKeys []cldfdatastore.AddressRefKey
}

// DeleteAddressRefOutput is the serializable output of a DeleteAddressRefOp invocation.
type DeleteAddressRefOutput struct {
DataStore cldfdatastore.MutableDataStore
}

// DeleteAddressRefOp deletes address ref entries from the Catalog service or local datastore files.
var DeleteAddressRefOp = cldfops.NewOperation(
"datastore-delete-address-ref",
semver.MustParse("1.0.0"),
"Delete address ref entries from the Catalog service or local datastore files",
func(b cldfops.Bundle, deps DeleteAddressRefDeps, input DeleteAddressRefInput) (DeleteAddressRefOutput, error) {
dataStore := cldfdatastore.NewMemoryDataStore()
err := dataStore.Merge(deps.DataStore)
if err != nil {
return DeleteAddressRefOutput{}, fmt.Errorf("failed to create memory data store: %w", err)
}

for i, key := range input.AddressRefKeys {
err = dataStore.Addresses().RemoteDelete(key)
if err != nil {
return DeleteAddressRefOutput{}, fmt.Errorf("failed to delete address ref entry %d in datastore: %w", i, err)
}
}

b.Logger.Infow("Catalog AddressRef successfully staged for deletion")

return DeleteAddressRefOutput{DataStore: dataStore}, nil
},
)
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/smartcontractkit/cld-changesets
go 1.26.2

require (
github.com/Masterminds/semver/v3 v3.4.0
github.com/Masterminds/semver/v3 v3.5.0
github.com/aptos-labs/aptos-go-sdk v1.13.0
github.com/deckarep/golang-set/v2 v2.8.0
github.com/ethereum/go-ethereum v1.17.3
Expand All @@ -17,7 +17,7 @@ require (
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc
github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc
github.com/smartcontractkit/chainlink-common v0.11.2-0.20260506120607-7f10be016c89
github.com/smartcontractkit/chainlink-deployments-framework v0.105.0
github.com/smartcontractkit/chainlink-deployments-framework v0.107.0
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171
github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828
github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0
Expand Down Expand Up @@ -239,9 +239,9 @@ require (
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260505131349-78e491b80735 // indirect
github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect
github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785 // indirect
github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4 // indirect
github.com/smartcontractkit/chainlink-protos/op-catalog v0.1.0 // indirect
github.com/smartcontractkit/chainlink-sui v0.0.0-20260429183453-39df0198aed8 // indirect
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.1 // indirect
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.3 // indirect
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 // indirect
github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260514223130-48bc90aca745 // indirect
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20260408092456-3c6369888d4a // indirect
Expand Down Expand Up @@ -317,7 +317,7 @@ require (
golang.org/x/tools v0.45.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/grpc v1.81.0 // indirect
google.golang.org/grpc v1.81.1 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY=
github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE=
github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
Expand Down Expand Up @@ -858,8 +858,8 @@ github.com/smartcontractkit/chainlink-common/keystore v1.1.0 h1:2wzySccgk2fpWusP
github.com/smartcontractkit/chainlink-common/keystore v1.1.0/go.mod h1:6JexOOhPhknQ0QMuppFIlOpm6wCp54yZMxai+tWugwY=
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg=
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY=
github.com/smartcontractkit/chainlink-deployments-framework v0.105.0 h1:Vp4EwkvxcBzgahIZdbWyCExDXLha93cS63xvwd2xwx8=
github.com/smartcontractkit/chainlink-deployments-framework v0.105.0/go.mod h1:xFLOOpIz7vqqno4YngHZlF9MKqk8rnvQa9adVElUXaE=
github.com/smartcontractkit/chainlink-deployments-framework v0.107.0 h1:7fbWOseJ2LwCc09KKfWUBzPKMwPbDit2PEagzwPlKdU=
github.com/smartcontractkit/chainlink-deployments-framework v0.107.0/go.mod h1:ubpvoLoRdru8IQHw3TFr7KthbjYpAwmiRmvvNCf2daA=
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171 h1:HY+Ekr4+E3xokyNZ0oOj0gjO7B065uqTxa6wcXJfJto=
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429160308-91a892a60171/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ=
github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4=
Expand All @@ -872,12 +872,12 @@ github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-202510021
github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY=
github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785 h1:oli+2uLU6jcrJGCuYFqk3475hiwL17SWlITWLv+tx/w=
github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785/go.mod h1:dkR2uYg9XYJuT1JASkPzWE51jjFkVb86P7a/yXe5/GM=
github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4 h1:AEnxv4HM3WD1RbQkRiFyb9cJ6YKAcqBp1CpIcFdZfuo=
github.com/smartcontractkit/chainlink-protos/op-catalog v0.0.4/go.mod h1:PjZD54vr6rIKEKQj6HNA4hllvYI/QpT+Zefj3tqkFAs=
github.com/smartcontractkit/chainlink-protos/op-catalog v0.1.0 h1:hGEJFD2X3oNIPXQbtIPxCJyg5CcKglRCYBmESS+gmeQ=
github.com/smartcontractkit/chainlink-protos/op-catalog v0.1.0/go.mod h1:PjZD54vr6rIKEKQj6HNA4hllvYI/QpT+Zefj3tqkFAs=
github.com/smartcontractkit/chainlink-sui v0.0.0-20260429183453-39df0198aed8 h1:sWpTYRucOQQ/wXbKj52UE59JMMEq2Aq5g+sMdjYzfRM=
github.com/smartcontractkit/chainlink-sui v0.0.0-20260429183453-39df0198aed8/go.mod h1:k1HSbHyPaQWPOj6lXDIAe04EuwbC5ge1nK+cpG2E8hE=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.1 h1:wZd5hIQRcQaq3FgW1lg/4ilk68Id6cxYKFNU9iTnugs=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.1/go.mod h1:wxgGfrJpzIdC1wyMJEGOfN4H4yPQTZD/DdrMRBxA0io=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.3 h1:y3dFPfouGziisDJa0JbY6DE7/JjoSCP/5aebzHcj4jA=
github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.3/go.mod h1:W+X9xaRulD8dD87QOB0njHkBKkmYxB4E0osfpe9808I=
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 h1:RwZXxdIAOyjp6cwc9Quxgr38k8r7ACz+Lxh9o/A6oH0=
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0=
github.com/smartcontractkit/chainlink-ton v1.0.5-0.20260514223130-48bc90aca745 h1:eieKLvYuzwBPh/FdbUS1gnIanI86zgWby1L10o90g4o=
Expand Down Expand Up @@ -1444,8 +1444,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw=
google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand Down
Loading