diff --git a/packages/account/package.json b/packages/account/package.json index 8093602b3d7d..ba1b91aa7b27 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -36,8 +36,8 @@ "formik": "^2.1.4", "i18n-iso-countries": "^6.8.0", "js-cookie": "^2.2.1", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", + "mobx": "6.5.0", + "mobx-react": "7.3.0", "onfido-sdk-ui": "6.8.0", "prop-types": "^15.7.2", "qrcode.react": "^1.0.0", diff --git a/packages/account/src/Components/self-exclusion/self-exclusion-inputs.jsx b/packages/account/src/Components/self-exclusion/self-exclusion-inputs.jsx index 110df8870525..97b312732820 100644 --- a/packages/account/src/Components/self-exclusion/self-exclusion-inputs.jsx +++ b/packages/account/src/Components/self-exclusion/self-exclusion-inputs.jsx @@ -206,7 +206,7 @@ const SessionAndLoginLimitsInputs = () => { min_date={toMoment().add(1, 'days').format('YYYY-MM-DD')} max_date={toMoment().add(6, 'weeks').format('YYYY-MM-DD')} {...field} - should_show_today={false} + should_show_today="false" className='da-self-exclusion__input' label={localize('Date')} value={values.timeout_until && epochToMoment(values.timeout_until)} diff --git a/packages/appstore/package.json b/packages/appstore/package.json index 69d985b18801..4a26ad13ecad 100644 --- a/packages/appstore/package.json +++ b/packages/appstore/package.json @@ -36,8 +36,8 @@ "@deriv/translations": "^1.0.0", "classnames": "^2.2.6", "formik": "^2.1.4", - "mobx": "^5.15.7", - "mobx-react-lite": "^2.2.2", + "mobx": "6.5.0", + "mobx-react-lite": "3.3.0", "object.fromentries": "^2.0.0", "prop-types": "^15.7.2", "react-router": "^5.2.0", diff --git a/packages/bot-web-ui/package.json b/packages/bot-web-ui/package.json index 02882ba575c6..973e4e5ede39 100644 --- a/packages/bot-web-ui/package.json +++ b/packages/bot-web-ui/package.json @@ -66,7 +66,7 @@ "dependencies": { "@deriv/bot-skeleton": "^1.0.0", "@deriv/components": "^1.0.0", - "@deriv/deriv-charts": "^0.6.0", + "@deriv/deriv-charts": "0.6.3", "@deriv/shared": "^1.0.0", "@deriv/translations": "^1.0.0", "classnames": "^2.2.6", @@ -75,8 +75,8 @@ "gh-pages": "^2.1.1", "immutable": "^3.8.2", "lz-string": "^1.4.4", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", + "mobx": "6.5.0", + "mobx-react": "7.3.0", "pako": "^1.0.11", "prop-types": "^15.7.2", "react": "^16.14.0", diff --git a/packages/cashier/package.json b/packages/cashier/package.json index 0554968e98dc..161093067d17 100644 --- a/packages/cashier/package.json +++ b/packages/cashier/package.json @@ -43,8 +43,8 @@ "classnames": "^2.2.6", "formik": "^2.1.4", "loadjs": "^4.2.0", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", + "mobx": "6.5.0", + "mobx-react": "7.3.0", "moment": "^2.29.2", "prop-types": "^15.7.2", "qrcode.react": "^1.0.0", diff --git a/packages/cashier/src/Stores/account-prompt-dialog-store.js b/packages/cashier/src/Stores/account-prompt-dialog-store.js index 1133463d0fdc..0cf09eebb51b 100644 --- a/packages/cashier/src/Stores/account-prompt-dialog-store.js +++ b/packages/cashier/src/Stores/account-prompt-dialog-store.js @@ -1,17 +1,29 @@ -import { observable, action } from 'mobx'; +import { observable, action, makeObservable } from 'mobx'; import { isCryptocurrency } from '@deriv/shared'; export default class AccountPromptDialogStore { constructor(root_store) { + makeObservable(this, { + should_show: observable, + is_confirmed: observable, + last_location: observable, + current_location: observable, + shouldNavigateAfterPrompt: action.bound, + resetLastLocation: action.bound, + resetIsConfirmed: action.bound, + onConfirm: action.bound, + onCancel: action.bound, + continueRoute: action.bound + }); + this.root_store = root_store; } - @observable should_show = false; - @observable is_confirmed = false; - @observable last_location = null; - @observable current_location = null; + should_show = false; + is_confirmed = false; + last_location = null; + current_location = null; - @action.bound shouldNavigateAfterPrompt(next_location, current_location) { if (!this.is_confirmed) { this.last_location = next_location; @@ -20,17 +32,14 @@ export default class AccountPromptDialogStore { } } - @action.bound resetLastLocation() { this.last_location = null; } - @action.bound resetIsConfirmed() { this.is_confirmed = false; } - @action.bound async onConfirm() { const { client, modules } = this.root_store; const { accounts_list } = modules.cashier.account_transfer; @@ -55,12 +64,10 @@ export default class AccountPromptDialogStore { } } - @action.bound onCancel() { this.should_show = false; } - @action.bound continueRoute() { if (this.is_confirmed && this.last_location) { this.root_store.common.routeTo(this.last_location); diff --git a/packages/cashier/src/Stores/account-transfer-store.js b/packages/cashier/src/Stores/account-transfer-store.js index 5232c5e8666e..f7c7515cc6a7 100644 --- a/packages/cashier/src/Stores/account-transfer-store.js +++ b/packages/cashier/src/Stores/account-transfer-store.js @@ -1,5 +1,5 @@ import React from 'react'; -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { formatMoney, isEmptyObject, @@ -39,27 +39,70 @@ const getSelectedError = (selected_value, is_from_account) => { export default class AccountTransferStore { constructor({ WS, root_store }) { + makeObservable(this, { + accounts_list: observable, + container: observable, + error: observable, + has_no_account: observable, + has_no_accounts_balance: observable, + is_transfer_confirm: observable, + is_transfer_successful: observable, + is_mt5_transfer_in_progress: observable, + minimum_fee: observable, + receipt: observable, + selected_from: observable, + selected_to: observable, + account_transfer_amount: observable, + transfer_fee: observable, + transfer_limit: observable, + is_account_transfer_visible: computed, + is_transfer_locked: computed, + setBalanceByLoginId: action.bound, + setBalanceSelectedFrom: action.bound, + setBalanceSelectedTo: action.bound, + onMountAccountTransfer: action.bound, + setHasNoAccountsBalance: action.bound, + setHasNoAccount: action.bound, + setTransferFee: action.bound, + setMinimumFee: action.bound, + setTransferLimit: action.bound, + sortAccountsTransfer: action.bound, + setSelectedFrom: action.bound, + setSelectedTo: action.bound, + setAccounts: action.bound, + setIsTransferConfirm: action.bound, + setAccountTransferAmount: action.bound, + setIsTransferSuccessful: action.bound, + setIsMT5TransferInProgress: action.bound, + setReceiptTransfer: action.bound, + onChangeTransferFrom: action.bound, + onChangeTransferTo: action.bound, + resetAccountTransfer: action.bound, + setTransferPercentageSelectorResult: action.bound, + validateTransferFromAmount: action.bound, + validateTransferToAmount: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable accounts_list = []; - @observable container = Constants.containers.account_transfer; - @observable error = new ErrorStore(); - @observable has_no_account = false; - @observable has_no_accounts_balance = false; - @observable is_transfer_confirm = false; - @observable is_transfer_successful = false; - @observable is_mt5_transfer_in_progress = false; - @observable minimum_fee = null; - @observable receipt = {}; - @observable selected_from = {}; - @observable selected_to = {}; - @observable account_transfer_amount = ''; - @observable transfer_fee = null; - @observable transfer_limit = {}; - - @computed + accounts_list = []; + container = Constants.containers.account_transfer; + error = new ErrorStore(); + has_no_account = false; + has_no_accounts_balance = false; + is_transfer_confirm = false; + is_transfer_successful = false; + is_mt5_transfer_in_progress = false; + minimum_fee = null; + receipt = {}; + selected_from = {}; + selected_to = {}; + account_transfer_amount = ''; + transfer_fee = null; + transfer_limit = {}; + get is_account_transfer_visible() { const { has_maltainvest_account, landing_company_shortcode, residence } = this.root_store.client; // cashier Transfer account tab is hidden for iom clients @@ -67,7 +110,6 @@ export default class AccountTransferStore { return residence !== 'im' && (landing_company_shortcode !== 'malta' || has_maltainvest_account); } - @computed get is_transfer_locked() { const { is_financial_account, @@ -84,17 +126,14 @@ export default class AccountTransferStore { return need_financial_assessment && this.error.is_ask_financial_risk_approval; } - @action.bound setBalanceByLoginId(loginid, balance) { this.accounts_list.find(acc => loginid === acc.value).balance = balance; } - @action.bound setBalanceSelectedFrom(balance) { this.selected_from.balance = balance; } - @action.bound setBalanceSelectedTo(balance) { this.selected_to.balance = balance; } @@ -103,7 +142,6 @@ export default class AccountTransferStore { // 1. fiat to crypto & vice versa // 2. fiat to mt & vice versa // 3. crypto to mt & vice versa - @action.bound async onMountAccountTransfer() { const { client, modules } = this.root_store; const { onMountCommon, setLoading, setOnRemount } = modules.cashier.general_store; @@ -183,17 +221,14 @@ export default class AccountTransferStore { return can_transfer; } - @action.bound setHasNoAccountsBalance(has_no_accounts_balance) { this.has_no_accounts_balance = has_no_accounts_balance; } - @action.bound setHasNoAccount(has_no_account) { this.has_no_account = has_no_account; } - @action.bound setTransferFee() { const transfer_fee = getPropertyValue(getCurrencies(), [ this.selected_from.currency, @@ -204,14 +239,12 @@ export default class AccountTransferStore { this.transfer_fee = Number(transfer_fee || 0); } - @action.bound setMinimumFee() { const decimals = getDecimalPlaces(this.selected_from.currency); // we need .toFixed() so that it doesn't display in scientific notation, e.g. 1e-8 for currencies with 8 decimal places this.minimum_fee = (1 / Math.pow(10, decimals)).toFixed(decimals); } - @action.bound setTransferLimit() { const is_mt_transfer = this.selected_from.is_mt || this.selected_to.is_mt; const is_dxtrade_transfer = this.selected_from.is_dxtrade || this.selected_to.is_dxtrade; @@ -242,7 +275,6 @@ export default class AccountTransferStore { }; } - @action.bound async sortAccountsTransfer(response_accounts) { const transfer_between_accounts = response_accounts || (await this.WS.authorized.transferBetweenAccounts()); if (!this.accounts_list.length) { @@ -378,49 +410,40 @@ export default class AccountTransferStore { this.setAccounts(arr_accounts); } - @action.bound setSelectedFrom(obj_values) { this.selected_from = obj_values; } - @action.bound setSelectedTo(obj_values) { this.selected_to = obj_values; } - @action.bound setAccounts(arr_accounts) { this.accounts_list = arr_accounts; } - @action.bound setIsTransferConfirm(is_transfer_confirm) { this.is_transfer_confirm = is_transfer_confirm; } - @action.bound setAccountTransferAmount(amount) { this.account_transfer_amount = amount; } - @action.bound setIsTransferSuccessful(is_transfer_successful) { this.is_transfer_successful = is_transfer_successful; } - @action.bound setIsMT5TransferInProgress(is_mt5_transfer_in_progress) { this.is_mt5_transfer_in_progress = is_mt5_transfer_in_progress; } - @action.bound setReceiptTransfer({ amount }) { this.receipt = { amount_transferred: amount, }; } - @action.bound onChangeTransferFrom({ target }) { this.error.setErrorMessage(''); this.selected_from.error = ''; @@ -455,7 +478,6 @@ export default class AccountTransferStore { this.setTransferLimit(); } - @action.bound onChangeTransferTo({ target }) { this.error.setErrorMessage(''); this.selected_to.error = ''; @@ -551,13 +573,11 @@ export default class AccountTransferStore { return transfer_between_accounts; }; - @action.bound resetAccountTransfer = async () => { this.setIsTransferConfirm(false); this.setTransferLimit(); }; - @action.bound setTransferPercentageSelectorResult(amount) { const { crypto_fiat_converter, general_store } = this.root_store.modules.cashier; @@ -579,7 +599,6 @@ export default class AccountTransferStore { general_store.percentageSelectorSelectionStatus(false); } - @action.bound validateTransferFromAmount() { const { converter_from_amount, setConverterFromError } = this.root_store.modules.cashier.crypto_fiat_converter; @@ -602,7 +621,6 @@ export default class AccountTransferStore { } } - @action.bound validateTransferToAmount() { const { converter_to_amount, setConverterToError } = this.root_store.modules.cashier.crypto_fiat_converter; diff --git a/packages/cashier/src/Stores/base-store.js b/packages/cashier/src/Stores/base-store.js index 7953bcce6ce6..0f385ba0196e 100644 --- a/packages/cashier/src/Stores/base-store.js +++ b/packages/cashier/src/Stores/base-store.js @@ -1,4 +1,4 @@ -import { action, intercept, observable, reaction, toJS, when } from 'mobx'; +import { action, intercept, observable, reaction, toJS, when, makeObservable } from 'mobx'; import { isProduction, isEmptyObject } from '@deriv/shared'; import Validator from 'Utils/Validator'; @@ -17,10 +17,8 @@ export default class BaseStore { SESSION_STORAGE: Symbol('SESSION_STORAGE'), }); - @observable validation_errors = {}; - @observable validation_rules = {}; preSwitchAccountDisposer = null; @@ -44,7 +42,7 @@ export default class BaseStore { realAccountSignupEndedDisposer = null; real_account_signup_ended_listener = null; - @observable partial_fetch_time = 0; + partial_fetch_time = 0; /** * Constructor of the base class that gets properties' name of child which should be saved in storages @@ -57,6 +55,34 @@ export default class BaseStore { * @property {String} store_name - Explicit store name for browser application storage (to bypass minification) */ constructor(options = {}) { + makeObservable(this, { + validation_errors: observable, + validation_rules: observable, + partial_fetch_time: observable, + retrieveFromStorage: action, + setValidationErrorMessages: action, + setValidationRules: action, + addRule: action, + validateProperty: action, + validateAllProperties: action, + onSwitchAccount: action.bound, + onPreSwitchAccount: action.bound, + onLogout: action.bound, + onClientInit: action.bound, + onNetworkStatusChange: action.bound, + onThemeChange: action.bound, + onRealAccountSignupEnd: action.bound, + disposePreSwitchAccount: action.bound, + disposeSwitchAccount: action.bound, + disposeLogout: action.bound, + disposeClientInit: action.bound, + disposeNetworkStatusChange: action.bound, + disposeThemeChange: action.bound, + disposeRealAccountSignupEnd: action.bound, + onUnmount: action.bound, + assertHasValidCache: action.bound + }); + const { root_store, local_storage_properties, session_storage_properties, validation_rules, store_name } = options; @@ -172,7 +198,6 @@ export default class BaseStore { * Retrieves saved snapshot of the store and assigns to the current instance. * */ - @action retrieveFromStorage() { const local_storage_snapshot = JSON.parse(localStorage.getItem(this.store_name, {})); const session_storage_snapshot = JSON.parse(sessionStorage.getItem(this.store_name, {})); @@ -189,7 +214,6 @@ export default class BaseStore { * @param [{String}] messages - An array of strings that contains validation error messages for the particular property. * */ - @action setValidationErrorMessages(propertyName, messages) { const is_different = () => !!this.validation_errors[propertyName] @@ -206,7 +230,6 @@ export default class BaseStore { * @param {object} rules * */ - @action setValidationRules(rules = {}) { Object.keys(rules).forEach(key => { this.addRule(key, rules[key]); @@ -220,7 +243,6 @@ export default class BaseStore { * @param {String} rules * */ - @action addRule(property, rules) { this.validation_rules[property] = rules; @@ -237,7 +259,6 @@ export default class BaseStore { * @param {object} value - The value of the property, it can be undefined. * */ - @action validateProperty(property, value) { const trigger = this.validation_rules[property].trigger; const inputs = { [property]: value !== undefined ? value : this[property] }; @@ -261,7 +282,6 @@ export default class BaseStore { * Validates all properties which validation rule has been set for. * */ - @action validateAllProperties() { const validation_rules = Object.keys(this.validation_rules); const validation_errors = Object.keys(this.validation_errors); @@ -278,7 +298,6 @@ export default class BaseStore { }); } - @action.bound onSwitchAccount(listener) { if (listener) { this.switch_account_listener = listener; @@ -308,7 +327,6 @@ export default class BaseStore { } } - @action.bound onPreSwitchAccount(listener) { if (listener) { this.pre_switch_account_listener = listener; @@ -337,7 +355,6 @@ export default class BaseStore { } } - @action.bound onLogout(listener) { this.logoutDisposer = when( () => this.root_store.client.has_logged_out, @@ -364,7 +381,6 @@ export default class BaseStore { this.logout_listener = listener; } - @action.bound onClientInit(listener) { this.clientInitDisposer = when( () => this.root_store.client.initialized_broadcast, @@ -391,7 +407,6 @@ export default class BaseStore { this.client_init_listener = listener; } - @action.bound onNetworkStatusChange(listener) { this.networkStatusChangeDisposer = reaction( () => this.root_store.common.is_network_online, @@ -411,7 +426,6 @@ export default class BaseStore { this.network_status_change_listener = listener; } - @action.bound onThemeChange(listener) { this.themeChangeDisposer = reaction( () => this.root_store.ui.is_dark_mode_on, @@ -431,7 +445,6 @@ export default class BaseStore { this.theme_change_listener = listener; } - @action.bound onRealAccountSignupEnd(listener) { this.realAccountSignupEndedDisposer = when( () => this.root_store.ui.has_real_account_signup_ended, @@ -459,7 +472,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = listener; } - @action.bound disposePreSwitchAccount() { if (typeof this.preSwitchAccountDisposer === 'function') { this.preSwitchAccountDisposer(); @@ -467,7 +479,6 @@ export default class BaseStore { this.pre_switch_account_listener = null; } - @action.bound disposeSwitchAccount() { if (typeof this.switchAccountDisposer === 'function') { this.switchAccountDisposer(); @@ -475,7 +486,6 @@ export default class BaseStore { this.switch_account_listener = null; } - @action.bound disposeLogout() { if (typeof this.logoutDisposer === 'function') { this.logoutDisposer(); @@ -483,7 +493,6 @@ export default class BaseStore { this.logout_listener = null; } - @action.bound disposeClientInit() { if (typeof this.clientInitDisposer === 'function') { this.clientInitDisposer(); @@ -491,7 +500,6 @@ export default class BaseStore { this.client_init_listener = null; } - @action.bound disposeNetworkStatusChange() { if (typeof this.networkStatusChangeDisposer === 'function') { this.networkStatusChangeDisposer(); @@ -499,7 +507,6 @@ export default class BaseStore { this.network_status_change_listener = null; } - @action.bound disposeThemeChange() { if (typeof this.themeChangeDisposer === 'function') { this.themeChangeDisposer(); @@ -507,7 +514,6 @@ export default class BaseStore { this.theme_change_listener = null; } - @action.bound disposeRealAccountSignupEnd() { if (typeof this.realAccountSignupEndedDisposer === 'function') { this.realAccountSignupEndedDisposer(); @@ -515,7 +521,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = null; } - @action.bound onUnmount() { this.disposePreSwitchAccount(); this.disposeSwitchAccount(); @@ -526,7 +531,6 @@ export default class BaseStore { this.disposeRealAccountSignupEnd(); } - @action.bound assertHasValidCache(loginid, ...reactions) { // account was changed when this was unmounted. if (this.root_store.client.loginid !== loginid) { diff --git a/packages/cashier/src/Stores/crypto-fiat-converter-store.js b/packages/cashier/src/Stores/crypto-fiat-converter-store.js index feb27a634735..54397c8aaa20 100644 --- a/packages/cashier/src/Stores/crypto-fiat-converter-store.js +++ b/packages/cashier/src/Stores/crypto-fiat-converter-store.js @@ -1,49 +1,62 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { getDecimalPlaces } from '@deriv/shared'; export default class CryptoFiatConverterStore { constructor({ WS, root_store }) { + makeObservable(this, { + converter_from_amount: observable, + converter_to_amount: observable, + converter_from_error: observable, + converter_to_error: observable, + is_timer_visible: observable, + setConverterFromAmount: action.bound, + setConverterToAmount: action.bound, + setConverterFromError: action.bound, + setConverterToError: action.bound, + setIsTimerVisible: action.bound, + resetTimer: action.bound, + getExchangeRate: action.bound, + validateFromAmount: action.bound, + validateToAmount: action.bound, + onChangeConverterFromAmount: action.bound, + onChangeConverterToAmount: action.bound, + resetConverter: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable converter_from_amount = ''; - @observable converter_to_amount = ''; - @observable converter_from_error = ''; - @observable converter_to_error = ''; - @observable is_timer_visible = false; + converter_from_amount = ''; + converter_to_amount = ''; + converter_from_error = ''; + converter_to_error = ''; + is_timer_visible = false; - @action.bound setConverterFromAmount(amount) { this.converter_from_amount = amount; } - @action.bound setConverterToAmount(amount) { this.converter_to_amount = amount; } - @action.bound setConverterFromError(error) { this.converter_from_error = error; } - @action.bound setConverterToError(error) { this.converter_to_error = error; } - @action.bound setIsTimerVisible(is_timer_visible) { this.is_timer_visible = is_timer_visible; } - @action.bound resetTimer() { this.setIsTimerVisible(false); } - @action.bound async getExchangeRate(from_currency, to_currency) { const { exchange_rates } = await this.WS.send({ exchange_rates: 1, @@ -52,7 +65,6 @@ export default class CryptoFiatConverterStore { return exchange_rates.rates[to_currency]; } - @action.bound validateFromAmount() { const { account_transfer, general_store, withdraw } = this.root_store.modules.cashier; @@ -63,7 +75,6 @@ export default class CryptoFiatConverterStore { } } - @action.bound validateToAmount() { const { account_transfer, general_store, withdraw } = this.root_store.modules.cashier; @@ -74,7 +85,6 @@ export default class CryptoFiatConverterStore { } } - @action.bound async onChangeConverterFromAmount({ target }, from_currency, to_currency) { const { account_transfer, general_store } = this.root_store.modules.cashier; @@ -108,7 +118,6 @@ export default class CryptoFiatConverterStore { } } - @action.bound async onChangeConverterToAmount({ target }, from_currency, to_currency) { const { account_transfer, general_store } = this.root_store.modules.cashier; @@ -147,7 +156,6 @@ export default class CryptoFiatConverterStore { } } - @action.bound resetConverter() { this.setConverterFromAmount(''); this.setConverterToAmount(''); diff --git a/packages/cashier/src/Stores/deposit-store.js b/packages/cashier/src/Stores/deposit-store.js index 72b2f95d15f8..74e6bb32a56e 100644 --- a/packages/cashier/src/Stores/deposit-store.js +++ b/packages/cashier/src/Stores/deposit-store.js @@ -1,17 +1,24 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import Constants from 'Constants/constants'; import ErrorStore from './error-store'; export default class DepositStore { constructor({ WS, root_store }) { + makeObservable(this, { + container: observable, + error: observable, + onMountDeposit: action.bound, + is_deposit_locked: computed, + submitFundsProtection: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable container = Constants.containers.deposit; - @observable error = new ErrorStore(); + container = Constants.containers.deposit; + error = new ErrorStore(); - @action.bound async onMountDeposit() { const { client, modules } = this.root_store; const { active_container, is_crypto, onMountCommon, setLoading, setOnRemount } = modules.cashier.general_store; @@ -77,7 +84,6 @@ export default class DepositStore { setLoading(false); } - @computed get is_deposit_locked() { const { is_authentication_needed, @@ -112,7 +118,6 @@ export default class DepositStore { ); } - @action.bound submitFundsProtection() { this.WS.send({ ukgc_funds_protection: 1, tnc_approval: 1 }).then(response => { if (response.error) { diff --git a/packages/cashier/src/Stores/error-dialog-store.js b/packages/cashier/src/Stores/error-dialog-store.js index 70fd6eebbbfa..341579bebe58 100644 --- a/packages/cashier/src/Stores/error-dialog-store.js +++ b/packages/cashier/src/Stores/error-dialog-store.js @@ -1,39 +1,50 @@ -import { observable, action } from 'mobx'; +import { observable, action, makeObservable } from 'mobx'; export default class ErrorDialogStore { - @observable confirm_button_text = ''; - @observable error_message = ''; - @observable has_no_close_icon = false; - @observable should_show = false; - @observable should_not_show_title = false; + confirm_button_text = ''; + error_message = ''; + has_no_close_icon = false; + should_show = false; + should_not_show_title = false; + + constructor() { + makeObservable(this, { + confirm_button_text: observable, + error_message: observable, + has_no_close_icon: observable, + should_show: observable, + should_not_show_title: observable, + setShouldShow: action.bound, + setErrorMessage: action.bound, + setConfirmButtonText: action.bound, + setShouldNotShowTitle: action.bound, + setHasNoCloseIcon: action.bound, + openReadMoreDialog: action.bound, + reset: action.bound + }); + } - @action.bound setShouldShow(value) { this.should_show = value; } - @action.bound setErrorMessage(message) { this.error_message = message; this.setShouldShow(true); } - @action.bound setConfirmButtonText(text) { this.confirm_button_text = text; } - @action.bound setShouldNotShowTitle(value) { this.should_not_show_title = value; } - @action.bound setHasNoCloseIcon(value) { this.has_no_close_icon = value; } - @action.bound openReadMoreDialog(error_content, confirm_button_text) { this.setErrorMessage(error_content); this.setConfirmButtonText(confirm_button_text); @@ -41,7 +52,6 @@ export default class ErrorDialogStore { this.setShouldNotShowTitle(true); } - @action.bound reset() { this.setConfirmButtonText(''); this.setShouldNotShowTitle(false); diff --git a/packages/cashier/src/Stores/error-store.js b/packages/cashier/src/Stores/error-store.js index 52545ffb2013..c9c9c620185d 100644 --- a/packages/cashier/src/Stores/error-store.js +++ b/packages/cashier/src/Stores/error-store.js @@ -1,18 +1,38 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { getPropertyValue } from '@deriv/shared'; export default class ErrorStore { - @observable message = ''; - @observable code = ''; - @observable fields = ''; - @observable is_show_full_page = false; - @observable onClickButton = null; - @observable is_ask_uk_funds_protection = false; - @observable is_self_exclusion_max_turnover_set = false; - @observable is_ask_authentication = false; - @observable is_ask_financial_risk_approval = false; + message = ''; + code = ''; + fields = ''; + is_show_full_page = false; + onClickButton = null; + is_ask_uk_funds_protection = false; + is_self_exclusion_max_turnover_set = false; + is_ask_authentication = false; + is_ask_financial_risk_approval = false; + + constructor() { + makeObservable(this, { + message: observable, + code: observable, + fields: observable, + is_show_full_page: observable, + onClickButton: observable, + is_ask_uk_funds_protection: observable, + is_self_exclusion_max_turnover_set: observable, + is_ask_authentication: observable, + is_ask_financial_risk_approval: observable, + setErrorMessage: action.bound, + handleCashierError: action.bound, + setMessage: action.bound, + setIsAskUkFundsProtection: action.bound, + setIsSelfExclusionMaxTurnoverSet: action.bound, + setIsAskAuthentication: action.bound, + setIsAskFinancialRiskApproval: action.bound + }); + } - @action.bound setErrorMessage(error, onClickButton, is_show_full_page) { // for errors that need to show a button, reset the form const error_object = { @@ -36,7 +56,6 @@ export default class ErrorStore { this.is_ask_financial_risk_approval = error_object?.is_ask_financial_risk_approval; } - @action.bound handleCashierError(error) { switch (error.code) { case 'ASK_TNC_APPROVAL': @@ -67,27 +86,22 @@ export default class ErrorStore { } } - @action.bound setMessage(value) { this.message = value; } - @action.bound setIsAskUkFundsProtection(value) { this.is_ask_uk_funds_protection = value; } - @action.bound setIsSelfExclusionMaxTurnoverSet(value) { this.is_self_exclusion_max_turnover_set = value; } - @action.bound setIsAskAuthentication(value) { this.is_ask_authentication = value; } - @action.bound setIsAskFinancialRiskApproval(value) { this.is_ask_financial_risk_approval = value; } diff --git a/packages/cashier/src/Stores/general-store.js b/packages/cashier/src/Stores/general-store.js index e95ccc61f33c..ba9185c9e4ef 100644 --- a/packages/cashier/src/Stores/general-store.js +++ b/packages/cashier/src/Stores/general-store.js @@ -1,5 +1,5 @@ import React from 'react'; -import { action, computed, observable, reaction, when } from 'mobx'; +import { action, computed, observable, reaction, when, makeObservable } from 'mobx'; import { isCryptocurrency, getPropertyValue, routes } from '@deriv/shared'; import { localize } from '@deriv/translations'; import Constants from 'Constants/constants'; @@ -9,6 +9,54 @@ import BaseStore from './base-store'; export default class GeneralStore extends BaseStore { constructor({ root_store, WS }) { super({ root_store }); + + makeObservable(this, { + is_loading: observable, + is_p2p_visible: observable, + p2p_notification_count: observable, + cashier_route_tab_index: observable, + is_deposit: observable, + should_show_all_available_currencies: observable, + is_cashier_default: observable, + deposit_target: observable, + should_set_currency_modal_title_change: observable, + p2p_advertiser_error: observable, + has_set_currency: observable, + should_percentage_reset: observable, + percentage: observable, + show_p2p_in_cashier_default: observable, + onRemount: observable, + setOnRemount: action.bound, + is_crypto: computed, + is_p2p_enabled: computed, + showP2pInCashierDefault: action.bound, + attachCashierToMenu: action.bound, + replaceCashierMenuOnclick: action.bound, + setHasSetCurrency: action.bound, + changeSetCurrencyModalTitle: action.bound, + onMountCashierDefault: action.bound, + calculatePercentage: action.bound, + percentageSelectorSelectionStatus: action.bound, + setIsDeposit: action.bound, + setShouldShowAllAvailableCurrencies: action.bound, + setIsCashierDefault: action.bound, + setDepositTarget: action.bound, + continueRoute: action.bound, + setAccountSwitchListener: action.bound, + init: action.bound, + getAdvertizerError: action.bound, + setP2pAdvertiserError: action.bound, + checkP2pStatus: action.bound, + onMountCommon: action.bound, + setCashierTabIndex: action.bound, + setNotificationCount: action.bound, + setIsP2pVisible: action.bound, + is_cashier_locked: computed, + is_system_maintenance: computed, + setLoading: action.bound, + setActiveTab: action.bound, + }); + this.WS = WS; this.root_store = root_store; @@ -36,42 +84,38 @@ export default class GeneralStore extends BaseStore { ); } - @observable is_loading = false; - @observable is_p2p_visible = false; - @observable p2p_notification_count = 0; - @observable cashier_route_tab_index = 0; - @observable is_deposit = false; - @observable should_show_all_available_currencies = false; - @observable is_cashier_default = true; - @observable deposit_target = ''; - @observable should_set_currency_modal_title_change = false; - @observable p2p_advertiser_error = undefined; - @observable has_set_currency = false; - @observable should_percentage_reset = false; - @observable percentage = 0; - @observable show_p2p_in_cashier_default = false; - @observable onRemount = () => {}; + is_loading = false; + is_p2p_visible = false; + p2p_notification_count = 0; + cashier_route_tab_index = 0; + is_deposit = false; + should_show_all_available_currencies = false; + is_cashier_default = true; + deposit_target = ''; + should_set_currency_modal_title_change = false; + p2p_advertiser_error = undefined; + has_set_currency = false; + should_percentage_reset = false; + percentage = 0; + show_p2p_in_cashier_default = false; + onRemount = () => {}; active_container = Constants.containers.deposit; is_populating_values = false; - @action.bound setOnRemount(func) { this.onRemount = func; } - @computed get is_crypto() { const { currency } = this.root_store.client; return !!currency && isCryptocurrency(currency); } - @computed get is_p2p_enabled() { return this.is_p2p_visible && !this.root_store.client.is_eu; } - @action.bound showP2pInCashierDefault() { const { account_list, is_virtual } = this.root_store.client; @@ -88,7 +132,6 @@ export default class GeneralStore extends BaseStore { } } - @action.bound attachCashierToMenu() { const { menu, ui } = this.root_store; @@ -106,7 +149,6 @@ export default class GeneralStore extends BaseStore { }); } - @action.bound replaceCashierMenuOnclick() { const { menu, ui } = this.root_store; @@ -125,7 +167,6 @@ export default class GeneralStore extends BaseStore { ); } - @action.bound setHasSetCurrency() { const { account_list, has_active_real_account } = this.root_store.client; @@ -134,12 +175,10 @@ export default class GeneralStore extends BaseStore { !has_active_real_account; } - @action.bound changeSetCurrencyModalTitle() { this.should_set_currency_modal_title_change = true; } - @action.bound async onMountCashierDefault() { const { account_prompt_dialog, payment_agent } = this.root_store.modules.cashier; @@ -157,7 +196,6 @@ export default class GeneralStore extends BaseStore { this.setLoading(false); } - @action.bound calculatePercentage(amount = this.root_store.modules.cashier.crypto_fiat_converter.converter_from_amount) { const { client, modules } = this.root_store; const { account_transfer } = modules.cashier; @@ -172,7 +210,6 @@ export default class GeneralStore extends BaseStore { } } - @action.bound percentageSelectorSelectionStatus(should_percentage_reset) { this.should_percentage_reset = should_percentage_reset; @@ -181,32 +218,26 @@ export default class GeneralStore extends BaseStore { } } - @action.bound setIsDeposit(is_deposit) { this.is_deposit = is_deposit; } - @action.bound setShouldShowAllAvailableCurrencies(value) { this.should_show_all_available_currencies = value; } - @action.bound setIsCashierDefault(is_cashier_default) { this.is_cashier_default = is_cashier_default; } - @action.bound setDepositTarget(target) { this.deposit_target = target; } - @action.bound continueRoute() { this.root_store.common.routeTo(this.deposit_target); } - @action.bound setAccountSwitchListener() { // cashier inits once and tries to stay active until switching account // since cashier calls take a long time to respond or display in iframe @@ -216,7 +247,6 @@ export default class GeneralStore extends BaseStore { } // Initialise P2P attributes on app load without mounting the entire cashier - @action.bound async init() { if (this.root_store.modules.cashier) { const { @@ -241,25 +271,21 @@ export default class GeneralStore extends BaseStore { } } - @action.bound async getAdvertizerError() { const advertiser_info = await this.WS.authorized.p2pAdvertiserInfo(); this.setP2pAdvertiserError(getPropertyValue(advertiser_info, ['error', 'code'])); } - @action.bound setP2pAdvertiserError(value) { this.p2p_advertiser_error = value; } - @action.bound checkP2pStatus() { const advertiser_error = this.p2p_advertiser_error; const is_p2p_restricted = advertiser_error === 'RestrictedCountry' || advertiser_error === 'RestrictedCurrency'; this.setIsP2pVisible(!(is_p2p_restricted || this.root_store.client.is_virtual)); } - @action.bound async onMountCommon(should_remount) { const { client, common, modules } = this.root_store; const { account_transfer, onramp, payment_agent, payment_agent_transfer, transaction_history } = @@ -303,17 +329,14 @@ export default class GeneralStore extends BaseStore { } } - @action.bound setCashierTabIndex(index) { this.cashier_route_tab_index = index; } - @action.bound setNotificationCount(notification_count) { this.p2p_notification_count = notification_count; } - @action.bound setIsP2pVisible(is_p2p_visible) { this.is_p2p_visible = is_p2p_visible; if (!is_p2p_visible && window.location.pathname.endsWith(routes.cashier_p2p)) { @@ -323,7 +346,6 @@ export default class GeneralStore extends BaseStore { } } - @computed get is_cashier_locked() { const { account_status } = this.root_store.client; @@ -331,7 +353,6 @@ export default class GeneralStore extends BaseStore { return account_status.status.some(status_name => status_name === 'cashier_locked'); } - @computed get is_system_maintenance() { const { account_status } = this.root_store.client; @@ -339,12 +360,10 @@ export default class GeneralStore extends BaseStore { return account_status.cashier_validation.some(validation => validation === 'system_maintenance'); } - @action.bound setLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setActiveTab(container) { this.active_container = container; } diff --git a/packages/cashier/src/Stores/iframe-store.js b/packages/cashier/src/Stores/iframe-store.js index 09fa2ba1ec66..7f3df17d72fb 100644 --- a/packages/cashier/src/Stores/iframe-store.js +++ b/packages/cashier/src/Stores/iframe-store.js @@ -1,20 +1,33 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import Constants from 'Constants/constants'; export default class IframeStore { constructor({ WS, root_store }) { + makeObservable(this, { + iframe_height: observable, + iframe_url: observable, + is_session_timeout: observable, + timeout_session: observable, + setSessionTimeout: action.bound, + checkIframeLoaded: action.bound, + clearTimeoutCashierUrl: action.bound, + setTimeoutCashierUrl: action.bound, + setIframeUrl: action.bound, + setContainerHeight: action.bound, + clearIframe: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable iframe_height = 0; - @observable iframe_url = ''; - @observable is_session_timeout = true; + iframe_height = 0; + iframe_url = ''; + is_session_timeout = true; onIframeLoaded = ''; - @observable timeout_session = ''; + timeout_session = ''; - @action.bound setSessionTimeout(is_session_time_out) { this.is_session_timeout = is_session_time_out; if (is_session_time_out) { @@ -22,7 +35,6 @@ export default class IframeStore { } } - @action.bound async checkIframeLoaded() { const { modules, ui } = this.root_store; @@ -51,14 +63,12 @@ export default class IframeStore { } } - @action.bound clearTimeoutCashierUrl() { if (this.timeout_session) { clearTimeout(this.timeout_session); } } - @action.bound setTimeoutCashierUrl() { this.clearTimeoutCashierUrl(); this.timeout_session = setTimeout(() => { @@ -66,8 +76,10 @@ export default class IframeStore { }, 60000); } - @action.bound - setIframeUrl(url, container = this.root_store.modules.cashier.general_store.active_container) { + setIframeUrl( + url, + container = this.root_store.modules.cashier.general_store.active_container + ) { const { client, ui } = this.root_store; if (url) { @@ -79,12 +91,10 @@ export default class IframeStore { } } - @action.bound setContainerHeight(height) { this.iframe_height = height; } - @action.bound clearIframe() { this.setContainerHeight(0); this.setIframeUrl(''); diff --git a/packages/cashier/src/Stores/on-ramp-store.js b/packages/cashier/src/Stores/on-ramp-store.js index 2d374a6b4dfe..9cfe478a1c71 100644 --- a/packages/cashier/src/Stores/on-ramp-store.js +++ b/packages/cashier/src/Stores/on-ramp-store.js @@ -1,26 +1,65 @@ -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import { localize } from '@deriv/translations'; import { getKebabCase, isCryptocurrency, routes, websiteUrl } from '@deriv/shared'; import OnrampProviders from 'Config/on-ramp-providers'; import BaseStore from './base-store'; export default class OnRampStore extends BaseStore { - @observable api_error = null; - @observable deposit_address = null; - @observable is_deposit_address_loading = true; - @observable is_deposit_address_popover_open = false; - @observable is_onramp_modal_open = false; - @observable is_requesting_widget_html = false; - @observable.shallow onramp_providers = []; - @observable.ref selected_provider = null; - @observable should_show_widget = false; - @observable widget_error = null; - @observable widget_html = null; + api_error = null; + deposit_address = null; + is_deposit_address_loading = true; + is_deposit_address_popover_open = false; + is_onramp_modal_open = false; + is_requesting_widget_html = false; + onramp_providers = []; + selected_provider = null; + should_show_widget = false; + widget_error = null; + widget_html = null; deposit_address_ref = null; constructor({ WS, root_store }) { super({ root_store }); + + makeObservable(this, { + api_error: observable, + deposit_address: observable, + is_deposit_address_loading: observable, + is_deposit_address_popover_open: observable, + is_onramp_modal_open: observable, + is_requesting_widget_html: observable, + onramp_providers: observable.shallow, + selected_provider: observable.ref, + should_show_widget: observable, + widget_error: observable, + widget_html: observable, + is_onramp_tab_visible: computed, + filtered_onramp_providers: computed, + onramp_popup_modal_title: computed, + should_show_dialog: computed, + onMountOnramp: action.bound, + onUnmountOnramp: action.bound, + onClickCopyDepositAddress: action.bound, + onClickDisclaimerContinue: action.bound, + onClickGoToDepositPage: action.bound, + pollApiForDepositAddress: action.bound, + resetPopup: action.bound, + setApiError: action.bound, + setCopyIconRef: action.bound, + setDepositAddress: action.bound, + setDepositAddressRef: action.bound, + setIsDepositAddressLoading: action.bound, + setIsDepositAddressPopoverOpen: action.bound, + setIsOnRampModalOpen: action.bound, + setIsRequestingWidgetHtml: action.bound, + setSelectedProvider: action.bound, + setShouldShowWidget: action.bound, + setOnrampProviders: action.bound, + setWidgetError: action.bound, + setWidgetHtml: action.bound + }); + this.WS = WS; this.onClientInit(async () => { @@ -32,7 +71,6 @@ export default class OnRampStore extends BaseStore { }); } - @computed get is_onramp_tab_visible() { const { client } = this.root_store; @@ -43,7 +81,6 @@ export default class OnRampStore extends BaseStore { ); } - @computed get filtered_onramp_providers() { const { client } = this.root_store; @@ -62,7 +99,6 @@ export default class OnRampStore extends BaseStore { ); } - @computed get onramp_popup_modal_title() { if (this.should_show_widget) { return localize('Payment channel'); @@ -75,12 +111,10 @@ export default class OnRampStore extends BaseStore { return undefined; } - @computed get should_show_dialog() { return this.api_error; } - @action.bound onMountOnramp() { this.disposeThirdPartyJsReaction = reaction( () => this.selected_provider, @@ -139,7 +173,6 @@ export default class OnRampStore extends BaseStore { ); } - @action.bound onUnmountOnramp() { if (typeof this.disposeThirdPartyJsReaction === 'function') { this.disposeThirdPartyJsReaction(); @@ -149,7 +182,6 @@ export default class OnRampStore extends BaseStore { } } - @action.bound onClickCopyDepositAddress() { const range = document.createRange(); range.selectNodeContents(this.deposit_address_ref); @@ -164,18 +196,15 @@ export default class OnRampStore extends BaseStore { }); } - @action.bound onClickDisclaimerContinue() { this.setShouldShowWidget(true); } - @action.bound onClickGoToDepositPage() { this.pollApiForDepositAddress(false); window.open(websiteUrl() + routes.cashier_deposit.substring(1)); } - @action.bound pollApiForDepositAddress(should_allow_empty_address) { // should_allow_empty_address: API returns empty deposit address for legacy accounts // that have never generated a deposit address. Setting this to "true" will allow @@ -216,7 +245,6 @@ export default class OnRampStore extends BaseStore { }, 30000); } - @action.bound resetPopup() { this.setApiError(null); this.setDepositAddress(null); @@ -228,47 +256,38 @@ export default class OnRampStore extends BaseStore { this.setWidgetHtml(null); } - @action.bound setApiError(api_error) { this.api_error = api_error; } - @action.bound setCopyIconRef(ref) { this.copy_icon_ref = ref; } - @action.bound setDepositAddress(deposit_address) { this.deposit_address = deposit_address; } - @action.bound setDepositAddressRef(ref) { this.deposit_address_ref = ref; } - @action.bound setIsDepositAddressLoading(is_loading) { this.is_deposit_address_loading = is_loading; } - @action.bound setIsDepositAddressPopoverOpen(is_open) { this.is_deposit_address_popover_open = is_open; } - @action.bound setIsOnRampModalOpen(is_open) { this.is_onramp_modal_open = is_open; } - @action.bound setIsRequestingWidgetHtml(is_requesting_widget_html) { this.is_requesting_widget_html = is_requesting_widget_html; } - @action.bound setSelectedProvider(provider) { if (provider) { this.selected_provider = provider; @@ -280,22 +299,18 @@ export default class OnRampStore extends BaseStore { } } - @action.bound setShouldShowWidget(should_show) { this.should_show_widget = should_show; } - @action.bound setOnrampProviders(onramp_providers) { this.onramp_providers = onramp_providers.slice(); } - @action.bound setWidgetError(widget_error) { this.widget_error = widget_error; } - @action.bound setWidgetHtml(widget_html) { this.widget_html = widget_html; } diff --git a/packages/cashier/src/Stores/payment-agent-store.js b/packages/cashier/src/Stores/payment-agent-store.js index d9201072d2b2..93004ada08dc 100644 --- a/packages/cashier/src/Stores/payment-agent-store.js +++ b/packages/cashier/src/Stores/payment-agent-store.js @@ -1,4 +1,4 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { formatMoney, routes } from '@deriv/shared'; import Constants from 'Constants/constants'; import ErrorStore from './error-store'; @@ -6,33 +6,76 @@ import VerificationStore from './verification-store'; export default class PaymentAgentStore { constructor({ WS, root_store }) { + makeObservable(this, { + list: observable, + agents: observable, + container: observable, + error: observable, + filtered_list: observable, + is_name_selected: observable, + is_withdraw: observable, + is_try_withdraw_successful: observable, + is_withdraw_successful: observable, + confirm: observable, + receipt: observable, + selected_bank: observable, + supported_banks: observable, + verification: observable, + active_tab_index: observable, + all_payment_agent_list: observable, + setActiveTabIndex: action.bound, + setActiveTab: action.bound, + is_payment_agent_visible: computed, + getPaymentAgentList: action.bound, + getPaymentAgentDetails: action.bound, + addSupportedBank: action.bound, + clearSuppertedBanks: action.bound, + sortSupportedBanks: action.bound, + setList: action.bound, + clearList: action.bound, + setPaymentAgentList: action.bound, + filterPaymentAgentList: action.bound, + onChangePaymentMethod: action.bound, + setIsWithdraw: action.bound, + setIsTryWithdrawSuccessful: action.bound, + setIsWithdrawSuccessful: action.bound, + setConfirmation: action.bound, + setReceipt: action.bound, + addPaymentAgent: action.bound, + onMountPaymentAgentWithdraw: action.bound, + requestTryPaymentAgentWithdraw: action.bound, + resetPaymentAgent: action.bound, + onMountPaymentAgentList: action.bound, + setAllPaymentAgentList: action.bound, + is_payment_agent_visible_in_onboarding: computed, + requestPaymentAgentWithdraw: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable list = []; - @observable agents = []; - @observable container = Constants.containers.payment_agent; - @observable error = new ErrorStore(); - @observable filtered_list = []; - @observable is_name_selected = true; - @observable is_withdraw = false; - @observable is_try_withdraw_successful = false; - @observable is_withdraw_successful = false; - @observable confirm = {}; - @observable receipt = {}; - @observable selected_bank = 0; - @observable supported_banks = []; - @observable verification = new VerificationStore({ root_store: this.root_store, WS: this.WS }); - @observable active_tab_index = 0; - @observable all_payment_agent_list = []; - - @action.bound + list = []; + agents = []; + container = Constants.containers.payment_agent; + error = new ErrorStore(); + filtered_list = []; + is_name_selected = true; + is_withdraw = false; + is_try_withdraw_successful = false; + is_withdraw_successful = false; + confirm = {}; + receipt = {}; + selected_bank = 0; + supported_banks = []; + verification = new VerificationStore({ root_store: this.root_store, WS: this.WS }); + active_tab_index = 0; + all_payment_agent_list = []; + setActiveTabIndex(index) { this.active_tab_index = index; } - @action.bound setActiveTab(index) { this.setActiveTabIndex(index); @@ -41,12 +84,10 @@ export default class PaymentAgentStore { } } - @computed get is_payment_agent_visible() { return !!(this.filtered_list.length || this.agents.length); } - @action.bound async getPaymentAgentList() { // wait for get_settings so residence gets populated in client-store // TODO: set residence in client-store from authorize so it's faster @@ -55,13 +96,11 @@ export default class PaymentAgentStore { return this.WS.authorized.paymentAgentList(residence, currency); } - @action.bound async getPaymentAgentDetails() { const { paymentagent_details } = await this.WS.authorized.paymentAgentDetails(); return paymentagent_details; } - @action.bound addSupportedBank(bank) { const supported_bank_exists = this.supported_banks.find( supported_bank => supported_bank.value === bank.toLowerCase() @@ -71,12 +110,10 @@ export default class PaymentAgentStore { } } - @action.bound clearSuppertedBanks() { this.supported_banks = []; } - @action.bound sortSupportedBanks() { // sort supported banks alphabetically by value, the option 'All payment agents' with value 0 should be on top this.supported_banks.replace( @@ -92,17 +129,14 @@ export default class PaymentAgentStore { ); } - @action.bound setList(pa_list) { this.list.push(pa_list); } - @action.bound clearList() { this.list = []; } - @action.bound async setPaymentAgentList(pa_list) { const payment_agent_list = pa_list || (await this.getPaymentAgentList()); this.clearList(); @@ -134,7 +168,6 @@ export default class PaymentAgentStore { this.sortSupportedBanks(); } - @action.bound filterPaymentAgentList(bank) { const { common } = this.root_store; if (bank) { @@ -158,30 +191,25 @@ export default class PaymentAgentStore { } } - @action.bound onChangePaymentMethod({ target }) { const value = target.value === '0' ? parseInt(target.value) : target.value; this.selected_bank = value; this.filterPaymentAgentList(value); } - @action.bound setIsWithdraw(is_withdraw = !this.is_withdraw) { this.is_withdraw = is_withdraw; } - @action.bound setIsTryWithdrawSuccessful(is_try_withdraw_successful) { this.error.setErrorMessage(''); this.is_try_withdraw_successful = is_try_withdraw_successful; } - @action.bound setIsWithdrawSuccessful(is_withdraw_successful) { this.is_withdraw_successful = is_withdraw_successful; } - @action.bound setConfirmation({ amount, currency, loginid, payment_agent_name }) { this.confirm = { amount, @@ -191,15 +219,16 @@ export default class PaymentAgentStore { }; } - @action.bound - setReceipt({ - amount_transferred, - payment_agent_email, - payment_agent_id, - payment_agent_name, - payment_agent_phone, - payment_agent_url, - }) { + setReceipt( + { + amount_transferred, + payment_agent_email, + payment_agent_id, + payment_agent_name, + payment_agent_phone, + payment_agent_url, + } + ) { this.receipt = { amount_transferred, payment_agent_email, @@ -210,7 +239,6 @@ export default class PaymentAgentStore { }; } - @action.bound addPaymentAgent(payment_agent) { this.agents.push({ text: payment_agent.name, @@ -223,7 +251,6 @@ export default class PaymentAgentStore { }); } - @action.bound async onMountPaymentAgentWithdraw() { const { common, modules } = this.root_store; const { setLoading, onMountCommon } = modules.cashier.general_store; @@ -251,7 +278,6 @@ export default class PaymentAgentStore { setLoading(false); } - @action.bound async requestTryPaymentAgentWithdraw({ loginid, currency, amount, verification_code }) { this.error.setErrorMessage(''); const payment_agent_withdraw = await this.WS.authorized.paymentAgentWithdraw({ @@ -275,7 +301,6 @@ export default class PaymentAgentStore { } } - @action.bound resetPaymentAgent = () => { this.error.setErrorMessage(''); this.setIsWithdraw(false); @@ -283,7 +308,6 @@ export default class PaymentAgentStore { this.setActiveTabIndex(0); }; - @action.bound async onMountPaymentAgentList() { const { setLoading, onMountCommon } = this.root_store.modules.cashier.general_store; @@ -300,17 +324,14 @@ export default class PaymentAgentStore { return this.WS.allPaymentAgentList(this.root_store.client.residence); } - @action.bound setAllPaymentAgentList(list) { this.all_payment_agent_list = list; } - @computed get is_payment_agent_visible_in_onboarding() { return !!this.all_payment_agent_list?.paymentagent_list?.list?.length; } - @action.bound async requestPaymentAgentWithdraw({ loginid, currency, amount, verification_code }) { this.error.setErrorMessage(''); const payment_agent_withdraw = await this.WS.authorized.paymentAgentWithdraw({ diff --git a/packages/cashier/src/Stores/payment-agent-transfer-store.js b/packages/cashier/src/Stores/payment-agent-transfer-store.js index bf70be42e66d..99840816cbc2 100644 --- a/packages/cashier/src/Stores/payment-agent-transfer-store.js +++ b/packages/cashier/src/Stores/payment-agent-transfer-store.js @@ -1,24 +1,45 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { routes } from '@deriv/shared'; import Constants from 'Constants/constants'; import ErrorStore from './error-store'; export default class PaymentAgentTransferStore { constructor({ WS, root_store }) { + makeObservable(this, { + container: observable, + error: observable, + is_payment_agent: observable, + is_try_transfer_successful: observable, + is_transfer_successful: observable, + confirm: observable, + receipt: observable, + transfer_limit: observable, + is_payment_agent_transfer_visible: computed, + setIsPaymentAgent: action.bound, + setIsTryTransferSuccessful: action.bound, + setIsTransferSuccessful: action.bound, + setConfirmationPaymentAgentTransfer: action.bound, + setReceiptPaymentAgentTransfer: action.bound, + setMinMaxPaymentAgentTransfer: action.bound, + onMountPaymentAgentTransfer: action.bound, + requestTryPaymentAgentTransfer: action.bound, + requestPaymentAgentTransfer: action.bound, + resetPaymentAgentTransfer: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable container = Constants.containers.payment_agent_transfer; - @observable error = new ErrorStore(); - @observable is_payment_agent = false; - @observable is_try_transfer_successful = false; - @observable is_transfer_successful = false; - @observable confirm = {}; - @observable receipt = {}; - @observable transfer_limit = {}; + container = Constants.containers.payment_agent_transfer; + error = new ErrorStore(); + is_payment_agent = false; + is_try_transfer_successful = false; + is_transfer_successful = false; + confirm = {}; + receipt = {}; + transfer_limit = {}; - @computed get is_payment_agent_transfer_visible() { return this.is_payment_agent; } @@ -28,7 +49,6 @@ export default class PaymentAgentTransferStore { this.setIsPaymentAgent(get_settings?.is_authenticated_payment_agent ?? false); } - @action.bound setIsPaymentAgent(is_payment_agent) { if (!is_payment_agent && window.location.pathname.endsWith(routes.cashier_pa_transfer)) { this.root_store.common.routeTo(routes.cashier_deposit); @@ -36,18 +56,15 @@ export default class PaymentAgentTransferStore { this.is_payment_agent = !!is_payment_agent; } - @action.bound setIsTryTransferSuccessful(is_try_transfer_successful) { this.error.setErrorMessage(''); this.is_try_transfer_successful = is_try_transfer_successful; } - @action.bound setIsTransferSuccessful(is_transfer_successful) { this.is_transfer_successful = is_transfer_successful; } - @action.bound setConfirmationPaymentAgentTransfer({ amount, client_id, client_name, description }) { this.confirm = { amount, @@ -57,7 +74,6 @@ export default class PaymentAgentTransferStore { }; } - @action.bound setReceiptPaymentAgentTransfer({ amount_transferred, client_id, client_name }) { this.receipt = { amount_transferred, @@ -76,7 +92,6 @@ export default class PaymentAgentTransferStore { return current_payment_agent ?? {}; } - @action.bound setMinMaxPaymentAgentTransfer({ min_withdrawal, max_withdrawal }) { this.transfer_limit = { min: min_withdrawal, @@ -84,7 +99,6 @@ export default class PaymentAgentTransferStore { }; } - @action.bound async onMountPaymentAgentTransfer() { const { general_store, payment_agent } = this.root_store.modules.cashier; @@ -99,7 +113,6 @@ export default class PaymentAgentTransferStore { general_store.setLoading(false); } - @action.bound requestTryPaymentAgentTransfer = async ({ amount, currency, description, transfer_to }) => { this.error.setErrorMessage(''); const payment_agent_transfer = await this.WS.authorized.paymentAgentTransfer({ @@ -125,7 +138,6 @@ export default class PaymentAgentTransferStore { return payment_agent_transfer; }; - @action.bound requestPaymentAgentTransfer = async ({ amount, currency, description, transfer_to }) => { this.error.setErrorMessage(''); const payment_agent_transfer = await this.WS.authorized.paymentAgentTransfer({ @@ -150,7 +162,6 @@ export default class PaymentAgentTransferStore { return payment_agent_transfer; }; - @action.bound resetPaymentAgentTransfer = () => { this.setIsTransferSuccessful(false); this.error.setErrorMessage(''); diff --git a/packages/cashier/src/Stores/transaction-history-store.js b/packages/cashier/src/Stores/transaction-history-store.js index bded4e9ada0a..9a7e2cec1770 100644 --- a/packages/cashier/src/Stores/transaction-history-store.js +++ b/packages/cashier/src/Stores/transaction-history-store.js @@ -1,21 +1,49 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { isCryptocurrency } from '@deriv/shared'; export default class TransactionHistoryStore { constructor({ WS, root_store }) { + makeObservable(this, { + crypto_transactions: observable, + is_crypto_transactions_cancel_modal_visible: observable, + is_crypto_transactions_status_modal_visible: observable, + is_crypto_transactions_visible: observable, + is_loading: observable, + selected_crypto_transaction_id: observable, + selected_crypto_status: observable, + selected_crypto_status_description: observable, + onMount: action.bound, + unsubscribeCryptoTransactions: action.bound, + getCryptoTransactions: action.bound, + setCryptoTransactionsHistory: action.bound, + updateCryptoTransactions: action.bound, + sortCryptoTransactions: action.bound, + cancelCryptoTransaction: action.bound, + setSelectedCryptoTransactionId: action.bound, + setIsCryptoTransactionsCancelModalVisible: action.bound, + showCryptoTransactionsCancelModal: action.bound, + hideCryptoTransactionsCancelModal: action.bound, + setSelectedCryptoStatus: action.bound, + setSelectedCryptoStatusDescription: action.bound, + setIsCryptoTransactionsStatusModalVisible: action.bound, + showCryptoTransactionsStatusModal: action.bound, + hideCryptoTransactionsStatusModal: action.bound, + setLoading: action.bound, + setIsCryptoTransactionsVisible: action.bound + }); + this.root_store = root_store; this.WS = WS; } - @observable crypto_transactions = []; - @observable is_crypto_transactions_cancel_modal_visible = false; - @observable is_crypto_transactions_status_modal_visible = false; - @observable is_crypto_transactions_visible = false; - @observable is_loading = false; - @observable selected_crypto_transaction_id = ''; - @observable selected_crypto_status = ''; - @observable selected_crypto_status_description = ''; + crypto_transactions = []; + is_crypto_transactions_cancel_modal_visible = false; + is_crypto_transactions_status_modal_visible = false; + is_crypto_transactions_visible = false; + is_loading = false; + selected_crypto_transaction_id = ''; + selected_crypto_status = ''; + selected_crypto_status_description = ''; - @action.bound async onMount() { const { currency, switched } = this.root_store.client; const is_crypto = !!currency && isCryptocurrency(currency); @@ -28,7 +56,6 @@ export default class TransactionHistoryStore { } } - @action.bound async unsubscribeCryptoTransactions() { await this.WS.authorized.cashierPayments({ provider: 'crypto', transaction_type: 'all' }).then(response => { if (!response.error) { @@ -38,7 +65,6 @@ export default class TransactionHistoryStore { }); } - @action.bound async getCryptoTransactions() { await this.WS.subscribeCashierPayments(response => { if (!response.error) { @@ -48,13 +74,11 @@ export default class TransactionHistoryStore { }); } - @action.bound setCryptoTransactionsHistory(transactions) { this.crypto_transactions = transactions; this.sortCryptoTransactions(); } - @action.bound updateCryptoTransactions(transactions) { transactions.forEach(transaction => { const index = this.crypto_transactions.findIndex(crypto => crypto.id === transaction.id); @@ -67,14 +91,12 @@ export default class TransactionHistoryStore { this.sortCryptoTransactions(); } - @action.bound sortCryptoTransactions() { this.crypto_transactions.replace( this.crypto_transactions.slice().sort((a, b) => b.submit_date - a.submit_date) ); } - @action.bound async cancelCryptoTransaction(transaction_id) { await this.WS.cancelCryptoTransaction(transaction_id).then(response => { if (!response.error) { @@ -86,61 +108,50 @@ export default class TransactionHistoryStore { }); } - @action.bound setSelectedCryptoTransactionId(id) { this.selected_crypto_transaction_id = id; } - @action.bound setIsCryptoTransactionsCancelModalVisible(is_visible) { this.is_crypto_transactions_cancel_modal_visible = is_visible; } - @action.bound showCryptoTransactionsCancelModal(id) { this.setSelectedCryptoTransactionId(id); this.setIsCryptoTransactionsCancelModalVisible(true); } - @action.bound hideCryptoTransactionsCancelModal() { this.setSelectedCryptoTransactionId(''); this.setIsCryptoTransactionsCancelModalVisible(false); } - @action.bound setSelectedCryptoStatus(status) { this.selected_crypto_status = status; } - @action.bound setSelectedCryptoStatusDescription(description) { this.selected_crypto_status_description = description; } - @action.bound setIsCryptoTransactionsStatusModalVisible(is_visible) { this.is_crypto_transactions_status_modal_visible = is_visible; } - @action.bound showCryptoTransactionsStatusModal(description, name) { this.setSelectedCryptoStatusDescription(description); this.setSelectedCryptoStatus(name); this.setIsCryptoTransactionsStatusModalVisible(true); } - @action.bound hideCryptoTransactionsStatusModal() { this.setIsCryptoTransactionsStatusModalVisible(false); } - @action.bound setLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsCryptoTransactionsVisible(is_visible) { this.is_crypto_transactions_visible = is_visible; } diff --git a/packages/cashier/src/Stores/verification-store.js b/packages/cashier/src/Stores/verification-store.js index 3509f664e444..2ade0bae72f9 100644 --- a/packages/cashier/src/Stores/verification-store.js +++ b/packages/cashier/src/Stores/verification-store.js @@ -1,41 +1,53 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import Constants from 'Constants/constants'; import ErrorStore from './error-store'; export default class VerificationStore { constructor({ WS, root_store }) { + makeObservable(this, { + is_button_clicked: observable, + timeout_button: observable, + error: observable, + is_email_sent: observable, + is_resend_clicked: observable, + resend_timeout: observable, + setIsButtonClicked: action.bound, + setTimeoutButton: action.bound, + setIsEmailSent: action.bound, + setIsResendClicked: action.bound, + setResendTimeout: action.bound, + setTimeoutVerification: action.bound, + sendVerificationEmail: action.bound, + resendVerificationEmail: action.bound, + }); + this.root_store = root_store; this.WS = WS; } - @observable is_button_clicked = false; - @observable timeout_button = ''; - @observable error = new ErrorStore(); - @observable is_email_sent = false; - @observable is_resend_clicked = false; - @observable resend_timeout = 60; + is_button_clicked = false; + timeout_button = ''; + error = new ErrorStore(); + is_email_sent = false; + is_resend_clicked = false; + resend_timeout = 60; - @action.bound setIsButtonClicked(value) { this.is_button_clicked = value; } - @action.bound setTimeoutButton(value) { this.timeout_button = value; } - @action.bound setIsEmailSent(value) { this.is_email_sent = value; } - @action.bound setIsResendClicked(value) { this.is_resend_clicked = value; } - @action.bound setResendTimeout(value) { this.resend_timeout = value; } @@ -46,7 +58,6 @@ export default class VerificationStore { } } - @action.bound setTimeoutVerification() { this.clearTimeoutVerification(); this.setTimeoutButton( @@ -56,7 +67,6 @@ export default class VerificationStore { ); } - @action.bound async sendVerificationEmail() { const { client, modules } = this.root_store; const { resetPaymentAgent } = modules.cashier.payment_agent; @@ -99,7 +109,6 @@ export default class VerificationStore { } } - @action.bound resendVerificationEmail() { // don't allow clicking while ongoing timeout if (this.resend_timeout < 60) { diff --git a/packages/cashier/src/Stores/withdraw-store.js b/packages/cashier/src/Stores/withdraw-store.js index 5b6c9c484229..33df90690663 100644 --- a/packages/cashier/src/Stores/withdraw-store.js +++ b/packages/cashier/src/Stores/withdraw-store.js @@ -1,5 +1,5 @@ import React from 'react'; -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { formatMoney, getDecimalPlaces, getMinWithdrawal, isMobile, validNumber } from '@deriv/shared'; import { localize } from '@deriv/translations'; import { ReadMore } from '@deriv/components'; @@ -9,21 +9,49 @@ import VerificationStore from './verification-store'; export default class WithdrawStore { constructor({ WS, root_store }) { + makeObservable(this, { + blockchain_address: observable, + container: observable, + error: observable, + is_10k_withdrawal_limit_reached: observable, + is_withdraw_confirmed: observable, + verification: observable, + withdraw_amount: observable, + max_withdraw_amount: observable, + crypto_config: observable, + setIsWithdrawConfirmed: action.bound, + setWithdrawAmount: action.bound, + requestWithdraw: action.bound, + saveWithdraw: action.bound, + resetWithrawForm: action.bound, + setBlockchainAddress: action.bound, + willMountWithdraw: action.bound, + onMountWithdraw: action.bound, + onMountCryptoWithdraw: action.bound, + is_withdrawal_locked: computed, + setMaxWithdrawAmount: action.bound, + check10kLimit: action.bound, + set10kLimitation: action.bound, + setWithdrawPercentageSelectorResult: action.bound, + validateWithdrawFromAmount: action.bound, + validateWithdrawToAmount: action.bound, + account_platform_icon: computed + }); + this.root_store = root_store; this.WS = WS; } - @observable blockchain_address = ''; - @observable container = Constants.containers.withdraw; - @observable error = new ErrorStore(); - @observable is_10k_withdrawal_limit_reached = undefined; - @observable is_withdraw_confirmed = false; - @observable verification = new VerificationStore({ root_store: this.root_store, WS: this.WS }); - @observable withdraw_amount = ''; - @observable max_withdraw_amount = 0; - @observable crypto_config = {}; - - @action.bound + blockchain_address = ''; + container = Constants.containers.withdraw; + error = new ErrorStore(); + is_10k_withdrawal_limit_reached = undefined; + is_withdraw_confirmed = false; + verification = new VerificationStore({ root_store: this.root_store, WS: this.WS }); + withdraw_amount = ''; + max_withdraw_amount = 0; + crypto_config = {}; + setIsWithdrawConfirmed(is_withdraw_confirmed) { const { converter_from_amount } = this.root_store.modules.cashier.crypto_fiat_converter; this.is_withdraw_confirmed = is_withdraw_confirmed; @@ -35,12 +63,10 @@ export default class WithdrawStore { } } - @action.bound setWithdrawAmount(amount) { this.withdraw_amount = amount; } - @action.bound async requestWithdraw(verification_code) { const { client, modules } = this.root_store; const { crypto_fiat_converter, error_dialog } = modules.cashier; @@ -68,7 +94,6 @@ export default class WithdrawStore { }); } - @action.bound async saveWithdraw(verification_code) { const { converter_from_amount } = this.root_store.modules.cashier.crypto_fiat_converter; @@ -91,7 +116,6 @@ export default class WithdrawStore { }); } - @action.bound resetWithrawForm() { const { setConverterFromAmount, setConverterToAmount } = this.root_store.modules.cashier.crypto_fiat_converter; this.setBlockchainAddress(''); @@ -100,19 +124,16 @@ export default class WithdrawStore { this.verification.clearVerification(); } - @action.bound setBlockchainAddress(address) { this.blockchain_address = address; } - @action.bound willMountWithdraw(verification_code) { if (verification_code) { this.verification.clearVerification(); } } - @action.bound async onMountWithdraw(verification_code) { const { client, modules } = this.root_store; const { active_container, is_crypto, onMountCommon, setLoading, setOnRemount } = modules.cashier.general_store; @@ -180,7 +201,6 @@ export default class WithdrawStore { } } - @action.bound async onMountCryptoWithdraw(verification_code) { const { crypto_fiat_converter, general_store, iframe } = this.root_store.modules.cashier; @@ -214,7 +234,6 @@ export default class WithdrawStore { } } - @computed get is_withdrawal_locked() { const { client } = this.root_store; const { authentication } = client.account_status; @@ -226,12 +245,10 @@ export default class WithdrawStore { return client.is_withdrawal_lock || need_authentication || this.error.is_ask_financial_risk_approval; } - @action.bound setMaxWithdrawAmount(amount) { this.max_withdraw_amount = amount; } - @action.bound async check10kLimit() { const { client } = this.root_store; @@ -242,12 +259,10 @@ export default class WithdrawStore { this.set10kLimitation(is_limit_reached); } - @action.bound set10kLimitation(is_limit_reached) { this.is_10k_withdrawal_limit_reached = is_limit_reached; } - @action.bound setWithdrawPercentageSelectorResult(amount) { const { client, modules } = this.root_store; const { crypto_fiat_converter, general_store } = modules.cashier; @@ -268,7 +283,6 @@ export default class WithdrawStore { general_store.percentageSelectorSelectionStatus(false); } - @action.bound validateWithdrawFromAmount() { let error_message = ''; @@ -320,7 +334,6 @@ export default class WithdrawStore { setConverterFromError(error_message); } - @action.bound validateWithdrawToAmount() { let error_message = ''; const { client, modules } = this.root_store; @@ -338,7 +351,6 @@ export default class WithdrawStore { setConverterToError(error_message); } - @computed get account_platform_icon() { const { account_list, loginid } = this.root_store.client; const platform_icon = account_list.find(acc => loginid === acc.loginid).icon; diff --git a/packages/cfd/package.json b/packages/cfd/package.json index 7647cb63aa4d..d36cd549bf59 100644 --- a/packages/cfd/package.json +++ b/packages/cfd/package.json @@ -95,9 +95,9 @@ "extend": "^3.0.2", "formik": "^2.1.4", "i18next": "^20.3.2", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", - "mobx-utils": "^5.5.5", + "mobx": "6.5.0", + "mobx-react": "7.3.0", + "mobx-utils": "6.0.5", "moment": "^2.29.2", "null-loader": "^4.0.1", "object.fromentries": "^2.0.0", diff --git a/packages/components/src/components/date-picker/date-picker.jsx b/packages/components/src/components/date-picker/date-picker.jsx index 6040755826a8..1b3af2acfbc3 100644 --- a/packages/components/src/components/date-picker/date-picker.jsx +++ b/packages/components/src/components/date-picker/date-picker.jsx @@ -250,7 +250,7 @@ DatePicker.defaultProps = { date_format: 'YYYY-MM-DD', mode: 'date', display_format: 'DD MMM YYYY', - keep_open: false, + keep_open: "false", }; DatePicker.propTypes = { diff --git a/packages/core/package.json b/packages/core/package.json index 84c26327a46b..e018fbf20763 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -100,7 +100,7 @@ "@deriv/cfd": "^1.0.0", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.8", - "@deriv/deriv-charts": "^0.6.0", + "@deriv/deriv-charts": "0.6.3", "@deriv/p2p": "^0.7.3", "@deriv/shared": "^1.0.0", "@deriv/trader": "^3.8.0", @@ -116,9 +116,9 @@ "js-cookie": "^2.2.1", "loadjs": "^4.2.0", "lodash.debounce": "^4.0.8", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", - "mobx-utils": "^5.5.5", + "mobx": "6.5.0", + "mobx-react": "7.3.0", + "mobx-utils": "6.0.5", "moment": "^2.29.2", "null-loader": "^4.0.1", "object.fromentries": "^2.0.0", diff --git a/packages/core/src/Stores/base-store.js b/packages/core/src/Stores/base-store.js index 66eb8f8ad1c4..dff2a3e28969 100644 --- a/packages/core/src/Stores/base-store.js +++ b/packages/core/src/Stores/base-store.js @@ -1,4 +1,4 @@ -import { action, intercept, observable, reaction, toJS, when } from 'mobx'; +import { action, intercept, observable, reaction, toJS, when, makeObservable } from 'mobx'; import { isProduction, isEmptyObject } from '@deriv/shared'; import Validator from 'Utils/Validator'; @@ -17,10 +17,8 @@ export default class BaseStore { SESSION_STORAGE: Symbol('SESSION_STORAGE'), }); - @observable validation_errors = {}; - @observable validation_rules = {}; preSwitchAccountDisposer = null; @@ -44,7 +42,7 @@ export default class BaseStore { realAccountSignupEndedDisposer = null; real_account_signup_ended_listener = null; - @observable partial_fetch_time = 0; + partial_fetch_time = 0; /** * Constructor of the base class that gets properties' name of child which should be saved in storages @@ -57,6 +55,34 @@ export default class BaseStore { * @property {String} store_name - Explicit store name for browser application storage (to bypass minification) */ constructor(options = {}) { + makeObservable(this, { + validation_errors: observable, + validation_rules: observable, + partial_fetch_time: observable, + retrieveFromStorage: action, + setValidationErrorMessages: action, + setValidationRules: action, + addRule: action, + validateProperty: action, + validateAllProperties: action, + onSwitchAccount: action.bound, + onPreSwitchAccount: action.bound, + onLogout: action.bound, + onClientInit: action.bound, + onNetworkStatusChange: action.bound, + onThemeChange: action.bound, + onRealAccountSignupEnd: action.bound, + disposePreSwitchAccount: action.bound, + disposeSwitchAccount: action.bound, + disposeLogout: action.bound, + disposeClientInit: action.bound, + disposeNetworkStatusChange: action.bound, + disposeThemeChange: action.bound, + disposeRealAccountSignupEnd: action.bound, + onUnmount: action.bound, + assertHasValidCache: action.bound + }); + const { root_store, local_storage_properties, session_storage_properties, validation_rules, store_name } = options; @@ -172,7 +198,6 @@ export default class BaseStore { * Retrieves saved snapshot of the store and assigns to the current instance. * */ - @action retrieveFromStorage() { const local_storage_snapshot = JSON.parse(localStorage.getItem(this.store_name, {})); const session_storage_snapshot = JSON.parse(sessionStorage.getItem(this.store_name, {})); @@ -189,7 +214,6 @@ export default class BaseStore { * @param [{String}] messages - An array of strings that contains validation error messages for the particular property. * */ - @action setValidationErrorMessages(propertyName, messages) { const is_different = () => !!this.validation_errors[propertyName] @@ -206,7 +230,6 @@ export default class BaseStore { * @param {object} rules * */ - @action setValidationRules(rules = {}) { Object.keys(rules).forEach(key => { this.addRule(key, rules[key]); @@ -220,7 +243,6 @@ export default class BaseStore { * @param {String} rules * */ - @action addRule(property, rules) { this.validation_rules[property] = rules; @@ -237,7 +259,6 @@ export default class BaseStore { * @param {object} value - The value of the property, it can be undefined. * */ - @action validateProperty(property, value) { const trigger = this.validation_rules[property].trigger; const inputs = { [property]: value !== undefined ? value : this[property] }; @@ -261,7 +282,6 @@ export default class BaseStore { * Validates all properties which validation rule has been set for. * */ - @action validateAllProperties() { const validation_rules = Object.keys(this.validation_rules); const validation_errors = Object.keys(this.validation_errors); @@ -278,7 +298,6 @@ export default class BaseStore { }); } - @action.bound onSwitchAccount(listener) { if (listener) { this.switch_account_listener = listener; @@ -308,7 +327,6 @@ export default class BaseStore { } } - @action.bound onPreSwitchAccount(listener) { if (listener) { this.pre_switch_account_listener = listener; @@ -338,7 +356,6 @@ export default class BaseStore { } } - @action.bound onLogout(listener) { this.logoutDisposer = when( () => this.root_store.client.has_logged_out, @@ -365,7 +382,6 @@ export default class BaseStore { this.logout_listener = listener; } - @action.bound onClientInit(listener) { this.clientInitDisposer = when( () => this.root_store.client.initialized_broadcast, @@ -392,7 +408,6 @@ export default class BaseStore { this.client_init_listener = listener; } - @action.bound onNetworkStatusChange(listener) { this.networkStatusChangeDisposer = reaction( () => this.root_store.common.is_network_online, @@ -412,7 +427,6 @@ export default class BaseStore { this.network_status_change_listener = listener; } - @action.bound onThemeChange(listener) { this.themeChangeDisposer = reaction( () => this.root_store.ui.is_dark_mode_on, @@ -432,7 +446,6 @@ export default class BaseStore { this.theme_change_listener = listener; } - @action.bound onRealAccountSignupEnd(listener) { this.realAccountSignupEndedDisposer = when( () => this.root_store.ui.has_real_account_signup_ended, @@ -460,7 +473,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = listener; } - @action.bound disposePreSwitchAccount() { if (typeof this.preSwitchAccountDisposer === 'function') { this.preSwitchAccountDisposer(); @@ -468,7 +480,6 @@ export default class BaseStore { this.pre_switch_account_listener = null; } - @action.bound disposeSwitchAccount() { if (typeof this.switchAccountDisposer === 'function') { this.switchAccountDisposer(); @@ -476,7 +487,6 @@ export default class BaseStore { this.switch_account_listener = null; } - @action.bound disposeLogout() { if (typeof this.logoutDisposer === 'function') { this.logoutDisposer(); @@ -484,7 +494,6 @@ export default class BaseStore { this.logout_listener = null; } - @action.bound disposeClientInit() { if (typeof this.clientInitDisposer === 'function') { this.clientInitDisposer(); @@ -492,7 +501,6 @@ export default class BaseStore { this.client_init_listener = null; } - @action.bound disposeNetworkStatusChange() { if (typeof this.networkStatusChangeDisposer === 'function') { this.networkStatusChangeDisposer(); @@ -500,7 +508,6 @@ export default class BaseStore { this.network_status_change_listener = null; } - @action.bound disposeThemeChange() { if (typeof this.themeChangeDisposer === 'function') { this.themeChangeDisposer(); @@ -508,7 +515,6 @@ export default class BaseStore { this.theme_change_listener = null; } - @action.bound disposeRealAccountSignupEnd() { if (typeof this.realAccountSignupEndedDisposer === 'function') { this.realAccountSignupEndedDisposer(); @@ -516,7 +522,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = null; } - @action.bound onUnmount() { this.disposePreSwitchAccount(); this.disposeSwitchAccount(); @@ -527,7 +532,6 @@ export default class BaseStore { this.disposeRealAccountSignupEnd(); } - @action.bound assertHasValidCache(loginid, ...reactions) { // account was changed when this was unmounted. if (this.root_store.client.loginid !== loginid) { diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js index d6a01a96e150..8275e9dd2cda 100644 --- a/packages/core/src/Stores/client-store.js +++ b/packages/core/src/Stores/client-store.js @@ -17,7 +17,7 @@ import { } from '@deriv/shared'; import { getLanguage, localize } from '@deriv/translations'; import Cookies from 'js-cookie'; -import { action, computed, observable, reaction, runInAction, toJS, when } from 'mobx'; +import { action, computed, observable, reaction, runInAction, toJS, when, makeObservable } from 'mobx'; import moment from 'moment'; import { requestLogout, WS } from 'Services'; import BinarySocketGeneral from 'Services/socket-general'; @@ -36,44 +36,44 @@ const eu_shortcode_regex = new RegExp('^(maltainvest|malta|iom)$'); const eu_excluded_regex = new RegExp('^mt$'); export default class ClientStore extends BaseStore { - @observable loginid; - @observable preferred_language; - @observable upgrade_info; - @observable email; - @observable accounts = {}; - @observable pre_switch_broadcast = false; - @observable switched = ''; - @observable is_switching = false; - @observable switch_broadcast = false; - @observable initialized_broadcast = false; - @observable currencies_list = {}; - @observable residence_list = []; - @observable states_list = []; - @observable selected_currency = ''; - @observable is_populating_account_list = false; - @observable is_populating_mt5_account_list = true; - @observable is_populating_dxtrade_account_list = true; - @observable has_reality_check = false; - @observable is_reality_check_dismissed; - @observable reality_check_dur; - @observable reality_check_timeout; - @observable website_status = {}; - @observable account_settings = {}; - @observable account_status = {}; - @observable device_data = {}; - @observable is_logging_in = false; - @observable has_logged_out = false; - @observable is_landing_company_loaded = false; - @observable is_account_setting_loaded = false; + loginid; + preferred_language; + upgrade_info; + email; + accounts = {}; + pre_switch_broadcast = false; + switched = ''; + is_switching = false; + switch_broadcast = false; + initialized_broadcast = false; + currencies_list = {}; + residence_list = []; + states_list = []; + selected_currency = ''; + is_populating_account_list = false; + is_populating_mt5_account_list = true; + is_populating_dxtrade_account_list = true; + has_reality_check = false; + is_reality_check_dismissed; + reality_check_dur; + reality_check_timeout; + website_status = {}; + account_settings = {}; + account_status = {}; + device_data = {}; + is_logging_in = false; + has_logged_out = false; + is_landing_company_loaded = false; + is_account_setting_loaded = false; // this will store the landing_company API response, including // financial_company: {} // gaming_company: {} // mt_financial_company: {} // mt_gaming_company: {} - @observable landing_companies = {}; + landing_companies = {}; // All possible landing companies of user between all - @observable standpoint = { + standpoint = { iom: false, svg: false, malta: false, @@ -82,22 +82,22 @@ export default class ClientStore extends BaseStore { financial_company: false, }; - @observable upgradeable_landing_companies = []; - @observable mt5_disabled_signup_types = { real: false, demo: false }; - @observable mt5_login_list = []; - @observable mt5_login_list_error = null; - @observable dxtrade_accounts_list = []; - @observable dxtrade_accounts_list_error = null; - @observable dxtrade_disabled_signup_types = { real: false, demo: false }; - @observable statement = []; - @observable obj_total_balance = { + upgradeable_landing_companies = []; + mt5_disabled_signup_types = { real: false, demo: false }; + mt5_login_list = []; + mt5_login_list_error = null; + dxtrade_accounts_list = []; + dxtrade_accounts_list_error = null; + dxtrade_disabled_signup_types = { real: false, demo: false }; + statement = []; + obj_total_balance = { amount_real: undefined, amount_mt5: undefined, amount_dxtrade: undefined, currency: '', }; - @observable verification_code = { + verification_code = { signup: '', reset_password: '', payment_withdraw: '', @@ -108,25 +108,25 @@ export default class ClientStore extends BaseStore { system_email_change: '', }; - @observable new_email = { + new_email = { system_email_change: '', }; - @observable account_limits = {}; - @observable account_limits = {}; + account_limits = {}; + account_limits = {}; - @observable self_exclusion = {}; + self_exclusion = {}; - @observable local_currency_config = { + local_currency_config = { currency: '', decimal_places: undefined, }; - @observable has_cookie_account = false; + has_cookie_account = false; - @observable financial_assessment = null; + financial_assessment = null; - @observable mt5_trading_servers = []; - @observable dxtrade_trading_servers = []; + mt5_trading_servers = []; + dxtrade_trading_servers = []; is_mt5_account_list_updated = false; @@ -134,6 +134,211 @@ export default class ClientStore extends BaseStore { const local_storage_properties = ['device_data']; super({ root_store, local_storage_properties, store_name }); + makeObservable(this, { + loginid: observable, + preferred_language: observable, + upgrade_info: observable, + email: observable, + accounts: observable, + pre_switch_broadcast: observable, + switched: observable, + is_switching: observable, + switch_broadcast: observable, + initialized_broadcast: observable, + currencies_list: observable, + residence_list: observable, + states_list: observable, + selected_currency: observable, + is_populating_account_list: observable, + is_populating_mt5_account_list: observable, + is_populating_dxtrade_account_list: observable, + has_reality_check: observable, + is_reality_check_dismissed: observable, + reality_check_dur: observable, + reality_check_timeout: observable, + website_status: observable, + account_settings: observable, + account_status: observable, + device_data: observable, + is_logging_in: observable, + has_logged_out: observable, + is_landing_company_loaded: observable, + is_account_setting_loaded: observable, + landing_companies: observable, + standpoint: observable, + upgradeable_landing_companies: observable, + mt5_disabled_signup_types: observable, + mt5_login_list: observable, + mt5_login_list_error: observable, + dxtrade_accounts_list: observable, + dxtrade_accounts_list_error: observable, + dxtrade_disabled_signup_types: observable, + statement: observable, + obj_total_balance: observable, + verification_code: observable, + new_email: observable, + account_limits: observable, + account_limits: observable, + self_exclusion: observable, + local_currency_config: observable, + has_cookie_account: observable, + financial_assessment: observable, + mt5_trading_servers: observable, + dxtrade_trading_servers: observable, + balance: computed, + is_reality_check_visible: computed, + is_svg: computed, + reality_check_duration: computed, + reality_check_dismissed: computed, + has_active_real_account: computed, + has_maltainvest_account: computed, + has_malta_account: computed, + has_any_real_account: computed, + first_switchable_real_loginid: computed, + can_change_fiat_currency: computed, + legal_allowed_currencies: computed, + upgradeable_currencies: computed, + current_currency_type: computed, + available_crypto_currencies: computed, + has_iom_account: computed, + has_fiat: computed, + current_fiat_currency: computed, + current_landing_company: computed, + account_list: computed, + has_real_mt5_login: computed, + has_real_dxtrade_login: computed, + has_account_error_in_mt5_real_list: computed, + has_account_error_in_mt5_demo_list: computed, + has_account_error_in_dxtrade_real_list: computed, + has_account_error_in_dxtrade_demo_list: computed, + can_have_more_real_synthetic_mt5: computed, + active_accounts: computed, + all_loginids: computed, + account_title: computed, + currency: computed, + default_currency: computed, + should_allow_authentication: computed, + is_authentication_needed: computed, + is_identity_verification_needed: computed, + is_tnc_needed: computed, + is_social_signup: computed, + is_mt5_password_not_set: computed, + is_dxtrade_password_not_set: computed, + is_financial_information_incomplete: computed, + is_deposit_lock: computed, + is_withdrawal_lock: computed, + is_trading_experience_incomplete: computed, + authentication_status: computed, + social_identity_provider: computed, + is_from_restricted_country: computed, + is_fully_authenticated: computed, + is_pending_authentication: computed, + is_financial_account: computed, + is_age_verified: computed, + landing_company_shortcode: computed, + landing_company: computed, + is_valid_login: computed, + is_logged_in: computed, + is_virtual: computed, + is_eu: computed, + is_uk: computed, + country_standpoint: computed, + can_have_mlt_account: computed, + can_have_mx_account: computed, + can_have_mf_account: computed, + can_upgrade: computed, + can_upgrade_to: computed, + virtual_account_loginid: computed, + is_single_currency: computed, + account_type: computed, + is_mt5_allowed: computed, + is_dxtrade_allowed: computed, + is_bot_allowed: computed, + clients_country: computed, + is_eu_country: computed, + is_options_blocked: computed, + is_multipliers_only: computed, + resetLocalStorageValues: action.bound, + getBasicUpgradeInfo: action.bound, + setMT5DisabledSignupTypes: action.bound, + setCFDDisabledSignupTypes: action.bound, + getLimits: action.bound, + setPreferredLanguage: action.bound, + setCookieAccount: action.bound, + updateSelfExclusion: action.bound, + responsePayoutCurrencies: action.bound, + responseAuthorize: action.bound, + setWebsiteStatus: action.bound, + accountRealReaction: action.bound, + setLoginInformation: action.bound, + realAccountSignup: action.bound, + setAccountCurrency: action.bound, + updateAccountCurrency: action.bound, + createCryptoAccount: action.bound, + residence: computed, + email_address: computed, + is_website_status_ready: computed, + updateAccountList: action.bound, + switchAccount: action.bound, + resetVirtualBalance: action.bound, + switchEndSignal: action.bound, + init: action.bound, + resetMt5AccountListPopulation: action.bound, + responseWebsiteStatus: action.bound, + responseLandingCompany: action.bound, + setStandpoint: action.bound, + setRealityCheck: action.bound, + setLoginId: action.bound, + setAccounts: action.bound, + setSwitched: action.bound, + setIsLoggingIn: action.bound, + setPreSwitchAccount: action.bound, + broadcastAccountChange: action.bound, + switchAccountHandler: action.bound, + registerReactions: action.bound, + setBalanceActiveAccount: action.bound, + setBalanceOtherAccounts: action.bound, + selectCurrency: action.bound, + setResidence: action.bound, + setEmail: action.bound, + setAccountSettings: action.bound, + setAccountStatus: action.bound, + updateAccountStatus: action.bound, + setInitialized: action.bound, + cleanUp: action.bound, + logout: action.bound, + setLogout: action.bound, + storeClientAccounts: action.bound, + setUserLogin: action.bound, + canStoreClientAccounts: action.bound, + setVerificationCode: action.bound, + setNewEmail: action.bound, + setDeviceData: action.bound, + getSignupParams: action.bound, + onSetResidence: action.bound, + onSignup: action.bound, + fetchAccountSettings: action.bound, + fetchResidenceList: action.bound, + setResidenceList: action.bound, + fetchStatesList: action.bound, + resetMt5ListPopulatedState: action.bound, + updateMt5LoginList: action.bound, + responseMT5TradingServers: action.bound, + responseMt5LoginList: action.bound, + responseDxtradeTradingServers: action.bound, + responseTradingPlatformAccountsList: action.bound, + responseStatement: action.bound, + getChangeableFields: action.bound, + syncWithLegacyPlatforms: action.bound, + is_high_risk: computed, + has_residence: computed, + setVisibilityRealityCheck: action.bound, + clearRealityCheckTimeout: action.bound, + setRealityCheckDuration: action.bound, + cleanupRealityCheck: action.bound, + fetchFinancialAssessment: action.bound, + }); + reaction( () => [ this.is_logged_in, @@ -155,7 +360,6 @@ export default class ClientStore extends BaseStore { ); } - @computed get balance() { if (isEmptyObject(this.accounts)) return undefined; return this.accounts[this.loginid] && 'balance' in this.accounts[this.loginid] @@ -163,7 +367,6 @@ export default class ClientStore extends BaseStore { : undefined; } - @computed get is_reality_check_visible() { if (!this.loginid || !this.landing_company) { return false; @@ -171,7 +374,6 @@ export default class ClientStore extends BaseStore { return !!(this.has_reality_check && !this.reality_check_dismissed); } - @computed get is_svg() { if (!this.landing_company_shortcode) { return false; @@ -179,29 +381,24 @@ export default class ClientStore extends BaseStore { return this.landing_company_shortcode === 'svg' || this.landing_company_shortcode === 'costarica'; } - @computed get reality_check_duration() { return this.has_reality_check ? this.reality_check_dur || +LocalStore.get('reality_check_duration') : undefined; } - @computed get reality_check_dismissed() { return this.has_reality_check ? this.is_reality_check_dismissed || JSON.parse(LocalStore.get('reality_check_dismissed') || false) : undefined; } - @computed get has_active_real_account() { return this.active_accounts.some(acc => acc.is_virtual === 0); } - @computed get has_maltainvest_account() { return this.active_accounts.some(acc => acc.landing_company_shortcode === 'maltainvest'); } - @computed get has_malta_account() { return this.active_accounts.some(acc => acc.landing_company_shortcode === 'malta'); } @@ -210,12 +407,10 @@ export default class ClientStore extends BaseStore { return this.account_list.some(acc => acc.is_virtual === 0); }; - @computed get has_any_real_account() { return this.hasAnyRealAccount(); } - @computed get first_switchable_real_loginid() { const result = this.active_accounts.find( acc => acc.is_virtual === 0 && acc.landing_company_shortcode === 'svg' @@ -223,7 +418,6 @@ export default class ClientStore extends BaseStore { return result.loginid || undefined; } - @computed get can_change_fiat_currency() { const has_no_mt5 = !this.has_real_mt5_login; const has_no_dxtrade = !this.has_real_dxtrade_login; @@ -234,7 +428,6 @@ export default class ClientStore extends BaseStore { return !this.is_virtual && has_account_criteria && this.current_currency_type === 'fiat'; } - @computed get legal_allowed_currencies() { const getDefaultAllowedCurrencies = () => { if (this.landing_companies.gaming_company) { @@ -265,7 +458,6 @@ export default class ClientStore extends BaseStore { return getDefaultAllowedCurrencies(); } - @computed get upgradeable_currencies() { if (!this.legal_allowed_currencies || !this.website_status.currencies_config) return []; return this.legal_allowed_currencies.map(currency => ({ @@ -274,7 +466,6 @@ export default class ClientStore extends BaseStore { })); } - @computed get current_currency_type() { if (this.account_type === 'virtual') return 'virtual'; if ( @@ -288,7 +479,6 @@ export default class ClientStore extends BaseStore { return undefined; } - @computed get available_crypto_currencies() { const values = Object.values(this.accounts).reduce((acc, item) => { acc.push(item.currency); @@ -298,12 +488,10 @@ export default class ClientStore extends BaseStore { return this.upgradeable_currencies.filter(acc => !values.includes(acc.value) && acc.type === 'crypto'); } - @computed get has_iom_account() { return this.active_accounts.some(acc => acc.landing_company_shortcode === 'iom'); } - @computed get has_fiat() { const values = Object.values(this.accounts).reduce((acc, item) => { if (!item.is_virtual) { @@ -314,7 +502,6 @@ export default class ClientStore extends BaseStore { return !!this.upgradeable_currencies.filter(acc => values.includes(acc.value) && acc.type === 'fiat').length; } - @computed get current_fiat_currency() { const values = Object.values(this.accounts).reduce((acc, item) => { if (!item.is_virtual) { @@ -330,7 +517,6 @@ export default class ClientStore extends BaseStore { // return the landing company object that belongs to the current client by matching shortcode // note that it will be undefined for logged out and virtual clients - @computed get current_landing_company() { const landing_company = this.landing_companies && @@ -340,17 +526,14 @@ export default class ClientStore extends BaseStore { return landing_company ? this.landing_companies[landing_company] : undefined; } - @computed get account_list() { return this.all_loginids.map(id => this.getAccountInfo(id)).filter(account => account); } - @computed get has_real_mt5_login() { return this.mt5_login_list.some(account => account.account_type === 'real'); } - @computed get has_real_dxtrade_login() { return this.dxtrade_accounts_list.some(account => account.account_type === 'real'); } @@ -362,27 +545,22 @@ export default class ClientStore extends BaseStore { return list?.some(account => !!account.has_error && account.account_type === account_type); }; - @computed get has_account_error_in_mt5_real_list() { return this.hasAccountErrorInCFDList(CFD_PLATFORMS.MT5, 'real'); } - @computed get has_account_error_in_mt5_demo_list() { return this.hasAccountErrorInCFDList(CFD_PLATFORMS.MT5, 'demo'); } - @computed get has_account_error_in_dxtrade_real_list() { return this.hasAccountErrorInCFDList(CFD_PLATFORMS.DXTRADE, 'real'); } - @computed get has_account_error_in_dxtrade_demo_list() { return this.hasAccountErrorInCFDList(CFD_PLATFORMS.DXTRADE, 'demo'); } - @computed get can_have_more_real_synthetic_mt5() { const number_of_current_added_synthetics = this.mt5_login_list.reduce((acc, cur) => { const is_included = @@ -396,24 +574,20 @@ export default class ClientStore extends BaseStore { return number_of_current_added_synthetics > 0 && number_of_available_synthetic > 0; } - @computed get active_accounts() { return this.accounts instanceof Object ? Object.values(this.accounts).filter(account => !account.is_disabled) : []; } - @computed get all_loginids() { return !isEmptyObject(this.accounts) ? Object.keys(this.accounts) : []; } - @computed get account_title() { return getAccountTitle(this.loginid); } - @computed get currency() { if (this.selected_currency.length) { return this.selected_currency; @@ -424,7 +598,6 @@ export default class ClientStore extends BaseStore { return this.default_currency; } - @computed get default_currency() { if (Object.keys(this.currencies_list).length > 0) { const keys = Object.keys(this.currencies_list); @@ -436,25 +609,21 @@ export default class ClientStore extends BaseStore { return 'USD'; } - @computed get should_allow_authentication() { return this.account_status?.status?.some( status => status === 'allow_document_upload' || status === 'allow_poi_resubmission' ); } - @computed get is_authentication_needed() { return !this.is_fully_authenticated && !!this.account_status?.authentication?.needs_verification?.length; } - @computed get is_identity_verification_needed() { const needs_verification = this.account_status?.authentication?.needs_verification; return needs_verification?.length === 1 && needs_verification?.includes('identity'); } - @computed get is_tnc_needed() { if (this.is_virtual) return false; @@ -464,80 +633,65 @@ export default class ClientStore extends BaseStore { return typeof client_tnc_status !== 'undefined' && client_tnc_status !== terms_conditions_version; } - @computed get is_social_signup() { return this.account_status?.status?.includes('social_signup'); } - @computed get is_mt5_password_not_set() { return this.account_status?.status?.includes('mt5_password_not_set'); } - @computed get is_dxtrade_password_not_set() { return this.account_status?.status?.includes('dxtrade_password_not_set'); } - @computed get is_financial_information_incomplete() { return this.account_status?.status?.some(status => status === 'financial_information_not_complete'); } - @computed get is_deposit_lock() { return this.account_status?.status?.some(status_name => status_name === 'deposit_locked'); } - @computed get is_withdrawal_lock() { return this.account_status?.status?.some(status_name => status_name === 'withdrawal_locked'); } - @computed get is_trading_experience_incomplete() { return this.account_status?.status?.some(status => status === 'trading_experience_not_complete'); } - @computed get authentication_status() { const document_status = this.account_status?.authentication?.document?.status; const identity_status = this.account_status?.authentication?.identity?.status; return { document_status, identity_status }; } - @computed get social_identity_provider() { return this.account_status?.social_identity_provider; } - @computed get is_from_restricted_country() { return this.residence_list.find(item => item.value === this.residence)?.disabled === 'DISABLED'; } - @computed get is_fully_authenticated() { return this.account_status?.status?.some(status => status === 'authenticated'); } - @computed get is_pending_authentication() { return this.account_status?.status?.some(status => status === 'document_under_review'); } - @computed get is_financial_account() { if (!this.landing_companies) return false; return this.account_type === 'financial'; } - @computed get is_age_verified() { return this.account_status?.status?.some(status => status === 'age_verification'); } - @computed get landing_company_shortcode() { if (this.accounts[this.loginid]) { return this.accounts[this.loginid].landing_company_shortcode; @@ -545,19 +699,16 @@ export default class ClientStore extends BaseStore { return undefined; } - @computed get landing_company() { return this.landing_companies; } - @computed get is_valid_login() { if (!this.is_logged_in) return true; const valid_login_ids_regex = new RegExp('^(MX|MF|VRTC|MLT|CR|FOG)[0-9]+$', 'i'); return this.all_loginids.every(id => valid_login_ids_regex.test(id)); } - @computed get is_logged_in() { return !!( !isEmptyObject(this.accounts) && @@ -567,12 +718,10 @@ export default class ClientStore extends BaseStore { ); } - @computed get is_virtual() { return !isEmptyObject(this.accounts) && this.accounts[this.loginid] && !!this.accounts[this.loginid].is_virtual; } - @computed get is_eu() { if (!this.landing_companies) return false; const { gaming_company, financial_company, mt_gaming_company } = this.landing_companies; @@ -586,12 +735,10 @@ export default class ClientStore extends BaseStore { : eu_excluded_regex.test(this.residence); } - @computed get is_uk() { return this.residence === 'gb'; } - @computed get country_standpoint() { const result = { is_united_kingdom: this.is_uk, @@ -615,7 +762,6 @@ export default class ClientStore extends BaseStore { // Manual list of MLT countries during MLT/MX account removal. // Also needed to check onboarding modal text for specific country. - @computed get can_have_mlt_account() { const countries = [ 'nl', @@ -643,7 +789,6 @@ export default class ClientStore extends BaseStore { } // Manual list of MX countries during MLT/MX account removal. - @computed get can_have_mx_account() { const countries = ['gb', 'im'].includes(this.residence); return countries; @@ -651,7 +796,6 @@ export default class ClientStore extends BaseStore { // Manual list of MF countries during MLT/MX account removal. // Also needed to check onboarding modal text for specific country. - @computed get can_have_mf_account() { const countries = [ 'it', @@ -683,22 +827,18 @@ export default class ClientStore extends BaseStore { return countries; } - @computed get can_upgrade() { return this.upgrade_info && (this.upgrade_info.can_upgrade || this.upgrade_info.can_open_multi); } - @computed get can_upgrade_to() { return this.upgrade_info && this.upgrade_info.can_upgrade_to; } - @computed get virtual_account_loginid() { return this.all_loginids.find(loginid => !!this.accounts[loginid].is_virtual); } - @computed get is_single_currency() { return ( Object.keys(this.currencies_list) @@ -707,22 +847,18 @@ export default class ClientStore extends BaseStore { ); } - @computed get account_type() { return getClientAccountType(this.loginid); } - @computed get is_mt5_allowed() { return this.isMT5Allowed(this.landing_companies); } - @computed get is_dxtrade_allowed() { return this.isDxtradeAllowed(this.landing_companies); } - @computed get is_bot_allowed() { return this.isBotAllowed(); } @@ -761,24 +897,20 @@ export default class ClientStore extends BaseStore { return this.is_virtual ? !this.is_multipliers_only : !is_mf && !this.is_options_blocked; }; - @computed get clients_country() { return this.website_status?.clients_country; } - @computed get is_eu_country() { const country = this.website_status.clients_country; if (country) return isEuCountry(country); return false; } - @computed get is_options_blocked() { return isOptionsBlocked(this.residence); } - @computed get is_multipliers_only() { return isMultipliersOnly(this.residence); } @@ -788,7 +920,6 @@ export default class ClientStore extends BaseStore { * * @param loginid */ - @action.bound resetLocalStorageValues(loginid) { this.accounts[loginid].accepted_bch = 0; LocalStore.setObject(storage_key, this.accounts); @@ -797,7 +928,6 @@ export default class ClientStore extends BaseStore { this.loginid = loginid; } - @action.bound getBasicUpgradeInfo() { const upgradeable_landing_companies = [ ...new Set(State.getResponse('authorize.upgradeable_landing_companies')), @@ -827,13 +957,11 @@ export default class ClientStore extends BaseStore { }; } - @action.bound setMT5DisabledSignupTypes(disabled_types_obj) { const current_list = this.mt5_disabled_signup_types; this.mt5_disabled_signup_types = { ...current_list, ...disabled_types_obj }; } - @action.bound setCFDDisabledSignupTypes(platform, disabled_types_obj) { if (platform === CFD_PLATFORMS.DXTRADE) { const current_list = this.dxtrade_disabled_signup_types; @@ -841,7 +969,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound getLimits() { return new Promise(resolve => { WS.authorized.storage.getLimits().then(data => { @@ -863,13 +990,11 @@ export default class ClientStore extends BaseStore { }); } - @action.bound setPreferredLanguage = lang => { this.preferred_language = lang; LocalStore.setObject(LANGUAGE_KEY, lang); }; - @action.bound setCookieAccount() { const domain = /deriv\.(com|me)/.test(window.location.hostname) ? deriv_urls.DERIV_HOST_NAME : 'binary.sx'; // eslint-disable-next-line max-len @@ -918,7 +1043,6 @@ export default class ClientStore extends BaseStore { }); }); } - @action.bound updateSelfExclusion(values) { return new Promise(resolve => { WS.authorized.storage.setSelfExclusion(values).then(data => { @@ -930,14 +1054,12 @@ export default class ClientStore extends BaseStore { }); } - @action.bound responsePayoutCurrencies(response) { const list = response.payout_currencies || response; this.currencies_list = buildCurrenciesList(list); this.selectCurrency(''); } - @action.bound responseAuthorize(response) { this.accounts[this.loginid].email = response.authorize.email; this.accounts[this.loginid].currency = response.authorize.currency; @@ -958,14 +1080,12 @@ export default class ClientStore extends BaseStore { : +response.authorize.local_currencies[this.local_currency_config.currency].fractional_digits; } - @action.bound setWebsiteStatus(response) { this.website_status = response.website_status; this.responseWebsiteStatus(response); setCurrencies(this.website_status); } - @action.bound async accountRealReaction(response) { return new Promise(resolve => { let client_accounts; @@ -1011,7 +1131,6 @@ export default class ClientStore extends BaseStore { }); } - @action.bound setLoginInformation(client_accounts, client_id) { this.setAccounts(client_accounts); localStorage.setItem(storage_key, JSON.stringify(client_accounts)); @@ -1022,7 +1141,6 @@ export default class ClientStore extends BaseStore { this.syncWithLegacyPlatforms(client_id, client_accounts); } - @action.bound async realAccountSignup(form_values) { const DEFAULT_CRYPTO_ACCOUNT_CURRENCY = 'BTC'; const is_maltainvest_account = this.root_store.ui.real_account_signup_target === 'maltainvest'; @@ -1069,7 +1187,6 @@ export default class ClientStore extends BaseStore { return Promise.reject(response.error); } - @action.bound async setAccountCurrency(currency) { const response = await WS.setAccountCurrency(currency, { previous_currency: this.currency, @@ -1081,7 +1198,6 @@ export default class ClientStore extends BaseStore { return Promise.reject(response.error); } - @action.bound async updateAccountCurrency(currency, is_set_storage = true) { runInAction(() => { const new_account = { ...this.accounts[this.loginid] }; @@ -1103,7 +1219,6 @@ export default class ClientStore extends BaseStore { await this.init(); } - @action.bound async createCryptoAccount(currency) { const residence = this.residence; const { date_of_birth, first_name, last_name } = this.account_settings; @@ -1123,7 +1238,6 @@ export default class ClientStore extends BaseStore { return Promise.reject(response.error); } - @computed get residence() { if (this.is_logged_in) { return this.account_settings.country_code ?? ''; @@ -1131,7 +1245,6 @@ export default class ClientStore extends BaseStore { return ''; } - @computed get email_address() { if (this.accounts && this.accounts[this.loginid]) { return this.accounts[this.loginid].email; @@ -1140,7 +1253,6 @@ export default class ClientStore extends BaseStore { return ''; } - @computed get is_website_status_ready() { return this.website_status && !BinarySocket.getAvailability().is_down; } @@ -1172,7 +1284,6 @@ export default class ClientStore extends BaseStore { return !/crs_tin_information/.test((this.account_status || {})?.status); }; - @action.bound updateAccountList(account_list) { account_list.forEach(account => { if (this.accounts[account.loginid]) { @@ -1193,7 +1304,6 @@ export default class ClientStore extends BaseStore { * * @param {string} loginid */ - @action.bound async switchAccount(loginid) { this.setPreSwitchAccount(true); this.setIsLoggingIn(true); @@ -1203,7 +1313,6 @@ export default class ClientStore extends BaseStore { this.responsePayoutCurrencies(await WS.authorized.payoutCurrencies()); } - @action.bound async resetVirtualBalance() { this.root_store.notifications.removeNotificationByKey({ key: 'reset_virtual_balance' }); this.root_store.notifications.removeNotificationMessage({ @@ -1213,7 +1322,6 @@ export default class ClientStore extends BaseStore { await WS.authorized.topupVirtual(); } - @action.bound switchEndSignal() { this.switch_broadcast = false; } @@ -1221,7 +1329,6 @@ export default class ClientStore extends BaseStore { /** * We initially fetch things from local storage, and then do everything inside the store. */ - @action.bound async init(login_new_user) { const search = window.location.search; const search_params = new URLSearchParams(search); @@ -1330,12 +1437,10 @@ export default class ClientStore extends BaseStore { return true; } - @action.bound resetMt5AccountListPopulation() { this.is_populating_mt5_account_list = false; } - @action.bound responseWebsiteStatus(response) { this.website_status = response.website_status; if (this.website_status.message && this.website_status.message.length) { @@ -1353,7 +1458,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound responseLandingCompany(response) { this.is_landing_company_loaded = true; this.landing_companies = response.landing_company; @@ -1361,7 +1465,6 @@ export default class ClientStore extends BaseStore { this.setRealityCheck(); } - @action.bound setStandpoint(landing_companies) { if (!landing_companies) return; const { gaming_company, financial_company } = landing_companies; @@ -1381,7 +1484,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound setRealityCheck() { this.has_reality_check = this.current_landing_company?.has_reality_check; // if page reloaded after reality check was submitted @@ -1395,17 +1497,14 @@ export default class ClientStore extends BaseStore { } } - @action.bound setLoginId(loginid) { this.loginid = loginid; } - @action.bound setAccounts(accounts) { this.accounts = accounts; } - @action.bound setSwitched(switched) { this.switched = switched; } @@ -1462,17 +1561,14 @@ export default class ClientStore extends BaseStore { }; } - @action.bound setIsLoggingIn(bool) { this.is_logging_in = bool; } - @action.bound setPreSwitchAccount(is_pre_switch) { this.pre_switch_broadcast = is_pre_switch; } - @action.bound broadcastAccountChange() { this.switch_broadcast = true; } @@ -1497,7 +1593,6 @@ export default class ClientStore extends BaseStore { return !this.all_loginids.some(id => id !== this.switched) || this.switched === this.loginid; } - @action.bound async switchAccountHandler() { if (!this.switched || !this.switched.length || !this.getAccount(this.switched)?.token) { if (this.isUnableToFindLoginId()) { @@ -1550,7 +1645,6 @@ export default class ClientStore extends BaseStore { runInAction(() => (this.is_switching = false)); } - @action.bound registerReactions() { // Switch account reactions. when( @@ -1567,7 +1661,6 @@ export default class ClientStore extends BaseStore { ); } - @action.bound setBalanceActiveAccount(obj_balance) { if (this.accounts[obj_balance?.loginid] && obj_balance.loginid === this.loginid) { this.accounts[obj_balance.loginid].balance = obj_balance.balance; @@ -1581,7 +1674,6 @@ export default class ClientStore extends BaseStore { // This callback is used for balance: all // Balance: all is very slow // --> so we keep a separate balance subscription for the active account - @action.bound setBalanceOtherAccounts(obj_balance) { // Balance subscription response received when mt5 transfer is in progress should be ignored. // After mt5 transfer is done, `balanceAll` is requested along with `mt5LoginList` in order to update the correct balance. @@ -1619,34 +1711,28 @@ export default class ClientStore extends BaseStore { } } - @action.bound selectCurrency(value) { this.selected_currency = value; } - @action.bound setResidence(residence) { this.accounts[this.loginid].residence = residence; } - @action.bound setEmail(email) { this.accounts[this.loginid].email = email; this.email = email; } - @action.bound setAccountSettings(settings) { this.account_settings = settings; this.is_account_setting_loaded = true; } - @action.bound setAccountStatus(status) { this.account_status = status; } - @action.bound async updateAccountStatus() { const account_status_response = await WS.authorized.getAccountStatus(); if (!account_status_response.error) { @@ -1654,12 +1740,10 @@ export default class ClientStore extends BaseStore { } } - @action.bound setInitialized(is_initialized) { this.initialized_broadcast = is_initialized; } - @action.bound cleanUp() { this.root_store.gtm.pushDataLayer({ event: 'log_out', @@ -1681,7 +1765,6 @@ export default class ClientStore extends BaseStore { this.cleanupRealityCheck(); } - @action.bound async logout() { // TODO: [add-client-action] - Move logout functionality to client store const response = await requestLogout(); @@ -1696,14 +1779,12 @@ export default class ClientStore extends BaseStore { return response; } - @action.bound setLogout(is_logged_out) { this.has_logged_out = is_logged_out; if (this.root_store.common.has_error) this.root_store.common.setError(false, null); } /* eslint-disable */ - @action.bound storeClientAccounts(obj_params, account_list) { // store consistent names with other API calls // API_V4: send consistent names @@ -1764,7 +1845,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound async setUserLogin(login_new_user) { // login_new_user is populated only on virtual sign-up let obj_params = {}; @@ -1827,7 +1907,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound canStoreClientAccounts(obj_params, account_list) { const is_ready_to_process = account_list && isEmptyObject(this.accounts); const accts = Object.keys(obj_params).filter(value => /^acct./.test(value)); @@ -1839,7 +1918,6 @@ export default class ClientStore extends BaseStore { return is_ready_to_process && is_cross_checked; } - @action.bound setVerificationCode(code, action) { this.verification_code[action] = code; if (code) { @@ -1853,7 +1931,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound setNewEmail(email, action) { this.new_email[action] = email; if (email) { @@ -1863,12 +1940,10 @@ export default class ClientStore extends BaseStore { } } - @action.bound setDeviceData() { setDeviceDataCookie('signup_device', isDesktopOs() ? 'desktop' : 'mobile'); } - @action.bound getSignupParams() { const param_list = [ 'date_first_contact', @@ -1900,7 +1975,6 @@ export default class ClientStore extends BaseStore { return signup_params; } - @action.bound onSetResidence({ residence }, cb) { if (!residence) return; WS.setSettings({ @@ -1926,7 +2000,6 @@ export default class ClientStore extends BaseStore { }); } - @action.bound onSignup({ password, residence }, cb) { if (!this.verification_code.signup || !password || !residence) return; WS.newAccountVirtual(this.verification_code.signup, password, residence, this.getSignupParams()).then( @@ -1967,7 +2040,6 @@ export default class ClientStore extends BaseStore { this.broadcastAccountChange(); } - @action.bound fetchAccountSettings() { return new Promise(resolve => { WS.authorized.storage.getSettings().then(response => { @@ -1977,7 +2049,6 @@ export default class ClientStore extends BaseStore { }); } - @action.bound fetchResidenceList() { return new Promise(resolve => { WS.storage.residenceList().then(response => { @@ -1987,12 +2058,10 @@ export default class ClientStore extends BaseStore { }); } - @action.bound setResidenceList(residence_list_response) { this.residence_list = residence_list_response.residence_list || []; } - @action.bound fetchStatesList() { return new Promise((resolve, reject) => { WS.authorized.storage @@ -2012,14 +2081,12 @@ export default class ClientStore extends BaseStore { }); } - @action.bound resetMt5ListPopulatedState() { this.is_mt5_account_list_updated = false; this.is_populating_mt5_account_list = true; this.mt5_login_list_error = null; } - @action.bound async updateMt5LoginList() { if (this.is_logged_in && !this.is_mt5_account_list_updated && !this.is_populating_mt5_account_list) { const response = await WS.mt5LoginList(); @@ -2027,7 +2094,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound responseMT5TradingServers(response) { if (response.error) { this.mt5_trading_servers = []; @@ -2036,7 +2102,6 @@ export default class ClientStore extends BaseStore { this.mt5_trading_servers = response.trading_servers; } - @action.bound responseMt5LoginList(response) { this.is_populating_mt5_account_list = false; this.is_mt5_account_list_updated = true; @@ -2078,7 +2143,6 @@ export default class ClientStore extends BaseStore { } } - @action.bound responseDxtradeTradingServers(response) { if (response.error) { this.dxtrade_trading_servers = []; @@ -2096,7 +2160,6 @@ export default class ClientStore extends BaseStore { }); } - @action.bound responseTradingPlatformAccountsList(response) { const { platform } = response.echo_req || {}; @@ -2130,14 +2193,12 @@ export default class ClientStore extends BaseStore { } } - @action.bound responseStatement(response) { if (!response.error) { this.statement = response.statement; } } - @action.bound getChangeableFields() { const get_settings = Object.keys(this.account_settings).length === 0 @@ -2148,7 +2209,6 @@ export default class ClientStore extends BaseStore { return Object.keys(get_settings).filter(field => !readonly_fields.includes(field)); } - @action.bound syncWithLegacyPlatforms(active_loginid, client_accounts) { const smartTrader = {}; const binaryBot = {}; @@ -2179,18 +2239,15 @@ export default class ClientStore extends BaseStore { }); } - @computed get is_high_risk() { if (isEmptyObject(this.account_status)) return false; return this.account_status.risk_classification === 'high'; } - @computed get has_residence() { return !!this.accounts[this.loginid]?.residence; } - @action.bound setVisibilityRealityCheck(is_visible) { // if reality check timeout has been set, don't make it visible until it runs out if (is_visible && typeof this.reality_check_timeout === 'number') { @@ -2201,13 +2258,11 @@ export default class ClientStore extends BaseStore { LocalStore.set('reality_check_dismissed', !is_visible); } - @action.bound clearRealityCheckTimeout() { clearTimeout(this.reality_check_timeout); this.reality_check_timeout = undefined; } - @action.bound setRealityCheckDuration(duration) { this.reality_check_dur = +duration; this.clearRealityCheckTimeout(); @@ -2221,7 +2276,6 @@ export default class ClientStore extends BaseStore { }, +duration * 60 * 1000); } - @action.bound cleanupRealityCheck() { this.has_reality_check = false; this.is_reality_check_dismissed = undefined; @@ -2231,7 +2285,6 @@ export default class ClientStore extends BaseStore { LocalStore.remove('reality_check_dismissed'); } - @action.bound fetchFinancialAssessment() { return new Promise(async resolve => { const { get_financial_assessment } = await WS.getFinancialAssessment(); diff --git a/packages/core/src/Stores/common-store.js b/packages/core/src/Stores/common-store.js index cc0baa6263af..308cbc646e33 100644 --- a/packages/core/src/Stores/common-store.js +++ b/packages/core/src/Stores/common-store.js @@ -1,6 +1,6 @@ import { getAppId, getUrlBinaryBot, getUrlSmartTrader, isMobile, platforms, routes, toMoment } from '@deriv/shared'; import { getAllowedLanguages } from '@deriv/translations'; -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { currentLanguage } from 'Utils/Language/index'; import ServerTime from '_common/base/server_time'; import BinarySocket from '_common/base/socket_base'; @@ -9,45 +9,81 @@ import BaseStore from './base-store'; export default class CommonStore extends BaseStore { constructor(root_store) { super({ root_store }); + + makeObservable(this, { + server_time: observable, + current_language: observable, + allowed_languages: observable, + has_error: observable, + error: observable, + network_status: observable, + is_network_online: observable, + is_socket_opened: observable, + was_socket_opened: observable, + services_error: observable, + deposit_url: observable, + withdraw_url: observable, + app_routing_history: observable, + app_router: observable, + app_id: observable, + platform: observable, + selected_contract_type: observable, + setSelectedContractType: action.bound, + init: action.bound, + checkAppId: action.bound, + changeCurrentLanguage: action.bound, + setPlatform: action.bound, + is_from_derivgo: computed, + setInitialRouteHistoryItem: action.bound, + setServerTime: action.bound, + setIsSocketOpened: action.bound, + setNetworkStatus: action.bound, + setError: action.bound, + showError: action.bound, + setDepositURL: action.bound, + setWithdrawURL: action.bound, + setServicesError: action.bound, + setAppRouterHistory: action.bound, + routeTo: action.bound, + addRouteHistoryItem: action.bound, + routeBackInApp: action.bound + }); } - @observable server_time = ServerTime.get() || toMoment(); // fallback: get current time from moment.js - @observable current_language = currentLanguage; - @observable allowed_languages = Object.keys(getAllowedLanguages()); - @observable has_error = false; + server_time = ServerTime.get() || toMoment(); // fallback: get current time from moment.js + current_language = currentLanguage; + allowed_languages = Object.keys(getAllowedLanguages()); + has_error = false; - @observable error = { + error = { type: 'info', message: '', }; - @observable network_status = {}; - @observable is_network_online = false; - @observable is_socket_opened = false; - @observable was_socket_opened = false; + network_status = {}; + is_network_online = false; + is_socket_opened = false; + was_socket_opened = false; - @observable services_error = {}; + services_error = {}; - @observable deposit_url = ''; - @observable withdraw_url = ''; + deposit_url = ''; + withdraw_url = ''; - @observable app_routing_history = []; - @observable app_router = { history: null }; - @observable app_id = undefined; - @observable platform = ''; - @observable selected_contract_type = ''; + app_routing_history = []; + app_router = { history: null }; + app_id = undefined; + platform = ''; + selected_contract_type = ''; - @action.bound setSelectedContractType(contract_type) { this.selected_contract_type = contract_type; } - @action.bound init() { this.setPlatform(); } - @action.bound checkAppId() { if (this.app_id && this.app_id !== getAppId()) { BinarySocket.closeAndOpenNewConnection(); @@ -55,14 +91,12 @@ export default class CommonStore extends BaseStore { this.app_id = getAppId(); } - @action.bound changeCurrentLanguage(new_language) { if (this.current_language !== new_language) { this.current_language = new_language; } } - @action.bound setPlatform() { const search = window.location.search; if (search) { @@ -71,12 +105,10 @@ export default class CommonStore extends BaseStore { } } - @computed get is_from_derivgo() { return platforms[this.platform]?.platform_name === platforms.derivgo.platform_name; } - @action.bound setInitialRouteHistoryItem(location) { if (window.location.href.indexOf('?ext_platform_url=') !== -1) { const ext_url = decodeURI(new URL(window.location.href).searchParams.get('ext_platform_url')); @@ -97,12 +129,10 @@ export default class CommonStore extends BaseStore { } } - @action.bound setServerTime(server_time) { this.server_time = server_time; } - @action.bound setIsSocketOpened(is_socket_opened) { // note that it's not for account switch that we're doing this, // but rather to reset account related stores like portfolio and contract-trade @@ -116,7 +146,6 @@ export default class CommonStore extends BaseStore { } } - @action.bound setNetworkStatus(status, is_online) { if (this.network_status.class) { this.network_status.class = status.class; @@ -135,7 +164,6 @@ export default class CommonStore extends BaseStore { } } - @action.bound setError(has_error, error) { this.has_error = has_error; this.error = { @@ -153,16 +181,17 @@ export default class CommonStore extends BaseStore { }; } - @action.bound - showError({ - message, - header, - redirect_label, - redirectOnClick, - should_show_refresh, - redirect_to, - should_clear_error_on_click, - }) { + showError( + { + message, + header, + redirect_label, + redirectOnClick, + should_show_refresh, + redirect_to, + should_clear_error_on_click, + } + ) { this.setError(true, { header, message, @@ -175,17 +204,14 @@ export default class CommonStore extends BaseStore { }); } - @action.bound setDepositURL(deposit_url) { this.deposit_url = deposit_url; } - @action.bound setWithdrawURL(withdraw_url) { this.withdraw_url = withdraw_url; } - @action.bound setServicesError(error) { this.services_error = error; if (isMobile()) { @@ -198,17 +224,14 @@ export default class CommonStore extends BaseStore { } } - @action.bound setAppRouterHistory(history) { this.app_router.history = history; } - @action.bound routeTo(pathname) { if (this.app_router.history) this.app_router.history.push(pathname); } - @action.bound addRouteHistoryItem(router_action) { const check_existing = this.app_routing_history.findIndex( i => i.pathname === router_action.pathname && i.action === 'PUSH' @@ -219,7 +242,6 @@ export default class CommonStore extends BaseStore { this.app_routing_history.unshift(router_action); } - @action.bound routeBackInApp(history, additional_platform_path = []) { let route_to_item_idx = -1; const route_to_item = this.app_routing_history.find((history_item, idx) => { diff --git a/packages/core/src/Stores/gtm-store.js b/packages/core/src/Stores/gtm-store.js index 9225344bc200..f5bd9bb22008 100644 --- a/packages/core/src/Stores/gtm-store.js +++ b/packages/core/src/Stores/gtm-store.js @@ -1,5 +1,5 @@ import * as Cookies from 'js-cookie'; -import { action, computed } from 'mobx'; +import { action, computed, makeObservable } from 'mobx'; import { getAppId, toMoment, epochToMoment, CFD_PLATFORMS } from '@deriv/shared'; import { getLanguage } from '@deriv/translations'; import BinarySocket from '_common/base/socket_base'; @@ -12,10 +12,19 @@ export default class GTMStore extends BaseStore { constructor(root_store) { super({ root_store }); + makeObservable(this, { + visitorId: computed, + common_variables: computed, + accountSwitcherListener: action.bound, + pushDataLayer: action.bound, + pushTransactionData: action.bound, + eventHandler: action.bound, + setLoginFlag: action.bound + }); + this.onSwitchAccount(this.accountSwitcherListener); } - @computed get visitorId() { return this.root_store.client.loginid; } @@ -25,7 +34,6 @@ export default class GTMStore extends BaseStore { * * @returns {object} */ - @computed get common_variables() { const platform = () => { const url = new URL(window.location.href); @@ -61,7 +69,6 @@ export default class GTMStore extends BaseStore { }; } - @action.bound accountSwitcherListener() { return new Promise(resolve => resolve(this.pushDataLayer({ event: 'account switch' }))); } @@ -71,7 +78,6 @@ export default class GTMStore extends BaseStore { * * @param {object} data */ - @action.bound async pushDataLayer(data) { if (this.is_gtm_applicable) { BinarySocket.wait('authorize').then(() => { @@ -89,7 +95,6 @@ export default class GTMStore extends BaseStore { * @param {object} response * @param {object} extra_data */ - @action.bound pushTransactionData(response, extra_data = {}) { if (!this.is_gtm_applicable || this.root_store.client.is_virtual) return; if (!response.transaction || !response.transaction.action) return; @@ -130,7 +135,6 @@ export default class GTMStore extends BaseStore { } } - @action.bound eventHandler(get_settings) { if (!this.is_gtm_applicable) return; @@ -169,7 +173,6 @@ export default class GTMStore extends BaseStore { this.pushDataLayer(data); } - @action.bound setLoginFlag(event_name) { if (this.is_gtm_applicable && event_name) { localStorage.setItem('GTM_login', event_name); diff --git a/packages/core/src/Stores/menu-store.js b/packages/core/src/Stores/menu-store.js index a465e5c709c2..c689f82baf6f 100644 --- a/packages/core/src/Stores/menu-store.js +++ b/packages/core/src/Stores/menu-store.js @@ -1,12 +1,12 @@ import React from 'react'; -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { Icon } from '@deriv/components'; import { localize } from '@deriv/translations'; import { routes } from '@deriv/shared'; import BaseStore from './base-store'; export default class MenuStore extends BaseStore { - @observable extensions = [ + extensions = [ { id: 'dt_reports_tab', icon: , @@ -16,7 +16,17 @@ export default class MenuStore extends BaseStore { }, ]; - @action.bound + constructor() { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super(); + + makeObservable(this, { + extensions: observable, + attach: action.bound, + detach: action.bound + }); + } + attach(menu) { if (!(menu instanceof Object)) { throw new TypeError('Menu is not an instance of object.'); @@ -30,7 +40,6 @@ export default class MenuStore extends BaseStore { } } - @action.bound detach(menu) { this.extensions = this.extensions.filter(extension => extension.id !== menu); } diff --git a/packages/core/src/Stores/notification-store.js b/packages/core/src/Stores/notification-store.js index c646032c16fa..18f1635613d4 100644 --- a/packages/core/src/Stores/notification-store.js +++ b/packages/core/src/Stores/notification-store.js @@ -16,7 +16,7 @@ import { } from '@deriv/shared'; import { localize, Localize } from '@deriv/translations'; import { BinaryLink } from 'App/Components/Routes'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import React from 'react'; import { WS } from 'Services'; import { sortNotifications, sortNotificationsMobile } from '../App/Components/Elements/NotificationMessage/constants'; @@ -29,16 +29,48 @@ import { } from './Helpers/client-notifications'; export default class NotificationStore extends BaseStore { - @observable is_notifications_visible = false; - @observable notifications = []; - @observable notification_messages = []; - @observable marked_notifications = []; - @observable push_notifications = []; - @observable client_notifications = {}; - @observable should_show_popups = true; + is_notifications_visible = false; + notifications = []; + notification_messages = []; + marked_notifications = []; + push_notifications = []; + client_notifications = {}; + should_show_popups = true; constructor(root_store) { super({ root_store }); + + makeObservable(this, { + is_notifications_visible: observable, + notifications: observable, + notification_messages: observable, + marked_notifications: observable, + push_notifications: observable, + client_notifications: observable, + should_show_popups: observable, + custom_notifications: computed, + filtered_notifications: computed, + addNotificationBar: action.bound, + addNotificationMessage: action.bound, + addNotificationMessageByKey: action.bound, + addVerificationNotifications: action.bound, + filterNotificationMessages: action.bound, + handleClientNotifications: action.bound, + markNotificationMessage: action.bound, + refreshNotifications: action.bound, + removeAllNotificationMessages: action.bound, + removeNotifications: action.bound, + removeNotificationByKey: action.bound, + removeNotificationMessage: action.bound, + removeNotificationMessageByKey: action.bound, + resetVirtualBalanceNotification: action.bound, + setClientNotifications: action.bound, + setShouldShowPopups: action.bound, + toggleNotificationsModal: action.bound, + unmarkNotificationMessage: action.bound, + updateNotifications: action.bound + }); + reaction( () => root_store.common.app_routing_history.map(i => i.pathname), () => { @@ -69,7 +101,6 @@ export default class NotificationStore extends BaseStore { ); } - @computed get custom_notifications() { const { has_malta_account, can_have_mlt_account, is_uk } = this.root_store.client; const notification_content = { @@ -95,18 +126,15 @@ export default class NotificationStore extends BaseStore { return notification_content; } - @computed get filtered_notifications() { return this.notifications.filter(message => !['news', 'promotions'].includes(message.type)); } - @action.bound addNotificationBar(message) { this.push_notifications.push(message); this.push_notifications = unique(this.push_notifications, 'msg_type'); } - @action.bound addNotificationMessage(notification) { if (!notification) return; if (!this.notification_messages.find(item => item.key === notification.key)) { @@ -134,19 +162,16 @@ export default class NotificationStore extends BaseStore { } } - @action.bound addNotificationMessageByKey(key) { if (key) this.addNotificationMessage(this.client_notifications[key]); } - @action.bound addVerificationNotifications(identity, document) { if (identity.status === 'expired') this.addNotificationMessage(this.client_notifications.poi_expired); if (document.status === 'expired') this.addNotificationMessage(this.client_notifications.poa_expired); } - @action.bound filterNotificationMessages() { if (LocalStore.get('active_loginid') !== 'null') this.resetVirtualBalanceNotification(LocalStore.get('active_loginid')); @@ -166,7 +191,6 @@ export default class NotificationStore extends BaseStore { }); } - @action.bound handleClientNotifications() { const { account_settings, @@ -371,12 +395,10 @@ export default class NotificationStore extends BaseStore { } } - @action.bound markNotificationMessage({ key }) { this.marked_notifications.push(key); } - @action.bound refreshNotifications() { this.removeNotifications(true); this.removeAllNotificationMessages(); @@ -384,26 +406,22 @@ export default class NotificationStore extends BaseStore { this.handleClientNotifications(); } - @action.bound removeAllNotificationMessages(should_close_persistent) { this.notification_messages = should_close_persistent ? [] : [...this.notification_messages.filter(notifs => notifs.is_persistent)]; } - @action.bound removeNotifications(should_close_persistent) { this.notifications = should_close_persistent ? [] : [...this.notifications.filter(notifs => notifs.is_persistent)]; } - @action.bound removeNotificationByKey({ key }) { this.notifications = this.notifications.filter(n => n.key !== key); } - @action.bound removeNotificationMessage({ key, should_show_again } = {}) { if (!key) return; this.notification_messages = this.notification_messages.filter(n => n.key !== key); @@ -430,12 +448,10 @@ export default class NotificationStore extends BaseStore { } } - @action.bound removeNotificationMessageByKey({ key }) { this.notification_messages = this.notification_messages.filter(n => n.key !== key); } - @action.bound resetVirtualBalanceNotification(loginid) { const { accounts, is_logged_in } = this.root_store.client; if (!is_logged_in) return; @@ -462,7 +478,6 @@ export default class NotificationStore extends BaseStore { } } - @action.bound setClientNotifications(client_data = {}) { const { ui } = this.root_store; const mx_mlt_custom_header = this.custom_notifications.mx_mlt_notification.header(); @@ -1001,22 +1016,18 @@ export default class NotificationStore extends BaseStore { this.client_notifications = notifications; } - @action.bound setShouldShowPopups(should_show_popups) { this.should_show_popups = should_show_popups; } - @action.bound toggleNotificationsModal() { this.is_notifications_visible = !this.is_notifications_visible; } - @action.bound unmarkNotificationMessage({ key }) { this.marked_notifications = this.marked_notifications.filter(item => key !== item); } - @action.bound updateNotifications(notifications_array) { this.notifications = notifications_array.filter(message => !excluded_notifications.includes(message.key)); } diff --git a/packages/core/src/Stores/pushwoosh-store.js b/packages/core/src/Stores/pushwoosh-store.js index 0efb870c8864..dd01e7a2168f 100644 --- a/packages/core/src/Stores/pushwoosh-store.js +++ b/packages/core/src/Stores/pushwoosh-store.js @@ -1,4 +1,4 @@ -import { action, when } from 'mobx'; +import { action, when, makeObservable } from 'mobx'; import { Pushwoosh } from 'web-push-notifications'; import { getAppId, getBrandWebsiteName, urlForCurrentDomain } from '@deriv/shared'; import { getLanguage } from '@deriv/translations'; @@ -12,12 +12,16 @@ export default class PushwooshStore extends BaseStore { constructor(root_store) { super({ root_store }); + + makeObservable(this, { + init: action.bound, + sendTags: action.bound + }); } /** * Pushes initialize event to pushwoosh */ - @action.bound init = async () => { if (!this.is_applicable && this.has_initialized) return; await when(() => this.root_store.common.is_network_online); @@ -55,7 +59,6 @@ export default class PushwooshStore extends BaseStore { /** * Set tags containing client to pushwoosh */ - @action.bound sendTags = api => { api.getTags() .then(result => { diff --git a/packages/core/src/Stores/rudderstack-store.js b/packages/core/src/Stores/rudderstack-store.js index ad828313cd37..4b1bdec1e6bc 100644 --- a/packages/core/src/Stores/rudderstack-store.js +++ b/packages/core/src/Stores/rudderstack-store.js @@ -1,4 +1,4 @@ -import { action } from 'mobx'; +import { action, makeObservable } from 'mobx'; import { getAppId } from '@deriv/shared'; import { getLanguage } from '@deriv/translations'; import BinarySocket from '_common/base/socket_base'; @@ -12,9 +12,15 @@ export default class RudderStackStore extends BaseStore { constructor(root_store) { super({ root_store }); + + makeObservable(this, { + identifyEvent: action.bound, + pageView: action.bound, + reset: action.bound, + track: action.bound + }); } - @action.bound identifyEvent = async data => new Promise(resolve => { if (this.is_applicable && !this.has_identified) { @@ -40,7 +46,6 @@ export default class RudderStackStore extends BaseStore { /** * Pushes page view track event to rudderstack */ - @action.bound pageView() { const current_page = window.location.hostname + window.location.pathname; @@ -58,7 +63,6 @@ export default class RudderStackStore extends BaseStore { /** * Pushes reset event to rudderstack */ - @action.bound reset() { if (this.is_applicable) { window.rudderanalytics.reset(); @@ -69,7 +73,6 @@ export default class RudderStackStore extends BaseStore { /** * Pushes track event to rudderstack */ - @action.bound track(event_name, options) { if (this.is_applicable && this.has_identified) { window.rudderanalytics.track(event_name, options); diff --git a/packages/core/src/Stores/ui-store.js b/packages/core/src/Stores/ui-store.js index 16110ec1e3f3..d7fbc1bad7ec 100644 --- a/packages/core/src/Stores/ui-store.js +++ b/packages/core/src/Stores/ui-store.js @@ -1,109 +1,109 @@ import { getPlatformInformation, isMobile, isTouchDevice, LocalStore, platform_name, routes } from '@deriv/shared'; import { MAX_MOBILE_WIDTH, MAX_TABLET_WIDTH } from 'Constants/ui'; -import { action, autorun, computed, observable } from 'mobx'; +import { action, autorun, computed, observable, makeObservable } from 'mobx'; import BaseStore from './base-store'; const store_name = 'ui_store'; export default class UIStore extends BaseStore { - @observable is_account_settings_visible = false; - @observable is_positions_drawer_on = false; - @observable is_reports_visible = false; - @observable reports_route_tab_index = 0; - @observable is_cashier_visible = false; - @observable is_history_tab_active = false; + is_account_settings_visible = false; + is_positions_drawer_on = false; + is_reports_visible = false; + reports_route_tab_index = 0; + is_cashier_visible = false; + is_history_tab_active = false; // TODO: [cleanup ui-store] // Take profit, Stop loss & Deal cancellation checkbox - @observable should_show_cancellation_warning = true; + should_show_cancellation_warning = true; // Extensions - @observable footer_extensions = []; - @observable header_extension = undefined; - @observable settings_extension = undefined; - @observable notification_messages_ui = undefined; + footer_extensions = []; + header_extension = undefined; + settings_extension = undefined; + notification_messages_ui = undefined; - @observable is_dark_mode_on = window?.matchMedia?.('(prefers-color-scheme: dark)').matches && isMobile(); - @observable is_settings_modal_on = false; - @observable is_accounts_switcher_on = false; - @observable account_switcher_disabled_message = ''; + is_dark_mode_on = window?.matchMedia?.('(prefers-color-scheme: dark)').matches && isMobile(); + is_settings_modal_on = false; + is_accounts_switcher_on = false; + account_switcher_disabled_message = ''; - @observable has_only_forward_starting_contracts = false; + has_only_forward_starting_contracts = false; // Purchase Controls // @observable is_purchase_confirm_on = false; - @observable is_services_error_visible = false; - @observable is_unsupported_contract_modal_visible = false; - @observable is_account_signup_modal_visible = false; - @observable is_set_residence_modal_visible = false; - @observable is_reset_password_modal_visible = false; - @observable is_reset_email_modal_visible = false; - @observable is_update_email_modal_visible = false; - @observable is_reset_trading_password_modal_visible = false; + is_services_error_visible = false; + is_unsupported_contract_modal_visible = false; + is_account_signup_modal_visible = false; + is_set_residence_modal_visible = false; + is_reset_password_modal_visible = false; + is_reset_email_modal_visible = false; + is_update_email_modal_visible = false; + is_reset_trading_password_modal_visible = false; // @observable is_purchase_lock_on = false; // SmartCharts Controls // TODO: enable asset information // @observable is_chart_asset_info_visible = true; - @observable is_chart_countdown_visible = false; - @observable is_chart_layout_default = true; + is_chart_countdown_visible = false; + is_chart_layout_default = true; // PWA event and config - @observable pwa_prompt_event = null; - - @observable screen_width = window.innerWidth; - @observable screen_height = window.innerHeight; - @observable is_onscreen_keyboard_active = false; - - @observable is_advanced_duration = false; - @observable advanced_duration_unit = 't'; - @observable advanced_expiry_type = 'duration'; - @observable simple_duration_unit = 't'; - @observable duration_t = 5; - @observable duration_s = 15; - @observable duration_m = 3; - @observable duration_h = 1; - @observable duration_d = 1; + pwa_prompt_event = null; + + screen_width = window.innerWidth; + screen_height = window.innerHeight; + is_onscreen_keyboard_active = false; + + is_advanced_duration = false; + advanced_duration_unit = 't'; + advanced_expiry_type = 'duration'; + simple_duration_unit = 't'; + duration_t = 5; + duration_s = 15; + duration_m = 3; + duration_h = 1; + duration_d = 1; // purchase button states - @observable purchase_states = [false, false]; + purchase_states = [false, false]; // app states for modal - @observable is_app_disabled = false; - @observable is_route_modal_on = false; + is_app_disabled = false; + is_route_modal_on = false; // real account signup - @observable is_real_acc_signup_on = false; - @observable real_account_signup_target = undefined; - @observable deposit_real_account_signup_target = undefined; - @observable has_real_account_signup_ended = false; + is_real_acc_signup_on = false; + real_account_signup_target = undefined; + deposit_real_account_signup_target = undefined; + has_real_account_signup_ended = false; // Welcome modal - @observable is_welcome_modal_visible = false; + is_welcome_modal_visible = false; // Remove MX & MLT - @observable is_close_mx_mlt_account_modal_visible = false; + is_close_mx_mlt_account_modal_visible = false; // Remove MF account modal - @observable is_close_uk_account_modal_visible = false; + is_close_uk_account_modal_visible = false; // set currency modal - @observable is_set_currency_modal_visible = false; + is_set_currency_modal_visible = false; // position states - @observable show_positions_toggle = true; + show_positions_toggle = true; - @observable modal_index = 0; + modal_index = 0; // Mt5 topup - @observable is_top_up_virtual_open = false; - @observable is_top_up_virtual_in_progress = false; - @observable is_top_up_virtual_success = false; + is_top_up_virtual_open = false; + is_top_up_virtual_in_progress = false; + is_top_up_virtual_success = false; // MT5 create real STP from demo, show only real accounts from switcher - @observable should_show_real_accounts_list = false; + should_show_real_accounts_list = false; // Real account signup - @observable real_account_signup = { + real_account_signup = { active_modal_index: -1, previous_currency: '', current_currency: '', @@ -112,35 +112,35 @@ export default class UIStore extends BaseStore { }; // UI Focus retention - @observable current_focus = null; + current_focus = null; // Mobile mobile_toast_timeout = 3500; - @observable.shallow toasts = []; + toasts = []; - @observable is_cfd_page = false; - @observable is_nativepicker_visible = false; - @observable is_landscape = false; + is_cfd_page = false; + is_nativepicker_visible = false; + is_landscape = false; - @observable prompt_when = false; - @observable promptFn = () => {}; + prompt_when = false; + promptFn = () => {}; // MT5 account needed modal - @observable is_account_needed_modal_on = false; - @observable account_needed_modal_props = { + is_account_needed_modal_on = false; + account_needed_modal_props = { target: '', target_label: '', target_dmt5_label: '', }; - @observable manage_real_account_tab_index = 0; + manage_real_account_tab_index = 0; // onboarding - @observable should_show_multipliers_onboarding = false; - @observable choose_crypto_currency_target = null; + should_show_multipliers_onboarding = false; + choose_crypto_currency_target = null; // add crypto accounts - @observable should_show_cancel = false; + should_show_cancel = false; getDurationFromUnit = unit => this[`duration_${unit}`]; @@ -169,6 +169,151 @@ export default class UIStore extends BaseStore { super({ root_store, local_storage_properties, store_name }); + makeObservable(this, { + is_account_settings_visible: observable, + is_positions_drawer_on: observable, + is_reports_visible: observable, + reports_route_tab_index: observable, + is_cashier_visible: observable, + is_history_tab_active: observable, + should_show_cancellation_warning: observable, + footer_extensions: observable, + header_extension: observable, + settings_extension: observable, + notification_messages_ui: observable, + is_dark_mode_on: observable, + is_settings_modal_on: observable, + is_accounts_switcher_on: observable, + account_switcher_disabled_message: observable, + has_only_forward_starting_contracts: observable, + is_services_error_visible: observable, + is_unsupported_contract_modal_visible: observable, + is_account_signup_modal_visible: observable, + is_set_residence_modal_visible: observable, + is_reset_password_modal_visible: observable, + is_reset_email_modal_visible: observable, + is_update_email_modal_visible: observable, + is_reset_trading_password_modal_visible: observable, + is_chart_countdown_visible: observable, + is_chart_layout_default: observable, + pwa_prompt_event: observable, + screen_width: observable, + screen_height: observable, + is_onscreen_keyboard_active: observable, + is_advanced_duration: observable, + advanced_duration_unit: observable, + advanced_expiry_type: observable, + simple_duration_unit: observable, + duration_t: observable, + duration_s: observable, + duration_m: observable, + duration_h: observable, + duration_d: observable, + purchase_states: observable, + is_app_disabled: observable, + is_route_modal_on: observable, + is_real_acc_signup_on: observable, + real_account_signup_target: observable, + deposit_real_account_signup_target: observable, + has_real_account_signup_ended: observable, + is_welcome_modal_visible: observable, + is_close_mx_mlt_account_modal_visible: observable, + is_close_uk_account_modal_visible: observable, + is_set_currency_modal_visible: observable, + show_positions_toggle: observable, + modal_index: observable, + is_top_up_virtual_open: observable, + is_top_up_virtual_in_progress: observable, + is_top_up_virtual_success: observable, + should_show_real_accounts_list: observable, + real_account_signup: observable, + current_focus: observable, + toasts: observable.shallow, + is_cfd_page: observable, + is_nativepicker_visible: observable, + is_landscape: observable, + prompt_when: observable, + promptFn: observable, + is_account_needed_modal_on: observable, + account_needed_modal_props: observable, + manage_real_account_tab_index: observable, + should_show_multipliers_onboarding: observable, + choose_crypto_currency_target: observable, + should_show_cancel: observable, + init: action.bound, + populateFooterExtensions: action.bound, + populateHeaderExtensions: action.bound, + populateSettingsExtensions: action.bound, + onChangeUiStore: action.bound, + handleResize: action.bound, + setPromptHandler: action.bound, + showCloseMxMltAccountPopup: action.bound, + showCloseUKAccountPopup: action.bound, + is_mobile: computed, + is_tablet: computed, + is_account_switcher_disabled: computed, + setRouteModal: action.bound, + disableRouteModal: action.bound, + disableApp: action.bound, + enableApp: action.bound, + toggleAccountsDialog: action.bound, + setAccountSwitcherDisabledMessage: action.bound, + setPurchaseState: action.bound, + resetPurchaseStates: action.bound, + setChartLayout: action.bound, + setChartCountdown: action.bound, + setDarkMode: action.bound, + toggleSetCurrencyModal: action.bound, + toggleCashier: action.bound, + setModalIndex: action.bound, + toggleSettingsModal: action.bound, + openPositionsDrawer: action.bound, + openRealAccountSignup: action.bound, + setShouldShowCancel: action.bound, + resetRealAccountSignupTarget: action.bound, + setManageRealAccountActiveTabIndex: action.bound, + closeRealAccountSignup: action.bound, + openAccountNeededModal: action.bound, + closeAccountNeededModal: action.bound, + togglePositionsDrawer: action.bound, + toggleAccountSettings: action.bound, + toggleReports: action.bound, + toggleServicesErrorModal: action.bound, + removePWAPromptEvent: action.bound, + setPWAPromptEvent: action.bound, + setHasOnlyForwardingContracts: action.bound, + toggleUnsupportedContractModal: action.bound, + toggleAccountSignupModal: action.bound, + toggleSetResidenceModal: action.bound, + toggleCancellationWarning: action.bound, + toggleHistoryTab: action.bound, + setTopUpInProgress: action.bound, + closeTopUpModal: action.bound, + openTopUpModal: action.bound, + closeSuccessTopUpModal: action.bound, + toggleResetPasswordModal: action.bound, + toggleResetEmailModal: action.bound, + toggleUpdateEmailModal: action.bound, + setResetTradingPasswordModalOpen: action.bound, + setRealAccountSignupParams: action.bound, + setRealAccountSignupEnd: action.bound, + resetRealAccountSignupParams: action.bound, + onOrientationChange: action.bound, + toggleOnScreenKeyboard: action.bound, + setCurrentFocus: action.bound, + addToast: action.bound, + removeToast: action.bound, + setIsNativepickerVisible: action.bound, + setReportsTabIndex: action.bound, + toggleWelcomeModal: action.bound, + notifyAppInstall: action.bound, + installWithDeferredPrompt: action.bound, + toggleShouldShowRealAccountsList: action.bound, + toggleShouldShowMultipliersOnboarding: action.bound, + shouldNavigateAfterChooseCrypto: action.bound, + continueRouteAfterChooseCrypto: action.bound, + }); + window.addEventListener('resize', this.handleResize); autorun(() => { this.changeTheme(); @@ -193,27 +338,22 @@ export default class UIStore extends BaseStore { } }; - @action.bound init(notification_messages) { this.notification_messages_ui = notification_messages; } - @action.bound populateFooterExtensions(footer_extensions) { this.footer_extensions = footer_extensions; } - @action.bound populateHeaderExtensions(component) { this.header_extension = component; } - @action.bound populateSettingsExtensions(menu_items) { this.settings_extension = menu_items; } - @action.bound onChangeUiStore({ name, value }) { if (!(name in this)) { throw new Error(`Invalid Argument: ${name}`); @@ -221,69 +361,56 @@ export default class UIStore extends BaseStore { this[name] = value; } - @action.bound handleResize() { this.screen_width = window.innerWidth; this.screen_height = window.innerHeight; } - @action.bound setPromptHandler(condition, cb = () => {}) { this.prompt_when = condition; this.promptFn = cb; } - @action.bound showCloseMxMltAccountPopup(is_open) { this.is_close_mx_mlt_account_modal_visible = is_open; } - @action.bound showCloseUKAccountPopup(is_open) { this.is_close_uk_account_modal_visible = is_open; } - @computed get is_mobile() { return this.screen_width <= MAX_MOBILE_WIDTH; } - @computed get is_tablet() { return this.screen_width <= MAX_TABLET_WIDTH; } - @computed get is_account_switcher_disabled() { return !!this.account_switcher_disabled_message; } - @action.bound setRouteModal() { this.is_route_modal_on = true; } - @action.bound disableRouteModal() { this.is_route_modal_on = false; } - @action.bound disableApp() { this.is_app_disabled = true; } - @action.bound enableApp() { this.is_app_disabled = false; } - @action.bound toggleAccountsDialog(status = !this.is_accounts_switcher_on) { this.is_accounts_switcher_on = status; } - @action.bound setAccountSwitcherDisabledMessage(message) { if (message) { this.is_accounts_switcher_on = false; @@ -293,7 +420,6 @@ export default class UIStore extends BaseStore { } } - @action.bound setPurchaseState(index) { this.purchase_states[index] = true; @@ -312,12 +438,10 @@ export default class UIStore extends BaseStore { }, 250); } - @action.bound resetPurchaseStates() { this.purchase_states = [false, false]; } - @action.bound setChartLayout(is_default) { this.is_chart_layout_default = is_default; } @@ -328,7 +452,6 @@ export default class UIStore extends BaseStore { // this.is_chart_asset_info_visible = is_visible; // } - @action.bound setChartCountdown(is_visible) { this.is_chart_countdown_visible = is_visible; } @@ -348,7 +471,6 @@ export default class UIStore extends BaseStore { // this.is_purchase_confirm_on = !this.is_purchase_confirm_on; // } - @action.bound setDarkMode(is_dark_mode_on) { if (this.is_dark_mode_on !== is_dark_mode_on) { this.is_dark_mode_on = is_dark_mode_on; @@ -359,56 +481,46 @@ export default class UIStore extends BaseStore { return this.is_dark_mode_on; } - @action.bound toggleSetCurrencyModal() { this.is_set_currency_modal_visible = !this.is_set_currency_modal_visible; } - @action.bound toggleCashier() { this.is_cashier_visible = !this.is_cashier_visible; } - @action.bound setModalIndex(index = 0) { this.modal_index = index; } - @action.bound toggleSettingsModal() { this.is_settings_modal_on = !this.is_settings_modal_on; } - @action.bound openPositionsDrawer() { // show and hide Positions Drawer this.is_positions_drawer_on = true; } - @action.bound openRealAccountSignup(target = this.root_store.client.upgradeable_landing_companies?.[0]) { this.is_real_acc_signup_on = true; this.real_account_signup_target = target; this.is_accounts_switcher_on = false; } - @action.bound setShouldShowCancel(value) { this.should_show_cancel = value; } - @action.bound resetRealAccountSignupTarget() { this.deposit_real_account_signup_target = this.real_account_signup_target; this.real_account_signup_target = ''; } - @action.bound setManageRealAccountActiveTabIndex(index) { this.manage_real_account_tab_index = index; } - @action.bound closeRealAccountSignup() { this.is_real_acc_signup_on = false; this.resetRealAccountSignupTarget(); @@ -418,7 +530,6 @@ export default class UIStore extends BaseStore { }, 300); } - @action.bound openAccountNeededModal(target, target_label, target_dmt5_label) { this.is_account_needed_modal_on = true; this.account_needed_modal_props = { @@ -428,7 +539,6 @@ export default class UIStore extends BaseStore { }; } - @action.bound closeAccountNeededModal() { this.is_account_needed_modal_on = false; this.account_needed_modal_props = { @@ -438,108 +548,87 @@ export default class UIStore extends BaseStore { }; } - @action.bound togglePositionsDrawer() { // toggle Positions Drawer this.is_positions_drawer_on = !this.is_positions_drawer_on; } - @action.bound toggleAccountSettings(is_visible) { this.is_account_settings_visible = is_visible; } - @action.bound toggleReports(is_visible) { this.is_reports_visible = is_visible; } - @action.bound toggleServicesErrorModal(is_visible) { this.is_services_error_visible = is_visible; } - @action.bound removePWAPromptEvent() { this.pwa_prompt_event = null; } - @action.bound setPWAPromptEvent(e) { this.pwa_prompt_event = e; } - @action.bound setHasOnlyForwardingContracts(has_only_forward_starting_contracts) { this.has_only_forward_starting_contracts = has_only_forward_starting_contracts; } - @action.bound toggleUnsupportedContractModal(state_change = !this.is_unsupported_contract_modal_visible) { this.is_unsupported_contract_modal_visible = state_change; } - @action.bound toggleAccountSignupModal(state_change = !this.is_account_signup_modal_visible) { this.is_account_signup_modal_visible = state_change; } - @action.bound toggleSetResidenceModal(state_change = !this.is_set_residence_modal_visible) { this.is_set_residence_modal_visible = state_change; } - @action.bound toggleCancellationWarning(state_change = !this.should_show_cancellation_warning) { this.should_show_cancellation_warning = state_change; } - @action.bound toggleHistoryTab(state_change = !this.is_history_tab_active) { this.is_history_tab_active = state_change; } - @action.bound setTopUpInProgress(bool) { this.is_top_up_virtual_in_progress = bool; } - @action.bound closeTopUpModal() { this.is_top_up_virtual_open = false; } - @action.bound openTopUpModal() { this.is_top_up_virtual_open = true; } - @action.bound closeSuccessTopUpModal() { this.is_top_up_virtual_success = false; } - @action.bound toggleResetPasswordModal(state_change = !this.is_reset_password_modal_visible) { this.is_reset_password_modal_visible = state_change; } - @action.bound toggleResetEmailModal(state_change = !this.is_reset_email_modal_visible) { this.is_reset_email_modal_visible = state_change; } - @action.bound toggleUpdateEmailModal(state_change = !this.is_update_email_modal_visible) { this.is_update_email_modal_visible = state_change; } - @action.bound setResetTradingPasswordModalOpen(is_reset_trading_password_modal_visible) { this.is_reset_trading_password_modal_visible = is_reset_trading_password_modal_visible; } - @action.bound setRealAccountSignupParams(params) { this.real_account_signup = { ...this.real_account_signup, @@ -547,12 +636,10 @@ export default class UIStore extends BaseStore { }; } - @action.bound setRealAccountSignupEnd(has_ended) { this.has_real_account_signup_ended = has_ended; } - @action.bound resetRealAccountSignupParams() { this.real_account_signup = { active_modal_index: -1, @@ -563,23 +650,19 @@ export default class UIStore extends BaseStore { }; } - @action.bound onOrientationChange({ is_landscape_orientation }) { this.is_landscape = is_landscape_orientation; } - @action.bound toggleOnScreenKeyboard() { this.is_onscreen_keyboard_active = this.current_focus !== null && this.is_mobile && isTouchDevice(); } - @action.bound setCurrentFocus(value) { this.current_focus = value; this.toggleOnScreenKeyboard(); } - @action.bound addToast(toast_config) { toast_config.key = toast_config.key ?? toast_config.content; const toast_index = this.toasts.findIndex(t => t.key === toast_config.key); @@ -595,7 +678,6 @@ export default class UIStore extends BaseStore { } } - @action.bound removeToast(key) { const index = this.toasts.findIndex(t => t.key === key); if (index > -1) { @@ -603,17 +685,14 @@ export default class UIStore extends BaseStore { } } - @action.bound setIsNativepickerVisible(is_nativepicker_visible) { this.is_nativepicker_visible = is_nativepicker_visible; } - @action.bound setReportsTabIndex(tab_index = 0) { this.reports_route_tab_index = tab_index; } - @action.bound toggleWelcomeModal({ is_visible = !this.is_welcome_modal_visible, should_persist = false }) { if (LocalStore.get('has_viewed_welcome_screen') && !should_persist) return; this.is_welcome_modal_visible = is_visible; @@ -623,7 +702,6 @@ export default class UIStore extends BaseStore { } } - @action.bound notifyAppInstall(prompt) { this.deferred_prompt = prompt; setTimeout(() => { @@ -631,7 +709,6 @@ export default class UIStore extends BaseStore { }, 10000); } - @action.bound async installWithDeferredPrompt() { this.deferred_prompt.prompt(); const choice = await this.deferred_prompt.userChoice; @@ -645,22 +722,18 @@ export default class UIStore extends BaseStore { } } - @action.bound toggleShouldShowRealAccountsList(value) { this.should_show_real_accounts_list = value; } - @action.bound toggleShouldShowMultipliersOnboarding(value) { this.should_show_multipliers_onboarding = value; } - @action.bound shouldNavigateAfterChooseCrypto(next_location) { this.choose_crypto_currency_target = next_location; } - @action.bound continueRouteAfterChooseCrypto() { this.root_store.common.routeTo(this.choose_crypto_currency_target); diff --git a/packages/p2p/package.json b/packages/p2p/package.json index 2f2f30d61752..6780d7738a47 100644 --- a/packages/p2p/package.json +++ b/packages/p2p/package.json @@ -39,8 +39,8 @@ "formik": "^2.1.4", "i18next": "^20.3.2", "lodash.debounce": "^4.0.8", - "mobx": "^5.15.7", - "mobx-react-lite": "^2.2.2", + "mobx": "6.5.0", + "mobx-react-lite": "3.3.0", "prop-types": "^15.7.2", "react": "^16.14.0", "react-content-loader": "^4.3.2", diff --git a/packages/p2p/src/stores/advertiser-page-store.js b/packages/p2p/src/stores/advertiser-page-store.js index f44693826db0..5156814057bb 100644 --- a/packages/p2p/src/stores/advertiser-page-store.js +++ b/packages/p2p/src/stores/advertiser-page-store.js @@ -1,57 +1,101 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { buy_sell } from 'Constants/buy-sell'; import { getShortNickname } from 'Utils/string'; import { requestWS } from 'Utils/websocket'; import BaseStore from 'Stores/base_store'; export default class AdvertiserPageStore extends BaseStore { - @observable active_index = 0; - @observable ad = null; - @observable advertiser_first_name = ''; - @observable advertiser_last_name = ''; - @observable advertiser_info = {}; - @observable adverts = []; - @observable counterparty_type = buy_sell.BUY; - @observable api_error_message = ''; - @observable form_error_message = ''; - @observable has_more_adverts_to_load = false; - @observable is_loading = true; - @observable is_loading_adverts = true; - @observable is_submit_disabled = true; - @observable show_ad_popup = false; - @observable submitForm = () => {}; - - @computed + active_index = 0; + ad = null; + advertiser_first_name = ''; + advertiser_last_name = ''; + advertiser_info = {}; + adverts = []; + counterparty_type = buy_sell.BUY; + api_error_message = ''; + form_error_message = ''; + has_more_adverts_to_load = false; + is_loading = true; + is_loading_adverts = true; + is_submit_disabled = true; + show_ad_popup = false; + submitForm = () => {}; + + constructor() { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super(); + + makeObservable(this, { + active_index: observable, + ad: observable, + advertiser_first_name: observable, + advertiser_last_name: observable, + advertiser_info: observable, + adverts: observable, + counterparty_type: observable, + api_error_message: observable, + form_error_message: observable, + has_more_adverts_to_load: observable, + is_loading: observable, + is_loading_adverts: observable, + is_submit_disabled: observable, + show_ad_popup: observable, + submitForm: observable, + account_currency: computed, + advert: computed, + advertiser_details: computed, + advertiser_details_id: computed, + advertiser_details_name: computed, + advertiser_full_name: computed, + short_name: computed, + getAdvertiserInfo: action.bound, + handleTabItemClick: action.bound, + onCancelClick: action.bound, + onConfirmClick: action.bound, + onMount: action.bound, + setActiveIndex: action.bound, + setAd: action.bound, + setAdvertiserFirstName: action.bound, + setAdvertiserLastName: action.bound, + setAdvertiserInfo: action.bound, + setAdverts: action.bound, + setCounterpartyType: action.bound, + setErrorMessage: action.bound, + setFormErrorMessage: action.bound, + setHasMoreAdvertsToLoad: action.bound, + setIsLoading: action.bound, + setIsLoadingAdverts: action.bound, + setIsSubmitDisabled: action.bound, + setShowAdPopup: action.bound, + setSubmitForm: action.bound, + showAdPopup: action.bound, + }); + } + get account_currency() { return this.advert?.account_currency; } - @computed get advert() { return this.root_store.buy_sell_store.selected_ad_state; } - @computed get advertiser_details() { return this.advert?.advertiser_details || {}; } - @computed get advertiser_details_id() { return this.advert?.advertiser_details?.id; } - @computed get advertiser_details_name() { return this.advert?.advertiser_details?.name; } - @computed get advertiser_full_name() { return `${this.advertiser_first_name} ${this.advertiser_last_name}`; } - @computed get short_name() { return getShortNickname(this.advertiser_details_name); } @@ -82,7 +126,6 @@ export default class AdvertiserPageStore extends BaseStore { }); } - @action.bound getAdvertiserInfo() { this.setIsLoading(true); @@ -103,7 +146,6 @@ export default class AdvertiserPageStore extends BaseStore { }); } - @action.bound handleTabItemClick(idx) { this.setActiveIndex(idx); if (idx === 0) { @@ -113,18 +155,15 @@ export default class AdvertiserPageStore extends BaseStore { } } - @action.bound onCancelClick() { this.setShowAdPopup(false); } - @action.bound onConfirmClick(order_info) { const nav = { location: 'buy_sell' }; this.root_store.general_store.redirectTo('orders', { order_info, nav }); } - @action.bound onMount() { this.getAdvertiserInfo(); } @@ -134,82 +173,66 @@ export default class AdvertiserPageStore extends BaseStore { this.loadMoreAdvertiserAdverts({ startIndex: 0 }); } - @action.bound setActiveIndex(active_index) { this.active_index = active_index; } - @action.bound setAd(ad) { this.ad = ad; } - @action.bound setAdvertiserFirstName(advertiser_first_name) { this.advertiser_first_name = advertiser_first_name; } - @action.bound setAdvertiserLastName(advertiser_last_name) { this.advertiser_last_name = advertiser_last_name; } - @action.bound setAdvertiserInfo(advertiser_info) { this.advertiser_info = advertiser_info; } - @action.bound setAdverts(adverts) { this.adverts = adverts; } - @action.bound setCounterpartyType(counterparty_type) { this.counterparty_type = counterparty_type; } - @action.bound setErrorMessage(api_error_message) { this.api_error_message = api_error_message; } - @action.bound setFormErrorMessage(form_error_message) { this.form_error_message = form_error_message; } - @action.bound setHasMoreAdvertsToLoad(has_more_adverts_to_load) { this.has_more_adverts_to_load = has_more_adverts_to_load; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsLoadingAdverts(is_loading_adverts) { this.is_loading_adverts = is_loading_adverts; } - @action.bound setIsSubmitDisabled(is_submit_disabled) { this.is_submit_disabled = is_submit_disabled; } - @action.bound setShowAdPopup(show_ad_popup) { this.show_ad_popup = show_ad_popup; } - @action.bound setSubmitForm(submitFormFn) { this.submitForm = submitFormFn; } - @action.bound showAdPopup() { if (!this.root_store.general_store.is_advertiser) { this.root_store.buy_sell_store.showVerification(); diff --git a/packages/p2p/src/stores/buy-sell-store.js b/packages/p2p/src/stores/buy-sell-store.js index aac019721495..079c50a288a2 100644 --- a/packages/p2p/src/stores/buy-sell-store.js +++ b/packages/p2p/src/stores/buy-sell-store.js @@ -1,4 +1,4 @@ -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import { formatMoney, getDecimalPlaces, getRoundedNumber, isMobile } from '@deriv/shared'; import { localize } from 'Components/i18next'; import { buy_sell } from 'Constants/buy-sell'; @@ -8,35 +8,35 @@ import { countDecimalPlaces } from 'Utils/string'; import BaseStore from 'Stores/base_store'; export default class BuySellStore extends BaseStore { - @observable api_error_message = ''; - @observable contact_info = ''; - @observable error_message = ''; - @observable form_error_code = ''; - @observable has_more_items_to_load = false; - @observable has_payment_methods = false; - @observable is_filter_modal_loading = false; - @observable is_filter_modal_open = false; - @observable is_loading = true; - @observable is_sort_dropdown_open = false; - @observable is_submit_disabled = true; - @observable items = []; - @observable payment_info = ''; - @observable receive_amount = 0; - @observable search_results = []; - @observable search_term = ''; - @observable selected_ad_state = {}; - @observable selected_payment_method_value = []; - @observable selected_payment_method_text = []; - @observable selected_value = 'rate'; - @observable should_show_popup = false; - @observable should_show_verification = false; - @observable should_use_client_limits = false; - @observable show_advertiser_page = false; - @observable show_filter_payment_methods = false; - @observable sort_by = 'rate'; - @observable submitForm = () => {}; - @observable table_type = buy_sell.BUY; - @observable form_props = {}; + api_error_message = ''; + contact_info = ''; + error_message = ''; + form_error_code = ''; + has_more_items_to_load = false; + has_payment_methods = false; + is_filter_modal_loading = false; + is_filter_modal_open = false; + is_loading = true; + is_sort_dropdown_open = false; + is_submit_disabled = true; + items = []; + payment_info = ''; + receive_amount = 0; + search_results = []; + search_term = ''; + selected_ad_state = {}; + selected_payment_method_value = []; + selected_payment_method_text = []; + selected_value = 'rate'; + should_show_popup = false; + should_show_verification = false; + should_use_client_limits = false; + show_advertiser_page = false; + show_filter_payment_methods = false; + sort_by = 'rate'; + submitForm = () => {}; + table_type = buy_sell.BUY; + form_props = {}; initial_values = { amount: this.advert?.min_order_amount_limit, @@ -50,37 +50,121 @@ export default class BuySellStore extends BaseStore { { text: localize('Completion rate'), value: 'completion' }, ]; - @computed + constructor({ general_store, root_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ general_store, root_store }); + + makeObservable(this, { + api_error_message: observable, + contact_info: observable, + error_message: observable, + form_error_code: observable, + has_more_items_to_load: observable, + has_payment_methods: observable, + is_filter_modal_loading: observable, + is_filter_modal_open: observable, + is_loading: observable, + is_sort_dropdown_open: observable, + is_submit_disabled: observable, + items: observable, + payment_info: observable, + receive_amount: observable, + search_results: observable, + search_term: observable, + selected_ad_state: observable, + selected_payment_method_value: observable, + selected_payment_method_text: observable, + selected_value: observable, + should_show_popup: observable, + should_show_verification: observable, + should_use_client_limits: observable, + show_advertiser_page: observable, + show_filter_payment_methods: observable, + sort_by: observable, + submitForm: observable, + table_type: observable, + form_props: observable, + account_currency: computed, + advert: computed, + has_payment_info: computed, + is_buy: computed, + is_buy_advert: computed, + is_sell_advert: computed, + modal_title: computed, + rendered_items: computed, + should_filter_by_payment_method: computed, + getAdvertiserInfo: action.bound, + handleChange: action.bound, + handleSubmit: action.bound, + hideAdvertiserPage: action.bound, + hideVerification: action.bound, + loadMoreItems: action.bound, + onCancelClick: action.bound, + onChangeTableType: action.bound, + onClickApply: action.bound, + onClickReset: action.bound, + onConfirmClick: action.bound, + setApiErrorMessage: action.bound, + setContactInfo: action.bound, + setErrorMessage: action.bound, + setFormErrorCode: action.bound, + setFormProps: action.bound, + setHasMoreItemsToLoad: action.bound, + setHasPaymentMethods: action.bound, + setIsFilterModalLoading: action.bound, + setIsFilterModalOpen: action.bound, + setIsLoading: action.bound, + setIsSortDropdownOpen: action.bound, + setIsSubmitDisabled: action.bound, + setItems: action.bound, + setPaymentInfo: action.bound, + setInitialReceiveAmount: action.bound, + setReceiveAmount: action.bound, + setSearchResults: action.bound, + setSearchTerm: action.bound, + setSelectedAdState: action.bound, + setSelectedPaymentMethodValue: action.bound, + setSelectedPaymentMethodText: action.bound, + setSelectedValue: action.bound, + setShouldShowPopup: action.bound, + setShouldShowVerification: action.bound, + setShouldUseClientLimits: action.bound, + setShowAdvertiserPage: action.bound, + setShowFilterPaymentMethods: action.bound, + setSortBy: action.bound, + setTableType: action.bound, + setSelectedAdvert: action.bound, + setSubmitFormFn: action.bound, + showAdvertiserPage: action.bound, + showVerification: action.bound, + validatePopup: action.bound, + }); + } + get account_currency() { return this.advert?.account_currency; } - @computed get advert() { return this.form_props?.advert; } - @computed get has_payment_info() { return this.contact_info.length; } - @computed get is_buy() { return this.table_type === buy_sell.BUY; } - @computed get is_buy_advert() { return this.advert?.counterparty_type === buy_sell.BUY; } - @computed get is_sell_advert() { return this.advert?.counterparty_type === buy_sell.SELL; } - @computed get modal_title() { if (this.is_buy_advert) { return localize('Buy {{ account_currency }}', { account_currency: this.account_currency }); @@ -89,7 +173,6 @@ export default class BuySellStore extends BaseStore { return localize('Sell {{ account_currency }}', { account_currency: this.account_currency }); } - @computed get rendered_items() { if (isMobile()) { if (this.search_term) { @@ -113,13 +196,11 @@ export default class BuySellStore extends BaseStore { return this.items; } - @computed get should_filter_by_payment_method() { const { my_profile_store } = this.root_store; return my_profile_store.payment_methods_list_values !== this.selected_payment_method_value; } - @action.bound getAdvertiserInfo() { requestWS({ p2p_advertiser_info: 1, @@ -138,7 +219,6 @@ export default class BuySellStore extends BaseStore { }); } - @action.bound handleChange(e) { this.setIsLoading(true); this.setSelectedValue(e.target.value); @@ -148,7 +228,6 @@ export default class BuySellStore extends BaseStore { this.setIsSortDropdownOpen(false); } - @action.bound handleSubmit = async (isMountedFn, values, { setSubmitting }) => { if (isMountedFn()) { setSubmitting(true); @@ -185,17 +264,14 @@ export default class BuySellStore extends BaseStore { } }; - @action.bound hideAdvertiserPage() { this.setShowAdvertiserPage(false); } - @action.bound hideVerification() { this.setShouldShowVerification(false); } - @action.bound loadMoreItems({ startIndex }) { const { general_store } = this.root_store; const counterparty_type = this.is_buy ? buy_sell.BUY : buy_sell.SELL; @@ -269,17 +345,14 @@ export default class BuySellStore extends BaseStore { }); } - @action.bound onCancelClick() { this.setShouldShowPopup(false); } - @action.bound onChangeTableType(event) { this.setTableType(event.target.value); } - @action.bound onClickApply(payment_method_value, payment_method_text) { this.setSelectedPaymentMethodValue(payment_method_value); this.setSelectedPaymentMethodText(payment_method_text); @@ -289,12 +362,10 @@ export default class BuySellStore extends BaseStore { this.setIsFilterModalOpen(false); } - @action.bound onClickReset() { this.setShouldUseClientLimits(false); } - @action.bound onConfirmClick(order_info) { const { general_store, order_store } = this.root_store; @@ -317,77 +388,62 @@ export default class BuySellStore extends BaseStore { }; } - @action.bound setApiErrorMessage(api_error_message) { this.api_error_message = api_error_message; } - @action.bound setContactInfo(contact_info) { this.contact_info = contact_info; } - @action.bound setErrorMessage(error_message) { this.error_message = error_message; } - @action.bound setFormErrorCode(form_error_code) { this.form_error_code = form_error_code; } - @action.bound setFormProps(props) { this.form_props = props; } - @action.bound setHasMoreItemsToLoad(has_more_items_to_load) { this.has_more_items_to_load = has_more_items_to_load; } - @action.bound setHasPaymentMethods(has_payment_methods) { this.has_payment_methods = has_payment_methods; } - @action.bound setIsFilterModalLoading(is_filter_modal_loading) { this.is_filter_modal_loading = is_filter_modal_loading; } - @action.bound setIsFilterModalOpen(is_filter_modal_open) { this.is_filter_modal_open = is_filter_modal_open; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsSortDropdownOpen(is_sort_dropdown_open) { this.is_sort_dropdown_open = is_sort_dropdown_open; } - @action.bound setIsSubmitDisabled(is_submit_disabled) { this.is_submit_disabled = is_submit_disabled; } - @action.bound setItems(items) { this.items = items; } - @action.bound setPaymentInfo(payment_info) { this.payment_info = payment_info; } - @action.bound setInitialReceiveAmount() { this.receive_amount = getRoundedNumber( this.advert.min_order_amount_limit * this.advert.price, @@ -395,77 +451,62 @@ export default class BuySellStore extends BaseStore { ); } - @action.bound setReceiveAmount(receive_amount) { this.receive_amount = receive_amount; } - @action.bound setSearchResults(search_results) { this.search_results = search_results; } - @action.bound setSearchTerm(search_term) { this.search_term = search_term; } - @action.bound setSelectedAdState(selected_ad_state) { this.selected_ad_state = selected_ad_state; } - @action.bound setSelectedPaymentMethodValue(payment_method_value) { this.selected_payment_method_value = [...payment_method_value]; } - @action.bound setSelectedPaymentMethodText(payment_method_text) { this.selected_payment_method_text = [...payment_method_text]; } - @action.bound setSelectedValue(selected_value) { this.selected_value = selected_value; } - @action.bound setShouldShowPopup(should_show_popup) { this.should_show_popup = should_show_popup; } - @action.bound setShouldShowVerification(should_show_verification) { this.should_show_verification = should_show_verification; } - @action.bound setShouldUseClientLimits(should_use_client_limits) { this.should_use_client_limits = should_use_client_limits; } - @action.bound setShowAdvertiserPage(show_advertiser_page) { this.show_advertiser_page = show_advertiser_page; } - @action.bound setShowFilterPaymentMethods(show_filter_payment_methods) { this.show_filter_payment_methods = show_filter_payment_methods; } - @action.bound setSortBy(sort_by) { this.sort_by = sort_by; } - @action.bound setTableType(table_type) { this.table_type = table_type; } - @action.bound setSelectedAdvert(selected_advert) { if (!this.root_store.general_store.is_advertiser) { this.setShouldShowVerification(true); @@ -479,23 +520,19 @@ export default class BuySellStore extends BaseStore { } } - @action.bound setSubmitFormFn(submitFormFn) { this.submitForm = submitFormFn; } - @action.bound showAdvertiserPage(selected_advert) { this.setSelectedAdState(selected_advert); this.setShowAdvertiserPage(true); } - @action.bound showVerification() { this.setShouldShowVerification(true); } - @action.bound validatePopup(values) { const validations = { amount: [ diff --git a/packages/p2p/src/stores/general-store.js b/packages/p2p/src/stores/general-store.js index b05f48b53330..7daffcb4839a 100644 --- a/packages/p2p/src/stores/general-store.js +++ b/packages/p2p/src/stores/general-store.js @@ -1,5 +1,5 @@ import React from 'react'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import { isEmptyObject, isMobile, toMoment } from '@deriv/shared'; import BaseStore from 'Stores/base_store'; import { localize, Localize } from 'Components/i18next'; @@ -9,29 +9,29 @@ import { init as WebsocketInit, requestWS, subscribeWS } from 'Utils/websocket'; import { order_list } from '../constants/order-list'; export default class GeneralStore extends BaseStore { - @observable active_index = 0; - @observable active_notification_count = 0; - @observable advertiser_id = null; - @observable inactive_notification_count = 0; - @observable is_advertiser = false; - @observable is_blocked = false; - @observable is_listed = false; - @observable is_loading = false; - @observable is_p2p_blocked_for_pa = false; - @observable is_restricted = false; - @observable nickname = null; - @observable nickname_error = ''; - @observable notification_count = 0; - @observable order_table_type = order_list.ACTIVE; - @observable orders = []; - @observable order_timeout = 0; - @observable parameters = null; - @observable poi_status = null; - @observable.ref props = {}; - @observable should_show_real_name = false; - @observable should_show_popup = false; - @observable user_blocked_until = null; - @observable is_high_risk_fully_authed_without_fa = false; + active_index = 0; + active_notification_count = 0; + advertiser_id = null; + inactive_notification_count = 0; + is_advertiser = false; + is_blocked = false; + is_listed = false; + is_loading = false; + is_p2p_blocked_for_pa = false; + is_restricted = false; + nickname = null; + nickname_error = ''; + notification_count = 0; + order_table_type = order_list.ACTIVE; + orders = []; + order_timeout = 0; + parameters = null; + poi_status = null; + props = {}; + should_show_real_name = false; + should_show_popup = false; + user_blocked_until = null; + is_high_risk_fully_authed_without_fa = false; list_item_limit = isMobile() ? 10 : 50; path = { @@ -43,37 +43,102 @@ export default class GeneralStore extends BaseStore { ws_subscriptions = {}; service_token_timeout; - @computed + constructor({ general_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ general_store }); + + makeObservable(this, { + active_index: observable, + active_notification_count: observable, + advertiser_id: observable, + inactive_notification_count: observable, + is_advertiser: observable, + is_blocked: observable, + is_listed: observable, + is_loading: observable, + is_p2p_blocked_for_pa: observable, + is_restricted: observable, + nickname: observable, + nickname_error: observable, + notification_count: observable, + order_table_type: observable, + orders: observable, + order_timeout: observable, + parameters: observable, + poi_status: observable, + props: observable.ref, + should_show_real_name: observable, + should_show_popup: observable, + user_blocked_until: observable, + is_high_risk_fully_authed_without_fa: observable, + client: computed, + blocked_until_date_time: computed, + is_active_tab: computed, + is_barred: computed, + is_my_profile_tab_visible: computed, + should_show_dp2p_blocked: computed, + createAdvertiser: action.bound, + handleNotifications: action.bound, + handleTabClick: action.bound, + onMount: action.bound, + onUnmount: action.bound, + onNicknamePopupClose: action.bound, + redirectTo: action.bound, + setActiveIndex: action.bound, + setActiveNotificationCount: action.bound, + setAdvertiserId: action.bound, + setAppProps: action.bound, + setInactiveNotificationCount: action.bound, + setIsAdvertiser: action.bound, + setIsBlocked: action.bound, + setIsHighRiskFullyAuthedWithoutFa: action.bound, + setIsListed: action.bound, + setIsLoading: action.bound, + setIsP2pBlockedForPa: action.bound, + setIsRestricted: action.bound, + setNickname: action.bound, + setNicknameError: action.bound, + setNotificationCount: action.bound, + setOrderTableType: action.bound, + setOrderTimeOut: action.bound, + setP2PConfig: action.bound, + setP2pOrderList: action.bound, + setParameters: action.bound, + setPoiStatus: action.bound, + setShouldShowRealName: action.bound, + setShouldShowPopup: action.bound, + setUserBlockedUntil: action.bound, + setWebsocketInit: action.bound, + toggleNicknamePopup: action.bound, + updateAdvertiserInfo: action.bound, + updateP2pNotifications: action.bound, + }); + } + get client() { return this.props?.client || {}; } - @computed get blocked_until_date_time() { return getFormattedDateString(new Date(convertToMillis(this.user_blocked_until)), false, true); } - @computed get is_active_tab() { return this.order_table_type === order_list.ACTIVE; } - @computed get is_barred() { return !!this.user_blocked_until; } - @computed get is_my_profile_tab_visible() { return this.is_advertiser && !this.root_store.my_profile_store.should_hide_my_profile_tab; } - @computed get should_show_dp2p_blocked() { return this.is_blocked || this.is_high_risk_fully_authed_without_fa; } - @action.bound createAdvertiser(name) { requestWS({ p2p_advertiser_create: 1, @@ -89,7 +154,7 @@ export default class GeneralStore extends BaseStore { this.setIsAdvertiser(!!p2p_advertiser_create.is_approved); this.setNickname(p2p_advertiser_create.name); this.setNicknameError(undefined); - sendbird_store.handleP2pAdvertiserInfo(response); + sendbird_store?.handleP2pAdvertiserInfo(response); this.toggleNicknamePopup(); buy_sell_store.hideVerification(); } @@ -110,7 +175,6 @@ export default class GeneralStore extends BaseStore { return local_storage_settings; } - @action.bound handleNotifications(old_orders, new_orders) { const { order_store } = this.root_store; const { client, props } = this; @@ -160,13 +224,11 @@ export default class GeneralStore extends BaseStore { this.updateP2pNotifications(notifications); } - @action.bound handleTabClick(idx) { this.setActiveIndex(idx); this.setParameters(null); } - @action.bound onMount() { this.setIsLoading(true); this.setIsBlocked(false); @@ -236,7 +298,7 @@ export default class GeneralStore extends BaseStore { p2p_advertiser_info: 1, subscribe: 1, }, - [this.updateAdvertiserInfo, response => sendbird_store.handleP2pAdvertiserInfo(response)] + [this.updateAdvertiserInfo, response => sendbird_store?.handleP2pAdvertiserInfo(response)] ), order_list_subscription: subscribeWS( { @@ -255,7 +317,6 @@ export default class GeneralStore extends BaseStore { }); } - @action.bound onUnmount() { clearTimeout(this.service_token_timeout); clearTimeout(this.user_blocked_timeout); @@ -267,7 +328,6 @@ export default class GeneralStore extends BaseStore { } } - @action.bound onNicknamePopupClose() { this.setShouldShowPopup(false); } @@ -287,101 +347,82 @@ export default class GeneralStore extends BaseStore { } }; - @action.bound redirectTo(path_name, params = null) { this.setActiveIndex(this.path[path_name]); this.setParameters(params); } - @action.bound setActiveIndex(active_index) { this.active_index = active_index; } - @action.bound setActiveNotificationCount(active_notification_count) { this.active_notification_count = active_notification_count; } - @action.bound setAdvertiserId(advertiser_id) { this.advertiser_id = advertiser_id; } - @action.bound setAppProps(props) { this.props = props; } - @action.bound setInactiveNotificationCount(inactive_notification_count) { this.inactive_notification_count = inactive_notification_count; } - @action.bound setIsAdvertiser(is_advertiser) { this.is_advertiser = is_advertiser; } - @action.bound setIsBlocked(is_blocked) { this.is_blocked = is_blocked; } - @action.bound setIsHighRiskFullyAuthedWithoutFa(is_high_risk_fully_authed_without_fa) { this.is_high_risk_fully_authed_without_fa = is_high_risk_fully_authed_without_fa; } - @action.bound setIsListed(is_listed) { this.is_listed = is_listed; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsP2pBlockedForPa(is_p2p_blocked_for_pa) { this.is_p2p_blocked_for_pa = is_p2p_blocked_for_pa; } - @action.bound setIsRestricted(is_restricted) { this.is_restricted = is_restricted; } - @action.bound setNickname(nickname) { this.nickname = nickname; } - @action.bound setNicknameError(nickname_error) { this.nickname_error = nickname_error; } - @action.bound setNotificationCount(notification_count) { this.notification_count = notification_count; } - @action.bound setOrderTableType(order_table_type) { const { order_store } = this.root_store; - order_store.setIsLoading(true); + order_store?.setIsLoading(true); this.order_table_type = order_table_type; } - @action.bound setOrderTimeOut(time) { this.order_timeout = time; } - @action.bound setP2PConfig() { requestWS({ website_status: 1 }).then(response => { if (response && !response.error) { @@ -391,7 +432,6 @@ export default class GeneralStore extends BaseStore { }); } - @action.bound setP2pOrderList(order_response) { if (order_response.error) { this.ws_subscriptions.order_list_subscription.unsubscribe(); @@ -404,12 +444,12 @@ export default class GeneralStore extends BaseStore { if (p2p_order_list) { const { list } = p2p_order_list; // it's an array of orders from p2p_order_list - this.handleNotifications(order_store.orders, list); + this.handleNotifications(order_store?.orders, list); list.forEach(order => order_store.syncOrder(order)); } else if (p2p_order_info) { // it's a single order from p2p_order_info - const idx_order_to_update = order_store.orders.findIndex(order => order.id === p2p_order_info.id); - const updated_orders = [...order_store.orders]; + const idx_order_to_update = order_store?.orders.findIndex(order => order.id === p2p_order_info.id); + const updated_orders = [...order_store?.orders]; // if it's a new order, add it to the top of the list if (idx_order_to_update < 0) { updated_orders.unshift(p2p_order_info); @@ -418,48 +458,40 @@ export default class GeneralStore extends BaseStore { updated_orders[idx_order_to_update] = p2p_order_info; } - this.handleNotifications(order_store.orders, updated_orders); + this.handleNotifications(order_store?.orders, updated_orders); order_store.syncOrder(p2p_order_info); } } - @action.bound setParameters(parameters) { this.parameters = parameters; } - @action.bound setPoiStatus(poi_status) { this.poi_status = poi_status; } - @action.bound setShouldShowRealName(should_show_real_name) { this.should_show_real_name = should_show_real_name; } - @action.bound setShouldShowPopup(should_show_popup) { this.should_show_popup = should_show_popup; } - @action.bound setUserBlockedUntil(user_blocked_until) { this.user_blocked_until = user_blocked_until; } - @action.bound setWebsocketInit = (websocket, local_currency_decimal_places) => { WebsocketInit(websocket, local_currency_decimal_places); }; - @action.bound toggleNicknamePopup() { this.setShouldShowPopup(!this.should_show_popup); this.setNicknameError(undefined); } - @action.bound updateAdvertiserInfo(response) { const { p2p_advertiser_info } = response; if (!response.error) { @@ -496,7 +528,6 @@ export default class GeneralStore extends BaseStore { this.setIsLoading(false); } - @action.bound updateP2pNotifications(notifications) { const unseen_notifications = notifications.filter(notification => notification.is_seen === false); const notification_count = unseen_notifications.length; diff --git a/packages/p2p/src/stores/my-ads-store.js b/packages/p2p/src/stores/my-ads-store.js index 0cb904e21848..7479ba5ddc55 100644 --- a/packages/p2p/src/stores/my-ads-store.js +++ b/packages/p2p/src/stores/my-ads-store.js @@ -1,4 +1,4 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { getDecimalPlaces } from '@deriv/shared'; import { localize } from 'Components/i18next'; import { buy_sell } from 'Constants/buy-sell'; @@ -8,45 +8,140 @@ import { decimalValidator, lengthValidator, textValidator } from 'Utils/validati import { requestWS } from 'Utils/websocket'; export default class MyAdsStore extends BaseStore { - @observable activate_deactivate_error_message = ''; - @observable advert_details = null; - @observable adverts = []; - @observable adverts_archive_period = null; - @observable api_error = ''; - @observable api_error_message = ''; - @observable api_table_error_message = ''; - @observable available_balance = null; - @observable contact_info = ''; - @observable default_advert_description = ''; - @observable delete_error_message = ''; - @observable edit_ad_form_error = ''; - @observable error_message = ''; - @observable has_more_items_to_load = false; - @observable has_missing_payment_methods = false; - @observable is_ad_created_modal_visible = false; - @observable is_ad_exceeds_daily_limit_modal_open = false; - @observable is_api_error_modal_visible = false; - @observable is_delete_modal_open = false; - @observable is_edit_ad_error_modal_visible = false; - @observable is_form_loading = false; - @observable is_quick_add_error_modal_open = false; - @observable is_quick_add_modal_open = false; - @observable is_table_loading = false; - @observable is_loading = false; - @observable item_offset = 0; - @observable p2p_advert_information = {}; - @observable selected_ad_id = ''; - @observable selected_advert = null; - @observable should_show_add_payment_method = false; - @observable should_show_add_payment_method_modal = false; - @observable show_ad_form = false; - @observable show_edit_ad_form = false; - @observable update_payment_methods_error_message = ''; + activate_deactivate_error_message = ''; + advert_details = null; + adverts = []; + adverts_archive_period = null; + api_error = ''; + api_error_message = ''; + api_table_error_message = ''; + available_balance = null; + contact_info = ''; + default_advert_description = ''; + delete_error_message = ''; + edit_ad_form_error = ''; + error_message = ''; + has_more_items_to_load = false; + has_missing_payment_methods = false; + is_ad_created_modal_visible = false; + is_ad_exceeds_daily_limit_modal_open = false; + is_api_error_modal_visible = false; + is_delete_modal_open = false; + is_edit_ad_error_modal_visible = false; + is_form_loading = false; + is_quick_add_error_modal_open = false; + is_quick_add_modal_open = false; + is_table_loading = false; + is_loading = false; + item_offset = 0; + p2p_advert_information = {}; + selected_ad_id = ''; + selected_advert = null; + should_show_add_payment_method = false; + should_show_add_payment_method_modal = false; + show_ad_form = false; + show_edit_ad_form = false; + update_payment_methods_error_message = ''; payment_method_ids = []; payment_method_names = []; - @action.bound + constructor({ general_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ general_store }); + + makeObservable(this, { + activate_deactivate_error_message: observable, + advert_details: observable, + adverts: observable, + adverts_archive_period: observable, + api_error: observable, + api_error_message: observable, + api_table_error_message: observable, + available_balance: observable, + contact_info: observable, + default_advert_description: observable, + delete_error_message: observable, + edit_ad_form_error: observable, + error_message: observable, + has_more_items_to_load: observable, + has_missing_payment_methods: observable, + is_ad_created_modal_visible: observable, + is_ad_exceeds_daily_limit_modal_open: observable, + is_api_error_modal_visible: observable, + is_delete_modal_open: observable, + is_edit_ad_error_modal_visible: observable, + is_form_loading: observable, + is_quick_add_error_modal_open: observable, + is_quick_add_modal_open: observable, + is_table_loading: observable, + is_loading: observable, + item_offset: observable, + p2p_advert_information: observable, + selected_ad_id: observable, + selected_advert: observable, + should_show_add_payment_method: observable, + should_show_add_payment_method_modal: observable, + show_ad_form: observable, + show_edit_ad_form: observable, + update_payment_methods_error_message: observable, + getAccountStatus: action.bound, + getAdvertInfo: action.bound, + getAdvertiserInfo: action.bound, + getWebsiteStatus: action.bound, + handleSubmit: action.bound, + hideQuickAddModal: action.bound, + onClickActivateDeactivate: action.bound, + onClickCancel: action.bound, + onClickConfirm: action.bound, + onClickCreate: action.bound, + onClickDelete: action.bound, + onClickEdit: action.bound, + onClickSaveEditAd: action.bound, + onClickUpdatePaymentMethods: action.bound, + loadMoreAds: action.bound, + restrictLength: action.bound, + showQuickAddModal: action.bound, + setActivateDeactivateErrorMessage: action.bound, + setAdvertDetails: action.bound, + setAdverts: action.bound, + setAdvertsArchivePeriod: action.bound, + setApiError: action.bound, + setApiErrorMessage: action.bound, + setApiTableErrorMessage: action.bound, + setAvailableBalance: action.bound, + setContactInfo: action.bound, + setCreateAdErrorCode: action.bound, + setDefaultAdvertDescription: action.bound, + setDeleteErrorMessage: action.bound, + setEditAdFormError: action.bound, + setErrorMessage: action.bound, + setHasMoreItemsToLoad: action.bound, + setMissingPaymentMethods: action.bound, + setIsAdCreatedModalVisible: action.bound, + setIsAdExceedsDailyLimitModalOpen: action.bound, + setIsApiErrorModalVisible: action.bound, + setIsDeleteModalOpen: action.bound, + setIsEditAdErrorModalVisible: action.bound, + setIsFormLoading: action.bound, + setIsLoading: action.bound, + setIsQuickAddErrorModalOpen: action.bound, + setIsQuickAddModalOpen: action.bound, + setIsTableLoading: action.bound, + setItemOffset: action.bound, + setP2pAdvertInformation: action.bound, + setSelectedAdId: action.bound, + setSelectedAdvert: action.bound, + setShouldShowAddPaymentMethod: action.bound, + setShouldShowAddPaymentMethodModal: action.bound, + setShowAdForm: action.bound, + setShowEditAdForm: action.bound, + setUpdatePaymentMethodsErrorMessage: action.bound, + validateCreateAdForm: action.bound, + validateEditAdForm: action.bound, + }); + } + getAccountStatus() { this.setIsLoading(true); @@ -66,7 +161,6 @@ export default class MyAdsStore extends BaseStore { } } - @action.bound getAdvertInfo() { this.setIsFormLoading(true); @@ -86,7 +180,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound getAdvertiserInfo() { this.setIsFormLoading(true); @@ -106,7 +199,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound getWebsiteStatus(createAd = () => {}, setSubmitting) { requestWS({ website_status: 1 }).then(response => { if (response.error) { @@ -120,7 +212,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound handleSubmit(values, { setSubmitting }) { this.setApiErrorMessage(''); @@ -181,13 +272,11 @@ export default class MyAdsStore extends BaseStore { } } - @action.bound hideQuickAddModal() { this.setIsQuickAddModalOpen(false); this.setSelectedAdId(undefined); } - @action.bound onClickActivateDeactivate(id, is_ad_active, setIsAdvertActive) { if (!this.root_store.general_store.is_barred) { requestWS({ p2p_advert_update: 1, id, is_active: is_ad_active ? 0 : 1 }).then(response => { @@ -201,13 +290,11 @@ export default class MyAdsStore extends BaseStore { } } - @action.bound onClickCancel() { this.setSelectedAdId(''); this.setShouldShowPopup(false); } - @action.bound onClickConfirm(showError) { requestWS({ p2p_advert_update: 1, id: this.selected_ad_id, delete: 1 }).then(response => { if (response.error) { @@ -221,12 +308,10 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound onClickCreate() { this.setShowAdForm(true); } - @action.bound onClickDelete(id) { if (!this.root_store.general_store.is_barred) { this.setSelectedAdId(id); @@ -234,7 +319,6 @@ export default class MyAdsStore extends BaseStore { } } - @action.bound onClickEdit(id) { if (!this.root_store.general_store.is_barred) { this.setSelectedAdId(id); @@ -243,7 +327,6 @@ export default class MyAdsStore extends BaseStore { } } - @action.bound onClickSaveEditAd(values, { setSubmitting }) { const is_sell_ad = values.type === buy_sell.SELL; @@ -281,7 +364,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound onClickUpdatePaymentMethods(id, is_buy_advert) { requestWS({ p2p_advert_update: 1, @@ -305,7 +387,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound loadMoreAds({ startIndex }, is_initial_load = false) { if (is_initial_load) { this.setIsTableLoading(true); @@ -337,7 +418,6 @@ export default class MyAdsStore extends BaseStore { }); } - @action.bound restrictLength = (e, handleChange) => { // typing more than 15 characters will break the layout // max doesn't disable typing, so we will use this to restrict length @@ -349,188 +429,151 @@ export default class MyAdsStore extends BaseStore { handleChange(e); }; - @action.bound showQuickAddModal(advert) { this.setSelectedAdId(advert); this.setIsQuickAddModalOpen(true); } - @action.bound setActivateDeactivateErrorMessage(activate_deactivate_error_message) { this.activate_deactivate_error_message = activate_deactivate_error_message; } - @action.bound setAdvertDetails(advert_details) { this.advert_details = advert_details; } - @action.bound setAdverts(adverts) { this.adverts = adverts; } - @action.bound setAdvertsArchivePeriod(adverts_archive_period) { this.adverts_archive_period = adverts_archive_period; } - @action.bound setApiError(api_error) { this.api_error = api_error; } - @action.bound setApiErrorMessage(api_error_message) { this.api_error_message = api_error_message; } - @action.bound setApiTableErrorMessage(api_table_error_message) { this.api_table_error_message = api_table_error_message; } - @action.bound setAvailableBalance(available_balance) { this.available_balance = available_balance; } - @action.bound setContactInfo(contact_info) { this.contact_info = contact_info; } - @action.bound setCreateAdErrorCode(create_ad_error_code) { this.create_ad_error_code = create_ad_error_code; } - @action.bound setDefaultAdvertDescription(default_advert_description) { this.default_advert_description = default_advert_description; } - @action.bound setDeleteErrorMessage(delete_error_message) { this.delete_error_message = delete_error_message; } - @action.bound setEditAdFormError(edit_ad_form_error) { this.edit_ad_form_error = edit_ad_form_error; } - @action.bound setErrorMessage(error_message) { this.error_message = error_message; } - @action.bound setHasMoreItemsToLoad(has_more_items_to_load) { this.has_more_items_to_load = has_more_items_to_load; } - @action.bound setMissingPaymentMethods(has_missing_payment_methods) { this.has_missing_payment_methods = has_missing_payment_methods; } - @action.bound setIsAdCreatedModalVisible(is_ad_created_modal_visible) { this.is_ad_created_modal_visible = is_ad_created_modal_visible; } - @action.bound setIsAdExceedsDailyLimitModalOpen(is_ad_exceeds_daily_limit_modal_open) { this.is_ad_exceeds_daily_limit_modal_open = is_ad_exceeds_daily_limit_modal_open; } - @action.bound setIsApiErrorModalVisible(is_api_error_modal_visible) { this.is_api_error_modal_visible = is_api_error_modal_visible; } - @action.bound setIsDeleteModalOpen(is_delete_modal_open) { this.is_delete_modal_open = is_delete_modal_open; } - @action.bound setIsEditAdErrorModalVisible(is_edit_ad_error_modal_visible) { this.is_edit_ad_error_modal_visible = is_edit_ad_error_modal_visible; } - @action.bound setIsFormLoading(is_form_loading) { this.is_form_loading = is_form_loading; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsQuickAddErrorModalOpen(is_quick_add_error_modal_open) { this.is_quick_add_error_modal_open = is_quick_add_error_modal_open; } - @action.bound setIsQuickAddModalOpen(is_quick_add_modal_open) { this.is_quick_add_modal_open = is_quick_add_modal_open; } - @action.bound setIsTableLoading(is_table_loading) { this.is_table_loading = is_table_loading; } - @action.bound setItemOffset(item_offset) { this.item_offset = item_offset; } - @action.bound setP2pAdvertInformation(p2p_advert_information) { this.p2p_advert_information = p2p_advert_information; } - @action.bound setSelectedAdId(selected_ad_id) { this.selected_ad_id = selected_ad_id; } - @action.bound setSelectedAdvert(selected_advert) { this.selected_advert = selected_advert; } - @action.bound setShouldShowAddPaymentMethod(should_show_add_payment_method) { this.should_show_add_payment_method = should_show_add_payment_method; } - @action.bound setShouldShowAddPaymentMethodModal(should_show_add_payment_method_modal) { this.should_show_add_payment_method_modal = should_show_add_payment_method_modal; } - @action.bound setShowAdForm(show_ad_form) { this.show_ad_form = show_ad_form; } - @action.bound setShowEditAdForm(show_edit_ad_form) { this.show_edit_ad_form = show_edit_ad_form; } - @action.bound setUpdatePaymentMethodsErrorMessage(update_payment_methods_error_message) { this.update_payment_methods_error_message = update_payment_methods_error_message; } - @action.bound validateCreateAdForm(values) { const validations = { default_advert_description: [v => !v || lengthValidator(v), v => !v || textValidator(v)], @@ -677,7 +720,6 @@ export default class MyAdsStore extends BaseStore { return errors; } - @action.bound validateEditAdForm(values) { const validations = { description: [v => !v || lengthValidator(v), v => !v || textValidator(v)], diff --git a/packages/p2p/src/stores/my-profile-store.js b/packages/p2p/src/stores/my-profile-store.js index 43ecc9c8c2ed..490e4cd4e487 100644 --- a/packages/p2p/src/stores/my-profile-store.js +++ b/packages/p2p/src/stores/my-profile-store.js @@ -1,4 +1,4 @@ -import { observable, action, computed } from 'mobx'; +import { observable, action, computed, makeObservable } from 'mobx'; import { requestWS } from 'Utils/websocket'; import { localize } from 'Components/i18next'; import { textValidator } from 'Utils/validations'; @@ -6,48 +6,143 @@ import BaseStore from 'Stores/base_store'; import { my_profile_tabs } from 'Constants/my-profile-tabs'; export default class MyProfileStore extends BaseStore { - @observable active_tab = my_profile_tabs.MY_STATS; - @observable add_payment_method_error_message = ''; - @observable advertiser_info = {}; - @observable advertiser_payment_methods = {}; - @observable advertiser_payment_methods_error = ''; - @observable available_payment_methods = {}; - @observable balance_available = null; - @observable contact_info = ''; - @observable default_advert_description = ''; - @observable delete_error_message = ''; - @observable error_message = ''; - @observable form_error = ''; - @observable full_name = ''; - @observable is_button_loading = false; - @observable is_cancel_add_payment_method_modal_open = false; - @observable is_cancel_edit_payment_method_modal_open = false; - @observable is_confirm_delete_modal_open = false; - @observable is_delete_error_modal_open = false; - @observable is_loading = true; - @observable is_submit_success = false; - @observable payment_info = ''; - @observable payment_method_value = undefined; - @observable payment_methods_list = []; - @observable payment_method_to_delete = {}; - @observable payment_method_to_edit = {}; - @observable search_results = []; - @observable search_term = ''; - @observable selected_payment_method = ''; - @observable selected_payment_method_display_name = ''; - @observable selected_payment_method_fields = []; - @observable selected_payment_method_type = ''; - @observable should_hide_my_profile_tab = false; - @observable should_show_add_payment_method_error_modal = false; - @observable should_show_add_payment_method_form = false; - @observable should_show_edit_payment_method_form = false; - - @computed + active_tab = my_profile_tabs.MY_STATS; + add_payment_method_error_message = ''; + advertiser_info = {}; + advertiser_payment_methods = {}; + advertiser_payment_methods_error = ''; + available_payment_methods = {}; + balance_available = null; + contact_info = ''; + default_advert_description = ''; + delete_error_message = ''; + error_message = ''; + form_error = ''; + full_name = ''; + is_button_loading = false; + is_cancel_add_payment_method_modal_open = false; + is_cancel_edit_payment_method_modal_open = false; + is_confirm_delete_modal_open = false; + is_delete_error_modal_open = false; + is_loading = true; + is_submit_success = false; + payment_info = ''; + payment_method_value = undefined; + payment_methods_list = []; + payment_method_to_delete = {}; + payment_method_to_edit = {}; + search_results = []; + search_term = ''; + selected_payment_method = ''; + selected_payment_method_display_name = ''; + selected_payment_method_fields = []; + selected_payment_method_type = ''; + should_hide_my_profile_tab = false; + should_show_add_payment_method_error_modal = false; + should_show_add_payment_method_form = false; + should_show_edit_payment_method_form = false; + + constructor() { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super(); + + makeObservable(this, { + active_tab: observable, + add_payment_method_error_message: observable, + advertiser_info: observable, + advertiser_payment_methods: observable, + advertiser_payment_methods_error: observable, + available_payment_methods: observable, + balance_available: observable, + contact_info: observable, + default_advert_description: observable, + delete_error_message: observable, + error_message: observable, + form_error: observable, + full_name: observable, + is_button_loading: observable, + is_cancel_add_payment_method_modal_open: observable, + is_cancel_edit_payment_method_modal_open: observable, + is_confirm_delete_modal_open: observable, + is_delete_error_modal_open: observable, + is_loading: observable, + is_submit_success: observable, + payment_info: observable, + payment_method_value: observable, + payment_methods_list: observable, + payment_method_to_delete: observable, + payment_method_to_edit: observable, + search_results: observable, + search_term: observable, + selected_payment_method: observable, + selected_payment_method_display_name: observable, + selected_payment_method_fields: observable, + selected_payment_method_type: observable, + should_hide_my_profile_tab: observable, + should_show_add_payment_method_error_modal: observable, + should_show_add_payment_method_form: observable, + should_show_edit_payment_method_form: observable, + advertiser_has_payment_methods: computed, + advertiser_payment_methods_list: computed, + initial_values: computed, + payment_method_field_set: computed, + payment_method_info: computed, + payment_methods_list_items: computed, + payment_methods_list_methods: computed, + payment_methods_list_values: computed, + createPaymentMethod: action.bound, + getAdvertiserInfo: action.bound, + getAdvertiserPaymentMethods: action.bound, + getPaymentMethodsList: action.bound, + getPaymentMethodDisplayName: action.bound, + getPaymentMethodValue: action.bound, + getSelectedPaymentMethodDetails: action.bound, + handleSubmit: action.bound, + handleToggle: action.bound, + hideAddPaymentMethodForm: action.bound, + onClickDelete: action.bound, + showAddPaymentMethodForm: action.bound, + updatePaymentMethod: action.bound, + setActiveTab: action.bound, + setAddPaymentMethodErrorMessage: action.bound, + setAdvertiserInfo: action.bound, + setAdvertiserPaymentMethods: action.bound, + setAdvertiserPaymentMethodsError: action.bound, + setAvailablePaymentMethods: action.bound, + setBalanceAvailable: action.bound, + setContactInfo: action.bound, + setDefaultAdvertDescription: action.bound, + setDeleteErrorMessage: action.bound, + setErrorMessage: action.bound, + setFormError: action.bound, + setFullName: action.bound, + setIsCancelAddPaymentMethodModalOpen: action.bound, + setIsCancelEditPaymentMethodModalOpen: action.bound, + setIsConfirmDeleteModalOpen: action.bound, + setIsDeleteErrorModalOpen: action.bound, + setIsLoading: action.bound, + setIsSubmitSuccess: action.bound, + setPaymentMethodValue: action.bound, + setPaymentMethodsList: action.bound, + setPaymentMethodToDelete: action.bound, + setPaymentMethodToEdit: action.bound, + setSearchResults: action.bound, + setSearchTerm: action.bound, + setSelectedPaymentMethod: action.bound, + setSelectedPaymentMethodDisplayName: action.bound, + setSelectedPaymentMethodFields: action.bound, + setSelectedPaymentMethodType: action.bound, + setShouldHideMyProfileTab: action.bound, + setShouldShowAddPaymentMethodErrorModal: action.bound, + setShouldShowAddPaymentMethodForm: action.bound, + setShouldShowEditPaymentMethodForm: action.bound, + }); + } + get advertiser_has_payment_methods() { return !!Object.keys(this.advertiser_payment_methods).length; } - @computed get advertiser_payment_methods_list() { const list = []; @@ -64,7 +159,6 @@ export default class MyProfileStore extends BaseStore { return list; } - @computed get payment_method_field_set() { // The fields are rendered dynamically based on the response. This variable will hold a dictionary of field id and their name return this.selected_payment_method_fields.reduce((dict, field_data) => { @@ -72,7 +166,6 @@ export default class MyProfileStore extends BaseStore { }, {}); } - @computed get initial_values() { const object = {}; @@ -91,12 +184,10 @@ export default class MyProfileStore extends BaseStore { return object; } - @computed get payment_method_info() { return this.advertiser_payment_methods_list.filter(method => method.ID === this.payment_method_to_edit.ID)[0]; } - @computed get payment_methods_list_items() { const list_items = []; @@ -107,7 +198,6 @@ export default class MyProfileStore extends BaseStore { return list_items; } - @computed get payment_methods_list_methods() { const methods = []; @@ -124,7 +214,6 @@ export default class MyProfileStore extends BaseStore { return methods; } - @computed get payment_methods_list_values() { const list = []; @@ -133,7 +222,6 @@ export default class MyProfileStore extends BaseStore { return list; } - @action.bound createPaymentMethod(values, { setSubmitting }) { setSubmitting(true); requestWS({ @@ -174,7 +262,6 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound getAdvertiserInfo() { this.setIsLoading(true); this.setErrorMessage(''); @@ -197,7 +284,6 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound getAdvertiserPaymentMethods() { this.setIsLoading(true); requestWS({ @@ -212,7 +298,6 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound getPaymentMethodsList() { requestWS({ p2p_payment_methods: 1, @@ -246,13 +331,11 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound getPaymentMethodDisplayName(payment_method) { this.setSelectedPaymentMethodDisplayName(this.available_payment_methods[payment_method].display_name); return this.selected_payment_method_display_name; } - @action.bound getPaymentMethodValue(payment_method) { const method = Object.entries(this.available_payment_methods).filter( pm => pm[1].display_name === payment_method @@ -262,7 +345,6 @@ export default class MyProfileStore extends BaseStore { return this.payment_method_value; } - @action.bound getSelectedPaymentMethodDetails() { this.setPaymentMethodValue(undefined); @@ -297,7 +379,6 @@ export default class MyProfileStore extends BaseStore { } }); } - @action.bound handleSubmit(values) { requestWS({ p2p_advertiser_update: 1, @@ -319,7 +400,6 @@ export default class MyProfileStore extends BaseStore { }, 3000); }); } - @action.bound handleToggle() { this.root_store.general_store.setShouldShowRealName(!this.root_store?.general_store?.should_show_real_name); requestWS({ @@ -335,12 +415,10 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound hideAddPaymentMethodForm() { this.setShouldShowAddPaymentMethodForm(false); } - @action.bound onClickDelete() { requestWS({ p2p_advertiser_payment_methods: 1, @@ -356,12 +434,10 @@ export default class MyProfileStore extends BaseStore { }); } - @action.bound showAddPaymentMethodForm() { this.setShouldShowAddPaymentMethodForm(true); } - @action.bound updatePaymentMethod(values, { setSubmitting }) { requestWS({ p2p_advertiser_payment_methods: 1, @@ -427,167 +503,134 @@ export default class MyProfileStore extends BaseStore { return errors; }; - @action.bound setActiveTab(active_tab) { this.active_tab = active_tab; } - @action.bound setAddPaymentMethodErrorMessage(add_payment_method_error_message) { this.add_payment_method_error_message = add_payment_method_error_message; } - @action.bound setAdvertiserInfo(advertiser_info) { this.advertiser_info = advertiser_info; } - @action.bound setAdvertiserPaymentMethods(advertiser_payment_methods) { this.advertiser_payment_methods = advertiser_payment_methods; } - @action.bound setAdvertiserPaymentMethodsError(advertiser_payment_methods_error) { this.advertiser_payment_methods_error = advertiser_payment_methods_error; } - @action.bound setAvailablePaymentMethods(available_payment_methods) { this.available_payment_methods = available_payment_methods; } - @action.bound setBalanceAvailable(balance_available) { this.balance_available = balance_available; } - @action.bound setContactInfo(contact_info) { this.contact_info = contact_info; } - @action.bound setDefaultAdvertDescription(default_advert_description) { this.default_advert_description = default_advert_description; } - @action.bound setDeleteErrorMessage(delete_error_message) { this.delete_error_message = delete_error_message; } - @action.bound setErrorMessage(error_message) { this.error_message = error_message; } - @action.bound setFormError(form_error) { this.form_error = form_error; } - @action.bound setFullName(full_name) { this.full_name = full_name; } - @action.bound setIsCancelAddPaymentMethodModalOpen(is_cancel_add_payment_method_modal_open) { this.is_cancel_add_payment_method_modal_open = is_cancel_add_payment_method_modal_open; } - @action.bound setIsCancelEditPaymentMethodModalOpen(is_cancel_edit_payment_method_modal_open) { this.is_cancel_edit_payment_method_modal_open = is_cancel_edit_payment_method_modal_open; } - @action.bound setIsConfirmDeleteModalOpen(is_confirm_delete_modal_open) { this.is_confirm_delete_modal_open = is_confirm_delete_modal_open; } - @action.bound setIsDeleteErrorModalOpen(is_delete_error_modal_open) { this.is_delete_error_modal_open = is_delete_error_modal_open; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setIsSubmitSuccess(is_submit_success) { this.is_submit_success = is_submit_success; } - @action.bound setPaymentMethodValue(payment_method_value) { this.payment_method_value = payment_method_value; } - @action.bound setPaymentMethodsList(payment_methods_list) { this.payment_methods_list = payment_methods_list; } - @action.bound setPaymentMethodToDelete(payment_method_to_delete) { this.payment_method_to_delete = payment_method_to_delete; } - @action.bound setPaymentMethodToEdit(payment_method_to_edit) { this.payment_method_to_edit = payment_method_to_edit; } - @action.bound setSearchResults(search_results) { this.search_results = search_results; } - @action.bound setSearchTerm(search_term) { this.search_term = search_term; } - @action.bound setSelectedPaymentMethod(selected_payment_method) { this.selected_payment_method = selected_payment_method; } - @action.bound setSelectedPaymentMethodDisplayName(selected_payment_method_display_name) { this.selected_payment_method_display_name = selected_payment_method_display_name; } - @action.bound setSelectedPaymentMethodFields(selected_payment_method_fields) { this.selected_payment_method_fields = selected_payment_method_fields; } - @action.bound setSelectedPaymentMethodType(selected_payment_method_type) { this.selected_payment_method_type = selected_payment_method_type; } - @action.bound setShouldHideMyProfileTab(should_hide_my_profile_tab) { this.should_hide_my_profile_tab = should_hide_my_profile_tab; } - @action.bound setShouldShowAddPaymentMethodErrorModal(should_show_add_payment_method_error_modal) { this.should_show_add_payment_method_error_modal = should_show_add_payment_method_error_modal; } - @action.bound setShouldShowAddPaymentMethodForm(should_show_add_payment_method_form) { this.should_show_add_payment_method_form = should_show_add_payment_method_form; } - @action.bound setShouldShowEditPaymentMethodForm(should_show_edit_payment_method_form) { this.should_show_edit_payment_method_form = should_show_edit_payment_method_form; } diff --git a/packages/p2p/src/stores/order-details-store.js b/packages/p2p/src/stores/order-details-store.js index ac8acec9ec37..2950ec0ce920 100644 --- a/packages/p2p/src/stores/order-details-store.js +++ b/packages/p2p/src/stores/order-details-store.js @@ -1,19 +1,32 @@ -import { observable, action } from 'mobx'; +import { observable, action, makeObservable } from 'mobx'; import { secondsToTimer } from 'Utils/date-time'; import ServerTime from 'Utils/server-time'; import { localize } from 'Components/i18next'; export default class OrderDetailsStore { constructor(root_store) { + makeObservable(this, { + interval: observable, + popup_options: observable, + remaining_time: observable, + should_show_popup: observable, + countDownTimer: action.bound, + handleShowPopup: action.bound, + onCancelClick: action.bound, + setIntervalState: action.bound, + setPopupOptions: action.bound, + setRemainingTime: action.bound, + setShouldShowPopup: action.bound, + }); + this.root_store = root_store; } - @observable interval = null; - @observable popup_options = {}; - @observable remaining_time; - @observable should_show_popup = false; + interval = null; + popup_options = {}; + remaining_time; + should_show_popup = false; - @action.bound countDownTimer() { const distance = ServerTime.getDistanceToServerTime( this.root_store.order_store.order_information.order_expiry_milliseconds @@ -28,33 +41,27 @@ export default class OrderDetailsStore { } } - @action.bound handleShowPopup(options) { this.setPopupOptions(options); this.setShouldShowPopup(true); } - @action.bound onCancelClick() { this.setShouldShowPopup(false); } - @action.bound setIntervalState(interval) { this.interval = interval; } - @action.bound setPopupOptions(popup_options) { this.popup_options = popup_options; } - @action.bound setRemainingTime(remaining_time) { this.remaining_time = remaining_time; } - @action.bound setShouldShowPopup(should_show_popup) { this.should_show_popup = should_show_popup; } diff --git a/packages/p2p/src/stores/order-store.js b/packages/p2p/src/stores/order-store.js index 855ab9d5a67d..c58e7c17ea60 100644 --- a/packages/p2p/src/stores/order-store.js +++ b/packages/p2p/src/stores/order-store.js @@ -1,10 +1,53 @@ import { cloneObject } from '@deriv/shared'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import { createExtendedOrderDetails } from 'Utils/orders'; import { requestWS, subscribeWS } from 'Utils/websocket'; export default class OrderStore { constructor(root_store) { + makeObservable(this, { + api_error_message: observable, + cancellation_block_duration: observable, + cancellation_count_period: observable, + cancellation_limit: observable, + cancels_remaining: observable, + error_message: observable, + has_more_items_to_load: observable, + is_loading: observable, + orders: observable, + order_id: observable, + order_payment_method_details: observable, + order_rerender_timeout: observable, + has_order_payment_method_details: computed, + order_information: computed, + nav: computed, + getAdvertiserInfo: action.bound, + getWebsiteStatus: action.bound, + hideDetails: action.bound, + loadMoreOrders: action.bound, + onOrderIdUpdate: action.bound, + onOrdersUpdate: action.bound, + onUnmount: action.bound, + setApiErrorMessage: action.bound, + setCancellationBlockDuration: action.bound, + setCancellationCountPeriod: action.bound, + setCancellationLimit: action.bound, + setCancelsRemaining: action.bound, + setErrorMessage: action.bound, + setHasMoreItemsToLoad: action.bound, + setIsLoading: action.bound, + setOrderPaymentMethodDetails: action.bound, + setOrderDetails: action.bound, + setOrderId: action.bound, + setOrders: action.bound, + setOrderRendererTimeout: action.bound, + setQueryDetails: action.bound, + setData: action.bound, + subscribeToCurrentOrder: action.bound, + syncOrder: action.bound, + unsubscribeFromCurrentOrder: action.bound, + }); + this.root_store = root_store; reaction( @@ -15,29 +58,27 @@ export default class OrderStore { ); } - @observable api_error_message = ''; - @observable cancellation_block_duration = 0; - @observable cancellation_count_period = 0; - @observable cancellation_limit = 0; - @observable cancels_remaining = null; - @observable error_message = ''; - @observable has_more_items_to_load = false; - @observable is_loading = false; - @observable orders = []; - @observable order_id = null; - @observable order_payment_method_details = null; - @observable order_rerender_timeout = null; + api_error_message = ''; + cancellation_block_duration = 0; + cancellation_count_period = 0; + cancellation_limit = 0; + cancels_remaining = null; + error_message = ''; + has_more_items_to_load = false; + is_loading = false; + orders = []; + order_id = null; + order_payment_method_details = null; + order_rerender_timeout = null; interval; order_info_subscription = {}; previous_orders = []; - @computed get has_order_payment_method_details() { return !!this.order_payment_method_details; } - @computed get order_information() { const { general_store } = this.root_store; const order = this.orders.find(o => o.id === this.order_id); @@ -47,12 +88,10 @@ export default class OrderStore { : null; } - @computed get nav() { return this.root_store.general_store.parameters?.nav; } - @action.bound getAdvertiserInfo(setShouldShowCancelModal) { requestWS({ p2p_advertiser_info: 1 }).then(response => { if (response.error) { @@ -65,7 +104,6 @@ export default class OrderStore { this.getWebsiteStatus(setShouldShowCancelModal); } - @action.bound getWebsiteStatus(setShouldShowCancelModal) { requestWS({ website_status: 1 }).then(response => { if (response.error) { @@ -83,7 +121,6 @@ export default class OrderStore { }); } - @action.bound hideDetails(should_navigate) { if (should_navigate && this.nav) { this.root_store.general_store.redirectTo(this.nav.location); @@ -92,7 +129,6 @@ export default class OrderStore { this.setOrderId(null); } - @action.bound loadMoreOrders({ startIndex }) { this.setApiErrorMessage(''); @@ -140,7 +176,6 @@ export default class OrderStore { }); } - @action.bound onOrderIdUpdate() { this.unsubscribeFromCurrentOrder(); @@ -149,7 +184,6 @@ export default class OrderStore { } } - @action.bound onOrdersUpdate() { if (this.order_id) { // If orders was updated, find current viewed order (if any) @@ -164,59 +198,48 @@ export default class OrderStore { } } - @action.bound onUnmount() { clearTimeout(this.order_rerender_timeout); this.unsubscribeFromCurrentOrder(); this.hideDetails(false); } - @action.bound setApiErrorMessage(api_error_message) { this.api_error_message = api_error_message; } - @action.bound setCancellationBlockDuration(cancellation_block_duration) { this.cancellation_block_duration = cancellation_block_duration; } - @action.bound setCancellationCountPeriod(cancellation_count_period) { this.cancellation_count_period = cancellation_count_period; } - @action.bound setCancellationLimit(cancellation_limit) { this.cancellation_limit = cancellation_limit; } - @action.bound setCancelsRemaining(cancels_remaining) { this.cancels_remaining = cancels_remaining; } - @action.bound setErrorMessage(error_message) { this.error_message = error_message; } - @action.bound setHasMoreItemsToLoad(has_more_items_to_load) { this.has_more_items_to_load = has_more_items_to_load; } - @action.bound setIsLoading(is_loading) { this.is_loading = is_loading; } - @action.bound setOrderPaymentMethodDetails(order_payment_method_details) { this.order_payment_method_details = order_payment_method_details; } - @action.bound setOrderDetails(response) { if (!response.error) { const { p2p_order_info } = response; @@ -227,7 +250,6 @@ export default class OrderStore { } } - @action.bound setOrderId(order_id) { this.order_id = order_id; @@ -238,18 +260,15 @@ export default class OrderStore { } } - @action.bound setOrders(orders) { this.previous_orders = cloneObject(this.orders); this.orders = orders; } - @action.bound setOrderRendererTimeout(order_rerender_timeout) { this.order_rerender_timeout = order_rerender_timeout; } - @action.bound setQueryDetails(input_order) { const { general_store } = this.root_store; const order_information = createExtendedOrderDetails( @@ -291,12 +310,10 @@ export default class OrderStore { } } - @action.bound setData(data) { this.data = data; } - @action.bound subscribeToCurrentOrder() { this.order_info_subscription = subscribeWS( { @@ -308,7 +325,6 @@ export default class OrderStore { ); } - @action.bound syncOrder(p2p_order_info) { const { general_store } = this.root_store; @@ -336,7 +352,6 @@ export default class OrderStore { } } - @action.bound unsubscribeFromCurrentOrder() { clearTimeout(this.order_rerender_timeout); diff --git a/packages/p2p/src/stores/sendbird-store.js b/packages/p2p/src/stores/sendbird-store.js index 6d8175146d0b..19c409dff1bb 100644 --- a/packages/p2p/src/stores/sendbird-store.js +++ b/packages/p2p/src/stores/sendbird-store.js @@ -1,36 +1,63 @@ import SendBird from 'sendbird'; import { epochToMoment } from '@deriv/shared'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable } from 'mobx'; import BaseStore from 'Stores/base_store'; import ChatMessage, { convertFromChannelMessage } from 'Utils/chat-message'; import { requestWS } from 'Utils/websocket'; export default class SendbirdStore extends BaseStore { - @observable active_chat_channel = null; - @observable.ref chat_channel_url = null; - @observable.ref chat_info = { app_id: null, user_id: null, token: null }; - @observable.shallow chat_messages = []; - @observable has_chat_error = null; - @observable is_chat_loading = true; - @observable should_show_chat_modal = false; - @observable should_show_chat_on_orders = false; + active_chat_channel = null; + chat_channel_url = null; + chat_info = { app_id: null, user_id: null, token: null }; + chat_messages = []; + has_chat_error = null; + is_chat_loading = true; + should_show_chat_modal = false; + should_show_chat_on_orders = false; messages_ref = null; sendbird_api = null; service_token_timeout = null; scroll_debounce = null; - @computed + constructor() { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super(); + + makeObservable(this, { + active_chat_channel: observable, + chat_channel_url: observable.ref, + chat_info: observable.ref, + chat_messages: observable.shallow, + has_chat_error: observable, + is_chat_loading: observable, + should_show_chat_modal: observable, + should_show_chat_on_orders: observable, + has_chat_info: computed, + is_chat_frozen: computed, + last_other_user_activity: computed, + addChannelMessage: action.bound, + createChatForNewOrder: action.bound, + replaceChannelMessage: action.bound, + setActiveChatChannel: action.bound, + setChatChannelUrl: action.bound, + setChatInfo: action.bound, + setHasChatError: action.bound, + setIsChatLoading: action.bound, + setChannelMessages: action.bound, + setShouldShowChatModal: action.bound, + setShouldShowChatOnOrders: action.bound, + }); + } + get has_chat_info() { return this.chat_info.app_id && this.chat_info.user_id && this.chat_info.token; } - @computed get is_chat_frozen() { return this.active_chat_channel?.isFrozen; } - @computed get last_other_user_activity() { const message = this.chat_messages .slice() @@ -40,12 +67,10 @@ export default class SendbirdStore extends BaseStore { return message ? epochToMoment(Math.floor(message.created_at / 1000)).fromNow() : null; } - @action.bound addChannelMessage(chat_message) { this.chat_messages.push(chat_message); } - @action.bound createChatForNewOrder(id) { if (!this.chat_channel_url) { // If order_information doesn't have chat_channel_url this is a new order @@ -61,47 +86,38 @@ export default class SendbirdStore extends BaseStore { } } - @action.bound replaceChannelMessage(idx_to_replace, num_items_to_delete, chat_message) { this.chat_messages.splice(idx_to_replace, num_items_to_delete, chat_message); } - @action.bound setActiveChatChannel(active_chat_channel) { this.active_chat_channel = active_chat_channel; } - @action.bound setChatChannelUrl(chat_channel_url) { this.chat_channel_url = chat_channel_url; } - @action.bound setChatInfo(chat_info) { this.chat_info = chat_info; } - @action.bound setHasChatError(has_chat_error) { this.has_chat_error = has_chat_error; } - @action.bound setIsChatLoading(is_chat_loading) { this.is_chat_loading = is_chat_loading; } - @action.bound setChannelMessages(chat_messages) { this.chat_messages = chat_messages; } - @action.bound setShouldShowChatModal(should_show_chat_modal) { this.should_show_chat_modal = should_show_chat_modal; } - @action.bound setShouldShowChatOnOrders(should_show_chat_on_orders) { this.should_show_chat_on_orders = should_show_chat_on_orders; } diff --git a/packages/trader/package.json b/packages/trader/package.json index 8db946623708..6650c4b7165c 100644 --- a/packages/trader/package.json +++ b/packages/trader/package.json @@ -87,7 +87,7 @@ "@deriv/api-types": "1.0.48", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.8", - "@deriv/deriv-charts": "^0.6.0", + "@deriv/deriv-charts": "0.6.3", "@deriv/shared": "^1.0.0", "@deriv/translations": "^1.0.0", "@types/classnames": "^2.2.11", @@ -97,9 +97,9 @@ "formik": "^2.1.4", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", - "mobx": "^5.15.7", - "mobx-react": "6.3.1", - "mobx-utils": "^5.5.5", + "mobx": "6.5.0", + "mobx-react": "7.3.0", + "mobx-utils": "6.0.5", "moment": "^2.29.2", "null-loader": "^4.0.1", "prop-types": "^15.7.2", diff --git a/packages/trader/src/Stores/Modules/Contract/contract-replay-store.js b/packages/trader/src/Stores/Modules/Contract/contract-replay-store.js index a3150859cf5f..7a4abfd5a107 100644 --- a/packages/trader/src/Stores/Modules/Contract/contract-replay-store.js +++ b/packages/trader/src/Stores/Modules/Contract/contract-replay-store.js @@ -1,4 +1,4 @@ -import { action, observable } from 'mobx'; +import { action, observable, makeObservable, override } from 'mobx'; import { routes, isEmptyObject, isForwardStarting, WS } from '@deriv/shared'; import { localize } from '@deriv/translations'; import ContractStore from './contract-store'; @@ -6,31 +6,31 @@ import { contractCancelled, contractSold } from '../Portfolio/Helpers/portfolio- import BaseStore from '../../base-store'; export default class ContractReplayStore extends BaseStore { - @observable chart_state = ''; - @observable contract_store = { contract_info: {} }; + chart_state = ''; + contract_store = { contract_info: {} }; // --- Observable properties --- - @observable is_market_closed = false; - @observable is_sell_requested = false; - @observable has_error = false; - @observable error_message = ''; - @observable error_code = ''; - @observable is_chart_loading = true; - @observable is_chart_scaling = false; - @observable is_forward_starting = false; + is_market_closed = false; + is_sell_requested = false; + has_error = false; + error_message = ''; + error_code = ''; + is_chart_loading = true; + is_chart_scaling = false; + is_forward_starting = false; // ---- chart props - @observable margin; + margin; // ---- Replay Contract Config ---- - @observable contract_id; - @observable indicative_status; - @observable.ref contract_info = observable.object({}); - @observable is_static_chart = false; + contract_id; + indicative_status; + contract_info = observable.object({}); + is_static_chart = false; // ---- Normal properties --- is_ongoing_contract = false; prev_indicative = 0; - @observable.ref contract_update = observable.object({}); + contract_update = observable.object({}); // TODO: you view a contract and then share that link with another person, // when the person opens, try to switch account they get the error // Forget old proposal_open_contract stream on account switch from ErrorComponent @@ -62,7 +62,39 @@ export default class ContractReplayStore extends BaseStore { }); }; - @action.bound + constructor({ root_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ root_store }); + + makeObservable(this, { + chart_state: observable, + contract_store: observable, + is_market_closed: observable, + is_sell_requested: observable, + has_error: observable, + error_message: observable, + error_code: observable, + is_chart_loading: observable, + is_chart_scaling: observable, + is_forward_starting: observable, + margin: observable, + contract_id: observable, + indicative_status: observable, + contract_info: observable.ref, + is_static_chart: observable, + contract_update: observable.ref, + onMount: action.bound, + onUnmount: override, + populateConfig: action.bound, + updateMargin: action.bound, + chartStateChange: action.bound, + onClickCancel: action.bound, + onClickSell: action.bound, + handleSell: action.bound, + removeErrorMessage: action.bound, + }); + } + onMount(contract_id) { if (contract_id) { this.contract_id = contract_id; @@ -77,7 +109,6 @@ export default class ContractReplayStore extends BaseStore { } } - @action.bound onUnmount() { this.forgetProposalOpenContract(this.contract_id, this.populateConfig); this.contract_id = null; @@ -92,7 +123,6 @@ export default class ContractReplayStore extends BaseStore { WS.removeOnReconnect(); } - @action.bound populateConfig(response) { if (!this.switch_account_listener) return; @@ -159,14 +189,12 @@ export default class ContractReplayStore extends BaseStore { } } - @action.bound updateMargin(duration) { const granularity = this.contract_store.contract_config.granularity; this.margin = Math.floor(!granularity ? Math.max(300, (30 * duration) / (60 * 60) || 0) : 3 * granularity); } - @action.bound chartStateChange(state, option) { this.chart_state = state; const market_close_prop = 'isClosed'; @@ -208,7 +236,6 @@ export default class ContractReplayStore extends BaseStore { } } - @action.bound onClickCancel(contract_id) { if (contract_id) { WS.cancelContract(contract_id).then(response => { @@ -224,7 +251,6 @@ export default class ContractReplayStore extends BaseStore { } } - @action.bound onClickSell(contract_id) { const { bid_price } = this.contract_info; if (contract_id && bid_price) { @@ -233,7 +259,6 @@ export default class ContractReplayStore extends BaseStore { } } - @action.bound handleSell(response) { if (response.error) { // If unable to sell due to error, give error via pop up if not in contract mode @@ -262,7 +287,6 @@ export default class ContractReplayStore extends BaseStore { } }; - @action.bound removeErrorMessage() { this.error_message = ''; this.has_error = false; diff --git a/packages/trader/src/Stores/Modules/Contract/contract-store.js b/packages/trader/src/Stores/Modules/Contract/contract-store.js index 94f5bfe8457a..1d9583341c1a 100644 --- a/packages/trader/src/Stores/Modules/Contract/contract-store.js +++ b/packages/trader/src/Stores/Modules/Contract/contract-store.js @@ -1,4 +1,4 @@ -import { action, extendObservable, observable, toJS } from 'mobx'; +import { action, extendObservable, observable, toJS, makeObservable } from 'mobx'; import { isEnded, isEqualObject, @@ -24,45 +24,72 @@ export default class ContractStore extends BaseStore { validation_rules: getValidationRules(), }); + makeObservable(this, { + digits_info: observable, + sell_info: observable, + contract_config: observable.ref, + display_status: observable, + is_ended: observable, + is_digit_contract: observable, + error_message: observable, + contract_info: observable.ref, + is_static_chart: observable, + end_time: observable, + contract_update_take_profit: observable, + contract_update_stop_loss: observable, + has_contract_update_take_profit: observable, + has_contract_update_stop_loss: observable, + contract_update_history: observable.ref, + margin: observable, + barriers_array: observable.shallow, + markers_array: observable.shallow, + marker: observable.ref, + populateConfig: action.bound, + populateContractUpdateConfig: action.bound, + populateContractUpdateHistory: action.bound, + clearContractUpdateConfigValues: action.bound, + onChange: action.bound, + updateLimitOrder: action.bound + }); + this.root_store = root_store; this.contract_id = contract_id; } // --- Observable properties --- - @observable digits_info = observable.object({}); - @observable sell_info = observable.object({}); + digits_info = observable.object({}); + sell_info = observable.object({}); - @observable.ref contract_config = {}; - @observable display_status = 'purchased'; - @observable is_ended = false; - @observable is_digit_contract = false; + contract_config = {}; + display_status = 'purchased'; + is_ended = false; + is_digit_contract = false; // TODO: see how to handle errors. - @observable error_message = ''; + error_message = ''; - @observable.ref contract_info = observable.object({}); + contract_info = observable.object({}); - @observable is_static_chart = false; - @observable end_time = null; + is_static_chart = false; + end_time = null; // Multiplier contract update config - @observable contract_update_take_profit = ''; - @observable contract_update_stop_loss = ''; - @observable has_contract_update_take_profit = false; - @observable has_contract_update_stop_loss = false; - @observable.ref contract_update_history = []; + contract_update_take_profit = ''; + contract_update_stop_loss = ''; + has_contract_update_take_profit = false; + has_contract_update_stop_loss = false; + contract_update_history = []; contract_update_config = {}; // ---- chart props - @observable margin; - @observable.shallow barriers_array = []; - @observable.shallow markers_array = []; - @observable.ref marker = null; + margin; + barriers_array = []; + markers_array = []; + marker = null; // ---- Normal properties --- is_ongoing_contract = false; - @action.bound populateConfig(contract_info) { const prev_contract_info = this.contract_info; this.contract_info = contract_info; @@ -103,7 +130,6 @@ export default class ContractStore extends BaseStore { WS.storage.set({ proposal_open_contract: 1, contract_id }, response); }; - @action.bound populateContractUpdateConfig(response) { const contract_update_config = getContractUpdateConfig(response); if (!isEqualObject(this.contract_update_config, contract_update_config)) { @@ -117,7 +143,6 @@ export default class ContractStore extends BaseStore { } } - @action.bound populateContractUpdateHistory({ contract_update_history }) { this.root_store.modules.contract_replay.contract_store.contract_update_history = contract_update_history.sort( (a, b) => b.order_date - a.order_date @@ -172,20 +197,17 @@ export default class ContractStore extends BaseStore { return barriers; }; - @action.bound clearContractUpdateConfigValues() { Object.assign(this, getContractUpdateConfig(this.contract_info)); this.validation_errors.contract_update_stop_loss = []; this.validation_errors.contract_update_take_profit = []; } - @action.bound onChange({ name, value }) { this[name] = value; this.validateProperty(name, this[name]); } - @action.bound updateLimitOrder() { const limit_order = getLimitOrder(this); diff --git a/packages/trader/src/Stores/Modules/Contract/contract-trade-store.js b/packages/trader/src/Stores/Modules/Contract/contract-trade-store.js index a859122f4519..dda1c53efff4 100644 --- a/packages/trader/src/Stores/Modules/Contract/contract-trade-store.js +++ b/packages/trader/src/Stores/Modules/Contract/contract-trade-store.js @@ -1,4 +1,4 @@ -import { action, computed, observable, toJS } from 'mobx'; +import { action, computed, observable, toJS, makeObservable, override } from 'mobx'; import { isDesktop, isEnded, isMultiplierContract, LocalStore } from '@deriv/shared'; import { switch_to_tick_chart } from './Helpers/chart-notifications'; import ContractStore from './contract-store'; @@ -8,18 +8,35 @@ import BaseStore from '../../base-store'; export default class ContractTradeStore extends BaseStore { // --- Observable properties --- - @observable.shallow contracts = []; + contracts = []; contracts_map = {}; - @observable has_error = false; - @observable error_message = ''; + has_error = false; + error_message = ''; // Chart specific observables - @observable granularity = +LocalStore.get('contract_trade.granularity') || 0; - @observable chart_type = LocalStore.get('contract_trade.chart_type') || 'mountain'; + granularity = +LocalStore.get('contract_trade.granularity') || 0; + chart_type = LocalStore.get('contract_trade.chart_type') || 'mountain'; constructor({ root_store }) { - super({ - root_store, + super({ root_store }); + + makeObservable(this, { + contracts: observable.shallow, + has_error: observable, + error_message: observable, + granularity: observable, + chart_type: observable, + updateChartType: action.bound, + updateGranularity: action.bound, + markers_array: computed, + addContract: action.bound, + removeContract: action.bound, + accountSwitchListener: action.bound, + onUnmount: override, + updateProposal: action.bound, + last_contract: computed, + clearError: action.bound, + getContractById: action.bound, }); this.onSwitchAccount(this.accountSwitchListener); @@ -29,13 +46,11 @@ export default class ContractTradeStore extends BaseStore { // ----- Actions ----- // ------------------- - @action.bound updateChartType(type) { LocalStore.set('contract_trade.chart_type', type); this.chart_type = type; } - @action.bound updateGranularity(granularity) { const tick_chart_types = ['mountain', 'line', 'colored_line', 'spline', 'baseline']; if (granularity === 0 && tick_chart_types.indexOf(this.chart_type) === -1) { @@ -84,7 +99,6 @@ export default class ContractTradeStore extends BaseStore { }); }; - @computed get markers_array() { const markers = this.applicable_contracts() .map(c => c.marker) @@ -96,7 +110,6 @@ export default class ContractTradeStore extends BaseStore { return markers; } - @action.bound addContract({ barrier, contract_id, @@ -130,13 +143,11 @@ export default class ContractTradeStore extends BaseStore { } } - @action.bound removeContract({ contract_id }) { this.contracts = this.contracts.filter(c => c.contract_id !== contract_id); delete this.contracts_map[contract_id]; } - @action.bound accountSwitchListener() { if (this.has_error) { this.clearError(); @@ -145,14 +156,12 @@ export default class ContractTradeStore extends BaseStore { return Promise.resolve(); } - @action.bound onUnmount() { this.disposeSwitchAccount(); // TODO: don't forget the tick history when switching to contract-replay-store } // Called from portfolio - @action.bound updateProposal(response) { if ('error' in response) { this.has_error = true; @@ -171,20 +180,17 @@ export default class ContractTradeStore extends BaseStore { } } - @computed get last_contract() { const applicable_contracts = this.applicable_contracts(); const length = applicable_contracts.length; return length > 0 ? applicable_contracts[length - 1] : {}; } - @action.bound clearError() { this.error_message = ''; this.has_error = false; } - @action.bound getContractById(contract_id) { return ( this.contracts_map[contract_id] || diff --git a/packages/trader/src/Stores/Modules/Portfolio/portfolio-store.js b/packages/trader/src/Stores/Modules/Portfolio/portfolio-store.js index 14b3269ecd34..bde53b89e8f5 100644 --- a/packages/trader/src/Stores/Modules/Portfolio/portfolio-store.js +++ b/packages/trader/src/Stores/Modules/Portfolio/portfolio-store.js @@ -1,5 +1,5 @@ import throttle from 'lodash.throttle'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, makeObservable, override } from 'mobx'; import { createTransformer } from 'mobx-utils'; import { isEmptyObject, @@ -19,18 +19,54 @@ import { getEndTime } from '../Contract/Helpers/logic'; import BaseStore from '../../base-store'; export default class PortfolioStore extends BaseStore { - @observable.shallow positions = []; - @observable.shallow all_positions = []; + positions = []; + all_positions = []; positions_map = {}; - @observable is_loading = false; - @observable error = ''; + is_loading = false; + error = ''; getPositionById = createTransformer(id => this.positions.find(position => +position.id === +id)); responseQueue = []; - @observable.shallow active_positions = []; + active_positions = []; + + constructor({ root_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ root_store }); + + makeObservable(this, { + positions: observable.shallow, + all_positions: observable.shallow, + is_loading: observable, + error: observable, + active_positions: observable.shallow, + initializePortfolio: action.bound, + clearTable: action.bound, + portfolioHandler: action.bound, + onBuyResponse: action.bound, + transactionHandler: action.bound, + proposalOpenContractHandler: action.bound, + onClickCancel: action.bound, + onClickSell: action.bound, + handleSell: action.bound, + populateResultDetailsFromTransaction: action.bound, + populateResultDetails: action.bound, + populateContractUpdate: action.bound, + pushNewPosition: action.bound, + removePositionById: action.bound, + onHoverPosition: action.bound, + logoutListener: action.bound, + networkStatusChangeListener: action.bound, + onMount: action.bound, + onUnmount: override, + totals: computed, + setActivePositions: action.bound, + is_active_empty: computed, + active_positions_count: computed, + is_empty: computed, + }); + } - @action.bound async initializePortfolio() { if (this.has_subscribed_to_poc_and_transaction) { this.clearTable(); @@ -43,7 +79,6 @@ export default class PortfolioStore extends BaseStore { this.has_subscribed_to_poc_and_transaction = true; } - @action.bound clearTable() { this.positions = []; this.positions_map = {}; @@ -56,7 +91,6 @@ export default class PortfolioStore extends BaseStore { this.has_subscribed_to_poc_and_transaction = false; } - @action.bound portfolioHandler(response) { this.is_loading = false; if ('error' in response) { @@ -76,7 +110,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound onBuyResponse({ contract_id, longcode, contract_type }) { const new_pos = { contract_id, @@ -86,7 +119,6 @@ export default class PortfolioStore extends BaseStore { this.pushNewPosition(new_pos); } - @action.bound async transactionHandler(response) { if ('error' in response) { this.error = response.error.message; @@ -158,7 +190,6 @@ export default class PortfolioStore extends BaseStore { this.throttledUpdatePositions(); }; - @action.bound proposalOpenContractHandler(response) { if ('error' in response) { this.updateContractTradeStore(response); @@ -226,7 +257,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound onClickCancel(contract_id) { const i = this.getPositionIndexById(contract_id); if (this.positions[i].is_sell_requested) return; @@ -246,7 +276,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound onClickSell(contract_id) { const i = this.getPositionIndexById(contract_id); if (this.positions[i].is_sell_requested) return; @@ -258,7 +287,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound handleSell(response) { if (response.error) { // If unable to sell due to error, give error via pop up if not in contract mode @@ -284,7 +312,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound populateResultDetailsFromTransaction = response => { const transaction_response = response.transaction; const { contract_id, amount } = transaction_response; @@ -310,7 +337,6 @@ export default class PortfolioStore extends BaseStore { this.updatePositions(); }; - @action.bound populateResultDetails = response => { const contract_response = response.proposal_open_contract; const i = this.getPositionIndexById(contract_response.contract_id); @@ -342,7 +368,6 @@ export default class PortfolioStore extends BaseStore { this.positions[i].is_loading = false; }; - @action.bound populateContractUpdate({ contract_update }, contract_id) { const position = this.getPositionById(contract_id); if (position) { @@ -351,7 +376,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound pushNewPosition(new_pos) { const position = formatPortfolioPosition(new_pos, this.root_store.modules.trade.active_symbols); if (this.positions_map[position.id]) return; @@ -361,7 +385,6 @@ export default class PortfolioStore extends BaseStore { this.updatePositions(); } - @action.bound removePositionById(contract_id) { const contract_idx = this.getPositionIndexById(contract_id); @@ -376,7 +399,6 @@ export default class PortfolioStore extends BaseStore { return Promise.resolve(); } - @action.bound onHoverPosition(is_over, position) { const { symbol: underlying } = this.root_store.modules.trade; if ( @@ -396,18 +418,15 @@ export default class PortfolioStore extends BaseStore { return Promise.resolve(); } - @action.bound logoutListener() { this.clearTable(); return Promise.resolve(); } - @action.bound networkStatusChangeListener(is_online) { this.is_loading = !is_online; } - @action.bound onMount() { this.onPreSwitchAccount(this.preSwitchAccountListener); this.onSwitchAccount(this.accountSwitcherListener); @@ -430,7 +449,6 @@ export default class PortfolioStore extends BaseStore { } } - @action.bound onUnmount() { this.disposePreSwitchAccount(); this.disposeSwitchAccount(); @@ -442,7 +460,6 @@ export default class PortfolioStore extends BaseStore { return this.positions.findIndex(pos => +pos.id === +contract_id); } - @computed get totals() { let indicative = 0; let payout = 0; @@ -460,7 +477,6 @@ export default class PortfolioStore extends BaseStore { }; } - @action.bound setActivePositions() { this.active_positions = this.positions.filter(portfolio_pos => !getEndTime(portfolio_pos.contract_info)); this.all_positions = [...this.positions]; @@ -474,17 +490,14 @@ export default class PortfolioStore extends BaseStore { throttledUpdatePositions = throttle(this.updatePositions, 500); - @computed get is_active_empty() { return !this.is_loading && this.active_positions.length === 0; } - @computed get active_positions_count() { return this.active_positions.length || 0; } - @computed get is_empty() { return !this.is_loading && this.all_positions.length === 0; } diff --git a/packages/trader/src/Stores/Modules/Profit/profit-store.js b/packages/trader/src/Stores/Modules/Profit/profit-store.js index 00c4c07e137c..535d432f6e24 100644 --- a/packages/trader/src/Stores/Modules/Profit/profit-store.js +++ b/packages/trader/src/Stores/Modules/Profit/profit-store.js @@ -1,5 +1,5 @@ import debounce from 'lodash.debounce'; -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable, override } from 'mobx'; import { toMoment, WS } from '@deriv/shared'; import getDateBoundaries from './Helpers/format-request'; @@ -10,19 +10,48 @@ const batch_size = 50; const delay_on_scroll_time = 150; export default class ProfitTableStore extends BaseStore { - @observable data = []; - @observable date_from = null; - @observable date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); - @observable error = ''; - @observable has_loaded_all = false; - @observable is_loading = false; - @observable filtered_date_range; + data = []; + date_from = null; + date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); + error = ''; + has_loaded_all = false; + is_loading = false; + filtered_date_range; // `client_loginid` is only used to detect if this is in sync with the client-store, don't rely on // this for calculations. Use the client.currency instead. - @observable client_loginid = ''; + client_loginid = ''; + + constructor({ root_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ root_store }); + + makeObservable(this, { + data: observable, + date_from: observable, + date_to: observable, + error: observable, + has_loaded_all: observable, + is_loading: observable, + filtered_date_range: observable, + client_loginid: observable, + total_profit: computed, + is_empty: computed, + has_selected_date: computed, + fetchNextBatch: action.bound, + profitTableResponseHandler: action.bound, + handleScroll: action.bound, + networkStatusChangeListener: action.bound, + onMount: action.bound, + onUnmount: override, + totals: computed, + accountSwitcherListener: action.bound, + clearTable: action.bound, + clearDateFilter: action.bound, + handleDateChange: action.bound, + }); + } - @computed get total_profit() { return this.data.reduce((previous, current) => { const buy_price = Number(parseFloat(current.buy_price)); @@ -32,12 +61,10 @@ export default class ProfitTableStore extends BaseStore { }, 0); } - @computed get is_empty() { return !this.is_loading && this.data.length === 0; } - @computed get has_selected_date() { return !!(this.date_from || this.date_to); } @@ -47,7 +74,6 @@ export default class ProfitTableStore extends BaseStore { return true; } - @action.bound async fetchNextBatch() { if (!this.shouldFetchNextBatch()) return; this.is_loading = true; @@ -61,7 +87,6 @@ export default class ProfitTableStore extends BaseStore { this.profitTableResponseHandler(response); } - @action.bound profitTableResponseHandler(response) { if ('error' in response) { this.error = response.error.message; @@ -87,19 +112,16 @@ export default class ProfitTableStore extends BaseStore { } }, delay_on_scroll_time); - @action.bound handleScroll(event) { const { scrollTop, scrollHeight, clientHeight } = event.target; const left_to_scroll = scrollHeight - (scrollTop + clientHeight); this.fetchOnScroll(left_to_scroll); } - @action.bound networkStatusChangeListener(is_online) { this.is_loading = !is_online; } - @action.bound async onMount() { this.assertHasValidCache(this.client_loginid, this.clearDateFilter, WS.forgetAll.bind(null, 'proposal')); this.client_loginid = this.root_store.client.loginid; @@ -117,13 +139,11 @@ export default class ProfitTableStore extends BaseStore { /* DO NOT call clearDateFilter() upon unmounting the component, date filters should stay as we change tab or click on any contract for later references as discussed with UI/UX and QA */ - @action.bound onUnmount() { this.disposeSwitchAccount(); WS.forgetAll('proposal'); } - @computed get totals() { let profit_loss = 0; @@ -135,7 +155,6 @@ export default class ProfitTableStore extends BaseStore { }; } - @action.bound accountSwitcherListener() { return new Promise(resolve => { this.clearTable(); @@ -144,20 +163,17 @@ export default class ProfitTableStore extends BaseStore { }); } - @action.bound clearTable() { this.data = []; this.has_loaded_all = false; this.is_loading = false; } - @action.bound clearDateFilter() { this.date_from = null; this.date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); } - @action.bound handleDateChange(date_values, { date_range } = {}) { this.filtered_date_range = date_range; this.date_from = date_values?.from ?? (date_values.is_batch ? null : this.date_from); diff --git a/packages/trader/src/Stores/Modules/SmartChart/chart-barrier-store.js b/packages/trader/src/Stores/Modules/SmartChart/chart-barrier-store.js index 6f57838f9593..8f7174bc468e 100644 --- a/packages/trader/src/Stores/Modules/SmartChart/chart-barrier-store.js +++ b/packages/trader/src/Stores/Modules/SmartChart/chart-barrier-store.js @@ -1,27 +1,48 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, makeObservable } from 'mobx'; import { BARRIER_COLORS, BARRIER_LINE_STYLES, CONTRACT_SHADES, DEFAULT_SHADES } from './Constants/barriers'; import { barriersToString } from './Helpers/barriers'; export class ChartBarrierStore { - @observable color; - @observable lineStyle; - @observable shade; - @observable shadeColor; + color; + lineStyle; + shade; + shadeColor; - @observable high; - @observable low; + high; + low; - @observable relative; - @observable draggable; + relative; + draggable; - @observable hidePriceLines; - @observable hideBarrierLine; - @observable hideOffscreenLine; - @observable title; + hidePriceLines; + hideBarrierLine; + hideOffscreenLine; + title; onChartBarrierChange; constructor(high_barrier, low_barrier, onChartBarrierChange = null, { color, line_style, not_draggable } = {}) { + makeObservable(this, { + color: observable, + lineStyle: observable, + shade: observable, + shadeColor: observable, + high: observable, + low: observable, + relative: observable, + draggable: observable, + hidePriceLines: observable, + hideBarrierLine: observable, + hideOffscreenLine: observable, + title: observable, + updateBarriers: action.bound, + updateBarrierShade: action.bound, + onBarrierChange: action.bound, + updateBarrierColor: action.bound, + barrier_count: computed, + default_shade: computed + }); + this.color = color; this.lineStyle = line_style || BARRIER_LINE_STYLES.SOLID; this.onChange = this.onBarrierChange; @@ -43,7 +64,6 @@ export class ChartBarrierStore { this.hidePriceLines = !has_barrier; } - @action.bound updateBarriers(high, low, isFromChart = false) { if (!isFromChart) { this.relative = /^[+-]/.test(high); @@ -52,28 +72,23 @@ export class ChartBarrierStore { this.low = +low || undefined; } - @action.bound updateBarrierShade(should_display, contract_type) { this.shade = (should_display && CONTRACT_SHADES[contract_type]) || this.default_shade; } - @action.bound onBarrierChange({ high, low }) { this.updateBarriers(high, low, true); this.onChartBarrierChange(...barriersToString(this.relative, high, low)); } - @action.bound updateBarrierColor(is_dark_mode) { this.color = is_dark_mode ? BARRIER_COLORS.DARK_GRAY : BARRIER_COLORS.GRAY; } - @computed get barrier_count() { return (typeof this.high !== 'undefined') + (typeof this.low !== 'undefined'); } - @computed get default_shade() { return DEFAULT_SHADES[this.barrier_count]; } diff --git a/packages/trader/src/Stores/Modules/SmartChart/chart-marker-store.js b/packages/trader/src/Stores/Modules/SmartChart/chart-marker-store.js index 3248a1b09f8a..166a2dcf7f11 100644 --- a/packages/trader/src/Stores/Modules/SmartChart/chart-marker-store.js +++ b/packages/trader/src/Stores/Modules/SmartChart/chart-marker-store.js @@ -1,10 +1,15 @@ -import { observable } from 'mobx'; +import { observable, makeObservable } from 'mobx'; export class ChartMarkerStore { - @observable marker_config = observable.object({}); - @observable content_config = observable.object({}); + marker_config = observable.object({}); + content_config = observable.object({}); constructor(marker_config, content_config) { + makeObservable(this, { + marker_config: observable, + content_config: observable + }); + this.marker_config = marker_config; this.content_config = content_config; } diff --git a/packages/trader/src/Stores/Modules/Statement/statement-store.js b/packages/trader/src/Stores/Modules/Statement/statement-store.js index c7b70a83c6ed..0cd4f87badfc 100644 --- a/packages/trader/src/Stores/Modules/Statement/statement-store.js +++ b/packages/trader/src/Stores/Modules/Statement/statement-store.js @@ -1,5 +1,5 @@ import debounce from 'lodash.debounce'; -import { action, computed, observable, runInAction } from 'mobx'; +import { action, computed, observable, runInAction, makeObservable, override } from 'mobx'; import { toMoment, WS } from '@deriv/shared'; import { formatStatementTransaction } from './Helpers/format-response'; @@ -10,39 +10,67 @@ const batch_size = 100; // request response limit const delay_on_scroll_time = 150; // fetch debounce delay on scroll export default class StatementStore extends BaseStore { - @observable data = []; - @observable is_loading = false; - @observable has_loaded_all = false; - @observable date_from = null; - @observable date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); - @observable error = ''; - @observable action_type = 'all'; - @observable filtered_date_range; + data = []; + is_loading = false; + has_loaded_all = false; + date_from = null; + date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); + error = ''; + action_type = 'all'; + filtered_date_range; // `client_loginid` is only used to detect if this is in sync with the client-store, don't rely on // this for calculations. Use the client.currency instead. - @observable client_loginid = ''; - - @observable account_statistics = {}; + client_loginid = ''; + + account_statistics = {}; + + constructor({ root_store }) { + // TODO: [mobx-undecorate] verify the constructor arguments and the arguments of this automatically generated super call + super({ root_store }); + + makeObservable(this, { + data: observable, + is_loading: observable, + has_loaded_all: observable, + date_from: observable, + date_to: observable, + error: observable, + action_type: observable, + filtered_date_range: observable, + client_loginid: observable, + account_statistics: observable, + is_empty: computed, + has_selected_date: computed, + clearTable: action.bound, + clearDateFilter: action.bound, + fetchNextBatch: action.bound, + statementHandler: action.bound, + handleDateChange: action.bound, + handleFilterChange: action.bound, + handleScroll: action.bound, + loadAccountStatistics: action.bound, + accountSwitcherListener: action.bound, + networkStatusChangeListener: action.bound, + onMount: action.bound, + onUnmount: override, + }); + } - @computed get is_empty() { return !this.is_loading && this.data.length === 0; } - @computed get has_selected_date() { return !!(this.date_from || this.date_to); } - @action.bound clearTable() { this.data = []; this.has_loaded_all = false; this.is_loading = false; } - @action.bound clearDateFilter() { this.date_from = null; this.date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); @@ -56,7 +84,6 @@ export default class StatementStore extends BaseStore { return true; } - @action.bound async fetchNextBatch(should_load_partially = false) { if (!this.shouldFetchNextBatch(should_load_partially)) return; this.is_loading = true; @@ -80,7 +107,6 @@ export default class StatementStore extends BaseStore { this.statementHandler(response, should_load_partially); } - @action.bound statementHandler(response, should_load_partially) { if ('error' in response) { this.error = response.error.message; @@ -107,7 +133,6 @@ export default class StatementStore extends BaseStore { } } - @action.bound handleDateChange(date_values, { date_range } = {}) { this.filtered_date_range = date_range; this.date_from = date_values?.from ?? (date_values.is_batch ? null : this.date_from); @@ -116,7 +141,6 @@ export default class StatementStore extends BaseStore { this.fetchNextBatch(); } - @action.bound handleFilterChange(filterValue = {}) { this.action_type = filterValue; this.clearTable(); @@ -129,7 +153,6 @@ export default class StatementStore extends BaseStore { } }, delay_on_scroll_time); - @action.bound handleScroll(event) { const { scrollTop, scrollHeight, clientHeight } = event.target; const left_to_scroll = scrollHeight - (scrollTop + clientHeight); @@ -137,7 +160,6 @@ export default class StatementStore extends BaseStore { this.fetchOnScroll(left_to_scroll); } - @action.bound async loadAccountStatistics() { this.account_statistics = {}; const { client } = this.root_store; @@ -155,7 +177,6 @@ export default class StatementStore extends BaseStore { } } - @action.bound accountSwitcherListener() { return new Promise(resolve => { this.clearTable(); @@ -165,12 +186,10 @@ export default class StatementStore extends BaseStore { }); } - @action.bound networkStatusChangeListener(is_online) { this.is_loading = !is_online; } - @action.bound async onMount() { this.assertHasValidCache( this.client_loginid, @@ -188,7 +207,6 @@ export default class StatementStore extends BaseStore { /* DO NOT call clearDateFilter() upon unmounting the component, date filters should stay as we change tab or click on any contract for later references as discussed with UI/UX and QA */ - @action.bound onUnmount() { this.disposeSwitchAccount(); WS.forgetAll('proposal'); diff --git a/packages/trader/src/Stores/Modules/Trading/trade-store.js b/packages/trader/src/Stores/Modules/Trading/trade-store.js index cfe59ac1fece..505102defec1 100644 --- a/packages/trader/src/Stores/Modules/Trading/trade-store.js +++ b/packages/trader/src/Stores/Modules/Trading/trade-store.js @@ -1,5 +1,5 @@ import debounce from 'lodash.debounce'; -import { action, computed, observable, reaction, runInAction, toJS, when } from 'mobx'; +import { action, computed, observable, reaction, runInAction, toJS, when, makeObservable, override } from 'mobx'; import { cloneObject, extractInfoFromShortcode, @@ -42,56 +42,56 @@ const g_subscribers_map = {}; // blame amin.m export default class TradeStore extends BaseStore { // Control values - @observable is_trade_component_mounted = false; - @observable is_purchase_enabled = false; - @observable is_trade_enabled = false; - @observable is_equal = 0; - @observable has_equals_only = false; + is_trade_component_mounted = false; + is_purchase_enabled = false; + is_trade_enabled = false; + is_equal = 0; + has_equals_only = false; // Underlying - @observable symbol; - @observable is_market_closed = false; - @observable previous_symbol = ''; - @observable active_symbols = []; + symbol; + is_market_closed = false; + previous_symbol = ''; + active_symbols = []; - @observable form_components = []; + form_components = []; // Contract Type - @observable contract_expiry_type = ''; - @observable contract_start_type = ''; - @observable contract_type = ''; - @observable contract_types_list = {}; - @observable trade_types = {}; + contract_expiry_type = ''; + contract_start_type = ''; + contract_type = ''; + contract_types_list = {}; + trade_types = {}; // Amount - @observable amount = 10; - @observable basis = ''; - @observable basis_list = []; - @observable currency = ''; + amount = 10; + basis = ''; + basis_list = []; + currency = ''; // Duration - @observable duration = 5; - @observable duration_unit = ''; - @observable duration_units_list = []; - @observable duration_min_max = {}; - @observable expiry_date = ''; - @observable expiry_time = ''; - @observable expiry_type = 'duration'; + duration = 5; + duration_unit = ''; + duration_units_list = []; + duration_min_max = {}; + expiry_date = ''; + expiry_time = ''; + expiry_type = 'duration'; // Barrier - @observable barrier_1 = ''; - @observable barrier_2 = ''; - @observable barrier_count = 0; - @observable main_barrier = null; - @observable barriers = []; + barrier_1 = ''; + barrier_2 = ''; + barrier_count = 0; + main_barrier = null; + barriers = []; // Start Time - @observable start_date = Number(0); // Number(0) refers to 'now' - @observable start_dates_list = []; - @observable start_time = null; - @observable sessions = []; + start_date = Number(0); // Number(0) refers to 'now' + start_dates_list = []; + start_time = null; + sessions = []; - @observable market_open_times = []; + market_open_times = []; // End Date Time /** * An array that contains market closing time. @@ -99,38 +99,38 @@ export default class TradeStore extends BaseStore { * e.g. ["04:00:00", "08:00:00"] * */ - @observable market_close_times = []; + market_close_times = []; // Last Digit - @observable last_digit = 5; - @observable is_mobile_digit_view_selected = false; + last_digit = 5; + is_mobile_digit_view_selected = false; // Purchase - @observable.ref proposal_info = {}; - @observable.ref purchase_info = {}; + proposal_info = {}; + purchase_info = {}; // Chart loader observables - @observable is_chart_loading; - @observable should_show_active_symbols_loading = false; + is_chart_loading; + should_show_active_symbols_loading = false; // Multiplier trade params - @observable multiplier; - @observable multiplier_range_list = []; - @observable stop_loss; - @observable take_profit; - @observable has_stop_loss = false; - @observable has_take_profit = false; - @observable has_cancellation = false; - @observable commission; - @observable cancellation_price; - @observable stop_out; - @observable expiration; - @observable hovered_contract_type; - @observable cancellation_duration = '60m'; - @observable cancellation_range_list = []; + multiplier; + multiplier_range_list = []; + stop_loss; + take_profit; + has_stop_loss = false; + has_take_profit = false; + has_cancellation = false; + commission; + cancellation_price; + stop_out; + expiration; + hovered_contract_type; + cancellation_duration = '60m'; + cancellation_range_list = []; // Mobile - @observable is_trade_params_expanded = true; + is_trade_params_expanded = true; addTickByProposal = () => null; debouncedProposal = debounce(this.requestProposal, 500); @@ -140,7 +140,7 @@ export default class TradeStore extends BaseStore { initial_barriers; is_initial_barrier_applied = false; - @observable should_skip_prepost_lifecycle = false; + should_skip_prepost_lifecycle = false; constructor({ root_store }) { const local_storage_properties = [ @@ -175,6 +175,126 @@ export default class TradeStore extends BaseStore { validation_rules: getValidationRules(), }); + makeObservable(this, { + is_trade_component_mounted: observable, + is_purchase_enabled: observable, + is_trade_enabled: observable, + is_equal: observable, + has_equals_only: observable, + symbol: observable, + is_market_closed: observable, + previous_symbol: observable, + active_symbols: observable, + form_components: observable, + contract_expiry_type: observable, + contract_start_type: observable, + contract_type: observable, + contract_types_list: observable, + trade_types: observable, + amount: observable, + basis: observable, + basis_list: observable, + currency: observable, + duration: observable, + duration_unit: observable, + duration_units_list: observable, + duration_min_max: observable, + expiry_date: observable, + expiry_time: observable, + expiry_type: observable, + barrier_1: observable, + barrier_2: observable, + barrier_count: observable, + main_barrier: observable, + barriers: observable, + start_date: observable, + start_dates_list: observable, + start_time: observable, + sessions: observable, + market_open_times: observable, + market_close_times: observable, + last_digit: observable, + is_mobile_digit_view_selected: observable, + proposal_info: observable.ref, + purchase_info: observable.ref, + is_chart_loading: observable, + should_show_active_symbols_loading: observable, + multiplier: observable, + multiplier_range_list: observable, + stop_loss: observable, + take_profit: observable, + has_stop_loss: observable, + has_take_profit: observable, + has_cancellation: observable, + commission: observable, + cancellation_price: observable, + stop_out: observable, + expiration: observable, + hovered_contract_type: observable, + cancellation_duration: observable, + cancellation_range_list: observable, + is_trade_params_expanded: observable, + should_skip_prepost_lifecycle: observable, + is_symbol_in_active_symbols: computed, + setSkipPrePostLifecycle: action.bound, + setTradeStatus: action.bound, + refresh: action.bound, + clearContracts: action.bound, + loadActiveSymbols: action.bound, + setDefaultSymbol: action.bound, + setActiveSymbols: action.bound, + setContractTypes: action.bound, + prepareTradeStore: action.bound, + onChangeMultiple: action.bound, + onChange: action.bound, + setPreviousSymbol: action.bound, + setAllowEqual: action.bound, + setIsTradeParamsExpanded: action.bound, + resetPreviousSymbol: action.bound, + updateBarrierColor: action.bound, + onHoverPurchase: action.bound, + setPurchaseSpotBarrier: action.bound, + updateLimitOrderBarriers: action.bound, + clearLimitOrderBarriers: action.bound, + barrier_pipsize: computed, + main_barrier_flattened: computed, + barriers_flattened: computed, + onPurchase: action.bound, + processPurchase: action.bound, + enablePurchase: action.bound, + updateStore: action.bound, + is_synthetics_available: computed, + show_digits_stats: computed, + setMobileDigitView: action.bound, + pushPurchaseDataToGtm: action.bound, + clearPurchaseInfo: action.bound, + requestProposal: action.bound, + forgetAllProposal: action.bound, + setMarketStatus: action.bound, + onProposalResponse: action.bound, + onChartBarrierChange: action.bound, + onAllowEqualsChange: action.bound, + updateSymbol: action.bound, + changeDurationValidationRules: action.bound, + accountSwitcherListener: action.bound, + preSwitchAccountListener: action.bound, + logoutListener: action.bound, + clientInitListener: action.bound, + networkStatusChangeListener: action.bound, + themeChangeListener: action.bound, + resetErrorServices: action.bound, + onMount: action.bound, + manageMxMltRemovalNotification: action.bound, + setChartStatus: action.bound, + initAccountCurrency: action.bound, + onUnmount: override, + exportLayout: action.bound, + chartStateChange: action.bound, + has_alternative_source: computed, + is_multiplier: computed, + getFirstOpenMarket: action.bound, + }); + // Adds intercept to change min_max value of duration validation reaction( () => [this.contract_expiry_type, this.duration_min_max, this.duration_unit, this.expiry_type], @@ -230,14 +350,12 @@ export default class TradeStore extends BaseStore { ); } - @computed get is_symbol_in_active_symbols() { return this.active_symbols.some( symbol_info => symbol_info.symbol === this.symbol && symbol_info.exchange_is_open === 1 ); } - @action.bound setSkipPrePostLifecycle(should_skip) { if (!!should_skip !== !!this.should_skip_prepost_lifecycle) { // to skip assignment if no change is made @@ -245,12 +363,10 @@ export default class TradeStore extends BaseStore { } } - @action.bound setTradeStatus(status) { this.is_trade_enabled = status; } - @action.bound refresh() { this.forgetAllProposal(); this.proposal_info = {}; @@ -258,12 +374,10 @@ export default class TradeStore extends BaseStore { this.proposal_requests = {}; } - @action.bound clearContracts = () => { this.root_store.modules.contract_trade.contracts = []; }; - @action.bound async loadActiveSymbols(should_set_default_symbol = true, should_show_loading = true) { this.should_show_active_symbols_loading = should_show_loading; @@ -281,7 +395,6 @@ export default class TradeStore extends BaseStore { }); } - @action.bound async setDefaultSymbol() { if (!this.is_symbol_in_active_symbols) { this.is_trade_enabled = false; @@ -291,7 +404,6 @@ export default class TradeStore extends BaseStore { } } - @action.bound async setActiveSymbols() { const is_on_mf_account = this.root_store.client.landing_company_shortcode === 'maltainvest'; const hide_close_mx_mlt_storage_flag = !!parseInt( @@ -357,7 +469,6 @@ export default class TradeStore extends BaseStore { await this.processNewValuesAsync({ active_symbols }); } - @action.bound async setContractTypes() { if (this.symbol && this.is_symbol_in_active_symbols) { await Symbol.onChangeSymbolAsync(this.symbol); @@ -373,7 +484,6 @@ export default class TradeStore extends BaseStore { this.root_store.common.setSelectedContractType(this.contract_type); } - @action.bound async prepareTradeStore(should_set_default_symbol = true) { this.initial_barriers = { barrier_1: this.barrier_1, barrier_2: this.barrier_2 }; await when(() => !this.root_store.client.is_populating_account_list); @@ -404,7 +514,6 @@ export default class TradeStore extends BaseStore { ); } - @action.bound async onChangeMultiple(values) { Object.keys(values).forEach(name => { if (!(name in this)) { @@ -416,7 +525,6 @@ export default class TradeStore extends BaseStore { this.validateAllProperties(); // then run validation before sending proposal } - @action.bound async onChange(e) { const { name, value } = e.target; @@ -449,22 +557,18 @@ export default class TradeStore extends BaseStore { this.root_store.common.setSelectedContractType(this.contract_type); } - @action.bound setPreviousSymbol(symbol) { if (this.previous_symbol !== symbol) this.previous_symbol = symbol; } - @action.bound setAllowEqual(is_equal) { this.is_equal = is_equal; } - @action.bound setIsTradeParamsExpanded(value) { this.is_trade_params_expanded = value; } - @action.bound async resetPreviousSymbol() { this.setMarketStatus(isMarketClosed(this.active_symbols, this.previous_symbol)); @@ -477,14 +581,12 @@ export default class TradeStore extends BaseStore { }); } - @action.bound updateBarrierColor(is_dark_mode) { if (this.main_barrier) { this.main_barrier.updateBarrierColor(is_dark_mode); } } - @action.bound onHoverPurchase(is_over, contract_type) { if (this.is_purchase_enabled && this.main_barrier && !this.is_multiplier) { this.main_barrier.updateBarrierShade(is_over, contract_type); @@ -501,7 +603,6 @@ export default class TradeStore extends BaseStore { }); } - @action.bound setPurchaseSpotBarrier(is_over, position) { const key = 'PURCHASE_SPOT_BARRIER'; if (!is_over) { @@ -527,7 +628,6 @@ export default class TradeStore extends BaseStore { } } - @action.bound updateLimitOrderBarriers(is_over, position) { const contract_info = position.contract_info; const { barriers } = this; @@ -539,7 +639,6 @@ export default class TradeStore extends BaseStore { }); } - @action.bound clearLimitOrderBarriers() { this.hovered_contract_type = null; const { barriers } = this; @@ -549,18 +648,15 @@ export default class TradeStore extends BaseStore { }); } - @computed get barrier_pipsize() { return getBarrierPipSize(this.barrier_1); } - @computed get main_barrier_flattened() { const is_digit_trade_type = isDigitTradeType(this.contract_type); return is_digit_trade_type ? null : toJS(this.main_barrier); } - @computed get barriers_flattened() { return this.barriers && toJS(this.barriers); } @@ -583,10 +679,8 @@ export default class TradeStore extends BaseStore { } }; - @action.bound onPurchase = debounce(this.processPurchase, 300); - @action.bound processPurchase(proposal_id, price, type) { if (!this.is_purchase_enabled) return; if (proposal_id) { @@ -684,7 +778,6 @@ export default class TradeStore extends BaseStore { } } - @action.bound enablePurchase() { if (!this.root_store.client.is_unwelcome) { this.is_purchase_enabled = true; @@ -707,7 +800,6 @@ export default class TradeStore extends BaseStore { * @param {Object} new_state - new values to update the store with * @return {Object} returns the object having only those values that are updated */ - @action.bound updateStore(new_state) { Object.keys(cloneObject(new_state) || {}).forEach(key => { if (key === 'root_store' || ['validation_rules', 'validation_errors', 'currency'].indexOf(key) > -1) return; @@ -823,22 +915,18 @@ export default class TradeStore extends BaseStore { } } - @computed get is_synthetics_available() { return !!this.active_symbols?.find(item => item.market === 'synthetic_index'); } - @computed get show_digits_stats() { return isDigitTradeType(this.contract_type); } - @action.bound setMobileDigitView(bool) { this.is_mobile_digit_view_selected = bool; } - @action.bound pushPurchaseDataToGtm(contract_data) { const data = { event: 'buy_contract', @@ -872,14 +960,12 @@ export default class TradeStore extends BaseStore { this.root_store.gtm.pushDataLayer(data); } - @action.bound clearPurchaseInfo() { this.purchase_info = {}; this.proposal_requests = {}; this.proposal_info = {}; } - @action.bound requestProposal() { const requests = createProposalRequests(this); @@ -901,18 +987,15 @@ export default class TradeStore extends BaseStore { this.root_store.ui.resetPurchaseStates(); } - @action.bound forgetAllProposal() { const length = Object.keys(this.proposal_requests).length; if (length > 0) WS.forgetAll('proposal'); } - @action.bound setMarketStatus(status) { this.is_market_closed = status; } - @action.bound onProposalResponse(response) { const contract_type = response.echo_req.contract_type; const prev_proposal_info = getPropertyValue(this.proposal_info, contract_type) || {}; @@ -993,17 +1076,14 @@ export default class TradeStore extends BaseStore { } } - @action.bound onChartBarrierChange(barrier_1, barrier_2) { this.processNewValuesAsync({ barrier_1, barrier_2 }, true); } - @action.bound onAllowEqualsChange() { this.processNewValuesAsync({ contract_type: parseInt(this.is_equal) ? 'rise_fall_equal' : 'rise_fall' }, true); } - @action.bound updateSymbol(underlying) { if (!underlying) return; this.onChange({ @@ -1014,7 +1094,6 @@ export default class TradeStore extends BaseStore { }); } - @action.bound changeDurationValidationRules() { if (this.expiry_type === 'endtime') { this.validation_errors.duration = []; @@ -1041,7 +1120,6 @@ export default class TradeStore extends BaseStore { } } - @action.bound async accountSwitcherListener() { await this.loadActiveSymbols(true, false); @@ -1058,14 +1136,12 @@ export default class TradeStore extends BaseStore { return Promise.resolve(); } - @action.bound preSwitchAccountListener() { this.clearContracts(); this.is_trade_enabled = false; return Promise.resolve(); } - @action.bound async logoutListener() { this.clearContracts(); this.refresh(); @@ -1075,28 +1151,23 @@ export default class TradeStore extends BaseStore { this.debouncedProposal(); } - @action.bound clientInitListener() { this.initAccountCurrency(this.root_store.client.currency || this.root_store.client.default_currency); return Promise.resolve(); } - @action.bound networkStatusChangeListener(is_online) { this.setTradeStatus(is_online); } - @action.bound themeChangeListener(is_dark_mode_on) { this.updateBarrierColor(is_dark_mode_on); } - @action.bound resetErrorServices() { this.root_store.ui.toggleServicesErrorModal(false); } - @action.bound onMount() { if (this.is_trade_component_mounted && this.should_skip_prepost_lifecycle) { return; @@ -1118,7 +1189,6 @@ export default class TradeStore extends BaseStore { this.manageMxMltRemovalNotification(); } - @action.bound manageMxMltRemovalNotification() { const { addNotificationMessage, client_notifications, notification_messages, unmarkNotificationMessage } = this.root_store.notifications; @@ -1141,12 +1211,10 @@ export default class TradeStore extends BaseStore { } } - @action.bound setChartStatus(status) { this.is_chart_loading = status; } - @action.bound async initAccountCurrency(new_currency) { if (this.currency === new_currency) return; @@ -1155,7 +1223,6 @@ export default class TradeStore extends BaseStore { this.debouncedProposal(); } - @action.bound onUnmount() { if (this.should_skip_prepost_lifecycle) { return; @@ -1193,7 +1260,6 @@ export default class TradeStore extends BaseStore { return this.contract_type === 'multiplier' && /^cry/.test(this.symbol); } - @action.bound exportLayout(layout) { delete layout.previousMaxTicks; // TODO: fix it in smartcharts this.prev_chart_layout = layout; @@ -1246,7 +1312,6 @@ export default class TradeStore extends BaseStore { return WS.storage.send(req); }; - @action.bound chartStateChange(state, option) { const market_close_prop = 'isClosed'; switch (state) { @@ -1264,17 +1329,14 @@ export default class TradeStore extends BaseStore { this.addTickByProposal = ref; }; - @computed get has_alternative_source() { return this.is_multiplier && !!this.hovered_contract_type; } - @computed get is_multiplier() { return this.contract_type === 'multiplier'; } - @action.bound async getFirstOpenMarket(markets_to_search) { if (this.active_symbols?.length) { return findFirstOpenMarket(this.active_symbols, markets_to_search); diff --git a/packages/trader/src/Stores/base-store.js b/packages/trader/src/Stores/base-store.js index 7953bcce6ce6..f9dbcbe80390 100644 --- a/packages/trader/src/Stores/base-store.js +++ b/packages/trader/src/Stores/base-store.js @@ -1,4 +1,4 @@ -import { action, intercept, observable, reaction, toJS, when } from 'mobx'; +import { action, intercept, observable, reaction, toJS, when, makeObservable, isObservable } from 'mobx'; import { isProduction, isEmptyObject } from '@deriv/shared'; import Validator from 'Utils/Validator'; @@ -17,10 +17,8 @@ export default class BaseStore { SESSION_STORAGE: Symbol('SESSION_STORAGE'), }); - @observable validation_errors = {}; - @observable validation_rules = {}; preSwitchAccountDisposer = null; @@ -44,7 +42,7 @@ export default class BaseStore { realAccountSignupEndedDisposer = null; real_account_signup_ended_listener = null; - @observable partial_fetch_time = 0; + partial_fetch_time = 0; /** * Constructor of the base class that gets properties' name of child which should be saved in storages @@ -57,6 +55,34 @@ export default class BaseStore { * @property {String} store_name - Explicit store name for browser application storage (to bypass minification) */ constructor(options = {}) { + makeObservable(this, { + validation_errors: observable, + validation_rules: observable, + partial_fetch_time: observable, + retrieveFromStorage: action, + setValidationErrorMessages: action, + setValidationRules: action, + addRule: action, + validateProperty: action, + validateAllProperties: action, + onSwitchAccount: action.bound, + onPreSwitchAccount: action.bound, + onLogout: action.bound, + onClientInit: action.bound, + onNetworkStatusChange: action.bound, + onThemeChange: action.bound, + onRealAccountSignupEnd: action.bound, + disposePreSwitchAccount: action.bound, + disposeSwitchAccount: action.bound, + disposeLogout: action.bound, + disposeClientInit: action.bound, + disposeNetworkStatusChange: action.bound, + disposeThemeChange: action.bound, + disposeRealAccountSignupEnd: action.bound, + onUnmount: action.bound, + assertHasValidCache: action.bound, + }); + const { root_store, local_storage_properties, session_storage_properties, validation_rules, store_name } = options; @@ -172,7 +198,6 @@ export default class BaseStore { * Retrieves saved snapshot of the store and assigns to the current instance. * */ - @action retrieveFromStorage() { const local_storage_snapshot = JSON.parse(localStorage.getItem(this.store_name, {})); const session_storage_snapshot = JSON.parse(sessionStorage.getItem(this.store_name, {})); @@ -189,7 +214,6 @@ export default class BaseStore { * @param [{String}] messages - An array of strings that contains validation error messages for the particular property. * */ - @action setValidationErrorMessages(propertyName, messages) { const is_different = () => !!this.validation_errors[propertyName] @@ -206,7 +230,6 @@ export default class BaseStore { * @param {object} rules * */ - @action setValidationRules(rules = {}) { Object.keys(rules).forEach(key => { this.addRule(key, rules[key]); @@ -220,14 +243,14 @@ export default class BaseStore { * @param {String} rules * */ - @action addRule(property, rules) { this.validation_rules[property] = rules; - - intercept(this, property, change => { - this.validateProperty(property, change.newValue); - return change; - }); + if (isObservable(this[property])) { + intercept(this, property, change => { + this.validateProperty(property, change.newValue); + return change; + }); + } } /** @@ -237,7 +260,6 @@ export default class BaseStore { * @param {object} value - The value of the property, it can be undefined. * */ - @action validateProperty(property, value) { const trigger = this.validation_rules[property].trigger; const inputs = { [property]: value !== undefined ? value : this[property] }; @@ -261,7 +283,6 @@ export default class BaseStore { * Validates all properties which validation rule has been set for. * */ - @action validateAllProperties() { const validation_rules = Object.keys(this.validation_rules); const validation_errors = Object.keys(this.validation_errors); @@ -278,7 +299,6 @@ export default class BaseStore { }); } - @action.bound onSwitchAccount(listener) { if (listener) { this.switch_account_listener = listener; @@ -308,7 +328,6 @@ export default class BaseStore { } } - @action.bound onPreSwitchAccount(listener) { if (listener) { this.pre_switch_account_listener = listener; @@ -337,7 +356,6 @@ export default class BaseStore { } } - @action.bound onLogout(listener) { this.logoutDisposer = when( () => this.root_store.client.has_logged_out, @@ -364,7 +382,6 @@ export default class BaseStore { this.logout_listener = listener; } - @action.bound onClientInit(listener) { this.clientInitDisposer = when( () => this.root_store.client.initialized_broadcast, @@ -391,7 +408,6 @@ export default class BaseStore { this.client_init_listener = listener; } - @action.bound onNetworkStatusChange(listener) { this.networkStatusChangeDisposer = reaction( () => this.root_store.common.is_network_online, @@ -411,7 +427,6 @@ export default class BaseStore { this.network_status_change_listener = listener; } - @action.bound onThemeChange(listener) { this.themeChangeDisposer = reaction( () => this.root_store.ui.is_dark_mode_on, @@ -431,7 +446,6 @@ export default class BaseStore { this.theme_change_listener = listener; } - @action.bound onRealAccountSignupEnd(listener) { this.realAccountSignupEndedDisposer = when( () => this.root_store.ui.has_real_account_signup_ended, @@ -459,7 +473,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = listener; } - @action.bound disposePreSwitchAccount() { if (typeof this.preSwitchAccountDisposer === 'function') { this.preSwitchAccountDisposer(); @@ -467,7 +480,6 @@ export default class BaseStore { this.pre_switch_account_listener = null; } - @action.bound disposeSwitchAccount() { if (typeof this.switchAccountDisposer === 'function') { this.switchAccountDisposer(); @@ -475,7 +487,6 @@ export default class BaseStore { this.switch_account_listener = null; } - @action.bound disposeLogout() { if (typeof this.logoutDisposer === 'function') { this.logoutDisposer(); @@ -483,7 +494,6 @@ export default class BaseStore { this.logout_listener = null; } - @action.bound disposeClientInit() { if (typeof this.clientInitDisposer === 'function') { this.clientInitDisposer(); @@ -491,7 +501,6 @@ export default class BaseStore { this.client_init_listener = null; } - @action.bound disposeNetworkStatusChange() { if (typeof this.networkStatusChangeDisposer === 'function') { this.networkStatusChangeDisposer(); @@ -499,7 +508,6 @@ export default class BaseStore { this.network_status_change_listener = null; } - @action.bound disposeThemeChange() { if (typeof this.themeChangeDisposer === 'function') { this.themeChangeDisposer(); @@ -507,7 +515,6 @@ export default class BaseStore { this.theme_change_listener = null; } - @action.bound disposeRealAccountSignupEnd() { if (typeof this.realAccountSignupEndedDisposer === 'function') { this.realAccountSignupEndedDisposer(); @@ -515,7 +522,6 @@ export default class BaseStore { this.real_account_signup_ended_listener = null; } - @action.bound onUnmount() { this.disposePreSwitchAccount(); this.disposeSwitchAccount(); @@ -526,7 +532,6 @@ export default class BaseStore { this.disposeRealAccountSignupEnd(); } - @action.bound assertHasValidCache(loginid, ...reactions) { // account was changed when this was unmounted. if (this.root_store.client.loginid !== loginid) {