diff --git a/packages/playground/docs/build.md b/packages/playground/docs/build.md
index b252bdee85..88180c4ab2 100644
--- a/packages/playground/docs/build.md
+++ b/packages/playground/docs/build.md
@@ -30,6 +30,8 @@ bash ../scripts/build-env.sh
- SENTRY_DSN
- ENABLE_TELEMETRY
+- The use can provide a single URL or multiple URLs separated with a comma, for `GRAPHQL_URL, GRIDPROXY_URL, SUBSTRATE_URL, ACTIVATION_SERVICE_URL, RELAY_DOMAIN, STATS_URL`, If the user provides multiple URLs, it will be considered as a priority list, which means the dashboard will try to connect over the first URL in the list; if it fails, it will move to the next one, and so on.
+
- The backend payments are done with stellar so you need to decide which network of stellar you want to connect to
```bash
diff --git a/packages/playground/index.html b/packages/playground/index.html
index 72f6262517..67f78846b6 100644
--- a/packages/playground/index.html
+++ b/packages/playground/index.html
@@ -41,7 +41,12 @@
});
- Loading dashboard. Please wait...
+ Loading dashboard. Please wait...
+
+
Refresh
diff --git a/packages/playground/package.json b/packages/playground/package.json
index 7a95653d5d..87bb7a5f78 100644
--- a/packages/playground/package.json
+++ b/packages/playground/package.json
@@ -16,6 +16,7 @@
"@threefold/graphql_client": "2.5.0",
"@threefold/grid_client": "2.5.0",
"@threefold/gridproxy_client": "2.5.0",
+ "@threefold/monitoring": "2.5.0",
"@threefold/types": "2.5.0",
"@types/ip": "^1.1.3",
"@types/md5": "^2.3.5",
diff --git a/packages/playground/public/config.js b/packages/playground/public/config.js
index 3c87acb26b..96b19eb9fd 100644
--- a/packages/playground/public/config.js
+++ b/packages/playground/public/config.js
@@ -1,16 +1,19 @@
window.env = {
NETWORK: "dev",
- GRAPHQL_URL: "https://graphql.dev.grid.tf/graphql",
- GRIDPROXY_URL: "https://gridproxy.dev.grid.tf",
- SUBSTRATE_URL: "wss://tfchain.dev.grid.tf/ws",
- ACTIVATION_SERVICE_URL: "https://activation.dev.grid.tf/activation/activate",
- RELAY_DOMAIN: "wss://relay.dev.grid.tf",
+ GRAPHQL_STACKS: ["https://graphql.dev.grid.tf/graphql", "https://graphql.02.dev.grid.tf/graphql"],
+ GRIDPROXY_STACKS: ["https://gridproxy.dev.grid.tf", "https://gridproxy.02.dev.grid.tf"],
+ SUBSTRATE_STACKS: ["wss://tfchain.dev.grid.tf/ws", "wss://tfchain.02.dev.grid.tf/ws"],
+ ACTIVATION_SERVICE_STACKS: [
+ "https://activation.dev.grid.tf/activation/activate",
+ "https://activation.02.dev.grid.tf/activation/activate",
+ ],
+ RELAY_STACKS: ["wss://relay.dev.grid.tf", "wss://relay.02.dev.grid.tf"],
BRIDGE_TFT_ADDRESS: "GDHJP6TF3UXYXTNEZ2P36J5FH7W4BJJQ4AYYAXC66I2Q2AH5B6O6BCFG",
STELLAR_NETWORK: "test",
STELLAR_HORIZON_URL: "https://horizon-testnet.stellar.org",
TFT_ASSET_ISSUER: "GA47YZA3PKFUZMPLQ3B5F2E3CJIB57TGGU7SPCQT2WAEYKN766PWIMB3",
MINTING_URL: "https://alpha.minting.tfchain.grid.tf",
- STATS_URL: "https://stats.dev.grid.tf",
+ STATS_STACKS: ["https://stats.dev.grid.tf", "https://stats.02.dev.grid.tf"],
TIMEOUT: +"10000",
PAGE_SIZE: +"20",
MANUAL_URL: "https://www.manual.grid.tf",
diff --git a/packages/playground/public/loader/loader.css b/packages/playground/public/loader/loader.css
index 28d5167c91..49f52c77d3 100644
--- a/packages/playground/public/loader/loader.css
+++ b/packages/playground/public/loader/loader.css
@@ -23,6 +23,54 @@
margin-top: 30vh;
}
+.app-monitor-container {
+ flex-direction: column;
+ align-items: center;
+ margin-top: 20px;
+ display: none;
+ border: 1px solid #fff;
+ border-radius: 5px;
+ padding: 5px 25px;
+}
+
+.app-monitor-container.active {
+ display: flex;
+}
+
+.app-monitor-status {
+ text-align: left;
+ color: #fff;
+ margin: 0;
+ font-family: sans-serif;
+ max-width: 500px;
+ line-height: 1;
+}
+
+.service-name {
+ color: #fff;
+ width: 100px;
+ padding: 2px 0;
+ font-family: sans-serif;
+ line-height: 1;
+ font-weight: bold;
+ text-align: left;
+}
+
+.service-status {
+ display: inline;
+ font-family: sans-serif;
+ line-height: 1;
+ font-weight: bold;
+ font-size: x-large;
+}
+
+.service-reachable {
+ color: rgb(var(--v-theme-success, "76, 175, 80"));
+}
+
+.service-unreachable {
+ color: rgb(207 102 121);
+}
.app-loader-logo {
max-width: 100%;
display: block;
@@ -86,7 +134,9 @@
}
}
-.app-loader-msg {
+.app-loader-msg,
+.app-monitor-msg {
+ display: none;
color: #fff;
margin: 0;
margin-top: 20px;
@@ -96,6 +146,14 @@
text-align: center;
}
+.app-monitor-msg {
+ display: none;
+}
+
+.app-loader-msg.active,
+.app-monitor-msg.active {
+ display: block;
+}
.app-loader-refresh {
border: none;
outline: none;
@@ -134,4 +192,4 @@
.app-loader-refresh:focus {
box-shadow: 0 0 0 2px rgba(115, 221, 195, 0.5);
-}
+}
\ No newline at end of file
diff --git a/packages/playground/public/loader/loader.js b/packages/playground/public/loader/loader.js
index 69dd8f766b..71e521e429 100644
--- a/packages/playground/public/loader/loader.js
+++ b/packages/playground/public/loader/loader.js
@@ -10,6 +10,12 @@ const msgElement = document.querySelector(".app-loader-msg");
/** @type { HTMLButtonElement} */
const refreshBtn = document.querySelector(".app-loader-refresh");
+/** @type { HTMLDivElement } */
+const monitor = document.querySelector(".app-monitor-container");
+
+/** @type { HTMLUListElement} */
+const monitorList = document.querySelector(".app-monitor-status");
+
const slowConnectionTime = 60 * 1000;
const noConnectionTime = 120 * 1000;
const appLoaderContainerTime = 0.3 * 1000;
@@ -58,3 +64,25 @@ window.$$appLoader = () => {
}
}, welcomeMsgTime);
};
+window.$$showMonitorError = urls => {
+ if (msgElement) msgElement.classList.remove("active");
+
+ if (monitor) monitor.classList.add("active");
+
+ const monitorMsgElement = document.querySelector(".app-monitor-msg");
+ if (monitorMsgElement) {
+ monitorMsgElement.classList.add("active");
+ monitorMsgElement.textContent = "Can't reach some services on provided stacks, Please try again";
+ }
+
+ if (monitorList) {
+ monitorList.innerHTML = Object.entries(urls).map(createElement).join(" ");
+ }
+ refreshBtn && refreshBtn.classList.add("active");
+};
+
+function createElement([serviceName, serviceStatus]) {
+ return `${serviceName}
${serviceStatus !== null ? "✓" : "✗"}
`;
+}
diff --git a/packages/playground/scripts/build-env.sh b/packages/playground/scripts/build-env.sh
index ecd2581631..83f4cf3ff8 100644
--- a/packages/playground/scripts/build-env.sh
+++ b/packages/playground/scripts/build-env.sh
@@ -15,46 +15,46 @@ STELLAR_ENV_Vars=(
case $MODE in
"dev")
- GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.dev.grid.tf/graphql}"
- GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.dev.grid.tf}"
- SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.dev.grid.tf/ws}"
- ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.dev.grid.tf/activation/activate}"
- RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.dev.grid.tf}"
+ GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.dev.grid.tf/graphql,https://graphql.02.dev.grid.tf/graphql"}"
+ GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.dev.grid.tf,https://gridproxy.02.dev.grid.tf"}"
+ SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.dev.grid.tf/ws,wss://tfchain.02.dev.grid.tf/ws"}"
+ ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.dev.grid.tf/activation/activate,https://activation.02.dev.grid.tf/activation/activate"}"
+ RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.dev.grid.tf,wss://relay.02.dev.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GDHJP6TF3UXYXTNEZ2P36J5FH7W4BJJQ4AYYAXC66I2Q2AH5B6O6BCFG}"
- STATS_URL="${STATS_URL:-https://stats.dev.grid.tf}"
+ STATS_URL="${STATS_URL:-"https://stats.dev.grid.tf,https://stats.02.dev.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-test}"
SENTRY_DSN="https://b9af6796f176d1f02837a06f0da3caee@dev.sentry.grid.tf/2"
;;
"qa")
- GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.qa.grid.tf/graphql}"
- GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.qa.grid.tf}"
- SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.qa.grid.tf/ws}"
- ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.qa.grid.tf/activation/activate}"
- RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.qa.grid.tf}"
+ GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.qa.grid.tf/graphql,https://graphql.02.qa.grid.tf/graphql"}"
+ GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.qa.grid.tf,https://gridproxy.02.qa.grid.tf"}"
+ SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.qa.grid.tf/ws,wss://tfchain.02.qa.grid.tf/ws"}"
+ ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.qa.grid.tf/activation/activate,https://activation.02.qa.grid.tf/activation/activate"}"
+ RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.qa.grid.tf,wss://relay.02.qa.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GAQH7XXFBRWXT2SBK6AHPOLXDCLXVFAKFSOJIRMRNCDINWKHGI6UYVKM}"
- STATS_URL="${STATS_URL:-https://stats.qa.grid.tf}"
+ STATS_URL="${STATS_URL:-"https://stats.qa.grid.tf,https://stats.02.qa.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-test}"
SENTRY_DSN="https://b9af6796f176d1f02837a06f0da3caee@dev.sentry.grid.tf/2"
;;
"test")
- GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.test.grid.tf/graphql}"
- GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.test.grid.tf}"
- SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.test.grid.tf/ws}"
- ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.test.grid.tf/activation/activate}"
- RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.test.grid.tf}"
+ GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.test.grid.tf/graphql,https://graphql.02.test.grid.tf/graphql"}"
+ GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.test.grid.tf,https://gridproxy.02.test.grid.tf"}"
+ SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.test.grid.tf/ws,wss://tfchain.02.test.grid.tf/ws"}"
+ ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.test.grid.tf/activation/activate,https://activation.02.test.grid.tf/activation/activate"}"
+ RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.test.grid.tf,wss://relay.02.test.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GA2CWNBUHX7NZ3B5GR4I23FMU7VY5RPA77IUJTIXTTTGKYSKDSV6LUA4}"
- STATS_URL="${STATS_URL:-https://stats.test.grid.tf}"
+ STATS_URL="${STATS_URL:-"https://stats.test.grid.tf,https://stats.02.test.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-main}"
SENTRY_DSN="https://b9af6796f176d1f02837a06f0da3caee@dev.sentry.grid.tf/2"
;;
"main")
- GRAPHQL_URL="${GRAPHQL_URL:-https://graphql.grid.tf/graphql}"
- GRIDPROXY_URL="${GRIDPROXY_URL:-https://gridproxy.grid.tf}"
- SUBSTRATE_URL="${SUBSTRATE_URL:-wss://tfchain.grid.tf/ws}"
- ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-https://activation.grid.tf/activation/activate}"
- RELAY_DOMAIN="${RELAY_DOMAIN:-wss://relay.grid.tf}"
+ GRAPHQL_URL="${GRAPHQL_URL:-"https://graphql.grid.tf/graphql,https://graphql.02.grid.tf/graphql"}"
+ GRIDPROXY_URL="${GRIDPROXY_URL:-"https://gridproxy.grid.tf,https://gridproxy.02.grid.tf"}"
+ SUBSTRATE_URL="${SUBSTRATE_URL:-"wss://tfchain.grid.tf/ws,wss://tfchain.02.grid.tf/ws"}"
+ ACTIVATION_SERVICE_URL="${ACTIVATION_SERVICE_URL:-"https://activation.grid.tf/activation/activate,https://activation.02.grid.tf/activation/activate"}"
+ RELAY_DOMAIN="${RELAY_DOMAIN:-"wss://relay.grid.tf,wss://relay.02.grid.tf"}"
BRIDGE_TFT_ADDRESS="${BRIDGE_TFT_ADDRESS:-GBNOTAYUMXVO5QDYWYO2SOCOYIJ3XFIP65GKOQN7H65ZZSO6BK4SLWSC}"
- STATS_URL="${STATS_URL:-https://stats.grid.tf}"
+ STATS_URL="${STATS_URL:-"https://stats.grid.tf,https://stats.02.grid.tf"}"
STELLAR_NETWORK="${STELLAR_NETWORK:-main}"
SENTRY_DSN="https://598bcc658bd99042ab429166035f8278@sentry.grid.tf/2"
;;
@@ -81,20 +81,35 @@ case $STELLAR_NETWORK in
;;
esac
+parss_array(){
+ local service_urls=$1
+ toString=($(echo "$service_urls" | tr ',' "\n"))
+ for item in "${toString[@]}"; do
+ quoted_string+="'$item' "
+ done
+
+ # add single quate to each elament
+ quoted_string=${quoted_string// /,}
+
+ # remove trailing comma
+ echo "${quoted_string%?}"
+
+}
+
configs="
window.env = {
NETWORK: '$MODE',
- GRAPHQL_URL: '$GRAPHQL_URL',
- GRIDPROXY_URL: '$GRIDPROXY_URL',
- SUBSTRATE_URL: '$SUBSTRATE_URL',
- ACTIVATION_SERVICE_URL: '$ACTIVATION_SERVICE_URL',
- RELAY_DOMAIN: '$RELAY_DOMAIN',
+ GRAPHQL_STACKS: "[$(parss_array "$GRAPHQL_URL")]",
+ GRIDPROXY_STACKS: "[$(parss_array "$GRIDPROXY_URL")]",
+ SUBSTRATE_STACKS: "[$(parss_array "$SUBSTRATE_URL")]",
+ ACTIVATION_SERVICE_STACKS: "[$(parss_array "$ACTIVATION_SERVICE_URL")]",
+ RELAY_STACKS: "[$(parss_array "$RELAY_DOMAIN")]",
BRIDGE_TFT_ADDRESS: '$BRIDGE_TFT_ADDRESS',
STELLAR_NETWORK: '$STELLAR_NETWORK',
STELLAR_HORIZON_URL: '$STELLAR_HORIZON_URL',
TFT_ASSET_ISSUER: '$TFT_ASSET_ISSUER',
MINTING_URL: '$MINTING_URL',
- STATS_URL: '$STATS_URL',
+ STATS_STACKS: "[$(parss_array "$STATS_URL")]",
TIMEOUT: +'$TIMEOUT',
PAGE_SIZE: +'$PAGE_SIZE',
MANUAL_URL: '$MANUAL_URL',
@@ -104,7 +119,7 @@ window.env = {
"
# decide the config file path
-[ -d dist ] && file="dist/config.js" || file="config.js"
+[ -d public ] && file="public/config.js" || file="config.js"
# override the content of the config file & echo the result
echo $configs > $file
diff --git a/packages/playground/src/Monitor.vue b/packages/playground/src/Monitor.vue
new file mode 100644
index 0000000000..76bbc61e45
--- /dev/null
+++ b/packages/playground/src/Monitor.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/packages/playground/src/clients/index.ts b/packages/playground/src/clients/index.ts
index a9b33d6a04..71bfb8697f 100644
--- a/packages/playground/src/clients/index.ts
+++ b/packages/playground/src/clients/index.ts
@@ -1,7 +1,6 @@
import TFGridGqlClient from "@threefold/graphql_client";
import GridProxyClient from "@threefold/gridproxy_client";
import { QueryClient } from "@threefold/tfchain_client";
-
const gqlClient = new TFGridGqlClient(window.env.GRAPHQL_URL);
const gridProxyClient = new GridProxyClient(window.env.GRIDPROXY_URL);
const queryClient = new QueryClient(window.env.SUBSTRATE_URL);
diff --git a/packages/playground/src/components/logger.vue b/packages/playground/src/components/logger.vue
index 848bd70e39..f2e0928cee 100644
--- a/packages/playground/src/components/logger.vue
+++ b/packages/playground/src/components/logger.vue
@@ -203,7 +203,7 @@ export default {
let _interceptorQueue: LI[] = [];
async function interceptMessage(instance: LI) {
- if (connectDB.value.error) {
+ if (connectDB.value.error ) {
_interceptorQueue.push(instance);
return;
}
diff --git a/packages/playground/src/config.ts b/packages/playground/src/config.ts
index 0a9c9201e5..6194406320 100644
--- a/packages/playground/src/config.ts
+++ b/packages/playground/src/config.ts
@@ -1,30 +1,37 @@
+import {
+ ActivationMonitor,
+ GraphQLMonitor,
+ GridProxyMonitor,
+ RMBMonitor,
+ ServiceUrlManager,
+ StatsMonitor,
+ TFChainMonitor,
+} from "@threefold/monitoring";
import { marked } from "marked";
-import type { App, Component } from "vue";
+import { type App, type Component, defineAsyncComponent } from "vue";
import CopyInputWrapper from "./components/copy_input_wrapper.vue";
-import DTabs from "./components/dynamic_tabs.vue";
import Filters from "./components/filter.vue";
import FormValidator from "./components/form_validator.vue";
import InputTooltip from "./components/input_tooltip.vue";
import InputValidator from "./components/input_validator.vue";
import TfSelectCountry from "./components/node_selector/select_location_internals/TfSelectCountry.vue";
import TfSelectRegion from "./components/node_selector/select_location_internals/TfSelectRegion.vue";
-import TfSelectionDetails from "./components/node_selector/TfSelectionDetails.vue";
import PasswordInputWrapper from "./components/password_input_wrapper.vue";
import ViewLayout from "./components/view_layout.vue";
-import WebletLayout from "./components/weblet_layout.vue";
import * as validators from "./utils/validators";
+
const GLOBAL_COMPONENTS: { [key: string]: Component } = {
PasswordInputWrapper,
- WebletLayout,
+ WebletLayout: defineAsyncComponent(() => import("./components/weblet_layout.vue")),
CopyInputWrapper,
- DTabs,
+ DTabs: defineAsyncComponent(() => import("./components/dynamic_tabs.vue")),
InputValidator,
FormValidator,
ViewLayout,
InputTooltip,
Filters,
- TfSelectionDetails,
+ TfSelectionDetails: defineAsyncComponent(() => import("./components/node_selector/TfSelectionDetails.vue")),
TfSelectRegion,
TfSelectCountry,
};
@@ -68,3 +75,43 @@ function defineGlobalProps(app: App) {
app.config.globalProperties.validators = validators;
app.config.globalProperties.MANUAL_URL = window.env.MANUAL_URL;
}
+/**
+ * Configures global environment variables based on available service URLs.
+ *
+ * This asynchronous function initializes a `ServiceUrlManager` with a set of predefined services and their URLs.
+ * It then retrieves the available service stacks and updates the global `window.env` object with the URLs for each service.
+ * If any service URLs are not available, an error is displayed and the function returns `false`.
+ * If all service URLs are successfully retrieved and set, the function returns `true`.
+ *
+ * @returns A promise that resolves to `true` if all service URLs are successfully set, or `false` if any service URL is missing.
+ */
+export async function setGlobalEnv() {
+ const { GRIDPROXY_STACKS, GRAPHQL_STACKS, STATS_STACKS, RELAY_STACKS, SUBSTRATE_STACKS, ACTIVATION_SERVICE_STACKS } =
+ window.env;
+ const urlManger = new ServiceUrlManager({
+ services: [
+ { URLs: GRIDPROXY_STACKS, service: new GridProxyMonitor() },
+ { URLs: GRAPHQL_STACKS, service: new GraphQLMonitor() },
+ { URLs: STATS_STACKS, service: new StatsMonitor() },
+ { URLs: SUBSTRATE_STACKS, service: new TFChainMonitor() },
+ { URLs: ACTIVATION_SERVICE_STACKS, service: new ActivationMonitor() },
+ { URLs: RELAY_STACKS, service: new RMBMonitor() },
+ ],
+ silent: true,
+ });
+ const result = await urlManger.getAvailableServicesStack();
+
+ if (Object.values(result).includes(null)) {
+ window.$$showMonitorError(result);
+ return false;
+ }
+ const { GridProxy, Stats, TFChain, GraphQl, Activation, RMB } = result;
+
+ window.env.GRIDPROXY_URL = GridProxy!;
+ window.env.STATS_URL = Stats!;
+ window.env.GRAPHQL_URL = GraphQl!;
+ window.env.SUBSTRATE_URL = TFChain!;
+ window.env.ACTIVATION_SERVICE_URL = Activation!;
+ window.env.RELAY_DOMAIN = RMB!;
+ return true;
+}
diff --git a/packages/playground/src/global-components.d.ts b/packages/playground/src/global-components.d.ts
index 4a96d6c38e..50de9e277a 100644
--- a/packages/playground/src/global-components.d.ts
+++ b/packages/playground/src/global-components.d.ts
@@ -38,7 +38,14 @@ declare module "@vue/runtime-core" {
declare global {
interface Window {
$$appLoader: () => void;
+ $$showMonitorError: (urls: { [key: string]: string | null }) => void;
env: {
+ GRAPHQL_STACKS: string[];
+ GRIDPROXY_STACKS: string[];
+ SUBSTRATE_STACKS: string[];
+ ACTIVATION_SERVICE_STACKS: string[];
+ RELAY_STACKS: string[];
+ STATS_STACKS: string[];
NETWORK: NetworkEnv;
GRAPHQL_URL: string;
GRIDPROXY_URL: string;
diff --git a/packages/playground/src/main.ts b/packages/playground/src/main.ts
index d8955a2949..b6462b2866 100644
--- a/packages/playground/src/main.ts
+++ b/packages/playground/src/main.ts
@@ -7,12 +7,12 @@ import { createApp } from "vue";
import vuetify from "@/plugins/vuetify";
-import App from "./App.vue";
import { defineGlobals } from "./config";
+import Monitor from "./Monitor.vue";
import router from "./router";
import { normalizeError } from "./utils/helpers";
-const app = createApp(App);
+const app = createApp(Monitor);
app.config.errorHandler = error => {
console.error(