diff --git a/.github/markets/pr_template.md b/.github/markets/pr_template.md index ed4bd64..83dea19 100644 --- a/.github/markets/pr_template.md +++ b/.github/markets/pr_template.md @@ -17,7 +17,7 @@ Each json file under the [configs](../../configs) folder correspond to their res |`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. | |`cross_selling_source_tokens` |`string[]` |true |The array of cross selling source tokens. Acquiring these tokens on the spot market will trigger a help wizard, prompting users to borrow USDG and trade perps on Demex. |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). | - +|`typeform_widget_config` |`TypeformWidgetConfig[]` |false |Object that contains the parameters for ongoing surveys. | If the `message` property is omitted, default message is shown: "We want to hear from you!". Multiple widgets being displayed on the same page is not supported. Ensure pages don't overlap between configs. | ## Maintenance Data Structure |Field |Type |Required |Description |Notes | |---|---|---|---|---| @@ -47,4 +47,12 @@ Each json file under the [configs](../../configs) folder correspond to their res |`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. | + +## TypeformWidgetConfig +|Field |Type |Required |Description |Notes | +|---|---|---|---|---| +|`message` |`string` |false |The message shown to the user on the widget. | +|`surveyLink` |`string` |true |The link to the survey that will be shown when user clicks on the widget. | +|`endTime` |`string` |true |End time of the survey | +|`pages` |`string[]` | true |The paths to the pages on which the typeform widget must be shown. \ No newline at end of file diff --git a/README.md b/README.md index b29a604..97fd52d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Currently, each JSON file contain the following data on its corresponding networ Additionally, the JSON file for mainnet contains the following data to support ongoing campaigns/promotions: - demex points config - perp pool promotion parameters +- typeform survey parameters More metadata will be added in the future if required by the Demex frontend. Please see below the structure of the JSON file: diff --git a/config.schema.json b/config.schema.json index 61e0aa3..be7609e 100644 --- a/config.schema.json +++ b/config.schema.json @@ -167,6 +167,32 @@ } } }, + "typeform_widget_config": { + "type": "array", + "description": "Ongoing survey configs for typeform survey widget", + "items": { + "type": "object", + "required": [ + "surveyLink", + "endTime", + "pages" + ], + "properties": { + "message": { + "type": "string" + }, + "surveyLink": { + "type": "string" + }, + "endTime": { + "$ref": "#/$defs/survey_end" + }, + "pages": { + "type": "array" + } + } + } + }, "$defs": { "prelaunch_market": { "type": "string", @@ -237,6 +263,11 @@ "cross_selling_source_token": { "type": "string", "description": "Cross selling source token denom" + }, + "survey_end": { + "type": "string", + "description": "The end time of the tyepform survey", + "pattern": "^\\d{4}(-\\d\\d(-\\d\\d(T\\d\\d:\\d\\d(:\\d\\d)?(\\.\\d+)?(([+-]\\d\\d:\\d\\d)|Z)?)?)?)?$" } } } \ No newline at end of file diff --git a/configs/mainnet.json b/configs/mainnet.json index 764102d..7d181e2 100644 --- a/configs/mainnet.json +++ b/configs/mainnet.json @@ -228,5 +228,15 @@ "perpTradingBoost": 3 } }, - "cross_selling_source_tokens": ["swth"] + "cross_selling_source_tokens": ["swth"], + "typeform_widget_config": [ + { + "surveyLink": "https://switcheonetwork.typeform.com/to/C1rheplK", + "endTime": "2024-07-26T23:00:00Z", + "pages": [ + "/account/overview", + "/account/balance" + ] + } + ] } diff --git a/scripts/check_configs.ts b/scripts/check_configs.ts index b915aaa..06f70cf 100644 --- a/scripts/check_configs.ts +++ b/scripts/check_configs.ts @@ -23,6 +23,7 @@ interface ConfigJSON { [perpPoolId: string]: PerpPoolPromo, }, cross_selling_source_tokens: string[]; + typeform_widget_config: TypeFormWidgetConfig[] } interface InvalidEntry { @@ -58,6 +59,12 @@ interface PerpPoolPromo { perpTradingBoost: string; } +interface TypeFormWidgetConfig { + surveyLink: string + endTime: string + pages: string[] +} + type OutcomeMap = { [key in CarbonSDK.Network]: boolean }; // true = success, false = failure const outcomeMap: OutcomeMap = { @@ -384,6 +391,38 @@ async function main() { } } } + if (jsonData.typeform_widget_config) { + const typeFormWidgetConfigs = jsonData.typeform_widget_config + const links: string[] = [] + let pages: string[] = [] + for (const config of typeFormWidgetConfigs) { + const startTime = new Date() + const endTime = new Date(config.endTime) + // Check if end time is before start time + if (endTime < startTime) { + console.error(`ERROR: ${network}.json has invalid end time (${endTime}) is before start time (${startTime}) for a typeform survey config.`); + outcomeMap[network] = false; + break; // Exit the loop early upon encountering an error + } + pages = pages.concat(config.pages) + links.push(config.surveyLink) + } + // look for duplicate links + const hasDuplicateLinks = checkDuplicateEntries(links); + if (hasDuplicateLinks.status && hasDuplicateLinks.entry) { + let listOfDuplicates: string = hasDuplicateLinks.entry.join(", "); + console.error(`ERROR: ${network}.json has the following duplicated links in the typeform survey configs: ${listOfDuplicates}. Please make sure to only input each link once in ${network}`); + outcomeMap[network] = false; + } + // look for duplicate pages + const hasDuplicatePages = checkDuplicateEntries(pages); + if (hasDuplicatePages.status && hasDuplicatePages.entry) { + let listOfDuplicates: string = hasDuplicatePages.entry.join(", "); + console.error(`ERROR: ${network}.json has the following duplicated pages in the typeform survey configs: ${listOfDuplicates}. Please make sure to only input each page once in ${network}`); + outcomeMap[network] = false; + } + } + } } const outcomeArr = Object.values(outcomeMap);