From fc4d9745f4ab8939dee6a4e9e3bd0851b380d393 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 19 Jun 2024 22:14:13 +0800 Subject: [PATCH 01/13] Add documentation for packet-forwarding addition --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 653749c..7d73405 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Currently, each JSON file contain the following data on its corresponding networ - blacklisted tokens - default blockchain transfer option order in deposit/withdrawal forms dropdown - default network token fee order +- config of IBC channels for external IBC chains (such as Osmosis, Noble, etc.) +- information about IBC tokens that are not added on chain or require packet forwarding Additionally, the JSON file for mainnet contains the following data to support ongoing campaigns/promotions: - demex points config @@ -48,6 +50,28 @@ More metadata will be added in the future if required by the Demex frontend. Ple "token_denom_1": 0, "token_denom_2": 1, "token_denom_3": 2 - } + }, + "external_chain_channels": { + "blockchain_1_from": { + "blockchain_1_to_1": "channel_1", + "blockchain_1_to_2": "channel_2" + }, + "blockchain_2_from": { + "blockchain_2_to_1": "channel_3", + "blockchain_2_to_2": "channel_4", + "blockchain_2_to_3": "channel_5" + } + }, + "additional_ibc_token_config": [{ + "baseDenom": "denom_1", + "chainRoutes": ["blockchain_1", "blockchain_2"] + }, { + "baseDenom": "denom_2", + "chainRoutes": ["blockchain_3", "blockchain_4"] + }, { + "baseDenom": "denom_3", + "chainRoutes": ["blockchain_5", "blockchain_6"], + "denomOnCarbon": "carbon_denom_1" + }] } ``` From 1d1369ce105640c8568da0352ee81e040dc09740 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Fri, 28 Jun 2024 15:50:16 +0800 Subject: [PATCH 02/13] Polish documentation in README.md and PR Template markdown --- .github/markets/pr_template.md | 13 +++++++++++-- README.md | 16 ++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/markets/pr_template.md b/.github/markets/pr_template.md index ad86dc2..58d046e 100644 --- a/.github/markets/pr_template.md +++ b/.github/markets/pr_template.md @@ -16,6 +16,8 @@ Each json file under the [configs](../../configs) folder correspond to their res |`perp_pool_banners` |`PerpPoolBanner` |true |List of Objects that indicate the banner content on specific perp pool pages. | |`demex_points_config` |`DemexPointsConfig` |false |Object that contains the parameters to earn demex points. |This object **must be included** for mainnet.json as demex points is already live on mainnet. | |`perp_pool_promo` |`PerpPoolPromo` |false |Map of Objects that contains perp pool promo parameters for each pool |If the `perp_pool_promo` property is omitted, no promo will be shown. The key of each entry is the ids of the perp pools with existing promo. | +|`external_chain_channels` |`obj` |true |Map of Objects containing destination channels for external IBC chains (e.g. Osmosis, Noble, etc.) |1. To transfer tokens from Osmosis => Noble, you need to look for the `Osmosis` object, then search for `Noble` in the object to get the channel to be input in `sourceChannel` for MsgTransfer tx msg (in this case channel-750)

2. Blockchain names in this object **MUST** match the valid chainName of the bridges listed under BridgeAll RPC call.

To view the values of BridgeAll RPC call, simply run `yarn get-bridges [network]` on the command line. Sample for mainnet: `yarn get-bridges mainnet` | +|`additional_ibc_token_config` |`AdditionalIBCTokenConfig[]` |true |List of information about IBC tokens that are not added on chain or require packet forwarding. | ## Maintenance Data Structure |Field |Type |Required |Description |Notes | @@ -40,10 +42,17 @@ Each json file under the [configs](../../configs) folder correspond to their res |`depositsPerSpin` |`integer` |true |Amount deposited in the perp pool that will earn 1 spin after 1 week. | |`tradingVolumePerSpin` |`integer` |true |Volume traded on perp markets that will earn 1 spin. | -## PerpPoolPromo +## PerpPoolPromo Data Structure |Field |Type |Required |Description |Notes | |---|---|---|---|---| |`start` |`string` |true |Start time of the promo. | |`end` |`string` |true |End time of the promo. | |`perpPoolDepositBoost` |`integer` |true |Boost to perp pool deposits required to earn 1 demex point spin. | -|`perpTradingBoost` |`integer` |true |Boost to trading volume required to earn 1 demex point spin. | \ No newline at end of file +|`perpTradingBoost` |`integer` |true |Boost to trading volume required to earn 1 demex point spin. | + +## AdditionalIBCTokenConfig Data Structure +|Field |Type |Required |Description |Notes | +|---|---|---|---|---| +|`baseDenom` |`string` |true |The denom of this token on its native chain (e.g. `uosmo` for $OSMO on Osmosis, `uatom` for $ATOM on CosmosHub) | +|`chainRoutes` |`string[]` |true |The list of IBC chains that this token needs to be forwarded through in order to be deposited into Carbon blockchain. |Blockchain networks in this array **MUST** match the valid chainName of the bridges listed under BridgeAll RPC call.

To view the values of BridgeAll RPC call, simply run `yarn get-bridges [network]` on the command line. Sample for mainnet: `yarn get-bridges mainnet` | +|`denomOnCarbon` |`string` |false |Denom of token that is added to Carbon chain but still requires packet-forwarding (omit if this token is **NOT** added to Carbon chain) |The denom in this field **MUST** match the token denoms listed under the Carbon [Tokens API](https://api.carbon.network/carbon/coin/v1/tokens?pagination.limit=10000). | \ No newline at end of file diff --git a/README.md b/README.md index 7d73405..da4514e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Currently, each JSON file contain the following data on its corresponding networ - blacklisted tokens - default blockchain transfer option order in deposit/withdrawal forms dropdown - default network token fee order -- config of IBC channels for external IBC chains (such as Osmosis, Noble, etc.) +- map of IBC channels for external IBC chains (such as Osmosis, Noble, etc.) - information about IBC tokens that are not added on chain or require packet forwarding Additionally, the JSON file for mainnet contains the following data to support ongoing campaigns/promotions: @@ -52,14 +52,14 @@ More metadata will be added in the future if required by the Demex frontend. Ple "token_denom_3": 2 }, "external_chain_channels": { - "blockchain_1_from": { - "blockchain_1_to_1": "channel_1", - "blockchain_1_to_2": "channel_2" + "from_blockchain_1": { + "to_blockchain_1": "channel_1", + "to_blockchain_2": "channel_2" }, - "blockchain_2_from": { - "blockchain_2_to_1": "channel_3", - "blockchain_2_to_2": "channel_4", - "blockchain_2_to_3": "channel_5" + "from_blockchain_2": { + "to_blockchain_3": "channel_3", + "to_blockchain_4": "channel_4", + "to_blockchain_5": "channel_5" } }, "additional_ibc_token_config": [{ From fdcf139331a1df0a52b66dca36cce586ff61c114 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Fri, 28 Jun 2024 16:27:14 +0800 Subject: [PATCH 03/13] Add schema definition for newly added fields --- .github/markets/pr_template.md | 2 +- config.schema.json | 52 +++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/markets/pr_template.md b/.github/markets/pr_template.md index 58d046e..3a85b21 100644 --- a/.github/markets/pr_template.md +++ b/.github/markets/pr_template.md @@ -54,5 +54,5 @@ Each json file under the [configs](../../configs) folder correspond to their res |Field |Type |Required |Description |Notes | |---|---|---|---|---| |`baseDenom` |`string` |true |The denom of this token on its native chain (e.g. `uosmo` for $OSMO on Osmosis, `uatom` for $ATOM on CosmosHub) | -|`chainRoutes` |`string[]` |true |The list of IBC chains that this token needs to be forwarded through in order to be deposited into Carbon blockchain. |Blockchain networks in this array **MUST** match the valid chainName of the bridges listed under BridgeAll RPC call.

To view the values of BridgeAll RPC call, simply run `yarn get-bridges [network]` on the command line. Sample for mainnet: `yarn get-bridges mainnet` | +|`chainRoutes` |`string[]` |true |The list of IBC chains that this token needs to be forwarded through in order to be deposited into Carbon blockchain. |1. You need to add **at least 1** blockchain network to this array.

2. Blockchain networks in this array **MUST** match the valid chainName of the bridges listed under BridgeAll RPC call.

To view the values of BridgeAll RPC call, simply run `yarn get-bridges [network]` on the command line. Sample for mainnet: `yarn get-bridges mainnet` | |`denomOnCarbon` |`string` |false |Denom of token that is added to Carbon chain but still requires packet-forwarding (omit if this token is **NOT** added to Carbon chain) |The denom in this field **MUST** match the token denoms listed under the Carbon [Tokens API](https://api.carbon.network/carbon/coin/v1/tokens?pagination.limit=10000). | \ No newline at end of file diff --git a/config.schema.json b/config.schema.json index 6d7c93f..22e622d 100644 --- a/config.schema.json +++ b/config.schema.json @@ -10,7 +10,9 @@ "blacklisted_tokens", "transfer_options", "network_fees", - "perp_pool_banners" + "perp_pool_banners", + "external_chain_channels", + "additional_ibc_token_config" ], "properties": { "network": { @@ -159,6 +161,28 @@ } } }, + "external_chain_channels": { + "type": "object", + "description": "Map of destination channels for external IBC chains", + "patternProperties": { + "^[\\w ]+$": { + "type": "object", + "patternProperties": { + "^[\\w ]+$": { + "type": "string", + "pattern": "^channel-[\\d]+$" + } + } + } + } + }, + "additional_ibc_token_config": { + "type": "array", + "description": "List of information for tokens that (1) are not added on Carbon blockchain or (2) require packet forwarding", + "items": { + "$ref": "#/$defs/additional_ibc_token_info" + } + }, "$defs": { "prelaunch_market": { "type": "string", @@ -225,6 +249,32 @@ "perpTradingBoost": { "type": "integer", "description": "The spin boost multiplier for boosted perp markets trading volume" + }, + "additional_ibc_token_info": { + "type": "object", + "description": "Information for token that (1) is not added on Carbon blockchain or (2) requires packet forwarding.", + "required": [ + "baseDenom", + "chainRoutes" + ], + "properties": { + "baseDenom": { + "type": "string", + "description": "Denom of token on its native chain" + }, + "chainRoutes": { + "type": "array", + "description": "List of IBC chains that token needs to be forwarded through before being deposited into Carbon", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "denomOnCarbon": { + "type": "string", + "description": "Denom of token on Carbon chain (omit if token is not added to Carbon chain)" + } + } } } } \ No newline at end of file From 190568a18d9a0599d40abe84e41bab6ef1f1fd1e Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Fri, 28 Jun 2024 16:29:18 +0800 Subject: [PATCH 04/13] Add required fields in json files --- configs/devnet.json | 4 +++- configs/mainnet.json | 4 +++- configs/testnet.json | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/configs/devnet.json b/configs/devnet.json index ef23ece..a1473b5 100644 --- a/configs/devnet.json +++ b/configs/devnet.json @@ -14,5 +14,7 @@ "usdc": 1, "eth": 2 }, - "perp_pool_banners": [] + "perp_pool_banners": [], + "external_chain_channels": {}, + "additional_ibc_token_config": [] } diff --git a/configs/mainnet.json b/configs/mainnet.json index 2d7c615..259fd23 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -199,5 +199,7 @@ "perpPoolDepositBoost": 2, "perpTradingBoost": 3 } - } + }, + "external_chain_channels": {}, + "additional_ibc_token_config": [] } diff --git a/configs/testnet.json b/configs/testnet.json index 8674c3c..185589f 100644 --- a/configs/testnet.json +++ b/configs/testnet.json @@ -32,5 +32,7 @@ "symbol": "1000PEPE" } } - } + }, + "external_chain_channels": {}, + "additional_ibc_token_config": [] } From 89ec75abd6d97e0352a0fa1cab9f9946f121cfe3 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Fri, 28 Jun 2024 17:11:19 +0800 Subject: [PATCH 05/13] Move additional token information config to mainnet.json --- configs/mainnet.json | 86 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index 259fd23..2f5ebc7 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -200,6 +200,88 @@ "perpTradingBoost": 3 } }, - "external_chain_channels": {}, - "additional_ibc_token_config": [] + "external_chain_channels": { + "Archway": { + "Noble": "channel-29" + }, + "Axelar": { + "Osmosis": "channel-3" + }, + "DYDX": { + "Noble": "channel-0" + }, + "Osmosis": { + "Axelar": "channel-208", + "Carbon": "channel-188", + "Cosmos Hub": "channel-0", + "Kujira": "channel-259", + "Noble": "channel-750", + "Stride": "channel-326" + }, + "Cosmos Hub": { + "Stride": "channel-391", + "Noble": "channel-536", + "Osmosis": "channel-141" + }, + "Kujira": { + "Noble": "channel-62", + "Osmosis": "channel-3" + }, + "Noble": { + "Archway": "channel-12", + "Cosmos Hub": "channel-4", + "DYDX": "channel-33", + "Kujira": "channel-2", + "Osmosis": "channel-1", + "Stargaze": "channel-11", + "Terra": "channel-30" + }, + "Stargaze": { + "Noble": "channel-204" + }, + "Stride": { + "Cosmos Hub": "channel-0", + "Osmosis": "channel-5" + }, + "Terra": { + "Noble": "channel-253" + } + }, + "additional_ibc_token_config": [{ + "baseDenom": "uusdc", + "chainRoutes": ["Archway", "Noble"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["Cosmos Hub", "Noble"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["DYDX", "Noble"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["Kujira", "Noble"] + }, { + "baseDenom": "swth", + "chainRoutes": ["Osmosis"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["Osmosis", "Noble"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["Stargaze", "Noble"] + }, { + "baseDenom": "uusdc", + "chainRoutes": ["Terra", "Noble"] + }, { + "baseDenom": "uatom", + "chainRoutes": ["Osmosis", "Cosmos Hub"], + "denomOnCarbon": "ibc/6CDD4663F2F09CD62285E2D45891FC149A3568E316CE3EBBE201A71A78A69388" + }, { + "baseDenom": "ustrd", + "chainRoutes": ["Osmosis", "Stride"], + "denomOnCarbon": "ibc/FCFF8B19C61677F3B78E2A5AE3B4A34A8D23858D16905F253B8438B3AFD07FF8" + }, { + "baseDenom": "ustrd", + "chainRoutes": ["Cosmos Hub", "Stride"], + "denomOnCarbon": "ibc/B8D03406E060650ECE2D521287AC9A94D036C4C78B4AB871AC740A5FF2030D79" + }] } From 24b3224273b9f770abdedbbf9d3198877b04f185 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 3 Jul 2024 22:03:02 +0800 Subject: [PATCH 06/13] Modify regex pattern for external_chain_channels --- config.schema.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/config.schema.json b/config.schema.json index 22e622d..899d9f7 100644 --- a/config.schema.json +++ b/config.schema.json @@ -165,16 +165,17 @@ "type": "object", "description": "Map of destination channels for external IBC chains", "patternProperties": { - "^[\\w ]+$": { + "^[0-9A-Za-z ]+$": { "type": "object", "patternProperties": { - "^[\\w ]+$": { + "^[0-9A-Za-z ]+$": { "type": "string", - "pattern": "^channel-[\\d]+$" + "pattern": "^channel-([0-9]+)$" } } } - } + }, + "additionalProperties": false }, "additional_ibc_token_config": { "type": "array", From aac7d9b698b9763cffc7b986ca956552485aff9f Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 3 Jul 2024 22:35:32 +0800 Subject: [PATCH 07/13] Upgrade carbon-js-sdk --- package.json | 4 +- scripts/check_configs.ts | 66 +++++++++++---------------------- scripts/get_all_bridges.ts | 9 ++--- scripts/get_all_network_fees.ts | 9 ++--- scripts/get_perp_pool_ids.ts | 9 ++--- yarn.lock | 8 ++-- 6 files changed, 36 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index 900c78d..24628b7 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,11 @@ "@cosmjs/tendermint-rpc": "~0.31.3", "@types/node": "^18.11.9", "@types/node-fetch": "^2.6.2", - "carbon-js-sdk": "^0.10.5", + "carbon-js-sdk": "^0.11.1", "long": "^4.0.0", "node-fetch": "^2.6.1", "pajv": "^1.2.0", "ts-node": "^10.9.1", "typescript": "^4.9.3" } -} \ No newline at end of file +} diff --git a/scripts/check_configs.ts b/scripts/check_configs.ts index c8facbc..d209cf1 100644 --- a/scripts/check_configs.ts +++ b/scripts/check_configs.ts @@ -1,6 +1,7 @@ -import { CarbonSDK } from 'carbon-js-sdk'; -import * as fs from 'fs'; -import Long from 'long'; +import { CarbonSDK } from "carbon-js-sdk"; +import { PageRequest } from "carbon-js-sdk/lib/codec/cosmos/base/query/v1beta1/pagination"; +import * as fs from "fs"; +import Long from "long"; const cwd = process.cwd(); const myArgs = process.argv.slice(2); @@ -148,27 +149,23 @@ async function main() { if (jsonData) { // query all markets const allMarkets = await sdk.query.market.MarketAll({ - pagination: { + pagination: PageRequest.fromPartial({ limit: new Long(100000), - offset: new Long(0), - key: new Uint8Array(), - countTotal: true, - reverse: false, - }, + }), }); const markets: string[] = allMarkets.markets.map(market => market.id); // look for invalid market entries const hasInvalidPrelaunchMarkets = checkValidEntries(jsonData.prelaunch_markets, markets); if (hasInvalidPrelaunchMarkets.status && hasInvalidPrelaunchMarkets.entry) { - let listOfInvalidMarkets: string = hasInvalidPrelaunchMarkets.entry.join(', '); + let listOfInvalidMarkets: string = hasInvalidPrelaunchMarkets.entry.join(", "); console.error(`ERROR: ${network}.json has the following invalid pre-launch market entries: ${listOfInvalidMarkets}. Please make sure to only input valid markets in ${network}`); outcomeMap[network] = false; } const hasInvalidBlacklistedMarkets = checkValidEntries(jsonData.blacklisted_markets, markets); if (hasInvalidBlacklistedMarkets.status && hasInvalidBlacklistedMarkets.entry) { - let listOfInvalidMarkets: string = hasInvalidBlacklistedMarkets.entry.join(', '); + let listOfInvalidMarkets: string = hasInvalidBlacklistedMarkets.entry.join(", "); console.error(`ERROR: ${network}.json has the following invalid blacklisted market entries: ${listOfInvalidMarkets}. Please make sure to only input valid markets in ${network}`); outcomeMap[network] = false; } @@ -198,19 +195,15 @@ async function main() { // query all liquidity pools const allPools = await sdk.query.liquiditypool.PoolAll({ - pagination: { + pagination: PageRequest.fromPartial({ limit: new Long(100000), - offset: new Long(0), - key: new Uint8Array(), - countTotal: true, - reverse: false, - } + }), }); const pools: string[] = allPools.pools.map(pool => pool.pool?.id.toString() ?? ""); const hasInvalidPools = checkValidEntries(jsonData.blacklisted_pools, pools); if (hasInvalidPools.status && hasInvalidPools.entry) { - let listOfInvalidPools: string = hasInvalidPools.entry.join(', '); + let listOfInvalidPools: string = hasInvalidPools.entry.join(", "); console.error(`ERROR: ${network}.json has the following invalid pool id entries: ${listOfInvalidPools}. Please make sure to only input valid pool id in ${network}`); outcomeMap[network] = false; } @@ -236,7 +229,7 @@ async function main() { const hasInvalidTokens = checkValidEntries(jsonData.blacklisted_tokens, tokens); if (hasInvalidTokens.status && hasInvalidTokens.entry) { - let listOfInvalidTokens: string = hasInvalidTokens.entry.join(', '); + let listOfInvalidTokens: string = hasInvalidTokens.entry.join(", "); console.error(`ERROR: ${network}.json has the following invalid token denom entries: ${listOfInvalidTokens}. Please make sure to only input valid token denom in ${network}`); outcomeMap[network] = false; } @@ -251,21 +244,17 @@ async function main() { // Checking transfer options const transferOptionsArr = Object.keys(jsonData.transfer_options) const bridgesQuery = await sdk.query.coin.BridgeAll({ - pagination: { - key: new Uint8Array(), + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: Long.UZERO, - countTotal: true, - reverse: false, - }, + }), }) const bridges = bridgesQuery.bridges const validTransferOptionChains = bridges.map(bridge => bridge.chainName) - validTransferOptionChains.push('Carbon') + validTransferOptionChains.push("Carbon") const hasInvalidChains = checkValidEntries(transferOptionsArr, validTransferOptionChains); if (hasInvalidChains.status && hasInvalidChains.entry) { - let listOfInvalidChains: string = hasInvalidChains.entry.join(', '); + let listOfInvalidChains: string = hasInvalidChains.entry.join(", "); console.error(`ERROR: ${network}.json has the following chain name entries under transfer_options field: ${listOfInvalidChains}. Please make sure to only input valid chain names in ${network}`); outcomeMap[network] = false; } @@ -273,13 +262,9 @@ async function main() { // Checking network fees const networkFeeDenomOptions = Object.keys(jsonData.network_fees) const gasPricesQuery = await sdk.query.fee.MinGasPriceAll({ - pagination: { + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: new Long(0), - key: new Uint8Array(), - countTotal: true, - reverse: false, - }, + }), }) const minGasPrices = gasPricesQuery.minGasPrices @@ -287,20 +272,16 @@ async function main() { const hasInvalidFeeDenoms = checkValidEntries(networkFeeDenomOptions, validNetworkFeeDenoms); if (hasInvalidFeeDenoms.status && hasInvalidFeeDenoms.entry) { - let listOfInvalidFeeDenoms: string = hasInvalidFeeDenoms.entry.join(', '); + let listOfInvalidFeeDenoms: string = hasInvalidFeeDenoms.entry.join(", "); console.error(`ERROR: ${network}.json has the following network fee token denoms under network_fees field: ${listOfInvalidFeeDenoms}. Please make sure to only input valid network fee token denoms in ${network}`); outcomeMap[network] = false; } // Checking perp pool banners const perpPoolsQuery = await sdk.query.perpspool.PoolInfoAll({ - pagination: { - key: new Uint8Array(), + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: Long.UZERO, - countTotal: true, - reverse: false, - }, + }), }) const perpPoolIds = perpPoolsQuery.pools.map((pool) => pool.poolId.toString()) @@ -321,11 +302,6 @@ async function main() { outcomeMap[network] = false; } - if (jsonData.perp_pool_promo) { - - } - - if (network === CarbonSDK.Network.MainNet && !jsonData.demex_points_config) { console.error(`ERROR: ${network}.json is missing demex_points_config`) outcomeMap[network] = false; diff --git a/scripts/get_all_bridges.ts b/scripts/get_all_bridges.ts index 26b7f8e..96b2e4e 100644 --- a/scripts/get_all_bridges.ts +++ b/scripts/get_all_bridges.ts @@ -1,4 +1,5 @@ import { CarbonSDK } from "carbon-js-sdk"; +import { PageRequest } from "carbon-js-sdk/lib/codec/cosmos/base/query/v1beta1/pagination"; import Long from "long"; const myArgs = process.argv.slice(2); @@ -22,13 +23,9 @@ const myArgs = process.argv.slice(2); const sdk = await CarbonSDK.instance({ network }); const bridges = await sdk.query.coin.BridgeAll({ - pagination: { - key: new Uint8Array(), + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: Long.UZERO, - countTotal: true, - reverse: false, - }, + }), }) console.log(bridges) })().catch(console.error).finally(() => process.exit(0)); diff --git a/scripts/get_all_network_fees.ts b/scripts/get_all_network_fees.ts index bc1e710..6a60b0d 100644 --- a/scripts/get_all_network_fees.ts +++ b/scripts/get_all_network_fees.ts @@ -1,4 +1,5 @@ import { CarbonSDK } from "carbon-js-sdk"; +import { PageRequest } from "carbon-js-sdk/lib/codec/cosmos/base/query/v1beta1/pagination"; import Long from "long"; const myArgs = process.argv.slice(2); @@ -28,13 +29,9 @@ const myArgs = process.argv.slice(2); const sdk = await CarbonSDK.instance({ network }); const feeQueryClient = sdk.query.fee const gasPrices = await feeQueryClient.MinGasPriceAll({ - pagination: { + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: new Long(0), - key: new Uint8Array(), - countTotal: true, - reverse: false, - }, + }), }) console.log(gasPrices) diff --git a/scripts/get_perp_pool_ids.ts b/scripts/get_perp_pool_ids.ts index e0edd9d..191a337 100644 --- a/scripts/get_perp_pool_ids.ts +++ b/scripts/get_perp_pool_ids.ts @@ -1,4 +1,5 @@ import { CarbonSDK } from "carbon-js-sdk"; +import { PageRequest } from "carbon-js-sdk/lib/codec/cosmos/base/query/v1beta1/pagination"; import Long from "long"; const myArgs = process.argv.slice(2); @@ -22,13 +23,9 @@ const myArgs = process.argv.slice(2); const sdk = await CarbonSDK.instance({ network }); const pools = await sdk.query.perpspool.PoolInfoAll({ - pagination: { - key: new Uint8Array(), + pagination: PageRequest.fromPartial({ limit: new Long(10000), - offset: Long.UZERO, - countTotal: true, - reverse: false, - }, + }), }) const poolIds = pools.pools.map((p) => p.poolId.toString()) diff --git a/yarn.lock b/yarn.lock index 4ab090a..c63cb1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1702,10 +1702,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -carbon-js-sdk@^0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/carbon-js-sdk/-/carbon-js-sdk-0.10.5.tgz#61e3afe83eef163d0baba0da861556494b3e0a94" - integrity sha512-G+OLLt4G2u6e+mg7JOJrCgADivlgTFf2uRb+vvH7dq4HBA6bAAJHfoNTo4B5h10UC2Ma0BVanJ9CO/U+uY5Rqw== +carbon-js-sdk@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/carbon-js-sdk/-/carbon-js-sdk-0.11.1.tgz#d61f446d61161c5b0be613848ec97f229c7d0ec3" + integrity sha512-MMt/JbcqCPMxXqSvyoC7R87uMe5ZEa3K5qtZ9VSeG0O+P1jMENuNswMQWSMK+RESYITAbGj8rpe3HYXwvyR5qQ== dependencies: "@cityofzion/neon-api" "^4.9.0" "@cityofzion/neon-core" "^4.9.0" From 303bc8c0f7e6a7d66ad7d45c9020f61f4e0fa423 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:18:53 +0800 Subject: [PATCH 08/13] Add checks for values in config data --- config.schema.json | 6 +- package.json | 2 +- scripts/check_configs.ts | 116 +++++++++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 20 deletions(-) diff --git a/config.schema.json b/config.schema.json index 899d9f7..8889c41 100644 --- a/config.schema.json +++ b/config.schema.json @@ -261,7 +261,8 @@ "properties": { "baseDenom": { "type": "string", - "description": "Denom of token on its native chain" + "description": "Denom of token on its native chain", + "minLength": 2 }, "chainRoutes": { "type": "array", @@ -273,7 +274,8 @@ }, "denomOnCarbon": { "type": "string", - "description": "Denom of token on Carbon chain (omit if token is not added to Carbon chain)" + "description": "Denom of token on Carbon chain (omit if token is not added to Carbon chain)", + "minLength": 2 } } } diff --git a/package.json b/package.json index 24628b7..20ac1d9 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "scripts": { "preinstall": "yarn config set ignore-engines true", "validate": "pajv validate -s config.schema.json -d \"configs/*.json\" --verbose", - "check-configs": "ts-node scripts/check_configs", + "check-configs": "ts-node scripts/check_configs mainnet testnet devnet", "upgrade-sdk": "yarn upgrade carbon-js-sdk@latest", "get-bridges": "ts-node scripts/get_all_bridges", "get-min-gas-prices": "ts-node scripts/get_all_network_fees", diff --git a/scripts/check_configs.ts b/scripts/check_configs.ts index d209cf1..d3ad462 100644 --- a/scripts/check_configs.ts +++ b/scripts/check_configs.ts @@ -1,4 +1,4 @@ -import { CarbonSDK } from "carbon-js-sdk"; +import { BlockchainUtils, CarbonSDK } from "carbon-js-sdk"; import { PageRequest } from "carbon-js-sdk/lib/codec/cosmos/base/query/v1beta1/pagination"; import * as fs from "fs"; import Long from "long"; @@ -22,7 +22,9 @@ interface ConfigJSON { demex_points_config: DemexPointsConfig, perp_pool_promo: { [perpPoolId: string]: PerpPoolPromo, - } + }, + external_chain_channels: ExternalChannelsObj, + additional_ibc_token_config: AdditionalIbcTokenConfigItem[], } interface InvalidEntry { @@ -58,6 +60,17 @@ interface PerpPoolPromo { perpTradingBoost: string; } +type ChainToChannelMap = Record; +type ExternalChannelsObj = Record; + +type ChainRoutes = [string, ...string[]]; + +interface AdditionalIbcTokenConfigItem { + baseDenom: string + chainRoutes: ChainRoutes // i.e. should have at least 1 item + denomOnCarbon?: string +} + type OutcomeMap = { [key in CarbonSDK.Network]: boolean }; // true = success, false = failure const outcomeMap: OutcomeMap = { @@ -67,9 +80,11 @@ const outcomeMap: OutcomeMap = { localhost: true, }; +const channelRegex = /^channel-([\d]+)$/; + // check for valid entries (match data to the api query) function checkValidEntries(data: string[], query: string[]): InvalidEntry { - let invalidEntries: string[] = []; + const invalidEntries: string[] = []; data.forEach(entry => { if (!query.includes(entry)) { invalidEntries.push(entry); @@ -83,6 +98,15 @@ function checkValidEntries(data: string[], query: string[]): InvalidEntry { }; } +function checkValuesAgainstRegex(data: string[], regex: RegExp): InvalidEntry { + const invalidValues: string[] = data.reduce((prev: string[], dataItem: string) => { + if (regex.test(dataItem)) return prev; + prev.push(dataItem); + return prev; + }, []); + return { status: invalidValues.length > 0 }; +} + // check for duplicate entries function checkDuplicateEntries(data: string[]): DuplicateEntry { let numOfDuplicates: number = 0; @@ -117,6 +141,67 @@ function checkBlacklistedMarkets(marketData: string[], blacklistedMarkets: strin }; } +function isValidExternalChainChannels(chainChannels: ExternalChannelsObj, bridges: string[], network: CarbonSDK.Network): boolean { + const duplicateChainKeys: string[] = []; + const invalidChainKeys: string[] = []; + const invalidChannelRegexValues: string[] = []; + Object.entries(chainChannels).forEach(([chain, channelMap]: [string, ChainToChannelMap]) => { + const chainsArr = Object.keys(channelMap).concat([chain]); + const duplicateCheckOutcome = checkDuplicateEntries(chainsArr); + if (duplicateCheckOutcome.status) duplicateChainKeys.push(chain); + + const invalidCheckOutcome = checkValidEntries(chainsArr, bridges); + if (invalidCheckOutcome.status) invalidChainKeys.push(chain); + + const channelsArr = Object.values(channelMap); + const invalidRegexValuesOutcome = checkValuesAgainstRegex(channelsArr, channelRegex); + if (invalidRegexValuesOutcome.status) invalidChannelRegexValues.push(chain); + }); + + if (duplicateChainKeys.length > 0) { + const duplicateChainsStr = duplicateChainKeys.length > 1 ? `${duplicateChainKeys.slice(0, -1).join(", ")} and ${duplicateChainKeys[duplicateChainKeys.length - 1]}` : duplicateChainKeys[0]; + console.error(`[ERROR] external_chain_channels of ${network}.json has duplicate chains in the ${duplicateChainsStr} object(s). Please make sure to input each chain only once in each object.`); + return false; + } + if (invalidChainKeys.length > 0) { + const invalidChainsStr = invalidChainKeys.length > 1 ? `${invalidChainKeys.slice(0, -1).join(", ")} and ${invalidChainKeys[invalidChainKeys.length - 1]}` : invalidChainKeys[0]; + console.error(`[ERROR] external_chain_channels of ${network}.json has invalid chains in the ${invalidChainsStr} object(s). Please make sure to input only IBC chains in each object.`); + return false; + } + if (invalidChannelRegexValues.length > 0) { + const invalidChannelIdStr = invalidChannelRegexValues.length > 1 ? `${invalidChannelRegexValues.slice(0, -1).join(", ")} and ${invalidChannelRegexValues[invalidChannelRegexValues.length - 1]}` : invalidChannelRegexValues[0]; + console.error(`[ERROR] external_chain_channels of ${network}.json has invalid channel ids in the ${invalidChannelIdStr} object(s). Please make sure to input valid IBC channel ids in each object.`); + return false; + } + return true; +} + +function isValidAdditionalIbcTokenConfig(addTokenConfigArr: AdditionalIbcTokenConfigItem[], bridges: string[], tokenDenoms: string[], network: CarbonSDK.Network): boolean { + const invalidChainIndexes: number[] = []; + const invalidDenomIndexes: number[] = []; + addTokenConfigArr.forEach((configItem: AdditionalIbcTokenConfigItem, index: number) => { + const invalidChainsOutcome = checkValidEntries(configItem.chainRoutes, bridges); + if (invalidChainsOutcome.status) invalidChainIndexes.push(index); + + if (configItem.denomOnCarbon) { + const invalidTokensOutcome = checkValidEntries([configItem.denomOnCarbon], tokenDenoms); + if (invalidTokensOutcome.status) invalidDenomIndexes.push(index); + } + }); + + if (invalidChainIndexes.length > 0) { + const invalidChainsStr = invalidChainIndexes.length > 1 ? `${invalidChainIndexes.slice(0, -1).join(", ")} and ${invalidChainIndexes[invalidChainIndexes.length - 1]}` : invalidChainIndexes[0].toString(10); + console.error(`[ERROR] additional_ibc_token_config of ${network}.json has invalid chains in the objects at index position(s) ${invalidChainsStr}. Please make sure to input only IBC chains in each object.`); + return false; + } + if (invalidDenomIndexes.length > 0) { + const invalidDenomsStr = invalidDenomIndexes.length > 1 ? `${invalidDenomIndexes.slice(0, -1).join(", ")} and ${invalidDenomIndexes[invalidDenomIndexes.length - 1]}` : invalidDenomIndexes[0].toString(10); + console.error(`[ERROR] additional_ibc_token_config of ${network}.json has invalid denomInCarbon values in the objects at index position(s) ${invalidDenomsStr}. Please make sure to input valid token denoms in each object.`); + return false; + } + return true; +} + async function main() { for (const net of myArgs) { let network: CarbonSDK.Network; @@ -217,13 +302,9 @@ async function main() { // query all tokens const allTokens = await sdk.query.coin.TokenAll({ - pagination: { + pagination: PageRequest.fromPartial({ limit: new Long(100000), - offset: new Long(0), - key: new Uint8Array(), - countTotal: true, - reverse: false, - } + }), }); const tokens: string[] = allTokens.tokens.map(token => token.denom); @@ -243,14 +324,9 @@ async function main() { // Checking transfer options const transferOptionsArr = Object.keys(jsonData.transfer_options) - const bridgesQuery = await sdk.query.coin.BridgeAll({ - pagination: PageRequest.fromPartial({ - limit: new Long(10000), - }), - }) - const bridges = bridgesQuery.bridges - const validTransferOptionChains = bridges.map(bridge => bridge.chainName) - validTransferOptionChains.push("Carbon") + const ibcBridgeNames = sdk.token.getIbcBlockchainNames(); + if (!ibcBridgeNames.includes("Carbon")) ibcBridgeNames.push("Carbon"); + const validTransferOptionChains = sdk.token.getPolynetworkBlockchainNames().concat(ibcBridgeNames); const hasInvalidChains = checkValidEntries(transferOptionsArr, validTransferOptionChains); if (hasInvalidChains.status && hasInvalidChains.entry) { @@ -345,6 +421,12 @@ async function main() { } } } + + const isExternalChannelsValid = isValidExternalChainChannels(jsonData.external_chain_channels, ibcBridgeNames, network); + if (!isExternalChannelsValid) outcomeMap[network] = false; + + const isAdditionalTokensConfigValid = isValidAdditionalIbcTokenConfig(jsonData.additional_ibc_token_config, ibcBridgeNames, tokens, network); + if (!isAdditionalTokensConfigValid) outcomeMap[network] = false; } } const outcomeArr = Object.values(outcomeMap); From b0c740dd703607dc05c3affd2f6a7dcad3850ea0 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:23:31 +0800 Subject: [PATCH 09/13] Add json schema validation to github actions --- .github/workflows/market-config-validation.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/market-config-validation.yml b/.github/workflows/market-config-validation.yml index 3ebfd86..44b1ce8 100644 --- a/.github/workflows/market-config-validation.yml +++ b/.github/workflows/market-config-validation.yml @@ -1,7 +1,7 @@ on: - pull_request: + push: branches: - - master + - feat/packet-forwarding-config name: Pull request workflow jobs: validate_markets: @@ -20,7 +20,10 @@ jobs: run: yarn install --ignore-engines # will run `yarn install` command - name: Validate config schema - run: yarn validate # validate using json schema + uses: docker://orrosenblatt/validate-json-action:latest + env: + INPUT_SCHEMA: ../../config.schema.json + INPUT_JSONS: ../../configs/mainnet.json,../../configs/testnet.json,../../configs/devnet.json - name: Test market entries for invalid/duplicate markets run: yarn check-configs mainnet testnet devnet # check using check_configs.ts script \ No newline at end of file From 5ac9af14f587741ce9fe5954e30a14d5d77a6664 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:27:20 +0800 Subject: [PATCH 10/13] Fix JSON file paths --- .github/workflows/market-config-validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/market-config-validation.yml b/.github/workflows/market-config-validation.yml index 44b1ce8..a25a441 100644 --- a/.github/workflows/market-config-validation.yml +++ b/.github/workflows/market-config-validation.yml @@ -22,8 +22,8 @@ jobs: - name: Validate config schema uses: docker://orrosenblatt/validate-json-action:latest env: - INPUT_SCHEMA: ../../config.schema.json - INPUT_JSONS: ../../configs/mainnet.json,../../configs/testnet.json,../../configs/devnet.json + INPUT_SCHEMA: config.schema.json + INPUT_JSONS: configs/mainnet.json,configs/testnet.json,configs/devnet.json - name: Test market entries for invalid/duplicate markets run: yarn check-configs mainnet testnet devnet # check using check_configs.ts script \ No newline at end of file From bd218a32aeb7fe8a17e06ba39367108b80197c39 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:46:55 +0800 Subject: [PATCH 11/13] Test json schema validation --- configs/mainnet.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index 2f5ebc7..93aa65d 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -248,11 +248,11 @@ } }, "additional_ibc_token_config": [{ - "baseDenom": "uusdc", + "baseDenom": "u", "chainRoutes": ["Archway", "Noble"] }, { "baseDenom": "uusdc", - "chainRoutes": ["Cosmos Hub", "Noble"] + "chainRoutes": [] }, { "baseDenom": "uusdc", "chainRoutes": ["DYDX", "Noble"] From 2806252951db89d59cef274924e3fea5b1c55137 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:53:37 +0800 Subject: [PATCH 12/13] Revert "Test json schema validation" This reverts commit bd218a32aeb7fe8a17e06ba39367108b80197c39. --- configs/mainnet.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/mainnet.json b/configs/mainnet.json index 93aa65d..2f5ebc7 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -248,11 +248,11 @@ } }, "additional_ibc_token_config": [{ - "baseDenom": "u", + "baseDenom": "uusdc", "chainRoutes": ["Archway", "Noble"] }, { "baseDenom": "uusdc", - "chainRoutes": [] + "chainRoutes": ["Cosmos Hub", "Noble"] }, { "baseDenom": "uusdc", "chainRoutes": ["DYDX", "Noble"] From 3d0f3c0737be49d60c0815f67468b4711b4c6c95 Mon Sep 17 00:00:00 2001 From: Thong Yuan Yu Sarah Date: Wed, 10 Jul 2024 22:56:56 +0800 Subject: [PATCH 13/13] Revert github actions trigger --- .github/workflows/market-config-validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/market-config-validation.yml b/.github/workflows/market-config-validation.yml index a25a441..5dea5e1 100644 --- a/.github/workflows/market-config-validation.yml +++ b/.github/workflows/market-config-validation.yml @@ -1,7 +1,7 @@ on: - push: + pull_request: branches: - - feat/packet-forwarding-config + - master name: Pull request workflow jobs: validate_markets: