mirror of
https://github.com/logos-messaging/lab.waku.org.git
synced 2026-01-04 23:03:08 +00:00
chore(keystore-management): upgrade to new API (#125)
This commit is contained in:
parent
1700af13b0
commit
b3b261fc26
56
examples/keystore-management/package-lock.json
generated
56
examples/keystore-management/package-lock.json
generated
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -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',
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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)}
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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';
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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';
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
29
examples/keystore-management/src/contexts/wallet/types.ts
Normal file
29
examples/keystore-management/src/contexts/wallet/types.ts
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user