diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/package-lock.json b/single-factor-auth-web/sfa-web-ton-telegram-example/package-lock.json index 53aa3733..12f2bb0c 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/package-lock.json +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/package-lock.json @@ -21,9 +21,10 @@ "@types/react": "^18.0.28", "@types/react-dom": "^18.0.10", "@vitejs/plugin-react": "^4.3.1", - "@web3auth/base": "^9.0.2", - "@web3auth/base-provider": "^9.0.2", - "@web3auth/single-factor-auth": "^9.0.0", + "@web3auth/base": "^9.3.0", + "@web3auth/base-provider": "^9.3.0", + "@web3auth/single-factor-auth": "^9.2.0", + "lucide-react": "^0.454.0", "react": "^18.3.1", "react-dom": "^18.3.1", "source-map-loader": "^4.0.1", diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.css b/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.css index 1f93ae85..d46f818a 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.css +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.css @@ -299,4 +299,19 @@ body { padding: 12px 0; margin-top: 12px; } -} \ No newline at end of file +} + +.breathing-outline { + border: 2px dashed rgba(0, 0, 0, 0.2); + border-radius: 8px; + animation: breathing 1.5s ease-in-out infinite; +} + +@keyframes breathing { + 0%, 100% { + border-color: rgba(0, 0, 0, 0.2); + } + 50% { + border-color: rgba(0, 0, 0, 0.5); + } +} diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.tsx b/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.tsx index 218a19e1..ff226aad 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.tsx +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/src/App.tsx @@ -1,13 +1,12 @@ import { useEffect, useState } from "react"; -import { Web3Auth, decodeToken } from "@web3auth/single-factor-auth"; +import { Web3Auth } from "@web3auth/single-factor-auth"; import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from "@web3auth/base"; import { CommonPrivateKeyProvider } from "@web3auth/base-provider"; import { getHttpEndpoint } from "@orbs-network/ton-access"; import TonRPC from "./tonRpc"; -import { useLaunchParams } from "@telegram-apps/sdk-react"; +import { useLaunchParams, User } from "@telegram-apps/sdk-react"; import { useTelegramMock } from "./hooks/useMockTelegramInitData"; import { Sun, Moon, Copy, Check } from "lucide-react"; -import Loading from "./components/Loading"; import TelegramLogo from "./assets/TelegramLogo.svg"; import web3AuthLogoLight from "./assets/web3AuthLogoLight.svg"; import web3AuthLogoDark from "./assets/web3AuthLogoDark.svg"; @@ -16,14 +15,18 @@ import "./App.css"; const verifier = "w3a-telegram-demo"; const clientId = "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ"; +// Gravatar fallback URL with a default image +const getGravatarUrl = (identifier: string) => { + const hash = identifier.toLowerCase(); // Use identifier directly for simplicity + return `https://www.gravatar.com/avatar/${hash}?d=mp`; +}; + function App() { - const [isLoggingIn, setIsLoggingIn] = useState(false); const [web3authSfa, setWeb3authSfa] = useState(null); const [web3AuthInitialized, setWeb3AuthInitialized] = useState(false); - const [userData, setUserData] = useState(null); + const [userData, setUserData] = useState(null); const [tonAccountAddress, setTonAccountAddress] = useState(null); const [signedMessage, setSignedMessage] = useState(null); - const [isLoggedIn, setIsLoggedIn] = useState(false); const [isDarkMode, setIsDarkMode] = useState(false); const [copiedStates, setCopiedStates] = useState<{ [key: string]: boolean }>({ account: false, @@ -85,29 +88,31 @@ function App() { initializeWeb3Auth(); }, []); + // Set user data directly from initData if available + useEffect(() => { + if (initData && initData.user) { + setUserData(initData.user); + } + }, [initData]); + useEffect(() => { const connectWeb3Auth = async () => { if (web3authSfa && web3AuthInitialized && initDataRaw) { - setIsLoggingIn(true); try { if (web3authSfa.status === "connected") { await web3authSfa.logout(); } - const idToken = await getIdTokenFromServer(initDataRaw, initData?.user.photoUrl); + const idToken = await getIdTokenFromServer(initDataRaw, initData?.user?.photoUrl); if (!idToken) return; - const { payload } = decodeToken(idToken); - await web3authSfa.connect({ verifier, - verifierId: (payload as any).sub, + verifierId: initData?.user?.id.toString(), idToken: idToken, }); - setUserData(payload); - setIsLoggedIn(true); - + // Set TON account address and signed message after connecting const tonRpc = new TonRPC(web3authSfa.provider); const tonAddress = await tonRpc.getAccounts(); setTonAccountAddress(tonAddress); @@ -117,8 +122,6 @@ function App() { setSignedMessage(signedMsg); } catch (error) { console.error("Error during Web3Auth connection:", error); - } finally { - setIsLoggingIn(false); } } }; @@ -126,7 +129,7 @@ function App() { if (web3AuthInitialized && initDataRaw) { connectWeb3Auth(); } - }, [initDataRaw, web3authSfa, web3AuthInitialized, initData?.user.photoUrl]); + }, [initDataRaw, web3authSfa, web3AuthInitialized, initData?.user?.photoUrl]); const getIdTokenFromServer = async (initDataRaw: string, photoUrl: string | undefined) => { const isMocked = !!sessionStorage.getItem("____mocked"); @@ -149,7 +152,6 @@ function App() { [type]: true, })); - // Reset the copied state after 2 seconds setTimeout(() => { setCopiedStates((prev) => ({ ...prev, @@ -173,56 +175,63 @@ function App() {

Web3Auth Telegram MiniApp

-

Seamless wallet access on any chain with Telegram. Just one click, and you're in!

- {isLoggingIn ? ( - - ) : ( -
- {isLoggedIn && ( + +
+
+ {userData ? ( <> -
- User avatar -
-
-

- ID: {userData?.telegram_id} -

- Telegram Logo -
-

- Username: {userData?.username} -

+ User avatar +
+

- Name: {userData?.name} + ID: {userData?.id}

+ Telegram Logo
-
-
copyToClipboard(tonAccountAddress || "", "account")}> -
-

- TON Account: - {tonAccountAddress} -

- {copiedStates.account ? : } -
-
-
copyToClipboard(signedMessage || "", "message")}> -
-

- Signed Message: - {signedMessage} -

- {copiedStates.message ? : } -
+

+ Username: {userData?.username} +

+

+ Name: {`${userData?.firstName} ${userData?.lastName || ""}`} +

+ ) : ( +

Loading user info...

)}
- )} + +
tonAccountAddress && copyToClipboard(tonAccountAddress, "account")} + > +
+

+ TON Account: + {tonAccountAddress || "Loading..."} +

+ {tonAccountAddress && + (copiedStates.account ? : )} +
+
+ +
signedMessage && copyToClipboard(signedMessage, "message")} + > +
+

+ Signed Message: + {signedMessage || "Loading..."} +

+ {signedMessage && (copiedStates.message ? : )} +
+
+