Skip to content

Commit 33bd915

Browse files
committed
build(wasm): add make wasm target and browser demo harness
Add a 'wasm' Makefile target (GOARCH=wasm GOOS=js, nethttpomithttp2) that outputs wasm-demo/bee.wasm, plus the wasm-demo/ service-worker harness (sw.js, wasm_exec.js, index.html, main.js). Build artifacts (bee.wasm, sw_bundle.js) are gitignored. No cmd split needed: cmd/bee compiles as-is.
1 parent dc518ce commit 33bd915

11 files changed

Lines changed: 973 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ _testmain.go
3232
.DS_Store
3333

3434
AGENTS.md
35-
CLAUDE.md
35+
CLAUDE.md
36+
wasm-demo/bee.wasm
37+
wasm-demo/sw_bundle.js

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ binary: dist FORCE
3535
$(GO) version
3636
$(GO) build -trimpath -ldflags "$(LDFLAGS)" -o dist/bee ./cmd/bee
3737

38+
.PHONY: wasm
39+
wasm: export CGO_ENABLED=0
40+
wasm: dist FORCE
41+
$(GO) version
42+
GOARCH=wasm GOOS=js $(GO) build -trimpath -tags="nethttpomithttp2" -gcflags="all=-l" -ldflags "$(LDFLAGS) -buildid=" -o wasm-demo/bee.wasm ./cmd/bee
43+
3844
dist:
3945
mkdir $@
4046

wasm-demo/.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# dependencies (bun install)
2+
node_modules
3+
4+
# output
5+
out
6+
dist
7+
*.tgz
8+
9+
# code coverage
10+
coverage
11+
*.lcov
12+
13+
# logs
14+
logs
15+
_.log
16+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
17+
18+
# dotenv environment variable files
19+
.env
20+
.env.development.local
21+
.env.test.local
22+
.env.production.local
23+
.env.local
24+
25+
# caches
26+
.eslintcache
27+
.cache
28+
*.tsbuildinfo
29+
30+
# IntelliJ based IDEs
31+
.idea
32+
33+
# Finder (MacOS) folder config
34+
.DS_Store
35+
36+
sw_bundle.js
37+
bee.wasm

wasm-demo/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# wasm-demo
2+
3+
To install dependencies:
4+
5+
```bash
6+
bun install
7+
```
8+
9+
To run:
10+
11+
```bash
12+
bun run
13+
```
14+
15+
This project was created using `bun init` in bun v1.3.3. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.

wasm-demo/bun.lock

Lines changed: 116 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wasm-demo/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Browser Bee Demo</title>
7+
<link rel="stylesheet" href="style.css" />
8+
</head>
9+
<body>
10+
<script src="./main.js"></script>
11+
</body>
12+
</html>

wasm-demo/main.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
if ("serviceWorker" in navigator) {
2+
navigator.serviceWorker
3+
.register("/sw_bundle.js", { scope: "/" })
4+
.then((registration) => {
5+
console.log("Service Worker registered successfully:", registration);
6+
})
7+
.catch((error) => {
8+
console.error("Service Worker registration failed:", error);
9+
});
10+
} else {
11+
console.log("Service Worker is not supported in this browser.");
12+
}

wasm-demo/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "wasm-demo",
3+
"private": true,
4+
"devDependencies": {
5+
"@types/bun": "latest",
6+
"esbuild": "^0.27.1"
7+
},
8+
"peerDependencies": {
9+
"typescript": "^5"
10+
},
11+
"dependencies": {
12+
"@zenfs/core": "^2.4.4"
13+
},
14+
"scripts": {
15+
"build": "bunx esbuild sw.js --bundle --platform=browser > sw_bundle.js"
16+
}
17+
}

wasm-demo/sw.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import "./wasm_exec.js";
2+
3+
import { configure, fs, InMemory } from "@zenfs/core";
4+
5+
const WASM_PATH = "bee.wasm";
6+
7+
self.addEventListener("activate", (event) => {
8+
event.waitUntil(
9+
clients.claim().catch((error) => {
10+
console.error("Error during service worker activate:", error);
11+
}),
12+
);
13+
});
14+
15+
// Handle fetch events to serve the WASM module if needed
16+
const path = new URL(self.registration.scope).pathname;
17+
const handlerPromise = new Promise((setHandler) => {
18+
self.wasmhttp = { path, setHandler };
19+
});
20+
21+
self.addEventListener("fetch", (e) => {
22+
const { pathname } = new URL(e.request.url);
23+
if (!pathname.startsWith(path)) return;
24+
25+
e.respondWith(handlerPromise.then((handler) => handler(e.request)));
26+
});
27+
28+
async function main() {
29+
// Set up ZenFS in-memory filesystem
30+
await configure({
31+
mounts: {
32+
"/tmp": InMemory,
33+
"/home/user": InMemory,
34+
},
35+
});
36+
37+
// Create necessary directories
38+
await fs.promises.mkdir("/home/user/.bee/keys", {
39+
recursive: true,
40+
mode: 0o700,
41+
});
42+
43+
// Write key files
44+
await fs.promises.writeFile(
45+
"/home/user/.bee/keys/libp2p_v2.key",
46+
JSON.stringify({
47+
address:
48+
"049886e5793c6261f59e7b047a91c27226cdbc2ba5af60c9e26705c15441ec9e3f7daa7085a2a7665c338171eb2bf1b65a173636137405d825d0385bc4defacaf4",
49+
crypto: {
50+
cipher: "aes-128-ctr",
51+
ciphertext:
52+
"e35f6f83893bc6186119b85244b43d42b08f92891b6cb7c81f695c0a94ea2536c84fb84e3410618ddee7c814acdf35f1facc79597540e6fa3d460278ffa414311880676ef5fad8b06362b422c139ffb5cdbad530d371e645dc8e496b7b04f93c2ae23554cfc1452a414bf0c1324d326d45980d190ff784ebd9",
53+
cipherparams: { iv: "f917c56ec7e2aa36fd592c63894aa18a" },
54+
kdf: "scrypt",
55+
kdfparams: {
56+
n: 32768,
57+
r: 8,
58+
p: 1,
59+
dklen: 32,
60+
salt: "dcbc48279045788f9b12ffa7989880290b190e50506e2d9596b4d476528cedd0",
61+
},
62+
mac: "1482a352544e9cc13c1954acf9c313c9e25901c530262c7e198d4f221b76027a",
63+
},
64+
version: 3,
65+
id: "5117e84d-0a2b-4c4c-808d-1e9676903c8a",
66+
}),
67+
{ mode: 0o600 },
68+
);
69+
70+
await fs.promises.writeFile(
71+
"/home/user/.bee/keys/swarm.key",
72+
JSON.stringify({
73+
address: "ed48f21d97fd09d08584f42c97f737bc549c49bf",
74+
crypto: {
75+
cipher: "aes-128-ctr",
76+
ciphertext:
77+
"85221a9ec6ff8328f80686ddaa6afe9c1da4b74e8494515cc34e1ff2b9567285",
78+
cipherparams: { iv: "e01d72acdfb68338adcf99ae44f7aeb0" },
79+
kdf: "scrypt",
80+
kdfparams: {
81+
n: 32768,
82+
r: 8,
83+
p: 1,
84+
dklen: 32,
85+
salt: "7ac4dd27cfe9b796793270a6b4c84e9f717533161105a6425576da20aff0f554",
86+
},
87+
mac: "ccaa689b4f09bab5580b515dfcb1a6fcbc7ced6d769a5b8232b1508eaa9c6dc3",
88+
},
89+
version: 3,
90+
id: "2f567b5f-122d-4625-a9f5-25c3285550e1",
91+
}),
92+
{ mode: 0o600 },
93+
);
94+
95+
// Expose ZenFS for debugging purposes
96+
self.ZenFS = fs;
97+
98+
// Initialize Go runtime and set environment variables
99+
const go = new Go();
100+
101+
go.env = {
102+
HOME: "/home/user",
103+
PATH: "/usr/bin:/usr/local/bin",
104+
};
105+
106+
go.argv = [
107+
"bee.wasm",
108+
"start",
109+
"--password",
110+
"testing",
111+
"--bootnode",
112+
"/ip4/49.12.172.37/tcp/32510/tls/sni/49-12-172-37.k2k4r8mh36hk5mcrg2syh2amdbl4dmd08fjhtqrtvyn0gef71auumrvf.libp2p.direct/ws/p2p/QmWbXocGMpfa8zApx9kCNwfmc35bbRJv136bdtuQjbR4wL",
113+
"--data-dir",
114+
"/home/user/.bee/sepolia",
115+
"--verbosity",
116+
"debug",
117+
// '--blockchain-rpc-endpoint',
118+
// 'https://ethereum-sepolia-rpc.publicnode.com/ac5b7f52aabd778861c2588f872f15c5fc34f0b343ec3d18ac2e91f5526e9c2b',
119+
"--mainnet=false",
120+
"--network-id=5",
121+
"--p2p-ws-enable",
122+
];
123+
124+
// Override Go's `fs.readFile` with ZenFS readFile functionality
125+
const goImportObject = {
126+
...go.importObject,
127+
fs: {
128+
...fs,
129+
readFile: async (path) => {
130+
try {
131+
const data = await fs.promises.readFile(path, "utf8");
132+
return new TextEncoder().encode(data); // Return Uint8Array
133+
} catch (error) {
134+
console.error("Error reading file:", path, error);
135+
throw error;
136+
}
137+
},
138+
},
139+
};
140+
141+
// Load and run the WASM binary
142+
await WebAssembly.instantiateStreaming(fetch(WASM_PATH), goImportObject).then(
143+
(result) => {
144+
go.run(result.instance);
145+
},
146+
);
147+
}
148+
149+
main().catch((error) => {
150+
console.error("Error running worker:", error);
151+
});

0 commit comments

Comments
 (0)