Skip to main content

Integrate Web3Auth with TON Blockchain for a Telegram Mini App

reacttelegramsingle factor authtoncustom authenticationWeb3Auth Team | August 30, 2024

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

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.

What are Auth0 and Web3Auth verifiers?

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
Note on authentication methods

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.

What is Telegram Mini App?

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:

src/index.tsx
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.

tip

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.

App.tsx
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.

App.tsx
   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:

App.tsx
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]);
Understanding the idToken Logic

There'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:

App.tsx
   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:

  1. 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.
  2. 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).
  3. 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.
  4. 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.