Skip to content

Commit

Permalink
Suisin/chore: implement session account switching in dtrader and trad…
Browse files Browse the repository at this point in the history
…ershub (#18085)

* chore: implement session account switching in dtrader and tradershub

* chore: fix failing test cases
  • Loading branch information
suisin-deriv authored Mar 3, 2025
1 parent 37d75fe commit 18cf193
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 15 deletions.
1 change: 1 addition & 0 deletions packages/api-v2/src/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ const AuthProvider = ({ loginIDKey, children, cookieTimeout, selectDefaultAccoun
if (!activeAccount) return;

localStorage.setItem(loginIDKey ?? 'active_loginid', activeLoginID);
sessionStorage.setItem(loginIDKey ?? 'active_loginid', activeLoginID);
const isDemo = activeAccount.is_virtual;
const shouldCreateNewWSConnection =
(isDemo && wsClient?.endpoint === AppIDConstants.environments.real) ||
Expand Down
3 changes: 2 additions & 1 deletion packages/api/src/APIProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ type TAPIProviderProps = {
const APIProvider = ({ children, standalone = false }: PropsWithChildren<TAPIProviderProps>) => {
const WS = useWS();
const [reconnect, setReconnect] = useState(false);
const activeLoginid = window.localStorage.getItem('active_loginid');
const activeLoginid =
window.sessionStorage.getItem('active_loginid') || window.localStorage.getItem('active_loginid');
const [environment, setEnvironment] = useState(getEnvironment(activeLoginid));
const standaloneDerivAPI = useRef(standalone ? initializeDerivAPI(() => setReconnect(true)) : null);
const subscriptions = useRef<Record<string, DerivAPIBasic['subscribe']>>();
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/hooks/useAuthorize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const useAuthorize = () => {
(loginid: string) => {
const active_loginid = getActiveLoginIDFromLocalStorage();
if (active_loginid !== loginid) {
sessionStorage.setItem('active_loginid', loginid);
localStorage.setItem('active_loginid', loginid);
switchEnvironment(active_loginid);
// whenever we change the loginid, we need to invalidate all queries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const AccountSwitcherDTraderV2 = observer(({ history }: TAccountSwitcherDTraderV
}
};

const getAccountItem = (item: typeof account_list[0], is_demo?: boolean) => (
const getAccountItem = (item: (typeof account_list)[0], is_demo?: boolean) => (
<AccountListDTraderV2
key={item.loginid}
balance={accounts[item?.loginid ?? '']?.balance}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ const AccountInfoWallets = observer(({ is_dialog_on, toggleDialog }: TAccountInf
const { isDesktop } = useDevice();

const active_account = accounts?.[loginid ?? ''];
const wallet_loginid = localStorage.getItem('active_wallet_loginid');
const wallet_loginid =
sessionStorage.getItem('active_wallet_loginid') || localStorage.getItem('active_wallet_loginid');
const active_wallet =
wallet_list?.find(wallet => wallet.loginid === wallet_loginid) ??
wallet_list?.find(wallet => wallet.loginid === loginid);
Expand All @@ -126,7 +127,9 @@ const AccountInfoWallets = observer(({ is_dialog_on, toggleDialog }: TAccountInf
if (active_wallet) {
// get 'dtrade' loginid account linked to the current wallet
linked_dtrade_trading_account_loginid =
active_wallet.dtrade_loginid || linked_wallets_accounts.dtrade?.[0]?.loginid;
sessionStorage.getItem('active_loginid') ||
active_wallet.dtrade_loginid ||
linked_wallets_accounts.dtrade?.[0]?.loginid;

// switch to dtrade account
if (linked_dtrade_trading_account_loginid && linked_dtrade_trading_account_loginid !== loginid) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const AccountSwitcherWalletItem = observer(
if (is_dtrade_active) return;
await switchAccount(dtrade_loginid);
localStorage.setItem('active_wallet_loginid', loginid);
sessionStorage.setItem('active_wallet_loginid', loginid);
};

return (
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/App/Containers/Redirect/redirect.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,28 @@ const Redirect = observer(() => {
}
useEffect(() => {
if (!redirected_to_route && history.location.pathname !== routes.traders_hub) {
const account_currency = url_params.get('account');
const client_account_lists = JSON.parse(localStorage.getItem('client.accounts'));

if (account_currency) {
let matching_loginid;

const converted_account_currency = account_currency.toUpperCase();

if (converted_account_currency === 'DEMO') {
matching_loginid = Object.keys(client_account_lists).find(loginid => /^VR/.test(loginid));
} else {
matching_loginid = Object.keys(client_account_lists).find(
loginid =>
client_account_lists[loginid].currency?.toUpperCase() === converted_account_currency &&
client_account_lists[loginid].account_category === 'trading'
);
}

if (matching_loginid) {
sessionStorage.setItem('active_loginid', matching_loginid);
}
}
const route_mappings = [
{ pattern: /accumulator/i, route: routes.trade, type: 'accumulator' },
{ pattern: /turbos/i, route: routes.trade, type: 'turboslong' },
Expand Down
36 changes: 36 additions & 0 deletions packages/core/src/App/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,42 @@ const AppWithoutTranslation = ({ root_store }) => {
const is_dark_mode = is_dark_mode_on || JSON.parse(localStorage.getItem('ui_store'))?.is_dark_mode_on;
const language = preferred_language ?? getInitialLanguage();

const url_query_string = window.location.search;
const url_params = new URLSearchParams(url_query_string);
const account_currency = url_params.get('account');
const client_account_lists = JSON.parse(localStorage.getItem('client.accounts'));

if (account_currency) {
let matching_loginid, matching_wallet_loginid;

const converted_account_currency = account_currency.toUpperCase();

if (converted_account_currency === 'DEMO') {
matching_loginid = Object.keys(client_account_lists).find(loginid => /^VRTC/.test(loginid));
matching_wallet_loginid = Object.keys(client_account_lists).find(loginid => /^VRW/.test(loginid));
} else {
matching_loginid = Object.keys(client_account_lists).find(
loginid =>
client_account_lists[loginid].currency?.toUpperCase() === converted_account_currency &&
client_account_lists[loginid].account_category === 'trading' &&
client_account_lists[loginid]?.landing_company !== 'virtual'
);
matching_wallet_loginid = Object.keys(client_account_lists).find(
loginid =>
client_account_lists[loginid].currency?.toUpperCase() === converted_account_currency &&
client_account_lists[loginid].account_category === 'wallet' &&
client_account_lists[loginid]?.landing_company !== 'virtual'
);
}

if (matching_loginid) {
sessionStorage.setItem('active_loginid', matching_loginid);
}
if (matching_wallet_loginid) {
sessionStorage.setItem('active_wallet_loginid', matching_wallet_loginid);
}
}

React.useEffect(() => {
const dir = i18n.dir(i18n.language.toLowerCase());
document.documentElement.dir = dir;
Expand Down
27 changes: 22 additions & 5 deletions packages/core/src/Stores/client-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export default class ClientStore extends BaseStore {
setLoginId: action.bound,
setAccounts: action.bound,
setSwitched: action.bound,
setUrlParams: action.bound,
setIsAuthorize: action.bound,
setIsLoggingIn: action.bound,
setPreSwitchAccount: action.bound,
Expand Down Expand Up @@ -1065,11 +1066,22 @@ export default class ClientStore extends BaseStore {
resetLocalStorageValues(loginid) {
this.accounts[loginid].accepted_bch = 0;
LocalStore.setObject(storage_key, this.accounts);
LocalStore.set('active_loginid', loginid);
sessionStorage.setItem('active_loginid', loginid);
this.setUrlParams();
this.syncWithLegacyPlatforms(loginid, toJS(this.accounts));
this.loginid = loginid;
}

setUrlParams() {
const url = new URL(window.location.href);
const loginid = sessionStorage.getItem('active_wallet_loginid') || sessionStorage.getItem('active_loginid');
const account_param = /^VR/.test(loginid) ? 'demo' : this.accounts[loginid]?.currency;
if (account_param) {
url.searchParams.set('account', account_param);
window.history.replaceState({}, '', url.toString());
}
}

setIsAuthorize(value) {
this.is_authorize = value;
}
Expand Down Expand Up @@ -1576,7 +1588,7 @@ export default class ClientStore extends BaseStore {

if (['crypto_transactions_withdraw', 'payment_withdraw'].includes(action_param) && loginid_param)
this.setLoginId(loginid_param);
else this.setLoginId(LocalStore.get('active_loginid'));
else this.setLoginId(window.sessionStorage.getItem('active_loginid') || LocalStore.get('active_loginid'));
this.user_id = LocalStore.get('active_user_id');
this.setAccounts(LocalStore.getObject(storage_key));
this.setSwitched('');
Expand Down Expand Up @@ -2005,11 +2017,15 @@ export default class ClientStore extends BaseStore {

//temporary workaround to sync this.loginid with selected wallet loginid
if (window.location.pathname.includes(routes.wallets)) {
this.resetLocalStorageValues(localStorage.getItem('active_loginid') ?? this.loginid);
this.resetLocalStorageValues(
window.sessionStorage.getItem('active_loginid') ??
localStorage.getItem('active_loginid') ??
this.loginid
);
return;
}

this.resetLocalStorageValues(this.loginid);
this.resetLocalStorageValues(window.sessionStorage.getItem('active_loginid') ?? this.loginid);
}
}

Expand Down Expand Up @@ -2232,11 +2248,12 @@ export default class ClientStore extends BaseStore {
if (active_loginid && Object.keys(client_object).length) {
if (selected_account && is_wallets_selected) {
localStorage.setItem('active_wallet_loginid', active_wallet_loginid);
sessionStorage.setItem('active_wallet_loginid', active_wallet_loginid);
if (verification_code) {
localStorage.setItem('verification_code.payment_withdraw', verification_code);
}
}

sessionStorage.setItem('active_loginid', active_loginid);
localStorage.setItem('active_loginid', active_loginid);
localStorage.setItem('client.accounts', JSON.stringify(client_object));
this.syncWithLegacyPlatforms(active_loginid, this.accounts);
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/utils/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export const getSocketURL = (is_wallets = false) => {
active_loginid_from_url = params.get('acct1');
}
const local_storage_loginid = is_wallets
? window.localStorage.getItem('active_wallet_loginid')
: window.localStorage.getItem('active_loginid');
? window.sessionStorage.getItem('active_wallet_loginid') || window.localStorage.getItem('active_wallet_loginid')
: window.sessionStorage.getItem('active_loginid') || window.localStorage.getItem('active_loginid');
const loginid = local_storage_loginid || active_loginid_from_url;
const is_real = loginid && !/^(VRT|VRW)/.test(loginid);

Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/getActiveLoginIDFromLocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @deprecated Please use 'WebSocketUtils.getActiveLoginid' from '@deriv-com/utils' instead of this.
*/
const getActiveLoginIDFromLocalStorage = (loginid_key = 'active_loginid') => {
const active_custom_loginid = localStorage.getItem(loginid_key);
const active_custom_loginid = sessionStorage.getItem(loginid_key) || localStorage.getItem(loginid_key);
return active_custom_loginid ?? undefined;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,6 @@ describe('useWalletAccountSwitcher', () => {
const switchWalletAccount = result.current;

await switchWalletAccount('CRW34569');
expect(global.localStorage.getItem('active_loginid')).toBe('CR34567');
expect(global.sessionStorage.getItem('active_loginid')).toBe('CR34567');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ const useSyncLocalStorageClientAccounts = () => {
platform: 'dtrade',
},
];
sessionStorage.setItem('active_loginid', newAccount.client_id);
}

setLocalStorageClientAccounts(localStorageData);
Expand Down
16 changes: 14 additions & 2 deletions packages/wallets/src/hooks/useWalletAccountSwitcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const useWalletAccountSwitcher = () => {

const switchWalletAccount = useCallback(
async (loginid: string) => {
const url = new URL(window.location.href);
const dtradeAccount = walletAccounts
?.find(account => account.loginid === loginid)
?.linked_to?.find(linkedAccount => linkedAccount.platform === 'dtrade');
Expand All @@ -16,8 +17,19 @@ const useWalletAccountSwitcher = () => {
account => account.loginid === dtradeAccount?.loginid
);

if (dtradeAccount?.loginid && !linkedAccountDetails?.is_disabled)
localStorage.setItem('active_loginid', dtradeAccount.loginid);
const accountLoginId =
sessionStorage.getItem('active_wallet_loginid') || sessionStorage.getItem('active_loginid') || '';
const accountParam = /^VR/.test(accountLoginId)
? 'demo'
: authorizeData.account_list?.find(account => account.loginid === accountLoginId)?.currency;
if (accountParam) {
url.searchParams.set('account', accountParam);
window.history.replaceState({}, '', url.toString());
}

if (dtradeAccount?.loginid && !linkedAccountDetails?.is_disabled) {
sessionStorage.setItem('active_loginid', dtradeAccount.loginid);
}
},
[_switchAccount, authorizeData.account_list, walletAccounts]
);
Expand Down

0 comments on commit 18cf193

Please sign in to comment.