Skip to content

Commit 8ce736a

Browse files
chore(buddybook): improvements
1 parent c047f20 commit 8ce736a

File tree

3 files changed

+96
-57
lines changed

3 files changed

+96
-57
lines changed

examples/buddybook/src/App.tsx

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import ConnectionStatus from '@/components/ConnectionStatus';
1616

1717
type Status = 'success' | 'in-progress' | 'error';
1818

19+
20+
1921
interface WakuStatus {
2022
filter: Status;
2123
store: Status;
@@ -30,6 +32,9 @@ function App() {
3032
filter: 'in-progress',
3133
store: 'in-progress',
3234
});
35+
36+
(global.window as any).waku = node;
37+
3338
const [telemetryOptIn, setTelemetryOptIn] = useState<boolean | null>(null);
3439
const [isLoadingChains, setIsLoadingChains] = useState(true);
3540

@@ -41,10 +46,22 @@ function App() {
4146
}, []);
4247

4348
useEffect(() => {
44-
if (isWakuLoading || !node || node.libp2p.getConnections().length <= 1 || chainsData.length > 0 || isListening) return;
49+
if (isWakuLoading || !node || node.libp2p.getConnections().length === 0 || chainsData.length > 0 || isListening) {
50+
console.log("not starting message listening");
51+
console.log({
52+
isWakuLoading,
53+
node,
54+
connections: node?.libp2p.getConnections().length,
55+
chainsData,
56+
isListening
57+
})
58+
return;
59+
}
4560
setIsListening(true);
4661
console.log("connections", node.libp2p.getConnections().length)
47-
startMessageListening();
62+
setTimeout(() => {
63+
startMessageListening();
64+
}, 2000);
4865
}, [node, isWakuLoading, wakuStatus])
4966

5067
const handleTelemetryOptIn = (optIn: boolean) => {
@@ -69,25 +86,36 @@ function App() {
6986
const startMessageListening = async () => {
7087
console.log("Starting message listening")
7188
console.log("connections", node.libp2p.getConnections().length)
89+
90+
// Add timeout for store query
91+
const STORE_TIMEOUT = 30000; // 30 seconds
92+
const storeTimeout = new Promise((_, reject) => {
93+
setTimeout(() => reject(new Error('Store query timeout')), STORE_TIMEOUT);
94+
});
95+
7296
try {
7397
setWakuStatus(prev => ({ ...prev, store: 'in-progress' }));
7498
setIsLoadingChains(true);
7599
const messageGenerator = getMessagesFromStore(node as LightNode);
76100

77101
try {
78-
for await (const message of messageGenerator) {
79-
setChainsData(prevChains => {
80-
const blockExists = prevChains.some(block => block.blockUUID === message.blockUUID);
81-
if (blockExists) return prevChains;
82-
return [...prevChains, message];
83-
});
84-
}
102+
// Race between store query and timeout
103+
await Promise.race([
104+
(async () => {
105+
for await (const message of messageGenerator) {
106+
setChainsData(prevChains => {
107+
const blockExists = prevChains.some(block => block.blockUUID === message.blockUUID);
108+
if (blockExists) return prevChains;
109+
return [...prevChains, message];
110+
});
111+
}
112+
})(),
113+
storeTimeout
114+
]);
85115
setWakuStatus(prev => ({ ...prev, store: 'success' }));
86116
} catch (error) {
87117
console.error("Error processing message:", error);
88-
// Update store status to error when query fails
89118
setWakuStatus(prev => ({ ...prev, store: 'error' }));
90-
// Continue processing other messages
91119
}
92120
} catch (error) {
93121
console.error("Error fetching messages from store:", error);
@@ -96,11 +124,21 @@ function App() {
96124
setIsLoadingChains(false);
97125
}
98126

127+
// Add timeout for filter subscription
128+
const FILTER_TIMEOUT = 15000; // 15 seconds
99129
try {
100130
setWakuStatus(prev => ({ ...prev, filter: 'in-progress' }));
101-
await subscribeToFilter(node as LightNode, (message) => {
102-
handleChainUpdate(message); // Use the same function for both updates
103-
})
131+
const filterPromise = subscribeToFilter(node as LightNode, (message) => {
132+
handleChainUpdate(message);
133+
});
134+
135+
await Promise.race([
136+
filterPromise,
137+
new Promise((_, reject) =>
138+
setTimeout(() => reject(new Error('Filter subscription timeout')), FILTER_TIMEOUT)
139+
)
140+
]);
141+
104142
setWakuStatus(prev => ({ ...prev, filter: 'success' }));
105143
} catch (error) {
106144
console.error("Error subscribing to filter:", error);

examples/buddybook/src/components/Chain/SignChain.tsx

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -171,41 +171,37 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
171171
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'}
172172
</Button>
173173
<Dialog open={isOpen} onOpenChange={setIsOpen}>
174-
<DialogContent className="sm:max-w-md flex flex-col max-h-[90vh] md:max-h-[85vh]">
175-
<DialogHeader className="flex-shrink-0">
174+
<DialogContent className="sm:max-w-md">
175+
<DialogHeader>
176176
<DialogTitle>Sign Chain</DialogTitle>
177177
<DialogDescription>
178178
{alreadySigned
179179
? 'You have already signed this chain.'
180180
: 'Review the block details and sign to add your signature to the chain.'}
181181
</DialogDescription>
182182
</DialogHeader>
183-
<div className="flex-1 min-h-0 overflow-y-auto py-4">
184-
<div className="space-y-4">
185-
<div className="space-y-2">
186-
<h4 className="font-medium">Block Details</h4>
187-
<p className="text-sm text-muted-foreground">{block.title}</p>
188-
<p className="text-sm text-muted-foreground">{block.description}</p>
189-
</div>
190-
<div className="flex justify-center">
191-
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
192-
</div>
183+
<div className="flex flex-col space-y-4">
184+
<div className="space-y-2">
185+
<h4 className="font-medium">Block Details</h4>
186+
<p className="text-sm text-muted-foreground">{block.title}</p>
187+
<p className="text-sm text-muted-foreground">{block.description}</p>
193188
</div>
194-
{(error || isWalletPrompt) && (
195-
<div className="space-y-2 mt-4">
196-
{error && <p className="text-sm text-destructive">{error}</p>}
197-
{isWalletPrompt && (
198-
<div className="rounded-md bg-blue-50 p-4">
199-
<p className="text-sm text-blue-700">Attempting to connect to your wallet...</p>
200-
<p className="text-xs text-blue-600 mt-1">
201-
If your wallet doesn't open automatically, please open it manually to approve the connection.
202-
</p>
203-
</div>
204-
)}
205-
</div>
206-
)}
189+
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
207190
</div>
208-
<DialogFooter className="flex-shrink-0 mt-4">
191+
{(error || isWalletPrompt) && (
192+
<div className="space-y-2">
193+
{error && <p className="text-sm text-destructive">{error}</p>}
194+
{isWalletPrompt && (
195+
<div className="rounded-md bg-blue-50 p-4">
196+
<p className="text-sm text-blue-700">Attempting to connect to your wallet...</p>
197+
<p className="text-xs text-blue-600 mt-1">
198+
If your wallet doesn't open automatically, please open it manually to approve the connection.
199+
</p>
200+
</div>
201+
)}
202+
</div>
203+
)}
204+
<DialogFooter>
209205
<Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
210206
<Button
211207
onClick={handleSign}

examples/buddybook/src/lib/waku.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,36 +65,41 @@ export function createMessage({
6565

6666
export async function* getMessagesFromStore(node: LightNode) {
6767
console.time("getMessagesFromStore")
68-
for await (const messagePromises of node.store.queryGenerator([decoder])) {
69-
const messages = await Promise.all(messagePromises);
70-
for (const message of messages) {
71-
console.log(message)
72-
if (!message?.payload) continue;
73-
const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
74-
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
75-
yield blockPayload;
68+
try {
69+
for await (const messagePromises of node.store.queryGenerator([decoder])) {
70+
const messages = await Promise.all(messagePromises);
71+
for (const message of messages) {
72+
if (!message?.payload) continue;
73+
const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
74+
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
75+
yield blockPayload;
76+
}
7677
}
78+
} finally {
79+
console.timeEnd("getMessagesFromStore")
7780
}
78-
console.timeEnd("getMessagesFromStore")
7981
}
8082

8183
export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) {
82-
const {error, subscription, results} = await node.filter.subscribe([decoder], (message) => {
83-
console.log('message received from filter', message)
84-
if (message.payload) {
85-
const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
86-
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
87-
callback(blockPayload);
84+
const {error, subscription, results} = await node.filter.subscribe(
85+
[decoder],
86+
(message) => {
87+
console.log('message received from filter', message)
88+
if (message.payload) {
89+
const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
90+
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
91+
callback(blockPayload);
92+
}
8893
}
89-
}, {forceUseAllPeers: false});
94+
);
9095

9196
console.log("results", results)
9297

9398
if (error) {
9499
console.log("Error subscribing to filter", error)
95100
}
96101

97-
if (!subscription || error || results.successes.length === 0 ||results.failures.length >0) {
102+
if (!subscription || error || results.successes.length === 0 || results.failures.length > 0) {
98103
throw new Error("Failed to subscribe to filter")
99104
}
100105
}

0 commit comments

Comments
 (0)