Skip to content

Commit

Permalink
Merge pull request #141 from tonkeeper/feature/new-storage-structure
Browse files Browse the repository at this point in the history
New storage structure
  • Loading branch information
KuznetsovNikita authored Aug 2, 2024
2 parents 2f27fe3 + 0d6ea56 commit afaffb0
Show file tree
Hide file tree
Showing 214 changed files with 5,891 additions and 4,213 deletions.
116 changes: 56 additions & 60 deletions apps/desktop/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { localizationText } from '@tonkeeper/core/dist/entries/language';
import { Network, getApiConfig } from '@tonkeeper/core/dist/entries/network';
import { AuthState } from '@tonkeeper/core/dist/entries/password';
import { WalletState } from '@tonkeeper/core/dist/entries/wallet';
import { getApiConfig } from '@tonkeeper/core/dist/entries/network';
import { WalletVersion } from '@tonkeeper/core/dist/entries/wallet';
import { useWindowsScroll } from '@tonkeeper/uikit/dist/components/Body';
import ConnectLedgerNotification from '@tonkeeper/uikit/dist/components/ConnectLedgerNotification';
import { CopyNotification } from '@tonkeeper/uikit/dist/components/CopyNotification';
Expand Down Expand Up @@ -33,13 +32,12 @@ import { DesktopCoinPage } from '@tonkeeper/uikit/dist/desktop-pages/coin/Deskto
import DashboardPage from '@tonkeeper/uikit/dist/desktop-pages/dashboard';
import { DesktopHistoryPage } from '@tonkeeper/uikit/dist/desktop-pages/history/DesktopHistoryPage';
import { DesktopMultiSendPage } from '@tonkeeper/uikit/dist/desktop-pages/multi-send';
import { NotcoinPage } from '@tonkeeper/uikit/dist/desktop-pages/notcoin/NotcoinPage';
import { DesktopPreferencesRouting } from '@tonkeeper/uikit/dist/desktop-pages/preferences/DesktopPreferencesRouting';
import { DesktopWalletSettingsRouting } from '@tonkeeper/uikit/dist/desktop-pages/settings/DesktopWalletSettingsRouting';
import { DesktopSwapPage } from '@tonkeeper/uikit/dist/desktop-pages/swap';
import { DesktopTokens } from '@tonkeeper/uikit/dist/desktop-pages/tokens/DesktopTokens';
import { AmplitudeAnalyticsContext, useTrackLocation } from '@tonkeeper/uikit/dist/hooks/amplitude';
import { AppContext, WalletStateContext } from '@tonkeeper/uikit/dist/hooks/appContext';
import { AppContext, IAppContext } from '@tonkeeper/uikit/dist/hooks/appContext';
import {
AfterImportAction,
AppSdkContext,
Expand All @@ -49,27 +47,30 @@ import { useRecommendations } from '@tonkeeper/uikit/dist/hooks/browser/useRecom
import { useLock } from '@tonkeeper/uikit/dist/hooks/lock';
import { StorageContext } from '@tonkeeper/uikit/dist/hooks/storage';
import { I18nContext, TranslationContext } from '@tonkeeper/uikit/dist/hooks/translation';
import { AppProRoute, AppRoute, any } from '@tonkeeper/uikit/dist/libs/routes';
import { any, AppProRoute, AppRoute } from '@tonkeeper/uikit/dist/libs/routes';
import { Unlock } from '@tonkeeper/uikit/dist/pages/home/Unlock';
import { UnlockNotification } from '@tonkeeper/uikit/dist/pages/home/UnlockNotification';
import ImportRouter from '@tonkeeper/uikit/dist/pages/import';
import Initialize, { InitializeContainer } from '@tonkeeper/uikit/dist/pages/import/Initialize';
import { UserThemeProvider } from '@tonkeeper/uikit/dist/providers/UserThemeProvider';
import { useAccountState } from '@tonkeeper/uikit/dist/state/account';
import { useUserFiat } from '@tonkeeper/uikit/dist/state/fiat';
import { useAuthState, useCanPromptTouchId } from '@tonkeeper/uikit/dist/state/password';
import { useCanPromptTouchId } from '@tonkeeper/uikit/dist/state/password';
import { useProBackupState } from '@tonkeeper/uikit/dist/state/pro';
import { useTonendpoint, useTonenpointConfig } from '@tonkeeper/uikit/dist/state/tonendpoint';
import { useActiveWallet } from '@tonkeeper/uikit/dist/state/wallet';
import {
useActiveAccountQuery,
useAccountsStateQuery,
useActiveTonNetwork
} from '@tonkeeper/uikit/dist/state/wallet';
import { Container, GlobalStyleCss } from '@tonkeeper/uikit/dist/styles/globalStyle';
import { FC, Suspense, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
createMemoryRouter,
Outlet,
Route,
RouterProvider,
Routes,
createMemoryRouter,
useLocation,
useNavigate
} from 'react-router-dom';
Expand All @@ -80,6 +81,11 @@ import { DeepLinkSubscription } from './components/DeepLink';
import { TonConnectSubscription } from './components/TonConnectSubscription';
import { DesktopDns } from '@tonkeeper/uikit/dist/desktop-pages/nft/DesktopDns';
import { DesktopCollectables } from '@tonkeeper/uikit/dist/desktop-pages/nft/DesktopCollectables';
import { useUserLanguage } from '@tonkeeper/uikit/dist/state/language';
import { useDebuggingTools } from '@tonkeeper/uikit/dist/hooks/useDebuggingTools';
import { useDevSettings } from '@tonkeeper/uikit/dist/state/dev';
import { ModalsRoot } from '@tonkeeper/uikit/dist/components/ModalsRoot';
import { Account } from '@tonkeeper/core/dist/entries/account';

const queryClient = new QueryClient({
defaultOptions: {
Expand Down Expand Up @@ -121,7 +127,6 @@ const sdk = new DesktopAppSdk();
const TARGET_ENV = 'desktop';

const langs = 'en,zh_CN,ru,it,tr';
const listOfAuth: AuthState['kind'][] = ['keychain'];

declare const REACT_APP_TONCONSOLE_API: string;
declare const REACT_APP_TG_BOT_ID: string;
Expand Down Expand Up @@ -254,60 +259,57 @@ const FullSizeWrapperBounded = styled(FullSizeWrapper)`
`;

export const Loader: FC = () => {
const { data: activeWallet } = useActiveWallet();
const network = useActiveTonNetwork();
const { data: activeAccount, isLoading: activeWalletLoading } = useActiveAccountQuery();
const { data: accounts, isLoading: isWalletsLoading } = useAccountsStateQuery();
const { data: lang, isLoading: isLangLoading } = useUserLanguage();
const { data: devSettings } = useDevSettings();

const lock = useLock(sdk);
const { i18n } = useTranslation();
const { data: account } = useAccountState();
const { data: auth } = useAuthState();
const { data: fiat } = useUserFiat();

const tonendpoint = useTonendpoint({
targetEnv: TARGET_ENV,
build: sdk.version,
network: activeWallet?.network,
lang: activeWallet?.lang,
network,
lang,
platform: 'desktop'
});
const { data: config } = useTonenpointConfig(tonendpoint);

const navigate = useNavigate();
useAppHeight();

const { data: tracker } = useAnalytics(sdk.version, account, activeWallet);
const { data: tracker } = useAnalytics(sdk.version, activeAccount, accounts);

useEffect(() => {
if (
activeWallet &&
activeWallet.lang &&
i18n.language !== localizationText(activeWallet.lang)
) {
i18n.reloadResources([localizationText(activeWallet.lang)]).then(() =>
i18n.changeLanguage(localizationText(activeWallet.lang))
if (lang && i18n.language !== localizationText(lang)) {
i18n.reloadResources([localizationText(lang)]).then(() =>
i18n.changeLanguage(localizationText(lang))
);
}
}, [activeWallet, i18n]);
}, [lang, i18n]);

useEffect(() => {
window.backgroundApi.onRefresh(() => queryClient.invalidateQueries());
}, []);

if (
auth === undefined ||
account === undefined ||
activeWalletLoading ||
isLangLoading ||
isWalletsLoading ||
config === undefined ||
lock === undefined ||
fiat === undefined
fiat === undefined ||
!devSettings
) {
return <Loading />;
}

const network = activeWallet?.network ?? Network.MAINNET;
const context = {
const context: IAppContext = {
api: getApiConfig(config, network, REACT_APP_TONCONSOLE_API),
auth,
fiat,
account,
config,
tonendpoint,
standalone: true,
Expand All @@ -318,7 +320,8 @@ export const Loader: FC = () => {
env: {
tgAuthBotId: REACT_APP_TG_BOT_ID,
stonfiReferralAddress: REACT_APP_STONFI_REFERRAL_ADDRESS
}
},
defaultWalletVersion: WalletVersion.V5R1
};

return (
Expand All @@ -328,9 +331,10 @@ export const Loader: FC = () => {
value={() => navigate(AppRoute.home, { replace: true })}
>
<AppContext.Provider value={context}>
<Content activeWallet={activeWallet} lock={lock} />
<Content activeAccount={activeAccount} lock={lock} />
<CopyNotification hideSimpleCopyNotifications />
<QrScanner />
<ModalsRoot />
</AppContext.Provider>
</AfterImportAction.Provider>
</OnImportAction.Provider>
Expand All @@ -344,14 +348,15 @@ const usePrefetch = () => {
};

export const Content: FC<{
activeWallet?: WalletState | null;
activeAccount?: Account | null;
lock: boolean;
}> = ({ activeWallet, lock }) => {
}> = ({ activeAccount, lock }) => {
const location = useLocation();
useWindowsScroll();
useAppWidth();
useTrackLocation();
usePrefetch();
useDebuggingTools();

if (lock) {
return (
Expand All @@ -361,15 +366,12 @@ export const Content: FC<{
);
}

if (!activeWallet || location.pathname.startsWith(AppRoute.import)) {
if (!activeAccount || location.pathname.startsWith(AppRoute.import)) {
return (
<FullSizeWrapperBounded className="full-size-wrapper">
<InitializeContainer fullHeight={false}>
<Routes>
<Route
path={any(AppRoute.import)}
element={<ImportRouter listOfAuth={listOfAuth} />}
/>
<Route path={any(AppRoute.import)} element={<ImportRouter />} />
<Route path="*" element={<Initialize />} />
</Routes>
</InitializeContainer>
Expand All @@ -378,24 +380,19 @@ export const Content: FC<{
}

return (
<WalletStateContext.Provider value={activeWallet}>
<WideLayout>
<AsideMenu />
<WideContent>
<Routes>
<Route path={AppProRoute.dashboard} element={<DashboardPage />} />
<Route path={AppRoute.browser} element={<DesktopBrowser />} />
<Route path={any(AppRoute.settings)} element={<PreferencesContent />} />
<Route
path={any(AppProRoute.multiSend)}
element={<DesktopMultiSendPage />}
/>
<Route path="*" element={<WalletContent />} />
</Routes>
</WideContent>
<BackgroundElements />
</WideLayout>
</WalletStateContext.Provider>
<WideLayout>
<AsideMenu />
<WideContent>
<Routes>
<Route path={AppProRoute.dashboard} element={<DashboardPage />} />
<Route path={AppRoute.browser} element={<DesktopBrowser />} />
<Route path={any(AppRoute.settings)} element={<PreferencesContent />} />
<Route path={any(AppProRoute.multiSend)} element={<DesktopMultiSendPage />} />
<Route path="*" element={<WalletContent />} />
</Routes>
</WideContent>
<BackgroundElements />
</WideLayout>
);
};

Expand Down Expand Up @@ -423,7 +420,6 @@ const WalletContent = () => {
element={<DesktopWalletSettingsRouting />}
/>
<Route path={AppRoute.swap} element={<DesktopSwapPage />} />
<Route path={AppRoute.notcoin} element={<NotcoinPage />} />
<Route path="*" element={<DesktopTokens />} />
</Route>
</Routes>
Expand Down
43 changes: 29 additions & 14 deletions apps/desktop/src/electron/sseEvetns.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import { TonConnectAppRequest } from '@tonkeeper/core/dist/entries/tonConnect';
import { accountSelectWallet, getAccountState } from '@tonkeeper/core/dist/service/accountService';
import {
replyBadRequestResponse,
replyDisconnectResponse
} from '@tonkeeper/core/dist/service/tonConnect/actionService';
import {
AccountConnection,
disconnectAppConnection,
getAccountConnection
getTonWalletConnections
} from '@tonkeeper/core/dist/service/tonConnect/connectionService';
import {
getLastEventId,
subscribeTonConnect
} from '@tonkeeper/core/dist/service/tonConnect/httpBridge';
import { getWalletState } from '@tonkeeper/core/dist/service/wallet/storeService';
import { delay } from '@tonkeeper/core/dist/utils/common';
import { Buffer as BufferPolyfill } from 'buffer';
import log from 'electron-log/main';
import EventSourcePolyfill from 'eventsource';
import { MainWindow } from './mainWindow';
import { mainStorage } from './storageService';
import { isStandardTonWallet, WalletId } from '@tonkeeper/core/dist/entries/wallet';
import { accountsStorage } from '@tonkeeper/core/dist/service/accountsStorage';
import { getWalletById } from '@tonkeeper/core/dist/entries/account';

globalThis.Buffer = BufferPolyfill;

export class TonConnectSSE {
private lastEventId: string;
private connections: AccountConnection[];
private dist: Record<string, string>;
private dist: Record<string, WalletId>;
private closeConnection: () => void | null = null;

private static instance: TonConnectSSE = null;
Expand All @@ -48,18 +49,19 @@ export class TonConnectSSE {
public async init() {
this.lastEventId = await getLastEventId(mainStorage);

const account = await getAccountState(mainStorage);
const walletsState = (await accountsStorage(mainStorage).getAccounts()).flatMap(
a => a.allTonWallets
);

this.connections = [];
this.dist = {};

for (const key of account.publicKeys) {
const wallet = await getWalletState(mainStorage, key);
const walletConnections = await getAccountConnection(mainStorage, wallet);
for (const wallet of walletsState) {
const walletConnections = await getTonWalletConnections(mainStorage, wallet);

this.connections = this.connections.concat(walletConnections);
walletConnections.forEach(item => {
this.dist[item.clientSessionId] = key;
this.dist[item.clientSessionId] = wallet.id;
});
}
}
Expand All @@ -78,7 +80,13 @@ export class TonConnectSSE {
};

private onDisconnect = async ({ connection, request }: TonConnectAppRequest) => {
const wallet = await getWalletState(mainStorage, this.dist[connection.clientSessionId]);
const accounts = await accountsStorage(mainStorage).getAccounts();
const wallet = getWalletById(accounts, this.dist[connection.clientSessionId]);

if (!wallet || !isStandardTonWallet(wallet)) {
return;
}

await disconnectAppConnection({
storage: mainStorage,
wallet,
Expand All @@ -101,14 +109,21 @@ export class TonConnectSSE {
payload: JSON.parse(params.request.params[0])
};

const walletPublicKey = this.dist[params.connection.clientSessionId];
const walletId = this.dist[params.connection.clientSessionId];

const account = await getAccountState(mainStorage);
const activeAccount = await accountsStorage(mainStorage).getActiveAccount();
const activeWallet = activeAccount.activeTonWallet;

const window = await MainWindow.bringToFront();

if (account.activePublicKey !== walletPublicKey) {
await accountSelectWallet(mainStorage, walletPublicKey);
if (activeWallet.id !== walletId) {
const accountToActivate = (
await accountsStorage(mainStorage).getAccounts()
).find(a => a.getTonWallet(walletId) !== undefined);

accountToActivate.setActiveTonWallet(walletId);
await accountsStorage(mainStorage).updateAccountInState(accountToActivate);
await accountsStorage(mainStorage).setActiveAccountId(accountToActivate.id);
window.webContents.send('refresh');
await delay(500);
}
Expand Down
Loading

0 comments on commit afaffb0

Please sign in to comment.