Skip to content

Commit

Permalink
fix: e2e fixes (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-roak authored Sep 11, 2024
1 parent a5873fd commit 9e2c0ab
Show file tree
Hide file tree
Showing 30 changed files with 2,419 additions and 794 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,14 @@ This repository is a monorepo that contains the following packages:
# Examples

All the examples are located in the `examples` directory. Currently, there is only one example, which is a simple canvas where you can paint pixels. You can also look into the [counter-splash](https://github.com/topology-foundation/counter-splash) (demo for EthCC 2024) repository for a more complex example.

# Usage

This workspae has all packages and examples linked together, so you can run the following commands to start the development:

```bash
# pnpm
pnpm install
```

The postinstall script will build all the packages. In case you have errors, please manually build every package inside the folder `packages`.
9 changes: 5 additions & 4 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ version: v2
plugins:
- local: ./node_modules/ts-proto/protoc-gen-ts_proto
strategy: directory
# out: ./packages/network/src
out: ./packages/object/src
out: ./packages
opt:
- esModuleInterop=true
- fileSuffix=_pb
inputs:
#- directory: ./packages/network/src
- directory: ./packages/object/src
- directory: ./packages
exclude_paths:
- packages/network/node_modules
- packages/object/node_modules
23 changes: 0 additions & 23 deletions examples/canvas/src/handlers.ts

This file was deleted.

112 changes: 48 additions & 64 deletions examples/canvas/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { GCounter } from "@topology-foundation/crdt";
import { TopologyNode } from "@topology-foundation/node";
import type { TopologyObject } from "@topology-foundation/object";
import { handleObjectOps } from "./handlers";
import { Canvas } from "./objects/canvas";
import { Pixel } from "./objects/pixel";

const node = new TopologyNode();
let canvasCRO: Canvas;
let topologyObject: TopologyObject;
let canvasCRO: Canvas;
let peers: string[] = [];
let discoveryPeers: string[] = [];
let objectPeers: string[] = [];
Expand All @@ -25,34 +22,23 @@ const render = () => {
document.getElementById("object_peers")
);
object_element.innerHTML = `[${objectPeers.join(", ")}]`;
(<HTMLSpanElement>document.getElementById("canvasId")).innerText =
topologyObject?.id;

if (!canvasCRO) return;
const canvas = canvasCRO.canvas;
const canvas_element = <HTMLDivElement>document.getElementById("canvas");
canvas_element.innerHTML = "";
canvas_element.style.display = "inline-grid";

canvas_element.style.gridTemplateColumns = Array(canvas.length)
.fill("1fr")
.join(" ");

for (let x = 0; x < canvas.length; x++) {
for (let y = 0; y < canvas[x].length; y++) {
const pixel = document.createElement("div");
pixel.id = `${x}-${y}`;
pixel.style.width = "25px";
pixel.style.height = "25px";
const pixel = document.getElementById(`${x}-${y}`);
if (!pixel) continue;
pixel.style.backgroundColor = `rgb(${canvas[x][y].color()[0]}, ${canvas[x][y].color()[1]}, ${canvas[x][y].color()[2]})`;
pixel.style.cursor = "pointer";
pixel.addEventListener("click", () => paint_pixel(pixel));
canvas_element.appendChild(pixel);
}
}
};

const random_int = (max: number) => Math.floor(Math.random() * max);

async function paint_pixel(pixel: HTMLDivElement) {
function paint_pixel(pixel: HTMLDivElement) {
const [x, y] = pixel.id.split("-").map((v) => Number.parseInt(v, 10));
const painting: [number, number, number] = [
random_int(256),
Expand All @@ -62,21 +48,41 @@ async function paint_pixel(pixel: HTMLDivElement) {
canvasCRO.paint(node.networkNode.peerId, [x, y], painting);
const [r, g, b] = canvasCRO.pixel(x, y).color();
pixel.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
}

node.updateObject(topologyObject.id, [
{
fn: "paint",
args: [
node.networkNode.peerId,
`${x},${y}`,
`${painting[0]},${painting[1]},${painting[2]}`,
],
},
]);
async function createConnectHandlers() {
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
if (topologyObject)
objectPeers = node.networkNode.getGroupPeers(topologyObject.id);
render();
});

node.objectStore.subscribe(topologyObject.id, (_, _obj) => {
render();
});
}

async function init() {
await node.start();
render();

const canvas_element = <HTMLDivElement>document.getElementById("canvas");
canvas_element.innerHTML = "";
canvas_element.style.display = "inline-grid";

canvas_element.style.gridTemplateColumns = Array(5).fill("1fr").join(" ");
for (let x = 0; x < 5; x++) {
for (let y = 0; y < 10; y++) {
const pixel = document.createElement("div");
pixel.id = `${x}-${y}`;
pixel.style.width = "25px";
pixel.style.height = "25px";
pixel.style.backgroundColor = "rgb(0, 0, 0)";
pixel.style.cursor = "pointer";
pixel.addEventListener("click", () => paint_pixel(pixel));
canvas_element.appendChild(pixel);
}
}

node.addCustomGroupMessageHandler("", (e) => {
peers = node.networkNode.getAllPeers();
Expand All @@ -86,23 +92,10 @@ async function init() {

const create_button = <HTMLButtonElement>document.getElementById("create");
create_button.addEventListener("click", async () => {
canvasCRO = new Canvas(5, 10);
topologyObject = await node.createObject();

// message handler for the CRO
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
// on create/connect
if (topologyObject)
objectPeers = node.networkNode.getGroupPeers(topologyObject.id);
render();
});
topologyObject = await node.createObject(new Canvas(5, 10));
canvasCRO = topologyObject.cro as Canvas;

node.objectStore.subscribe(topologyObject.id, (_, obj) => {
handleObjectOps(canvasCRO, obj.operations);
});

(<HTMLSpanElement>document.getElementById("canvasId")).innerText =
topologyObject.id;
createConnectHandlers();
render();
});

Expand All @@ -111,24 +104,15 @@ async function init() {
const croId = (<HTMLInputElement>document.getElementById("canvasIdInput"))
.value;
try {
canvasCRO = new Canvas(5, 10);
topologyObject = await node.createObject();

// message handler for the CRO
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
// on create/connect
if (topologyObject)
objectPeers = node.networkNode.getGroupPeers(topologyObject.id);
(<HTMLSpanElement>document.getElementById("canvasId")).innerText =
topologyObject.id;
render();
});

node.objectStore.subscribe(topologyObject.id, (_, obj) => {
handleObjectOps(canvasCRO, obj.operations);
render();
});

topologyObject = await node.createObject(
new Canvas(5, 10),
croId,
undefined,
true,
);
canvasCRO = topologyObject.cro as Canvas;

createConnectHandlers();
render();
} catch (e) {
console.error("Error while connecting with CRO", croId, e);
Expand Down
11 changes: 0 additions & 11 deletions examples/canvas/src/objects/abi/canvas.json

This file was deleted.

10 changes: 0 additions & 10 deletions examples/canvas/src/objects/abi/pixel.json

This file was deleted.

57 changes: 53 additions & 4 deletions examples/canvas/src/objects/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import {
ActionType,
type CRO,
type Operation,
} from "@topology-foundation/object";
import { Pixel } from "./pixel";

export class Canvas {
export class Canvas implements CRO {
operations: string[] = ["splash", "paint"];

width: number;
height: number;
canvas: Pixel[][];
Expand All @@ -14,7 +21,24 @@ export class Canvas {
}

splash(
node_id: string,
nodeId: string,
offset: [number, number],
size: [number, number],
rgb: [number, number, number],
): void {
this._splash(nodeId, offset, size, rgb);
}

paint(
nodeId: string,
offset: [number, number],
rgb: [number, number, number],
): void {
this._paint(nodeId, offset, rgb);
}

private _splash(
nodeId: string,
offset: [number, number],
size: [number, number],
rgb: [number, number, number],
Expand All @@ -24,12 +48,12 @@ export class Canvas {

for (let x = offset[0]; x < this.width || x < offset[0] + size[0]; x++) {
for (let y = offset[1]; y < this.height || y < offset[1] + size[1]; y++) {
this.canvas[x][y].paint(node_id, rgb);
this.canvas[x][y].paint(nodeId, rgb);
}
}
}

paint(
private _paint(
nodeId: string,
offset: [number, number],
rgb: [number, number, number],
Expand All @@ -49,4 +73,29 @@ export class Canvas {
row.forEach((pixel, y) => pixel.merge(peerCanvas.pixel(x, y))),
);
}

resolveConflicts(_): ActionType {
return ActionType.Nop;
}

mergeCallback(operations: Operation[]): void {
this.canvas = Array.from(new Array(this.width), () =>
Array.from(new Array(this.height), () => new Pixel()),
);
for (const op of operations) {
if (!op.value) continue;
switch (op.type) {
case "splash": {
const [nodeId, offset, size, rgb] = op.value;
this._splash(nodeId, offset, size, rgb);
break;
}
case "paint": {
const [nodeId, offset, rgb] = op.value;
this._paint(nodeId, offset, rgb);
break;
}
}
}
}
}
1 change: 0 additions & 1 deletion examples/chat/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ <h1>Topology Protocol - Chat</h1>

<input id="roomInput" type="text" placeholder="Room ID" />
<button id="joinRoom">Connect</button>
<button id="fetchMessages">Fetch Messages</button>
<button id="createRoom">Create Room</button>
</div>

Expand Down
14 changes: 0 additions & 14 deletions examples/chat/src/handlers.ts

This file was deleted.

Loading

0 comments on commit 9e2c0ab

Please sign in to comment.