diff --git a/.github/workflows/pinata-build-deploy-ui.yml b/.github/workflows/pinata-build-deploy-ui.yml
index 2ca90a0f2..432ca40f0 100644
--- a/.github/workflows/pinata-build-deploy-ui.yml
+++ b/.github/workflows/pinata-build-deploy-ui.yml
@@ -32,12 +32,15 @@ jobs:
if [[ $BRANCH_NAME == 'master' ]]
then
echo "SUBDOMAIN=dex" >> $GITHUB_ENV
+ echo "VITE_APP_DEPLOYMENT=production"
elif [[ $BRANCH_NAME == 'develop' ]] && [[ "$TAG_NAME" != '' ]]
then
# because testnet is promoted to mainnet
echo "SUBDOMAIN=testnet" >> $GITHUB_ENV
+ echo "VITE_APP_DEPLOYMENT=staging"
else
echo "SUBDOMAIN=devnet" >> $GITHUB_ENV
+ echo "VITE_APP_DEPLOYMENT=develop"
fi
- name: Build App
diff --git a/docs/README.md b/docs/README.md
index 1feef7527..be1685a38 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -26,7 +26,7 @@ First of all you need is Keplr / Metamask installed. Generate a wallet for each
Run the yarn commands, pointed at devnet.
```
-export VUE_APP_DEPLOYMENT_TAG=devnet
+export VUE_APP_DEPLOYMENT=develop
export VUE_APP_ETHEREUM_ASSET_TAG=ethereum.mainnet
export VUE_APP_SIFCHAIN_ASSET_TAG=sifchain.mainnet
diff --git a/ui/app/package.json b/ui/app/package.json
index f41d80b74..dd9dc486d 100644
--- a/ui/app/package.json
+++ b/ui/app/package.json
@@ -15,12 +15,14 @@
"@sentry/vue": "^6.12.0",
"@sifchain/sdk": "^1.0.0",
"@types/color-hash": "^1.0.0",
+ "@types/dat.gui": "^0.7.7",
"autoprefixer": "^10.3.3",
"buffer": "^6.0.3",
"clsx": "^1.1.1",
"color-hash": "^1.0.3",
"copy-to-clipboard": "^3.3.1",
"core-js": "^3.6.5",
+ "dat.gui": "^0.7.7",
"flip-toolkit": "^7.0.13",
"normalize-scss": "^7.0.1",
"process": "^0.11.10",
diff --git a/ui/app/scripts/vite-polyfills.ts b/ui/app/scripts/vite-polyfills.ts
new file mode 100644
index 000000000..722d5afc0
--- /dev/null
+++ b/ui/app/scripts/vite-polyfills.ts
@@ -0,0 +1,24 @@
+// We have to add a few node polyfills to make Vite work.
+// Vite's official stance is they DO NOT support modules that
+// require node builtins as dependencies, but that doesn't really
+// work for us because of all the crypto modules.
+// So on the first js file compiled by vite, add a few globals...
+export function vitePolyfills() {
+ let addedPolyfills = false;
+ return {
+ name: "vite-polyfills",
+ transform(src, id) {
+ if (!addedPolyfills && /\.m?js$/.test(id)) {
+ addedPolyfills = true;
+ return {
+ code: [
+ `import { Buffer as ___Buffer } from 'buffer'; window.Buffer = ___Buffer;`,
+ `import * as ___process from 'process'; window.process = ___process;`,
+ `window.global = window;`,
+ src,
+ ].join("\n"),
+ };
+ }
+ },
+ };
+}
diff --git a/ui/app/src/App.vue b/ui/app/src/App.vue
index 6cdfd20ee..c3f1f3e09 100644
--- a/ui/app/src/App.vue
+++ b/ui/app/src/App.vue
@@ -1,29 +1,5 @@
-
+
@@ -42,6 +19,7 @@ import { useInitialize } from "./hooks/useInitialize";
import EnvAlert from "@/componentsLegacy/shared/EnvAlert.vue";
import SideBar from "@/componentsLegacy/NavSidePanel/NavSidePanel";
import Layout from "@/componentsLegacy/Layout/Layout";
+import { Flags } from "@/components/Flags/Flags";
import { useRoute, useRouter } from "vue-router";
import { accountStore } from "./store/modules/accounts";
import { Amount } from "@sifchain/sdk";
@@ -72,6 +50,7 @@ export default defineComponent({
EnvAlert,
SideBar,
OnboardingModal,
+ Flags,
},
computed: {
key() {
diff --git a/ui/app/src/assets/icons/interactive/settings.svg b/ui/app/src/assets/icons/interactive/settings.svg
new file mode 100644
index 000000000..19c27265a
--- /dev/null
+++ b/ui/app/src/assets/icons/interactive/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ui/app/src/components/AssetIcon.tsx b/ui/app/src/components/AssetIcon.tsx
index 2c35d3d53..7bcedd45d 100644
--- a/ui/app/src/components/AssetIcon.tsx
+++ b/ui/app/src/components/AssetIcon.tsx
@@ -50,6 +50,7 @@ export type InteractiveIconName =
| "tick"
| "wallet"
| "warning"
+ | "settings"
| "picture";
export type NavIconName =
diff --git a/ui/app/src/components/Flags/Flags.tsx b/ui/app/src/components/Flags/Flags.tsx
new file mode 100644
index 000000000..61f067adc
--- /dev/null
+++ b/ui/app/src/components/Flags/Flags.tsx
@@ -0,0 +1,46 @@
+import { useCore } from "@/hooks/useCore";
+import { flagsStore } from "@/store/modules/flags";
+import { defineComponent, watch } from "@vue/runtime-core";
+import { onMounted, ref } from "vue";
+import { Button } from "../Button/Button";
+
+const isProduction = import.meta.env.VITE_APP_DEPLOYMENT === "production";
+
+const loadGui = async () => {
+ return (await import("./flagsGui")).createGui;
+};
+
+export const Flags = defineComponent({
+ name: "FlagsGui",
+ setup() {
+ if (isProduction) return null;
+
+ const guiRef = ref();
+
+ watch(flagsStore.state, () => flagsStore.persist(), { deep: true });
+
+ watch(flagsStore.refs.ibcTransferTimeoutMinutes.computed(), (timeout) => {
+ useCore().services.ibc.transferTimeoutMinutes = timeout;
+ });
+
+ const toggleGui = async () => {
+ if (!guiRef.value) {
+ const createGui = await loadGui();
+ guiRef.value = createGui();
+ document.body.appendChild(guiRef.value.domElement);
+ } else {
+ guiRef.value.domElement.remove();
+ guiRef.value.destroy();
+ guiRef.value = undefined;
+ }
+ };
+
+ return () => (
+
+ );
+ },
+});
diff --git a/ui/app/src/components/Flags/flagsGui.ts b/ui/app/src/components/Flags/flagsGui.ts
new file mode 100644
index 000000000..b94d072eb
--- /dev/null
+++ b/ui/app/src/components/Flags/flagsGui.ts
@@ -0,0 +1,30 @@
+import { flagsStore } from "@/store/modules/flags";
+import * as dat from "dat.gui";
+
+export const createGui = () => {
+ const gui = new dat.GUI({
+ load: {
+ preset: "Default",
+ closed: true,
+ },
+ autoPlace: false,
+ width: 400,
+ });
+
+ gui.useLocalStorage = true;
+
+ Object.assign(gui.domElement.style, {
+ zIndex: 30,
+ position: "fixed",
+ top: "48px",
+ right: 0,
+ });
+ gui.domElement.querySelector(".close-button")?.remove();
+ gui.show();
+
+ Object.keys(flagsStore.state).forEach((key) => {
+ gui.add(flagsStore.state, key);
+ });
+
+ return gui;
+};
diff --git a/ui/app/src/main.ts b/ui/app/src/main.ts
index 0b9c573dc..4e6c6a7a3 100644
--- a/ui/app/src/main.ts
+++ b/ui/app/src/main.ts
@@ -20,7 +20,11 @@ if (process.env.NODE_ENV === "development") {
// @ts-ignore
app.config.devtools = true;
}
-console.log(import.meta.env.VITE_APP_VERSION, import.meta.env.VITE_APP_SHA);
+console.log(
+ import.meta.env.VITE_APP_DEPLOYMENT,
+ import.meta.env.VITE_APP_VERSION,
+ import.meta.env.VITE_APP_SHA,
+);
app.use(vuexStore);
app.use(router).mount("#app");
diff --git a/ui/app/src/store/index.ts b/ui/app/src/store/index.ts
index f6eec85ca..c24428965 100644
--- a/ui/app/src/store/index.ts
+++ b/ui/app/src/store/index.ts
@@ -2,6 +2,7 @@ import { accountStore } from "./modules/accounts";
import { importStore } from "./modules/import";
import { createStore } from "vuex";
import { exportStore } from "./modules/export";
+import { flagsStore } from "./modules/flags";
export const vuexStore = createStore({
devtools: true,
@@ -9,10 +10,12 @@ export const vuexStore = createStore({
accountStore.register(vuexStore);
importStore.register(vuexStore);
exportStore.register(vuexStore);
+flagsStore.register(vuexStore);
export const rootStore = {
accounts: accountStore,
import: importStore,
export: exportStore,
+ flags: flagsStore,
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
diff --git a/ui/app/src/store/modules/flags.ts b/ui/app/src/store/modules/flags.ts
new file mode 100644
index 000000000..5bc166318
--- /dev/null
+++ b/ui/app/src/store/modules/flags.ts
@@ -0,0 +1,33 @@
+import { defineComponent } from "@vue/runtime-core";
+import { Vuextra } from "../Vuextra";
+
+export type FlagsState = {
+ ibcTransferTimeoutMinutes: number;
+ enableRewardsClaim: boolean;
+};
+
+let json: any = {};
+try {
+ json = JSON.parse(localStorage.getItem("flags") || "") || {};
+} catch (_) {}
+
+export const flagsStore = Vuextra.createStore({
+ name: "flags",
+ options: {
+ devtools: true,
+ },
+ state: {
+ ibcTransferTimeoutMinutes: json?.ibcTransferTimeoutMinutes || 45,
+ enableRewardsClaim: json?.enableRewardsClaim || false,
+ } as FlagsState,
+ getters: (state) => ({}),
+ mutations: (state) => ({}),
+ actions: (ctx) => ({
+ persist: () => {
+ localStorage.setItem("flags", JSON.stringify(ctx.state));
+ },
+ }),
+ modules: [],
+});
+
+const self = flagsStore;
diff --git a/ui/app/src/views/RewardsPage/components/RewardSection.tsx b/ui/app/src/views/RewardsPage/components/RewardSection.tsx
index 045c2f067..884a47130 100644
--- a/ui/app/src/views/RewardsPage/components/RewardSection.tsx
+++ b/ui/app/src/views/RewardsPage/components/RewardSection.tsx
@@ -11,6 +11,7 @@ import { Button } from "@/components/Button/Button";
import { defineComponent, PropType, computed } from "vue";
import { useCore } from "@/hooks/useCore";
import { accountStore } from "@/store/modules/accounts";
+import { flagsStore } from "@/store/modules/flags";
const REWARD_TYPE_DISPLAY_DATA = {
lm: {
@@ -161,7 +162,7 @@ export const RewardSection = defineComponent({
icon="navigation/rewards"
active
disabled={
- true ||
+ !flagsStore.state.enableRewardsClaim ||
!props.data?.user
?.totalClaimableCommissionsAndClaimableRewards ||
props.alreadyClaimed
diff --git a/ui/app/vite.config.ts b/ui/app/vite.config.ts
index 73ba1baae..6b19c6136 100644
--- a/ui/app/vite.config.ts
+++ b/ui/app/vite.config.ts
@@ -7,6 +7,7 @@ import { viteSingleFile } from "vite-plugin-singlefile";
import svgLoader from "./scripts/vite-svg-loader";
import { minifyHtml } from "vite-plugin-html";
import { visualizer } from "rollup-plugin-visualizer";
+import { vitePolyfills } from "./scripts/vite-polyfills";
// We turned off vite hmr because it's buggy, so we gotta add livereload.
import liveReload from "vite-plugin-live-reload";
@@ -14,7 +15,7 @@ const LR_EXTENSIONS = "js,json,ts,tsx,css,scss,html,vue,webp,jpg";
export default defineConfig({
plugins: [
- sifchainPolyfillPlugin(),
+ vitePolyfills(),
vueJsx(),
vue(),
(svgLoader as () => Plugin)(),
@@ -38,7 +39,7 @@ export default defineConfig({
cssCodeSplit: false,
rollupOptions: {
output: {
- // inlineDynamicImports: true,
+ inlineDynamicImports: false,
manualChunks: () => "everything.js",
},
plugins: [visualizer()],
@@ -64,28 +65,3 @@ export default defineConfig({
},
},
});
-
-// We have to add a few node polyfills to make Vite work.
-// Vite's official stance is they DO NOT support modules that
-// require node builtins as dependencies, but that doesn't really
-// work for us because of all the crypto modules.
-// So on the first js file compiled by vite, add a few globals...
-function sifchainPolyfillPlugin() {
- let addedPolyfills = false;
- return {
- name: "sifchain-polyfill-plugin",
- transform(src, id) {
- if (!addedPolyfills && /\.m?js$/.test(id)) {
- addedPolyfills = true;
- return {
- code: [
- `import { Buffer as ___Buffer } from 'buffer'; window.Buffer = ___Buffer;`,
- `import * as ___process from 'process'; window.process = ___process;`,
- `window.global = window;`,
- src,
- ].join("\n"),
- };
- }
- },
- };
-}
diff --git a/ui/core/src/services/IBCService/IBCService.ts b/ui/core/src/services/IBCService/IBCService.ts
index 83338e1a7..808cc981e 100644
--- a/ui/core/src/services/IBCService/IBCService.ts
+++ b/ui/core/src/services/IBCService/IBCService.ts
@@ -46,6 +46,8 @@ export class IBCService {
keplrProvider = KeplrWalletProvider.create(this.context);
+ public transferTimeoutMinutes = 45;
+
constructor(private context: IBCServiceContext) {}
static create(context: IBCServiceContext) {
return new this(context);
@@ -354,7 +356,7 @@ export class IBCService {
const symbol = params.assetAmountToTransfer.asset.symbol;
- const timeoutInMinutes = 45;
+ const timeoutInMinutes = this.transferTimeoutMinutes;
const timeoutTimestampInSeconds = Math.floor(
new Date().getTime() / 1000 + 60 * timeoutInMinutes,
);
diff --git a/ui/yarn.lock b/ui/yarn.lock
index 24578e32e..fc19dfe85 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -3375,6 +3375,11 @@
resolved "https://registry.yarnpkg.com/@types/color-hash/-/color-hash-1.0.0.tgz#2671e71d46ce07248ca149ca058bdc01c2dbb975"
integrity sha512-Vj9gPc43pJeILnI0Yh0ds4+1toNUmvVqKxg/5sY8ESZafKo24TY5eCKXwXPym1xcgEMb2Qxy3dRwaYOro4U5Tg==
+"@types/dat.gui@^0.7.7":
+ version "0.7.7"
+ resolved "https://registry.yarnpkg.com/@types/dat.gui/-/dat.gui-0.7.7.tgz#2125aedfaa190364c5a50b0447858a7e159aea2e"
+ integrity sha512-CxLCme0He5Jk3uQwfO/fGZMyNhb/ypANzqX0yU9lviBQMlen5SOvQTBQ/Cd9x5mFlUAK5Tk8RgvTyLj1nYkz+w==
+
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@@ -6628,6 +6633,11 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
+dat.gui@^0.7.7:
+ version "0.7.7"
+ resolved "https://registry.yarnpkg.com/dat.gui/-/dat.gui-0.7.7.tgz#7f96dbd21621a76385203659aebfa264ee6ae89b"
+ integrity sha512-sRl/28gF/XRC5ywC9I4zriATTsQcpSsRG7seXCPnTkK8/EQMIbCu5NPMpICLGxX9ZEUvcXR3ArLYCtgreFoMDw==
+
data-uri-to-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"