From 4102e145f694adb67078a95bb639346a13752e69 Mon Sep 17 00:00:00 2001 From: Maharshi Mishra Date: Mon, 28 Oct 2024 09:55:17 +0530 Subject: [PATCH 01/13] tweaked with MainButton parameter --- .../sfa-web-ton-telegram-example/.env | 2 +- .../sfa-web-ton-telegram-example/src/App.tsx | 144 +++++------------- .../src/assets/{Logo.svg => TelegramLogo.svg} | 0 .../src/{ => assets}/spinner.svg | 0 .../src/assets/web3AuthLogoDark.png | Bin 0 -> 1692 bytes .../src/assets/web3AuthLogoLight.png | Bin 0 -> 2030 bytes .../src/{ => components}/Loading.tsx | 2 +- 7 files changed, 42 insertions(+), 106 deletions(-) rename single-factor-auth-web/sfa-web-ton-telegram-example/src/assets/{Logo.svg => TelegramLogo.svg} (100%) rename single-factor-auth-web/sfa-web-ton-telegram-example/src/{ => assets}/spinner.svg (100%) create mode 100644 single-factor-auth-web/sfa-web-ton-telegram-example/src/assets/web3AuthLogoDark.png create mode 100644 single-factor-auth-web/sfa-web-ton-telegram-example/src/assets/web3AuthLogoLight.png rename single-factor-auth-web/sfa-web-ton-telegram-example/src/{ => components}/Loading.tsx (63%) diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/.env b/single-factor-auth-web/sfa-web-ton-telegram-example/.env index 3048f226..75a4abe6 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/.env +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/.env @@ -1,4 +1,4 @@ -VITE_SERVER_URL="" # server-url +VITE_SERVER_URL="http://localhost:3000" # server-url VITE_W3A_VERIFIER_NAME="" # w3a-verifier-name VITE_W3A_CLIENT_ID="" # w3a-client-id from web3auth dashboard REACT_APP_SERVER_URL="http://localhost:3000" # server-url 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 1b4a39f2..29f8e7c0 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 @@ -4,10 +4,10 @@ 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 the TonRPC class -import { useLaunchParams } from "@telegram-apps/sdk-react"; +import { useLaunchParams, mainButton } from "@telegram-apps/sdk-react"; import { useTelegramMock } from "./hooks/useMockTelegramInitData"; -import Loading from "./Loading"; -import TelegramLogo from "./assets/Logo.svg"; // Assuming the logo is in the assets folder +import Loading from "./components/Loading"; +import TelegramLogo from "./assets/TelegramLogo.svg"; // Assuming the logo is in the assets folder import "./App.css"; const verifier = "w3a-telegram-demo"; @@ -17,7 +17,7 @@ function App() { const [isLoggingIn, setIsLoggingIn] = useState(false); const [web3authSfa, setWeb3authSfa] = useState(null); const [web3AuthInitialized, setWeb3AuthInitialized] = useState(false); - const [userData, setUserData] = useState(null); // State to hold parsed user info + const [userData, setUserData] = useState(null); const [tonAccountAddress, setTonAccountAddress] = useState(null); const [signedMessage, setSignedMessage] = useState(null); const [isLoggedIn, setIsLoggedIn] = useState(false); @@ -38,27 +38,21 @@ function App() { useEffect(() => { const initializeWeb3Auth = async () => { try { - console.log("Fetching TON Testnet RPC endpoint..."); const testnetRpc = await getHttpEndpoint({ network: "testnet", protocol: "json-rpc", }); - console.log("TON Testnet RPC endpoint: ", testnetRpc); - const chainConfig = { chainNamespace: CHAIN_NAMESPACES.OTHER, chainId: "testnet", rpcTarget: testnetRpc, displayName: "TON Testnet", - blockExplorerUrl: "https://testnet.tonscan.org", ticker: "TON", tickerName: "Toncoin", }; - const privateKeyProvider = new CommonPrivateKeyProvider({ - config: { chainConfig }, - }); + const privateKeyProvider = new CommonPrivateKeyProvider({ config: { chainConfig } }); const web3authInstance = new Web3Auth({ clientId, @@ -69,13 +63,10 @@ function App() { setWeb3authSfa(web3authInstance); - console.log("Initializing Web3Auth..."); - await web3authInstance.init(); // Ensure Web3Auth is initialized - console.log("Web3Auth initialized."); - + await web3authInstance.init(); setWeb3AuthInitialized(true); } catch (error) { - console.error("Error fetching TON Testnet RPC endpoint: ", error); + console.error("Error initializing Web3Auth:", error); } }; @@ -87,30 +78,14 @@ function App() { if (web3authSfa && web3AuthInitialized && initDataRaw) { setIsLoggingIn(true); try { - console.log("Checking Web3Auth connection status..."); - if (web3authSfa.status === "connected") { await web3authSfa.logout(); - console.log("Logged out successfully."); } - if (web3authSfa.status === "not_ready") { - await web3authSfa.init(); - console.log("Web3Auth initialized."); - } - console.log("initData: ", initData); - console.log("initData.user: ", initData.user); - console.log("initData.user.photoUrl: ", initData.user.photoUrl); - - const idToken = await getIdTokenFromServer(initDataRaw, initData.user.photoUrl); // Pass photoUrl - if (!idToken) { - console.error("No ID token found."); - setIsLoggingIn(false); - return; - } + const idToken = await getIdTokenFromServer(initDataRaw, initData.user.photoUrl); + if (!idToken) return; const { payload } = decodeToken(idToken); - console.log("Decoded idToken payload: ", payload); await web3authSfa.connect({ verifier, @@ -118,19 +93,29 @@ function App() { idToken: idToken, }); - console.log("Successfully logged in."); setUserData(payload); setIsLoggedIn(true); - // Initialize TonRPC and fetch the account address const tonRpc = new TonRPC(web3authSfa.provider); const tonAddress = await tonRpc.getAccounts(); - setTonAccountAddress(tonAddress); // Set the TON address dynamically + setTonAccountAddress(tonAddress); - // Sign a message and set it const messageToSign = "Hello, TON!"; const signedMsg = await tonRpc.signMessage(messageToSign); - setSignedMessage(signedMsg); // Set the signed message + setSignedMessage(signedMsg); + + mainButton.setParams({ + text: tonAccountAddress ? "Copy TON Address" : "Copy Signed Message", + backgroundColor: "#000000", + textColor: "#ffffff", + isVisible: true, + }); + + mainButton.onClick(() => { + const textToCopy = tonAccountAddress || signedMessage || ""; + navigator.clipboard.writeText(textToCopy); + alert("Copied to clipboard!"); + }); } catch (error) { console.error("Error during Web3Auth connection:", error); } finally { @@ -142,89 +127,40 @@ function App() { if (web3AuthInitialized && initDataRaw) { connectWeb3Auth(); } - }, [initDataRaw, web3authSfa, web3AuthInitialized]); + }, [initDataRaw, web3authSfa, web3AuthInitialized, tonAccountAddress, signedMessage]); const getIdTokenFromServer = async (initDataRaw: string, photoUrl: string | undefined) => { const isMocked = !!sessionStorage.getItem("____mocked"); - const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/auth/telegram`, { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ initDataRaw, isMocked, photoUrl }), // Send photoUrl as an additional field + body: JSON.stringify({ initDataRaw, isMocked, photoUrl }), }); - const data = await response.json(); - console.log("Received ID token from server:", data.token); return data.token; }; - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text); - alert("Copied to clipboard!"); - }; - - const userInfoBox = ( -
- User avatar -
-
-

- ID: {userData?.telegram_id} -

- Telegram Logo -
-

- Username: {userData?.username} -

-

- Name: {userData?.name} -

-
-
- ); - - const tonAccountBox = ( -
copyToClipboard(tonAccountAddress || "")}> -

- TON Account: {tonAccountAddress} -

-
- ); - - const signedMessageBox = ( -
copyToClipboard(signedMessage || "")}> -

- Signed Message: {signedMessage} -

-
- ); - - const logoutView = ( -
- -
- ); - return (

Web3Auth TON Telegram MiniApp

- {isLoggingIn ? ( - - ) : ( + {isLoggingIn ? : null} + {isLoggedIn ? (
- {isLoggedIn ? ( - <> - {userInfoBox} - {tonAccountBox} - {signedMessageBox} - - ) : ( - logoutView - )} +
+ User avatar +
+

+ Username: {userData?.username} +

+

+ Name: {userData?.name} +

+
+
- )} + ) : null}
From 0e519aa9fd6736bf5e0702eee62d9d96a06e48f3 Mon Sep 17 00:00:00 2001 From: Maharshi Mishra Date: Tue, 29 Oct 2024 10:52:25 +0530 Subject: [PATCH 10/13] theme tweak, fixed alignment of webhook --- .../server/api/telegram.js | 81 +++++++------- .../sfa-web-ton-telegram-example/src/App.css | 101 +++++++++++++----- .../sfa-web-ton-telegram-example/src/App.tsx | 35 +++--- 3 files changed, 126 insertions(+), 91 deletions(-) diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js b/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js index e086718e..9dec5539 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js @@ -1,51 +1,48 @@ import { Telegraf } from "telegraf"; export default async function handler(req, res) { - if (req.method !== 'POST') { - return res.status(405).json({ error: 'Method not allowed' }); - } + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method not allowed' }); + } - const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN); - - // Command handler - bot.command('start', async (ctx) => { - await ctx.reply( - `Welcome to Web3Auth MiniApp! 🌟 - - Experience blockchain wallets reimagined inside Telegram! Our demo showcases integration with the TON blockchain, but that's just the beginning - the same seamless experience can be adapted for any blockchain network. - - How does it work? It's brilliantly simple: - - Your Telegram identity securely powers your Web3 wallet creation - - Access your wallet seamlessly across all your Telegram devices - - No repeated setups - your wallet is always ready when you are - - Ready to experience the future of Web3 authentication?`, - { - reply_markup: { - inline_keyboard: [[ - { - text: "Launch Web3Auth MiniApp 🚀", - web_app: { url: process.env.APP_URL } - } - ]] - } - } - ); - }); + const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN); + + bot.command('start', async (ctx) => { + await ctx.reply( +`Welcome to Web3Auth MiniApp! 🌟 - try { - // Process the update - await bot.handleUpdate(req.body); - res.status(200).json({ ok: true }); - } catch (error) { - console.error('Webhook handling error:', error); - res.status(500).json({ error: 'Failed to process update' }); - } +Experience blockchain wallets reimagined inside Telegram! Our demo showcases integration with the TON blockchain, but that's just the beginning - the same seamless experience can be adapted for any blockchain network. + +How does it work? It's brilliantly simple: +- Your Telegram identity securely powers your Web3 wallet creation +- Access your wallet seamlessly across all your Telegram devices +- No repeated setups - your wallet is always ready when you are + +Ready to experience the future of Web3 authentication?`, + { + reply_markup: { + inline_keyboard: [[ + { + text: "Launch Web3Auth MiniApp 🚀", + web_app: { url: process.env.APP_URL } + } + ]] + } + } + ); + }); + + try { + await bot.handleUpdate(req.body); + res.status(200).json({ ok: true }); + } catch (error) { + console.error('Webhook handling error:', error); + res.status(500).json({ error: 'Failed to process update' }); + } } -// Disable body parsing as Telegram sends updates in raw format export const config = { - api: { - bodyParser: false, - }, + api: { + bodyParser: false, + }, }; \ No newline at end of file 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 cf5f1ca8..c5d89735 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 @@ -1,28 +1,39 @@ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); :root { - --bg-color: #ffffff; - --text-color: #333333; + --bg-color: #f8faff; + --text-color: #1a1b25; --border-color: #e0e0e0; --hover-bg: rgba(0, 0, 0, 0.05); - --box-shadow: rgba(0, 0, 0, 0.1); + --box-shadow: rgba(0, 0, 0, 0.08); + --card-bg: #ffffff; } -.dark-mode { - --bg-color: #1a1a1a; +:root.dark-mode { + --bg-color: #0F1221; --text-color: #ffffff; - --border-color: #333333; + --border-color: #2a2d3d; --hover-bg: rgba(255, 255, 255, 0.1); - --box-shadow: rgba(0, 0, 0, 0.2); + --box-shadow: rgba(0, 0, 0, 0.3); + --card-bg: #1A1F35; } body { font-family: 'Inter', sans-serif; - background-color: var(--bg-color); - color: var(--text-color); margin: 0; padding: 0; - transition: background-color 0.3s ease, color 0.3s ease; + min-height: 100vh; + background: var(--bg-color); + color: var(--text-color); + transition: all 0.3s ease; +} + +body:not(.dark-mode) { + background: linear-gradient(135deg, #f5f7ff 0%, #eef1ff 100%); +} + +body.dark-mode { + background: #0F1221; } .container { @@ -30,7 +41,6 @@ body { max-width: 600px; margin: auto; padding: 20px; - background-color: var(--bg-color); color: var(--text-color); } @@ -39,24 +49,27 @@ body { flex-direction: column; align-items: center; text-align: center; - gap: 20px; - margin-bottom: 30px; + gap: 12px; + margin-bottom: 40px; position: relative; width: 100%; + padding-top: 10px; } .logo-container { position: relative; width: 100%; display: flex; - justify-content: center; align-items: center; + justify-content: center; + margin-bottom: 24px; } .web3auth-logo { - width: 150px; + width: 180px; height: auto; margin: 0 auto; + filter: drop-shadow(0 2px 4px var(--box-shadow)); } .theme-toggle { @@ -66,13 +79,14 @@ body { transform: translateY(-50%); padding: 8px; border-radius: 50%; + background: var(--card-bg); border: 1px solid var(--border-color); - background-color: var(--bg-color); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; + margin-right: 10px; } .theme-toggle:hover { @@ -86,18 +100,28 @@ body { } .title { - font-size: 1.8rem; - font-weight: 700; + font-size: 2rem; + font-weight: 800; margin: 0; - color: var(--text-color); + letter-spacing: -0.5px; + background: linear-gradient(to right, #66D4F6, #4D92FF, #BB65FF); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + margin-bottom: 12px; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .description { - font-size: 1rem; - font-weight: 400; - margin: 10px 0; + font-size: 1.1rem; + font-weight: 500; + line-height: 1.5; + margin: 16px 0 24px 0; text-align: center; color: var(--text-color); + opacity: 0.9; + max-width: 500px; + padding: 0 20px; } .how-it-works { @@ -133,9 +157,9 @@ body { padding: 20px; margin: 0; border: 1px solid var(--border-color); - border-radius: 10px; - background-color: var(--bg-color); - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border-radius: 12px; + background: var(--card-bg); + box-shadow: 0 4px 12px var(--box-shadow); width: 100%; cursor: pointer; transition: all 0.3s ease; @@ -156,6 +180,19 @@ body { transform: translateY(-2px); } +.dark-mode .user-info-box, +.dark-mode .info-box { + background: #1A1F35; + border-color: rgba(255, 255, 255, 0.1); +} + +.dark-mode .info-box:hover, +.dark-mode .learn-more-button:hover, +.dark-mode .theme-toggle:hover { + background: rgba(255, 255, 255, 0.05); + border-color: rgba(255, 255, 255, 0.2); +} + .user-info { display: flex; flex-direction: column; @@ -253,9 +290,10 @@ body { border-radius: 8px; text-decoration: none; transition: all 0.3s ease; - background-color: var(--bg-color); color: var(--text-color); + background: var(--card-bg); border: 1px solid var(--border-color); + box-shadow: 0 2px 8px var(--box-shadow); } .learn-more-button:hover { @@ -263,6 +301,12 @@ body { border-color: var(--text-color); } +.dark-mode .learn-more-button, +.dark-mode .theme-toggle { + background: #1A1F35; + border-color: rgba(255, 255, 255, 0.1); +} + @media (max-width: 768px) { .container { width: 95%; @@ -274,7 +318,10 @@ body { } .web3auth-logo { - width: 120px; + width: 180px; + height: auto; + margin: 0 auto; + filter: drop-shadow(0 2px 4px var(--box-shadow)); } .user-info-box { 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 e12b8a75..218a19e1 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 @@ -39,11 +39,13 @@ function App() { }; useEffect(() => { - const newBgColor = isDarkMode ? "#1a1a1a" : "#ffffff"; - const newTextColor = isDarkMode ? "#ffffff" : "#333333"; - document.documentElement.style.setProperty("--bg-color", newBgColor); - document.documentElement.style.setProperty("--text-color", newTextColor); - document.documentElement.classList.toggle("dark-mode", isDarkMode); + if (isDarkMode) { + document.documentElement.classList.add("dark-mode"); + document.body.classList.add("dark-mode"); + } else { + document.documentElement.classList.remove("dark-mode"); + document.body.classList.remove("dark-mode"); + } }, [isDarkMode]); useEffect(() => { @@ -168,25 +170,14 @@ function App() { {isDarkMode ? : } -

Telegram MiniApp Demo

- - -
-

- Seamlessly generate a blockchain wallet with Web3Auth right inside Telegram. This demo shows a wallet for the TON blockchain, but it's fully - adaptable for any other chain. No extra steps—just connect and go! -

-
+
+

Web3Auth Telegram MiniApp

+
-
-

How It Works

-
    -
  • Your Telegram account authenticates you securely, creating an embedded wallet.
  • -
  • The wallet is available across both desktop and mobile Telegram clients.
  • -
  • Your wallet stays accessible whenever you log in with Telegram—no setup needed each time.
  • -
+
+

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

+
- {isLoggingIn ? ( ) : ( From 78073222ead705c21c8002cb303dd9fa90a8580d Mon Sep 17 00:00:00 2001 From: Maharshi Mishra Date: Tue, 29 Oct 2024 12:01:50 +0530 Subject: [PATCH 11/13] Changed the App css --- .../sfa-web-ton-telegram-example/src/App.css | 444 ++++++++---------- 1 file changed, 208 insertions(+), 236 deletions(-) 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 c5d89735..1f93ae85 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 @@ -1,330 +1,302 @@ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); :root { - --bg-color: #f8faff; - --text-color: #1a1b25; - --border-color: #e0e0e0; - --hover-bg: rgba(0, 0, 0, 0.05); - --box-shadow: rgba(0, 0, 0, 0.08); - --card-bg: #ffffff; + --bg-color: #f8faff; + --text-color: #1a1b25; + --border-color: #e0e0e0; + --hover-bg: rgba(0, 0, 0, 0.05); + --box-shadow: rgba(0, 0, 0, 0.08); + --card-bg: #ffffff; } :root.dark-mode { - --bg-color: #0F1221; - --text-color: #ffffff; - --border-color: #2a2d3d; - --hover-bg: rgba(255, 255, 255, 0.1); - --box-shadow: rgba(0, 0, 0, 0.3); - --card-bg: #1A1F35; + --bg-color: #0F1221; + --text-color: #ffffff; + --border-color: #2a2d3d; + --hover-bg: rgba(255, 255, 255, 0.1); + --box-shadow: rgba(0, 0, 0, 0.3); + --card-bg: #1a1f35; } -body { - font-family: 'Inter', sans-serif; - margin: 0; - padding: 0; - min-height: 100vh; - background: var(--bg-color); - color: var(--text-color); - transition: all 0.3s ease; -} - -body:not(.dark-mode) { - background: linear-gradient(135deg, #f5f7ff 0%, #eef1ff 100%); +/* Base styles */ +html, body { + max-width: 100vw; + overflow-x: hidden; + margin: 0; + padding: 0; } -body.dark-mode { - background: #0F1221; +body { + font-family: 'Inter', sans-serif; + background: var(--bg-color); + color: var(--text-color); + min-height: 100vh; + transition: background-color 0.3s ease; } +/* Container */ .container { - width: 90%; - max-width: 600px; - margin: auto; - padding: 20px; - color: var(--text-color); -} - + width: 100%; + max-width: min(600px, 90%); + margin: 0 auto; + padding: 16px; + min-height: 100vh; + display: flex; + flex-direction: column; + justify-content: space-between; + box-sizing: border-box; +} + +/* Header section */ .header { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - gap: 12px; - margin-bottom: 40px; - position: relative; - width: 100%; - padding-top: 10px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; + margin-bottom: 24px; } .logo-container { - position: relative; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 24px; + position: relative; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 16px; } .web3auth-logo { - width: 180px; - height: auto; - margin: 0 auto; - filter: drop-shadow(0 2px 4px var(--box-shadow)); + width: min(180px, 40%); + height: auto; + margin: 0 auto; + filter: drop-shadow(0 2px 4px var(--box-shadow)); } .theme-toggle { - position: absolute; - right: 0; - top: 50%; - transform: translateY(-50%); - padding: 8px; - border-radius: 50%; - background: var(--card-bg); - border: 1px solid var(--border-color); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.3s ease; - margin-right: 10px; + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + padding: 8px; + border-radius: 50%; + background: var(--card-bg); + border: 1px solid var(--border-color); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; } .theme-toggle:hover { - background-color: var(--hover-bg); + background-color: var(--hover-bg); } .theme-toggle svg { - width: 20px; - height: 20px; - color: var(--text-color); + width: 20px; + height: 20px; + color: var(--text-color); } +/* Title and description */ .title { - font-size: 2rem; - font-weight: 800; - margin: 0; - letter-spacing: -0.5px; - background: linear-gradient(to right, #66D4F6, #4D92FF, #BB65FF); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - margin-bottom: 12px; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + font-size: clamp(1.5rem, 4vw, 2rem); + font-weight: 800; + margin: 0; + letter-spacing: -0.5px; + background: linear-gradient(to right, #66D4F6, #4D92FF, #BB65FF); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; } .description { - font-size: 1.1rem; - font-weight: 500; - line-height: 1.5; - margin: 16px 0 24px 0; - text-align: center; - color: var(--text-color); - opacity: 0.9; - max-width: 500px; - padding: 0 20px; -} - -.how-it-works { - margin: 20px 0; - text-align: center; - color: var(--text-color); -} - -.how-it-works h3 { - font-size: 1.5rem; - font-weight: 600; -} - -.how-it-works ul { - list-style-type: none; - padding: 0; - font-weight: 400; -} - -.how-it-works li { - margin: 10px 0; -} - + font-size: clamp(0.9rem, 3vw, 1.1rem); + font-weight: 500; + line-height: 1.5; + margin: 8px 0 16px; + text-align: center; + color: var(--text-color); + opacity: 0.9; + max-width: 500px; + padding: 0 16px; +} + +/* Grid layout */ .grid { - display: flex; - flex-direction: column; - gap: 15px; - margin: 20px 0; - width: 100%; + display: flex; + flex-direction: column; + gap: 12px; + margin: 16px 0; } +/* Info boxes */ .user-info-box, .info-box { - padding: 20px; - margin: 0; - border: 1px solid var(--border-color); - border-radius: 12px; - background: var(--card-bg); - box-shadow: 0 4px 12px var(--box-shadow); - width: 100%; - cursor: pointer; - transition: all 0.3s ease; - box-sizing: border-box; + padding: 16px; + margin: 0; + border: 1px solid var(--border-color); + border-radius: 12px; + background: var(--card-bg); + box-shadow: 0 4px 12px var(--box-shadow); + width: 100%; + cursor: pointer; + transition: all 0.3s ease; + box-sizing: border-box; } .user-info-box { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 15px; - flex-wrap: wrap; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 15px; + flex-wrap: wrap; } .info-box:hover { - background-color: var(--hover-bg); - border-color: var(--text-color); - transform: translateY(-2px); -} - -.dark-mode .user-info-box, -.dark-mode .info-box { - background: #1A1F35; - border-color: rgba(255, 255, 255, 0.1); -} - -.dark-mode .info-box:hover, -.dark-mode .learn-more-button:hover, -.dark-mode .theme-toggle:hover { - background: rgba(255, 255, 255, 0.05); - border-color: rgba(255, 255, 255, 0.2); + background-color: var(--hover-bg); + border-color: var(--text-color); + transform: translateY(-2px); } +/* User info */ .user-info { - display: flex; - flex-direction: column; - gap: 8px; + display: flex; + flex-direction: column; + gap: 8px; } .user-info p { - margin: 0; - display: flex; - align-items: center; - gap: 8px; + margin: 0; + display: flex; + align-items: center; + gap: 8px; } .user-info strong { - color: var(--text-color); + color: var(--text-color); } .id-with-logo { - display: flex; - align-items: center; - gap: 8px; + display: flex; + align-items: center; + gap: 8px; } .telegram-logo { - width: 20px; - height: 20px; + width: 20px; + height: 20px; } .user-avatar { - width: 50px; - height: 50px; - border-radius: 50%; - object-fit: cover; + width: 50px; + height: 50px; + border-radius: 50%; + object-fit: cover; } +/* Info box content */ .info-box-content { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 10px; - width: 100%; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 10px; + width: 100%; } .info-box-content p { - margin: 0; - flex: 1; - text-align: left; - min-width: 0; + margin: 0; + flex: 1; + text-align: left; + min-width: 0; } .info-box-content strong { - display: block; - margin-bottom: 5px; + display: block; + margin-bottom: 5px; } .ellipsed-text { - display: block; - width: 100%; - word-wrap: break-word; - word-break: break-all; - font-family: monospace; - font-size: 0.9em; - text-align: left; + display: block; + width: 100%; + word-wrap: break-word; + word-break: break-all; + font-family: monospace; + font-size: clamp(0.75rem, 2.5vw, 0.9rem); + text-align: left; } +/* Copy icon */ .copy-icon { - color: var(--text-color); - opacity: 0.6; - transition: all 0.2s ease; - flex-shrink: 0; - margin-top: 4px; + color: var(--text-color); + opacity: 0.6; + transition: all 0.2s ease; + flex-shrink: 0; + margin-top: 4px; } .copy-icon.success { - color: #4CAF50; - opacity: 1; + color: #4CAF50; + opacity: 1; } .info-box:hover .copy-icon { - opacity: 1; + opacity: 1; } +/* Footer */ .footer { - display: flex; - justify-content: center; - padding: 2rem 0; - border-top: 1px solid var(--border-color); - margin-top: 30px; + display: flex; + justify-content: center; + padding: 16px 0; + margin-top: 16px; + position: relative; + border-top: 1px solid var(--border-color); } .learn-more-button { - padding: 12px 24px; - font-weight: 600; - text-align: center; - border-radius: 8px; - text-decoration: none; - transition: all 0.3s ease; - color: var(--text-color); - background: var(--card-bg); - border: 1px solid var(--border-color); - box-shadow: 0 2px 8px var(--box-shadow); + padding: 12px 24px; + font-weight: 600; + text-align: center; + border-radius: 8px; + text-decoration: none; + transition: all 0.3s ease; + color: var(--text-color); + background: var(--card-bg); + border: 1px solid var(--border-color); + box-shadow: 0 2px 8px var(--box-shadow); } .learn-more-button:hover { - background-color: var(--hover-bg); - border-color: var(--text-color); -} - -.dark-mode .learn-more-button, -.dark-mode .theme-toggle { - background: #1A1F35; - border-color: rgba(255, 255, 255, 0.1); -} - -@media (max-width: 768px) { - .container { - width: 95%; - padding: 15px; - } - - .title { - font-size: 1.5rem; - } - - .web3auth-logo { - width: 180px; - height: auto; - margin: 0 auto; - filter: drop-shadow(0 2px 4px var(--box-shadow)); - } - - .user-info-box { - padding: 15px; - } + background-color: var(--hover-bg); + border-color: var(--text-color); +} + +/* Responsive adjustments */ +@media (max-height: 700px) { + .container { + padding: 12px; + } + + .header { + gap: 6px; + margin-bottom: 16px; + } + + .logo-container { + margin-bottom: 12px; + } + + .grid { + gap: 8px; + } + + .user-info-box, .info-box { + padding: 12px; + } + + .footer { + padding: 12px 0; + margin-top: 12px; + } } \ No newline at end of file From 6cb0d5ce4a30440a29a3e311330a9f95276ec6f0 Mon Sep 17 00:00:00 2001 From: Maharshi Mishra Date: Tue, 29 Oct 2024 12:21:46 +0530 Subject: [PATCH 12/13] Added Telegram --- .../sfa-web-ton-telegram-example/server/api/telegram.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js b/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js index 9dec5539..fdcb3da1 100644 --- a/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js +++ b/single-factor-auth-web/sfa-web-ton-telegram-example/server/api/telegram.js @@ -9,7 +9,7 @@ export default async function handler(req, res) { bot.command('start', async (ctx) => { await ctx.reply( -`Welcome to Web3Auth MiniApp! 🌟 +`Welcome to Web3Auth Telegram MiniApp! 🌟 Experience blockchain wallets reimagined inside Telegram! Our demo showcases integration with the TON blockchain, but that's just the beginning - the same seamless experience can be adapted for any blockchain network. @@ -23,7 +23,7 @@ Ready to experience the future of Web3 authentication?`, reply_markup: { inline_keyboard: [[ { - text: "Launch Web3Auth MiniApp 🚀", + text: "Launch Web3Auth Telegram MiniApp 🚀", web_app: { url: process.env.APP_URL } } ]] From 961dbd279d5758185156dfbc0f338eab9820c15b Mon Sep 17 00:00:00 2001 From: Maharshi Mishra Date: Wed, 13 Nov 2024 13:58:41 +0700 Subject: [PATCH 13/13] added quicker loading of user details --- .../package-lock.json | 7 +- .../sfa-web-ton-telegram-example/src/App.css | 17 ++- .../sfa-web-ton-telegram-example/src/App.tsx | 121 ++++++++++-------- 3 files changed, 85 insertions(+), 60 deletions(-) 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 ? : )} +
+
+