diff --git a/package-lock.json b/package-lock.json index ee7825ad..2195baa2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "dependencies": { "@deriv-com/analytics": "^1.5.3", - "@deriv-com/api-hooks": "^0.0.22", + "@deriv-com/api-hooks": "^1.1.1", "@deriv-com/translations": "^1.2.4", "@deriv-com/ui": "latest", "@deriv-com/utils": "latest", @@ -102,6 +102,7 @@ "stylelint-selector-bem-pattern": "^4.0.0", "ts-jest": "^29.1.2", "typescript": "^5.2.2", + "vite-live-preview": "^0.1.6", "vite-plugin-svgr": "^4.2.0", "vite-require": "^0.2.3", "vite-tsconfig-paths": "^4.3.2", @@ -1103,6 +1104,15 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@commander-js/extra-typings": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-12.1.0.tgz", + "integrity": "sha512-wf/lwQvWAA0goIghcb91dQYpkLBcyhOhQNqG/VgWhnKzgt+UOMvra7EX/2fv70arm5RW+PUHoQHHDa6/p77Eqg==", + "dev": true, + "peerDependencies": { + "commander": "~12.1.0" + } + }, "node_modules/@commitlint/cli": { "version": "17.8.1", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz", @@ -1714,23 +1724,21 @@ } }, "node_modules/@deriv-com/api-hooks": { - "version": "0.0.22", - "resolved": "https://registry.npmjs.org/@deriv-com/api-hooks/-/api-hooks-0.0.22.tgz", - "integrity": "sha512-/EH4I4eNS6EO2ukpYemVXfHNgjxeCQiORXLS2dlszD7hQwGTmeQ6acMIPm4TPVz8nsJ8q9rXlL3JHEpQMaFmTQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@deriv-com/api-hooks/-/api-hooks-1.1.1.tgz", + "integrity": "sha512-lM/XrjCLXF6NMuzGz5Tza1OhfuvP5/NxZ8ofykVG0wySNF4klYvTiSOvk+kJv+MLT8FY48JhdH1HMbdPKREtvA==", "dependencies": { - "@deriv-com/utils": "^0.0.11", - "@deriv/api-types": "^1.0.177", + "@deriv-com/utils": "^0.0.24", + "@deriv/api-types": "^1.0.667", "@deriv/deriv-api": "^1.0.15", - "@tanstack/react-query": "^5.28.14", + "@tanstack/react-query": "^5.40.0", "@types/js-cookie": "^3.0.6", "js-cookie": "^3.0.5" + }, + "optionalDependencies": { + "@rollup/rollup-linux-x64-gnu": "^4.18.0" } }, - "node_modules/@deriv-com/api-hooks/node_modules/@deriv-com/utils": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@deriv-com/utils/-/utils-0.0.11.tgz", - "integrity": "sha512-O2ueP2Gu0FjPAe/4x94cj9b/cre8bIm0FdBL42TGy8dFa4zqA44fJdyl6uI1Ohg/uqQia7f/aR9iBBtnK3pg3A==" - }, "node_modules/@deriv-com/eslint-config-deriv": { "version": "2.1.0-beta.3", "resolved": "https://registry.npmjs.org/@deriv-com/eslint-config-deriv/-/eslint-config-deriv-2.1.0-beta.3.tgz", @@ -4413,6 +4421,12 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/ansi-html": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@types/ansi-html/-/ansi-html-0.0.0.tgz", + "integrity": "sha512-PEBpUlteD0VW02udY7UjjgjxHwVXmkdanhmRIMkzatGmORJGjzqKylrXVxz1G5xRTEECMxIkwTHpPmZ9Jb7ANQ==", + "dev": true + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -4724,6 +4738,15 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -5527,6 +5550,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -8126,6 +8161,18 @@ "node": ">=6" } }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -19036,9 +19083,9 @@ } }, "node_modules/vite": { - "version": "5.2.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", - "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", + "version": "5.2.13", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz", + "integrity": "sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==", "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", @@ -19089,6 +19136,41 @@ } } }, + "node_modules/vite-live-preview": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/vite-live-preview/-/vite-live-preview-0.1.6.tgz", + "integrity": "sha512-U+l8ntZObG1/RqDhUBMJ5SuK0l4rk2YtGPJRQC/2bkxk/V34lnOumix0TKl0ABND7jZKe+3dp9PIwbNFkUJFkQ==", + "dev": true, + "dependencies": { + "@commander-js/extra-typings": "^12.1.0", + "@types/ansi-html": "^0.0.0", + "@types/ws": "^8.5.10", + "ansi-html": "^0.0.9", + "chalk": "^5.3.0", + "commander": "^12.1.0", + "escape-goat": "^4.0.0", + "ws": "^8.17.0" + }, + "bin": { + "vite-live-preview": "bin.js", + "vlp": "bin.js" + }, + "peerDependencies": { + "vite": ">=5.2.13" + } + }, + "node_modules/vite-live-preview/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/vite-node": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", diff --git a/package.json b/package.json index 26cc666f..10724499 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "start": "vite", + "start:dev": "vite-live-preview --reload --port=8443", "build": "vite build", "preview": "vite preview", "test:lint": "prettier --log-level silent --write . && eslint \"./src/**/*.?(js|jsx|ts|tsx)\"", @@ -18,7 +19,7 @@ }, "dependencies": { "@deriv-com/analytics": "^1.5.3", - "@deriv-com/api-hooks": "^0.0.22", + "@deriv-com/api-hooks": "^1.1.1", "@deriv-com/translations": "^1.2.4", "@deriv-com/ui": "latest", "@deriv-com/utils": "latest", @@ -111,6 +112,7 @@ "stylelint-selector-bem-pattern": "^4.0.0", "ts-jest": "^29.1.2", "typescript": "^5.2.2", + "vite-live-preview": "^0.1.6", "vite-plugin-svgr": "^4.2.0", "vite-require": "^0.2.3", "vite-tsconfig-paths": "^4.3.2", diff --git a/src/app/app-content.jsx b/src/app/app-content.jsx index bbbce1a4..61bf5703 100644 --- a/src/app/app-content.jsx +++ b/src/app/app-content.jsx @@ -118,7 +118,7 @@ const AppContent = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - return !is_loading ? ( + return is_loading ? ( ) : ( <> diff --git a/src/app/index.ts b/src/app/index.ts index ee338bcf..f1f2a246 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -1,3 +1,3 @@ -import App from './app'; +import App from './App'; export default App; diff --git a/src/external/bot-skeleton/services/api/active-symbols.js b/src/external/bot-skeleton/services/api/active-symbols.js index 0d5a6cd6..1d426d74 100644 --- a/src/external/bot-skeleton/services/api/active-symbols.js +++ b/src/external/bot-skeleton/services/api/active-symbols.js @@ -4,6 +4,8 @@ import { localize } from '@/utils/tmp/dummy'; import { config } from '../../constants/config'; import PendingPromise from '../../utils/pending-promise'; +import { api_base } from './api-base'; + export default class ActiveSymbols { constructor(ws, trading_times) { this.active_symbols = []; @@ -25,11 +27,12 @@ export default class ActiveSymbols { } this.is_initialised = true; - - const { active_symbols } = await this.ws.authorized.activeSymbols(); + const active_symbols = api_base?.active_symbols ?? []; this.active_symbols = active_symbols; this.processed_symbols = this.processActiveSymbols(); + + // TODO: fix need to look into it as the method is not present this.trading_times.onMarketOpenCloseChanged = changes => { Object.keys(changes).forEach(symbol_name => { const symbol_obj = this.active_symbols[symbol_name]; diff --git a/src/external/bot-skeleton/services/api/api-base.js b/src/external/bot-skeleton/services/api/api-base.js index 81898ed2..9b8fdf64 100644 --- a/src/external/bot-skeleton/services/api/api-base.js +++ b/src/external/bot-skeleton/services/api/api-base.js @@ -14,6 +14,7 @@ class APIBase { time_interval = null; has_activeSymbols = false; is_stopping = false; + active_symbols = []; async init(force_update = false) { if (getLoginId()) { @@ -25,6 +26,11 @@ class APIBase { if (this.time_interval) clearInterval(this.time_interval); this.time_interval = null; this.getTime(); + } else { + this.api = generateDerivApiInstance(); + if (!this.has_activeSymbols) { + this.getActiveSymbols(); + } } } @@ -103,6 +109,7 @@ class APIBase { }); this.pip_sizes = pip_sizes; this.toggleRunButton(false); + this.active_symbols = active_symbols; }); }; diff --git a/src/external/bot-skeleton/services/api/trading-times.js b/src/external/bot-skeleton/services/api/trading-times.js index fb23f9df..c8c5ed03 100644 --- a/src/external/bot-skeleton/services/api/trading-times.js +++ b/src/external/bot-skeleton/services/api/trading-times.js @@ -71,7 +71,7 @@ export default class TradingTimes { async updateTradingTimes() { const last_update_date = this.last_update_moment.format('YYYY-MM-DD'); - const response = await this.ws.tradingTimes(last_update_date); + const response = await this.ws?.send({ trading_times: last_update_date }); if (response.error) { return; diff --git a/src/external/bot-skeleton/services/tradeEngine/trade/Balance.js b/src/external/bot-skeleton/services/tradeEngine/trade/Balance.js index dd2c1e96..7f24aac8 100644 --- a/src/external/bot-skeleton/services/tradeEngine/trade/Balance.js +++ b/src/external/bot-skeleton/services/tradeEngine/trade/Balance.js @@ -11,7 +11,7 @@ export default Engine => observeBalance() { if (!api_base.api) return; const subscription = api_base.api.onMessage().subscribe(({ data }) => { - if (data.msg_type === 'balance') { + if (data?.msg_type === 'balance' && data?.balance) { const { balance: { balance: b, currency }, } = data; diff --git a/src/hooks/useStore.tsx b/src/hooks/useStore.tsx index 8e030207..c6d296c0 100644 --- a/src/hooks/useStore.tsx +++ b/src/hooks/useStore.tsx @@ -1,4 +1,8 @@ -import { createContext, useContext, useMemo } from 'react'; +import { createContext, useContext, useEffect, useRef, useState } from 'react'; + +import { Loader } from '@deriv-com/ui'; + +import { api_base } from '@/external/bot-skeleton'; import Bot from '../external/bot-skeleton/scratch/dbot'; import RootStore from '../stores'; @@ -10,11 +14,28 @@ type TStoreProvider = { }; const StoreProvider: React.FC = ({ children }) => { - const memoizedValue = useMemo(() => { - return new RootStore(Bot); - }, []); + const [store, setStore] = useState(null); + const initializingStore = useRef(false); + + useEffect(() => { + const initializeStore = async () => { + await api_base.init(); + const ws = api_base.api; + const rootStore = new RootStore(Bot, ws); + setStore(rootStore); + }; + + if (!store && !initializingStore.current) { + initializingStore.current = true; + initializeStore(); + } + }, [store]); + + if (!store) { + return ; + } - return {children}; + return {children}; }; const useStore = () => { diff --git a/src/stores/app-store.ts b/src/stores/app-store.ts index 2393f5f8..a7520e28 100644 --- a/src/stores/app-store.ts +++ b/src/stores/app-store.ts @@ -25,7 +25,6 @@ export default class AppStore { disposeSwitchAccountListener: unknown; disposeLandingCompanyChangeReaction: unknown; disposeResidenceChangeReaction: unknown; - is_dbot_initialized: boolean; constructor(root_store: RootStore, core: TStores) { makeObservable(this, { @@ -47,7 +46,6 @@ export default class AppStore { this.dbot_store = null; this.api_helpers_store = null; this.timer = null; - this.is_dbot_initialized = false; } getErrorForNonEuClients = () => ({ @@ -148,7 +146,6 @@ export default class AppStore { blockly_store.setLoading(true); await DBot.initWorkspace('/', this.dbot_store, this.api_helpers_store, ui.is_mobile, false); - this.is_dbot_initialized = true; blockly_store.setContainerSize(); blockly_store.setLoading(false); @@ -335,10 +332,6 @@ export default class AppStore { server_time: this.core.common.server_time, ws: this.root_store.ws, }; - - if (!this.is_dbot_initialized) { - this.onMount(); - } }; onClickOutsideBlockly = (event: Event) => { diff --git a/src/stores/index.ts b/src/stores/index.ts index 166b8263..298d259d 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,7 +1,5 @@ import moment from 'moment'; -import { generateDerivApiInstance } from '@/external/bot-skeleton/services/api/appId'; - import AppStore from './app-store'; import BlocklyStore from './blockly-store'; import ChartStore from './chart-store'; @@ -46,9 +44,7 @@ export default class RootStore { public blockly_store: BlocklyStore; public data_collection_store: DataCollectionStore; - // TODO: fix - // ws = new WebSocket(`wss://${getSocketURL()}/websockets/v3?app_id=36300&l=EN&brand=deriv`); - ws = generateDerivApiInstance(); + ws = null; core = { client: { loginid: '', @@ -57,7 +53,6 @@ export default class RootStore { balance: 0, currency: 'USD', is_logged_in: false, - getSelfExclusion: () => {}, }, common: { is_socket_opened: false, @@ -82,7 +77,8 @@ export default class RootStore { pushDataLayer: () => {}, }; - constructor(dbot: unknown) { + constructor(dbot: unknown, ws: unknown) { + this.ws = ws; this.dbot = dbot; this.app = new AppStore(this, this.core); this.summary_card = new SummaryCardStore(this, this.core); diff --git a/src/stores/self-exclusion-store.ts b/src/stores/self-exclusion-store.ts index 820fe598..c186d696 100644 --- a/src/stores/self-exclusion-store.ts +++ b/src/stores/self-exclusion-store.ts @@ -2,6 +2,8 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { TStores } from '@deriv/stores/types'; +import { api_base } from '@/external/bot-skeleton'; + import RootStore from './root-store'; export default class SelfExclusionStore { @@ -64,10 +66,13 @@ export default class SelfExclusionStore { } async checkRestriction() { - const { client } = this.core; - await client.getSelfExclusion(); - if (client.self_exclusion.max_losses) { - this.setApiMaxLosses(client.self_exclusion.max_losses); + if (api_base.api) { + api_base.api.getSelfExclusion().then(response => { + const { max_losses: maxLosses } = response.get_self_exclusion; + if (maxLosses) { + this.setApiMaxLosses(maxLosses); + } + }); } } } diff --git a/vite.config.ts b/vite.config.ts index 45931c2e..254e961e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -33,15 +33,15 @@ export default defineConfig({ preprocessorOptions: { scss: { additionalData: ` - @import "src/components/shared/styles/constants.scss"; - @import "src/components/shared/styles/themes.scss"; - @import "src/components/shared/styles/devices.scss"; - @import "src/components/shared/styles/fonts.scss"; - @import "src/components/shared/styles/mixins.scss"; - @import "src/components/shared/styles/reset.scss"; - @import "src/components/shared/styles/inline-icons.scss"; - @import "src/components/shared/styles/google-fonts.scss"; - @import "src/styles/mixins.scss"; + @import "src/components/shared/styles/constants"; + @import "src/components/shared/styles/themes"; + @import "src/components/shared/styles/devices"; + @import "src/components/shared/styles/fonts"; + @import "src/components/shared/styles/mixins"; + @import "src/components/shared/styles/reset"; + @import "src/components/shared/styles/inline-icons"; + @import "src/components/shared/styles/google-fonts"; + @import "src/styles/mixins"; `, }, },