diff --git a/api/serializers.py b/api/serializers.py index 327eb23a..0c9cfd08 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -534,22 +534,23 @@ class UserGenSerializer(serializers.Serializer): required=True, help_text="SHA256 of user secret", ) + # Optional fields + # (PGP keys are mandatory for new users, but optional for logins) public_key = serializers.CharField( max_length=2000, allow_null=False, allow_blank=False, - required=True, + required=False, help_text="Armored ASCII PGP public key block", ) encrypted_private_key = serializers.CharField( max_length=2000, allow_null=False, allow_blank=False, - required=True, + required=False, help_text="Armored ASCII PGP encrypted private key block", ) - # Optional fields ref_code = serializers.CharField( max_length=30, allow_null=True, diff --git a/api/views.py b/api/views.py index 4478e43c..034aff50 100644 --- a/api/views.py +++ b/api/views.py @@ -653,19 +653,6 @@ class UserView(APIView): encrypted_private_key = serializer.data.get("encrypted_private_key") ref_code = serializer.data.get("ref_code") - if not public_key or not encrypted_private_key: - context["bad_request"] = "Must provide valid 'pub' and 'enc_priv' PGP keys" - return Response(context, status.HTTP_400_BAD_REQUEST) - - ( - valid, - bad_keys_context, - public_key, - encrypted_private_key, - ) = Logics.validate_pgp_keys(public_key, encrypted_private_key) - if not valid: - return Response(bad_keys_context, status.HTTP_400_BAD_REQUEST) - # Now the server only receives a hash of the token. So server trusts the client # with computing length, counts and unique_values to confirm the high entropy of the token # In any case, it is up to the client if they want to create a bad high entropy token. @@ -712,6 +699,20 @@ class UserView(APIView): # Create new credentials and login if nickname is new if len(User.objects.filter(username=nickname)) == 0: + if not public_key or not encrypted_private_key: + context[ + "bad_request" + ] = "Must provide valid 'pub' and 'enc_priv' PGP keys" + return Response(context, status.HTTP_400_BAD_REQUEST) + ( + valid, + bad_keys_context, + public_key, + encrypted_private_key, + ) = Logics.validate_pgp_keys(public_key, encrypted_private_key) + if not valid: + return Response(bad_keys_context, status.HTTP_400_BAD_REQUEST) + User.objects.create_user( username=nickname, password=token_sha256, is_staff=False ) @@ -931,25 +932,6 @@ class InfoView(ListAPIView): BalanceLog.objects.latest("time") ) - if request.user.is_authenticated: - context["nickname"] = request.user.username - context["referral_code"] = str(request.user.profile.referral_code) - context["earned_rewards"] = request.user.profile.earned_rewards - context["wants_stealth"] = request.user.profile.wants_stealth - # Adds/generate telegram token and whether it is enabled - context = {**context, **Telegram.get_context(request.user)} - has_no_active_order, _, order = Logics.validate_already_maker_or_taker( - request.user - ) - if not has_no_active_order: - context["active_order_id"] = order.id - else: - last_order = Order.objects.filter( - Q(maker=request.user) | Q(taker=request.user) - ).last() - if last_order: - context["last_order_id"] = last_order.id - return Response(context, status.HTTP_200_OK) diff --git a/frontend/src/basic/Main.tsx b/frontend/src/basic/Main.tsx index 73e06843..b96f754a 100644 --- a/frontend/src/basic/Main.tsx +++ b/frontend/src/basic/Main.tsx @@ -7,7 +7,7 @@ import MakerPage from './MakerPage'; import BookPage from './BookPage'; import OrderPage from './OrderPage'; import SettingsPage from './SettingsPage'; -import NavBar from './NavBar'; +import NavBar, { Page } from './NavBar'; import MainDialogs, { OpenDialogs } from './MainDialogs'; import { apiClient } from '../services/api'; @@ -25,6 +25,8 @@ import { defaultRobot, defaultInfo, } from '../models'; +import { sha256 } from 'js-sha256'; +import RobotAvatar from '../components/RobotAvatar'; const getWindowSize = function (fontSize: number) { // returns window size in EM units @@ -34,7 +36,6 @@ const getWindowSize = function (fontSize: number) { }; }; -type Page = 'robot' | 'order' | 'create' | 'offers' | 'settings' | 'none'; interface SlideDirection { in: 'left' | 'right' | undefined; out: 'left' | 'right' | undefined; @@ -66,6 +67,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { in: undefined, out: undefined, }); + const [order, setOrder] = useState(null); const navbarHeight = 2.5; const closeAll = { @@ -76,6 +78,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { coordinator: false, stats: false, update: false, + profile: false, }; const [open, setOpen] = useState(closeAll); @@ -133,27 +136,60 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { coordinatorVersion: versionInfo.coordinatorVersion, clientVersion: versionInfo.clientVersion, }); - if (!robot.nickname && data.nickname && !robot.loading) { - setRobot({ - ...robot, - nickname: data.nickname, - loading: false, - activeOrderId: data.active_order_id ?? null, - lastOrderId: data.last_order_id ?? null, - referralCode: data.referral_code, - tgEnabled: data.tg_enabled, - tgBotName: data.tg_bot_name, - tgToken: data.tg_token, - earnedRewards: data.earned_rewards ?? 0, - stealthInvoices: data.wants_stealth, - }); - } }); }; - console.log(page, slideDirection); + const fetchRobot = function () { + const requestBody = { + token_sha256: sha256(robot.token), + }; + + apiClient.post('/api/user/', requestBody).then((data: any) => { + console.log(data); + setOrder( + data.active_order_id + ? data.active_order_id + : data.last_order_id + ? data.last_order_id + : order, + ); + setRobot({ + ...robot, + nickname: data.nickname, + token: robot.token, + loading: false, + avatarLoaded: false, + activeOrderId: data.active_order_id ? data.active_order_id : null, + lastOrderId: data.last_order_id ? data.last_order_id : null, + referralCode: data.referral_code, + earnedRewards: data.earned_rewards ?? 0, + stealthInvoices: data.wants_stealth, + tgEnabled: data.tg_enabled, + tgBotName: data.tg_bot_name, + tgToken: data.tg_token, + bitsEntropy: data.token_bits_entropy, + shannonEntropy: data.token_shannon_entropy, + pub_key: data.public_key, + enc_priv_key: data.encrypted_private_key, + copiedToken: data.found ? true : robot.copiedToken, + }); + }); + }; + + useEffect(() => { + if (robot.token && robot.nickname === null) { + fetchRobot(); + } + }, []); + return ( + {/* load robot avatar image, set avatarLoaded: true */} + setRobot({ ...robot, avatarLoaded: true })} + /> { exact path='/' render={(props: any) => ( - + )} /> ( - + )} /> @@ -195,6 +243,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { setMaker={setMaker} lastDayPremium={info.last_day_nonkyc_btc_premium} windowSize={windowSize} + hasRobot={robot.avatarLoaded} /> @@ -213,9 +262,12 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { fetchLimits={fetchLimits} maker={maker} setMaker={setMaker} + setPage={setPage} + setOrder={setOrder} fav={fav} setFav={setFav} windowSize={{ ...windowSize, height: windowSize.height - navbarHeight }} + hasRobot={robot.avatarLoaded} /> @@ -244,6 +296,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => { { setOpen={setOpen} closeAll={closeAll} setSlideDirection={setSlideDirection} - robot={robot} + order={order} + hasRobot={robot.avatarLoaded} + /> + - ); }; diff --git a/frontend/src/basic/MainDialogs/index.tsx b/frontend/src/basic/MainDialogs/index.tsx index 73aee5de..a934d73e 100644 --- a/frontend/src/basic/MainDialogs/index.tsx +++ b/frontend/src/basic/MainDialogs/index.tsx @@ -1,12 +1,11 @@ -import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useTheme, styled, Grid, IconButton } from '@mui/material'; -import { Info } from '../../models'; +import React, { useEffect } from 'react'; +import { Info, Robot } from '../../models'; import { CommunityDialog, CoordinatorSummaryDialog, InfoDialog, LearnDialog, + ProfileDialog, StatsDialog, UpdateClientDialog, } from '../../components/Dialogs'; @@ -19,19 +18,26 @@ export interface OpenDialogs { coordinator: boolean; stats: boolean; update: boolean; + profile: boolean; // temporary until new Robot Page is ready } interface MainDialogsProps { open: OpenDialogs; setOpen: (state: OpenDialogs) => void; info: Info; + robot: Robot; + setRobot: (state: Robot) => void; closeAll: OpenDialogs; } -const MainDialogs = ({ open, setOpen, info, closeAll }: MainDialogsProps): JSX.Element => { - const { t } = useTranslation(); - const theme = useTheme(); - +const MainDialogs = ({ + open, + setOpen, + info, + closeAll, + robot, + setRobot, +}: MainDialogsProps): JSX.Element => { useEffect(() => { if (info.openUpdateClient) { setOpen({ ...closeAll, update: true }); @@ -83,6 +89,12 @@ const MainDialogs = ({ open, setOpen, info, closeAll }: MainDialogsProps): JSX.E lastDayVolume={info.last_day_volume} lifetimeVolume={info.lifetime_volume} /> + setOpen({ ...open, profile: false })} + robot={robot} + setRobot={setRobot} + /> ); }; diff --git a/frontend/src/basic/MakerPage/index.tsx b/frontend/src/basic/MakerPage/index.tsx index 193f0880..aeae8324 100644 --- a/frontend/src/basic/MakerPage/index.tsx +++ b/frontend/src/basic/MakerPage/index.tsx @@ -8,6 +8,7 @@ import { filterOrders } from '../../utils'; import MakerForm from '../../components/MakerForm'; import BookTable from '../../components/BookTable'; +import { Page } from '../NavBar'; interface MakerPageProps { limits: { list: LimitList; loading: boolean }; @@ -18,6 +19,9 @@ interface MakerPageProps { setFav: (state: Favorites) => void; setMaker: (state: Maker) => void; windowSize: { width: number; height: number }; + hasRobot: boolean; + setOrder: (state: number) => void; + setPage: (state: Page) => void; } const MakerPage = ({ @@ -29,6 +33,9 @@ const MakerPage = ({ setFav, setMaker, windowSize, + setOrder, + setPage, + hasRobot = false, }: MakerPageProps): JSX.Element => { const { t } = useTranslation(); @@ -86,6 +93,10 @@ const MakerPage = ({ setFav={setFav} maker={maker} setMaker={setMaker} + onOrderCreated={(id) => { + setOrder(id); + setPage('order'); + }} disableRequest={matches.length > 0 && !showMatches} collapseAll={showMatches} onSubmit={() => setShowMatches(matches.length > 0)} diff --git a/frontend/src/basic/NavBar/MoreTooltip.tsx b/frontend/src/basic/NavBar/MoreTooltip.tsx index 581fb456..8a3f3dcd 100644 --- a/frontend/src/basic/NavBar/MoreTooltip.tsx +++ b/frontend/src/basic/NavBar/MoreTooltip.tsx @@ -19,24 +19,21 @@ const StyledTooltip = styled(({ className, ...props }: TooltipProps) => ( }, })); -export interface OpenDialogs { - more: boolean; - learn: boolean; - community: boolean; - info: boolean; - coordinator: boolean; - stats: boolean; - update: boolean; -} - interface MoreTooltipProps { open: OpenDialogs; + nickname: string | null; setOpen: (state: OpenDialogs) => void; closeAll: OpenDialogs; children: JSX.Element; } -const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): JSX.Element => { +const MoreTooltip = ({ + open, + setOpen, + closeAll, + nickname, + children, +}: MoreTooltipProps): JSX.Element => { const { t } = useTranslation(); const theme = useTheme(); return ( @@ -56,7 +53,7 @@ const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): J sx={{ color: open.info ? theme.palette.primary.main : theme.palette.text.secondary, }} - onClick={() => setOpen({ ...closeAll, more: true, info: !open.info })} + onClick={() => setOpen({ ...closeAll, info: !open.info })} > @@ -69,7 +66,7 @@ const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): J sx={{ color: open.learn ? theme.palette.primary.main : theme.palette.text.secondary, }} - onClick={() => setOpen({ ...closeAll, more: true, learn: !open.learn })} + onClick={() => setOpen({ ...closeAll, learn: !open.learn })} > @@ -86,7 +83,7 @@ const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): J sx={{ color: open.community ? theme.palette.primary.main : theme.palette.text.secondary, }} - onClick={() => setOpen({ ...closeAll, more: true, community: !open.community })} + onClick={() => setOpen({ ...closeAll, community: !open.community })} > @@ -101,7 +98,7 @@ const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): J ? theme.palette.primary.main : theme.palette.text.secondary, }} - onClick={() => setOpen({ ...closeAll, more: true, coordinator: !open.coordinator })} + onClick={() => setOpen({ ...closeAll, coordinator: !open.coordinator })} > @@ -114,7 +111,7 @@ const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): J sx={{ color: open.stats ? theme.palette.primary.main : theme.palette.text.secondary, }} - onClick={() => setOpen({ ...closeAll, more: true, stats: !open.stats })} + onClick={() => setOpen({ ...closeAll, stats: !open.stats })} > diff --git a/frontend/src/basic/NavBar/NavBar.tsx b/frontend/src/basic/NavBar/NavBar.tsx index 0cec35e9..5f9f3f79 100644 --- a/frontend/src/basic/NavBar/NavBar.tsx +++ b/frontend/src/basic/NavBar/NavBar.tsx @@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; import { Tabs, Tab, Paper, useTheme } from '@mui/material'; -import RobotAvatar from '../../components/RobotAvatar'; import MoreTooltip from './MoreTooltip'; import { OpenDialogs } from '../MainDialogs'; +import { Page } from '.'; + import { SettingsApplications, SmartToy, @@ -15,12 +16,13 @@ import { Assignment, MoreHoriz, } from '@mui/icons-material'; +import RobotAvatar from '../../components/RobotAvatar'; -type Page = 'robot' | 'offers' | 'create' | 'order' | 'settings' | 'none'; type Direction = 'left' | 'right' | undefined; interface NavBarProps { page: Page; + nickname?: string | null; setPage: (state: Page) => void; slideDirection: { in: Direction; out: Direction }; setSlideDirection: (state: { in: Direction; out: Direction }) => void; @@ -29,6 +31,8 @@ interface NavBarProps { open: OpenDialogs; setOpen: (state: OpenDialogs) => void; closeAll: OpenDialogs; + order: number | null; + hasRobot: boolean; } const NavBar = ({ @@ -37,20 +41,24 @@ const NavBar = ({ slideDirection, setSlideDirection, open, + nickname = null, setOpen, closeAll, width, height, + order, + hasRobot = false, }: NavBarProps): JSX.Element => { const theme = useTheme(); const { t } = useTranslation(); const history = useHistory(); const smallBar = width < 50; - const tabWidth = smallBar ? 1 : 12; const [newPage, setNewPage] = useState(history.location.pathname.split('/')[1]); - const tabSx = smallBar ? {} : { position: 'relative', bottom: '1em' }; + const tabSx = smallBar + ? { position: 'relative', bottom: nickname ? '0.8em' : '0em', minWidth: '1em' } + : { position: 'relative', bottom: '1em', minWidth: '2em' }; const pagesPosition = { robot: 1, offers: 2, @@ -73,7 +81,11 @@ const NavBar = ({ } else { handleSlideDirection(page, newPage); setNewPage(newPage); - setTimeout(() => history.push(`/${newPage}`), theme.transitions.duration.leavingScreen * 3); + const param = newPage === 'order' ? order ?? '' : ''; + setTimeout( + () => history.push(`/${newPage}/${param}`), + theme.transitions.duration.leavingScreen * 3, + ); } }; @@ -92,16 +104,30 @@ const NavBar = ({ > + setOpen({ ...closeAll, profile: !open.profile })} + icon={ + nickname ? ( + + ) : ( + <> + ) + } + /> + } iconPosition='start' @@ -124,7 +150,8 @@ const NavBar = ({ } iconPosition='start' /> @@ -136,18 +163,20 @@ const NavBar = ({ iconPosition='start' /> - - { - setOpen(open.more ? closeAll : { ...open, more: true }); - }} - icon={} - iconPosition='start' - /> - + { + open.more ? null : setOpen({ ...open, more: true }); + }} + icon={ + + + + } + iconPosition='start' + /> ); diff --git a/frontend/src/basic/NavBar/index.tsx b/frontend/src/basic/NavBar/index.tsx index 269d480c..70f2e10c 100644 --- a/frontend/src/basic/NavBar/index.tsx +++ b/frontend/src/basic/NavBar/index.tsx @@ -1,4 +1,5 @@ import NavBar from './NavBar'; +export type Page = 'robot' | 'order' | 'create' | 'offers' | 'settings' | 'none'; export type { OpenDialogs } from './MoreTooltip'; export default NavBar; diff --git a/frontend/src/basic/SettingsPage/index.tsx b/frontend/src/basic/SettingsPage/index.tsx index f6039abb..eebd4292 100644 --- a/frontend/src/basic/SettingsPage/index.tsx +++ b/frontend/src/basic/SettingsPage/index.tsx @@ -18,7 +18,7 @@ const SettingsPage = ({ settings, setSettings, windowSize }: SettingsPageProps): return ( diff --git a/frontend/src/basic/UserGenPage.js b/frontend/src/basic/UserGenPage.js index 7b3f591c..02a3b4ff 100644 --- a/frontend/src/basic/UserGenPage.js +++ b/frontend/src/basic/UserGenPage.js @@ -10,8 +10,6 @@ import { CircularProgress, IconButton, } from '@mui/material'; -import { Link } from 'react-router-dom'; -import { InfoDialog } from '../components/Dialogs'; import SmartToyIcon from '@mui/icons-material/SmartToy'; import CasinoIcon from '@mui/icons-material/Casino'; @@ -72,6 +70,7 @@ class UserGenPage extends Component { ref_code: refCode, }; }); + requestBody.then((body) => console.log(body)); requestBody.then((body) => apiClient.post('/api/user/', body).then((data) => { this.setState({ found: data.found, bad_request: data.bad_request }); @@ -87,6 +86,9 @@ class UserGenPage extends Component { earnedRewards: data.earned_rewards ?? this.props.eartnedRewards, lastOrderId: data.last_order_id ?? this.props.lastOrderId, stealthInvoices: data.wants_stealth ?? this.props.stealthInvoices, + tgEnabled: data.tg_enabled, + tgBotName: data.tg_bot_name, + tgToken: data.tg_token, }) : this.props.setRobot({ ...this.props.robot, @@ -359,36 +361,6 @@ class UserGenPage extends Component { )} - - - - - - diff --git a/frontend/src/components/Dialogs/Profile.tsx b/frontend/src/components/Dialogs/Profile.tsx index 9c16e739..4cb4716d 100644 --- a/frontend/src/components/Dialogs/Profile.tsx +++ b/frontend/src/components/Dialogs/Profile.tsx @@ -39,52 +39,26 @@ import { UserNinjaIcon, BitcoinIcon } from '../Icons'; import { systemClient } from '../../services/System'; import { getHost, getWebln } from '../../utils'; import RobotAvatar from '../RobotAvatar'; +import { apiClient } from '../../services/api'; +import { Robot } from '../../models'; interface Props { open: boolean; - handleClickCloseProfile: () => void; - nickname: string; - activeOrderId: string | number; - lastOrderId: string | number; - referralCode: string; - tgEnabled: boolean; - tgBotName: string; - tgToken: string; - handleSubmitInvoiceClicked: (e: any, invoice: string) => void; - showRewardsSpinner: boolean; - withdrawn: boolean; - badInvoice: boolean | string; - earnedRewards: number; - stealthInvoices: boolean; - handleSetStealthInvoice: (wantsStealth: boolean) => void; - updateRobot: (state: any) => void; // TODO: move to a ContextProvider + onClose: () => void; + robot: Robot; + setRobot: (state: Robot) => void; } -const ProfileDialog = ({ - open = false, - handleClickCloseProfile, - nickname, - activeOrderId, - lastOrderId, - referralCode, - tgEnabled, - tgBotName, - tgToken, - handleSubmitInvoiceClicked, - showRewardsSpinner, - withdrawn, - badInvoice, - earnedRewards, - updateRobot, - stealthInvoices, - handleSetStealthInvoice, -}: Props): JSX.Element => { +const ProfileDialog = ({ open = false, onClose, robot, setRobot }: Props): JSX.Element => { const { t } = useTranslation(); const theme = useTheme(); const host = getHost(); const [rewardInvoice, setRewardInvoice] = useState(''); const [showRewards, setShowRewards] = useState(false); + const [showRewardsSpinner, setShowRewardsSpinner] = useState(false); + const [withdrawn, setWithdrawn] = useState(false); + const [badInvoice, setBadInvoice] = useState(''); const [openClaimRewards, setOpenClaimRewards] = useState(false); const [weblnEnabled, setWeblnEnabled] = useState(false); const [openEnableTelegram, setOpenEnableTelegram] = useState(false); @@ -100,19 +74,19 @@ const ProfileDialog = ({ if (robotToken) { systemClient.copyToClipboard(robotToken); - updateRobot({ copiedToken: true }); + setRobot({ ...robot, copiedToken: true }); } }; const copyReferralCodeHandler = () => { - systemClient.copyToClipboard(`http://${host}/ref/${referralCode}`); + systemClient.copyToClipboard(`http://${host}/ref/${robot.referralCode}`); }; const handleWeblnInvoiceClicked = async (e: any) => { e.preventDefault(); - if (earnedRewards) { + if (robot.earnedRewards) { const webln = await getWebln(); - const invoice = webln.makeInvoice(earnedRewards).then(() => { + const invoice = webln.makeInvoice(robot.earnedRewards).then(() => { if (invoice) { handleSubmitInvoiceClicked(e, invoice.paymentRequest); } @@ -120,15 +94,39 @@ const ProfileDialog = ({ } }; + const handleSubmitInvoiceClicked = (e: any, rewardInvoice: string) => { + setBadInvoice(''); + setShowRewardsSpinner(true); + + apiClient + .post('/api/reward/', { + invoice: rewardInvoice, + }) + .then((data) => { + setBadInvoice(data.bad_invoice); + setShowRewardsSpinner(false); + setWithdrawn(!!data.successful_withdrawal); + setOpenClaimRewards(!data.successful_withdrawal); + setRobot({ ...robot, earnedRewards: data.successful_withdrawal ? 0 : robot.earnedRewards }); + }); + e.preventDefault(); + }; + const handleClickEnableTelegram = () => { - window.open('https://t.me/' + tgBotName + '?start=' + tgToken, '_blank').focus(); + window.open('https://t.me/' + robot.tgBotName + '?start=' + robot.tgToken, '_blank').focus(); setOpenEnableTelegram(false); }; + const setStealthInvoice = (wantsStealth: boolean) => { + apiClient + .put('/api/stealth/', { wantsStealth }) + .then((data) => setRobot({ ...robot, stealthInvoices: data?.wantsStealth })); + }; + return ( @@ -143,7 +141,7 @@ const ProfileDialog = ({ - {nickname ? ( + {robot.nickname ? (
@@ -169,17 +167,17 @@ const ProfileDialog = ({ - {activeOrderId ? ( + {robot.activeOrderId ? ( @@ -188,21 +186,21 @@ const ProfileDialog = ({ - ) : lastOrderId ? ( + ) : robot.lastOrderId ? ( @@ -253,8 +251,8 @@ const ProfileDialog = ({ setOpenEnableTelegram(false)} - tgBotName={tgBotName} - tgToken={tgToken} + tgBotName={robot.tgBotName} + tgToken={robot.tgToken} onClickEnable={handleClickEnableTelegram} /> @@ -264,7 +262,7 @@ const ProfileDialog = ({ - {tgEnabled ? ( + {robot.tgEnabled ? ( {t('Telegram enabled')} @@ -295,8 +293,8 @@ const ProfileDialog = ({ label={t('Use stealth invoices')} control={ handleSetStealthInvoice(!stealthInvoices)} + checked={robot.stealthInvoices} + onChange={() => setStealthInvoice(!robot.stealthInvoices)} /> } /> @@ -335,7 +333,7 @@ const ProfileDialog = ({ - {`${earnedRewards} Sats`} + {`${robot.earnedRewards} Sats`}