Skip to content

Commit c1e68b7

Browse files
[CLD-267]: feat: new blockchain field (#108)
As part of improving the existing design for chains to be more scalable, we are moving the specific chain code into their own package. These chains will be abstracted by a higher level field call BlockChains. This limits the exposure of Map fields externally and allow the design to scale better as we introduce more chains to the framework JIRA: https://smartcontract-it.atlassian.net/browse/CLD-267
1 parent bdddc37 commit c1e68b7

17 files changed

+968
-314
lines changed

.changeset/hot-shoes-know.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
feat: new blockchains field in environment

chain/aptos/aptos_chain.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package aptos
2+
3+
import (
4+
"github.com/aptos-labs/aptos-go-sdk"
5+
6+
chain_common "github.com/smartcontractkit/chainlink-deployments-framework/chain/internal/common"
7+
)
8+
9+
// Chain represents an Aptos chain.
10+
type Chain struct {
11+
Selector uint64
12+
13+
Client aptos.AptosRpcClient
14+
DeployerSigner aptos.TransactionSigner
15+
URL string
16+
17+
Confirm func(txHash string, opts ...any) error
18+
}
19+
20+
// ChainSelector returns the chain selector of the chain
21+
func (c Chain) ChainSelector() uint64 {
22+
return c.Selector
23+
}
24+
25+
// String returns chain name and selector "<name> (<selector>)"
26+
func (c Chain) String() string {
27+
return chain_common.ChainMetadata{Selector: c.Selector}.String()
28+
}
29+
30+
// Name returns the name of the chain
31+
func (c Chain) Name() string {
32+
return chain_common.ChainMetadata{Selector: c.Selector}.Name()
33+
}

chain/blockchain.go

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package chain
2+
3+
import (
4+
"sort"
5+
6+
chain_selectors "github.com/smartcontractkit/chain-selectors"
7+
8+
"github.com/smartcontractkit/chainlink-deployments-framework/chain/aptos"
9+
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm"
10+
"github.com/smartcontractkit/chainlink-deployments-framework/chain/solana"
11+
"github.com/smartcontractkit/chainlink-deployments-framework/chain/sui"
12+
)
13+
14+
var _ BlockChain = evm.Chain{}
15+
var _ BlockChain = solana.Chain{}
16+
var _ BlockChain = aptos.Chain{}
17+
var _ BlockChain = sui.Chain{}
18+
19+
// BlockChains represents a collection of chains.
20+
// It provides querying capabilities for different types of chains.
21+
type BlockChains struct {
22+
chains map[uint64]BlockChain
23+
}
24+
25+
// NewBlockChains initializes a new BlockChains instance
26+
func NewBlockChains(chains map[uint64]BlockChain) BlockChains {
27+
// perform a copy of chains
28+
// to avoid mutating the original map
29+
if chains == nil {
30+
chains = make(map[uint64]BlockChain)
31+
} else {
32+
newChains := make(map[uint64]BlockChain, len(chains))
33+
for k, v := range chains {
34+
newChains[k] = v
35+
}
36+
chains = newChains
37+
}
38+
39+
return BlockChains{
40+
chains: chains,
41+
}
42+
}
43+
44+
// BlockChain is an interface that represents a chain.
45+
// A chain can be an EVM chain, Solana chain Aptos chain or others.
46+
type BlockChain interface {
47+
// String returns chain name and selector "<name> (<selector>)"
48+
String() string
49+
// Name returns the name of the chain
50+
Name() string
51+
ChainSelector() uint64
52+
}
53+
54+
// EVMChains returns a map of all EVM chains with their selectors.
55+
func (b BlockChains) EVMChains() (map[uint64]evm.Chain, error) {
56+
var evmChains = make(map[uint64]evm.Chain)
57+
for selector, chain := range b.chains {
58+
c, ok := chain.(evm.Chain)
59+
if !ok {
60+
continue
61+
}
62+
evmChains[selector] = c
63+
}
64+
65+
return evmChains, nil
66+
}
67+
68+
// SolanaChains returns a map of all Solana chains with their selectors.
69+
func (b BlockChains) SolanaChains() (map[uint64]solana.Chain, error) {
70+
var solanaChains = make(map[uint64]solana.Chain)
71+
for selector, chain := range b.chains {
72+
c, ok := chain.(solana.Chain)
73+
if !ok {
74+
continue
75+
}
76+
solanaChains[selector] = c
77+
}
78+
79+
return solanaChains, nil
80+
}
81+
82+
// AptosChains returns a map of all Aptos chains with their selectors.
83+
func (b BlockChains) AptosChains() (map[uint64]aptos.Chain, error) {
84+
var aptosChains = make(map[uint64]aptos.Chain)
85+
for selector, chain := range b.chains {
86+
c, ok := chain.(aptos.Chain)
87+
if !ok {
88+
continue
89+
}
90+
aptosChains[selector] = c
91+
}
92+
93+
return aptosChains, nil
94+
}
95+
96+
// SuiChains returns a map of all Sui chains with their selectors.
97+
func (b BlockChains) SuiChains() (map[uint64]sui.Chain, error) {
98+
var suiChains = make(map[uint64]sui.Chain)
99+
for selector, chain := range b.chains {
100+
c, ok := chain.(sui.Chain)
101+
if !ok {
102+
continue
103+
}
104+
suiChains[selector] = c
105+
}
106+
107+
return suiChains, nil
108+
}
109+
110+
// ChainSelectorsOption defines a function type for configuring ChainSelectors
111+
type ChainSelectorsOption func(*chainSelectorsOptions)
112+
113+
type chainSelectorsOptions struct {
114+
family string
115+
excluding []uint64
116+
}
117+
118+
// WithFamily returns an option to filter chains by family (evm, solana, aptos)
119+
// Use constants from chain_selectors package eg WithFamily(chain_selectors.FamilySolana)
120+
func WithFamily(family string) ChainSelectorsOption {
121+
return func(o *chainSelectorsOptions) {
122+
o.family = family
123+
}
124+
}
125+
126+
// WithChainSelectorsExclusion returns an option to exclude specific chain selectors
127+
func WithChainSelectorsExclusion(chainSelectors []uint64) ChainSelectorsOption {
128+
return func(o *chainSelectorsOptions) {
129+
o.excluding = chainSelectors
130+
}
131+
}
132+
133+
// ListChainSelectors returns all chain selectors with optional filtering
134+
// Options:
135+
// - WithFamily: filter by family eg WithFamily(chain_selectors.FamilySolana)
136+
// - WithChainSelectorsExclusion: exclude specific chain selectors
137+
func (b BlockChains) ListChainSelectors(options ...ChainSelectorsOption) []uint64 {
138+
// Initialize default options
139+
opts := chainSelectorsOptions{
140+
family: "",
141+
excluding: []uint64{},
142+
}
143+
144+
// Apply all provided options
145+
for _, option := range options {
146+
option(&opts)
147+
}
148+
149+
selectors := make([]uint64, 0, len(b.chains))
150+
151+
for selector, chain := range b.chains {
152+
// Skip if in exclusion list
153+
excluded := false
154+
for _, exclude := range opts.excluding {
155+
if selector == exclude {
156+
excluded = true
157+
break
158+
}
159+
}
160+
if excluded {
161+
continue
162+
}
163+
164+
// Apply family filter if specified
165+
if opts.family != "" {
166+
switch chain.(type) {
167+
case evm.Chain:
168+
if opts.family != chain_selectors.FamilyEVM {
169+
continue
170+
}
171+
case solana.Chain:
172+
if opts.family != chain_selectors.FamilySolana {
173+
continue
174+
}
175+
case aptos.Chain:
176+
if opts.family != chain_selectors.FamilyAptos {
177+
continue
178+
}
179+
case sui.Chain:
180+
if opts.family != chain_selectors.FamilySui {
181+
continue
182+
}
183+
default:
184+
continue
185+
}
186+
}
187+
188+
selectors = append(selectors, selector)
189+
}
190+
191+
// Sort for consistent output
192+
sort.Slice(selectors, func(i, j int) bool {
193+
return selectors[i] < selectors[j]
194+
})
195+
196+
return selectors
197+
}

0 commit comments

Comments
 (0)