Skip to content

Commit de2cf76

Browse files
committed
add skeleton functions for space events and identity
1 parent 4d8b3f9 commit de2cf76

File tree

12 files changed

+314
-0
lines changed

12 files changed

+314
-0
lines changed

docs/technology-stack.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Technology Stack
2+
3+
- Frontend
4+
- React
5+
- Shadcn
6+
- Vite
7+
- TypeScript
8+
- Testing
9+
- Vitest
10+
- Backend
11+
- Database: Postgres + Prisma (explore Neo4j as well)
12+
- API: Websocket
13+
- Effect
14+
- Other
15+
- CRDT: Automerge
16+
- Cryptography: Nobel
17+
- Auth: Privy
18+
- ESM
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { v4 as uuidv4 } from "uuid";
2+
3+
export const generateId = () => {
4+
return uuidv4();
5+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export const createIdentity = () => {
2+
return {
3+
signaturePublicKey: "",
4+
signaturePrivateKey: "",
5+
encryptionPublicKey: "",
6+
encryptionPrivateKey: "",
7+
};
8+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
type Params = {
2+
preKey: string;
3+
};
4+
5+
export const restoreIdentity = ({ preKey }: Params) => {
6+
return {
7+
signaturePublicKey: "",
8+
signaturePrivateKey: "",
9+
encryptionPublicKey: "",
10+
encryptionPrivateKey: "",
11+
};
12+
};
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {
2+
SpaceEvent,
3+
SpaceInvitation,
4+
SpaceMember,
5+
SpaceState,
6+
} from "./types.js";
7+
8+
type Params = {
9+
state?: SpaceState;
10+
event: SpaceEvent;
11+
};
12+
13+
export const applyEvent = ({ state, event: rawEvent }: Params): SpaceState => {
14+
// TODO parse the event
15+
const event = rawEvent;
16+
17+
// TODO verify the event
18+
// - verify the signature
19+
// - verify that this event is based on the previous one
20+
// - verify versioning
21+
22+
let id = "";
23+
let members: { [signaturePublicKey: string]: SpaceMember } = {};
24+
let removedMembers: { [signaturePublicKey: string]: SpaceMember } = {};
25+
let invitations: { [id: string]: SpaceInvitation } = {};
26+
27+
if (event.transaction.type === "create-space") {
28+
id = event.transaction.id;
29+
members[event.transaction.creatorSignaturePublicKey] = {
30+
signaturePublicKey: event.transaction.creatorSignaturePublicKey,
31+
encryptionPublicKey: event.transaction.creatorEncryptionPublicKey,
32+
role: "admin",
33+
};
34+
} else if (state !== undefined) {
35+
id = state.id;
36+
members = { ...state.members };
37+
removedMembers = { ...state.removedMembers };
38+
invitations = { ...state.invitations };
39+
40+
if (event.transaction.type === "delete-space") {
41+
removedMembers = { ...members };
42+
members = {};
43+
invitations = {};
44+
} else if (event.transaction.type === "create-invitation") {
45+
invitations[event.transaction.id] = {
46+
signaturePublicKey: event.transaction.signaturePublicKey,
47+
encryptionPublicKey: event.transaction.encryptionPublicKey,
48+
};
49+
}
50+
} else {
51+
throw new Error("State is required for all events except create-space");
52+
}
53+
54+
return {
55+
id,
56+
members,
57+
removedMembers,
58+
invitations,
59+
transactionHash: "", // TODO
60+
};
61+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect, it } from "vitest";
2+
import { applyEvent } from "./apply-event.js";
3+
import { createInvitation } from "./create-invitation.js";
4+
import { createSpace } from "./create-space.js";
5+
6+
it("should create an invitation", () => {
7+
const author = {
8+
signaturePublicKey: "signature",
9+
encryptionPublicKey: "encryption",
10+
};
11+
const spaceEvent = createSpace({ author });
12+
const state = applyEvent({ event: spaceEvent });
13+
const spaceEvent2 = createInvitation({ author, id: state.id });
14+
const state2 = applyEvent({ state, event: spaceEvent2 });
15+
expect(state2).toEqual({
16+
id: state.id,
17+
members: {
18+
[author.signaturePublicKey]: {
19+
signaturePublicKey: author.signaturePublicKey,
20+
encryptionPublicKey: author.encryptionPublicKey,
21+
role: "admin",
22+
},
23+
},
24+
removedMembers: {},
25+
invitations: {
26+
[spaceEvent2.transaction.id]: {
27+
signaturePublicKey: "",
28+
encryptionPublicKey: "",
29+
},
30+
},
31+
transactionHash: "",
32+
});
33+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Author, SpaceEvent } from "./types.js";
2+
3+
type Params = {
4+
author: Author;
5+
id: string;
6+
};
7+
8+
export const createInvitation = ({ author, id }: Params): SpaceEvent => {
9+
const transaction = {
10+
type: "create-invitation" as const,
11+
id,
12+
ciphertext: "",
13+
nonce: "",
14+
signaturePublicKey: "",
15+
encryptionPublicKey: "",
16+
};
17+
// TODO canonicalize, hash and sign the transaction
18+
const signature = "";
19+
20+
return {
21+
transaction,
22+
author: {
23+
publicKey: author.signaturePublicKey,
24+
signature,
25+
},
26+
};
27+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { expect, it } from "vitest";
2+
import { applyEvent } from "./apply-event.js";
3+
import { createSpace } from "./create-space.js";
4+
5+
it("should create a space state", () => {
6+
const author = {
7+
signaturePublicKey: "signature",
8+
encryptionPublicKey: "encryption",
9+
};
10+
const spaceEvent = createSpace({ author });
11+
const state = applyEvent({ event: spaceEvent });
12+
expect(state).toEqual({
13+
id: spaceEvent.transaction.id,
14+
invitations: {},
15+
members: {
16+
[author.signaturePublicKey]: {
17+
signaturePublicKey: author.signaturePublicKey,
18+
encryptionPublicKey: author.encryptionPublicKey,
19+
role: "admin",
20+
},
21+
},
22+
removedMembers: {},
23+
transactionHash: "",
24+
});
25+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { generateId } from "../generateId.js";
2+
import { Author, SpaceEvent } from "./types.js";
3+
4+
type Params = {
5+
author: Author;
6+
};
7+
8+
export const createSpace = ({ author }: Params): SpaceEvent => {
9+
const transaction = {
10+
type: "create-space" as const,
11+
id: generateId(),
12+
creatorSignaturePublicKey: author.signaturePublicKey,
13+
creatorEncryptionPublicKey: author.encryptionPublicKey,
14+
};
15+
// TODO canonicalize, hash and sign the transaction
16+
const signature = "";
17+
18+
return {
19+
transaction,
20+
author: {
21+
publicKey: author.signaturePublicKey,
22+
signature,
23+
},
24+
};
25+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { expect, it } from "vitest";
2+
import { applyEvent } from "./apply-event.js";
3+
import { createSpace } from "./create-space.js";
4+
import { deleteSpace } from "./delete-space.js";
5+
6+
it("should delete a space", () => {
7+
const author = {
8+
signaturePublicKey: "signature",
9+
encryptionPublicKey: "encryption",
10+
};
11+
const spaceEvent = createSpace({ author });
12+
const state = applyEvent({ event: spaceEvent });
13+
const spaceEvent2 = deleteSpace({ author, id: state.id });
14+
const state2 = applyEvent({ state, event: spaceEvent2 });
15+
expect(state2).toEqual({
16+
id: state.id,
17+
members: {},
18+
invitations: {},
19+
removedMembers: {
20+
[author.signaturePublicKey]: {
21+
signaturePublicKey: author.signaturePublicKey,
22+
encryptionPublicKey: author.encryptionPublicKey,
23+
role: "admin",
24+
},
25+
},
26+
transactionHash: "",
27+
});
28+
});

0 commit comments

Comments
 (0)