fix: correctly initialise credentialsmanager/RLN

This commit is contained in:
Danish Arora 2025-04-18 13:49:54 +05:30
parent 046b7427ed
commit d8cbc3f586
No known key found for this signature in database
GPG Key ID: 1C6EF37CDAE1426E
3 changed files with 57 additions and 247 deletions

View File

@ -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 = () => {

View File

@ -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(() => {

View File

@ -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<RLNContextType | undefined>(undefined);
export function RLNProvider({ children }: { children: ReactNode }) {
const { isConnected, signer } = useWallet();
const [rln, setRln] = useState<RLNCredentialsManager | null>(null);
const [isInitialized, setIsInitialized] = useState(false);
const [isStarted, setIsStarted] = useState(false);
const [error, setError] = useState<string | null>(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 (
<RLNContext.Provider
value={{
rln,
isInitialized,
isStarted,
error,
initializeRLN,
registerMembership,
rateMinLimit,
rateMaxLimit
}}
>
{children}
</RLNContext.Provider>
);
}
export function useRLN() {
const context = useContext(RLNContext);
if (context === undefined) {
throw new Error('useRLN must be used within a RLNProvider');
}
return context;
}