diff --git a/.github/markets/pr_template.md b/.github/markets/pr_template.md
index 8eb3771..842e88e 100644
--- a/.github/markets/pr_template.md
+++ b/.github/markets/pr_template.md
@@ -36,6 +36,7 @@ Each json file under the [configs](../../configs) folder correspond to their res
|---|---|---|---|---|
|`deposit` |`string[]` |true |List of tokens for which deposits are temporarily disabled |The token denoms listed here **MUST** match the token denoms listed under the Carbon [Tokens API](https://api.carbon.network/carbon/coin/v1/tokens?pagination.limit=10000). |
|`withdraw` |`string[]` |true |List of tokens for which withdrawals are temporarily disabled |The token denoms listed here **MUST** match the token denoms listed under the Carbon [Tokens API](https://api.carbon.network/carbon/coin/v1/tokens?pagination.limit=10000). |
+|`announcement_banner` |`AnnouncementBanner` |false |Custom announcement banner through all or only on specificed paths |
## Maintenance Data Structure
|Field |Type |Required |Description |Notes |
@@ -122,6 +123,15 @@ Each json file under the [configs](../../configs) folder correspond to their res
|---|---|---|---|---|
|`show_apr_tooltip` |`boolean` |true |Indicates whether or not to show the Annual Percentage Returns (APR) tooltip on [Spot Pools](https://app.dem.exchange/pools/spot) page |
+## AnnouncementBanner
+|Field |Type |Required |Description |Notes |
+|---|---|---|---|---|
+|`show_from` |`string` |false |The date and time when the market banner is scheduled to begin displaying. |If not provided, the banner will be shown immediately.
This field **MUST** follow the valid ISO 8601 format
e.g. *2024-01-23T09:00+00:00* (23 Jan 2024, 9am UTC) |
+|`show_until` |`string` |false |The date and time when the market banner is scheduled to stop displaying. |If not provided, the banner will continue to display indefinitely.
This field **MUST** follow the valid ISO 8601 format
e.g. *2024-01-23T09:00+00:00* (23 Jan 2024, 9am UTC) |
+|`content` |`string` |true |The content shown on the market banner. |
+|`hideable` |`boolean` |false |Indicates if user can hide the banner by clicking on the close button |If set to `false`, the close button will not be rendered on the banner, and user will not be able to dismiss the banner. |
+|`show_only_on` |`string[]` |true |Default is empty list, then banner will be shown on all pages |If list has specified path(s), the banner will be shown on these/that path(s) only, sample: `['/rewards', '/nitron']` |
+
## QuickSelectToken Data Structure
|Field |Type |Required |Description |Notes |
|---|---|---|---|---|
diff --git a/config.schema.json b/config.schema.json
index e8ca37a..277dd0d 100644
--- a/config.schema.json
+++ b/config.schema.json
@@ -19,7 +19,11 @@
"properties": {
"network": {
"type": "string",
- "enum": ["mainnet", "testnet", "devnet"]
+ "enum": [
+ "mainnet",
+ "testnet",
+ "devnet"
+ ]
},
"prelaunch_markets": {
"type": "array",
@@ -168,7 +172,11 @@
"description": "Ongoing survey configs for typeform survey widget",
"items": {
"type": "object",
- "required": ["surveyLink", "endTime", "pages"],
+ "required": [
+ "surveyLink",
+ "endTime",
+ "pages"
+ ],
"properties": {
"message": {
"type": "string"
@@ -251,7 +259,10 @@
"description": "List of banner information to be displayed over the TradingView chart for the required market",
"items": {
"type": "object",
- "required": ["market_id", "content"],
+ "required": [
+ "market_id",
+ "content"
+ ],
"properties": {
"market_id": {
"$ref": "#/$defs/market_id"
@@ -421,7 +432,10 @@
"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"],
+ "required": [
+ "baseDenom",
+ "chainRoutes"
+ ],
"properties": {
"baseDenom": {
"type": "string",
@@ -461,7 +475,10 @@
"description": "List of perp pool banners",
"items": {
"type": "object",
- "required": ["perp_pool_id", "title"],
+ "required": [
+ "perp_pool_id",
+ "title"
+ ],
"properties": {
"perp_pool_id": {
"$ref": "#/$defs/perp_pool_id"
@@ -516,6 +533,36 @@
}
}
},
+ "announcement_banner": {
+ "type": "object",
+ "description": "Custom announcement banner through all or only on specificed paths",
+ "required": [
+ "content",
+ "show_only_on"
+ ],
+ "patternProperties": {
+ "show_from": {
+ "$ref": "#/$defs/show_from"
+ },
+ "show_until": {
+ "$ref": "#/$defs/show_until"
+ },
+ "content": {
+ "$ref": "#/$defs/content"
+ },
+ "hideable": {
+ "$ref": "#/$defs/hideable"
+ },
+ "show_only_on": {
+ "type": "array",
+ "description": "List of paths that announcement will be show on. Empty array will be shown on all paths",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 0
+ }
+ }
+ },
"quick_select_token": {
"type": "object",
"description": "Token denom for quick select in transfer form",
@@ -539,4 +586,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/configs/devnet.json b/configs/devnet.json
index b15a558..8540a65 100644
--- a/configs/devnet.json
+++ b/configs/devnet.json
@@ -46,6 +46,13 @@
"spot_pool_config": {
"show_apr_tooltip": false
},
+ "announcement_banner": {
+ "show_from": "2024-12-19T02:18+00:00",
+ "show_until": "2024-12-19T02:21+00:00",
+ "content": "Demex will be down for maintenance from 03:00 - 08:00 UTC, 23 Dec. We recommend closing any open orders during this time to minimize potential risks.",
+ "hideable": false,
+ "show_only_on": []
+ },
"quick_select_deposit_options": [
{
"label_denom": "swth",
diff --git a/configs/mainnet.json b/configs/mainnet.json
index 3f6d81a..94c1508 100644
--- a/configs/mainnet.json
+++ b/configs/mainnet.json
@@ -483,6 +483,13 @@
"spot_pool_config": {
"show_apr_tooltip": true
},
+ "announcement_banner": {
+ "show_from": "",
+ "show_until": "",
+ "content": "",
+ "hideable": true,
+ "show_only_on": []
+ },
"quick_select_deposit_options": [
{
"label_denom": "brdg/d8c3db91ad4ba11fe52971b4c387b0110c8951ec0f5b8f0fb445ef0306a349e1",
diff --git a/configs/testnet.json b/configs/testnet.json
index 39e3b49..3d76c22 100644
--- a/configs/testnet.json
+++ b/configs/testnet.json
@@ -60,6 +60,13 @@
"spot_pool_config": {
"show_apr_tooltip": false
},
+ "announcement_banner": {
+ "show_from": "",
+ "show_until": "",
+ "content": "",
+ "hideable": true,
+ "show_only_on": []
+ },
"quick_select_deposit_options": [
{
"label_denom": "swth",
diff --git a/scripts/check_configs.ts b/scripts/check_configs.ts
index 76467b6..97be1b3 100644
--- a/scripts/check_configs.ts
+++ b/scripts/check_configs.ts
@@ -34,6 +34,7 @@ interface ConfigJSON {
market_banners?: MarketBanner[];
market_promo?: {[marketId: string]: MarketPromo};
spot_pool_config?: SpotPoolConfig;
+ announcement_banner: AnnouncementBanner;
quick_select_deposit_options?: QuickSelectToken[];
}
@@ -133,6 +134,14 @@ interface SpotPoolConfig {
show_apr_tooltip: boolean;
}
+interface AnnouncementBanner {
+ show_from?: string;
+ show_until?: string;
+ content: string;
+ hideable?: boolean;
+ show_only_on: string[];
+}
+
interface QuickSelectToken {
label_denom: string;
target_denom: string;
@@ -391,6 +400,20 @@ function isValidMarketBanners(marketBanners: MarketBanner[], network: CarbonSDK.
return true;
}
+function isValidAnnouncementBanner(announcementBanner: AnnouncementBanner, network: CarbonSDK.Network): boolean {
+ const startTime = announcementBanner.show_from ? new Date(announcementBanner.show_from) : null
+ const endTime = announcementBanner.show_until ? new Date(announcementBanner.show_until) : null
+
+ if (startTime && endTime) {
+ const isValidStartEndTime = endTime.getTime() > startTime.getTime()
+ if (!isValidStartEndTime) {
+ console.error(`ERROR: ${network}.json has the following invalid show_from ${announcementBanner.show_from} and invalid show_until ${announcementBanner.show_until} `);
+ return false
+ }
+ }
+ return true
+}
+
function isValidMarketPromo(marketPromo: {[marketId: string]: MarketPromo}, network: CarbonSDK.Network, marketIds: string[]): boolean {
const marketPromoIds = Object.keys(marketPromo)
const hasInvalidMarketPromoIds = checkValidEntries(marketPromoIds, marketIds)
@@ -785,6 +808,10 @@ async function main() {
outcomeMap[network] = false;
}
+ if(jsonData.announcement_banner && !isValidAnnouncementBanner(jsonData.announcement_banner, network)) {
+ outcomeMap[network] = false;
+ }
+
// check for spot pool config
if (jsonData.spot_pool_config) {
const spotPoolConfig = jsonData.spot_pool_config