chore: add telemetry to buddy book and change text to use Book instea… (#110)
This commit is contained in:
parent
87d1499aa1
commit
7613b1e9e4
File diff suppressed because it is too large
Load Diff
|
@ -50,6 +50,7 @@
|
|||
"@types/react-dom": "^18.3.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"@waku/interfaces": "^0.0.29-5674b0e.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
|
|
|
@ -206,15 +206,15 @@ const Home: React.FC = () => (
|
|||
<div className="w-full max-w-sm mx-auto p-4 md:p-6 bg-card rounded-lg shadow-md">
|
||||
<Link to="create">
|
||||
<Button className="w-full mb-4">
|
||||
Create New Chain
|
||||
Create New Book
|
||||
</Button>
|
||||
</Link>
|
||||
<p className="text-sm md:text-base text-muted-foreground">
|
||||
Click the button above to start creating a new chain.
|
||||
Click the button above to start creating a new book.
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs md:text-sm text-muted-foreground text-center">
|
||||
Welcome to BuddyBook - Create and share your chains!
|
||||
Welcome to BuddyBook - Create and share your books!
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -13,6 +13,7 @@ import { useWaku } from '@waku/react';
|
|||
import { LightNode } from '@waku/sdk';
|
||||
import { createMessage, encoder } from '@/lib/waku';
|
||||
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
|
||||
import { fromLightPush, Telemetry, TelemetryType, buildExtraData, toInt } from '@/lib/telemetry';
|
||||
|
||||
interface FormData {
|
||||
title: string;
|
||||
|
@ -48,18 +49,49 @@ const ChainCreationForm: React.FC = () => {
|
|||
const blockUUID = uuidv4();
|
||||
setCreatedBlockUUID(blockUUID);
|
||||
|
||||
const timestamp = Date.now();
|
||||
const message = createMessage({
|
||||
chainUUID: formData.uuid,
|
||||
blockUUID: blockUUID,
|
||||
title: formData.title,
|
||||
description: formData.description,
|
||||
signedMessage: signature,
|
||||
timestamp: Date.now(),
|
||||
timestamp: timestamp,
|
||||
signatures: [{address, signature}],
|
||||
parentBlockUUID: null
|
||||
});
|
||||
|
||||
await node?.lightPush.send(encoder, message)
|
||||
try {
|
||||
const result = await node?.lightPush.send(encoder, message);
|
||||
Telemetry.push(fromLightPush({
|
||||
result,
|
||||
wallet: address,
|
||||
bookId: formData.uuid,
|
||||
node,
|
||||
encoder,
|
||||
timestamp,
|
||||
}));
|
||||
} catch (e) {
|
||||
Telemetry.push([{
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "lightPush",
|
||||
timestamp: toInt(timestamp),
|
||||
createdAt: toInt(timestamp),
|
||||
seenTimestamp: toInt(timestamp),
|
||||
peerId: node.peerId.toString(),
|
||||
contentTopic: encoder.contentTopic,
|
||||
pubsubTopic: encoder.pubsubTopic,
|
||||
ephemeral: encoder.ephemeral,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: (e as Error)?.message ?? "Error during LightPush",
|
||||
extraData: buildExtraData({
|
||||
wallet: address,
|
||||
bookId: formData.uuid,
|
||||
}),
|
||||
}]);
|
||||
throw e;
|
||||
}
|
||||
|
||||
setIsSuccess(true);
|
||||
setIsSigning(false);
|
||||
},
|
||||
|
@ -112,8 +144,8 @@ const ChainCreationForm: React.FC = () => {
|
|||
const handleSubmit = async () => {
|
||||
setIsSigning(true);
|
||||
setSendError(null);
|
||||
const message = `Create Chain:
|
||||
Chain UUID: ${formData.uuid}
|
||||
const message = `Create Book:
|
||||
Book UUID: ${formData.uuid}
|
||||
Title: ${formData.title}
|
||||
Description: ${formData.description}
|
||||
Timestamp: ${new Date().getTime()}
|
||||
|
@ -132,12 +164,12 @@ const ChainCreationForm: React.FC = () => {
|
|||
return (
|
||||
<Card className="w-full max-w-2xl mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>Create a New Chain</CardTitle>
|
||||
<CardTitle>Create a New Book</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleCreateChain} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="title">Chain Title</Label>
|
||||
<Label htmlFor="title">Book Title</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="title"
|
||||
|
@ -150,7 +182,7 @@ const ChainCreationForm: React.FC = () => {
|
|||
{errors.title && <p className="text-sm text-destructive">{errors.title}</p>}
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description">Chain Description</Label>
|
||||
<Label htmlFor="description">Book Description</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
name="description"
|
||||
|
@ -161,13 +193,13 @@ const ChainCreationForm: React.FC = () => {
|
|||
/>
|
||||
{errors.description && <p className="text-sm text-destructive">{errors.description}</p>}
|
||||
</div>
|
||||
<Button type="submit" className="w-full py-6 text-base sm:py-2 sm:text-sm">Create Chain</Button>
|
||||
<Button type="submit" className="w-full py-6 text-base sm:py-2 sm:text-sm">Create Book</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
<Dialog open={showModal} onOpenChange={handleCloseModal}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{isSuccess ? "Chain Created" : "Chain Preview"}</DialogTitle>
|
||||
<DialogTitle>{isSuccess ? "Book Created" : "Book Preview"}</DialogTitle>
|
||||
</DialogHeader>
|
||||
{!isSuccess ? (
|
||||
<>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Loader2 } from "lucide-react";
|
|||
import QRCode from '@/components/QRCode';
|
||||
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { fromLightPush, Telemetry } from '@/lib/telemetry';
|
||||
|
||||
interface SignChainProps {
|
||||
block: BlockPayload;
|
||||
|
@ -76,19 +77,31 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||
return;
|
||||
}
|
||||
|
||||
const timestamp = Date.now();
|
||||
const newBlock: BlockPayload = {
|
||||
chainUUID: block.chainUUID,
|
||||
blockUUID: uuidv4(),
|
||||
title: block.title,
|
||||
description: block.description,
|
||||
signedMessage: signature,
|
||||
timestamp: Date.now(),
|
||||
timestamp,
|
||||
signatures: [{ address, signature }],
|
||||
parentBlockUUID: block.blockUUID
|
||||
};
|
||||
|
||||
const wakuMessage = createMessage(newBlock);
|
||||
const { failures, successes } = await node.lightPush.send(encoder, wakuMessage);
|
||||
const result = await node.lightPush.send(encoder, wakuMessage);
|
||||
|
||||
Telemetry.push(fromLightPush({
|
||||
result,
|
||||
node,
|
||||
encoder,
|
||||
timestamp,
|
||||
bookId: block.chainUUID,
|
||||
wallet: address,
|
||||
}));
|
||||
|
||||
const { failures, successes } = result;
|
||||
|
||||
if (failures.length > 0 || successes.length === 0) {
|
||||
throw new Error('Failed to send message to Waku network');
|
||||
|
@ -168,16 +181,16 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||
return (
|
||||
<>
|
||||
<Button onClick={() => setIsOpen(true)} disabled={alreadySigned}>
|
||||
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'}
|
||||
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Book'}
|
||||
</Button>
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Sign Chain</DialogTitle>
|
||||
<DialogTitle>Sign Book</DialogTitle>
|
||||
<DialogDescription>
|
||||
{alreadySigned
|
||||
? 'You have already signed this chain.'
|
||||
: 'Review the block details and sign to add your signature to the chain.'}
|
||||
? 'You have already signed this book.'
|
||||
: 'Review the block details and sign to add your signature to the book.'}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col space-y-4">
|
||||
|
|
|
@ -29,7 +29,7 @@ const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUp
|
|||
<Card className="w-full max-w-md mx-auto">
|
||||
<CardContent className="flex flex-col items-center justify-center py-8 space-y-4">
|
||||
<Loader2 className="h-8 w-8 animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">Looking for chain...</p>
|
||||
<p className="text-sm text-muted-foreground">Looking for book...</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
@ -39,11 +39,11 @@ const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUp
|
|||
return (
|
||||
<Card className="w-full max-w-md mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>Chain Not Found</CardTitle>
|
||||
<CardTitle>Book Not Found</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="mb-4">The requested chain or block could not be found.</p>
|
||||
<Button onClick={() => navigate('/view')}>View All Chains</Button>
|
||||
<p className="mb-4">The requested book or block could not be found.</p>
|
||||
<Button onClick={() => navigate('/view')}>View All Books</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
@ -52,7 +52,7 @@ const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUp
|
|||
return (
|
||||
<Card className="w-full max-w-2xl mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>Sign Shared Chain</CardTitle>
|
||||
<CardTitle>Sign Shared Book</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<h2 className="text-xl font-semibold mb-2">{block.title}</h2>
|
||||
|
|
|
@ -66,9 +66,9 @@ const ChainList: React.FC<ChainListProps> = ({ chainsData, onChainUpdate, isLoad
|
|||
</DialogTrigger>
|
||||
<DialogContent className="flex flex-col gap-4">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Share Chain</DialogTitle>
|
||||
<DialogTitle>Share this Book</DialogTitle>
|
||||
<DialogDescription>
|
||||
Share this chain with others to collect their signatures.
|
||||
Share this book with others to collect their signatures.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
@ -110,18 +110,18 @@ const ChainList: React.FC<ChainListProps> = ({ chainsData, onChainUpdate, isLoad
|
|||
<Card className="w-full max-w-4xl mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
Existing Chains
|
||||
Existing Books
|
||||
{isLoading && (
|
||||
<span className="ml-2 inline-flex items-center text-muted-foreground text-sm font-normal">
|
||||
<Loader2 className="h-4 w-4 animate-spin mr-2" />
|
||||
Loading more chains...
|
||||
Loading more books...
|
||||
</span>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{rootBlocks.length === 0 && !isLoading ? (
|
||||
<p>No chains found.</p>
|
||||
<p>No books found.</p>
|
||||
) : (
|
||||
<ul className="space-y-4">
|
||||
{rootBlocks.map((block) => renderBlock(block, 0))}
|
||||
|
|
|
@ -44,8 +44,8 @@ const ConnectionStatus: React.FC<ConnectionStatusProps> = ({ filter, store }) =>
|
|||
return (
|
||||
<Card className="fixed bottom-4 left-4 right-4 md:static md:bottom-auto md:left-auto p-2 bg-background/80 backdrop-blur-sm border shadow-lg z-50 md:z-auto">
|
||||
<div className="flex flex-row justify-around md:justify-start md:gap-4">
|
||||
<StatusIndicator status={filter} label="Filter" />
|
||||
<StatusIndicator status={store} label="Store" />
|
||||
<StatusIndicator status={filter} label="Connection" />
|
||||
<StatusIndicator status={store} label="History" />
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
|
|
@ -86,14 +86,14 @@ const Header: React.FC<HeaderProps> = ({ wakuStatus }) => {
|
|||
{!isWakuLoading && !wakuError && (
|
||||
<>
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="hidden md:inline text-muted-foreground">Filter:</span>
|
||||
<span className="hidden md:inline text-muted-foreground">Connection:</span>
|
||||
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.filter)}`}></div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="hidden md:inline text-muted-foreground">Store:</span>
|
||||
<span className="hidden md:inline text-muted-foreground">History:</span>
|
||||
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.store)}`}></div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className="flex items-center space-x-1 hidden">
|
||||
<span className="hidden md:inline text-muted-foreground">Peers:</span>
|
||||
{isWakuLoading ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
import { IDecoder, IEncoder, LightNode, SDKProtocolResult, SubscribeResult } from "@waku/interfaces";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export enum TelemetryType {
|
||||
LIGHT_PUSH_FILTER = "LightPushFilter",
|
||||
}
|
||||
|
||||
interface TelemetryMessage {
|
||||
type: string;
|
||||
|
||||
timestamp: number;
|
||||
contentTopic: string;
|
||||
pubsubTopic: string;
|
||||
peerId: string;
|
||||
errorMessage: string;
|
||||
extraData: string;
|
||||
}
|
||||
|
||||
export interface TelemetryPushFilter extends TelemetryMessage {
|
||||
type: "LightPushFilter",
|
||||
protocol: string;
|
||||
ephemeral: boolean;
|
||||
seenTimestamp: number;
|
||||
createdAt: number;
|
||||
messageHash: string;
|
||||
}
|
||||
|
||||
export class TelemetryClient {
|
||||
constructor(
|
||||
private readonly url: string,
|
||||
private intervalPeriod: number = 5000
|
||||
) {
|
||||
this.start();
|
||||
}
|
||||
|
||||
private queue: TelemetryMessage[] = [];
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
private requestId = 0;
|
||||
|
||||
public push<T extends TelemetryMessage>(messages: T[]) {
|
||||
this.queue.push(...messages);
|
||||
}
|
||||
|
||||
public async start() {
|
||||
if (!this.intervalId) {
|
||||
this.intervalId = setInterval(async () => {
|
||||
if (this.queue.length > 0) {
|
||||
const success = await this.send(this.queue);
|
||||
if (success) {
|
||||
console.log("Sent ", this.queue.length, " telemetry logs");
|
||||
this.queue = [];
|
||||
}
|
||||
}
|
||||
}, this.intervalPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
public stop() {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async send<T extends TelemetryMessage>(messages: T[]) {
|
||||
const isTelemetryOn = localStorage.getItem("telemetryOptIn");
|
||||
if (!isTelemetryOn || isTelemetryOn === "false" || isTelemetryOn !== "true" || !window.location.hostname.includes("buddybook.fun")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const telemetryRequests = messages.map((message) => ({
|
||||
id: ++this.requestId,
|
||||
telemetryType: message.type.toString(),
|
||||
telemetryData: message
|
||||
}));
|
||||
|
||||
try {
|
||||
const res = await fetch(this.url, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(telemetryRequests),
|
||||
});
|
||||
if (res.status !== 201) {
|
||||
console.log("DEBUG: Error sending messages to telemetry service: ", res.status, res.statusText, res.json);
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.log("DEBUG: Error sending messages to telemetry service", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const Telemetry = new TelemetryClient("https://telemetry.status.im/waku-metrics", 5000);
|
||||
|
||||
type ExtraData = {
|
||||
wallet?: string;
|
||||
bookId?: string;
|
||||
timeTaken?: number;
|
||||
};
|
||||
|
||||
export const buildExtraData = ({
|
||||
wallet,
|
||||
bookId,
|
||||
timeTaken,
|
||||
}: ExtraData): string => {
|
||||
return JSON.stringify({
|
||||
sdk: "@waku/react:0.0.7-9a7287d",
|
||||
wallet,
|
||||
bookId,
|
||||
timeTaken,
|
||||
});
|
||||
};
|
||||
|
||||
type FromLightPush = {
|
||||
node: LightNode,
|
||||
timestamp: number,
|
||||
encoder: IEncoder,
|
||||
wallet: string,
|
||||
bookId: string,
|
||||
result: SDKProtocolResult,
|
||||
}
|
||||
|
||||
export const fromLightPush = (data: FromLightPush): TelemetryPushFilter[] => {
|
||||
const telemetry: TelemetryPushFilter[] = [];
|
||||
|
||||
data.result?.successes?.forEach((success) => {
|
||||
telemetry.push({
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "lightPush",
|
||||
timestamp: data.timestamp,
|
||||
createdAt: data.timestamp,
|
||||
seenTimestamp: data.timestamp,
|
||||
peerId: success.toString(),
|
||||
contentTopic: data.encoder.contentTopic,
|
||||
pubsubTopic: data.encoder.pubsubTopic,
|
||||
ephemeral: false,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: "",
|
||||
extraData: buildExtraData({
|
||||
bookId: data.bookId,
|
||||
wallet: data.wallet,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
data.result?.failures?.forEach((fail) => {
|
||||
telemetry.push({
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "lightPush",
|
||||
timestamp: data.timestamp,
|
||||
createdAt: data.timestamp,
|
||||
seenTimestamp: data.timestamp,
|
||||
peerId: fail?.peerId?.toString() || "missing",
|
||||
contentTopic: data.encoder.contentTopic,
|
||||
pubsubTopic: data.encoder.pubsubTopic,
|
||||
ephemeral: data.encoder.ephemeral,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: fail.error.toString(),
|
||||
extraData: buildExtraData({
|
||||
wallet: data.wallet,
|
||||
bookId: data.bookId,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
return telemetry;
|
||||
};
|
||||
|
||||
type FromFilter = {
|
||||
result: SubscribeResult,
|
||||
node: LightNode,
|
||||
timestamp: number,
|
||||
decoder: IDecoder<any>,
|
||||
};
|
||||
|
||||
export const fromFilter = (data: FromFilter): TelemetryPushFilter[] => {
|
||||
const telemetry: TelemetryPushFilter[] = [];
|
||||
const { error, results } = data.result;
|
||||
|
||||
if (error) {
|
||||
telemetry.push({
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "filter",
|
||||
timestamp: toInt(data.timestamp),
|
||||
createdAt: toInt(data.timestamp),
|
||||
seenTimestamp: toInt(data.timestamp),
|
||||
peerId: data.node.peerId.toString(),
|
||||
contentTopic: data.decoder.contentTopic,
|
||||
pubsubTopic: data.decoder.pubsubTopic,
|
||||
ephemeral: false,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: error,
|
||||
extraData: buildExtraData({}),
|
||||
});
|
||||
}
|
||||
|
||||
results?.failures?.forEach((fail) => {
|
||||
telemetry.push({
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "filter",
|
||||
timestamp: toInt(data.timestamp),
|
||||
createdAt: toInt(data.timestamp),
|
||||
seenTimestamp: toInt(data.timestamp),
|
||||
peerId: fail?.peerId?.toString() || "",
|
||||
contentTopic: data.decoder.contentTopic,
|
||||
pubsubTopic: data.decoder.pubsubTopic,
|
||||
ephemeral: false,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: fail?.error || "Unknown error",
|
||||
extraData: buildExtraData({}),
|
||||
});
|
||||
});
|
||||
|
||||
results?.successes?.forEach((success) => {
|
||||
telemetry.push({
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "filter",
|
||||
timestamp: toInt(data.timestamp),
|
||||
createdAt: toInt(data.timestamp),
|
||||
seenTimestamp: toInt(data.timestamp),
|
||||
peerId: success.toString(),
|
||||
contentTopic: data.decoder.contentTopic,
|
||||
pubsubTopic: data.decoder.pubsubTopic,
|
||||
ephemeral: false,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: "",
|
||||
extraData: buildExtraData({}),
|
||||
});
|
||||
});
|
||||
|
||||
return telemetry;
|
||||
};
|
||||
|
||||
type FromStore = {
|
||||
timestamp: number,
|
||||
timeTaken: number,
|
||||
node: LightNode,
|
||||
decoder: IDecoder<any>,
|
||||
};
|
||||
|
||||
export const fromStore = (data: FromStore): TelemetryPushFilter[] => {
|
||||
return [{
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "filter",
|
||||
timestamp: toInt(data.timestamp),
|
||||
createdAt: toInt(data.timestamp),
|
||||
seenTimestamp: toInt(data.timestamp),
|
||||
peerId: data.node.peerId.toString(),
|
||||
contentTopic: data.decoder.contentTopic,
|
||||
pubsubTopic: data.decoder.pubsubTopic,
|
||||
ephemeral: false,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: "",
|
||||
extraData: buildExtraData({
|
||||
timeTaken: data.timeTaken
|
||||
}),
|
||||
}];
|
||||
};
|
||||
|
||||
export function toInt(v: any): number {
|
||||
return parseInt(v);
|
||||
}
|
|
@ -1,8 +1,15 @@
|
|||
import { createEncoder, createDecoder, type LightNode, type CreateWakuNodeOptions } from "@waku/sdk";
|
||||
import { createEncoder, createDecoder, type LightNode } from "@waku/sdk";
|
||||
import { type CreateWakuNodeOptions } from "@waku/sdk";
|
||||
import protobuf from 'protobufjs';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Telemetry, fromFilter, fromStore, TelemetryType, buildExtraData, toInt } from "./telemetry";
|
||||
|
||||
export const WAKU_NODE_OPTIONS: CreateWakuNodeOptions = { defaultBootstrap: true, nodeToUse: {store: "/dns4/boot-01.do-ams3.status.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmEqqio4UR1SWqAc7KY19t6qyDvtmyjreZpzUBJvb4u65R"} };
|
||||
|
||||
export const WAKU_NODE_OPTIONS: CreateWakuNodeOptions = {
|
||||
defaultBootstrap: true,
|
||||
nodeToUse: {
|
||||
store: "/dns4/node-01.ac-cn-hongkong-c.waku.test.status.im/tcp/8000/wss/p2p/16Uiu2HAkzHaTP5JsUwfR9NR8Rj9HC24puS6ocaU8wze4QrXr9iXp"
|
||||
}
|
||||
};
|
||||
|
||||
export type Signature = {
|
||||
address: `0x${string}`;
|
||||
|
@ -64,35 +71,67 @@ export function createMessage({
|
|||
}
|
||||
|
||||
export async function* getMessagesFromStore(node: LightNode) {
|
||||
console.time("getMessagesFromStore")
|
||||
const startTime = performance.now();
|
||||
try {
|
||||
for await (const messagePromises of node.store.queryGenerator([decoder])) {
|
||||
const messages = await Promise.all(messagePromises);
|
||||
for (const message of messages) {
|
||||
console.log(message)
|
||||
if (!message?.payload) continue;
|
||||
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);
|
||||
yield blockPayload;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
console.timeEnd("getMessagesFromStore")
|
||||
const endTime = performance.now();
|
||||
const timeTaken = endTime - startTime;
|
||||
console.log("getMessagesFromStore", timeTaken)
|
||||
|
||||
Telemetry.push(fromStore({
|
||||
node,
|
||||
decoder,
|
||||
timestamp: startTime,
|
||||
timeTaken,
|
||||
}));
|
||||
} catch(e) {
|
||||
const endTime = performance.now();
|
||||
const timeTaken = endTime - startTime;
|
||||
Telemetry.push([{
|
||||
type: TelemetryType.LIGHT_PUSH_FILTER,
|
||||
protocol: "lightPush",
|
||||
timestamp: toInt(startTime),
|
||||
createdAt: toInt(startTime),
|
||||
seenTimestamp: toInt(startTime),
|
||||
peerId: node.peerId.toString(),
|
||||
contentTopic: encoder.contentTopic,
|
||||
pubsubTopic: encoder.pubsubTopic,
|
||||
ephemeral: encoder.ephemeral,
|
||||
messageHash: uuidv4(),
|
||||
errorMessage: (e as Error)?.message ?? "Error during Store",
|
||||
extraData: buildExtraData({ timeTaken }),
|
||||
}]);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) {
|
||||
const {error, subscription, results} = await node.filter.subscribe(
|
||||
[decoder],
|
||||
(message) => {
|
||||
const result = await node.filter.subscribe([decoder], (message) => {
|
||||
console.log('message received from filter', message)
|
||||
if (message.payload) {
|
||||
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});
|
||||
|
||||
Telemetry.push(fromFilter({
|
||||
result,
|
||||
node,
|
||||
decoder,
|
||||
timestamp: Date.now(),
|
||||
}));
|
||||
|
||||
const {error, subscription, results} = result;
|
||||
console.log("results", results)
|
||||
|
||||
if (error) {
|
||||
|
|
Loading…
Reference in New Issue