chore(buddybook): improvements

This commit is contained in:
Danish Arora 2024-11-13 12:20:46 +07:00
parent c047f204e9
commit 8ce736a665
No known key found for this signature in database
GPG Key ID: 1C6EF37CDAE1426E
3 changed files with 96 additions and 57 deletions

View File

@ -16,6 +16,8 @@ import ConnectionStatus from '@/components/ConnectionStatus';
type Status = 'success' | 'in-progress' | 'error'; type Status = 'success' | 'in-progress' | 'error';
interface WakuStatus { interface WakuStatus {
filter: Status; filter: Status;
store: Status; store: Status;
@ -30,6 +32,9 @@ function App() {
filter: 'in-progress', filter: 'in-progress',
store: 'in-progress', store: 'in-progress',
}); });
(global.window as any).waku = node;
const [telemetryOptIn, setTelemetryOptIn] = useState<boolean | null>(null); const [telemetryOptIn, setTelemetryOptIn] = useState<boolean | null>(null);
const [isLoadingChains, setIsLoadingChains] = useState(true); const [isLoadingChains, setIsLoadingChains] = useState(true);
@ -41,10 +46,22 @@ function App() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (isWakuLoading || !node || node.libp2p.getConnections().length <= 1 || chainsData.length > 0 || isListening) return; if (isWakuLoading || !node || node.libp2p.getConnections().length === 0 || chainsData.length > 0 || isListening) {
console.log("not starting message listening");
console.log({
isWakuLoading,
node,
connections: node?.libp2p.getConnections().length,
chainsData,
isListening
})
return;
}
setIsListening(true); setIsListening(true);
console.log("connections", node.libp2p.getConnections().length) console.log("connections", node.libp2p.getConnections().length)
startMessageListening(); setTimeout(() => {
startMessageListening();
}, 2000);
}, [node, isWakuLoading, wakuStatus]) }, [node, isWakuLoading, wakuStatus])
const handleTelemetryOptIn = (optIn: boolean) => { const handleTelemetryOptIn = (optIn: boolean) => {
@ -69,25 +86,36 @@ function App() {
const startMessageListening = async () => { const startMessageListening = async () => {
console.log("Starting message listening") console.log("Starting message listening")
console.log("connections", node.libp2p.getConnections().length) console.log("connections", node.libp2p.getConnections().length)
// Add timeout for store query
const STORE_TIMEOUT = 30000; // 30 seconds
const storeTimeout = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Store query timeout')), STORE_TIMEOUT);
});
try { try {
setWakuStatus(prev => ({ ...prev, store: 'in-progress' })); setWakuStatus(prev => ({ ...prev, store: 'in-progress' }));
setIsLoadingChains(true); setIsLoadingChains(true);
const messageGenerator = getMessagesFromStore(node as LightNode); const messageGenerator = getMessagesFromStore(node as LightNode);
try { try {
for await (const message of messageGenerator) { // Race between store query and timeout
setChainsData(prevChains => { await Promise.race([
const blockExists = prevChains.some(block => block.blockUUID === message.blockUUID); (async () => {
if (blockExists) return prevChains; for await (const message of messageGenerator) {
return [...prevChains, message]; setChainsData(prevChains => {
}); const blockExists = prevChains.some(block => block.blockUUID === message.blockUUID);
} if (blockExists) return prevChains;
return [...prevChains, message];
});
}
})(),
storeTimeout
]);
setWakuStatus(prev => ({ ...prev, store: 'success' })); setWakuStatus(prev => ({ ...prev, store: 'success' }));
} catch (error) { } catch (error) {
console.error("Error processing message:", error); console.error("Error processing message:", error);
// Update store status to error when query fails
setWakuStatus(prev => ({ ...prev, store: 'error' })); setWakuStatus(prev => ({ ...prev, store: 'error' }));
// Continue processing other messages
} }
} catch (error) { } catch (error) {
console.error("Error fetching messages from store:", error); console.error("Error fetching messages from store:", error);
@ -96,11 +124,21 @@ function App() {
setIsLoadingChains(false); setIsLoadingChains(false);
} }
// Add timeout for filter subscription
const FILTER_TIMEOUT = 15000; // 15 seconds
try { try {
setWakuStatus(prev => ({ ...prev, filter: 'in-progress' })); setWakuStatus(prev => ({ ...prev, filter: 'in-progress' }));
await subscribeToFilter(node as LightNode, (message) => { const filterPromise = subscribeToFilter(node as LightNode, (message) => {
handleChainUpdate(message); // Use the same function for both updates handleChainUpdate(message);
}) });
await Promise.race([
filterPromise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Filter subscription timeout')), FILTER_TIMEOUT)
)
]);
setWakuStatus(prev => ({ ...prev, filter: 'success' })); setWakuStatus(prev => ({ ...prev, filter: 'success' }));
} catch (error) { } catch (error) {
console.error("Error subscribing to filter:", error); console.error("Error subscribing to filter:", error);

View File

@ -171,8 +171,8 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'} {alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'}
</Button> </Button>
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent className="sm:max-w-md flex flex-col max-h-[90vh] md:max-h-[85vh]"> <DialogContent className="sm:max-w-md">
<DialogHeader className="flex-shrink-0"> <DialogHeader>
<DialogTitle>Sign Chain</DialogTitle> <DialogTitle>Sign Chain</DialogTitle>
<DialogDescription> <DialogDescription>
{alreadySigned {alreadySigned
@ -180,32 +180,28 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
: 'Review the block details and sign to add your signature to the chain.'} : 'Review the block details and sign to add your signature to the chain.'}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="flex-1 min-h-0 overflow-y-auto py-4"> <div className="flex flex-col space-y-4">
<div className="space-y-4"> <div className="space-y-2">
<div className="space-y-2"> <h4 className="font-medium">Block Details</h4>
<h4 className="font-medium">Block Details</h4> <p className="text-sm text-muted-foreground">{block.title}</p>
<p className="text-sm text-muted-foreground">{block.title}</p> <p className="text-sm text-muted-foreground">{block.description}</p>
<p className="text-sm text-muted-foreground">{block.description}</p>
</div>
<div className="flex justify-center">
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
</div>
</div> </div>
{(error || isWalletPrompt) && ( <QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
<div className="space-y-2 mt-4">
{error && <p className="text-sm text-destructive">{error}</p>}
{isWalletPrompt && (
<div className="rounded-md bg-blue-50 p-4">
<p className="text-sm text-blue-700">Attempting to connect to your wallet...</p>
<p className="text-xs text-blue-600 mt-1">
If your wallet doesn't open automatically, please open it manually to approve the connection.
</p>
</div>
)}
</div>
)}
</div> </div>
<DialogFooter className="flex-shrink-0 mt-4"> {(error || isWalletPrompt) && (
<div className="space-y-2">
{error && <p className="text-sm text-destructive">{error}</p>}
{isWalletPrompt && (
<div className="rounded-md bg-blue-50 p-4">
<p className="text-sm text-blue-700">Attempting to connect to your wallet...</p>
<p className="text-xs text-blue-600 mt-1">
If your wallet doesn't open automatically, please open it manually to approve the connection.
</p>
</div>
)}
</div>
)}
<DialogFooter>
<Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button> <Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button <Button
onClick={handleSign} onClick={handleSign}

View File

@ -65,28 +65,33 @@ export function createMessage({
export async function* getMessagesFromStore(node: LightNode) { export async function* getMessagesFromStore(node: LightNode) {
console.time("getMessagesFromStore") console.time("getMessagesFromStore")
for await (const messagePromises of node.store.queryGenerator([decoder])) { try {
const messages = await Promise.all(messagePromises); for await (const messagePromises of node.store.queryGenerator([decoder])) {
for (const message of messages) { const messages = await Promise.all(messagePromises);
console.log(message) for (const message of messages) {
if (!message?.payload) continue; if (!message?.payload) continue;
const blockPayload = block.decode(message.payload) as unknown as BlockPayload; const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature); blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
yield blockPayload; yield blockPayload;
}
} }
} finally {
console.timeEnd("getMessagesFromStore")
} }
console.timeEnd("getMessagesFromStore")
} }
export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) { export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) {
const {error, subscription, results} = await node.filter.subscribe([decoder], (message) => { const {error, subscription, results} = await node.filter.subscribe(
console.log('message received from filter', message) [decoder],
if (message.payload) { (message) => {
const blockPayload = block.decode(message.payload) as unknown as BlockPayload; console.log('message received from filter', message)
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature); if (message.payload) {
callback(blockPayload); const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
callback(blockPayload);
}
} }
}, {forceUseAllPeers: false}); );
console.log("results", results) console.log("results", results)
@ -94,7 +99,7 @@ export async function subscribeToFilter(node: LightNode, callback: (message: Blo
console.log("Error subscribing to filter", error) console.log("Error subscribing to filter", error)
} }
if (!subscription || error || results.successes.length === 0 ||results.failures.length >0) { if (!subscription || error || results.successes.length === 0 || results.failures.length > 0) {
throw new Error("Failed to subscribe to filter") throw new Error("Failed to subscribe to filter")
} }
} }