From d8cbc3f586d247371268e78aa5e53867211494d3 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Fri, 18 Apr 2025 13:49:54 +0530 Subject: [PATCH] fix: correctly initialise credentialsmanager/RLN --- src/components/RLNStatusIndicator.tsx | 5 +- src/contexts/rln/RLNContext.tsx | 81 ++++++---- src/contexts/rln/light.tsx | 218 -------------------------- 3 files changed, 57 insertions(+), 247 deletions(-) delete mode 100644 src/contexts/rln/light.tsx diff --git a/src/components/RLNStatusIndicator.tsx b/src/components/RLNStatusIndicator.tsx index 62f99a7..8afcfa0 100644 --- a/src/components/RLNStatusIndicator.tsx +++ b/src/components/RLNStatusIndicator.tsx @@ -5,7 +5,7 @@ import { useRLN } from '../contexts'; import { useWallet } from '../contexts'; export function RLNStatusIndicator() { - const { isInitialized, isStarted, isLoading, error } = useRLN(); + const { isInitialized, isStarted, isLoading, error, rln } = useRLN(); const { isConnected, chainId } = useWallet(); // Debug logging @@ -15,7 +15,8 @@ export function RLNStatusIndicator() { isInitialized, isStarted, isLoading, - error + error, + rln }); const getStatusColor = () => { diff --git a/src/contexts/rln/RLNContext.tsx b/src/contexts/rln/RLNContext.tsx index 1921dd6..a1edef0 100644 --- a/src/contexts/rln/RLNContext.tsx +++ b/src/contexts/rln/RLNContext.tsx @@ -95,52 +95,79 @@ export function RLNProvider({ children }: { children: ReactNode }) { const initializeRLN = useCallback(async () => { console.log("InitializeRLN called. Connected:", isConnected, "Signer available:", !!signer); - + + if (!isConnected || !signer) { + console.log("Cannot initialize RLN: Wallet not connected or signer not available."); + setError("Wallet not connected. Please connect your wallet."); + setIsLoading(false); + return; + } + + setIsLoading(true); + setError(null); + try { - setError(null); - setIsLoading(true); - - const rlnInstance = rln; - - if (!rlnInstance) { - console.log("Creating RLN light instance..."); + let currentRln = rln; + + if (!currentRln) { + console.log("Creating RLN instance..."); try { - console.log("RLN instance created successfully:", !!rlnInstance); - setRln(rlnInstance); + currentRln = new RLNCredentialsManager(); + setRln(currentRln); setIsInitialized(true); - setIsStarted(true); - console.log("isInitialized and isStarted set to true"); + console.log("RLN instance created successfully."); } catch (createErr) { console.error("Error creating RLN instance:", createErr); - throw createErr; + setError(createErr instanceof Error ? createErr.message : 'Failed to create RLN instance'); + setIsLoading(false); + return; } } else { - console.log("RLN instance already exists, skipping creation"); + console.log("RLN instance already exists, skipping creation."); } - - // Fetch rate limits if available - if (rlnInstance && rlnInstance.contract) { + + if (currentRln && !isStarted) { + console.log("Starting RLN with signer..."); try { - const minLimit = await rlnInstance.contract.getMinRateLimit(); - const maxLimit = await rlnInstance.contract.getMaxRateLimit(); - if (minLimit !== undefined && maxLimit !== undefined) { - setRateMinLimit(minLimit); - setRateMaxLimit(maxLimit); - console.log("Rate limits fetched:", { min: minLimit, max: maxLimit }); + await currentRln.start({ signer }); + setIsStarted(true); + console.log("RLN started successfully."); + + if (currentRln.contract) { + try { + const minLimit = await currentRln.contract.getMinRateLimit(); + const maxLimit = await currentRln.contract.getMaxRateLimit(); + if (minLimit !== undefined && maxLimit !== undefined) { + setRateMinLimit(minLimit); + setRateMaxLimit(maxLimit); + console.log("Rate limits fetched:", { min: minLimit, max: maxLimit }); + } else { + console.warn("Could not fetch rate limits: undefined values returned."); + } + } catch (limitErr) { + console.warn("Could not fetch rate limits after start:", limitErr); + // Don't fail initialization for this, but log it. + } } else { - throw new Error("Rate limits not available"); + console.warn("RLN contract not available after start, cannot fetch rate limits."); } - } catch (limitErr) { - console.warn("Could not fetch rate limits:", limitErr); + + } catch (startErr) { + console.error("Error starting RLN:", startErr); + setError(startErr instanceof Error ? startErr.message : 'Failed to start RLN'); + setIsStarted(false); } + } else if (isStarted) { + console.log("RLN already started."); } + } catch (err) { console.error('Error in initializeRLN:', err); setError(err instanceof Error ? err.message : 'Failed to initialize RLN'); } finally { setIsLoading(false); } - }, [isConnected, signer, rln, isStarted]); + }, [isConnected, signer, rln, isStarted]); // Auto-initialize effect for Light implementation useEffect(() => { diff --git a/src/contexts/rln/light.tsx b/src/contexts/rln/light.tsx deleted file mode 100644 index 75000cf..0000000 --- a/src/contexts/rln/light.tsx +++ /dev/null @@ -1,218 +0,0 @@ -"use client"; - -import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react'; -import { RLNCredentialsManager } from '@waku/rln'; -import { ethers } from 'ethers'; -import { ensureLineaSepoliaNetwork, ERC20_ABI, SIGNATURE_MESSAGE } from '../../utils/network'; -import { useWallet } from '@/contexts'; -import { RLNContextType } from './types'; - -const RLNContext = createContext(undefined); - -export function RLNProvider({ children }: { children: ReactNode }) { - const { isConnected, signer } = useWallet(); - const [rln, setRln] = useState(null); - const [isInitialized, setIsInitialized] = useState(false); - const [isStarted, setIsStarted] = useState(false); - const [error, setError] = useState(null); - const [rateMinLimit, setRateMinLimit] = useState(0); - const [rateMaxLimit, setRateMaxLimit] = useState(0); - - const initializeRLN = useCallback(async () => { - console.log("InitializeRLN called. Connected:", isConnected, "Signer available:", !!signer); - - try { - setError(null); - - if (!rln) { - console.log("Creating RLN instance..."); - - try { - const rlnInstance = new RLNCredentialsManager(); - - console.log("RLN instance created successfully:", !!rlnInstance); - setRln(rlnInstance); - - setIsInitialized(true); - console.log("isInitialized set to true"); - } catch (createErr) { - console.error("Error creating RLN instance:", createErr); - throw createErr; - } - } else { - console.log("RLN instance already exists, skipping creation"); - } - - // Start RLN if wallet is connected - if (isConnected && signer && rln && !isStarted) { - console.log("Starting RLN with signer..."); - try { - await rln.start({ signer }); - - setIsStarted(true); - console.log("RLN started successfully, isStarted set to true"); - - const minRate = await rln.contract?.getMinRateLimit(); - const maxRate = await rln.contract?.getMaxRateLimit(); - if (!minRate || !maxRate) { - throw new Error("Failed to get rate limits from contract"); - } - - setRateMinLimit(minRate); - setRateMaxLimit(maxRate); - console.log("Min rate:", minRate); - console.log("Max rate:", maxRate); - } catch (startErr) { - console.error("Error starting RLN:", startErr); - throw startErr; - } - } else { - console.log("Skipping RLN start because:", { - isConnected, - hasSigner: !!signer, - hasRln: !!rln, - isAlreadyStarted: isStarted - }); - } - } catch (err) { - console.error('Error in initializeRLN:', err); - setError(err instanceof Error ? err.message : 'Failed to initialize RLN'); - } - }, [isConnected, signer, rln, isStarted]); - - const registerMembership = async (rateLimit: number) => { - console.log("registerMembership called with rate limit:", rateLimit); - - if (!rln || !isStarted) { - return { success: false, error: 'RLN not initialized or not started' }; - } - - if (!signer) { - return { success: false, error: 'No signer available' }; - } - - try { - // Validate rate limit - if (rateLimit < rateMinLimit || rateLimit > rateMaxLimit) { - return { - success: false, - error: `Rate limit must be between ${rateMinLimit} and ${rateMaxLimit}` - }; - } - await rln.contract?.setRateLimit(rateLimit); - - // Ensure we're on the correct network - const isOnLineaSepolia = await ensureLineaSepoliaNetwork(signer); - if (!isOnLineaSepolia) { - console.warn("Could not switch to Linea Sepolia network. Registration may fail."); - } - - // Get user address and contract address - const userAddress = await signer.getAddress(); - - if (!rln.contract || !rln.contract.address) { - return { success: false, error: "RLN contract address not available. Cannot proceed with registration." }; - } - - const contractAddress = rln.contract.address; - const tokenAddress = '0x185A0015aC462a0aECb81beCc0497b649a64B9ea'; // Linea Sepolia token address - - // Create token contract instance - const tokenContract = new ethers.Contract( - tokenAddress, - ERC20_ABI, - signer - ); - - // Check token balance - const tokenBalance = await tokenContract.balanceOf(userAddress); - if (tokenBalance.isZero()) { - return { success: false, error: "You need tokens to register a membership. Your token balance is zero." }; - } - - // Check and approve token allowance if needed - const currentAllowance = await tokenContract.allowance(userAddress, contractAddress); - if (currentAllowance.eq(0)) { - console.log("Requesting token approval..."); - - // Approve a large amount (max uint256) - const maxUint256 = ethers.constants.MaxUint256; - - try { - const approveTx = await tokenContract.approve(contractAddress, maxUint256); - console.log("Approval transaction submitted:", approveTx.hash); - - // Wait for the transaction to be mined - await approveTx.wait(1); - console.log("Token approval confirmed"); - } catch (approvalErr) { - console.error("Error during token approval:", approvalErr); - return { - success: false, - error: `Failed to approve token: ${approvalErr instanceof Error ? approvalErr.message : String(approvalErr)}` - }; - } - } else { - console.log("Token allowance already sufficient"); - } - - // Generate signature for identity - const message = `${SIGNATURE_MESSAGE} ${Date.now()}`; - const signature = await signer.signMessage(message); - - const _credentials = await rln.registerMembership({signature: signature}); - if (!_credentials) { - throw new Error("Failed to register membership: No credentials returned"); - } - if (!_credentials.identity) { - throw new Error("Failed to register membership: Missing identity information"); - } - if (!_credentials.membership) { - throw new Error("Failed to register membership: Missing membership information"); - } - - return { success: true, credentials: _credentials }; - } catch (err) { - let errorMsg = "Failed to register membership"; - if (err instanceof Error) { - errorMsg = err.message; - } - - return { success: false, error: errorMsg }; - } - }; - - // Initialize RLN when wallet connects - useEffect(() => { - console.log("Wallet connection state changed:", { isConnected, hasSigner: !!signer }); - if (isConnected && signer) { - console.log("Wallet connected, attempting to initialize RLN"); - initializeRLN(); - } - }, [isConnected, signer, initializeRLN]); - - return ( - - {children} - - ); -} - -export function useRLN() { - const context = useContext(RLNContext); - if (context === undefined) { - throw new Error('useRLN must be used within a RLNProvider'); - } - return context; -} \ No newline at end of file