diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f87792e3e..cb9b2f1ce 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,40 +1,52 @@ -name: Run Tests +name: Run Workflow Tests πŸ§ͺ on: - push: - pull_request: - types: [opened, reopened] - + types: [opened, push, reopened] workflow_dispatch: jobs: run-tests: runs-on: ubuntu-latest steps: - - name: Checkout Repository πŸ›ŽοΈ + - name: Checkout Repository πŸ“₯ uses: actions/checkout@v4 + with: + submodules: 'recursive' # Ensures submodules are also checked out - - name: Setup Node.js + - name: Setup Node.js 🌐 uses: actions/setup-node@v4 with: node-version: '20.x' + cache: 'yarn' - - name: Install Dependencies + - name: Update Git Submodules πŸ”„ + run: | + git submodule update --remote + cd packages/chain-registry/chain-registry + git fetch + git checkout 5b5b73004a1acf84ed65694121828ddb6cb34de4 + + - name: Install Dependencies 🧢 run: yarn install - - name: Build Project + - name: Build Project πŸ—οΈ run: yarn build - - name: Test @chain-registry/keplr + - name: Test @chain-registry/keplr πŸ” run: cd packages/keplr && yarn test - - name: Test @chain-registry/cosmostation + - name: Test @chain-registry/cosmostation πŸ” run: cd packages/cosmostation && yarn test - - name: Test @chain-registry/utils + - name: Test @chain-registry/utils πŸ” run: cd packages/utils && yarn test - - name: Test @chain-registry/client + - name: Test @chain-registry/client πŸ” run: cd packages/client && yarn test + - name: Test @chain-registry/workflows πŸ” + run: cd workflows/workflows && yarn test + + - name: Test @chain-registry/cli πŸ” + run: cd workflows/cli && yarn test diff --git a/__output__/base/assetlist.schema.ts b/__output__/base/assetlist.schema.ts new file mode 100644 index 000000000..a5b5dde4d --- /dev/null +++ b/__output__/base/assetlist.schema.ts @@ -0,0 +1,90 @@ +export interface Asset { + deprecated?: boolean; + description?: string; + extended_description?: string; + denom_units: DenomUnit[]; + type_asset?: "sdk.coin" | "cw20" | "erc20" | "ics20" | "snip20" | "snip25" | "bitcoin-like" | "evm-base" | "svm-base" | "substrate"; + address?: string; + base: string; + name: string; + display: string; + symbol: string; + traces?: (IbcTransition | IbcCw20Transition | NonIbcTransition)[]; + ibc?: { + source_channel: string; + dst_channel: string; + source_denom: string; + }; + logo_URIs?: { + png?: string; + svg?: string; + }; + images?: { + image_sync?: Pointer; + png?: string; + svg?: string; + theme?: { + primary_color_hex?: string; + circle?: boolean; + dark_mode?: boolean; + }; + }[]; + coingecko_id?: string; + keywords?: string[]; + socials?: { + website?: string; + twitter?: string; + }; +} +export interface DenomUnit { + denom: string; + exponent: number; + aliases?: string[]; +} +export interface Pointer { + chain_name: string; + base_denom?: string; +} +export interface IbcTransition { + type: "ibc"; + counterparty: { + chain_name: string; + base_denom: string; + channel_id: string; + }; + chain: { + channel_id: string; + path: string; + }; +} +export interface IbcCw20Transition { + type: "ibc-cw20"; + counterparty: { + chain_name: string; + base_denom: string; + port: string; + channel_id: string; + }; + chain: { + port: string; + channel_id: string; + path: string; + }; +} +export interface NonIbcTransition { + type: "bridge" | "liquid-stake" | "synthetic" | "wrapped" | "additional-mintage" | "test-mintage"; + counterparty: { + chain_name: string; + base_denom: string; + contract?: string; + }; + chain?: { + contract: string; + }; + provider: string; +} +export interface AssetList { + $schema?: string; + chain_name: string; + assets: Asset[]; +} \ No newline at end of file diff --git a/__output__/base/chain.schema.ts b/__output__/base/chain.schema.ts new file mode 100644 index 000000000..39900d6bd --- /dev/null +++ b/__output__/base/chain.schema.ts @@ -0,0 +1,159 @@ +export interface Peer { + id: string; + address: string; + provider?: string; +} +export interface Endpoint { + address: string; + provider?: string; + archive?: boolean; +} +export interface Explorer { + kind?: string; + url?: string; + tx_page?: string; + account_page?: string; +} +export interface FeeToken { + denom: string; + fixed_min_gas_price?: number; + low_gas_price?: number; + average_gas_price?: number; + high_gas_price?: number; + gas_costs?: { + cosmos_send?: number; + ibc_transfer?: number; + }; +} +export interface StakingToken { + denom: string; +} +export interface Pointer { + chain_name: string; + base_denom?: string; +} +export interface Chain { + $schema?: string; + chain_name: string; + chain_id: string; + pre_fork_chain_name?: string; + pretty_name?: string; + website?: string; + update_link?: string; + status?: "live" | "upcoming" | "killed"; + network_type?: "mainnet" | "testnet" | "devnet"; + bech32_prefix: string; + bech32_config?: { + bech32PrefixAccAddr?: string; + bech32PrefixAccPub?: string; + bech32PrefixValAddr?: string; + bech32PrefixValPub?: string; + bech32PrefixConsAddr?: string; + bech32PrefixConsPub?: string; + }; + daemon_name?: string; + node_home?: string; + key_algos?: ("secp256k1" | "ethsecp256k1" | "ed25519" | "sr25519" | "bn254")[]; + slip44?: number; + alternative_slip44s?: number[]; + fees?: { + fee_tokens: FeeToken[]; + }; + staking?: { + staking_tokens: StakingToken[]; + lock_duration?: { + blocks?: number; + time?: string; + }; + }; + codebase?: { + git_repo?: string; + recommended_version?: string; + go_version?: string; + compatible_versions?: string[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + genesis?: { + name?: string; + genesis_url: string; + ics_ccv_url?: string; + }; + versions?: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previous_version_name?: string; + next_version_name?: string; + recommended_version?: string; + go_version?: string; + compatible_versions?: string[]; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; + }; + images?: { + image_sync?: Pointer; + png?: string; + svg?: string; + theme?: { + primary_color_hex?: string; + circle?: boolean; + dark_mode?: boolean; + }; + layout?: "logo" | "logomark" | "logotype"; + text_position?: "top" | "bottom" | "left" | "right" | "integrated"; + }[]; + logo_URIs?: { + png?: string; + svg?: string; + }; + description?: string; + peers?: { + seeds?: Peer[]; + persistent_peers?: Peer[]; + }; + apis?: { + rpc?: Endpoint[]; + rest?: Endpoint[]; + grpc?: Endpoint[]; + wss?: Endpoint[]; + "grpc-web"?: Endpoint[]; + "evm-http-jsonrpc"?: Endpoint[]; + }; + explorers?: Explorer[]; + keywords?: string[]; + extra_codecs?: ("ethermint" | "injective")[]; +} \ No newline at end of file diff --git a/__output__/base/ibc_data.schema.ts b/__output__/base/ibc_data.schema.ts new file mode 100644 index 000000000..e9acd2c9a --- /dev/null +++ b/__output__/base/ibc_data.schema.ts @@ -0,0 +1,40 @@ +export interface ChainOperatorInfo { + address?: string; +} +export interface ChainInfo { + chain_name: string; + client_id: string; + connection_id: string; +} +export interface ChannelInfo { + channel_id: string; + port_id: string; + client_id?: string; + connection_id?: string; +} +export interface IBCData { + $schema?: string; + chain_1: ChainInfo; + chain_2: ChainInfo; + channels: { + chain_1: ChannelInfo; + chain_2: ChannelInfo; + ordering: "ordered" | "unordered"; + version: string; + fee_version?: string; + description?: string; + tags?: { + status?: "live" | "upcoming" | "killed"; + preferred?: boolean; + dex?: string; + properties?: string; + }; + }[]; + operators?: { + chain_1: ChainOperatorInfo; + chain_2: ChainOperatorInfo; + memo: string; + name: string; + discord_handle?: string; + }[]; +} \ No newline at end of file diff --git a/__output__/base/memo_keys.schema.ts b/__output__/base/memo_keys.schema.ts new file mode 100644 index 000000000..01adef63a --- /dev/null +++ b/__output__/base/memo_keys.schema.ts @@ -0,0 +1,11 @@ +export interface MemoKeys { + $schema?: string; + memo_keys: { + key: string; + description: string; + git_repo: string; + memo: { + [key: string]: unknown; + }; + }[]; +} \ No newline at end of file diff --git a/__output__/base/versions.schema.ts b/__output__/base/versions.schema.ts new file mode 100644 index 000000000..292946885 --- /dev/null +++ b/__output__/base/versions.schema.ts @@ -0,0 +1,33 @@ +export interface Versions { + $schema?: string; + chain_name: string; + versions: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previous_version_name?: string; + next_version_name?: string; + recommended_version?: string; + compatible_versions?: string[]; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; +} \ No newline at end of file diff --git a/__output__/camel/assetlist.schema.ts b/__output__/camel/assetlist.schema.ts new file mode 100644 index 000000000..62559ee7f --- /dev/null +++ b/__output__/camel/assetlist.schema.ts @@ -0,0 +1,90 @@ +export interface Asset { + deprecated?: boolean; + description?: string; + extendedDescription?: string; + denomUnits: DenomUnit[]; + typeAsset?: "sdk.coin" | "cw20" | "erc20" | "ics20" | "snip20" | "snip25" | "bitcoin-like" | "evm-base" | "svm-base" | "substrate"; + address?: string; + base: string; + name: string; + display: string; + symbol: string; + traces?: (IbcTransition | IbcCw20Transition | NonIbcTransition)[]; + ibc?: { + sourceChannel: string; + dstChannel: string; + sourceDenom: string; + }; + logoURIs?: { + png?: string; + svg?: string; + }; + images?: { + imageSync?: Pointer; + png?: string; + svg?: string; + theme?: { + primaryColorHex?: string; + circle?: boolean; + darkMode?: boolean; + }; + }[]; + coingeckoId?: string; + keywords?: string[]; + socials?: { + website?: string; + twitter?: string; + }; +} +export interface DenomUnit { + denom: string; + exponent: number; + aliases?: string[]; +} +export interface Pointer { + chainName: string; + baseDenom?: string; +} +export interface IbcTransition { + type: "ibc"; + counterparty: { + chainName: string; + baseDenom: string; + channelId: string; + }; + chain: { + channelId: string; + path: string; + }; +} +export interface IbcCw20Transition { + type: "ibc-cw20"; + counterparty: { + chainName: string; + baseDenom: string; + port: string; + channelId: string; + }; + chain: { + port: string; + channelId: string; + path: string; + }; +} +export interface NonIbcTransition { + type: "bridge" | "liquid-stake" | "synthetic" | "wrapped" | "additional-mintage" | "test-mintage"; + counterparty: { + chainName: string; + baseDenom: string; + contract?: string; + }; + chain?: { + contract: string; + }; + provider: string; +} +export interface AssetList { + schema?: string; + chainName: string; + assets: Asset[]; +} \ No newline at end of file diff --git a/__output__/camel/chain.schema.ts b/__output__/camel/chain.schema.ts new file mode 100644 index 000000000..ad138f655 --- /dev/null +++ b/__output__/camel/chain.schema.ts @@ -0,0 +1,159 @@ +export interface Peer { + id: string; + address: string; + provider?: string; +} +export interface Endpoint { + address: string; + provider?: string; + archive?: boolean; +} +export interface Explorer { + kind?: string; + url?: string; + txPage?: string; + accountPage?: string; +} +export interface FeeToken { + denom: string; + fixedMinGasPrice?: number; + lowGasPrice?: number; + averageGasPrice?: number; + highGasPrice?: number; + gasCosts?: { + cosmosSend?: number; + ibcTransfer?: number; + }; +} +export interface StakingToken { + denom: string; +} +export interface Pointer { + chainName: string; + baseDenom?: string; +} +export interface Chain { + schema?: string; + chainName: string; + chainId: string; + preForkChainName?: string; + prettyName?: string; + website?: string; + updateLink?: string; + status?: "live" | "upcoming" | "killed"; + networkType?: "mainnet" | "testnet" | "devnet"; + bech32Prefix: string; + bech32Config?: { + bech32PrefixAccAddr?: string; + bech32PrefixAccPub?: string; + bech32PrefixValAddr?: string; + bech32PrefixValPub?: string; + bech32PrefixConsAddr?: string; + bech32PrefixConsPub?: string; + }; + daemonName?: string; + nodeHome?: string; + keyAlgos?: ("secp256k1" | "ethsecp256k1" | "ed25519" | "sr25519" | "bn254")[]; + slip44?: number; + alternativeSlip44s?: number[]; + fees?: { + feeTokens: FeeToken[]; + }; + staking?: { + stakingTokens: StakingToken[]; + lockDuration?: { + blocks?: number; + time?: string; + }; + }; + codebase?: { + gitRepo?: string; + recommendedVersion?: string; + goVersion?: string; + compatibleVersions?: string[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + genesis?: { + name?: string; + genesisUrl: string; + icsCcvUrl?: string; + }; + versions?: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previousVersionName?: string; + nextVersionName?: string; + recommendedVersion?: string; + goVersion?: string; + compatibleVersions?: string[]; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; + }; + images?: { + imageSync?: Pointer; + png?: string; + svg?: string; + theme?: { + primaryColorHex?: string; + circle?: boolean; + darkMode?: boolean; + }; + layout?: "logo" | "logomark" | "logotype"; + textPosition?: "top" | "bottom" | "left" | "right" | "integrated"; + }[]; + logoURIs?: { + png?: string; + svg?: string; + }; + description?: string; + peers?: { + seeds?: Peer[]; + persistentPeers?: Peer[]; + }; + apis?: { + rpc?: Endpoint[]; + rest?: Endpoint[]; + grpc?: Endpoint[]; + wss?: Endpoint[]; + "grpc-web"?: Endpoint[]; + "evm-http-jsonrpc"?: Endpoint[]; + }; + explorers?: Explorer[]; + keywords?: string[]; + extraCodecs?: ("ethermint" | "injective")[]; +} \ No newline at end of file diff --git a/__output__/camel/ibc_data.schema.ts b/__output__/camel/ibc_data.schema.ts new file mode 100644 index 000000000..a7e6d5533 --- /dev/null +++ b/__output__/camel/ibc_data.schema.ts @@ -0,0 +1,40 @@ +export interface ChainOperatorInfo { + address?: string; +} +export interface ChainInfo { + chainName: string; + clientId: string; + connectionId: string; +} +export interface ChannelInfo { + channelId: string; + portId: string; + clientId?: string; + connectionId?: string; +} +export interface IBCData { + schema?: string; + chain1: ChainInfo; + chain2: ChainInfo; + channels: { + chain1: ChannelInfo; + chain2: ChannelInfo; + ordering: "ordered" | "unordered"; + version: string; + feeVersion?: string; + description?: string; + tags?: { + status?: "live" | "upcoming" | "killed"; + preferred?: boolean; + dex?: string; + properties?: string; + }; + }[]; + operators?: { + chain1: ChainOperatorInfo; + chain2: ChainOperatorInfo; + memo: string; + name: string; + discordHandle?: string; + }[]; +} \ No newline at end of file diff --git a/__output__/camel/memo_keys.schema.ts b/__output__/camel/memo_keys.schema.ts new file mode 100644 index 000000000..35c0206a4 --- /dev/null +++ b/__output__/camel/memo_keys.schema.ts @@ -0,0 +1,11 @@ +export interface MemoKeys { + schema?: string; + memoKeys: { + key: string; + description: string; + gitRepo: string; + memo: { + [key: string]: unknown; + }; + }[]; +} \ No newline at end of file diff --git a/__output__/camel/versions.schema.ts b/__output__/camel/versions.schema.ts new file mode 100644 index 000000000..8139967a5 --- /dev/null +++ b/__output__/camel/versions.schema.ts @@ -0,0 +1,33 @@ +export interface Versions { + schema?: string; + chainName: string; + versions: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previousVersionName?: string; + nextVersionName?: string; + recommendedVersion?: string; + compatibleVersions?: string[]; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + goVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; +} \ No newline at end of file diff --git a/lerna.json b/lerna.json index 9e431b480..eeb6fd964 100644 --- a/lerna.json +++ b/lerna.json @@ -6,7 +6,9 @@ "--no-lockfile" ], "packages": [ - "packages/*" + "packages/*", + "workflows/*", + "v2/*" ], "version": "independent", "registry": "https://registry.npmjs.org", diff --git a/package.json b/package.json index dd903b2aa..b4e01fa12 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,9 @@ "access": "restricted" }, "workspaces": [ - "packages/*" + "packages/*", + "workflows/*", + "v2/*" ], "scripts": { "clean": "lerna run clean", diff --git a/packages/assets/package.json b/packages/assets/package.json index 25219efa7..5c6979db0 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "codegen": "ts-node ./scripts/build.ts", diff --git a/packages/chain-registry/chain-registry b/packages/chain-registry/chain-registry index 310030624..5b5b73004 160000 --- a/packages/chain-registry/chain-registry +++ b/packages/chain-registry/chain-registry @@ -1 +1 @@ -Subproject commit 310030624e634495bcabb34f85d13a2d9c468633 +Subproject commit 5b5b73004a1acf84ed65694121828ddb6cb34de4 diff --git a/packages/chain-registry/package.json b/packages/chain-registry/package.json index aaf9e1064..074a0ee27 100644 --- a/packages/chain-registry/package.json +++ b/packages/chain-registry/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "codegen": "ts-node ./scripts/build.ts", diff --git a/packages/client/package.json b/packages/client/package.json index 625bc8376..bbb857f8a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", diff --git a/packages/cosmostation/package.json b/packages/cosmostation/package.json index b8939df7c..c729955d7 100644 --- a/packages/cosmostation/package.json +++ b/packages/cosmostation/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", diff --git a/packages/juno/package.json b/packages/juno/package.json index 1d05fdb7a..31d1346f7 100644 --- a/packages/juno/package.json +++ b/packages/juno/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "codegen": "ts-node ./scripts/build.ts", diff --git a/packages/keplr/package.json b/packages/keplr/package.json index 9efa15d04..215505c5a 100644 --- a/packages/keplr/package.json +++ b/packages/keplr/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", diff --git a/packages/osmosis/package.json b/packages/osmosis/package.json index d0c4d89cc..8f2679f5d 100644 --- a/packages/osmosis/package.json +++ b/packages/osmosis/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build:pkg": "ts-node ./scripts/build.ts", diff --git a/packages/types/package.json b/packages/types/package.json index 22e7a0680..fd1771b94 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", diff --git a/packages/utils/package.json b/packages/utils/package.json index d6d2dcd7f..4470b6d05 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/cosmology-tech/chain-registry/issues" }, "scripts": { - "copy": "copyfiles -f ../../LICENSE README.md package.json dist", + "copy": "copyfiles -f LICENSE README.md package.json dist", "clean": "del dist/**", "prepare": "npm run build", "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", diff --git a/v2/interfaces/LICENSE b/v2/interfaces/LICENSE new file mode 100644 index 000000000..b0b3013a6 --- /dev/null +++ b/v2/interfaces/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/v2/interfaces/README.md b/v2/interfaces/README.md new file mode 100644 index 000000000..05bba0013 --- /dev/null +++ b/v2/interfaces/README.md @@ -0,0 +1,74 @@ +# @chain-registry/interfaces + +

+ +

+ +

+ + + + + + +

+ +The `@chain-registry/interfaces` module provides TypeScript interfaces that represent the structured data types as defined in the original JSON schema from the [`cosmos/chain-registry`](https://github.com/cosmos/chain-registry) repository. These interfaces are generated to facilitate type-safe development when interacting with chain registry data within TypeScript projects. + +## Installation + +To install the `@chain-registry/interfaces` module, run the following command in your project directory: + +```sh +npm install @chain-registry/interfaces +``` + +## Usage + +Once installed, you can import the interfaces into your TypeScript project to ensure type safety and auto-completion within your IDE. + +Example of using an interface: + +```js +import { Chain } from '@chain-registry/interfaces'; + +function displayChainInfo(chain: Chain) { + console.log(`Chain Name: ${chain.chain_name}`); + console.log(`Chain ID: ${chain.chain_id}`); + // Add more fields as necessary +} + +// Example usage with dummy data +const cosmosHub: Chain = { + chain_name: "Cosmos Hub", + chain_id: "cosmoshub-4", + bech32_prefix: "cosmos", + // Assume other necessary fields are filled in +}; + +displayChainInfo(cosmosHub); +``` + +## Related + +Checkout these related projects: + +* [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules. +* [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) Convert your CosmWasm smart contracts into dev-friendly TypeScript classes. +* [chain-registry](https://github.com/cosmology-tech/chain-registry) Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application. +* [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface. +* [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command. +* [interchain-ui](https://github.com/cosmology-tech/interchain-ui) The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit. +* [starship](https://github.com/cosmology-tech/starship) Unified Testing and Development for the Interchain. + +## Credits + +πŸ›  Built by Cosmology β€”Β if you like our tools, please consider delegating to [our validator βš›οΈ](https://cosmology.zone/validator) + + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED β€œAS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. + diff --git a/v2/interfaces/jest.config.js b/v2/interfaces/jest.config.js new file mode 100644 index 000000000..0aa3aaa49 --- /dev/null +++ b/v2/interfaces/jest.config.js @@ -0,0 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + babelConfig: false, + tsconfig: "tsconfig.json", + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["dist/*"] +}; diff --git a/v2/interfaces/package.json b/v2/interfaces/package.json new file mode 100644 index 000000000..365791d12 --- /dev/null +++ b/v2/interfaces/package.json @@ -0,0 +1,36 @@ +{ + "name": "@chain-registry/interfaces", + "version": "0.25.7", + "description": "Chain Registry interfaces", + "author": "Dan Lynch ", + "homepage": "https://github.com/cosmology-tech/chain-registry", + "license": "SEE LICENSE IN LICENSE", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/chain-registry" + }, + "bugs": { + "url": "https://github.com/cosmology-tech/chain-registry/issues" + }, + "scripts": { + "copy": "copyfiles -f LICENSE README.md package.json dist", + "clean": "del dist/**", + "prepare": "npm run build", + "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "chain-registry", + "web3", + "cosmos", + "interchain" + ] +} diff --git a/v2/interfaces/src/assetlist.schema.ts b/v2/interfaces/src/assetlist.schema.ts new file mode 100644 index 000000000..4e2d696cc --- /dev/null +++ b/v2/interfaces/src/assetlist.schema.ts @@ -0,0 +1,88 @@ +import { Pointer } from "./shared"; + +export interface Asset { + deprecated?: boolean; + description?: string; + extended_description?: string; + denom_units: DenomUnit[]; + type_asset?: "sdk.coin" | "cw20" | "erc20" | "ics20" | "snip20" | "snip25" | "bitcoin-like" | "evm-base" | "svm-base" | "substrate"; + address?: string; + base: string; + name: string; + display: string; + symbol: string; + traces?: (IbcTransition | IbcCw20Transition | NonIbcTransition)[]; + ibc?: { + source_channel: string; + dst_channel: string; + source_denom: string; + }; + logo_URIs?: { + png?: string; + svg?: string; + }; + images?: { + image_sync?: Pointer; + png?: string; + svg?: string; + theme?: { + primary_color_hex?: string; + circle?: boolean; + dark_mode?: boolean; + }; + }[]; + coingecko_id?: string; + keywords?: string[]; + socials?: { + website?: string; + twitter?: string; + }; +} +export interface DenomUnit { + denom: string; + exponent: number; + aliases?: string[]; +} +export interface IbcTransition { + type: "ibc"; + counterparty: { + chain_name: string; + base_denom: string; + channel_id: string; + }; + chain: { + channel_id: string; + path: string; + }; +} +export interface IbcCw20Transition { + type: "ibc-cw20"; + counterparty: { + chain_name: string; + base_denom: string; + port: string; + channel_id: string; + }; + chain: { + port: string; + channel_id: string; + path: string; + }; +} +export interface NonIbcTransition { + type: "bridge" | "liquid-stake" | "synthetic" | "wrapped" | "additional-mintage" | "test-mintage"; + counterparty: { + chain_name: string; + base_denom: string; + contract?: string; + }; + chain?: { + contract: string; + }; + provider: string; +} +export interface AssetList { + $schema?: string; + chain_name: string; + assets: Asset[]; +} \ No newline at end of file diff --git a/v2/interfaces/src/chain.schema.ts b/v2/interfaces/src/chain.schema.ts new file mode 100644 index 000000000..1380d7ecc --- /dev/null +++ b/v2/interfaces/src/chain.schema.ts @@ -0,0 +1,157 @@ +import { Pointer } from "./shared"; + +export interface Peer { + id: string; + address: string; + provider?: string; +} +export interface Endpoint { + address: string; + provider?: string; + archive?: boolean; +} +export interface Explorer { + kind?: string; + url?: string; + tx_page?: string; + account_page?: string; +} +export interface FeeToken { + denom: string; + fixed_min_gas_price?: number; + low_gas_price?: number; + average_gas_price?: number; + high_gas_price?: number; + gas_costs?: { + cosmos_send?: number; + ibc_transfer?: number; + }; +} +export interface StakingToken { + denom: string; +} +export interface Chain { + $schema?: string; + chain_name: string; + chain_id: string; + pre_fork_chain_name?: string; + pretty_name?: string; + website?: string; + update_link?: string; + status?: "live" | "upcoming" | "killed"; + network_type?: "mainnet" | "testnet" | "devnet"; + bech32_prefix: string; + bech32_config?: { + bech32PrefixAccAddr?: string; + bech32PrefixAccPub?: string; + bech32PrefixValAddr?: string; + bech32PrefixValPub?: string; + bech32PrefixConsAddr?: string; + bech32PrefixConsPub?: string; + }; + daemon_name?: string; + node_home?: string; + key_algos?: ("secp256k1" | "ethsecp256k1" | "ed25519" | "sr25519" | "bn254")[]; + slip44?: number; + alternative_slip44s?: number[]; + fees?: { + fee_tokens: FeeToken[]; + }; + staking?: { + staking_tokens: StakingToken[]; + lock_duration?: { + blocks?: number; + time?: string; + }; + }; + codebase?: { + git_repo?: string; + recommended_version?: string; + go_version?: string; + compatible_versions?: string[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + genesis?: { + name?: string; + genesis_url: string; + ics_ccv_url?: string; + }; + versions?: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previous_version_name?: string; + next_version_name?: string; + recommended_version?: string; + go_version?: string; + compatible_versions?: string[]; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; + }; + images?: { + image_sync?: Pointer; + png?: string; + svg?: string; + theme?: { + primary_color_hex?: string; + circle?: boolean; + dark_mode?: boolean; + }; + layout?: "logo" | "logomark" | "logotype"; + text_position?: "top" | "bottom" | "left" | "right" | "integrated"; + }[]; + logo_URIs?: { + png?: string; + svg?: string; + }; + description?: string; + peers?: { + seeds?: Peer[]; + persistent_peers?: Peer[]; + }; + apis?: { + rpc?: Endpoint[]; + rest?: Endpoint[]; + grpc?: Endpoint[]; + wss?: Endpoint[]; + "grpc-web"?: Endpoint[]; + "evm-http-jsonrpc"?: Endpoint[]; + }; + explorers?: Explorer[]; + keywords?: string[]; + extra_codecs?: ("ethermint" | "injective")[]; +} \ No newline at end of file diff --git a/v2/interfaces/src/ibc_data.schema.ts b/v2/interfaces/src/ibc_data.schema.ts new file mode 100644 index 000000000..e9acd2c9a --- /dev/null +++ b/v2/interfaces/src/ibc_data.schema.ts @@ -0,0 +1,40 @@ +export interface ChainOperatorInfo { + address?: string; +} +export interface ChainInfo { + chain_name: string; + client_id: string; + connection_id: string; +} +export interface ChannelInfo { + channel_id: string; + port_id: string; + client_id?: string; + connection_id?: string; +} +export interface IBCData { + $schema?: string; + chain_1: ChainInfo; + chain_2: ChainInfo; + channels: { + chain_1: ChannelInfo; + chain_2: ChannelInfo; + ordering: "ordered" | "unordered"; + version: string; + fee_version?: string; + description?: string; + tags?: { + status?: "live" | "upcoming" | "killed"; + preferred?: boolean; + dex?: string; + properties?: string; + }; + }[]; + operators?: { + chain_1: ChainOperatorInfo; + chain_2: ChainOperatorInfo; + memo: string; + name: string; + discord_handle?: string; + }[]; +} \ No newline at end of file diff --git a/v2/interfaces/src/index.ts b/v2/interfaces/src/index.ts new file mode 100644 index 000000000..b60795a2d --- /dev/null +++ b/v2/interfaces/src/index.ts @@ -0,0 +1,6 @@ +export * from './assetlist.schema'; +export * from './chain.schema'; +export * from './ibc_data.schema'; +export * from './memo_keys.schema'; +export * from './shared'; +export * from './versions.schema'; \ No newline at end of file diff --git a/v2/interfaces/src/memo_keys.schema.ts b/v2/interfaces/src/memo_keys.schema.ts new file mode 100644 index 000000000..01adef63a --- /dev/null +++ b/v2/interfaces/src/memo_keys.schema.ts @@ -0,0 +1,11 @@ +export interface MemoKeys { + $schema?: string; + memo_keys: { + key: string; + description: string; + git_repo: string; + memo: { + [key: string]: unknown; + }; + }[]; +} \ No newline at end of file diff --git a/v2/interfaces/src/shared.ts b/v2/interfaces/src/shared.ts new file mode 100644 index 000000000..4a6e92841 --- /dev/null +++ b/v2/interfaces/src/shared.ts @@ -0,0 +1,5 @@ +export interface Pointer { + chain_name: string; + base_denom?: string; + } + \ No newline at end of file diff --git a/v2/interfaces/src/versions.schema.ts b/v2/interfaces/src/versions.schema.ts new file mode 100644 index 000000000..292946885 --- /dev/null +++ b/v2/interfaces/src/versions.schema.ts @@ -0,0 +1,33 @@ +export interface Versions { + $schema?: string; + chain_name: string; + versions: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previous_version_name?: string; + next_version_name?: string; + recommended_version?: string; + compatible_versions?: string[]; + cosmos_sdk_version?: string; + consensus?: { + type: "tendermint" | "cometbft"; + version?: string; + }; + cosmwasm_version?: string; + cosmwasm_enabled?: boolean; + cosmwasm_path?: string; + ibc_go_version?: string; + go_version?: string; + ics_enabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; +} \ No newline at end of file diff --git a/v2/interfaces/tsconfig.esm.json b/v2/interfaces/tsconfig.esm.json new file mode 100644 index 000000000..800d7506d --- /dev/null +++ b/v2/interfaces/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false + } +} diff --git a/v2/interfaces/tsconfig.json b/v2/interfaces/tsconfig.json new file mode 100644 index 000000000..1a9d5696c --- /dev/null +++ b/v2/interfaces/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src/" + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] +} diff --git a/v2/types/LICENSE b/v2/types/LICENSE new file mode 100644 index 000000000..b0b3013a6 --- /dev/null +++ b/v2/types/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/v2/types/README.md b/v2/types/README.md new file mode 100644 index 000000000..3151f786c --- /dev/null +++ b/v2/types/README.md @@ -0,0 +1,93 @@ +# @chain-registry/v2-types + +

+ +

+ +

+ + + + + + +

+ +The `@chain-registry/v2-types` module provides TypeScript types derived from the [`cosmos/chain-registry`](https://github.com/cosmos/chain-registry), formatted with camelCase properties for better integration in JavaScript and TypeScript projects. This module is designed to offer developers easy-to-use types for building applications that interact with blockchain data. + +## Installation + +To add these types to your project, run the following command: + +```sh +npm install @chain-registry/v2-types +``` + +## Usage + +The types provided by this package can be imported into your TypeScript files. This allows you to utilize autocomplete features and enhance type-checking in your IDE, making your development process faster and reducing runtime errors. + +Here’s how you can use these types in your code: + + +```js +import { Chain, AssetList } from '@chain-registry/v2-types'; + +function displayChainDetails(chain: Chain) { + console.log(`Chain Name: ${chain.chainName}`); + console.log(`Chain ID: ${chain.chainId}`); + console.log(`Bech32 Prefix: ${chain.bech32Prefix}`); +} + +function displayAssetDetails(assetList: AssetList) { + assetList.assets.forEach(asset => { + console.log(`Asset Name: ${asset.name}`); + console.log(`Base Denom: ${asset.base}`); + console.log(`Display Denom: ${asset.display}`); + }); +} + +// Usage with hypothetical data +const sampleChain: Chain = { + chainName: "Osmosis", + chainId: "osmosis-1", + bech32Prefix: "osmo", + // Other necessary properties... +}; + +const sampleAssetList: AssetList = { + chainName: "Osmosis", + assets: [ + { name: "Osmo", symbol: "OSMO", base: "uosmo", display: "osmo" }, + // More assets... + ], +}; + +displayChainDetails(sampleChain); +displayAssetDetails(sampleAssetList); +``` + + +## Related + +Checkout these related projects: + +* [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules. +* [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) Convert your CosmWasm smart contracts into dev-friendly TypeScript classes. +* [chain-registry](https://github.com/cosmology-tech/chain-registry) Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application. +* [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface. +* [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command. +* [interchain-ui](https://github.com/cosmology-tech/interchain-ui) The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit. +* [starship](https://github.com/cosmology-tech/starship) Unified Testing and Development for the Interchain. + +## Credits + +πŸ›  Built by Cosmology β€”Β if you like our tools, please consider delegating to [our validator βš›οΈ](https://cosmology.zone/validator) + + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED β€œAS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. + diff --git a/v2/types/jest.config.js b/v2/types/jest.config.js new file mode 100644 index 000000000..0aa3aaa49 --- /dev/null +++ b/v2/types/jest.config.js @@ -0,0 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + babelConfig: false, + tsconfig: "tsconfig.json", + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["dist/*"] +}; diff --git a/v2/types/package.json b/v2/types/package.json new file mode 100644 index 000000000..2c63f9532 --- /dev/null +++ b/v2/types/package.json @@ -0,0 +1,36 @@ +{ + "name": "@chain-registry/v2-types", + "version": "0.25.7", + "description": "Chain Registry types", + "author": "Dan Lynch ", + "homepage": "https://github.com/cosmology-tech/chain-registry", + "license": "SEE LICENSE IN LICENSE", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/chain-registry" + }, + "bugs": { + "url": "https://github.com/cosmology-tech/chain-registry/issues" + }, + "scripts": { + "copy": "copyfiles -f LICENSE README.md package.json dist", + "clean": "del dist/**", + "prepare": "npm run build", + "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", + "test": "jest", + "test:watch": "jest --watch" + }, + "keywords": [ + "chain-registry", + "web3", + "cosmos", + "interchain" + ] +} diff --git a/v2/types/src/assetlist.schema.ts b/v2/types/src/assetlist.schema.ts new file mode 100644 index 000000000..63de8fda8 --- /dev/null +++ b/v2/types/src/assetlist.schema.ts @@ -0,0 +1,88 @@ +import { Pointer } from "./shared"; + +export interface Asset { + deprecated?: boolean; + description?: string; + extendedDescription?: string; + denomUnits: DenomUnit[]; + typeAsset?: "sdk.coin" | "cw20" | "erc20" | "ics20" | "snip20" | "snip25" | "bitcoin-like" | "evm-base" | "svm-base" | "substrate"; + address?: string; + base: string; + name: string; + display: string; + symbol: string; + traces?: (IbcTransition | IbcCw20Transition | NonIbcTransition)[]; + ibc?: { + sourceChannel: string; + dstChannel: string; + sourceDenom: string; + }; + logoURIs?: { + png?: string; + svg?: string; + }; + images?: { + imageSync?: Pointer; + png?: string; + svg?: string; + theme?: { + primaryColorHex?: string; + circle?: boolean; + darkMode?: boolean; + }; + }[]; + coingeckoId?: string; + keywords?: string[]; + socials?: { + website?: string; + twitter?: string; + }; +} +export interface DenomUnit { + denom: string; + exponent: number; + aliases?: string[]; +} +export interface IbcTransition { + type: "ibc"; + counterparty: { + chainName: string; + baseDenom: string; + channelId: string; + }; + chain: { + channelId: string; + path: string; + }; +} +export interface IbcCw20Transition { + type: "ibc-cw20"; + counterparty: { + chainName: string; + baseDenom: string; + port: string; + channelId: string; + }; + chain: { + port: string; + channelId: string; + path: string; + }; +} +export interface NonIbcTransition { + type: "bridge" | "liquid-stake" | "synthetic" | "wrapped" | "additional-mintage" | "test-mintage"; + counterparty: { + chainName: string; + baseDenom: string; + contract?: string; + }; + chain?: { + contract: string; + }; + provider: string; +} +export interface AssetList { + schema?: string; + chainName: string; + assets: Asset[]; +} \ No newline at end of file diff --git a/v2/types/src/chain.schema.ts b/v2/types/src/chain.schema.ts new file mode 100644 index 000000000..1cd1c099c --- /dev/null +++ b/v2/types/src/chain.schema.ts @@ -0,0 +1,157 @@ +import { Pointer } from "./shared"; + +export interface Peer { + id: string; + address: string; + provider?: string; +} +export interface Endpoint { + address: string; + provider?: string; + archive?: boolean; +} +export interface Explorer { + kind?: string; + url?: string; + txPage?: string; + accountPage?: string; +} +export interface FeeToken { + denom: string; + fixedMinGasPrice?: number; + lowGasPrice?: number; + averageGasPrice?: number; + highGasPrice?: number; + gasCosts?: { + cosmosSend?: number; + ibcTransfer?: number; + }; +} +export interface StakingToken { + denom: string; +} +export interface Chain { + schema?: string; + chainName: string; + chainId: string; + preForkChainName?: string; + prettyName?: string; + website?: string; + updateLink?: string; + status?: "live" | "upcoming" | "killed"; + networkType?: "mainnet" | "testnet" | "devnet"; + bech32Prefix: string; + bech32Config?: { + bech32PrefixAccAddr?: string; + bech32PrefixAccPub?: string; + bech32PrefixValAddr?: string; + bech32PrefixValPub?: string; + bech32PrefixConsAddr?: string; + bech32PrefixConsPub?: string; + }; + daemonName?: string; + nodeHome?: string; + keyAlgos?: ("secp256k1" | "ethsecp256k1" | "ed25519" | "sr25519" | "bn254")[]; + slip44?: number; + alternativeSlip44s?: number[]; + fees?: { + feeTokens: FeeToken[]; + }; + staking?: { + stakingTokens: StakingToken[]; + lockDuration?: { + blocks?: number; + time?: string; + }; + }; + codebase?: { + gitRepo?: string; + recommendedVersion?: string; + goVersion?: string; + compatibleVersions?: string[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + genesis?: { + name?: string; + genesisUrl: string; + icsCcvUrl?: string; + }; + versions?: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previousVersionName?: string; + nextVersionName?: string; + recommendedVersion?: string; + goVersion?: string; + compatibleVersions?: string[]; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft" | "sei-tendermint"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; + }; + images?: { + imageSync?: Pointer; + png?: string; + svg?: string; + theme?: { + primaryColorHex?: string; + circle?: boolean; + darkMode?: boolean; + }; + layout?: "logo" | "logomark" | "logotype"; + textPosition?: "top" | "bottom" | "left" | "right" | "integrated"; + }[]; + logoURIs?: { + png?: string; + svg?: string; + }; + description?: string; + peers?: { + seeds?: Peer[]; + persistentPeers?: Peer[]; + }; + apis?: { + rpc?: Endpoint[]; + rest?: Endpoint[]; + grpc?: Endpoint[]; + wss?: Endpoint[]; + "grpc-web"?: Endpoint[]; + "evm-http-jsonrpc"?: Endpoint[]; + }; + explorers?: Explorer[]; + keywords?: string[]; + extraCodecs?: ("ethermint" | "injective")[]; +} \ No newline at end of file diff --git a/v2/types/src/ibc_data.schema.ts b/v2/types/src/ibc_data.schema.ts new file mode 100644 index 000000000..a7e6d5533 --- /dev/null +++ b/v2/types/src/ibc_data.schema.ts @@ -0,0 +1,40 @@ +export interface ChainOperatorInfo { + address?: string; +} +export interface ChainInfo { + chainName: string; + clientId: string; + connectionId: string; +} +export interface ChannelInfo { + channelId: string; + portId: string; + clientId?: string; + connectionId?: string; +} +export interface IBCData { + schema?: string; + chain1: ChainInfo; + chain2: ChainInfo; + channels: { + chain1: ChannelInfo; + chain2: ChannelInfo; + ordering: "ordered" | "unordered"; + version: string; + feeVersion?: string; + description?: string; + tags?: { + status?: "live" | "upcoming" | "killed"; + preferred?: boolean; + dex?: string; + properties?: string; + }; + }[]; + operators?: { + chain1: ChainOperatorInfo; + chain2: ChainOperatorInfo; + memo: string; + name: string; + discordHandle?: string; + }[]; +} \ No newline at end of file diff --git a/v2/types/src/index.ts b/v2/types/src/index.ts new file mode 100644 index 000000000..b60795a2d --- /dev/null +++ b/v2/types/src/index.ts @@ -0,0 +1,6 @@ +export * from './assetlist.schema'; +export * from './chain.schema'; +export * from './ibc_data.schema'; +export * from './memo_keys.schema'; +export * from './shared'; +export * from './versions.schema'; \ No newline at end of file diff --git a/v2/types/src/memo_keys.schema.ts b/v2/types/src/memo_keys.schema.ts new file mode 100644 index 000000000..35c0206a4 --- /dev/null +++ b/v2/types/src/memo_keys.schema.ts @@ -0,0 +1,11 @@ +export interface MemoKeys { + schema?: string; + memoKeys: { + key: string; + description: string; + gitRepo: string; + memo: { + [key: string]: unknown; + }; + }[]; +} \ No newline at end of file diff --git a/v2/types/src/shared.ts b/v2/types/src/shared.ts new file mode 100644 index 000000000..62799f562 --- /dev/null +++ b/v2/types/src/shared.ts @@ -0,0 +1,5 @@ +export interface Pointer { + chainName: string; + baseDenom?: string; + } + \ No newline at end of file diff --git a/v2/types/src/versions.schema.ts b/v2/types/src/versions.schema.ts new file mode 100644 index 000000000..8139967a5 --- /dev/null +++ b/v2/types/src/versions.schema.ts @@ -0,0 +1,33 @@ +export interface Versions { + schema?: string; + chainName: string; + versions: { + name: string; + tag?: string; + height?: number; + proposal?: number; + previousVersionName?: string; + nextVersionName?: string; + recommendedVersion?: string; + compatibleVersions?: string[]; + cosmosSdkVersion?: string; + consensus?: { + type: "tendermint" | "cometbft"; + version?: string; + }; + cosmwasmVersion?: string; + cosmwasmEnabled?: boolean; + cosmwasmPath?: string; + ibcGoVersion?: string; + goVersion?: string; + icsEnabled?: ("ics20-1" | "ics27-1" | "mauth")[]; + binaries?: { + "linux/amd64"?: string; + "linux/arm64"?: string; + "darwin/amd64"?: string; + "darwin/arm64"?: string; + "windows/amd64"?: string; + "windows/arm64"?: string; + }; + }[]; +} \ No newline at end of file diff --git a/v2/types/tsconfig.esm.json b/v2/types/tsconfig.esm.json new file mode 100644 index 000000000..800d7506d --- /dev/null +++ b/v2/types/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false + } +} diff --git a/v2/types/tsconfig.json b/v2/types/tsconfig.json new file mode 100644 index 000000000..1a9d5696c --- /dev/null +++ b/v2/types/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src/" + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] +} diff --git a/workflows/cli/LICENSE b/workflows/cli/LICENSE new file mode 100644 index 000000000..2619f34f0 --- /dev/null +++ b/workflows/cli/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/workflows/cli/README.md b/workflows/cli/README.md new file mode 100644 index 000000000..ac0e5cfc6 --- /dev/null +++ b/workflows/cli/README.md @@ -0,0 +1,38 @@ +# @chain-registry/cli + +

+ +

+ +

+ + + + + +

+ +TODO + +## Related + +Checkout these related projects: + +* [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules. +* [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) Convert your CosmWasm smart contracts into dev-friendly TypeScript classes. +* [chain-registry](https://github.com/cosmology-tech/chain-registry) Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application. +* [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface. +* [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command. +* [interchain-ui](https://github.com/cosmology-tech/interchain-ui) The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit. +* [starship](https://github.com/cosmology-tech/starship) Unified Testing and Development for the Interchain. + +## Credits + +πŸ›  Built by Cosmology β€”Β if you like our tools, please consider delegating to [our validator βš›οΈ](https://cosmology.zone/validator) + + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED β€œAS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/workflows/cli/__tests__/__snapshots__/assets.test.ts.snap b/workflows/cli/__tests__/__snapshots__/assets.test.ts.snap new file mode 100644 index 000000000..48131dbfa --- /dev/null +++ b/workflows/cli/__tests__/__snapshots__/assets.test.ts.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Inquirerer prompts user and correctly processes delayed input 1`] = ` +{ + "_": [], + "asset": "uion", + "chain": "osmosis", + "command": "asset-list", + "registryDir": "../../packages/chain-registry/chain-registry", + "tty": true, +} +`; + +exports[`Inquirerer prompts user and correctly processes delayed input 2`] = `[]`; + +exports[`Inquirerer prompts user and correctly processes delayed input 3`] = `[]`; diff --git a/workflows/cli/__tests__/__snapshots__/chain.test.ts.snap b/workflows/cli/__tests__/__snapshots__/chain.test.ts.snap new file mode 100644 index 000000000..3b071393d --- /dev/null +++ b/workflows/cli/__tests__/__snapshots__/chain.test.ts.snap @@ -0,0 +1,552 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Inquirerer prompts user and correctly processes delayed input 1`] = ` +{ + "_": [], + "chain": { + "$schema": "../chain.schema.json", + "apis": { + "grpc": [ + { + "address": "osmosis-grpc.lavenderfive.com:443", + "provider": "Lavender.Five Nodes 🐝", + }, + { + "address": "grpc-osmosis-ia.cosmosia.notional.ventures:443", + "provider": "Notional", + }, + { + "address": "osmosis.grpc.stakin-nodes.com:443", + "provider": "Stakin", + }, + { + "address": "osmosis-mainnet-grpc.autostake.com:443", + "provider": "AutoStake πŸ›‘οΈ Slash Protected", + }, + { + "address": "grpc-osmosis.cosmos-spaces.cloud:1130", + "provider": "Cosmos Spaces", + }, + { + "address": "grpc-osmosis-01.stakeflow.io:6754", + "provider": "Stakeflow", + }, + { + "address": "services.staketab.com:9010", + "provider": "Staketab", + }, + { + "address": "osmosis-grpc.w3coins.io:12590", + "provider": "w3coins", + }, + { + "address": "grpc-osmosis.mms.team:443", + "provider": "MMS", + }, + { + "address": "osmosis-grpc.publicnode.com:443", + "provider": "Allnodes ⚑️ Nodes & Staking", + }, + { + "address": "osmosis-grpc.stake-town.com:443", + "provider": "StakeTown", + }, + { + "address": "https://grpc-osmosis.nodeist.net", + "provider": "Nodeist", + }, + { + "address": "osmosis-mainnet.grpc.l0vd.com:80", + "provider": "L0vd.com ❀️", + }, + { + "address": "grpc-osmosis.whispernode.com:443", + "provider": "WhisperNode 🀐", + }, + { + "address": "grpc.osmosis.validatus.com:443", + "provider": "Validatus", + }, + { + "address": "https://grpc.osmosis.bronbro.io:443", + "provider": "Bro_n_Bro", + }, + { + "address": "osmosis-grpc.noders.services:10090", + "provider": "[NODERS]TEAM", + }, + ], + "rest": [ + { + "address": "https://lcd.osmosis.zone/", + "provider": "Osmosis Foundation", + }, + { + "address": "https://osmosis-lcd.quickapi.com:443", + "provider": "Chainlayer", + }, + { + "address": "https://lcd-osmosis.blockapsis.com", + "provider": "chainapsis", + }, + { + "address": "https://osmosis-api.lavenderfive.com:443", + "provider": "Lavender.Five Nodes 🐝", + }, + { + "address": "https://rest-osmosis.ecostake.com", + "provider": "ecostake", + }, + { + "address": "https://api-osmosis-ia.cosmosia.notional.ventures", + "provider": "Notional", + }, + { + "address": "https://api-osmosis.cosmos-spaces.cloud", + "provider": "Cosmos Spaces", + }, + { + "address": "https://osmosis-api.polkachu.com", + "provider": "Polkachu", + }, + { + "address": "https://osmosis.rest.stakin-nodes.com", + "provider": "Stakin", + }, + { + "address": "https://osmosis-mainnet-lcd.autostake.com:443", + "provider": "AutoStake πŸ›‘οΈ Slash Protected", + }, + { + "address": "https://api-osmosis-01.stakeflow.io", + "provider": "Stakeflow", + }, + { + "address": "https://osmosis-api.w3coins.io", + "provider": "w3coins", + }, + { + "address": "https://lcd-osmosis.whispernode.com:443", + "provider": "WhisperNode 🀐", + }, + { + "address": "https://osmosis-rest.publicnode.com", + "provider": "Allnodes ⚑️ Nodes & Staking", + }, + { + "address": "https://community.nuxian-node.ch:6797/osmosis/crpc", + "provider": "PRO Delegators", + }, + { + "address": "https://osmosis-api.stake-town.com", + "provider": "StakeTown", + }, + { + "address": "https://osmosis-api.reece.sh", + "provider": "Reecepbcups", + }, + { + "address": "https://api.osmosis.validatus.com:443", + "provider": "Validatus", + }, + { + "address": "https://lcd.osmosis.bronbro.io:443", + "provider": "Bro_n_Bro", + }, + { + "address": "https://osmosis-rest.interstellar-lounge.org", + "provider": "Interstellar Lounge 🍸", + }, + { + "address": "https://public.stakewolle.com/cosmos/osmosis/rest", + "provider": "Stakewolle", + }, + { + "address": "https://rest.cros-nest.com/osmosis", + "provider": "Crosnest", + }, + { + "address": "https://rest-osmo.kewrnode.com", + "provider": "Kewr Node", + }, + { + "address": "https://osmosis-api.noders.services", + "provider": "[NODERS]TEAM", + }, + ], + "rpc": [ + { + "address": "https://rpc.osmosis.zone/", + "provider": "Osmosis Foundation", + }, + { + "address": "https://rpc-osmosis.blockapsis.com", + "provider": "chainapsis", + }, + { + "address": "https://osmosis-rpc.onivalidator.com", + "provider": "Oni Validator ⛩️", + }, + { + "address": "https://osmosis-rpc.quickapi.com:443", + "provider": "Chainlayer", + }, + { + "address": "https://rpc-osmosis.whispernode.com:443", + "provider": "WhisperNode 🀐", + }, + { + "address": "https://osmosis-rpc.lavenderfive.com:443", + "provider": "Lavender.Five Nodes 🐝", + }, + { + "address": "https://rpc-osmosis.ecostake.com", + "provider": "ecostake", + }, + { + "address": "https://rpc-osmosis.cosmos-spaces.cloud", + "provider": "Cosmos Spaces", + }, + { + "address": "https://osmosis-rpc.polkachu.com", + "provider": "Polkachu", + }, + { + "address": "https://rpc-osmosis-ia.cosmosia.notional.ventures", + "provider": "Notional", + }, + { + "address": "https://osmosis.rpc.stakin-nodes.com", + "provider": "Stakin", + }, + { + "address": "https://osmosis-mainnet-rpc.autostake.com:443", + "provider": "AutoStake πŸ›‘οΈ Slash Protected", + }, + { + "address": "https://osmosis.api.onfinality.io/public", + "provider": "OnFinality", + }, + { + "address": "https://rpc-osmosis-01.stakeflow.io", + "provider": "Stakeflow", + }, + { + "address": "https://osmosis-rpc.w3coins.io", + "provider": "w3coins", + }, + { + "address": "https://osmosis-rpc.publicnode.com:443", + "provider": "Allnodes ⚑️ Nodes & Staking", + }, + { + "address": "https://community.nuxian-node.ch:6797/osmosis/trpc", + "provider": "PRO Delegators", + }, + { + "address": "http://rpc-osmosis.freshstaking.com:31657", + "provider": "FreshSTAKING", + }, + { + "address": "https://osmosis-rpc.stake-town.com", + "provider": "StakeTown", + }, + { + "address": "https://osmosis-mainnet.rpc.l0vd.com:443", + "provider": "L0vd.com ❀️", + }, + { + "address": "https://osmosis-rpc.reece.sh", + "provider": "Reecepbcups", + }, + { + "address": "https://rpc.osmosis.validatus.com", + "provider": "Validatus", + }, + { + "address": "https://rpc.osmosis.bronbro.io:443", + "provider": "Bro_n_Bro", + }, + { + "address": "https://osmosis.interstellar-lounge.org", + "provider": "Interstellar Lounge 🍸", + }, + { + "address": "https://public.stakewolle.com/cosmos/osmosis/rpc", + "provider": "Stakewolle", + }, + { + "address": "https://rpc.cros-nest.com/osmosis", + "provider": "Crosnest", + }, + { + "address": "https://rpc-osmo.kewrnode.com", + "provider": "Kewr Node", + }, + { + "address": "https://osmosis-rpc.noders.services", + "provider": "[NODERS]TEAM", + }, + ], + }, + "bech32_prefix": "osmo", + "chain_id": "osmosis-1", + "chain_name": "osmosis", + "codebase": { + "binaries": { + "linux/amd64": "https://github.com/osmosis-labs/osmosis/releases/download/v24.0.1/osmosisd-24.0.1-linux-amd64", + "linux/arm64": "https://github.com/osmosis-labs/osmosis/releases/download/v24.0.1/osmosisd-24.0.1-linux-arm64", + }, + "compatible_versions": [ + "v24.0.1", + "v24.0.0", + ], + "consensus": { + "type": "cometbft", + "version": "osmosis-labs/cometbft v0.37.4-v24-osmo-2", + }, + "cosmos_sdk_version": "osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5", + "cosmwasm_enabled": true, + "cosmwasm_version": "osmosis-labs/wasmd v0.45.0-osmo", + "genesis": { + "genesis_url": "https://github.com/osmosis-labs/networks/raw/main/osmosis-1/genesis.json", + "name": "v3", + }, + "git_repo": "https://github.com/osmosis-labs/osmosis", + "go_version": "1.21", + "ibc_go_version": "v7.4.0", + "ics_enabled": [ + "ics20-1", + ], + "recommended_version": "v24.0.1", + }, + "daemon_name": "osmosisd", + "description": "Osmosis (OSMO) is the premier DEX and cross-chain DeFi hub within the Cosmos ecosystem, a network of over 50 sovereign, interoperable blockchains seamlessly connected through the Inter-Blockchain Communication Protocol (IBC). Pioneering in its approach, Osmosis offers a dynamic trading and liquidity provision experience, integrating non-IBC assets from other ecosystems, including Ethereum, Solana, Avalanche, and Polkadot. Initially adopting Balancer-style pools, Osmosis now also features a concentrated liquidity model that is orders of magnitude more capital efficient, meaning that significantly less liquidity is required to handle the same amount of trading volume with minimal slippage. + +As a true appchain, Osmosis has greater control over the full blockchain stack than traditional smart contract DEXs, which must follow the code of the parent chain that it is built on. This fine-grained control has enabled, for example, the development of Superfluid Staking, an extension of Proof of Stake that allows assets at the application layer to be staked to secure the chain. The customizability of appchains also allows implementing features like the Protocol Revenue module, which enables Osmosis to conduct on-chain arbitrage on behalf of OSMO stakers, balancing prices across pools while generating real yield revenue from this volume. Additionally, as a sovereign appchain, Osmosis governance can vote on upgrades to the protocol. One example of this was the introduction of a Taker Fee, which switched on the collection of exchange fees to generate diverse yield from Osmosis volume and distribute it to OSMO stakers. + +Osmosis is bringing the full centralized exchange experience to the decentralized world by building a cross-chain native DEX and trading suite that connects all chains over IBC, including Ethereum and Bitcoin. To reach this goal, Osmosis hosts an ever-expanding suite of DeFi applications aimed at providing a one-stop experience that includes lending, credit, margin, DeFi strategy vaults, power perps, fiat on-ramps, NFTs, stablecoins, and more β€” all of the functionalities that centralized exchange offer and more, in the trust-minimized environment of decentralized finance.", + "explorers": [ + { + "account_page": "https://ezstaking.app/osmosis/account/\${accountAddress}", + "kind": "ezstaking", + "tx_page": "https://ezstaking.app/osmosis/txs/\${txHash}", + "url": "https://ezstaking.app/osmosis", + }, + { + "account_page": "https://www.mintscan.io/osmosis/accounts/\${accountAddress}", + "kind": "mintscan", + "tx_page": "https://www.mintscan.io/osmosis/transactions/\${txHash}", + "url": "https://www.mintscan.io/osmosis", + }, + { + "kind": "ping.pub", + "tx_page": "https://ping.pub/osmosis/tx/\${txHash}", + "url": "https://ping.pub/osmosis", + }, + { + "account_page": "https://osmosis.explorers.guru/account/\${accountAddress}", + "kind": "explorers.guru", + "tx_page": "https://osmosis.explorers.guru/transaction/\${txHash}", + "url": "https://osmosis.explorers.guru", + }, + { + "account_page": "https://atomscan.com/osmosis/accounts/\${accountAddress}", + "kind": "atomscan", + "tx_page": "https://atomscan.com/osmosis/transactions/\${txHash}", + "url": "https://atomscan.com/osmosis", + }, + { + "account_page": "https://explorer.tcnetwork.io/osmosis/account/\${accountAddress}", + "kind": "TC Network", + "tx_page": "https://explorer.tcnetwork.io/osmosis/transaction/\${txHash}", + "url": "https://explorer.tcnetwork.io/osmosis", + }, + { + "account_page": "https://stakeflow.io/osmosis/accounts/\${accountAddress}", + "kind": "Stakeflow", + "url": "https://stakeflow.io/osmosis", + }, + { + "kind": "Nodeist Explorer", + "tx_page": "https://exp.nodeist.net/osmosis/tx/\${txHash}", + "url": "https://exp.nodeist.net/osmosis", + }, + { + "kind": "L0vd.com ❀️", + "tx_page": "https://explorers.l0vd.com/osmosis-mainnet/tx/\${txHash}", + "url": "https://explorers.l0vd.com/osmosis-mainnet", + }, + { + "kind": "Chainscope", + "tx_page": "https://chainsco.pe/osmosis/tx/\${txHash}", + "url": "https://chainsco.pe/osmosis", + }, + ], + "fees": { + "fee_tokens": [ + { + "average_gas_price": 0.025, + "denom": "uosmo", + "fixed_min_gas_price": 0.0025, + "high_gas_price": 0.04, + "low_gas_price": 0.0025, + }, + ], + }, + "images": [ + { + "layout": "logo", + "png": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmosis-chain-logo.png", + "text_position": "right", + "theme": { + "primary_color_hex": "#231D4B", + }, + }, + { + "layout": "logomark", + "svg": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmo.svg", + }, + ], + "key_algos": [ + "secp256k1", + ], + "keywords": [ + "dex", + ], + "logo_URIs": { + "png": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmosis-chain-logo.png", + }, + "network_type": "mainnet", + "node_home": "$HOME/.osmosisd", + "peers": { + "persistent_peers": [ + { + "address": "37.187.38.191:26656", + "id": "4d9ac3510d9f5cfc975a28eb2a7b8da866f7bc47", + "provider": "stakelab", + }, + { + "address": "37.120.245.167:26656", + "id": "2f9c16151400d8516b0f58c030b3595be20b804c", + "provider": "syncnode", + }, + { + "address": "osmosis-mainnet-peer.autostake.com:26716", + "id": "ebc272824924ea1a27ea3183dd0b9ba713494f83", + "provider": "AutoStake πŸ›‘οΈ Slash Protected", + }, + { + "address": "seed-osmosis.freshstaking.com:31656", + "id": "e891d42c31064fb7e0d99839536164473c4905c2", + "provider": "FreshSTAKING", + }, + { + "address": "peer-osmosis-01.stakeflow.io:65535", + "id": "38ab18cb2ea1dfeb6232b429e1508f56b6ae5031", + "provider": "Stakeflow", + }, + { + "address": "65.21.91.99:16956", + "id": "6f1d92857e39a6f26a3a914f807064824c255939", + "provider": "Staketab", + }, + { + "address": "peer-osmosis.mms.team:56102", + "id": "50d0865decf5657eaf8e50e51bd9d8ce5f927f6c", + "provider": "MMS", + }, + { + "address": "65.108.195.213:41656", + "id": "b95edbc3337a6fdd672cd6af2790c0e9ade2c4dd", + "provider": "StakeTown", + }, + { + "address": "osmosis-mainnet.peers.l0vd.com:12656", + "id": "10539f7c0e3ab233cf0deec9930aa8b660aeeabf", + "provider": "L0vd.com ❀️", + }, + ], + "seeds": [ + { + "address": "osmosis.blockpane.com:26656", + "id": "f515a8599b40f0e84dfad935ba414674ab11a668", + "provider": "blockpane", + }, + { + "address": "seeds.polkachu.com:12556", + "id": "ade4d8bc8cbe014af6ebdf3cb7b1e9ad36f412c0", + "provider": "Polkachu", + }, + { + "address": "seeds.lavenderfive.com:12556", + "id": "20e1000e88125698264454a884812746c2eb4807", + "provider": "Lavender.Five Nodes 🐝", + }, + { + "address": "osmosis-mainnet-seed.autostake.com:26716", + "id": "ebc272824924ea1a27ea3183dd0b9ba713494f83", + "provider": "AutoStake πŸ›‘οΈ Slash Protected", + }, + { + "address": "seeds.goldenratiostaking.net:1630", + "id": "3cc024d1c760c9cd96e6413abaf3b36a8bdca58e", + "provider": "Golden Ratio Staking", + }, + { + "address": "seed-osmosis.freshstaking.com:31656", + "id": "e891d42c31064fb7e0d99839536164473c4905c2", + "provider": "FreshSTAKING", + }, + { + "address": "seeds.whispernode.com:12556", + "id": "c28827cb96c14c905b127b92065a3fb4cd77d7f6", + "provider": "WhisperNode 🀐", + }, + { + "address": "seed-osmosis-01.stakeflow.io:65535", + "id": "38ab18cb2ea1dfeb6232b429e1508f56b6ae5031", + "provider": "Stakeflow", + }, + { + "address": "seed-node.mms.team:31656", + "id": "954ab3a0551b592b654b1554af8fc8746ed7b362", + "provider": "MMS", + }, + { + "address": "seed.publicnode.com:26656", + "id": "8542cd7e6bf9d260fef543bc49e59be5a3fa9074", + "provider": "Allnodes ⚑️ Nodes & Staking", + }, + { + "address": "seed.osmosis.validatus.com:2000", + "id": "2cb8dd6195c65458e3c18505bb70ce2ff624f85c", + "provider": "Validatus", + }, + ], + }, + "pretty_name": "Osmosis", + "slip44": 118, + "staking": { + "lock_duration": { + "time": "1209600s", + }, + "staking_tokens": [ + { + "denom": "uosmo", + }, + ], + }, + "status": "live", + "update_link": "https://raw.githubusercontent.com/osmosis-labs/osmosis/main/chain.schema.json", + "website": "https://osmosis.zone/", + }, + "command": "chain", + "registryDir": "../../packages/chain-registry/chain-registry", + "tty": true, +} +`; + +exports[`Inquirerer prompts user and correctly processes delayed input 2`] = `[]`; + +exports[`Inquirerer prompts user and correctly processes delayed input 3`] = `[]`; diff --git a/workflows/cli/__tests__/__snapshots__/validate.test.ts.snap b/workflows/cli/__tests__/__snapshots__/validate.test.ts.snap new file mode 100644 index 000000000..f6bfc1e84 --- /dev/null +++ b/workflows/cli/__tests__/__snapshots__/validate.test.ts.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Inquirerer prompts user and correctly processes delayed input 1`] = ` +{ + "_": [], + "command": "validate", + "registryDir": "../../packages/chain-registry/chain-registry", + "tty": true, +} +`; diff --git a/workflows/cli/__tests__/assets.test.ts b/workflows/cli/__tests__/assets.test.ts new file mode 100644 index 000000000..7e8709a1c --- /dev/null +++ b/workflows/cli/__tests__/assets.test.ts @@ -0,0 +1,38 @@ +import { CLI } from 'inquirerer'; + +import { commands } from '../src/commands/info'; +import { setupTests, TestEnvironment } from '../test-utils'; + +const beforeEachSetup = setupTests(); +const registryDir = '../../packages/chain-registry/chain-registry'; + +describe('Inquirerer', () => { + let environment: TestEnvironment; + + beforeEach(() => { + environment = beforeEachSetup(); + }); + + it('prompts user and correctly processes delayed input', async () => { + const { options, writeResults, transformResults } = environment; + + // enqueueInputResponse({ type: 'read', value: registryDir }); + // enqueueInputResponse({ type: 'read', value: 'osmosis' }); + // enqueueInputResponse({ type: 'key', value: KEY_SEQUENCES.ENTER }); + // enqueueInputResponse({ type: 'read', value: 'agoric' }); + // enqueueInputResponse({ type: 'key', value: KEY_SEQUENCES.ENTER }); + + const app = new CLI(commands, options, { + _: ['asset-list'], + registryDir, + chain: 'osmosis', + asset: 'uion' + }); + + const result = await app.run(); + + expect(result).toMatchSnapshot(); + expect(writeResults).toMatchSnapshot(); + expect(transformResults).toMatchSnapshot(); + }); +}); diff --git a/workflows/cli/__tests__/chain.test.ts b/workflows/cli/__tests__/chain.test.ts new file mode 100644 index 000000000..a10c4517b --- /dev/null +++ b/workflows/cli/__tests__/chain.test.ts @@ -0,0 +1,32 @@ +import { CLI } from 'inquirerer'; + +import { commands } from '../src/commands/info'; +import { setupTests, TestEnvironment } from '../test-utils'; + +const beforeEachSetup = setupTests(); +const registryDir = '../../packages/chain-registry/chain-registry'; + +describe('Inquirerer', () => { + let environment: TestEnvironment; + + beforeEach(() => { + environment = beforeEachSetup(); + }); + + it('prompts user and correctly processes delayed input', async () => { + const { options, writeResults, transformResults } = environment; + + + const app = new CLI(commands, options, { + _: ['chain'], + registryDir, + chain: 'osmosis' + }); + + const result = await app.run(); + + expect(result).toMatchSnapshot(); + expect(writeResults).toMatchSnapshot(); + expect(transformResults).toMatchSnapshot(); + }); +}); diff --git a/workflows/cli/__tests__/validate.test.ts b/workflows/cli/__tests__/validate.test.ts new file mode 100644 index 000000000..2451f58f8 --- /dev/null +++ b/workflows/cli/__tests__/validate.test.ts @@ -0,0 +1,28 @@ +import { CLI } from 'inquirerer'; + +import { commands } from '../src/commands/info'; +import { setupTests, TestEnvironment } from '../test-utils'; + +const beforeEachSetup = setupTests(); +const registryDir = '../../packages/chain-registry/chain-registry'; + +describe('Inquirerer', () => { + let environment: TestEnvironment; + + beforeEach(() => { + environment = beforeEachSetup(); + }); + + it('prompts user and correctly processes delayed input', async () => { + const { options } = environment; + + const app = new CLI(commands, options, { + _: ['validate'], + registryDir + }); + + const result = await app.run(); + + expect(result).toMatchSnapshot(); + }); +}); diff --git a/workflows/cli/jest.config.js b/workflows/cli/jest.config.js new file mode 100644 index 000000000..0aa3aaa49 --- /dev/null +++ b/workflows/cli/jest.config.js @@ -0,0 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + babelConfig: false, + tsconfig: "tsconfig.json", + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["dist/*"] +}; diff --git a/workflows/cli/package.json b/workflows/cli/package.json new file mode 100644 index 000000000..cd868b31c --- /dev/null +++ b/workflows/cli/package.json @@ -0,0 +1,49 @@ +{ + "name": "@chain-registry/cli", + "version": "1.26.3", + "description": "Chain Registry CLI", + "author": "Dan Lynch ", + "homepage": "https://github.com/cosmology-tech/chain-registry", + "license": "SEE LICENSE IN LICENSE", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "bin": { + "registry": "cli.js" + }, + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/chain-registry" + }, + "bugs": { + "url": "https://github.com/cosmology-tech/chain-registry/issues" + }, + "scripts": { + "copy": "copyfiles -f LICENSE README.md package.json dist", + "clean": "del dist/**", + "prepare": "npm run build", + "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", + "dev": "ts-node src/cli", + "test": "jest", + "test:watch": "jest --watch" + }, + "dependencies": { + "@chain-registry/workflows": "^1.26.3", + "@chain-registry/interfaces": "^0.25.7", + "chalk": "^4.1.0", + "deepmerge": "^4.3.1", + "inquirerer": "1.8.0", + "minimist": "^1.2.8" + }, + "keywords": [ + "cli", + "chain-registry", + "web3", + "cosmos", + "interchain" + ] +} diff --git a/workflows/cli/src/cli.ts b/workflows/cli/src/cli.ts new file mode 100755 index 000000000..e03f2d8ff --- /dev/null +++ b/workflows/cli/src/cli.ts @@ -0,0 +1,21 @@ +#!/usr/bin/env node +import { CLI, CLIOptions } from 'inquirerer'; + +import { commands } from './commands' + +export const options: Partial = { + minimistOpts: { + alias: { + v: 'version' + } + } + }; + +const app = new CLI(commands, options); + +app.run().then(()=> { + // all done! +}).catch(error => { + console.error(error); + process.exit(1); +}) diff --git a/workflows/cli/src/commands/codegen/index.ts b/workflows/cli/src/commands/codegen/index.ts new file mode 100644 index 000000000..4b2da02d8 --- /dev/null +++ b/workflows/cli/src/commands/codegen/index.ts @@ -0,0 +1,56 @@ +import { Registry, SchemaTypeGenerator } from '@chain-registry/workflows'; +import { existsSync } from 'fs'; +import { CLIOptions, Inquirerer } from 'inquirerer' +import { ParsedArgs } from 'minimist'; + +export const commands = async (argv: Partial, prompter: Inquirerer, _options: CLIOptions) => { + + const { + registryDir, + outputDir, + strictTypeSafety, + useCamelCase + } = await prompter.prompt(argv, [ + { + type: 'text', + name: 'registryDir', + message: 'provide a registryDir:' + }, + { + type: 'text', + name: 'outputDir', + message: 'provide a outputDir:' + }, + { + type: 'confirm', + name: 'strictTypeSafety', + default: true, + useDefault: true + }, + { + type: 'confirm', + name: 'useCamelCase', + default: true, + useDefault: false + } + ]); + + if (!existsSync(registryDir)) { + prompter.exit(); + throw new Error('bad registry path!'); + } + + const registry: Registry = new Registry(registryDir); + const generator = new SchemaTypeGenerator({ + outputDir, + registry, + schemaTSOptions: { + strictTypeSafety, + useCamelCase + } + }); + + generator.generateTypes() + + return argv; +}; \ No newline at end of file diff --git a/workflows/cli/src/commands/index.ts b/workflows/cli/src/commands/index.ts new file mode 100644 index 000000000..ebd94e336 --- /dev/null +++ b/workflows/cli/src/commands/index.ts @@ -0,0 +1,59 @@ +import { CLIOptions, Inquirerer, Question } from 'inquirerer' +import { ParsedArgs } from 'minimist'; + +import { commands as codegen } from './codegen'; +import { commands as info } from './info'; +import { commands as validate } from './validate'; + +export const commands = async (argv: Partial, prompter: Inquirerer, _options: CLIOptions) => { + let command; + + if (argv._.length > 0) { + command = argv._.shift(); + } + + if (command) { + argv.command = command; + } + + const questions: Question[] = [ + { + type: 'autocomplete', + name: 'command', + message: 'choose a command', + options: [ + 'info', + 'validate', + 'codegen' + ] + } + ]; + + ({ command } = await prompter.prompt(argv, questions)); + + // recursive... + delete argv.command; + + // @ts-ignore + prompter.exit = () => {}; + + switch (command) { + case 'info': + argv = await info(argv, prompter, _options); + break; + case 'validate': + argv = await validate(argv, prompter, _options); + break; + + case 'codegen': + argv = await codegen(argv, prompter, _options); + break; + + default: + console.log(`No recognized command provided or no command given: ${command}`); + break; + } + + return argv; + +}; \ No newline at end of file diff --git a/workflows/cli/src/commands/info/asset-list.ts b/workflows/cli/src/commands/info/asset-list.ts new file mode 100644 index 000000000..61a7d7438 --- /dev/null +++ b/workflows/cli/src/commands/info/asset-list.ts @@ -0,0 +1,12 @@ +import { AssetList } from '@chain-registry/interfaces'; +import chalk from 'chalk'; + +import { displayAsset } from './asset'; + +export function displayAssetList(assetList: AssetList): void { + console.log(chalk.bold.blue(`Asset List for Chain: ${assetList.chain_name}`)); + console.log(chalk.underline(`${assetList.assets.length} Assets Found:`)); + assetList.assets.forEach(asset => { + displayAsset(asset); // Call displayAsset for each asset in the list + }); +} diff --git a/workflows/cli/src/commands/info/asset.ts b/workflows/cli/src/commands/info/asset.ts new file mode 100644 index 000000000..84734507b --- /dev/null +++ b/workflows/cli/src/commands/info/asset.ts @@ -0,0 +1,53 @@ +import { Asset } from '@chain-registry/interfaces'; +import chalk from 'chalk'; + +export function displayAsset(asset: Asset): void { + console.log(chalk.bold.blue(`Asset Name: ${asset.name}`)); + console.log(chalk.bold(`Symbol: ${asset.symbol}`)); + console.log(chalk.bold(`Type: ${asset.type_asset || 'Not specified'}`)); + console.log(`Base Unit: ${asset.base}`); + console.log(`Display Unit: ${asset.display}`); + if (asset.deprecated) { + console.log(chalk.red('Deprecated: Yes')); + } + if (asset.description) { + console.log(chalk.italic(`Description: ${asset.description}`)); + } + if (asset.extended_description) { + console.log(chalk.italic(`Extended Description: ${asset.extended_description}`)); + } + if (asset.denom_units) { + console.log(chalk.bold.green('Denomination Units:')); + asset.denom_units.forEach(unit => { + console.log(` - Denom: ${unit.denom}, Exponent: ${unit.exponent}${unit.aliases ? `, Aliases: ${unit.aliases.join(', ')}` : ''}`); + }); + } + if (asset.ibc) { + console.log(chalk.bold.yellow('IBC Info:')); + console.log(` Source Channel: ${asset.ibc.source_channel}`); + console.log(` Destination Channel: ${asset.ibc.dst_channel}`); + console.log(` Source Denom: ${asset.ibc.source_denom}`); + } + if (asset.logo_URIs) { + console.log(chalk.bold.cyan('Logos:')); + asset.logo_URIs.png && console.log(` PNG: ${asset.logo_URIs.png}`); + asset.logo_URIs.svg && console.log(` SVG: ${asset.logo_URIs.svg}`); + } + if (asset.images && asset.images.length > 0) { + console.log(chalk.bold.magenta('Images:')); + asset.images.forEach((image, index) => { + console.log(` Image ${index + 1}:`); + image.png && console.log(` PNG: ${image.png}`); + image.svg && console.log(` SVG: ${image.svg}`); + if (image.theme) { + console.log(` Theme: ${image.theme.primary_color_hex} Circle: ${image.theme.circle ? 'Yes' : 'No'} Dark Mode: ${image.theme.dark_mode ? 'Yes' : 'No'}`); + } + }); + } + if (asset.socials) { + console.log(chalk.bold('Socials:')); + asset.socials.website && console.log(` Website: ${asset.socials.website}`); + asset.socials.twitter && console.log(` Twitter: ${asset.socials.twitter}`); + } + console.log('\n'); +} \ No newline at end of file diff --git a/workflows/cli/src/commands/info/chain.ts b/workflows/cli/src/commands/info/chain.ts new file mode 100644 index 000000000..852f28bda --- /dev/null +++ b/workflows/cli/src/commands/info/chain.ts @@ -0,0 +1,76 @@ +import { Chain } from '@chain-registry/interfaces'; +import chalk from 'chalk'; + +export function displayChain(chain: Chain): void { + console.log(chalk.bold.green(`Chain Details: ${chain.chain_name}`)); + console.log(chalk.bold(`Chain ID: ${chalk.cyan(chain.chain_id)}`)); + if (chain.pretty_name) { + console.log(chalk.bold(`Pretty Name: ${chalk.cyan(chain.pretty_name)}`)); + } + if (chain.website) { + console.log(chalk.bold(`Website: ${chalk.underline.blue(chain.website)}`)); + } + if (chain.status) { + console.log(chalk.bold(`Status: ${chalk.yellow(chain.status)}`)); + } + if (chain.network_type) { + console.log(chalk.bold(`Network Type: ${chalk.magenta(chain.network_type)}`)); + } + console.log(chalk.bold(`Bech32 Prefix: ${chalk.cyan(chain.bech32_prefix)}`)); + + if (chain.daemon_name) { + console.log(chalk.bold(`Daemon Name: ${chain.daemon_name}`)); + } + + if (chain.codebase) { + console.log(chalk.bold(`Codebase:`)); + console.log(` Git Repo: ${chain.codebase.git_repo}`); + console.log(` Recommended Version: ${chain.codebase.recommended_version}`); + console.log(` Go Version: ${chain.codebase.go_version}`); + } + + if (chain.fees) { + console.log(chalk.bold(`Fee Tokens:`)); + chain.fees.fee_tokens.forEach(fee => { + console.log(` Denom: ${fee.denom}, Fixed Min Gas Price: ${fee.fixed_min_gas_price}`); + }); + } + + if (chain.staking) { + console.log(chalk.bold(`Staking Tokens:`)); + chain.staking.staking_tokens.forEach(token => { + console.log(` Denom: ${token.denom}`); + }); + } + + if (chain.apis) { + console.log(chalk.bold(`APIs:`)); + if (chain.apis.rpc) { + console.log(` RPC:`); + chain.apis.rpc.forEach(endpoint => { + console.log(` Address: ${endpoint.address}`); + }); + } + if (chain.apis.rest) { + console.log(` REST:`); + chain.apis.rest.forEach(endpoint => { + console.log(` Address: ${endpoint.address}`); + }); + } + } + + if (chain.explorers) { + console.log(chalk.bold(`Explorers:`)); + chain.explorers.forEach(explorer => { + console.log(` URL: ${explorer.url}`); + if (explorer.tx_page) { + console.log(` TX Page: ${explorer.tx_page}`); + } + if (explorer.account_page) { + console.log(` Account Page: ${explorer.account_page}`); + } + }); + } + + console.log(chalk.bold(`Keywords: ${chain.keywords?.join(', ')}`)); +} diff --git a/workflows/cli/src/commands/info/index.ts b/workflows/cli/src/commands/info/index.ts new file mode 100644 index 000000000..cf3a3a17e --- /dev/null +++ b/workflows/cli/src/commands/info/index.ts @@ -0,0 +1,117 @@ +import { Registry } from '@chain-registry/workflows'; +import { existsSync } from 'fs'; +import { CLIOptions, Inquirerer, Question } from 'inquirerer' +import { ParsedArgs } from 'minimist'; + +import { displayAsset } from './asset'; +import { displayAssetList } from './asset-list'; +import { displayChain } from './chain'; + +export const commands = async (argv: Partial, prompter: Inquirerer, _options: CLIOptions) => { + let command; + + if (argv._.length > 0) { + command = argv._.shift(); + } + + if (command) { + argv.command = command; + } + + const questions: Question[] = [ + { + type: 'autocomplete', + name: 'command', + message: 'choose a command', + options: [ + 'chain', + 'asset-list', + 'asset' + ] + } + ]; + + ({ command } = await prompter.prompt(argv, questions)); + + argv = await prompter.prompt(argv, [ + { + type: 'text', + name: 'registryDir', + message: 'provide a registryDir:' + } + ]); + + if (!existsSync(argv.registryDir)) { + prompter.exit(); + throw new Error('bad registry path!'); + } + + const registry: Registry = new Registry(argv.registryDir); + + switch (command) { + case 'chain': + argv = await prompter.prompt(argv, [ + { + type: 'autocomplete', + name: 'chain', + message: 'Select a chain:', + options: registry.chains.map(chain => ({ name: chain.chain_name, value: chain })), + maxDisplayLines: 15 + } + ]); + displayChain(argv.chain); + break; + + case 'asset-list': + argv = await prompter.prompt(argv, [ + { + type: 'autocomplete', + name: 'chain', + message: 'Select a chain:', + options: registry.chains.map(chain => chain.chain_name), + maxDisplayLines: 15 + } + ]); + + const assetList = registry.assetLists.find(a => a.chain_name === argv.chain); + displayAssetList(assetList); + break; + + case 'asset': + argv = await prompter.prompt(argv, [ + { + type: 'autocomplete', + name: 'chain', + message: 'Select a chain:', + options: registry.chains.map(chain => chain.chain_name), + maxDisplayLines: 15 + } + ]); + + argv = await prompter.prompt(argv, [ + { + type: 'autocomplete', + name: 'asset', + message: 'Select an asset:', + options: registry.assetLists + .filter(list => list.chain_name === argv.chain) + .flatMap(list => list.assets) + .map(asset => ({ + name: asset.base, + value: asset + })), + maxDisplayLines: 15 + } + ]); + + displayAsset(argv.asset); + break; + + default: + console.log(`No recognized command provided or no command given: ${command}`); + break; + } + + return argv; + +}; \ No newline at end of file diff --git a/workflows/cli/src/commands/validate/index.ts b/workflows/cli/src/commands/validate/index.ts new file mode 100644 index 000000000..c0561ad64 --- /dev/null +++ b/workflows/cli/src/commands/validate/index.ts @@ -0,0 +1,27 @@ +import { Registry, SchemaValidator } from '@chain-registry/workflows'; +import { existsSync } from 'fs'; +import { CLIOptions, Inquirerer } from 'inquirerer' +import { ParsedArgs } from 'minimist'; + +export const commands = async (argv: Partial, prompter: Inquirerer, _options: CLIOptions) => { + + argv = await prompter.prompt(argv, [ + { + type: 'text', + name: 'registryDir', + message: 'provide a registryDir:' + } + ]); + + if (!existsSync(argv.registryDir)) { + prompter.exit(); + throw new Error('bad registry path!'); + } + + const registry = new Registry(argv.registryDir) + const validator = new SchemaValidator(registry); + + validator.validateAllData(true); + + return argv; +}; \ No newline at end of file diff --git a/workflows/cli/src/index.ts b/workflows/cli/src/index.ts new file mode 100644 index 000000000..91cd0d14a --- /dev/null +++ b/workflows/cli/src/index.ts @@ -0,0 +1,2 @@ +export * from './commands/info'; +export * from './utils'; \ No newline at end of file diff --git a/workflows/cli/src/package.ts b/workflows/cli/src/package.ts new file mode 100644 index 000000000..74d39ab3a --- /dev/null +++ b/workflows/cli/src/package.ts @@ -0,0 +1,33 @@ +import { existsSync,readFileSync } from "fs"; +import { dirname,join } from "path"; + +// need to search due to the dist/ folder and src/, etc. +function findPackageJson(currentDir: string): string { + const filePath = join(currentDir, 'package.json'); + + // Check if package.json exists in the current directory + if (existsSync(filePath)) { + return filePath; + } + + // Get the parent directory + const parentDir = dirname(currentDir); + + // If reached the root directory, package.json is not found + if (parentDir === currentDir) { + throw new Error('package.json not found in any parent directory'); + } + + // Recursively look in the parent directory + return findPackageJson(parentDir); +} + +export function readAndParsePackageJson(): any { + // Start searching from the current directory + const pkgPath = findPackageJson(__dirname); + + // Read and parse the package.json + const str = readFileSync(pkgPath, 'utf8'); + const pkg = JSON.parse(str); + return pkg; +} \ No newline at end of file diff --git a/workflows/cli/src/utils.ts b/workflows/cli/src/utils.ts new file mode 100644 index 000000000..da009b651 --- /dev/null +++ b/workflows/cli/src/utils.ts @@ -0,0 +1,15 @@ +import chalk from 'chalk'; + +import { readAndParsePackageJson } from "./package"; + +// Function to display the version information +export function displayVersion(): void { + const pkg = readAndParsePackageJson(); + console.log(chalk.green(`Name: ${pkg.name}`)); + console.log(chalk.blue(`Version: ${pkg.version}`)); +} + +export function getVersion(): string { + const pkg = readAndParsePackageJson(); + return pkg.version; +} diff --git a/workflows/cli/test-utils/index.ts b/workflows/cli/test-utils/index.ts new file mode 100644 index 000000000..178d69abf --- /dev/null +++ b/workflows/cli/test-utils/index.ts @@ -0,0 +1,137 @@ +import { CLIOptions } from 'inquirerer'; +import readline from 'readline'; +import { Readable, Transform, Writable } from 'stream'; +import stripAnsi from 'strip-ansi'; + +export const KEY_SEQUENCES = { + ENTER: '\u000d', + UP_ARROW: '\u001b[A', + DOWN_ARROW: '\u001b[B', + SPACE: ' ' +}; + +function humanizeKeySequences(data: string): string { + const keyMap: { [key: string]: string } = { + '\u000d': '', + '\u001b[A': '', + '\u001b[B': '', + ' ': '' + }; + + return data.replace(/[\u000d\u001b[A\u001b[B ]/g, (match) => keyMap[match] ?? match); +} +interface InputResponse { + type: 'key' | 'read'; + value: string; +} + +interface MockReadline { + question: (questionText: string, cb: (input: string) => void) => void; + close: () => void; +} + +export interface TestEnvironment { + options: Partial; + mockInput: Readable; + mockOutput: Writable; + writeResults: string[]; + transformResults: string[]; + enqueueInputResponse: (input: InputResponse) => void; +} + +function setupReadlineMock(inputQueue: InputResponse[], currentInputIndex: number): void { + readline.createInterface = jest.fn().mockReturnValue({ + question: (questionText: string, cb: (input: string) => void) => { + const nextInput = inputQueue[currentInputIndex++]; + if (nextInput && nextInput.type === 'read') { + setTimeout(() => cb(nextInput.value), 350); + } + }, + close: jest.fn(), + } as MockReadline); +} + +export function setupTests(): () => TestEnvironment { + let options: Partial; + let mockWrite: jest.Mock; + let mockInput: Readable; + let mockOutput: Writable; + let transformStream: Transform; + + let writeResults: string[] = []; + let transformResults: string[] = []; + + let inputQueue: InputResponse[] = []; + let currentInputIndex = 0; + let lastScheduledTime = 0; + + + const beforeEachSetup = (): TestEnvironment => { + jest.clearAllMocks(); + mockWrite = jest.fn(); + writeResults = []; + transformResults = []; + + mockInput = new Readable({ read(size) { } }); + (mockInput as any).setRawMode = jest.fn(); + + mockOutput = new Writable({ + write: (chunk, encoding, callback) => { + const str = chunk.toString(); + const humanizedStr = humanizeKeySequences(str); + const cleanStr = stripAnsi(humanizedStr); + writeResults.push(cleanStr); + mockWrite(str); + callback(); + } + }); + + // mock I/O streams so we can keep TTY for testing and CI/CD 🎨 + options = { + noTty: false, + input: mockInput, + output: mockOutput, + minimistOpts: { + alias: { + v: 'version' + } + } + }; + + transformStream = new Transform({ + transform(chunk, encoding, callback) { + const data = chunk.toString(); + const humanizedData = humanizeKeySequences(data); + const cleanData = stripAnsi(humanizedData); + transformResults.push(cleanData); + this.push(chunk); + callback(); + } + }); + + setupReadlineMock(inputQueue, currentInputIndex); + mockInput.pipe(transformStream); + + const enqueueInputResponse = (input: InputResponse) => { + lastScheduledTime += 350; + + if (input.type === 'key') { + setTimeout(() => mockInput.push(input.value), lastScheduledTime); + } else { + inputQueue.push(input); // We assume that handling read inputs remains the same unless you need to delay these as well + } + }; + + + return { + options, + mockInput, + mockOutput, + writeResults, + transformResults, + enqueueInputResponse + }; + }; + + return beforeEachSetup; +} diff --git a/workflows/cli/tsconfig.esm.json b/workflows/cli/tsconfig.esm.json new file mode 100644 index 000000000..800d7506d --- /dev/null +++ b/workflows/cli/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false + } +} diff --git a/workflows/cli/tsconfig.json b/workflows/cli/tsconfig.json new file mode 100644 index 000000000..1a9d5696c --- /dev/null +++ b/workflows/cli/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src/" + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] +} diff --git a/workflows/workflows/LICENSE b/workflows/workflows/LICENSE new file mode 100644 index 000000000..2619f34f0 --- /dev/null +++ b/workflows/workflows/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Dan Lynch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/workflows/workflows/README.md b/workflows/workflows/README.md new file mode 100644 index 000000000..2b59139bc --- /dev/null +++ b/workflows/workflows/README.md @@ -0,0 +1,39 @@ +# @chain-registry/workflows + +

+ +

+ +

+ + + + + +

+ +TODO + + +## Related + +Checkout these related projects: + +* [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules. +* [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) Convert your CosmWasm smart contracts into dev-friendly TypeScript classes. +* [chain-registry](https://github.com/cosmology-tech/chain-registry) Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application. +* [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface. +* [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command. +* [interchain-ui](https://github.com/cosmology-tech/interchain-ui) The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit. +* [starship](https://github.com/cosmology-tech/starship) Unified Testing and Development for the Interchain. + +## Credits + +πŸ›  Built by Cosmology β€”Β if you like our tools, please consider delegating to [our validator βš›οΈ](https://cosmology.zone/validator) + + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED β€œAS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/workflows/workflows/__tests__/__snapshots__/base.test.ts.snap b/workflows/workflows/__tests__/__snapshots__/base.test.ts.snap new file mode 100644 index 000000000..063ca3dd1 --- /dev/null +++ b/workflows/workflows/__tests__/__snapshots__/base.test.ts.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`types 1`] = ` +[ + "/assetlist.schema.ts", + "/chain.schema.ts", + "/ibc_data.schema.ts", + "/memo_keys.schema.ts", + "/versions.schema.ts", +] +`; diff --git a/workflows/workflows/__tests__/__snapshots__/camel.test.ts.snap b/workflows/workflows/__tests__/__snapshots__/camel.test.ts.snap new file mode 100644 index 000000000..063ca3dd1 --- /dev/null +++ b/workflows/workflows/__tests__/__snapshots__/camel.test.ts.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`types 1`] = ` +[ + "/assetlist.schema.ts", + "/chain.schema.ts", + "/ibc_data.schema.ts", + "/memo_keys.schema.ts", + "/versions.schema.ts", +] +`; diff --git a/workflows/workflows/__tests__/__snapshots__/registry.test.ts.snap b/workflows/workflows/__tests__/__snapshots__/registry.test.ts.snap new file mode 100644 index 000000000..221ca2423 --- /dev/null +++ b/workflows/workflows/__tests__/__snapshots__/registry.test.ts.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`registry 1`] = ` +{ + "assetLists": 290, + "chains": 263, + "ibcData": 616, + "memoKeys": 1, + "versions": 2, +} +`; diff --git a/workflows/workflows/__tests__/base.test.ts b/workflows/workflows/__tests__/base.test.ts new file mode 100644 index 000000000..d0c31c852 --- /dev/null +++ b/workflows/workflows/__tests__/base.test.ts @@ -0,0 +1,33 @@ +import { sync as globSync } from 'glob'; +import { join } from 'path'; + +import { SchemaTypeGenerator } from '../src'; +import { fixtureOutputDir, getRegistry } from '../test-utils'; + +const outputDir = join(fixtureOutputDir, 'base'); + +const registry = getRegistry() + +it('types', () => { + const generator = new SchemaTypeGenerator({ + outputDir, + supportedSchemas: [ + 'chain.schema.json', + 'assetlist.schema.json', + 'ibc_data.schema.json', + 'versions.schema.json', + 'memo_keys.schema.json', + ], + registry, + schemaTSOptions: { + strictTypeSafety: true, + useCamelCase: false, + useSingleQuotes: true + } + }); + generator.generateTypes(); + + const tsFiles = globSync(`${outputDir}/*.ts`).map(a=>a.split(outputDir)[1]) + expect(tsFiles).toMatchSnapshot(); + +}); \ No newline at end of file diff --git a/workflows/workflows/__tests__/camel.test.ts b/workflows/workflows/__tests__/camel.test.ts new file mode 100644 index 000000000..463801397 --- /dev/null +++ b/workflows/workflows/__tests__/camel.test.ts @@ -0,0 +1,33 @@ +import { sync as globSync } from 'glob'; +import { join } from "path"; + +import { SchemaTypeGenerator } from '../src'; +import { fixtureOutputDir, getRegistry } from '../test-utils'; + +const outputDir = join(fixtureOutputDir, 'camel'); + +const registry = getRegistry(); + +it('types', () => { + const generator = new SchemaTypeGenerator({ + outputDir, + supportedSchemas: [ + 'chain.schema.json', + 'assetlist.schema.json', + 'ibc_data.schema.json', + 'versions.schema.json', + 'memo_keys.schema.json', + ], + registry, + schemaTSOptions: { + strictTypeSafety: true, + useCamelCase: true, + useSingleQuotes: true + } + }); + generator.generateTypes(); + + const tsFiles = globSync(`${outputDir}/*.ts`).map(a=>a.split(outputDir)[1]) + expect(tsFiles).toMatchSnapshot(); + +}); \ No newline at end of file diff --git a/workflows/workflows/__tests__/registry.test.ts b/workflows/workflows/__tests__/registry.test.ts new file mode 100644 index 000000000..9b4ca5260 --- /dev/null +++ b/workflows/workflows/__tests__/registry.test.ts @@ -0,0 +1,22 @@ +import { join } from "path"; + +import { Registry } from "../src/registry"; +import { SchemaValidator } from "../src/validator"; + +const registry = new Registry( + join(__dirname, '/../../../packages/chain-registry/chain-registry') +); + +it('registry', () => { + expect(registry.count).toMatchSnapshot(); +}) + +it('validator', () => { + + const validator = new SchemaValidator( + registry + ); + + validator.validateAllData(); + +}) \ No newline at end of file diff --git a/workflows/workflows/jest.config.js b/workflows/workflows/jest.config.js new file mode 100644 index 000000000..0aa3aaa49 --- /dev/null +++ b/workflows/workflows/jest.config.js @@ -0,0 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + babelConfig: false, + tsconfig: "tsconfig.json", + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["dist/*"] +}; diff --git a/workflows/workflows/package.json b/workflows/workflows/package.json new file mode 100644 index 000000000..246a517be --- /dev/null +++ b/workflows/workflows/package.json @@ -0,0 +1,54 @@ +{ + "name": "@chain-registry/workflows", + "version": "1.26.3", + "description": "Chain Registry Workflows", + "author": "Dan Lynch ", + "homepage": "https://github.com/cosmology-tech/chain-registry", + "license": "SEE LICENSE IN LICENSE", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/chain-registry" + }, + "bugs": { + "url": "https://github.com/cosmology-tech/chain-registry/issues" + }, + "scripts": { + "copy": "copyfiles -f LICENSE README.md package.json dist", + "clean": "del dist/**", + "prepare": "npm run build", + "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy", + "test": "jest", + "test:watch": "jest --watch" + }, + "devDependencies": { + "@types/sha.js": "^2.4.0", + "strfy-js": "^2.2.2" + }, + "dependencies": { + "@chain-registry/interfaces": "^0.25.7", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "bignumber.js": "9.1.1", + "chalk": "^4.1.0", + "file-ts": "^0.7.15", + "glob": "^7.1.4", + "minimatch": "^9.0.4", + "mkdirp": "3.0.1", + "schema-typescript": "^0.2.5", + "sha.js": "^2.4.11", + "strfy-js": "^2.2.2" + }, + "keywords": [ + "chain-registry", + "web3", + "cosmos", + "interchain" + ] +} diff --git a/workflows/workflows/src/index.ts b/workflows/workflows/src/index.ts new file mode 100644 index 000000000..9de36411e --- /dev/null +++ b/workflows/workflows/src/index.ts @@ -0,0 +1,4 @@ +export * from './registry'; +export * from './schema-typescript'; +export * from './validator'; +export { JSONSchema } from 'schema-typescript'; diff --git a/workflows/workflows/src/registry.ts b/workflows/workflows/src/registry.ts new file mode 100644 index 000000000..4076e9df0 --- /dev/null +++ b/workflows/workflows/src/registry.ts @@ -0,0 +1,204 @@ +import { AssetList, Chain, IBCData, MemoKeys, Versions } from '@chain-registry/interfaces'; +import { readFileSync } from 'fs'; +import { sync as glob } from 'glob'; +import { basename } from 'path'; +import { JSONSchema } from "schema-typescript"; + +const SCHEMATA_MAPPING: Record = { + AssetList: 'assetLists', + Chain: 'chains', + IBCData: 'ibcData', + MemoKeys: 'memoKeys', + Versions: 'versions' +}; + +const SCHEMA_WHITELIST = [ + 'assetlist.schema.json', + 'chain.schema.json', + 'ibc_data.schema.json', + 'memo_keys.schema.json', + 'versions.schema.json' +]; + +export interface JSONSchemaContent { + $schemaFile: string; + path: string; + content: T; // Now generic, holds specific schema data type +} +export interface DataMapping { + AssetList: JSONSchemaContent[] + IBCData: JSONSchemaContent[] + Chain: JSONSchemaContent[] + MemoKeys: JSONSchemaContent[] + Versions: JSONSchemaContent[] +} + +const IGNORE_ROOT_DIRS = [ + `_template`, + `.github`, + `.git`, + `node_modules` +]; +export interface SchemaMapping { + AssetList: JSONSchemaContent; + IBCData: JSONSchemaContent; + Chain: JSONSchemaContent; + MemoKeys: JSONSchemaContent; + Versions: JSONSchemaContent; +} + +export class Registry { + private definitions: JSONSchemaContent[]; + public basePath: string; + public schemaMappings: SchemaMapping = { + AssetList: null, + IBCData: null, + Chain: null, + MemoKeys: null, + Versions: null + }; + public dataMappings: DataMapping = { + AssetList: [], + IBCData: [], + Chain: [], + MemoKeys: [], + Versions: [] + }; + + constructor(basePath: string) { + this.basePath = basePath; + this.initializeData(); + } + + private isJsonSchema(schema: JSONSchema): boolean { + const $schema = schema.$schema; + if (!$schema) return false; + return true; + } + + private startsWithUrl(schema: JSONSchema): boolean { + return (/^http/.test(schema.$schema)) + } + + private isSchema(schema: JSONSchema): boolean { + if (!this.isJsonSchema(schema)) return false; + if (!this.startsWithUrl(schema)) return false; + const url = new URL(schema.$schema); + const def = url.pathname; + if (def.match(/\/draft-0[47]\/schema$/)) { + return true; + } + return false; + } + + private getSchemaFrom$Schema(data: JSONSchemaContent): JSONSchema { + const schema = this.definitions.find(defn => { + const pred = basename(defn.path) === data.$schemaFile; + return pred; + }); + if (!schema) { + console.warn('missing schema definition: ' + data.$schemaFile); + } + return schema.content; + } + + private isData(schema: JSONSchema): boolean { + if (!this.isJsonSchema(schema)) return false; + if (this.startsWithUrl(schema)) return false; + if (SCHEMA_WHITELIST.includes(basename(schema.$schema))) return true; + return false; + } + + private loadData(schema: JSONSchemaContent): void { + if (this.isData(schema.content)) { + const defn = this.getSchemaFrom$Schema(schema); + this.dataMappings[defn.title as keyof DataMapping].push(schema as any); + } + } + + private initStoreForSchema(schema: JSONSchemaContent) { + // if it exists return + if (this.schemaMappings[schema.content.title as keyof SchemaMapping]) return; + + // initialize + this.schemaMappings[schema.content.title as keyof SchemaMapping] = schema; + } + + private initializeData(): void { + let types: any = {}; + + // parse every JSON file + this.definitions = glob(`${this.basePath}/**/*.json`, { + // ignore certain root directories + ignore: IGNORE_ROOT_DIRS.map(dir=>`${this.basePath}/${dir}/**/*`) + }) + .map(path => { + const content = JSON.parse(readFileSync(path, 'utf-8')); + if (!this.isJsonSchema(content)) return; + // https://stackoverflow.com/questions/69133771/ajv-no-schema-with-key-or-ref-https-json-schema-org-draft-07-schema + content.$schema = content.$schema.replace(/https/, 'http'); + types[basename(content.$schema)] = true; + return { + $schemaFile: basename(content.$schema), + path, + content + }; + }).filter(Boolean) + + // filter out schemas (e.g. draft-04/schema ) + const schemas = this.definitions.filter(schema => this.isSchema(schema.content)).filter(Boolean); + + // validate + schemas.forEach(schema => { + if (!(schema.content.title in SCHEMATA_MAPPING)) throw new Error('MISSING SCHEMA: ' + schema.content.title) + }); + + // create schemaMappings and data + schemas.forEach(schema => { + this.initStoreForSchema(schema); + }); + + // load data + this.definitions + .filter(d => SCHEMA_WHITELIST.includes(d.$schemaFile)) + .forEach(schema => { + this.loadData(schema) + }) + } + + public get chains(): Chain[] { + return this.dataMappings.Chain.map(c => c.content); + } + + public get assetLists(): AssetList[] { + return this.dataMappings.AssetList.map(c => c.content); + } + + public get ibcData(): IBCData[] { + return this.dataMappings.IBCData.map(c => c.content); + } + + public get memoKeys(): MemoKeys[] { + return this.dataMappings.MemoKeys.map(c => c.content); + } + + public get versions(): Versions[] { + return this.dataMappings.Versions.map(c => c.content); + } + + public get schemas(): JSONSchemaContent[] { + return Object.entries(this.schemaMappings).map(([_str, obj])=> { + return obj as JSONSchemaContent; + }) + } + + public get count() { + return { + chains: this.chains.length, + assetLists: this.assetLists.length, + ibcData: this.ibcData.length, + memoKeys: this.memoKeys.length, + versions: this.versions.length, + } + } +} \ No newline at end of file diff --git a/workflows/workflows/src/schema-typescript.ts b/workflows/workflows/src/schema-typescript.ts new file mode 100644 index 000000000..cc5223295 --- /dev/null +++ b/workflows/workflows/src/schema-typescript.ts @@ -0,0 +1,90 @@ +import * as fs from 'fs'; +import { basename, dirname, join } from 'path'; +import { generateTypeScript, JSONSchema, SchemaTSOptions } from 'schema-typescript'; + +import { Registry } from './registry'; + +// Default titles for certain schemas +// TODO create issue in cosmos/chain-registry +const DEFAULT_TITLES: { [filename: string]: string } = { + 'ibc_data.schema.json': 'IBCData', + 'chain.schema.json': 'Chain', + 'assetlist.schema.json': 'AssetList', + 'versions.schema.json': 'Versions', + 'memo_keys.schema.json': 'MemoKeys', +}; + + +// Define an interface for the constructor options +export interface SchemaTypeGeneratorOptions { + outputDir: string; + schemaTSOptions: Partial; + supportedSchemas?: string[]; + registry: Registry; +} + +export class SchemaTypeGenerator { + private outputDir: string; + private registry: Registry; + private schemaTSOptions: Partial + private supportedSchemas: Set; + + constructor(options: SchemaTypeGeneratorOptions) { + this.outputDir = options.outputDir; + this.registry = options.registry; + this.schemaTSOptions = options.schemaTSOptions; + this.supportedSchemas = new Set(options.supportedSchemas || []); + } + + private updateSchemaTitle(schema: JSONSchema, schemaFile: string): void { + const filename = basename(schemaFile); + if (DEFAULT_TITLES[filename]) { + schema.title = DEFAULT_TITLES[filename]; + } + } + + private isSchemaSupported(filePath: string): boolean { + if (this.supportedSchemas.size === 0) return true; // If no filter is provided, process all files + const filename = basename(filePath); + return this.supportedSchemas.has(filename); + } + + public generateTypes(): void { + this.registry.schemas.forEach(fileInfo => { + const schemaFile = fileInfo.path; + if (this.isSchemaSupported(schemaFile)) { + try { + const schema = fileInfo.content; + this.updateSchemaTitle(schema, schemaFile); + const result = generateTypeScript(schema, this.schemaTSOptions); + const filename = this.getOutputFilename(schemaFile); + this.ensureDirExists(filename); + this.writeFile(filename, result); + } catch (e) { + console.log({ schemaFile }) + } + } + }); + } + + private getOutputFilename(schemaFile: string): string { + const filename = basename(schemaFile); + return join(this.outputDir, filename.replace(/.json$/, '.ts')); + } + + private ensureDirExists(filePath: string): void { + this.mkdirpSync(dirname(filePath)); + } + + private mkdirpSync(p: string): void { + if (!fs.existsSync(p)) { + this.mkdirpSync(dirname(p)); + fs.mkdirSync(p); + } + } + + + private writeFile(filePath: string, content: string): void { + fs.writeFileSync(filePath, content); + } +} diff --git a/workflows/workflows/src/utils.ts b/workflows/workflows/src/utils.ts new file mode 100644 index 000000000..25d78d59c --- /dev/null +++ b/workflows/workflows/src/utils.ts @@ -0,0 +1,12 @@ +import { toCamelCase, toPascalCase } from "schema-typescript"; + +export const camelCase = (str: string) => { + if (str === 'IBCData') { + return 'ibcData' + } + return toCamelCase(str); +} + +export const pascalCase = (str: string) => { + return toPascalCase(str); +} \ No newline at end of file diff --git a/workflows/workflows/src/validator.ts b/workflows/workflows/src/validator.ts new file mode 100644 index 000000000..ce3c976f5 --- /dev/null +++ b/workflows/workflows/src/validator.ts @@ -0,0 +1,59 @@ +import Ajv, { ValidateFunction } from 'ajv/dist/2019'; +import addFormats from 'ajv-formats'; +import chalk from 'chalk'; +import { JSONSchema } from 'schema-typescript'; + +import { DataMapping, JSONSchemaContent, Registry } from './registry'; + +export interface SchemaValidatorOptions { + useStrict?: boolean; + allErrors?: boolean; + useDefaults?: boolean; +} + +export class SchemaValidator { + private ajv: Ajv; + private registry: Registry; + + constructor(registry: Registry, options?: SchemaValidatorOptions) { + const { useStrict = false, allErrors = true, useDefaults = true } = options ?? {}; + + this.ajv = new Ajv({ + strict: useStrict, + allErrors, + useDefaults + }); + + this.registry = registry; + addFormats(this.ajv); + } + + public validateAllData(verbose: boolean = false) { + // Compile and validate each schema, then validate corresponding data + Object.entries(this.registry.schemaMappings).forEach(([title, schema]) => { + schema.content.$schema = 'https://json-schema.org/draft/2019-09/schema'; + const validate: ValidateFunction = this.ajv.compile(schema.content); + const dataMap = this.registry.dataMappings[title as keyof DataMapping]; + + if (!dataMap) { + console.error(chalk.yellow(`⚠️ No data found for schema titled ${chalk.bold(title)}`)); + return; + } + + dataMap.forEach(data => { + this.validateJsonSchema(data, title, validate, verbose); + }); + }); + } + + private validateJsonSchema(data: JSONSchemaContent, title: string, validate: ValidateFunction, verbose: boolean) { + if (!validate(data.content)) { + console.error(chalk.red(`❌ Validation errors for ${chalk.bold(title)} in file ${chalk.magenta(data.path)}:`)); + validate.errors?.forEach(error => { + console.error(chalk.red(` ➑️ ${error.instancePath} ${error.message}`)); + }); + } else if (verbose) { + console.log(chalk.green(`βœ… Validation passed for ${chalk.bold(title)} in file ${chalk.magenta(data.path)}`)); + } + } +} diff --git a/workflows/workflows/test-utils/fixtures.ts b/workflows/workflows/test-utils/fixtures.ts new file mode 100644 index 000000000..00aef3216 --- /dev/null +++ b/workflows/workflows/test-utils/fixtures.ts @@ -0,0 +1,12 @@ +import { join, resolve } from "path"; + +import { Registry } from "../src/registry"; + +export const getRegistry = () => { + const registry = new Registry( + join(__dirname, '/../../../packages/chain-registry/chain-registry') + ); + return registry; +} + +export const fixtureOutputDir = resolve(__dirname +'/../../../__output__/'); diff --git a/workflows/workflows/test-utils/glob.ts b/workflows/workflows/test-utils/glob.ts new file mode 100644 index 000000000..aa52c9c6c --- /dev/null +++ b/workflows/workflows/test-utils/glob.ts @@ -0,0 +1,35 @@ +// @ts-nocheck +import { readdirSync } from 'file-ts' +import { join } from 'file-ts/main/emulation/path'; +import { minimatch } from 'minimatch'; + +/** + * Synchronous, recursive function to list files matching a glob pattern in a directory and its subdirectories using minimatch. + * @param dirPath Directory to search within + * @param pattern Glob pattern to match filenames (e.g., '*.txt') + * @returns Array of matching filenames, including path relative to the initial directory + */ +export function globSync(dirPath: string, pattern: string): string[] { + let results: string[] = []; + + function recurse(currentPath) { + const entries = readdirSync(currentPath, { withFileTypes: true }); + + for (let entry of entries) { + const fullPath = join(currentPath, entry.name); + if (entry.isDirectory()) { + recurse(fullPath); // Recursively search in subdirectory + } else if (minimatch(entry.name, pattern)) { + results.push(fullPath); // Add file to results if it matches the pattern + } + } + } + + try { + recurse(dirPath); // Start the recursion from the initial directory path + return results; + } catch (err) { + console.error('Error:', err); + return []; // Return an empty array in case of an error + } +} \ No newline at end of file diff --git a/workflows/workflows/test-utils/index.ts b/workflows/workflows/test-utils/index.ts new file mode 100644 index 000000000..f382a627f --- /dev/null +++ b/workflows/workflows/test-utils/index.ts @@ -0,0 +1,2 @@ +export * from './fixtures'; +export * from './glob'; \ No newline at end of file diff --git a/workflows/workflows/tsconfig.esm.json b/workflows/workflows/tsconfig.esm.json new file mode 100644 index 000000000..800d7506d --- /dev/null +++ b/workflows/workflows/tsconfig.esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "es2022", + "rootDir": "src/", + "declaration": false + } +} diff --git a/workflows/workflows/tsconfig.json b/workflows/workflows/tsconfig.json new file mode 100644 index 000000000..1a9d5696c --- /dev/null +++ b/workflows/workflows/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src/" + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "**/*.spec.*", "**/*.test.*"] +} diff --git a/yarn.lock b/yarn.lock index 6ff8e9350..4c86cd83e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,7 +28,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== @@ -1516,7 +1516,7 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== -"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.12.7": +"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.12.5", "@types/node@^20.12.7": version "20.12.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== @@ -1538,6 +1538,14 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== +"@types/readable-stream@^4.0.10": + version "4.0.11" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-4.0.11.tgz#684f1e947c90cb6a8ad3904523d650bb66cdbb84" + integrity sha512-R3eUMUTTKoIoaz7UpYLxvZCrOmCRPRbAmoDDHKcimTEySltaJhF8hLzj4+EzyDifiX5eK6oDQGSfmNnXjxZzYQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + "@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" @@ -1712,6 +1720,13 @@ abbrev@^2.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1762,6 +1777,13 @@ aggregate-error@^4.0.0: clean-stack "^4.0.0" indent-string "^5.0.0" +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1772,6 +1794,16 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@^4.1.1: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" @@ -2754,7 +2786,7 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.2.2: +deepmerge@^4.2.2, deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -3144,11 +3176,21 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" @@ -3279,6 +3321,17 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-ts@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/file-ts/-/file-ts-0.7.15.tgz#85d8f3b3c6bf3abab2e5fa6c33403f501a6d6387" + integrity sha512-CUXGAcIZH4SnBTsIFJ9s1QfnHmC4qAjSnAvySuBotX8SdDEOoloFNupJ7Bdyk9MpGish8s49Av9WK81DWtse5w== + dependencies: + "@types/node" "^20.12.5" + "@types/readable-stream" "^4.0.10" + buffer "^6.0.3" + minimatch "^9.0.3" + readable-stream "^4.5.2" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -4002,6 +4055,16 @@ inquirer@^8.2.4: through "^2.3.6" wrap-ansi "^6.0.1" +inquirerer@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/inquirerer/-/inquirerer-1.6.1.tgz#669fd17c9a1559ba1a42ad71af8a3fc9fa76a415" + integrity sha512-fV1We5PFBcmbmszubXW6PGFj7gtYYnkZ6XArjnHjKGdjsL1KWuuO9Z4LQdScG32qZTWzpTtwUIQxxYq6BFKU+g== + dependencies: + chalk "^4.1.0" + deepmerge "^4.3.1" + js-yaml "^4.1.0" + minimist "^1.2.8" + ip-address@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" @@ -4659,6 +4722,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -5186,7 +5254,7 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1: +minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3, minimatch@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== @@ -6114,6 +6182,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + promise-all-reject-late@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" @@ -6360,6 +6433,17 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stre string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + readable-stream@~1.0.31: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -6404,6 +6488,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -6516,6 +6605,16 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +schema-typescript@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/schema-typescript/-/schema-typescript-0.2.5.tgz#7ada4e9287dade85cb379ac1fdbc055264e4e166" + integrity sha512-PauNlmaOuGjOce9A0njOlxshRm6iYSzgXSH6yKQ2gM4S3kIpRmZ3/l/ekQYxgvEab7KQN9qQbOX05x58KuTU7w== + dependencies: + "@babel/core" "^7.24.4" + "@babel/generator" "^7.24.4" + "@babel/types" "^7.24.0" + deepmerge "^4.3.1" + "semver@2 || 3 || 4 || 5", semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -6755,6 +6854,11 @@ strfy-js@^1.5.0: resolved "https://registry.yarnpkg.com/strfy-js/-/strfy-js-1.5.0.tgz#80da9fe2a0599a6a7a36f7b514a4fd32323980ba" integrity sha512-QHyrXpVazTuLBRFLf96/pQaZ25WFq693KEfMfwVNB2Chj4QkTEXYXrJKULRTCBvADs35+Rl915A1saxZNT5X0A== +strfy-js@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/strfy-js/-/strfy-js-2.2.2.tgz#c97417f2bda827472ee8906bf94adb71cf185204" + integrity sha512-12QFZhbUY1nyyem5G/aLA34g8a8/GApAdLwX0xSu0syTuLXA3iK4kPIlZE+0fxsX6GudS+nA6a1FuWNnfAHpTg== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -6763,16 +6867,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6790,7 +6885,7 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -6809,14 +6904,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7430,7 +7518,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -7448,15 +7536,6 @@ wrap-ansi@^6.0.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"