mirror of
https://github.com/logos-messaging/examples.waku.org.git
synced 2026-01-02 12:53:08 +00:00
168 lines
3.7 KiB
JavaScript
168 lines
3.7 KiB
JavaScript
/*
|
|
to crate form:
|
|
-> generate pubkey/private key (maybe derived from wallet)
|
|
-> create scheme
|
|
-> sign scheme and send
|
|
creating form {
|
|
id(pubkey),
|
|
scheme: { nonce, scheme },
|
|
signature: "",
|
|
}
|
|
|
|
updating form {
|
|
id(pubkey),
|
|
nonce: 0,
|
|
scheme: { nonce, scheme },
|
|
signature: "",
|
|
}
|
|
|
|
fetching form:
|
|
-> get form by pubkey
|
|
-> is signature valid
|
|
-> encrypt answers
|
|
-> send update
|
|
|
|
answering form {
|
|
id(pubkey),
|
|
answers: encrypted({ nonce, answers }),
|
|
}
|
|
|
|
reading answers:
|
|
-> is possible to decrypt
|
|
->
|
|
*/
|
|
import {
|
|
createDecoder,
|
|
createEncoder,
|
|
createLightNode,
|
|
waitForRemotePeer,
|
|
} from "@waku/sdk";
|
|
import { enrTree, wakuDnsDiscovery } from "@waku/dns-discovery";
|
|
import * as utils from "@waku/utils/bytes";
|
|
|
|
const VERSION = `0.0.1-rc-1`;
|
|
|
|
export class Waku {
|
|
constructor(node) {
|
|
this.node = node;
|
|
}
|
|
|
|
static async create() {
|
|
const node = await createLightNode({
|
|
defaultBootstrap: true,
|
|
libp2p: {
|
|
peerDiscovery: [
|
|
wakuDnsDiscovery([enrTree["PROD"]], {
|
|
lightPush: 6,
|
|
store: 6,
|
|
filter: 6,
|
|
}),
|
|
],
|
|
},
|
|
});
|
|
|
|
await waitForRemotePeer(node);
|
|
|
|
return new Waku(node);
|
|
}
|
|
}
|
|
|
|
class Form {
|
|
constructor({ pubKey, privateKey, waku }) {
|
|
this.waku = waku;
|
|
this.history = [];
|
|
this.pubKey = pubKey;
|
|
this.privateKey = privateKey;
|
|
this.decoder = createDecoder(this.contentTopic);
|
|
this.contentTopic = `/free-form/${VERSION}/definition/proto`;
|
|
this.encoder = createEncoder({ contentTopic: this.contentTopic });
|
|
}
|
|
|
|
// Initiates new form
|
|
static async create(waku, { scheme }) {
|
|
const form = new Form(id, waku);
|
|
await form.createNew({ scheme });
|
|
return form;
|
|
}
|
|
|
|
// Fetches history of an existing form
|
|
static async fetch(waku, id) {
|
|
// TODO: throw on attempt to fetch non existing form
|
|
const form = new Form(id, waku);
|
|
await form.fetchState(id);
|
|
return form;
|
|
}
|
|
|
|
async createNew({ scheme }) {
|
|
// TODO: throw on attempt to create existing form
|
|
const command = {
|
|
type: "CREATE",
|
|
nonce: 0,
|
|
signature: "",
|
|
scheme,
|
|
};
|
|
const payload = this.toPayload(command);
|
|
await this.waku.lightPush.send(this.encoder, { payload });
|
|
this.history.push(command);
|
|
console.log("DEBUG", this.history);
|
|
}
|
|
|
|
async fetchState() {
|
|
let historyPromises = [];
|
|
|
|
for await (const promises of this.waku.store.queryGenerator([
|
|
this.decoder,
|
|
])) {
|
|
historyPromises = [...historyPromises, ...promises];
|
|
}
|
|
|
|
if (!historyPromises.length) {
|
|
console.error("DEBUG", "No form info fetched from store");
|
|
}
|
|
|
|
const commandPackets = await Promise.all(historyPromises);
|
|
const commands = commandPackets
|
|
.map(({ payload }) => {
|
|
try {
|
|
// validate scheme of command record
|
|
// check signature
|
|
const command = this.toCommand(payload);
|
|
return command;
|
|
} catch (e) {
|
|
console.error("DEBUG", "failed to parse update command.");
|
|
return;
|
|
}
|
|
})
|
|
.filter((c) => !!c);
|
|
|
|
this.history = [...this.history, ...commands];
|
|
console.log("DEBUG", this.history);
|
|
}
|
|
|
|
async patchState({ scheme }) {
|
|
if (!this.history.length) {
|
|
throw Error("no history");
|
|
}
|
|
|
|
const command = {
|
|
type: "PATCH",
|
|
nonce: this.history[this.history.length - 1].nonce + 1,
|
|
signature: "",
|
|
scheme,
|
|
};
|
|
const payload = this.toPayload(command);
|
|
|
|
await this.waku.lightPush.send(this.encoder, { payload });
|
|
this.history.push(command);
|
|
console.log("DEBUG patch", this.history);
|
|
}
|
|
|
|
toPayload(command) {
|
|
return utils.utf8ToBytes(JSON.stringify(command));
|
|
}
|
|
|
|
toCommand(payload) {
|
|
return JSON.parse(utils.bytesToUtf8(payload));
|
|
}
|
|
}
|