-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor with family specific chain selector support and added solana #70
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package chain_selectors | ||
|
||
import ( | ||
_ "embed" | ||
"fmt" | ||
"strconv" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
//go:generate go run genchains_evm.go | ||
|
||
//go:embed selectors.yml | ||
var selectorsYml []byte | ||
|
||
//go:embed test_selectors.yml | ||
var testSelectorsYml []byte | ||
|
||
type ChainDetails struct { | ||
ChainSelector uint64 `yaml:"selector"` | ||
ChainName string `yaml:"name"` | ||
} | ||
|
||
var ( | ||
evmSelectorsMap = parseYml(selectorsYml) | ||
evmTestSelectorsMap = parseYml(testSelectorsYml) | ||
evmChainIdToChainSelector = loadAllEVMSelectors() | ||
evmChainsBySelector = make(map[uint64]Chain) | ||
evmChainsByEvmChainID = make(map[uint64]Chain) | ||
) | ||
|
||
func init() { | ||
for _, ch := range ALL { | ||
evmChainsBySelector[ch.Selector] = ch | ||
evmChainsByEvmChainID[ch.EvmChainID] = ch | ||
} | ||
} | ||
|
||
func loadAllEVMSelectors() map[uint64]ChainDetails { | ||
output := make(map[uint64]ChainDetails, len(evmSelectorsMap)+len(evmTestSelectorsMap)) | ||
for k, v := range evmSelectorsMap { | ||
output[k] = v | ||
} | ||
for k, v := range evmTestSelectorsMap { | ||
output[k] = v | ||
} | ||
return output | ||
} | ||
|
||
func parseYml(ymlFile []byte) map[uint64]ChainDetails { | ||
type ymlData struct { | ||
SelectorsByEvmChainId map[uint64]ChainDetails `yaml:"selectors"` | ||
} | ||
|
||
var data ymlData | ||
err := yaml.Unmarshal(ymlFile, &data) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
return data.SelectorsByEvmChainId | ||
} | ||
|
||
func EvmChainIdToChainSelector() map[uint64]uint64 { | ||
copyMap := make(map[uint64]uint64, len(evmChainIdToChainSelector)) | ||
for k, v := range evmChainIdToChainSelector { | ||
copyMap[k] = v.ChainSelector | ||
} | ||
return copyMap | ||
} | ||
|
||
func ChainIdFromSelector(chainSelectorId uint64) (uint64, error) { | ||
for k, v := range evmChainIdToChainSelector { | ||
if v.ChainSelector == chainSelectorId { | ||
return k, nil | ||
} | ||
} | ||
return 0, fmt.Errorf("chain not found for chain selector %d", chainSelectorId) | ||
} | ||
|
||
func SelectorFromChainId(chainId uint64) (uint64, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here re: deprecation see above. |
||
if chainSelectorId, exist := evmChainIdToChainSelector[chainId]; exist { | ||
return chainSelectorId.ChainSelector, nil | ||
} | ||
return 0, fmt.Errorf("chain selector not found for chain %d", chainId) | ||
} | ||
|
||
func NameFromChainId(chainId uint64) (string, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here re: deprecation |
||
details, exist := evmChainIdToChainSelector[chainId] | ||
if !exist { | ||
return "", fmt.Errorf("chain name not found for chain %d", chainId) | ||
} | ||
if details.ChainName == "" { | ||
return strconv.FormatUint(chainId, 10), nil | ||
} | ||
return details.ChainName, nil | ||
} | ||
|
||
func ChainIdFromName(name string) (uint64, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here re: deprecation |
||
for k, v := range evmChainIdToChainSelector { | ||
if v.ChainName == name { | ||
return k, nil | ||
} | ||
} | ||
chainId, err := strconv.ParseUint(name, 10, 64) | ||
if err == nil { | ||
if details, exist := evmChainIdToChainSelector[chainId]; exist && details.ChainName == "" { | ||
return chainId, nil | ||
} | ||
} | ||
return 0, fmt.Errorf("chain not found for name %s", name) | ||
} | ||
|
||
func TestChainIds() []uint64 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here re: deprecation |
||
chainIds := make([]uint64, 0, len(evmTestSelectorsMap)) | ||
for k := range evmTestSelectorsMap { | ||
chainIds = append(chainIds, k) | ||
} | ||
return chainIds | ||
} | ||
|
||
func ChainBySelector(sel uint64) (Chain, bool) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here re: deprecation |
||
ch, exists := evmChainsBySelector[sel] | ||
return ch, exists | ||
} | ||
|
||
func ChainByEvmChainID(evmChainID uint64) (Chain, bool) { | ||
ch, exists := evmChainsByEvmChainID[evmChainID] | ||
return ch, exists | ||
} | ||
|
||
func IsEvm(chainSel uint64) (bool, error) { | ||
_, exists := ChainBySelector(chainSel) | ||
if !exists { | ||
return false, fmt.Errorf("chain %d not found", chainSel) | ||
} | ||
// We always return true since only evm chains are supported atm. | ||
return true, nil | ||
Comment on lines
+137
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is incorrect, should return false if its solana There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the condition is a bit confusing but still looks correct to me. ChainBySelector is EVM only, so if it does exist there it is EVM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops you're right, misread ChainBySelector already. Was already thinking it'd be chain agnostic hehe |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
//go:build ignore | ||
|
||
package main | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"go/format" | ||
"html/template" | ||
"os" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
"unicode" | ||
|
||
chain_selectors "github.com/smartcontractkit/chain-selectors" | ||
) | ||
|
||
const filename = "generated_chains_solana.go" | ||
|
||
type chain struct { | ||
ChainID string | ||
Selector uint64 | ||
Name string | ||
VarName string | ||
} | ||
|
||
var chainTemplate, _ = template.New("").Parse(`// Code generated by go generate please DO NOT EDIT | ||
package chain_selectors | ||
|
||
type SolanaChain struct { | ||
ChainID string | ||
Selector uint64 | ||
Name string | ||
VarName string | ||
} | ||
|
||
var ( | ||
{{ range . }} | ||
{{.VarName}} = SolanaChain{ChainID: "{{ .ChainID }}", Selector: {{ .Selector }}, Name: "{{ .Name }}"}{{ end }} | ||
) | ||
|
||
var SolanaALL = []SolanaChain{ | ||
{{ range . }}{{ .VarName }}, | ||
{{ end }} | ||
} | ||
|
||
`) | ||
|
||
func main() { | ||
src, err := genChainsSourceCode() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
formatted, err := format.Source([]byte(src)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
existingContent, err := os.ReadFile(filename) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if string(existingContent) == string(formatted) { | ||
fmt.Println("no changes detected") | ||
return | ||
} | ||
|
||
err = os.WriteFile(filename, formatted, 0644) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func genChainsSourceCode() (string, error) { | ||
var wr = new(bytes.Buffer) | ||
chains := make([]chain, 0) | ||
|
||
for ChainID, chainSel := range chain_selectors.SolanaChainIdToChainSelector() { | ||
name, err := chain_selectors.SolanaNameFromChainId(ChainID) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
chains = append(chains, chain{ | ||
ChainID: ChainID, | ||
Selector: chainSel, | ||
Name: name, | ||
VarName: toVarName(name, chainSel), | ||
}) | ||
} | ||
|
||
sort.Slice(chains, func(i, j int) bool { return chains[i].VarName < chains[j].VarName }) | ||
if err := chainTemplate.ExecuteTemplate(wr, "", chains); err != nil { | ||
return "", err | ||
} | ||
return wr.String(), nil | ||
} | ||
|
||
func toVarName(name string, chainSel uint64) string { | ||
const unnamed = "TEST" | ||
x := strings.ReplaceAll(name, "-", "_") | ||
x = strings.ToUpper(x) | ||
if len(x) > 0 && unicode.IsDigit(rune(x[0])) { | ||
x = unnamed + "_" + x | ||
} | ||
if len(x) == 0 { | ||
x = unnamed + "_" + strconv.FormatUint(chainSel, 10) | ||
} | ||
return x | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommendation: mark this function as deprecated and create a parallel func
EVMChainIDFromChainSelector
to make it clear this is EVM which should be used instead. The "chain ID" concept should now be abstract and be more scoped with the chain family that you want a chain ID for. Feels like someone can easily use this without intending to and run into issues.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it might be easier conceptually to just leave it as "Chain" is an EVM chain and then otherwise have a family prefix like SolXXX?