Skip to content
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

feat: expose chain-registry structs (backport #4472) #4473

Merged
merged 2 commits into from
Jan 16, 2025
Merged
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
52 changes: 52 additions & 0 deletions ignite/pkg/chainregistry/asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package chainregistry

import (
"encoding/json"
"os"
)

// AssetList represents the assetlist.json file from the chain registry.
// https://raw.githubusercontent.com/cosmos/chain-registry/master/assetlist.schema.json
// https://github.com/cosmos/chain-registry?tab=readme-ov-file#assetlists
type AssetList struct {
ChainName string `json:"chain_name"`
Assets []Asset `json:"assets"`
}

type Asset struct {
Description string `json:"description"`
DenomUnits []DenomUnit `json:"denom_units"`
Base string `json:"base"`
Name string `json:"name"`
Display string `json:"display"`
Symbol string `json:"symbol"`
LogoURIs LogoURIs `json:"logo_URIs"`
CoingeckoID string `json:"coingecko_id,omitempty"`
Socials Socials `json:"socials,omitempty"`
TypeAsset string `json:"type_asset"`
}

type DenomUnit struct {
Denom string `json:"denom"`
Exponent int `json:"exponent"`
}

type LogoURIs struct {
Png string `json:"png"`
Svg string `json:"svg"`
}

type Socials struct {
Website string `json:"website"`
Twitter string `json:"twitter"`
}

// SaveJSON saves the assetlist.json to the given out directory.
func (c AssetList) SaveJSON(out string) error {
bz, err := json.MarshalIndent(c, "", " ")
if err != nil {
return err
}

return os.WriteFile(out, bz, 0o600)
}
98 changes: 98 additions & 0 deletions ignite/pkg/chainregistry/chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package chainregistry

import (
"encoding/json"
"os"
)

// Chain represents the chain.json file from the chain registry.
// https://raw.githubusercontent.com/cosmos/chain-registry/master/chain.schema.json
type Chain struct {
ChainName string `json:"chain_name"`
Status ChainStatus `json:"status"`
NetworkType NetworkType `json:"network_type"`
Website string `json:"website"`
PrettyName string `json:"pretty_name"`
ChainType ChainType `json:"chain_type"`
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
DaemonName string `json:"daemon_name"`
NodeHome string `json:"node_home"`
KeyAlgos []KeyAlgos `json:"key_algos"`
Slip44 int `json:"slip44"`
Fees Fees `json:"fees"`
Staking Staking `json:"staking"`
Codebase Codebase `json:"codebase"`
Description string `json:"description"`
APIs APIs `json:"apis"`
}

type Staking struct {
StakingTokens []StakingToken `json:"staking_tokens"`
}

type StakingToken struct {
Denom string `json:"denom"`
}

type Codebase struct {
GitRepo string `json:"git_repo"`
Genesis CodebaseGenesis `json:"genesis"`
RecommendedVersion string `json:"recommended_version"`
CompatibleVersions []string `json:"compatible_versions"`
Consensus CodebaseInfo `json:"consensus"`
Sdk CodebaseInfo `json:"sdk"`
Ibc CodebaseInfo `json:"ibc,omitempty"`
Cosmwasm CodebaseInfoEnabled `json:"cosmwasm,omitempty"`
}

type CodebaseGenesis struct {
GenesisURL string `json:"genesis_url"`
}

type CodebaseInfo struct {
Type string `json:"type"`
Version string `json:"version"`
Repo string `json:"repo,omitempty"`
Tag string `json:"tag,omitempty"`
}

type CodebaseInfoEnabled struct {
Version string `json:"version,omitempty"`
Repo string `json:"repo,omitempty"`
Tag string `json:"tag,omitempty"`
Enabled bool `json:"enabled"`
}

type Fees struct {
FeeTokens []FeeToken `json:"fee_tokens"`
}

type FeeToken struct {
Denom string `json:"denom"`
FixedMinGasPrice float64 `json:"fixed_min_gas_price"`
LowGasPrice float64 `json:"low_gas_price"`
AverageGasPrice float64 `json:"average_gas_price"`
HighGasPrice float64 `json:"high_gas_price"`
}

type APIs struct {
RPC []APIProvider `json:"rpc"`
Rest []APIProvider `json:"rest"`
Grpc []APIProvider `json:"grpc"`
}

type APIProvider struct {
Address string `json:"address"`
Provider string `json:"provider"`
}

// SaveJSON saves the chainJSON to the given out directory.
func (c Chain) SaveJSON(out string) error {
bz, err := json.MarshalIndent(c, "", " ")
if err != nil {
return err
}

return os.WriteFile(out, bz, 0o600)
}
50 changes: 50 additions & 0 deletions ignite/pkg/chainregistry/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package chainregistry

type NetworkType string

const (
// NetworkTypeMainnet is the mainnet network type.
NetworkTypeMainnet NetworkType = "mainnet"

// NetworkTypeTestnet is the testnet network type.
NetworkTypeTestnet NetworkType = "testnet"

// NetworkTypeDevnet is the devnet network type.
NetworkTypeDevnet NetworkType = "devnet"
)

type ChainType string

const (
// ChainTypeCosmos is the cosmos chain type.
ChainTypeCosmos ChainType = "cosmos"

// ChainTypeEip155 is the eip155 chain type.
ChainTypeEip155 ChainType = "eip155"
)

type ChainStatus string

const (
// ChainStatusActive is the live chain status.
ChainStatusActive ChainStatus = "live"

// ChainStatusUpcoming is the upcoming chain status.
ChainStatusUpcoming ChainStatus = "upcoming"

// ChainStatusKilled is the inactive chain status.
ChainStatusKilled ChainStatus = "killed"
)

type KeyAlgos string

const (
// KeyAlgoSecp256k1 is the secp256k1 key algorithm.
KeyAlgoSecp256k1 KeyAlgos = "secp256k1"

// KeyAlgosEthSecp256k1 is the secp256k1 key algorithm with ethereum compatibility.
KeyAlgosEthSecp256k1 KeyAlgos = "ethsecp256k1"

// KeyAlgoEd25519 is the ed25519 key algorithm.
KeyAlgoEd25519 KeyAlgos = "ed25519"
)
3 changes: 3 additions & 0 deletions ignite/pkg/chainregistry/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// package chainregistry is a package that contains the chain.json and assetlist.json structs from the chain registry.
// Useful when parsing or creating chain.json and assetlist.json files.
package chainregistry
210 changes: 27 additions & 183 deletions ignite/services/scaffolder/chain_registry.go
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ package scaffolder

import (
"bufio"
"encoding/json"
"fmt"
"os"
"path/filepath"
@@ -11,172 +10,17 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

chainconfig "github.com/ignite/cli/v28/ignite/config/chain"
"github.com/ignite/cli/v28/ignite/pkg/chainregistry"
"github.com/ignite/cli/v28/ignite/pkg/errors"
"github.com/ignite/cli/v28/ignite/pkg/xgit"
"github.com/ignite/cli/v28/ignite/services/chain"
)

const (
// DefaultChainType is the default chain type for the chain.json
// More value are allowed by the chain registry schema, but Ignite only scaffolds Cosmos chains.
DefaultChainType = "cosmos"

// DefaultChainStatus is the default chain status for the chain.json
// More value are allowed by the chain registry schema, but Ignite only scaffolds upcoming chains.
DefaultChainStatus = "upcoming"

// DefaultNetworkType is the default network type for the chain.json
// More value are allowed by the chain registry schema, but Ignite only scaffolds devnet chains.
DefaultNetworkType = "devnet"

chainFilename = "chain.json"
assetListFilename = "assetlist.json"
)

// https://raw.githubusercontent.com/cosmos/chain-registry/master/chain.schema.json
type chainJSON struct {
ChainName string `json:"chain_name"`
Status string `json:"status"`
NetworkType string `json:"network_type"`
Website string `json:"website"`
PrettyName string `json:"pretty_name"`
ChainType string `json:"chain_type"`
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
DaemonName string `json:"daemon_name"`
NodeHome string `json:"node_home"`
KeyAlgos []string `json:"key_algos"`
Slip44 int `json:"slip44"`
Fees struct {
FeeTokens []feeToken `json:"fee_tokens"`
} `json:"fees"`
Staking staking `json:"staking"`
Codebase codebase `json:"codebase"`
Description string `json:"description"`
Apis apis `json:"apis"`
}

type staking struct {
StakingTokens []stakingToken `json:"staking_tokens"`
}

type stakingToken struct {
Denom string `json:"denom"`
}

type codebase struct {
GitRepo string `json:"git_repo"`
Genesis codebaseGenesis `json:"genesis"`
RecommendedVersion string `json:"recommended_version"`
CompatibleVersions []string `json:"compatible_versions"`
Consensus codebaseConsensus `json:"consensus"`
Sdk codebaseSDK `json:"sdk"`
Ibc codebaseIBC `json:"ibc,omitempty"`
Cosmwasm codebaseCosmwasm `json:"cosmwasm,omitempty"`
}

type codebaseGenesis struct {
GenesisURL string `json:"genesis_url"`
}

type codebaseConsensus struct {
Type string `json:"type"`
Version string `json:"version"`
}

type codebaseSDK struct {
Type string `json:"type"`
Version string `json:"version"`
}

type codebaseIBC struct {
Type string `json:"type"`
Version string `json:"version"`
}

type codebaseCosmwasm struct {
Version string `json:"version,omitempty"`
Enabled bool `json:"enabled"`
}

type fees struct {
FeeTokens []feeToken `json:"fee_tokens"`
}

type feeToken struct {
Denom string `json:"denom"`
FixedMinGasPrice float64 `json:"fixed_min_gas_price"`
LowGasPrice float64 `json:"low_gas_price"`
AverageGasPrice float64 `json:"average_gas_price"`
HighGasPrice float64 `json:"high_gas_price"`
}

type apis struct {
RPC []apiProvider `json:"rpc"`
Rest []apiProvider `json:"rest"`
Grpc []apiProvider `json:"grpc"`
}

type apiProvider struct {
Address string `json:"address"`
Provider string `json:"provider"`
}

// SaveJSON saves the chainJSON to the given out directory.
func (c chainJSON) SaveJSON(out string) error {
bz, err := json.MarshalIndent(c, "", " ")
if err != nil {
return err
}

return os.WriteFile(out, bz, 0o600)
}

// https://raw.githubusercontent.com/cosmos/chain-registry/master/assetlist.schema.json
// https://github.com/cosmos/chain-registry?tab=readme-ov-file#assetlists
type assetListJSON struct {
ChainName string `json:"chain_name"`
Assets []asset `json:"assets"`
}

type asset struct {
Description string `json:"description"`
DenomUnits []denomUnit `json:"denom_units"`
Base string `json:"base"`
Name string `json:"name"`
Display string `json:"display"`
Symbol string `json:"symbol"`
LogoURIs logoURIs `json:"logo_URIs"`
CoingeckoID string `json:"coingecko_id,omitempty"`
Socials socials `json:"socials,omitempty"`
TypeAsset string `json:"type_asset"`
}

type denomUnit struct {
Denom string `json:"denom"`
Exponent int `json:"exponent"`
}

type socials struct {
Website string `json:"website"`
Twitter string `json:"twitter"`
}

type logoURIs struct {
Png string `json:"png"`
Svg string `json:"svg"`
}

// SaveJSON saves the assetList to the given out directory.
func (c assetListJSON) SaveJSON(out string) error {
bz, err := json.MarshalIndent(c, "", " ")
if err != nil {
return err
}

return os.WriteFile(out, bz, 0o600)
}

// AddChainRegistryFiles generates the chain registry files in the scaffolded chains.
func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.Config) error {
binaryName, err := chain.Binary()
@@ -197,30 +41,30 @@ func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.C
chainGitURL, _ /* do not fail on non-existing git repo */ := xgit.RepositoryURL(chain.AppPath())

var (
consensus codebaseConsensus
cosmwasm codebaseCosmwasm
ibc codebaseIBC
consensus chainregistry.CodebaseInfo
ibc chainregistry.CodebaseInfo
cosmwasm chainregistry.CodebaseInfoEnabled
)

consensusVersion, err := getVersionOfFromGoMod(chain, "github.com/cometbft/cometbft")
if err == nil {
consensus = codebaseConsensus{
consensus = chainregistry.CodebaseInfo{
Type: "cometbft",
Version: consensusVersion,
}
}

cosmwasmVersion, err := getVersionOfFromGoMod(chain, "github.com/CosmWasm/wasmd")
if err == nil {
cosmwasm = codebaseCosmwasm{
cosmwasm = chainregistry.CodebaseInfoEnabled{
Version: cosmwasmVersion,
Enabled: true,
}
}

ibcVersion, err := getVersionOfFromGoMod(chain, "github.com/cosmos/ibc-go")
if err == nil {
ibc = codebaseIBC{
ibc = chainregistry.CodebaseInfo{
Type: "go",
Version: ibcVersion,
}
@@ -236,21 +80,21 @@ func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.C
}
}

chainData := chainJSON{
chainData := chainregistry.Chain{
ChainName: chain.Name(),
PrettyName: chain.Name(),
ChainType: DefaultChainType,
Status: DefaultChainStatus,
NetworkType: DefaultNetworkType,
ChainType: chainregistry.ChainTypeCosmos,
Status: chainregistry.ChainStatusUpcoming,
NetworkType: chainregistry.NetworkTypeDevnet,
Website: "https://example.com",
ChainID: chainID,
Bech32Prefix: "cosmos",
DaemonName: binaryName,
NodeHome: chainHome,
KeyAlgos: []string{"secp256k1"},
KeyAlgos: []chainregistry.KeyAlgos{chainregistry.KeyAlgoSecp256k1},
Slip44: 118,
Fees: fees{
FeeTokens: []feeToken{
Fees: chainregistry.Fees{
FeeTokens: []chainregistry.FeeToken{
{
Denom: defaultDenom,
FixedMinGasPrice: 0.025,
@@ -260,39 +104,39 @@ func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.C
},
},
},
Staking: staking{
StakingTokens: []stakingToken{
Staking: chainregistry.Staking{
StakingTokens: []chainregistry.StakingToken{
{
Denom: defaultDenom,
},
},
},
Codebase: codebase{
Codebase: chainregistry.Codebase{
GitRepo: chainGitURL,
RecommendedVersion: "v1.0.0",
CompatibleVersions: []string{"v1.0.0"},
Sdk: codebaseSDK{
Sdk: chainregistry.CodebaseInfo{
Type: "cosmos",
Version: chain.Version.String(),
},
Consensus: consensus,
Ibc: ibc,
Cosmwasm: cosmwasm,
},
Apis: apis{
RPC: []apiProvider{
APIs: chainregistry.APIs{
RPC: []chainregistry.APIProvider{
{
Address: "http://localhost:26657",
Provider: "localhost",
},
},
Rest: []apiProvider{
Rest: []chainregistry.APIProvider{
{
Address: "http://localhost:1317",
Provider: "localhost",
},
},
Grpc: []apiProvider{
Grpc: []chainregistry.APIProvider{
{
Address: "localhost:9090",
Provider: "localhost",
@@ -301,12 +145,12 @@ func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.C
},
}

assetListData := assetListJSON{
assetListData := chainregistry.AssetList{
ChainName: chainData.ChainName,
Assets: []asset{
Assets: []chainregistry.Asset{
{
Description: fmt.Sprintf("The native token of the %s chain", chainData.ChainName),
DenomUnits: []denomUnit{
DenomUnits: []chainregistry.DenomUnit{
{
Denom: defaultDenom,
Exponent: 0,
@@ -315,12 +159,12 @@ func (s Scaffolder) AddChainRegistryFiles(chain *chain.Chain, cfg *chainconfig.C
Base: defaultDenom,
Name: chainData.ChainName,
Symbol: strings.ToUpper(defaultDenom),
LogoURIs: logoURIs{
LogoURIs: chainregistry.LogoURIs{
Png: "https://ignite.com/favicon.ico",
Svg: "https://ignite.com/favicon.ico",
},
TypeAsset: "sdk.coin",
Socials: socials{
Socials: chainregistry.Socials{
Website: "https://ignite.com",
Twitter: "https://x.com/ignite",
},