chore(keystore-management): upgrade to new API (#125)

This commit is contained in:
Danish Arora 2025-04-04 17:24:48 +05:30 committed by GitHub
parent 1700af13b0
commit b3b261fc26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 158 additions and 280 deletions

View File

@ -8,7 +8,7 @@
"name": "waku-keystore-management",
"version": "0.1.0",
"dependencies": {
"@waku/rln": "0.1.5-ad0e277.0",
"@waku/rln": "0.1.5-6997987.0",
"next": "15.1.7",
"react": "^19.0.0",
"react-dom": "^19.0.0"
@ -2309,16 +2309,16 @@
}
},
"node_modules/@waku/core": {
"version": "0.0.35-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/core/-/core-0.0.35-ad0e277.0.tgz",
"integrity": "sha512-IfgWE/Kc8jpcmO6PGsLzySHAWwoDQtIY9gsxWtoqPnll1cE9ylxfGVh0je4o58E5F0XGw+wm9TdD149hq30cJQ==",
"version": "0.0.35-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/core/-/core-0.0.35-6997987.0.tgz",
"integrity": "sha512-rdTBFpaoJr9PClZWcnazRu2bydIjj1MnG31espjWNe072vepEAMZln48ZtPqtjIn1pfr5Dn0QOL9blVDdGIAkw==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@libp2p/ping": "2.0.1",
"@waku/enr": "0.0.29-ad0e277.0",
"@waku/interfaces": "0.0.30-ad0e277.0",
"@waku/proto": "0.0.10-ad0e277.0",
"@waku/utils": "0.0.23-ad0e277.0",
"@waku/enr": "0.0.29-6997987.0",
"@waku/interfaces": "0.0.30-6997987.0",
"@waku/proto": "0.0.10-6997987.0",
"@waku/utils": "0.0.23-6997987.0",
"debug": "^4.3.4",
"it-all": "^3.0.4",
"it-length-prefixed": "^9.0.4",
@ -2356,9 +2356,9 @@
}
},
"node_modules/@waku/enr": {
"version": "0.0.29-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/enr/-/enr-0.0.29-ad0e277.0.tgz",
"integrity": "sha512-3IoFVU3XX7rEge3VFMl5r3wc0XVnZTvheRuFYSm0HgPrMls23PmAd7IdFLOMq5e9CGWAbWx0fdT3StzIdN2PbQ==",
"version": "0.0.29-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/enr/-/enr-0.0.29-6997987.0.tgz",
"integrity": "sha512-w3ECNF1LuZ1Jwki3aeu9VJv2oGW0xXsgn8pgszGjFk0ydHPlJY9gbuvTK2xx+o+vedRaiAXWBXwOY5g7GRc9lg==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@ethersproject/rlp": "^5.7.0",
@ -2366,7 +2366,7 @@
"@libp2p/peer-id": "^5.0.1",
"@multiformats/multiaddr": "^12.0.0",
"@noble/secp256k1": "^1.7.1",
"@waku/utils": "0.0.23-ad0e277.0",
"@waku/utils": "0.0.23-6997987.0",
"debug": "^4.3.4",
"js-sha3": "^0.9.2"
},
@ -2383,21 +2383,21 @@
}
},
"node_modules/@waku/interfaces": {
"version": "0.0.30-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/interfaces/-/interfaces-0.0.30-ad0e277.0.tgz",
"integrity": "sha512-Xg0vupz9y+PGNKVsJ3AodpcxWLkGafLPser4H/0SYvwiBKR0doEs08wfRdXY83WID1GZPVkA3jcIm0rAnPZWSw==",
"version": "0.0.30-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/interfaces/-/interfaces-0.0.30-6997987.0.tgz",
"integrity": "sha512-df526iM92hkW2Fj2zrn+iDQp+xfhDx2EqGbUwaK/G52oK5cyh77a/AtaBEFIOE301i1Ur0TAi4KEivryfKYfwg==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@waku/proto": "0.0.10-ad0e277.0"
"@waku/proto": "0.0.10-6997987.0"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@waku/proto": {
"version": "0.0.10-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/proto/-/proto-0.0.10-ad0e277.0.tgz",
"integrity": "sha512-F4RKTcdX3v+E3/TxdINPWpsQEjst1VXlslJdNXC1LXPRqd87S7r2e47PXafM7TGBdOitIIPw8Xf4MxbPFGa1Gg==",
"version": "0.0.10-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/proto/-/proto-0.0.10-6997987.0.tgz",
"integrity": "sha512-OtM6cCFNlc8fcSj4t7Wcz2HEAcqDHh3cXZI4TLsvXk7Xm0/bJ5AR6KdPvmFdWNUWvMOGLkw6rVkXMsFTsgcN3A==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"protons-runtime": "^5.4.0"
@ -2407,15 +2407,15 @@
}
},
"node_modules/@waku/rln": {
"version": "0.1.5-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/rln/-/rln-0.1.5-ad0e277.0.tgz",
"integrity": "sha512-2QxvEhZoZjsP0J8wg6BAv7GTvDMeOzD7a46WR6M3Gld39TNf+2hQMzED5I91QxjcoAvMMbphD8FiH4X5tqzM5g==",
"version": "0.1.5-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/rln/-/rln-0.1.5-6997987.0.tgz",
"integrity": "sha512-lEoVyR2LdNIjo/VFeoBFKgDHspAoBQTdECLTIu9oOZ9iJLvT5VWX/PVGAoQ55yNteTu56Oivl9fkzDmITfIMbg==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@chainsafe/bls-keystore": "3.0.0",
"@noble/hashes": "^1.2.0",
"@waku/core": "0.0.35-ad0e277.0",
"@waku/utils": "0.0.23-ad0e277.0",
"@waku/core": "0.0.35-6997987.0",
"@waku/utils": "0.0.23-6997987.0",
"@waku/zerokit-rln-wasm": "^0.0.13",
"chai": "^5.1.2",
"chai-as-promised": "^8.0.1",
@ -2432,13 +2432,13 @@
}
},
"node_modules/@waku/utils": {
"version": "0.0.23-ad0e277.0",
"resolved": "https://registry.npmjs.org/@waku/utils/-/utils-0.0.23-ad0e277.0.tgz",
"integrity": "sha512-r3nef/L4fZx2GA7byUAOFLSjhVXuH22FFgmEp7+/jzbAjKAcVIaCfG2M09SnNDbxc5uViKeEE6ODIfw+k+2rZw==",
"version": "0.0.23-6997987.0",
"resolved": "https://registry.npmjs.org/@waku/utils/-/utils-0.0.23-6997987.0.tgz",
"integrity": "sha512-ExVLIpaBnjbGNjOl6JLTWMj0rBvqvK0kW/MhqtPue4i6l+iKVytdBAsq7KDT9V/DN1MyXpSVd8kptOPh5+y8iA==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@noble/hashes": "^1.3.2",
"@waku/interfaces": "0.0.30-ad0e277.0",
"@waku/interfaces": "0.0.30-6997987.0",
"chai": "^4.3.10",
"debug": "^4.3.4",
"uint8arrays": "^5.0.1"

View File

@ -10,7 +10,7 @@
"lint": "next lint"
},
"dependencies": {
"@waku/rln": "0.1.5-ad0e277.0",
"@waku/rln": "0.1.5-6997987.0",
"next": "15.1.7",
"react": "^19.0.0",
"react-dom": "^19.0.0"

View File

@ -1,123 +0,0 @@
"use client";
import { useState } from 'react';
import { useKeystore } from '../contexts/KeystoreContext';
import { saveKeystoreToFile, readKeystoreFromFile } from '../utils/fileUtils';
export default function KeystoreManager() {
const {
isInitialized: isKeystoreInitialized,
hasStoredCredentials,
storedCredentialsHashes,
exportKeystore,
importKeystore
} = useKeystore();
const [error, setError] = useState<string | null>(null);
const [successMessage, setSuccessMessage] = useState<string | null>(null);
const handleExport = () => {
try {
const keystoreJson = exportKeystore();
saveKeystoreToFile(keystoreJson);
setSuccessMessage('Keystore exported successfully');
setTimeout(() => setSuccessMessage(null), 3000);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to export keystore');
setTimeout(() => setError(null), 3000);
}
};
const handleImport = async () => {
try {
const keystoreJson = await readKeystoreFromFile();
const success = importKeystore(keystoreJson);
if (success) {
setSuccessMessage('Keystore imported successfully');
} else {
setError('Failed to import keystore');
}
setTimeout(() => {
setSuccessMessage(null);
setError(null);
}, 3000);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to import keystore');
setTimeout(() => setError(null), 3000);
}
};
if (!isKeystoreInitialized) {
return (
<div className="p-4 bg-gray-100 dark:bg-gray-700 rounded-lg">
<p className="text-gray-700 dark:text-gray-300">Initializing keystore...</p>
</div>
);
}
return (
<div className="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-md">
<h2 className="text-xl font-semibold mb-4 text-gray-900 dark:text-white">Keystore Management</h2>
{/* Status */}
<div className="mb-4 p-3 bg-gray-50 dark:bg-gray-700 rounded-lg">
<p className="text-sm text-gray-700 dark:text-gray-300">
<span className="font-semibold">Status:</span> {hasStoredCredentials ? 'Credentials found' : 'No credentials stored'}
</p>
{hasStoredCredentials && (
<p className="text-sm text-gray-700 dark:text-gray-300 mt-1">
<span className="font-semibold">Stored credentials:</span> {storedCredentialsHashes.length}
</p>
)}
</div>
{/* Notifications */}
{error && (
<div className="mb-4 p-3 bg-red-50 dark:bg-red-900 rounded-lg">
<p className="text-sm text-red-700 dark:text-red-300">{error}</p>
</div>
)}
{successMessage && (
<div className="mb-4 p-3 bg-green-50 dark:bg-green-900 rounded-lg">
<p className="text-sm text-green-700 dark:text-green-300">{successMessage}</p>
</div>
)}
{/* Import/Export Buttons */}
<div className="space-y-4">
{/* Export Keystore */}
<div>
<button
onClick={handleExport}
disabled={!hasStoredCredentials}
className={`w-full py-2 px-4 rounded ${
!hasStoredCredentials
? 'bg-gray-300 text-gray-500 cursor-not-allowed dark:bg-gray-600 dark:text-gray-400'
: 'bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800 dark:bg-blue-700 dark:hover:bg-blue-800'
}`}
>
Export Keystore
</button>
{!hasStoredCredentials && (
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
No credentials to export
</p>
)}
</div>
{/* Import Keystore */}
<div>
<button
onClick={handleImport}
className="w-full py-2 px-4 bg-green-600 text-white rounded hover:bg-green-700 active:bg-green-800 dark:bg-green-700 dark:hover:bg-green-800"
>
Import Keystore
</button>
</div>
</div>
</div>
);
}

View File

@ -1,10 +1,10 @@
"use client";
import React, { Children, isValidElement } from 'react';
import { TabNavigation, TabItem } from './Tabs/TabNavigation';
import { useAppState } from '../contexts/AppStateContext';
import { TabItem, TabNavigation } from './Tabs/TabNavigation';
import { useAppState } from '@/contexts/AppStateContext';
const tabs: TabItem[] = [
const tabs: TabItem [] = [
{
id: 'membership',
label: 'Membership Registration',

View File

@ -1,7 +1,7 @@
"use client";
import { useRLNImplementation } from '@/contexts';
import React from 'react';
import { useRLNImplementation } from '../contexts/rln';
export function RLNImplementationToggle() {
const { implementation, setImplementation } = useRLNImplementation();

View File

@ -1,7 +1,7 @@
"use client";
import { useRLN } from '@/contexts';
import React from 'react';
import { useRLN } from '../contexts/rln';
export function RLNInitButton() {
const { initializeRLN, isInitialized, isStarted, error, isLoading } = useRLN();

View File

@ -3,8 +3,8 @@
import React, { useState } from 'react';
import { useKeystore } from '@/contexts/keystore';
import { useRLN } from '@/contexts/rln';
import { saveKeystoreToFile, readKeystoreFromFile } from '../../../utils/fileUtils';
import { KeystoreEntity } from '@waku/rln';
import { saveKeystoreToFile, readKeystoreFromFile } from '../../../utils/file';
import { DecryptedCredentials } from '@waku/rln';
import { useAppState } from '@/contexts/AppStateContext';
export function KeystoreManagement() {
@ -23,7 +23,7 @@ export function KeystoreManagement() {
const [selectedCredential, setSelectedCredential] = useState<string | null>(null);
const [viewPassword, setViewPassword] = useState<string>('');
const [viewingCredential, setViewingCredential] = useState<string | null>(null);
const [decryptedInfo, setDecryptedInfo] = useState<KeystoreEntity | null>(null);
const [decryptedInfo, setDecryptedInfo] = useState<DecryptedCredentials | null>(null);
const [isDecrypting, setIsDecrypting] = useState(false);
React.useEffect(() => {
@ -206,7 +206,38 @@ export function KeystoreManagement() {
</h4>
<div className="space-y-2">
<pre className="text-xs text-gray-600 dark:text-gray-400 whitespace-pre-wrap bg-gray-100 dark:bg-gray-800 p-2 rounded overflow-auto max-h-60">
{JSON.stringify(decryptedInfo, null, 2)}
<div className="grid grid-cols-1 gap-1">
<div className="flex flex-col">
<span className="font-semibold">ID Commitment:</span>
<span className="break-all">{decryptedInfo.identity.IDCommitment}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">ID Nullifier:</span>
<span className="break-all">{decryptedInfo.identity.IDNullifier}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">ID Secret Hash:</span>
<span className="break-all">{decryptedInfo.identity.IDSecretHash}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">Membership Address:</span>
<span className="break-all">{decryptedInfo.membership.address}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">Chain ID:</span>
<span>{decryptedInfo.membership.chainId}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">Tree Index:</span>
<span>{decryptedInfo.membership.treeIndex}</span>
</div>
<div className="flex flex-col">
<span className="font-semibold">Rate Limit:</span>
<span>{decryptedInfo.membership.rateLimit}</span>
</div>
</div>
{/* {JSON.stringify(decryptedInfo, null, 2)} */}
</pre>
<button
onClick={() => setDecryptedInfo(null)}

View File

@ -1,15 +1,3 @@
// Re-export wallet context
export { WalletProvider, useWallet } from './wallet';
// Re-export keystore context
export { KeystoreProvider, useKeystore } from './keystore';
// Re-export RLN contexts
export {
RLNImplementationProvider,
useRLNImplementation,
type RLNImplementationType,
RLNProvider,
type UnifiedRLNInstance,
useRLN
} from './rln';
export { RLNImplementationProvider, useRLNImplementation, type RLNImplementationType, RLNProvider, useRLN } from './rln';

View File

@ -3,7 +3,8 @@
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { Keystore, KeystoreEntity } from '@waku/rln';
// Define types for the context
export const LOCAL_STORAGE_KEYSTORE_KEY = 'waku-rln-keystore';
interface KeystoreContextType {
keystore: Keystore | null;
isInitialized: boolean;
@ -17,10 +18,8 @@ interface KeystoreContextType {
getDecryptedCredential: (hash: string, password: string) => Promise<KeystoreEntity | null>;
}
// Create the context
const KeystoreContext = createContext<KeystoreContextType | undefined>(undefined);
// Provider component
export function KeystoreProvider({ children }: { children: ReactNode }) {
const [keystore, setKeystore] = useState<Keystore | null>(null);
const [isInitialized, setIsInitialized] = useState(false);
@ -30,7 +29,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
// Initialize keystore
useEffect(() => {
try {
const storedKeystore = localStorage.getItem('waku-rln-keystore');
const storedKeystore = localStorage.getItem(LOCAL_STORAGE_KEYSTORE_KEY);
let keystoreInstance: Keystore;
if (storedKeystore) {
@ -57,7 +56,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
useEffect(() => {
if (keystore && isInitialized) {
try {
localStorage.setItem('waku-rln-keystore', keystore.toString());
localStorage.setItem(LOCAL_STORAGE_KEYSTORE_KEY, keystore.toString());
} catch (err) {
console.warn("Could not save keystore to localStorage:", err);
}
@ -72,7 +71,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
try {
const hash = await keystore.addCredential(credentials, password);
localStorage.setItem('waku-rln-keystore', keystore.toString());
localStorage.setItem(LOCAL_STORAGE_KEYSTORE_KEY, keystore.toString());
setStoredCredentialsHashes(keystore.keys());
@ -124,7 +123,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
if (imported) {
setKeystore(imported);
setStoredCredentialsHashes(imported.keys());
localStorage.setItem('waku-rln-keystore', keystoreJson);
localStorage.setItem(LOCAL_STORAGE_KEYSTORE_KEY, keystoreJson);
return true;
}
return false;
@ -142,7 +141,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
keystore.removeCredential(hash);
setStoredCredentialsHashes(keystore.keys());
localStorage.setItem('waku-rln-keystore', keystore.toString());
localStorage.setItem(LOCAL_STORAGE_KEYSTORE_KEY, keystore.toString());
};
const contextValue: KeystoreContextType = {

View File

@ -1,15 +1,15 @@
"use client";
import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { KeystoreEntity } from '@waku/rln';
import { createRLNImplementation, UnifiedRLNInstance } from './implementations';
import { KeystoreEntity, RLNCredentialsManager } from '@waku/rln';
import { createRLNImplementation } from './implementations';
import { useRLNImplementation } from './RLNImplementationContext';
import { ethers } from 'ethers';
import { useKeystore } from '../keystore';
import { ERC20_ABI, LINEA_SEPOLIA_CONFIG, ensureLineaSepoliaNetwork } from './utils/network';
import { ERC20_ABI, LINEA_SEPOLIA_CONFIG, ensureLineaSepoliaNetwork } from '../../utils/network';
interface RLNContextType {
rln: UnifiedRLNInstance | null;
rln: RLNCredentialsManager | null;
isInitialized: boolean;
isStarted: boolean;
error: string | null;
@ -32,7 +32,7 @@ const RLNContext = createContext<RLNContextType | undefined>(undefined);
export function RLNProvider({ children }: { children: ReactNode }) {
const { implementation } = useRLNImplementation();
const [rln, setRln] = useState<UnifiedRLNInstance | null>(null);
const [rln, setRln] = useState<RLNCredentialsManager | null>(null);
const [isInitialized, setIsInitialized] = useState(false);
const [isStarted, setIsStarted] = useState(false);
const [error, setError] = useState<string | null>(null);
@ -130,11 +130,15 @@ export function RLNProvider({ children }: { children: ReactNode }) {
console.log("RLN started successfully, isStarted set to true");
try {
const minLimit = await rln.contract.getMinRateLimit();
const maxLimit = await rln.contract.getMaxRateLimit();
setRateMinLimit(minLimit);
setRateMaxLimit(maxLimit);
console.log("Rate limits fetched:", { min: minLimit, max: maxLimit });
const minLimit = await rln.contract?.getMinRateLimit();
const maxLimit = await rln.contract?.getMaxRateLimit();
if (minLimit !== undefined && maxLimit !== undefined) {
setRateMinLimit(minLimit);
setRateMaxLimit(maxLimit);
console.log("Rate limits fetched:", { min: minLimit, max: maxLimit });
} else {
throw new Error("Rate limits not available");
}
} catch (limitErr) {
console.warn("Could not fetch rate limits:", limitErr);
}
@ -192,12 +196,15 @@ export function RLNProvider({ children }: { children: ReactNode }) {
error: 'RLN not initialized or not started'
};
}
const minLimit = await rln.contract.getMinRateLimit();
const maxLimit = await rln.contract.getMaxRateLimit();
const minLimit = await rln.contract?.getMinRateLimit();
const maxLimit = await rln.contract?.getMaxRateLimit();
if (minLimit !== undefined && maxLimit !== undefined) {
// Update state
setRateMinLimit(minLimit);
setRateMaxLimit(maxLimit);
} else {
throw new Error("Rate limits not available");
}
return {
success: true,
@ -242,7 +249,7 @@ export function RLNProvider({ children }: { children: ReactNode }) {
error: `Rate limit must be between ${rateMinLimit} and ${rateMaxLimit}`
};
}
await rln.contract.setRateLimit(rateLimit);
await rln.contract?.setRateLimit(rateLimit);
// Ensure we're on the correct network
const isOnLineaSepolia = await ensureLineaSepoliaNetwork(signer);

View File

@ -1,33 +1,11 @@
"use client";
import { createRLN, MembershipInfo, RLNLightInstance } from '@waku/rln';
import { ethers } from 'ethers';
import { createRLN, RLNCredentialsManager } from '@waku/rln';
export interface UnifiedRLNInstance {
contract: {
address: string;
membershipFee?: () => Promise<ethers.BigNumber>;
getRateLimit: () => number;
getMinRateLimit: () => Promise<number>;
getMaxRateLimit: () => Promise<number>;
getMaxTotalRateLimit: () => Promise<number>;
getCurrentTotalRateLimit: () => Promise<number>;
getRemainingTotalRateLimit: () => Promise<number>;
setRateLimit: (newRateLimit: number) => Promise<void>;
getRemainingMessages: (membershipId: number) => Promise<number>;
getMembershipInfo: (idCommitment: string) => Promise<MembershipInfo | undefined>;
extendMembership: (idCommitment: string) => Promise<ethers.ContractTransaction>;
eraseMembership: (idCommitment: string, eraseFromMembershipSet?: boolean) => Promise<ethers.ContractTransaction>;
registerMembership: (idCommitment: string, rateLimit?: number) => Promise<ethers.ContractTransaction>;
};
start: (options: { signer: ethers.Signer }) => Promise<void>;
registerMembership: (options: { signature: string }) => Promise<Record<string, unknown>>;
}
export async function createRLNImplementation(type: 'standard' | 'light' = 'light'): Promise<UnifiedRLNInstance> {
export async function createRLNImplementation(type: 'standard' | 'light' = 'light') {
if (type === 'standard') {
return await createRLN() as unknown as UnifiedRLNInstance;
return await createRLN();
} else {
return new RLNLightInstance() as unknown as UnifiedRLNInstance;
return new RLNCredentialsManager;
}
}

View File

@ -1,3 +1,3 @@
export { RLNProvider as StandardRLNProvider, useRLN as useStandardRLN } from './standard';
export { RLNProvider as LightRLNProvider, useRLN as useLightRLN } from './light';
export { createRLNImplementation, type UnifiedRLNInstance } from './factory';
export { createRLNImplementation } from './factory';

View File

@ -1,27 +1,17 @@
"use client";
import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { DecryptedCredentials, RLNInstance, RLNLightInstance } from '@waku/rln';
import { useWallet } from '../../wallet';
import { RLNCredentialsManager } from '@waku/rln';
import { ethers } from 'ethers';
import { ensureLineaSepoliaNetwork, ERC20_ABI, SIGNATURE_MESSAGE } from '../utils/network';
interface RLNContextType {
rln: RLNLightInstance | RLNInstance | null;
isInitialized: boolean;
isStarted: boolean;
error: string | null;
initializeRLN: () => Promise<void>;
registerMembership: (rateLimit: number) => Promise<{ success: boolean; error?: string; credentials?: DecryptedCredentials }>;
rateMinLimit: number;
rateMaxLimit: number;
}
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<RLNLightInstance | RLNInstance | null>(null);
const [rln, setRln] = useState<RLNCredentialsManager | null>(null);
const [isInitialized, setIsInitialized] = useState(false);
const [isStarted, setIsStarted] = useState(false);
const [error, setError] = useState<string | null>(null);
@ -38,7 +28,7 @@ export function RLNProvider({ children }: { children: ReactNode }) {
console.log("Creating RLN instance...");
try {
const rlnInstance = new RLNLightInstance();
const rlnInstance = new RLNCredentialsManager();
console.log("RLN instance created successfully:", !!rlnInstance);
setRln(rlnInstance);

View File

@ -1,21 +1,13 @@
"use client";
import { createContext, useContext, useState, ReactNode } from 'react';
import { createRLN, DecryptedCredentials, LINEA_CONTRACT, RLNInstance } from '@waku/rln';
import { useWallet } from '../../wallet';
import { createRLN, LINEA_CONTRACT, RLNInstance } from '@waku/rln';
import { ethers } from 'ethers';
import { ensureLineaSepoliaNetwork, ERC20_ABI, SIGNATURE_MESSAGE } from '../utils/network';
import { ensureLineaSepoliaNetwork, ERC20_ABI, SIGNATURE_MESSAGE } from '../../../utils/network';
import { RLNContextType } from './types';
import { useWallet } from '@/contexts';
interface RLNContextType {
rln: RLNInstance | null;
isInitialized: boolean;
isStarted: boolean;
error: string | null;
initializeRLN: () => Promise<void>;
registerMembership: (rateLimit: number) => Promise<{ success: boolean; error?: string; credentials?: DecryptedCredentials }>;
rateMinLimit: number;
rateMaxLimit: number;
}
const RLNContext = createContext<RLNContextType | undefined>(undefined);

View File

@ -0,0 +1,12 @@
import { DecryptedCredentials, RLNCredentialsManager, RLNInstance } from "@waku/rln";
export interface RLNContextType {
rln: RLNInstance | RLNCredentialsManager | null;
isInitialized: boolean;
isStarted: boolean;
error: string | null;
initializeRLN: () => Promise<void>;
registerMembership: (rateLimit: number) => Promise<{ success: boolean; error?: string; credentials?: DecryptedCredentials }>;
rateMinLimit: number;
rateMaxLimit: number;
}

View File

@ -1,3 +1,2 @@
export { RLNProvider, useRLN } from './RLNContext';
export { RLNImplementationProvider, useRLNImplementation, type RLNImplementationType } from './RLNImplementationContext';
export type { UnifiedRLNInstance } from './implementations';
export { RLNImplementationProvider, useRLNImplementation, type RLNImplementationType } from './RLNImplementationContext';

View File

@ -3,17 +3,9 @@
import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { extractMetaMaskSigner } from '@waku/rln';
import { ethers } from 'ethers';
import { WalletContextType } from './types';
interface WalletContextType {
isConnected: boolean;
address: string | null;
signer: ethers.Signer | null;
balance: string | null;
chainId: number | null;
connectWallet: () => Promise<void>;
disconnectWallet: () => void;
error: string | null;
}
const WalletContext = createContext<WalletContextType | undefined>(undefined);
@ -146,19 +138,3 @@ export function useWallet() {
return context;
}
declare global {
interface Window {
ethereum?: {
isMetaMask?: boolean;
isConnected?: boolean;
selectedAddress?: string;
request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;
on(event: 'accountsChanged', listener: (accounts: string[]) => void): void;
on(event: 'chainChanged', listener: (chainId: string) => void): void;
on(event: string, listener: (...args: unknown[]) => void): void;
removeListener(event: 'accountsChanged', listener: (accounts: string[]) => void): void;
removeListener(event: 'chainChanged', listener: (chainId: string) => void): void;
removeListener(event: string, listener: (...args: unknown[]) => void): void;
};
}
}

View File

@ -0,0 +1,29 @@
import { ethers } from 'ethers';
export interface WalletContextType {
isConnected: boolean;
address: string | null;
signer: ethers.Signer | null;
balance: string | null;
chainId: number | null;
connectWallet: () => Promise<void>;
disconnectWallet: () => void;
error: string | null;
}
declare global {
interface Window {
ethereum?: {
isMetaMask?: boolean;
isConnected?: boolean;
selectedAddress?: string;
request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;
on(event: 'accountsChanged', listener: (accounts: string[]) => void): void;
on(event: 'chainChanged', listener: (chainId: string) => void): void;
on(event: string, listener: (...args: unknown[]) => void): void;
removeListener(event: 'accountsChanged', listener: (accounts: string[]) => void): void;
removeListener(event: 'chainChanged', listener: (chainId: string) => void): void;
removeListener(event: string, listener: (...args: unknown[]) => void): void;
};
}
}