Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: codebase check #261

Merged
merged 22 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ jobs:
run: |
pnpm install --no-frozen-lockfile

build-example-canvas:
generate-matrix:
runs-on: ubuntu-latest
outputs:
examples: ${{ steps.list-examples.outputs.examples }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- shell: bash
- name: List examples
id: list-examples
run: |
pnpm install --no-frozen-lockfile
cd examples/canvas
pnpm build
echo "examples=$(ls -d examples/*/ | xargs -n 1 basename | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT

build-example-chat:
build-examples:
needs: generate-matrix
runs-on: ubuntu-latest
strategy:
matrix:
example: ${{ fromJSON(needs.generate-matrix.outputs.examples) }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand All @@ -39,5 +41,5 @@ jobs:
- shell: bash
run: |
pnpm install --no-frozen-lockfile
cd examples/chat
cd examples/${{ matrix.example }}
pnpm build
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 Topology Foundation
Copyright (c) 2024 Topology

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div align="center">
<img src="https://avatars.githubusercontent.com/u/157637200" height="128">
<br />
<h1>The TypeScript implementation of the Topology Protocol</h1>
<h1>The TypeScript implementation of Distributed Replicated Programs (DRP)</h1>
d-roak marked this conversation as resolved.
Show resolved Hide resolved
</div>

<div align="center">
Expand All @@ -17,34 +17,36 @@
[![X](https://img.shields.io/badge/X-000000)](https://x.com/topology_gg)
[![Telegram](https://img.shields.io/badge/Telegram-24A1DE)](https://t.me/topologyfrens)
[![Discord](https://img.shields.io/badge/Discord-7289da)](https://discord.gg/GUDGzBP5mn)

</div>

# Overview

This is the official TypeScript implementation of the Topology Protocol. The Topology Protocol is a local-first decentralized protocol for real-time applications. It introduces a new concept for Conflict-free Replicated Objects (CRO), that are built on top of libp2p and composed of CRDTs.
This is the official TypeScript implementation of Distributed Replicated Programs (DRP). DRP is a local-first decentralized protocol for real-time applications. It is built on top of libp2p and with a similar design with CRDTs.

# Specifications

The specifications of the Topology Protocol are shared across different client implementations and can be found in the [specs repository](https://github.com/topology-foundation/specs). Currently the specifications are starting to be written based on this implementation.
The specifications of DRP are shared across different client implementations and can be found in the [specs repository](https://github.com/topology-foundation/specs). Currently the specifications are starting to be written based on this implementation.

# Packages

This repository is a monorepo that contains the following packages:

| Package | Description |
|---------|--------------------------------------------------|
| crdt | CRDT implementations intended to use as builtins |
| network | Network middleware to abstract libp2p |
| node | Topology Node library and CLI |
| object | CRO objects structure implementation |
| Package | Description |
| ---------- | ----------------------------------------------- |
| blueprints | Blueprints of some DRPs that can be freely used |
| logger | Logger for the whole project |
| network | Network middleware to abstract libp2p |
| node | Node for interacting with DRPs library and CLI |
| object | DRP objects structure implementation |

# 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.
All the examples are located in the `examples` directory.

# Usage

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

```bash
# pnpm
Expand Down
3 changes: 1 addition & 2 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"**/doc/*",
"**/*_pb.js",
"**/*_pb.ts",
"**/bundle/*",
"**/package.json"
"**/bundle/*"
]
},
"linter": {
Expand Down
6 changes: 0 additions & 6 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,3 @@ plugins:
out: .
opt:
- ts_proto_opt=esModuleInterop=true
inputs:
- directory: ./packages
exclude_paths:
- packages/node
- packages/network/node_modules
- packages/object/node_modules
6 changes: 3 additions & 3 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
version: v2
modules:
- path: packages/node/src/proto
name: buf.build/topology/node
name: buf.build/drp/node

- path: packages/object/src/proto
name: buf.build/topology/object
name: buf.build/drp/object

- path: packages/network/src/proto
name: buf.build/topology/network
name: buf.build/drp/network
2 changes: 1 addition & 1 deletion examples/canvas/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Topology - Canvas</title>
<title>DRP - Canvas</title>
</head>

<body>
Expand Down
45 changes: 18 additions & 27 deletions examples/canvas/package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
{
"name": "ts-topology-examples-canvas",
"version": "0.3.1",
"license": "MIT",
"scripts": {
"build": "vite build",
"clean": "rm -rf dist/ node_modules/",
"dev": "vite serve",
"start": "ts-node ./src/index.ts"
},
"dependencies": {
"@topology-foundation/blueprints": "0.3.1",
"@topology-foundation/network": "0.3.1",
"@topology-foundation/node": "0.3.1",
"@topology-foundation/object": "0.3.1",
"crypto-browserify": "^3.12.0",
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"ts-node": "^10.9.2",
"vm-browserify": "^1.1.2"
},
"devDependencies": {
"@types/node": "^22.5.4",
"ts-loader": "^9.3.1",
"typescript": "^5.5.4",
"vite": "^6.0.0",
"vite-plugin-node-polyfills": "^0.22.0"
}
"name": "ts-drp-examples-canvas",
"version": "0.3.1",
"license": "MIT",
"scripts": {
"build": "vite build",
"clean": "rm -rf dist/ node_modules/",
"dev": "vite serve"
},
"dependencies": {
"@ts-drp/node": "0.3.1",
"@ts-drp/object": "0.3.1"
},
"devDependencies": {
"@types/node": "^22.5.4",
"typescript": "^5.5.4",
"vite": "^5.4.9",
"vite-plugin-node-polyfills": "^0.22.0"
}
}
41 changes: 20 additions & 21 deletions examples/canvas/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { TopologyNode } from "@topology-foundation/node";
import type { TopologyObject } from "@topology-foundation/object";
import { DRPNode } from "@ts-drp/node";
import type { DRPObject } from "@ts-drp/object";
import { Canvas } from "./objects/canvas";

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

if (!canvasCRO) return;
const canvas = canvasCRO.canvas;
if (!canvasDRP) return;
const canvas = canvasDRP.canvas;
for (let x = 0; x < canvas.length; x++) {
for (let y = 0; y < canvas[x].length; y++) {
const pixel = document.getElementById(`${x}-${y}`);
Expand All @@ -45,19 +45,18 @@ function paint_pixel(pixel: HTMLDivElement) {
random_int(256),
random_int(256),
];
canvasCRO.paint([x, y], painting);
const [r, g, b] = canvasCRO.pixel(x, y).color();
canvasDRP.paint([x, y], painting);
const [r, g, b] = canvasDRP.pixel(x, y).color();
pixel.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
}

async function createConnectHandlers() {
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
if (topologyObject)
objectPeers = node.networkNode.getGroupPeers(topologyObject.id);
node.addCustomGroupMessageHandler(drpObject.id, (e) => {
if (drpObject) objectPeers = node.networkNode.getGroupPeers(drpObject.id);
render();
});

node.objectStore.subscribe(topologyObject.id, (_, _obj) => {
node.objectStore.subscribe(drpObject.id, (_, _obj) => {
render();
});
}
Expand Down Expand Up @@ -92,30 +91,30 @@ async function init() {

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

createConnectHandlers();
render();
});

const connect_button = <HTMLButtonElement>document.getElementById("connect");
connect_button.addEventListener("click", async () => {
const croId = (<HTMLInputElement>document.getElementById("canvasIdInput"))
const drpId = (<HTMLInputElement>document.getElementById("canvasIdInput"))
.value;
try {
topologyObject = await node.createObject(
drpObject = await node.createObject(
new Canvas(5, 10),
croId,
drpId,
undefined,
true,
);
canvasCRO = topologyObject.cro as Canvas;
canvasDRP = drpObject.drp as Canvas;

createConnectHandlers();
render();
} catch (e) {
console.error("Error while connecting with CRO", croId, e);
console.error("Error while connecting with DRP", drpId, e);
}
});
}
Expand Down
6 changes: 3 additions & 3 deletions examples/canvas/src/objects/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
ActionType,
type CRO,
type DRP,
type Operation,
type ResolveConflictsType,
SemanticsType,
} from "@topology-foundation/object";
} from "@ts-drp/object";
import { Pixel } from "./pixel";

export class Canvas implements CRO {
export class Canvas implements DRP {
operations: string[] = ["splash", "paint"];
semanticsType: SemanticsType = SemanticsType.pair;

Expand Down
2 changes: 1 addition & 1 deletion examples/canvas/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default defineConfig({
},
resolve: {
alias: {
"@topology-foundation": path.resolve(__dirname, "../../packages"),
"@ts-drp": path.resolve(__dirname, "../../packages"),
},
},
});
22 changes: 6 additions & 16 deletions examples/chat/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
# Topology Protocol Example
# DRP Example

This is an example of Topology Protocol usage in a chat system where a user can create or connect to a chat room, send and read the messages sent in the group chat.
This is an example of a DRP usage in a chat system where a user can create or connect to a chat room, send and read the messages sent in the group chat.

## Specifics

Messages are represented as strings in the format (timestamp, content, senderId). Chat is a class which extends TopologyObject and has Gset\<string> as an attribute to store the list of messages.
Messages are represented as strings in the format (timestamp, content, senderId). Chat is a class which extends DRPObject and stores the list of messages.

## How to run locally

After cloning the repository, run the following commands:

```bash
cd ts-topology/examples/chat
yarn
yarn build
yarn dev
```

Debugging is made easier by setting the mode in `webpack.config.js` to "development":

```js
module.exports = {
mode: "development",
...
}
cd ts-drp/examples/chat
pnpm i
pnpm dev
```
27 changes: 0 additions & 27 deletions examples/chat/asconfig.json

This file was deleted.

4 changes: 2 additions & 2 deletions examples/chat/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Topology - Chat</title>
<title>DRP - Chat</title>
</head>
<body>
<div>
<h1>Topology Protocol - Chat</h1>
<h1>DRP - Chat</h1>
<p>Current peer ID <span id="peerId"></span></p>
<p>Connected to <span id="chatId"></span></p>
<p>peers: <span id="peers"></span></p>
Expand Down
Loading