When asking for help in this category, please make sure to provide the following details:
- SDK Version: 8.0.2
- Platform: web
I have a component where i am trying to do custom authentication login just like with the example at web3auth-core-kit-examples/single-factor-auth-web/sfa-web-custom-jwt-example at main · Web3Auth/web3auth-core-kit-examples · GitHub
here is my component
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { tKey } from "../tkey";
import { generatePrivateKeyFromUserId } from "../utils/Helpers";
import { AxirCore } from "axr-erc4337-sdk";
import { ethers } from "ethers";
import { Web3Auth, decodeToken } from "@web3auth/single-factor-auth";
// import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from "@web3auth/base";
import * as jose from "jose";
import Loader from "../components/Loader";
import { encryptKey } from "../utils/Helpers";
import "./TelegramLogin.css";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
const verifier = "w3a-jwt-for-sfa-web";
const clientId =
"BEglQSgt4cUWcj6SKRdu5QkOXTsePmMcusG5EAoyjyOYKlVRjIF1iCNnMOTfpzCiunHRrMui8TIwQPXdkQ8Yxuk"; // get from https://dashboard.web3auth.io
const chainConfig = {
chainId: "0x1",
displayName: "Ethereum Mainnet",
chainNamespace: CHAIN_NAMESPACES.EIP155,
tickerName: "Ethereum",
ticker: "ETH",
decimals: 18,
rpcTarget: "https://rpc.ankr.com/eth",
blockExplorerUrl: "https://etherscan.io",
};
// const privateKeyProvider = new EthereumPrivateKeyProvider({
// config: { chainConfig },
// });
// // Initialising Web3Auth Single Factor Auth SDK
// const web3authSfa = new Web3Auth({
// clientId, // Get your Client ID from Web3Auth Dashboard
// web3AuthNetwork: WEB3AUTH_NETWORK.TESTNET, // ["cyan", "testnet"]
// usePnPKey: false, // Setting this to true returns the same key as PnP Web SDK, By default, this SDK returns CoreKitKey.
// privateKeyProvider,
// });
function TelegramLogin() {
const navigate = useNavigate();
const [loading, setLoading] = useState(true);
const [telegramPrivateKey, setTelegramPrivateKey] = useState("");
const [loginMethod, setLoginMethod] = useState("telegram");
const [privateKey, setPrivateKey] = useState("");
const [walletAddress, setWalletAddress] = useState("");
const [privateKeyError, setPrivateKeyError] = useState("");
const [walletAddressError, setWalletAddressError] = useState("");
const [web3authSfa, setWeb3authSfa] = useEffect(null);
useEffect(() => {
const init = async () => {
try {
const privateKeyProvider = new EthereumPrivateKeyProvider({
config: {
chainConfig: {
chainId: process.env.REACT_APP_WEB3AUTH_CHAIN_ID,
rpcTarget: process.env.REACT_APP_RPC_URL,
},
},
});
// Initialising Web3Auth Single Factor Auth SDK
const web3authSfa = new Web3Auth({
clientId, // Get your Client ID from Web3Auth Dashboard
web3AuthNetwork: WEB3AUTH_NETWORK.TESTNET, // ["cyan", "testnet"]
usePnPKey: false, // Setting this to true returns the same key as PnP Web SDK, By default, this SDK returns CoreKitKey.
privateKeyProvider,
});
setWeb3authSfa(web3authSfa);
web3authSfa.init({});
} catch (error) {
console.error(error);
}
};
init();
}, []);
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const authData = {};
for (let param of params) {
authData[param[0]] = param[1];
}
if (authData.id && authData.hash) {
validateTelegramAuth(authData);
} else {
navigate("/");
}
}, [navigate]);
const getIdToken = async (id) => {
// Get ID Token from server
const res = await fetch("http://localhost:5000/api/token", {
method: "POST",
body: {
id,
},
headers: {
"Content-Type": "application/json",
},
});
const data = await res.json();
return data?.token;
};
const validateTelegramAuth = async (authData) => {
try {
const response = await axios.get(
process.env.REACT_APP_VALIDATE_TELEGRAM_AUTH + "/telegram-login",
{
params: authData,
}
);
if (response.status === 200) {
handleTelegramAuthSuccess(authData?.id);
} else {
console.error("Telegram authentication failed");
navigate("/");
}
} catch (error) {
console.error("Error validating Telegram auth data:", error);
navigate("/");
}
};
// async function createJWT(userId) {
// // Assume the key is already imported or generated
// // For example, you might have imported it like this:
// // const privateKey = await jose.importJWK(yourJWK, 'RS256');
// const tokenPayload = {
// sub: `${userId}`, // must be unique to each user
// // name: newUser.username,
// // email: showOnlyVerified ? newUser.getEmailVerified() : newUser.email,
// // phoneNumber: showOnlyVerified ? newUser.getPhoneVerified() : newUser.phone_number,
// exp: Math.floor(Date.now() / 1000) + 86400, // expires in 1 day
// iat: Math.floor(Date.now() / 1000),
// iss: process.env.WEB3AUTH_ISS,
// aud: "axr-wallet",
// };
// const jwt = await new jose.SignJWT(tokenPayload)
// .setProtectedHeader({ alg: "RS256", typ: "JWT" })
// .sign(privateKey);
// return jwt;
// }
const generatePrivateKeyFromUserId = async (userId) => {
// trying logging in with the Single Factor Auth SDK
try {
if (!web3authSfa) {
console.log("**@ Web3Auth Single Factor Auth SDK not initialized yet");
return;
}
const idTokenResult = await getIdToken(userId);
const { payload } = decodeToken(idTokenResult);
await web3authSfa.connect({
verifier,
verifierId: payload.sub,
idToken: idTokenResult,
});
} catch (err) {
// Single Factor Auth SDK throws an error if the user has already enabled MFA
// One can use the Web3AuthNoModal SDK to handle this case
console.error(err);
}
};
const generatePrivateKeyFromUserIdOld = async (userId) => {
// try {
// const verifierId = userId;
// const rpcUrl = process.env.REACT_APP_RPC_URL;
// const idToken = await createJWT(userId);
// console.log("**@ generated idToken from createJWT is , ", idToken);
// //this code if for "@web3auth/node-sdk": "^3.1.0"
// const web3auth = new Web3Auth({
// clientId: process.env.REACT_APP_WEB3AUTH_CLIENT_ID,
// web3AuthNetwork: process.env.REACT_APP_WEB3AUTH_NETWORK,
// });
// const ethereumProvider = new EthereumPrivateKeyProvider({
// config: {
// chainConfig: {
// // chainNamespace: "eip155",
// chainId: process.env.REACT_APP_WEB3AUTH_CHAIN_ID,
// rpcTarget: rpcUrl,
// },
// },
// });
// web3auth.init({ provider: ethereumProvider });
// const provider = await web3auth.connect({
// verifier: process.env.REACT_APP_WEB3AUTH_VERIFIER_NAME,
// verifierId: verifierId,
// idToken: idToken,
// });
// // logger.info(`provider: ${provider.toString()}`);
// let socialLoginShare = await provider.request({
// method: "eth_private_key",
// });
// console.log("**@ GENERATED SOCIAL Login share", socialLoginShare);
// return socialLoginShare;
// } catch (err) {
// console.log(`**@ Error in getSocialLoginShare: ${JSON.stringify(err)}`);
// return null;
// }
};
const handleTelegramAuthSuccess = async (userId) => {
try {
const privateKey = await generatePrivateKeyFromUserId(userId);
console.log("**@ generatePrivateKeyFromUserId is , ", privateKey);
setTelegramPrivateKey(privateKey);
setLoading(false);
} catch (error) {
console.error("Error handling Telegram auth success:", error);
navigate("/");
}
};
const handlePrivateKeyChange = (e) => {
const value = e.target.value;
setPrivateKey(value);
if (value && !/^0x[a-fA-F0-9]{64}$/.test(value)) {
setPrivateKeyError("Invalid private key format");
} else {
setPrivateKeyError("");
}
};
const handleWalletAddressChange = (e) => {
const value = e.target.value;
setWalletAddress(value);
if (value && !/^0x[a-fA-F0-9]{40}$/.test(value)) {
setWalletAddressError("Invalid wallet address");
} else {
setWalletAddressError("");
}
};
const checkOwnerShip = async (smartWalletAccount, owner) => {
try {
const isOwner = await smartWalletAccount.isK1Owner(owner);
return isOwner;
} catch (e) {
return false;
}
};
const handleLogin = async () => {
if (loginMethod === "telegram") {
const encryptedPrivateKey = encryptKey(telegramPrivateKey);
navigate("/dashboard/home", {
state: { privateKey: encryptedPrivateKey, hideLogoutButton: true },
});
} else {
if (
!privateKeyError &&
!walletAddressError &&
privateKey &&
walletAddress
) {
const smartWalletAccount = new AxirCore(
privateKey,
process.env.REACT_APP_RPC_URL,
process.env.REACT_APP_BUNDLER_URL,
0,
{
walletAddress: walletAddress,
}
);
const walletOwner = new ethers.Wallet(privateKey);
const walletOwnerAddress = walletOwner.address;
const isOwner = await checkOwnerShip(
smartWalletAccount,
walletOwnerAddress
);
if (isOwner) {
const encryptedPrivateKey = encryptKey(privateKey);
navigate("/dashboard/home", {
state: {
privateKey: encryptedPrivateKey,
hideLogoutButton: true,
walletAddress: walletAddress,
},
});
} else {
setWalletAddressError(
"Private key is not the owner of the given wallet address"
);
}
}
}
};
if (loading) {
return (
<div className="telegram-login">
<h1 className="telegram-login__title">AXR Wallet</h1>
<p className="telegram-login__message">
Authenticating with Telegram...
</p>
<div className="telegram-login__loader"></div>
</div>
);
}
return (
<div className="login-screen">
<div className="login-container">
<h1 className="login-screen__title">AXR Wallet</h1>
<div className="login-screen__tabs">
<button
className={`login-screen__tab ${
loginMethod === "telegram" ? "active" : ""
}`}
onClick={() => setLoginMethod("telegram")}
>
Login with Telegram
</button>
<button
className={`login-screen__tab ${
loginMethod === "privateKey" ? "active" : ""
}`}
onClick={() => setLoginMethod("privateKey")}
>
Login with Private Key
</button>
</div>
<div className="login-screen__form-container">
{loginMethod === "telegram" ? (
<button className="login-screen__button" onClick={handleLogin}>
Login with Telegram
</button>
) : (
<div className="login-screen__form">
<input
type="password"
placeholder="Private Key(starting with 0x)"
value={privateKey}
onChange={handlePrivateKeyChange}
className="login-screen__input"
/>
{privateKeyError && (
<p className="login-screen__error">{privateKeyError}</p>
)}
<input
type="text"
placeholder="Wallet Address"
value={walletAddress}
onChange={handleWalletAddressChange}
className="login-screen__input"
/>
{walletAddressError && (
<p className="login-screen__error">{walletAddressError}</p>
)}
<button
className="login-screen__button login-screen__button--private-key"
onClick={handleLogin}
disabled={
!privateKey ||
!walletAddress ||
privateKeyError ||
walletAddressError
}
>
Login
</button>
</div>
)}
</div>
</div>
</div>
);
}
export default TelegramLogin;
The app fails to load and i get this error which i am unable to debug.
bool.ts:13 Uncaught TypeError: (0 , superstruct_1.boolean) is not a function
at ./node_modules/@metamask/abi-utils/dist/parsers/bool.js (bool.ts:13:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./node_modules/@metamask/abi-utils/dist/parsers/index.js (index.ts:3:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./node_modules/@metamask/abi-utils/dist/packer.js (packer.ts:10:1)
at options.factory (react refresh:6:1)
When i remove the ethereumKeyProvider part and try to run without it , it runs but fails otherwise. Its a create-react-app that i have. How do i fix this issue ?