Hello, thank you for the information. I have tried using the SFA Node with usePnPkey: true
and tested it in the “mainnet” / legacy mainnet environment using the same Google email. However, it results in different wallets between Web3Auth on the frontend side of the current project and the SFA Node. Could you please provide a solution for this?
Below is the code I am using for Web3Auth in the frontend React and in the SFA Node.
Note: The SFA Node is still in development, so the idToken
and email are hardcoded for testing purposes.
WEB3AUTH CONFIG ON REACT/FRONT END CODE (that is currently running)
Dependencies:
"@web3auth/base": "^6.1.7",
"@web3auth/ethereum-provider": "^6.1.7",
"@web3auth/metamask-adapter": "^6.1.7",
"@web3auth/no-modal": "^6.1.7",
"@web3auth/openlogin-adapter": "^6.1.7",
"@web3auth/torus-wallet-connector-plugin": "^6.1.7",
"@web3auth/wallet-connect-v2-adapter": "^6.1.7"
Code :
const web3AuthKey = process.env.WEB3_AUTH_KEY;
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: ethers.utils.hexValue(ethereumChain.id),
rpcTarget: getChainConfig(ethereumChain.id).rpcUrls?.alchemy?.http[0]
? `${getChainConfig(ethereumChain.id).rpcUrls.alchemy.http[0]}/${process.env.ALCHEMY_API_KEY}`
: getChainConfig(ethereumChain.id).rpcUrls.default?.http[0],
displayName: ethereumChain.name,
blockExplorer: ethereumChain.blockExplorers.default?.url,
ticker: ethereumChain.nativeCurrency?.symbol,
tickerName: ethereumChain.nativeCurrency?.name,
};
const web3AuthInstance_ = new Web3AuthNoModal({
clientId: web3AuthKey,
chainConfig: chainConfig,
web3AuthNetwork: process.env.NEXT_PUBLIC_VERCEL_ENV === 'production' ? 'mainnet' : 'testnet',
});
const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });
const openloginAdapter = new OpenloginAdapter({
privateKeyProvider,
loginSettings: {
mfaLevel: 'none',
},
adapterSettings: {
network: defaultNetwork,
uxMode: 'redirect',
replaceUrlOnRedirect: true,
whiteLabel: {
name: 'Gaspack App',
logoLight: '/images/logo-gaspack-dark.png',
logoDark: '/images/logo-gaspack-light.png',
defaultLanguage: 'en',
dark: true,
},
},
});
const metamaskAdapter = new MetamaskAdapter({
web3AuthNetwork: process.env.NEXT_PUBLIC_VERCEL_ENV === 'production' ? 'mainnet' : 'testnet',
});
const walletConnectV2Adapter = await (async () => {
const defaultWcSettings = await getWalletConnectV2Settings(
'eip155',
[1, 5, 137, 80001],
'6c5e637429bc2ce328a662d672e391d6',
);
return new WalletConnectV2Adapter({
web3AuthNetwork: defaultNetwork,
adapterSettings: { qrcodeModal: QRCodeModal, ...defaultWcSettings.adapterSettings },
loginSettings: { ...defaultWcSettings.loginSettings },
});
})();
web3AuthInstance_.configureAdapter(openloginAdapter);
web3AuthInstance_.configureAdapter(walletConnectV2Adapter);
web3AuthInstance_.configureAdapter(metamaskAdapter);
const torusPlugin = new TorusWalletConnectorPlugin({
torusWalletOpts: {},
walletInitOptions: {
whiteLabel: {
theme: { isDark: true, colors: { primary: '#4200ff' } },
logoLight: 'https://app.gaspack.xyz/images/logo-gaspack-light.png',
logoDark: 'https://app.gaspack.xyz/images/logo-gaspack-dark.png',
topupHide: true,
featuredBillboardHide: true,
disclaimerHide: true,
},
useWalletConnect: true,
showTorusButton: false,
enableLogging: true,
},
});
setTorusPlugin(torusPlugin);
await web3AuthInstance_.addPlugin(torusPlugin);
subscribeAuthEvents(web3AuthInstance_);
await web3AuthInstance_.init();
WEB3AUTH CONFIG ON SFA NODE
Depedencies
"@wagmi/chains": "^1.8.0",
"@web3auth/base": "^8.8.0",
"@web3auth/ethereum-provider": "^8.10.2",
"@web3auth/node-sdk": "^3.3.0",
"@web3auth/openlogin-adapter": "^8.8.0",
Code :
/* eslint-disable import/no-extraneous-dependencies */
import type { CustomChainConfig } from '@web3auth/base';
import { CHAIN_NAMESPACES } from '@web3auth/base';
import { EthereumPrivateKeyProvider } from '@web3auth/ethereum-provider';
import { Web3Auth } from '@web3auth/node-sdk';
import { ethers } from 'ethers';
import fs from 'fs';
import type { NextApiRequest, NextApiResponse } from 'next';
import { ethereumChain, getChainConfig } from '@/config/chainConfig';
const privateKey = fs.readFileSync('privateKey.pem');
type Data =
| {
ethPrivateKey: string;
ethAddress: string;
}
| {
error: string;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
try {
const web3AuthKey = process.env.NEXT_PUBLIC_WEB3_AUTH_KEY;
const web3auth = new Web3Auth({
clientId: web3AuthKey as string,
web3AuthNetwork: 'mainnet', // Get your Network ID from Web3Auth Dashboard
usePnPKey: true,
});
const chainConfig: CustomChainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: ethers.utils.hexValue(ethereumChain.id),
rpcTarget: getChainConfig(ethereumChain.id)?.rpcUrls?.alchemy?.http?.[0]
? `${getChainConfig(ethereumChain.id).rpcUrls.alchemy.http[0]}/${
process.env.ALCHEMY_API_KEY
}`
: getChainConfig(ethereumChain.id)?.rpcUrls?.default?.http?.[0],
displayName: ethereumChain.name,
blockExplorerUrl: ethereumChain.blockExplorers.default?.url,
ticker: ethereumChain.nativeCurrency?.symbol,
tickerName: ethereumChain.nativeCurrency?.name,
};
const ethereumProvider = new EthereumPrivateKeyProvider({
config: {
chainConfig,
},
});
web3auth.init({ provider: ethereumProvider });
const idTokenGoogle =
'eyJhbGciOiJSUzI1NiIsImtpZCI6ImYyZTExOTg2MjgyZGU5M2YyN2IyNjRmZDJhNGRlMTkyOTkzZGNiOGMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI1MDg1OTM0ODg1NDQtMmplMXByZmNrbnAzbjZiaGxiNnNwbGtwYTAyZnQwZGUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI1MDg1OTM0ODg1NDQtMmplMXByZmNrbnAzbjZiaGxiNnNwbGtwYTAyZnQwZGUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDAzNTAxNTgyMDE2MTMwMjY4MzYiLCJoZCI6Imdhc3BhY2sueHl6IiwiZW1haWwiOiJjaGFuZHJhQGdhc3BhY2sueHl6IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF0X2hhc2giOiJvdldFakRFaEI5OW5kczFfSDNaYzFBIiwibmFtZSI6IkNoYW5kcmEgTXVoYW1hZCBBcHJpYW5hIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FDZzhvY0luYmtRUmpkOXM4SlF0ZG15eG8zQmhJTjdvNTVuUmgtVHpGYVdDMlFDck5mNHpUZz1zOTYtYyIsImdpdmVuX25hbWUiOiJDaGFuZHJhIE11aGFtYWQiLCJmYW1pbHlfbmFtZSI6IkFwcmlhbmEiLCJpYXQiOjE3MjE5MTQwMzcsImV4cCI6MTcyMTkxNzYzN30.WR5Um6k02jaSw8OTTRW9LDNGBa-wRGPM2GKfx6WB48477re0NuuaFWwn2GiJFMTcQjOlGcG17suHco0cNK_sOIRI0f_vgJEhIA1sYyMOuLOefnnXJHZbBoiQ0qiMQAiPoLkdsRh44EbVFzaLcQiX4XZBVVnQQZHB1F9Rh0tCjxD8VTwSheaff84EY_aKb9YyvaB2GDIDbw_MHFFz1IBGMC6y9xkZmyFuDEcmXrVm-PauziWyUO-xCJP8HCL2dyTxO4hGs2xZPoTZbTkHItbfqVyclNPKjgjFciKj9jsWqm9PxyTw3WfnI1d5gfpXxJmI3pZpA4RKYNsf-rLeZlsyIA';
const provider = await web3auth.connect({
verifier: process.env.NEXT_PUBLIC_WEB3_AUTH_VERIFIER;,
verifierId: 'chandra@gaspack.xyz',
idToken: idTokenGoogle,
});
if (!provider) {
throw new Error('Failed to connect to provider');
}
const ethPrivateKey = (await provider.request({
method: 'eth_private_key',
})) as string;
const ethAddress = (await provider.request({
method: 'eth_accounts',
})) as string[];
res.status(200).json({ ethPrivateKey, ethAddress: ethAddress[0] });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to connect using Web3Auth' });
}
}
CHAIN CONFIG
/* eslint-disable import/no-extraneous-dependencies */
import { mainnet, polygon, polygonMumbai, sepolia } from '@wagmi/chains';
import { Network } from 'alchemy-sdk';
import { ethers } from 'ethers';
import { ghostnetTezos, tezos } from './customChainConfig';
const isProduction = process.env.NEXT_PUBLIC_STAGE === 'production';
export const ethereumChain = isProduction ? mainnet : sepolia;
export const polygonChain = isProduction ? polygon : polygonMumbai;
export const tezosChain = isProduction ? tezos : ghostnetTezos;
export const defaultNetwork = isProduction ? 'mainnet' : 'testnet';
export function getChainConfig(chainId: number | string) {
switch (chainId) {
case mainnet.id:
return {
...mainnet,
openSea: {
subDomain: null,
networkName: 'ethereum',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET,
},
estimatedMinimumTransactionFee: 0.001,
gasPriceLimit: ethers.utils.parseUnits('100', 'gwei'),
blockchain: 'evm',
rpcUrls: {
alchemy: {
http: ['https://eth-mainnet.g.alchemy.com/v2'],
webSocket: ['wss://eth-mainnet.g.alchemy.com/v2'],
},
infura: {
http: ['https://mainnet.infura.io/v3'],
webSocket: ['wss://mainnet.infura.io/ws/v3'],
},
default: {
http: [`https://cloudflare-eth.com"`],
},
public: {
http: [`https://cloudflare-eth.com"`],
},
},
};
case sepolia.id:
return {
...sepolia,
openSea: {
subDomain: 'testnets',
networkName: 'sepolia',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_SEPOLIA,
},
estimatedMinimumTransactionFee: 0.001,
gasPriceLimit: ethers.utils.parseUnits('100', 'gwei'),
blockchain: 'evm',
rpcUrls: {
alchemy: {
http: ['https://eth-sepolia.g.alchemy.com/v2'],
webSocket: ['wss://eth-sepolia.g.alchemy.com/v2'],
},
infura: {
http: ['https://sepolia.infura.io/v3'],
webSocket: ['wss://sepolia.infura.io/ws/v3'],
},
default: {
http: [`wss://sepolia.infura.io/ws/v3`],
},
public: {
http: [`wss://sepolia.infura.io/ws/v3`],
},
},
};
case polygon.id:
return {
...polygon,
rpcUrls: {
alchemy: {
http: ['https://polygon-mainnet.g.alchemy.com/v2'],
webSocket: ['wss://polygon-mainnet.g.alchemy.com/v2'],
},
infura: {
http: ['https://polygon-mainnet.infura.io/v3'],
webSocket: ['wss://polygon-mainnet.infura.io/ws/v3'],
},
default: {
http: [
`https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY_POLYGON}`,
],
},
public: {
http: [
`https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY_POLYGON}`,
],
},
},
openSea: {
subDomain: null,
networkName: 'matic',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY_POLYGON,
network: Network.MATIC_MAINNET,
},
estimatedMinimumTransactionFee: 0.1,
gasPriceLimit: ethers.utils.parseUnits('1000', 'gwei'),
blockchain: 'evm',
};
case polygonMumbai.id:
return {
...polygonMumbai,
rpcUrls: {
alchemy: {
http: ['https://polygon-mumbai.g.alchemy.com/v2'],
webSocket: ['wss://polygon-mumbai.g.alchemy.com/v2'],
},
infura: {
http: ['https://polygon-mumbai.infura.io/v3'],
webSocket: ['wss://polygon-mumbai.infura.io/ws/v3'],
},
default: {
http: [
`https://polygon-mumbai.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY_POLYGON}`,
],
},
public: {
http: [
`https://polygon-mumbai.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY_POLYGON}`,
],
},
},
openSea: {
subDomain: 'testnets',
networkName: 'mumbai',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY_POLYGON,
network: Network.MATIC_MUMBAI,
},
estimatedMinimumTransactionFee: 0.1,
gasPriceLimit: ethers.utils.parseUnits('1000', 'gwei'),
blockchain: 'evm',
};
case ghostnetTezos.id:
return {
...ghostnetTezos,
openSea: {
subDomain: 'testnet',
networkName: 'tezos',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET,
},
estimatedMinimumTransactionFee: 0.001,
gasPriceLimit: ethers.utils.parseUnits('100', 'gwei'),
blockchain: 'tezos',
};
case tezos.id:
return {
...tezos,
openSea: {
subDomain: '',
networkName: 'tezos',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET,
},
estimatedMinimumTransactionFee: 0.001,
gasPriceLimit: ethers.utils.parseUnits('100', 'gwei'),
blockchain: 'tezos',
};
default:
return {
...mainnet,
openSea: {
subDomain: null,
networkName: 'ethereum',
},
alchemySetting: {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET,
},
estimatedMinimumTransactionFee: 0.001,
gasPriceLimit: ethers.utils.parseUnits('100', 'gwei'),
blockchain: 'evm',
};
}
}