Integrate Web3Auth with TON Blockchain for a Telegram Mini App
Overview
In this guide, we will walk you through the process of integrating Web3Auth with the TON blockchain for a Telegram Mini App. The guide covers everything from setting up the development environment to deploying your application.
As an overview, this guide will demonstrate how to implement secure user authentication using GitHub (via Auth0), powered by the Web3Auth SFA SDK, and enable interaction with the TON blockchain. For those who want to skip straight to the code, you can find it on GitHub.
Prerequisites
- Basic knowledge of React, TypeScript, and working with npm.
- A Telegram bot token.
- Access to Web3Auth and Auth0 dashboards.
Step 1: Set Up Auth0 and Web3Auth Verifiers
Before diving into the code, it's crucial to set up your Auth0 dashboard and configure verifiers on the Web3Auth dashboard. These steps are essential to ensure that your authentication process works smoothly with the Web3Auth SFA JS SDK.
Auth0 is an identity platform that provides secure authentication services, while Web3Auth verifiers are components that validate user credentials. Together, they ensure a secure and seamless login process for your decentralized application.
For detailed instructions on setting up the Auth0 dashboard and configuring verifiers for the SFA Web SDK, refer to the SFA JS Auth0 guide. This guide will walk you through creating an Auth0 application, setting up your domain and client ID, and configuring the necessary verifiers on the Web3Auth dashboard.
Once you have completed these setups, proceed with the following steps.
Step 2: Install Required Packages
Assuming your React project is already created, start by installing the necessary packages:
npm install @twa-dev/sdk @web3auth/single-factor-auth @web3auth/base @web3auth/base-provider @orbs-network/ton-access tonweb @auth0/auth0-react
When integrating Auth0 with Web3Auth, you'll encounter two primary options for handling the login
process: loginWithPopup
and loginWithRedirect
. For Telegram Mini Apps, we recommend using
loginWithRedirect
to ensure the authentication flow remains within the app environment. This
method redirects users to the Auth0 login page and back to your application, allowing for a smoother
experience in the Telegram Mini App context.
Step 3: Add the @twa-dev/sdk
The @twa-dev/sdk
package allows you to work with the SDK as an npm package with TypeScript
support.
The WebApp.ready()
method informs the Telegram app that the Mini App is ready to be displayed. It
is recommended to call this method as early as possible, as soon as all essential interface elements
are loaded. Once this method is called, the loading placeholder is hidden, and the Mini App is
shown.
Telegram Mini Apps are lightweight web applications that run inside the Telegram messenger, providing a seamless user experience without leaving the chat interface.
Code Example:
Open your entry file (usually src/index.tsx
or src/main.tsx
) and add the following:
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import WebApp from "@twa-dev/sdk";
import { Auth0Provider } from "@auth0/auth0-react";
WebApp.ready();
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
<Auth0Provider
domain="web3auth.au.auth0.com"
clientId="hiLqaop0amgzCC0AXo4w0rrG9abuJTdu"
authorizationParams={{
redirect_uri: window.location.origin,
connection: "github",
}}
>
<App />
</Auth0Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Step 4: Setup TON Blockchain Connection
To integrate the TON blockchain into your app, you'll need to set up a connection to the TON
network. Below is a basic example of how to implement the TonRPC
class, which handles blockchain
interactions such as getting account details and balances.
The tonRpc
implementation includes the use of top-level await
. To avoid any unexpected errors,
ensure that your tsconfig.json
is configured with "target": "ES2020"
or later and
"module": "ESNext"
. This configuration allows TypeScript to support top-level await
in your
project.
Basic Code Example:
const rpc = await getHttpEndpoint({
network: "testnet",
protocol: "json-rpc",
});
class TonRPC {
private provider: IProvider;
private tonweb: TonWeb;
constructor(provider: IProvider) {
this.provider = provider;
this.tonweb = new TonWeb(new TonWeb.HttpProvider(rpc));
}
async getAccounts(): Promise<string> {
const privateKey = await this.getPrivateKey();
const keyPair = this.getKeyPairFromPrivateKey(privateKey);
const WalletClass = this.tonweb.wallet.all["v3R2"];
const wallet = new WalletClass(this.tonweb.provider, {
publicKey: keyPair.publicKey,
});
const address = await wallet.getAddress();
return address.toString(true, true, true);
}
// ... more methods like getBalance, sendTransaction, signMessage
}
For the complete code and additional functionalities such as sending transactions or signing messages, please refer to the full implementation provided on the TON Connect Blockchain page.
Step 5: Web3Auth Integration
Set up Web3Auth in your App.tsx
file to enable authentication using loginWithRedirect
.
Initialize Auth0 and Web3Auth
First, initialize both the Auth0 and Web3Auth SDKs in your App.tsx
file.
import { useEffect, useState } from "react";
import { Web3Auth, decodeToken } 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 { useAuth0 } from "@auth0/auth0-react";
import "./App.css";
const testnetRpc = await getHttpEndpoint({
network: "testnet",
protocol: "json-rpc",
});
const verifier = "w3a-a0-github-demo";
const clientId =
"BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ";
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 },
});
// Initialize Web3Auth with necessary configurations
const web3authSfa = new Web3Auth({
clientId,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
usePnPKey: false,
privateKeyProvider,
});
Setup Login State and Initialize SDKs
Use useState
and useEffect
hooks to manage login state and initialize the Web3Auth SDK.
function App() {
const [isLoggingIn, setIsLoggingIn] = useState(false);
const [loggedIn, setLoggedIn] = useState(false);
const { isAuthenticated, isLoading, getIdTokenClaims, loginWithRedirect, logout: auth0Logout } = useAuth0();
const [provider, setProvider] = useState<any>(null);
useEffect(() => {
const init = async () => {
try {
await web3authSfa.init();
if (web3authSfa.status === "connected") {
setLoggedIn(true);
setProvider(web3authSfa.provider);
}
} catch (error) {
console.error("Error during Web3Auth initialization:", error);
}
};
init();
}, []);
Implement Login Logic
The loginWithRedirect
function is triggered when the user attempts to log in. The function handles
redirecting the user to the Auth0 login page. Code Example:
const login = async () => {
if (!web3authSfa) {
uiConsole("Web3Auth Single Factor Auth SDK not initialized yet");
return;
}
if (web3authSfa.status === "not_ready") {
await web3authSfa.init();
}
await loginWithRedirect();
};
// Attempt to connect to Web3Auth when authenticated
const connectWeb3Auth = async () => {
if (isAuthenticated && !loggedIn && web3authSfa.status === "ready") {
try {
setIsLoggingIn(true);
const idToken = (await getIdTokenClaims())?.__raw; // Retrieve raw ID token from Auth0
if (!idToken) {
console.error("No ID token found");
return;
}
const { payload } = decodeToken(idToken); // Decode the token to access its payload
// Connect to Web3Auth using the verifier, verifierId, and idToken
await web3authSfa.connect({
verifier,
verifierId: (payload as any).sub,
idToken: idToken,
});
// Update state to reflect successful login
setIsLoggingIn(false);
setLoggedIn(true);
setProvider(web3authSfa.provider);
} catch (err) {
setIsLoggingIn(false);
console.error("Error during Web3Auth connection:", err);
}
}
};
useEffect(() => {
connectWeb3Auth();
}, [isAuthenticated, loggedIn, getIdTokenClaims]);
idToken
LogicThere's a lot happening in this single line, but let's break it down:
const idToken = (await getIdTokenClaims())?.__raw;
This line retrieves the raw ID token from Auth0, which is crucial for our Web3Auth integration. The
getIdTokenClaims()
function comes from the Auth0 SDK and returns a promise. When resolved, it
gives us an object packed with the user's identity information. We're specifically after the __raw
property, which contains the complete, encoded JWT (JSON Web Token). The ?.
(optional chaining)
operator is our safety net here – it gracefully handles cases where getIdTokenClaims()
might
return null or undefined, preventing potential errors. This raw token is what we've used to connect
with Web3Auth in the next step.
Render the UI
Conditionally render the UI based on whether the user is logged in. Here's a shortened version of
the loginView
:
const loginView = (
<>
<div className="flex-container">
<div>
<button onClick={getUserInfo} className="card">
Get User Info
</button>
</div>
<div>
<button onClick={authenticateUser} className="card">
Authenticate User
</button>
</div>
<div>
<button onClick={getAccounts} className="card">
Get Accounts
</button>
</div>
{/* Add more buttons and implement the corresponding functions as per your need */}
...
</div>
<div id="console" style={{ whiteSpace: "pre-line" }}>
<p style={{ whiteSpace: "pre-line" }}></p>
</div>
</>
);
const logoutView = (
<button onClick={login} className="card">
Login
</button>
);
return (
<div className="container">
<h1 className="title">
<a target="_blank" href="https://web3auth.io/docs/sdk/sfa/sfa-js" rel="noreferrer">
Web3Auth
</a>{" "}
SFA React Ton GitHub Example
</h1>
{isLoading || isLoggingIn ? <Loading /> : <div className="grid">{web3authSfa ? (loggedIn ? loginView : logoutView) : null}</div>}
</div>
);
Step 6: Deploy Your App
Deploy this app to GitHub Pages, Vercel, or any other hosting service. For Vercel:
- Push your code to GitHub.
- Sign in to Vercel.
- Import your GitHub repository.
- Deploy your project.
After deployment, you will get a domain link. Use this link when setting up your Telegram bot.
Step 7: Setting Up a Telegram Bot
To connect your Mini App to Telegram, you need to create a bot and set up a Mini App for it.
Follow these steps:
-
Start a Chat with BotFather
- Open the Telegram app or web version.
- Search for
@BotFather
or follow the link. - Start a chat with BotFather by clicking on the
START
button.
-
Create a New Bot
- Send the
/newbot
command to BotFather. - BotFather will ask you to choose a name for your bot (this is a display name and can contain spaces).
- Next, choose a unique username for your bot, which must end in "bot" (e.g.,
sample_bot
).
- Send the
-
Set Up Bot Mini App
- Send the
/mybots
command to BotFather. - Choose your bot from the list and select the "Bot Settings" option.
- Choose the "Menu Button" option.
- Choose "Edit Menu Button URL" and send the URL to your Telegram Mini App, for example, the link from GitHub Pages or Vercel deploy.
- Send the
-
Accessing the Bot
- You can now search for your bot using its username in Telegram's search bar.
- Press the button next to the attach picker to launch your Telegram Mini App in the messenger.
Conclusion
This guide provides all the steps and code needed to integrate the @twa-dev/sdk
, set up Web3Auth
with loginWithRedirect
, integrate the TON blockchain using Web3Auth's provided resources, and
create a Telegram bot for your Mini App.
You can view the full-fledged example on GitHub.