diff --git a/.env b/.env index c1948b4..e548574 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ -VITE_API_BASE_URL=https://my-public-node-1.projscale.dev/api/v1 \ No newline at end of file +VITE_API_BASE_URL=https://my-public-node-1.projscale.dev/api/v1 +SENTRY_DSN=https://4ef061d22eee4876ad8bb313134ebf009ed96c9da98742289ff733a301fcd184@k1.hawk.so/0 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 689d7c9..8b884c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@hookform/resolvers": "^3.3.4", + "@sentry/react": "^9.1.0", "@ton/core": "^0.59.1", "@tonconnect/ui-react": "^2.0.2", "@vkruglikov/react-telegram-web-app": "^2.1.9", @@ -1310,6 +1311,98 @@ "win32" ] }, + "node_modules/@sentry-internal/browser-utils": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.1.0.tgz", + "integrity": "sha512-S1uT+kkFlstWpwnaBTIJSwwAID8PS3aA0fIidOjNezeoUE5gOvpsjDATo9q+sl6FbGWynxMz6EnYSrq/5tuaBQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.1.0.tgz", + "integrity": "sha512-jTDCqkqH3QDC8m9WO4mB06hqnBRsl3p7ozoh0E774UvNB6blOEZjShhSGMMEy5jbbJajPWsOivCofUtFAwbfGw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.1.0.tgz", + "integrity": "sha512-E2xrUoms90qvm0BVOuaZ8QfkMoTUEgoIW/35uOeaqNcL7uOIj8c5cSEQQKit2Dr7CL6W+Ci5c6Khdyd5C0NL5w==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.1.0.tgz", + "integrity": "sha512-gxredVe+mOgfNqDJ3dTLiRON3FK1rZ8d0LHp7TICK/umLkWFkuso0DbNeyKU+3XCEjCr9VM7ZRqTDMzmY6zyVg==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.1.0.tgz", + "integrity": "sha512-G55e5j77DqRW3LkalJLAjRRfuyKrjHaKTnwIYXa6ycO+Q1+l14pEUxu+eK5Abu2rtSdViwRSb5/G6a/miSUlYA==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.1.0", + "@sentry-internal/feedback": "9.1.0", + "@sentry-internal/replay": "9.1.0", + "@sentry-internal/replay-canvas": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.1.0.tgz", + "integrity": "sha512-djWEzSBpMgqdF3GQuxO+kXCUX+Mgq42G4Uah/HSUBvPDHKipMmyWlutGRoFyVPPOnCDgpHu3wCt83wbpEyVmDw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.1.0.tgz", + "integrity": "sha512-aP2sXHH+erbomuzU762ktg340IGDh8zD7ueuqwBwGu98fhCpTYsLXiS85I29tUvPLljwNU9puLPmxbgW4iZ2tQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "9.1.0", + "@sentry/core": "9.1.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, "node_modules/@ton/core": { "version": "0.59.1", "resolved": "https://registry.npmjs.org/@ton/core/-/core-0.59.1.tgz", @@ -3661,7 +3754,6 @@ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "react-is": "^16.7.0" } diff --git a/package.json b/package.json index f4b588b..8559d60 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@hookform/resolvers": "^3.3.4", + "@sentry/react": "^9.1.0", "@ton/core": "^0.59.1", "@tonconnect/ui-react": "^2.0.2", "@vkruglikov/react-telegram-web-app": "^2.1.9", diff --git a/src/entry.tsx b/src/entry.tsx index 4517823..712f48c 100644 --- a/src/entry.tsx +++ b/src/entry.tsx @@ -1,3 +1,4 @@ +import './shared/services/sentry/index.ts'; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; diff --git a/src/pages/root/steps/data-step/components/disclaimer-modal/index.tsx b/src/pages/root/steps/data-step/components/disclaimer-modal/index.tsx new file mode 100644 index 0000000..9b20d66 --- /dev/null +++ b/src/pages/root/steps/data-step/components/disclaimer-modal/index.tsx @@ -0,0 +1,60 @@ +import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app"; +import { Button } from "~/shared/ui/button"; + +type DisclaimerModalProps = { + onConfirm(): void; +}; + +export const DisclaimerModal = ({ + onConfirm, +}: DisclaimerModalProps) => { + const [impactOccurred] = useHapticFeedback(); + + const handleClick = (fn: () => void) => { + impactOccurred("light"); + fn(); + }; + + return ( +
+
+
+

+ «Внимание! +

+

+ MY снимает с себя ответственность за правомерность загрузки контента пользователем. +

+

+ + Сервис исходит из личной + + ответственности пользователя перед законом и третьими лицами. MY категорически не приемлет любые виды пиратства, но признает за Пользователем право принятия самостоятельных решений. +

+

+ + Перед загрузкой контента + + необходимо убедиться, что первые 30 секунд контента, которые будут использоваться для превью, не содержат материалов, нарушающих возрастное ограничение 18+» +

+
+ + +
+
+ ); +}; diff --git a/src/pages/root/steps/data-step/index.tsx b/src/pages/root/steps/data-step/index.tsx index 8d4cdc6..eacd209 100644 --- a/src/pages/root/steps/data-step/index.tsx +++ b/src/pages/root/steps/data-step/index.tsx @@ -1,4 +1,4 @@ -import { useMemo } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; @@ -15,6 +15,7 @@ import { Checkbox } from "~/shared/ui/checkbox"; import { AudioPlayer } from "~/shared/ui/audio-player"; import { HashtagInput } from "~/shared/ui/hashtag-input"; import { Replace } from "~/shared/ui/icons/replace"; +import { DisclaimerModal } from "./components/disclaimer-modal"; type DataStepProps = { nextStep(): void; @@ -22,6 +23,8 @@ type DataStepProps = { export const DataStep = ({ nextStep }: DataStepProps) => { const rootStore = useRootStore(); + const [disclaimerAccepted, setDisclaimerAccepted] = useState(false); + const formSchema = useMemo(() => { return z.object({ @@ -64,8 +67,28 @@ export const DataStep = ({ nextStep }: DataStepProps) => { rootStore.setFileType(''); } + + useEffect(() => { + const storedValue = localStorage.getItem('disclaimerAccepted'); + if (storedValue === 'true') { + setDisclaimerAccepted(true); + } + }, []); + + const handleConfirmDisclaimer = () => { + setDisclaimerAccepted(true); + localStorage.setItem('disclaimerAccepted', 'true'); + }; + return (
+ + {(rootStore.fileSrc && !disclaimerAccepted) && + ( { + handleConfirmDisclaimer()}} + />)} +
/Заполните информацию о контенте
diff --git a/src/pages/root/steps/welcome-step/index.tsx b/src/pages/root/steps/welcome-step/index.tsx index 80243d2..ee75500 100644 --- a/src/pages/root/steps/welcome-step/index.tsx +++ b/src/pages/root/steps/welcome-step/index.tsx @@ -11,28 +11,51 @@ type WelcomeStepProps = { export const WelcomeStep = ({ nextStep }: WelcomeStepProps) => { const [tonConnectUI] = useTonConnectUI(); const [isLoaded, setLoaded] = useState(false); - + const [isConnected, setIsConnected] = useState(tonConnectUI.connected); + console.log("💩💩💩 enter WelcomeStep"); const auth = useAuth(); console.log("💩💩💩 after useAuth"); -const handleNextClick = async () => { - if (tonConnectUI.connected) { - await auth.mutateAsync(); - nextStep(); - } else { - try { - await tonConnectUI.openModal(); + useEffect(() => { + localStorage.setItem('disclaimerAccepted', 'false'); + }, []); + + useEffect(() => { + const unsubscribe = tonConnectUI.onStatusChange((wallet) => { + setIsConnected(!!wallet); + }); + + return () => { + unsubscribe(); + }; + }, [tonConnectUI]); + + const handleNextClick = async () => { + if (tonConnectUI.connected) { await auth.mutateAsync(); nextStep(); - } catch (error) { - console.error('Failed to connect or authenticate:', error); + } else { + try { + await tonConnectUI.openModal(); + await auth.mutateAsync(); + } catch (error) { + console.error('Failed to connect or authenticate:', error); + } + } + }; + + const handleDisconnect = async () => { + if (isConnected){ + try { + await tonConnectUI.disconnect(); + } catch (error) { + console.error('Failed to disconnect:', error); + } } } -}; - // useEffect(() => { // const first = setTimeout(async () => { // console.log("💩💩💩 call auth"); @@ -74,8 +97,8 @@ const handleNextClick = async () => { } return ( -
-
+
+
{"splash"} { />
-
- / Добро пожаловать в MY +
+
+ / Добро пожаловать в MY -
- [ -
- ]: +
+ [ +
+ ]: +
-
-
-

- децентрализованную систему монетизации контента. для продолжения - необходимо подключить криптокошелек TON -

+ + {isConnected ? + <> +
+

+ Вы зарегистрированы под кошельком: + {tonConnectUI.account?.address.slice(2, 9)}...{tonConnectUI.account?.address.slice(-4)} +

+
+
+
+ + : + <> +
+

+ Здесь вы можете загрузить свой контент.
Для продолжения подключите кошелек. +

+
+
+

+ Не волнуйтесь. Вы сможете поменять свой выбор в любой момент. +

+
+
- -
); }; \ No newline at end of file diff --git a/src/pages/view-content/components/congrats-modal/index.tsx b/src/pages/view-content/components/congrats-modal/index.tsx new file mode 100644 index 0000000..ee428a5 --- /dev/null +++ b/src/pages/view-content/components/congrats-modal/index.tsx @@ -0,0 +1,57 @@ +import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app"; +import { Button } from "~/shared/ui/button"; + +type CongratsModalProps = { + onConfirm(): void; +}; + +export const CongratsModal = ({ + onConfirm, +}: CongratsModalProps) => { + const [impactOccurred] = useHapticFeedback(); + + const handleClick = (fn: () => void) => { + impactOccurred("light"); + fn(); + }; + + return ( +
+
+
+

+ 🎉 + Поздравляем с покупкой! + 🎉 +

+

+ Ваш контент уже в пути! В ближайшее время в чат-боте MY Player вам придёт сообщение с доступом к купленному материалу. В этом чат-боте будет храниться весь ваш приобретённый контент. +

+

+ Теперь вы можете самостоятельно осуществить продажу купленного контента. + + Перешлите сообщение из чата My-Player друзьям или опубликуйте в своём Telegram-канале. Каждый, кто купит контент по вашей ссылке, принесёт вам доход, а автору — заслуженное вознаграждение. + +

+

+ Спасибо, что выбираете MY! +

+
+
+
+ ); +}; diff --git a/src/pages/view-content/components/error-modal/index.tsx b/src/pages/view-content/components/error-modal/index.tsx new file mode 100644 index 0000000..b60c8cc --- /dev/null +++ b/src/pages/view-content/components/error-modal/index.tsx @@ -0,0 +1,54 @@ +import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app"; +import { Button } from "~/shared/ui/button"; + +type ErrorModalProps = { + onConfirm(): void; +}; + +export const ErrorModal = ({ + onConfirm, +}: ErrorModalProps) => { + const [impactOccurred] = useHapticFeedback(); + + const handleClick = (fn: () => void) => { + impactOccurred("light"); + fn(); + }; + + return ( +
+
+
+

+ Ошибка запроса транзакции +

+

+ Не удалось отправить запрос на выполнение транзакции. +

+

+ + Попробуйте переподключить кошелек и повторить попытку. Если ошибка сохраняется, попробуйте запросить транзакцию еще раз. + +

+

+ Если проблема не исчезает, убедитесь, что ваш кошелек работает корректно, или свяжитесь с поддержкой. +

+
+
+
+ ); +}; diff --git a/src/pages/view-content/index.tsx b/src/pages/view-content/index.tsx index 877d5a6..3664400 100644 --- a/src/pages/view-content/index.tsx +++ b/src/pages/view-content/index.tsx @@ -5,9 +5,11 @@ import { useWebApp } from "@vkruglikov/react-telegram-web-app"; import { Button } from "~/shared/ui/button"; import { usePurchaseContent, useViewContent } from "~/shared/services/content"; import { fromNanoTON } from "~/shared/utils"; -import {useCallback, useEffect, useMemo} from "react"; +import {useCallback, useEffect, useMemo, useState} from "react"; import { AudioPlayer } from "~/shared/ui/audio-player"; import {useAuth} from "~/shared/services/auth"; +import { CongratsModal } from "./components/congrats-modal"; +import { ErrorModal } from "./components/error-modal"; export const ViewContentPage = () => { const WebApp = useWebApp(); @@ -20,8 +22,8 @@ export const ViewContentPage = () => { const auth = useAuth(); - - + const [isCongratsModal, setIsCongratsModal] = useState(false); + const [isErrorModal, setIsErrorModal] = useState(false); const handleBuyContent = useCallback(async () => { try { if (!tonConnectUI.connected) { @@ -50,11 +52,14 @@ export const ViewContentPage = () => { if (transactionResponse.boc) { void refetchContent() + setIsCongratsModal(true); console.log(transactionResponse.boc, "PURCHASED") } else { + setIsErrorModal(true); console.error("Transaction failed:", transactionResponse); } } catch (error) { + setIsErrorModal(true); console.error("Error handling Ton Connect subscription:", error); } }, [content, tonConnectUI.connected]); @@ -71,19 +76,28 @@ export const ViewContentPage = () => { return () => clearInterval(interval) }, []); + const handleConfirmCongrats = () => { + setIsCongratsModal(!isCongratsModal); + }; - + const handleErrorModal = () => { + setIsErrorModal(!isErrorModal); + } return ( -
- {content?.data?.content_type.startsWith("audio") && content?.data?.display_options?.metadata?.image && ( -
- {"content_image"} -
- )} +
+ {isCongratsModal && } + {isErrorModal && } + {content?.data?.content_type.startsWith("audio") && content?.data?.display_options?.metadata?.image && ( +
+ {"content_image"} +
+ )} {content?.data?.content_type.startsWith("audio") ? ( diff --git a/src/shared/services/auth/index.ts b/src/shared/services/auth/index.ts index fd0a308..bc63a47 100644 --- a/src/shared/services/auth/index.ts +++ b/src/shared/services/auth/index.ts @@ -1,5 +1,5 @@ import { useRef } from "react"; -import { useTonConnectUI, useTonWallet } from "@tonconnect/ui-react"; +import { useTonConnectUI } from "@tonconnect/ui-react"; import { useMutation } from "react-query"; import { request } from "~/shared/libs"; import { useWebApp } from "@vkruglikov/react-telegram-web-app"; @@ -9,7 +9,7 @@ const payloadTTLMS = 1000 * 60 * 20; export const useAuth = () => { const WebApp = useWebApp(); - const wallet = useTonWallet(); + // const wallet = useTonWallet(); const [tonConnectUI] = useTonConnectUI(); const interval = useRef | undefined>(); @@ -94,17 +94,20 @@ export const useAuth = () => { }); } + // Commented this part for two reasons: + // 1) When we include ton_proof from the wallet it fails the call for a reason of bad ton_proof + // 2) This call could happen only if the first case happened and it means that the ton_proof is already have been stored once before // Case 2: Connected with proof - use it - if (wallet?.connectItems?.tonProof && !("error" in wallet.connectItems.tonProof)) { - console.log("DEBUG: Using existing proof"); - return makeAuthRequest({ - twa_data: WebApp.initData, - ton_proof: { - account: wallet.account, - ton_proof: wallet.connectItems.tonProof.proof, - }, - }); - } + // if (wallet?.connectItems?.tonProof && !("error" in wallet.connectItems.tonProof)) { + // console.log("DEBUG: Using existing proof", wallet.connectItems.tonProof.proof); + // return makeAuthRequest({ + // twa_data: WebApp.initData, + // ton_proof: { + // account: wallet.account, + // ton_proof: wallet.connectItems.tonProof.proof, + // }, + // }); + // } // Case 3: Connected without proof - already authenticated console.log("DEBUG: Connected without proof, proceeding without it"); diff --git a/src/shared/services/sentry/index.ts b/src/shared/services/sentry/index.ts new file mode 100644 index 0000000..0e6eca4 --- /dev/null +++ b/src/shared/services/sentry/index.ts @@ -0,0 +1,42 @@ +import { useEffect } from "react"; +import * as Sentry from "@sentry/react"; +import { + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, +} from "react-router-dom"; + +Sentry.init({ + dsn: import.meta.env.SENTRY_DSN, + integrations: [ + // See docs for support of different versions of variation of react router + // https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/ + Sentry.reactRouterV6BrowserTracingIntegration({ + useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + Sentry.replayIntegration(), + ], + + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for tracing. + // Learn more at + // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate + tracesSampleRate: 1.0, + + // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled + tracePropagationTargets: [ + /^\//, + new RegExp(`^${import.meta.env.VITE_API_BASE_URL}`), + ], + // Capture Replay for 10% of all sessions, + // plus for 100% of sessions with an error + // Learn more at + // https://docs.sentry.io/platforms/javascript/session-replay/configuration/#general-integration-configuration + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, +}); diff --git a/yarn.lock b/yarn.lock index b76ae4b..9511a7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -386,6 +386,61 @@ resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz" integrity sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg== +"@sentry-internal/browser-utils@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.1.0.tgz" + integrity sha512-S1uT+kkFlstWpwnaBTIJSwwAID8PS3aA0fIidOjNezeoUE5gOvpsjDATo9q+sl6FbGWynxMz6EnYSrq/5tuaBQ== + dependencies: + "@sentry/core" "9.1.0" + +"@sentry-internal/feedback@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.1.0.tgz" + integrity sha512-jTDCqkqH3QDC8m9WO4mB06hqnBRsl3p7ozoh0E774UvNB6blOEZjShhSGMMEy5jbbJajPWsOivCofUtFAwbfGw== + dependencies: + "@sentry/core" "9.1.0" + +"@sentry-internal/replay-canvas@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.1.0.tgz" + integrity sha512-gxredVe+mOgfNqDJ3dTLiRON3FK1rZ8d0LHp7TICK/umLkWFkuso0DbNeyKU+3XCEjCr9VM7ZRqTDMzmY6zyVg== + dependencies: + "@sentry-internal/replay" "9.1.0" + "@sentry/core" "9.1.0" + +"@sentry-internal/replay@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.1.0.tgz" + integrity sha512-E2xrUoms90qvm0BVOuaZ8QfkMoTUEgoIW/35uOeaqNcL7uOIj8c5cSEQQKit2Dr7CL6W+Ci5c6Khdyd5C0NL5w== + dependencies: + "@sentry-internal/browser-utils" "9.1.0" + "@sentry/core" "9.1.0" + +"@sentry/browser@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry/browser/-/browser-9.1.0.tgz" + integrity sha512-G55e5j77DqRW3LkalJLAjRRfuyKrjHaKTnwIYXa6ycO+Q1+l14pEUxu+eK5Abu2rtSdViwRSb5/G6a/miSUlYA== + dependencies: + "@sentry-internal/browser-utils" "9.1.0" + "@sentry-internal/feedback" "9.1.0" + "@sentry-internal/replay" "9.1.0" + "@sentry-internal/replay-canvas" "9.1.0" + "@sentry/core" "9.1.0" + +"@sentry/core@9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry/core/-/core-9.1.0.tgz" + integrity sha512-djWEzSBpMgqdF3GQuxO+kXCUX+Mgq42G4Uah/HSUBvPDHKipMmyWlutGRoFyVPPOnCDgpHu3wCt83wbpEyVmDw== + +"@sentry/react@^9.1.0": + version "9.1.0" + resolved "https://registry.npmjs.org/@sentry/react/-/react-9.1.0.tgz" + integrity sha512-aP2sXHH+erbomuzU762ktg340IGDh8zD7ueuqwBwGu98fhCpTYsLXiS85I29tUvPLljwNU9puLPmxbgW4iZ2tQ== + dependencies: + "@sentry/browser" "9.1.0" + "@sentry/core" "9.1.0" + hoist-non-react-statics "^3.3.2" + "@ton/core@^0.59.1": version "0.59.1" resolved "https://registry.npmjs.org/@ton/core/-/core-0.59.1.tgz" @@ -2589,7 +2644,7 @@ react-tag-input@^6.10.3: classnames "~2.3.1" lodash-es "^4.17.21" -"react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18, react@^18.2.0, "react@>= 16.14", react@>=16.6.0, react@>=16.8, react@>=17.0.0: +"react@^16.14.0 || 17.x || 18.x || 19.x", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18, react@^18.2.0, "react@>= 16.14", react@>=16.6.0, react@>=16.8, react@>=17.0.0: version "18.2.0" resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==