@lat-murmeldjur/weeb_3 0.0.316001 → 0.0.319002

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,35 +1,41 @@
1
1
  # Weeb-3 - A Swarm client for browsers
2
2
 
3
- This project is a work in progress swarm client implementation relying solely on browser side technologies.
4
- It uses [wasm-pack](https://rustwasm.github.io/docs/wasm-pack/) to build the project for use in the browser.
3
+ This project is a work-in-progress Swarm client implementation that relies solely on browser-side technologies. It uses [wasm-pack](https://rustwasm.github.io/wasm-pack/) to build the Rust client to WebAssembly and runs the Swarm networking, retrieval, upload, persistence, service-worker integration, and UI logic inside the browser.
4
+
5
+ The codebase is still experimental. APIs, persistence formats, supported networks, and browser behavior may change while the implementation is being hardened.
5
6
 
6
7
  ## Building the code
7
8
 
8
- Ensure you have [`wasm-pack`](https://rustwasm.github.io/wasm-pack/), [`protoc`](https://grpc.io/docs/protoc-installation/), and [`clang`](https://clang.llvm.org/) installed.
9
+ Ensure you have [wasm-pack](https://rustwasm.github.io/wasm-pack/), [protoc](https://grpc.io/docs/protoc-installation/), and [clang](https://clang.llvm.org/) installed.
9
10
 
10
11
  1. Build the client library:
11
- ```shell
12
12
 
13
- RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack build --target web --out-dir static --out-name weeb_3
14
- ```
13
+ ```bash
14
+ RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack build --target web --out-dir static --out-name weeb_3
15
+ ```
15
16
 
16
- 2. Start the local server to serve html, js and wasm files:
17
- ```shell
18
- cargo run
19
- ```
20
- Note this server uses an unsecure self-signed certificate to provide https, which is not sufficient to enable Service Workers in chrome etc. This enables displaying single files from swarm, however to display websites a service worker is necessary, which requires a certificate deemed safe by the browser. You can however get your own safe certificate from - for example - github pages by forking the repository and setting the github pages to 'docs', and copying your latest version of the files from the static folder to the docs folder.
17
+ 2. Start the local server to serve the HTML, JavaScript, and Wasm files:
18
+
19
+ ```bash
20
+ cargo run
21
+ ```
21
22
 
22
- 3. Open the URL (https://localhost:8080/weeb-3 or for the github pages hosted version https://lat-murmeldjur.github.io/weeb-3)
23
+ The local server uses an insecure self-signed certificate to provide HTTPS. This is enough for loading the local application in many development flows, but it is not necessarily sufficient for enabling Service Workers in browsers such as Chrome. Single-file Swarm resources can still be displayed without the Service Worker, but rendering full Swarm websites requires a Service Worker and therefore a certificate that the browser treats as trusted.
24
+
25
+ For a trusted deployment, one option is to serve the static build from GitHub Pages or another HTTPS host with a browser-trusted certificate. A simple workflow is to fork the repository, enable GitHub Pages for the `docs` folder, and copy the latest files from `static` to `docs` after building.
26
+
27
+ 3. Open the application URL, for example [`https://localhost:8080/weeb-3`](https://localhost:8080/weeb-3), or the GitHub Pages hosted version at [`https://lat-murmeldjur.github.io/weeb-3`](https://lat-murmeldjur.github.io/weeb-3).
23
28
 
24
29
  ## Using the npm package
25
30
 
26
- The wasm-pack build now prepares the generated `static/package.json` for publishing to npm together with the assets required by the wrapper:
31
+ The `wasm-pack` build prepares the generated `static/package.json` for publishing to npm together with the wrapper assets required by the browser package:
27
32
 
28
33
  - `static/snippets/web3-0742d85b024bb6f5/inline0.js`
29
34
  - `static/weeb_3.js`
30
35
  - `static/weeb_3_bg.wasm`
36
+ - `static/weeb_3.d.ts`
31
37
 
32
- After publishing, the package can be used with the same API shape as `static/example.html`:
38
+ After publishing, the package can be used with the same API shape as the examples in `static/example.html` and `static/issue-1-json-sync-example.html`:
33
39
 
34
40
  ```js
35
41
  import init, { Weeb3No103, BootstrapNode } from "@lat-murmeldjur/weeb_3";
@@ -37,9 +43,31 @@ import init, { Weeb3No103, BootstrapNode } from "@lat-murmeldjur/weeb_3";
37
43
  await init();
38
44
 
39
45
  const weeb3node = new Weeb3No103();
46
+
47
+ // Use the built-in mainnet profile and browser-dialable bootnodes.
48
+ await weeb3node.connect();
49
+ console.log(await weeb3node.networkState());
50
+
51
+ // Switch explicitly between the built-in profiles.
52
+ await weeb3node.switchTestnet();
53
+ await weeb3node.switchMainnet();
54
+
55
+ // The generic form accepts "mainnet", "gnosis", or "1", and
56
+ // "testnet", "sepolia", or "10".
57
+ await weeb3node.switchNetwork("testnet");
58
+ await weeb3node.switchNetwork("mainnet");
59
+
60
+ // Or start with explicit browser-dialable bootnodes.
61
+ weeb3node.start([
62
+ new BootstrapNode("/ip4/example/tcp/443/wss/p2p/examplePeerId", true),
63
+ ], "1");
64
+
65
+ const ready = await weeb3node.ready(1, 20_000);
40
66
  ```
41
67
 
42
- The workflow defaults to publishing under the GitHub repository owner scope. If you need a different npm scope, set the `NPM_SCOPE` repository variable in GitHub Actions before pushing to `main`.
68
+ The wrapper exposes the browser node as `Weeb3No103`. It can start the runtime, connect to network profiles, switch between mainnet and testnet with `switchMainnet()` / `switchTestnet()` or `switchNetwork(mode)`, render the bundled interface into a container, report network and progress state, retrieve BZZ resources, retrieve raw bytes or chunks, upload `File` objects or byte arrays, publish and read feed updates, and expose feed identity helpers.
69
+
70
+ The publishing workflow defaults to the GitHub repository owner scope. If a different npm scope is needed, set the `NPM_SCOPE` repository variable in GitHub Actions before pushing to `main`.
43
71
 
44
72
  ## [Notes]
45
73
 
@@ -48,148 +76,186 @@ The workflow defaults to publishing under the GitHub repository owner scope. If
48
76
  - Chrome (on Windows 11)
49
77
  - Chrome (Android)
50
78
  - Brave (on Windows 11)
51
- - Edge
79
+ - Edge
52
80
  - Firefox (on Windows 11)
53
81
  - Firefox (on Android)
54
82
 
55
- Testing and modifying for other browsers is planned.
83
+ Testing and improving support for other browsers is planned.
56
84
 
57
85
  ### How it works (architectural overview)
58
86
 
59
87
  The weeb-3 client consists of several logical components:
60
- - The web interface (implemented by src/interface.rs & of course static/index.html) that creates with the main weeb process and loads the service worker
61
- - The libp2p/swarm client (with main entry point in src/lib.rs)
62
- - A service worker, that enables hot-loading assets on relative paths for websites loaded from swarm (found in static/service.js)
63
88
 
64
- Below is a piece by piece overview of the current logic of components
89
+ - The browser interface, implemented primarily by `static/index.html`, `src/interface.rs`, `src/interface_conventions.rs`, and `src/interface_runtime_conventions.rs`.
90
+ - The libp2p / Swarm node, whose main entry point is `src/lib.rs`.
91
+ - The Swarm protocol handlers and data pipelines for handshake, peer discovery, pricing, accounting, retrieval, pushsync, pseudosettle, swap, manifests, feeds, streaming, and uploads.
92
+ - The Service Worker in `static/service.js`, which provides deterministic browser routes for Swarm content and forwards canonical requests into the Rust runtime.
93
+ - The npm / library facade in `src/library.rs`, which wraps the same runtime for embedding in other browser applications.
94
+ - Browser persistence, secure local state, network profiles, and on-chain integration implemented by `src/persistence.rs`, `src/secure_vault.rs`, `src/network_profile.rs`, and `src/on_chain.rs`.
95
+
96
+ Below is a piece-by-piece overview of the current component logic.
65
97
 
66
98
  #### The interface
67
99
 
68
- As of "commit number 189" the instantiator of all components is the index.html that starts the interface (by calling the function "interweeb" from src/interface.rs).
100
+ The default browser application is instantiated by `static/index.html`, which loads the generated Wasm module and calls `interweeb` from `src/interface.rs`.
69
101
 
70
- The interweeb function has the following roles (in order of appearing in the code):
71
- - Starting the libp2p/swarm client in an async block
72
- - Setting a listener on the settings text input fields, triggering changing bootnode and connection settings to the weeb process on a button based event
73
- - Setting a listener on the navigation text input field, triggering requests to the shared worker on content change of the navigation text input field
74
- - Setting a listener on the create storage input fields, triggering connecting metamask and buying a batch with provided parameters
75
- - Setting a listener on the reuse space button, triggering resetting an already existing batch to clean slate
76
- - Setting a listener on the upload input fields, triggering uploading with the existing batch if there is one
77
- - Listening to logs sent back by the weeb process, as well as resources and responses of triggered requests and displaying them
78
- - Starting connection to bootnode after 600 milliseconds
102
+ `interweeb` creates a `Weeb3` node, clears legacy hash-based paths through `src/nav.rs`, and delegates the rest of the UI setup to `mount_interface`. `mount_interface` can either start the runtime itself or attach the interface to a runtime that has already been started by the package wrapper.
103
+
104
+ The interface layer currently has the following roles:
105
+
106
+ - Starting the libp2p / Swarm runtime in an async browser task when requested.
107
+ - Installing UI conventions and rendering the interface shell.
108
+ - Preloading the secure vault module before sensitive upload, feed, stamp, or cheque operations are requested.
109
+ - Registering the Service Worker and routing Service Worker messages back to the Rust runtime.
110
+ - Reading the configured network profile, network id, and browser-dialable bootnodes, then passing bootnode connection requests to the `Weeb3` node.
111
+ - Wiring the navigation input so BZZ references, raw byte routes, and chunk routes can be opened from the UI.
112
+ - Wiring upload controls for single files, tar-based collections, optional encryption, index document selection, optional feed publishing, and postage-stamp reuse or reset.
113
+ - Wiring on-chain controls for upload prerequisites, postage batch acquisition, chequebook deployment, cheque signer persistence, and chequebook deposits through the browser wallet.
114
+ - Providing runtime controls such as pausing and resuming transfers.
115
+ - Rendering retrieved resources, website iframes, streaming media, raw downloads, logs, connection status, network state, and progress rows.
116
+
117
+ The current interface no longer assumes that requests are handled by a shared worker. The tab owns the `Weeb3` runtime, while the Service Worker acts as a request forwarder between browser fetch events and the active controlled client.
79
118
 
80
119
  #### The weeb process
81
120
 
82
- Originally implemented in a shared web worker, the main weeb process was intended to function as a common resource for multiple tabs of the same origin.
83
- This design would have enabled having one swarm client serving multiple open tabs, however, at the cost of giving up on the possibility of being able to open webrtc connections. However, chrome on android does not support shared workers, so for the time being, the main weeb process was transfered back into the tab.
84
-
85
- The high level architecture of the client resides in src/lib.rs, which (in order of appearing in the code) implements the following functions:
86
-
87
- - Defining and importing the swarm protocols generated by the protoc compiler
88
- - Defining the client (as the class Weeb3), it's in-memory registry of peers and their accounting (as the struct Wings)
89
- - Defining the 6 main functions of the client, namely
90
- 1) Changing the bootnode address and network id
91
- 2) Uploading a file or a tar based collection, optionally to a feed as well
92
- 3) A function that enables using the running client to retreive resources (the function "acquire")
93
- 4) A function to reset a postage stamp to original state
94
- 5) Instantiation (the "new" function), that starts the libp2p client
95
- 6) A function that continues running the client, asynchronously maintains/establishes connections, serves requests from the interface, and engages in protocols with the swarm (the "run" function)
96
- 7) Helper functions for the interface to get new log lines, connection numbers, and to submit new logs meant to be shown on the interface
97
-
98
- In slightly more detail, the new function does the following (in order of appearing in the code):
99
- - Randomises a new secret keypair
100
- - Starts a libp2p client with the stream libp2p behaviour enabled using webrtc transport
101
- - Creates a registry of peers (connected_peers, overlay_peers) and peer accounting (accounting_peers, ongoing_refreshments)
102
- - Creates a message port (to be listened to by the client and to be used by the acquire function)
103
- This message port can receive the writing end of a channel of bytes along with an address, so that it can write back the results of looking up the address to the channel received.
104
-
105
- The run function of the client implements an asynchronous architecture that does the following functions (in order of appearance in the code):
106
- - Creating channels for swarm specific functions
107
- 1) Receiving new peers to connect from the gossip protocol (peers_instructions_chan, connections_instructions_chan)
108
- 2) Accounting related functions (accounting_peer_chan, pricing_chan, refreshment_instructions_chan, refreshment_chan)
109
- 3) Receiving new bootnode address to connect to
110
- - Setting up listening to gossip protocol messages (information about existing peers) and pricing protocol messages (for receiving connected peers payment threshold updates)
111
- - An async routine to continously establish new libp2p-connections (dial) and consume libp2p-swarm events (swarm_event_handle) as well as dialing to bootnode
112
- - An async routine that wraps a number of further async routines for the following functions (event_handle):
113
- 1) Accounting connecting newly established peer connections (k1)
114
- 2) Setting payment thresholds for peers after successfully receiving payment threshold updates in the pricing protocol (k2)
115
- 3) Initiating refreshments/pseudosettle protocol for peers when triggered by accounting actions (k3)
116
- 4) Registering the results of successful refreshments towards peers (k4)
117
- - Two async routines that listens to high level download / upload requests
118
- - Two async routines that listens to data object level download / upload requests enabling joining and splitting of chunks
119
- - Two async routines that enable concurrent chunk level pushsync and retrieval requests
120
- - An async routine that attempts to conduct handshakes with dialed connections
121
-
122
- Currently - due to the blocking - non-blocking nature of the async framework, and to avoid a waiting thread hogging the single execution thread, the aforementioned routines intermittently try progressing every 600ms with non cpu intensive async sleeps happening in-between.
121
+ The main Swarm client is implemented in `src/lib.rs`. It is compiled only for the `wasm32` target and is designed to run in the browser event loop.
122
+
123
+ At a high level, `src/lib.rs` does the following:
124
+
125
+ - Imports the generated protobuf protocol modules from `etiquette_0` through `etiquette_8`.
126
+ - Defines the Swarm protocol names used by the client, including handshake, pricing, hive peer discovery, pseudosettle, retrieval, pushsync, and swap.
127
+ - Defines network mode helpers for testnet and mainnet. The built-in profiles currently map Swarm network id `10` to the Sepolia-based testnet profile and Swarm network id `1` to the Gnosis / xDAI mainnet profile.
128
+ - Defines the `Weeb3` client, which owns the libp2p `Swarm`, runtime channels, connection state, network id, progress store, transfer pause flag, and peer registry.
129
+ - Defines `Wings`, the in-memory peer and accounting registry used to track connected peers, overlay addresses, bootnodes, accounting peers, settlement state, known underlays, and self-observed ephemeral addresses.
130
+ - Exposes the runtime functions used by the interface and library wrapper.
131
+
132
+ The most important public `Weeb3` operations are:
133
+
134
+ 1. Changing the network id and bootnode address.
135
+ 2. Disconnecting and clearing peer state when the active network profile changes.
136
+ 3. Uploading a `File` or tar collection, optionally encrypted, optionally with an index document, and optionally as a feed update.
137
+ 4. Pushing a raw chunk through pushsync.
138
+ 5. Resolving and acquiring BZZ resources.
139
+ 6. Retrieving raw bytes or individual chunks.
140
+ 7. Reading feed envelopes and feed content.
141
+ 8. Resetting the active postage stamp state.
142
+ 9. Reporting logs, connection counts, active network id, and progress snapshots.
143
+ 10. Pausing or resuming transfers.
144
+ 11. Running the asynchronous protocol loop.
145
+
146
+ The `new` function constructs the browser node. In the current implementation it:
147
+
148
+ - Generates a fresh libp2p identity key for the browser runtime.
149
+ - Builds a libp2p `Swarm` with the browser WebSocket / WebSys transport.
150
+ - Uses authenticated Noise and Yamux multiplexing for libp2p connections.
151
+ - Enables the stream behavior used by the Swarm protocol handlers.
152
+ - Creates the peer registry, connection registry, progress store, transfer control flag, and runtime channels.
153
+ - Initializes the default Swarm network id to `10`.
154
+
155
+ The `run` function is the long-running runtime loop. It builds a channel-based asynchronous task graph for the browser runtime and coordinates the major subsystems:
156
+
157
+ - Peer discovery, bootnode dialing, connection retry, and connection cleanup.
158
+ - Incoming and outgoing libp2p stream handling.
159
+ - Handshake, identify, pricing, and peer promotion.
160
+ - Accounting, pseudosettle refreshes, cheque sending, and swap-related settlement messages.
161
+ - High-level BZZ resolution, range preparation, and BZZ range retrieval.
162
+ - Data-level retrieval and upload requests.
163
+ - Chunk-level retrieval and pushsync with bounded concurrency.
164
+ - Upload progress reporting.
165
+ - Transfer pause and cancellation checks.
166
+ - Log forwarding to the interface.
167
+
168
+ The runtime is heavily asynchronous, but it is still running inside the browser's Wasm execution environment. It uses `spawn_local`, async channels, short queue polling, and protocol-specific retry delays rather than OS threads.
123
169
 
124
170
  #### The Swarm Client Subcomponents
125
171
 
126
- The aforementioned architecture further depends on the following code modules:
127
- - The protocol handlers for handshake, hive, pricing, pseudosettle and retrieval (src/handlers.rs)
128
- - The accounting functions, such as calculating chunk prices, reserving, crediting, refreshing (src/accounting.rs)
129
- - The retrieval logic such as selecting peers to retrieve chunks from, decrypting chunks, joining files and triggering manifest interpretations (src/retrieval.rs)
130
- - The pushsync logic such as selecting peers to push chunks to, encrypting chunks, splitting files, triggering manifest and soc creation (src/upload.rs)
131
- - The manifest creation logic (src/manifest_upload.rs)
132
- - The manifest interpretation logic (src/manifest.rs)
133
- - The ENS contenthash resolution logic (src/ens.rs)
134
- - The indexeddb in-browser storage solution (src/persistence.rs)
135
- - Common methods and struct declarations including DOM manipulation, calculating proximity orders, validating content addressed and single owner chunks, calculating feed addresses, and encoding/decoding resource groups to communicate through byte channels e.g. towards the interface (src/conventions.rs)
172
+ The main runtime depends on several focused modules:
173
+
174
+ - `src/handlers.rs` implements the libp2p stream handlers for Swarm protocol traffic such as handshake, hive, pricing, pseudosettle, retrieval, pushsync, and swap.
175
+ - `src/accounting.rs` implements local accounting, price calculations, reservations, peer credit / debit tracking, refresh triggers, and settlement coordination.
176
+ - `src/addresses.rs` normalizes and validates browser-dialable underlays, including WebSocket and secure WebSocket multiaddresses.
177
+ - `src/retrieval.rs` implements chunk retrieval, peer selection, validation, decryption, data joining, and request coordination.
178
+ - `src/upload.rs` implements file splitting, optional encryption, chunk creation, postage stamp use, pushsync, manifest creation, SOC creation, and feed upload support.
179
+ - `src/manifest.rs` interprets Swarm manifests.
180
+ - `src/manifest_upload.rs` creates manifests for uploads and collections.
181
+ - `src/bzz_stream.rs` parses canonical BZZ resources, resolves manifests and paths, prepares range trees, and retrieves byte ranges for BZZ resources.
182
+ - `src/streaming_player.rs` integrates range retrieval with browser fetch requests and streaming media playback.
183
+ - `src/nav.rs` normalizes browser paths and extracts BZZ route references from the location bar.
184
+ - `src/ens.rs` resolves ENS content hashes to Swarm references.
185
+ - `src/events.rs` stores progress rows and progress revisions for the UI and package wrapper.
186
+ - `src/persistence.rs` stores browser-side data in IndexedDB.
187
+ - `src/secure_vault.rs` manages sensitive local state such as upload identities, postage-stamp state, feed ownership, and cheque signer material.
188
+ - `src/network_profile.rs` defines the built-in testnet and mainnet profiles, wallet chain ids, token symbols, and bootnodes.
189
+ - `src/on_chain.rs` implements browser wallet and contract interactions for postage batches, price oracle access, chequebook operations, swap token operations, and related state.
190
+ - Batch state held by `weeb-3-secure` is requested with the active Swarm network id, so testnet and mainnet use separate batch owners, batch ids, bucket counters, and temp-auth authorization.
191
+ - `src/interface_conventions.rs` and `src/interface_runtime_conventions.rs` contain DOM helpers, UI rendering, route parsing, network controls, and Service Worker runtime integration.
192
+ - `src/library.rs` exposes the Wasm runtime to JavaScript as `Weeb3No103` and `BootstrapNode`.
193
+ - `src/conventions.rs` and `src/interface_conventions.rs` collect common encoding, decoding, hashing, resource, UI, and protocol helper logic.
194
+
195
+ The ABI files in `src/*.json` are consumed by the on-chain module and cover contracts such as the postage stamp contract, price oracle, factory, sBZZ token, and simple swap contract.
136
196
 
137
197
  #### Persistence and identity
138
198
 
139
- The weeb process persists 3 types of data:
140
- - Caching chunks retrieved previously
141
- - Identity related keys and identifiers used for uploads and creating feeds
142
- 1) Batch ID
143
- 2) Private key of Batch Owner
144
- 3) Batch Bucket Limit
145
- 4) Private key of Feed Owner
146
- - Saturation of individual Batch Buckets
199
+ The browser runtime maintains a mix of ephemeral and persistent state.
147
200
 
148
- The indexeddb access is denied to loaded websites by opening websites from swarm in iframes marked with the sandbox attribute.
149
- The private keys are not used for blockchain purposes, the wallet responsible for buying a batch can only be connected through metamask currently.
150
- The libp2p node keys are chosen randomly each time the tab is reloaded, resulting in a unique overlay every time
201
+ The libp2p identity used by a `Weeb3` runtime is generated when the node is created. That makes the live peer identity tab-local and runtime-local. Peer maps, connection attempts, active streams, and accounting state are kept in memory by the `Weeb3` and `Wings` structures.
151
202
 
152
- ### The Service Worker
203
+ Browser persistence is used for state that should survive page reloads or browser sessions, such as retrieved chunks, chequebook data, signer material, postage-stamp state, and other runtime settings. Sensitive state is routed through the secure vault module instead of being handled directly by ordinary UI code.
153
204
 
154
- Quoting from the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API), "Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available). They are intended, among other things, to enable the creation of effective offline experiences, intercept network requests, and take appropriate action based on whether the network is available, and update assets residing on the server. They will also allow access to push notifications and background sync APIs.".
205
+ Wallet access is requested only for on-chain operations. The browser wallet is used for chain switching, account access, postage purchase flows, chequebook deployment, and deposits. Upload/feed identities and cheque signer keys are managed separately from the wallet account so that Swarm protocol operations do not require signing every action with the injected wallet.
155
206
 
156
- The weeb-3 interface functions can display single files, for example pictures, documents, and other single files without relying on the service worker through dynamically creating blobs with associated mime types from the data retrieved from swarm, and making them available on [virtual urls](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static). These resources are displayed in embed tags prepended to the content of the resultField html tag.
207
+ When the network profile changes, the runtime clears the current peer state and increments its connection generation so stale dialing, handshake, and connection events do not leak into the new network session.
157
208
 
158
- However, this createObjectUrl method inserts random strings into the virtual urls assigned to individual resources, which makes it unfeasible to be used to render complete websites, as relative paths of assets embedded in the site would be broken by such random strings. This necessitates the use of a service worker, which can intercept the http requests aimed towards the de facto server (for example github pages) and is able to create objects with deterministic url paths to be served in response to these requests, making serving relative assets possible.
209
+ ### The Service Worker
159
210
 
160
- To enable this, upon detecting a website manifest, the interface sends each retrieved resource complete with relative path and mime type to the service worker (the message event listener in static/service.js), which injects it into a named cache ('default0'), before prepending the website index document as an iframe to the resultField html tag of the weeb-3 browser tab.
211
+ The Service Worker in `static/service.js` sits between the browser fetch layer and the active weeb-3 page. Its role has expanded beyond the original static cache approach.
161
212
 
162
- This service worker is only enabled by the browser if the browser detects that the site is served through a secure https connection based on a trusted certificate, as this functionality is clearly a security sensitive asset that can be used to intercept http requests and inject arbitrary resources. The use of this functionality also creates new surfaces of attack such as creating malicious websites that could load a malevolent service worker at runtime, to enable further malicious injections. Disableing such attacks is part of the security development topic of the planned developments section.
213
+ Single files can still be displayed without a Service Worker by creating `Blob` object URLs with the correct MIME type. This is enough for images, documents, and other standalone files. It is not enough for full websites, because browser-generated object URLs contain random identifiers and therefore cannot reliably satisfy relative paths for scripts, stylesheets, images, and other website assets.
163
214
 
164
- ### Main dependencies
215
+ The Service Worker solves this by providing deterministic application-scoped routes:
165
216
 
166
- The weeb-3 project uses the following main rust crates:
167
- - libp2p
168
- - alloy
169
- - ethers
170
- - web3-rs
171
- - async-std
172
- - wasm-bindgen
173
- - js-sys
174
- - web-sys
175
- - indexed_db_futures
217
+ - `GET` and `HEAD` requests below `/bzz/<reference>/<path>` are interpreted as canonical mainnet BZZ resource requests.
218
+ - Testnet can be selected from routes with `/testnet`, for example `/weeb-3/testnet` to boot the interface in testnet mode or `/weeb-3/testnet/bzz/<reference>/<path>` for a testnet BZZ link.
219
+ - Raw byte and chunk routes below `/bytes/`, `/chunks/`, and `/chunk/` are forwarded to the Rust runtime.
220
+ - `POST` requests to the scoped `/bzz` endpoint are forwarded as upload requests, including upload headers such as encryption, collection, and index-document hints.
221
+ - Fetch requests are forwarded to the active controlled client through `postMessage` and `MessageChannel`.
222
+ - BZZ resources can be answered as full responses, byte-range responses, or streaming responses depending on MIME type, request headers, and resource size.
223
+ - The app shell is cached with a network-first strategy so that the interface can continue to load when a cached shell is available.
176
224
 
177
- ### Concurrency and memory limitations
225
+ This design means that rendered Swarm websites can request their own relative assets through ordinary browser fetch/navigation behavior, while the active Rust runtime resolves and retrieves the underlying Swarm data.
178
226
 
179
- The architecture of the weeb process enables a high level of concurrency between different tasks, sending a high number of different types of protocol messages parallelly. The webassembly architecture currently does not support threads or utilizing multiple CPUs, and the 32bit memory addressing scheme limits the usable memory to 4 GBs. Offloading the work to multiple non-specialized web-workers would increase this limit in both dimensions as each web worker has a separate memory address space and a separate physical thread.
227
+ The Service Worker is security-sensitive. Browsers only enable it for secure origins, and a trusted certificate is required for normal deployment. Because a Service Worker can intercept requests for its scope, production deployments should treat Service Worker replacement, injected pages, and malicious Swarm-hosted websites as important security boundaries. The current architecture reduces some risk by rendering Swarm websites in iframes and by keeping sensitive state behind the secure vault layer, but security hardening remains an active development area.
180
228
 
181
- ## [Planned development]
229
+ ### Main dependencies
230
+
231
+ The weeb-3 project uses the following main Rust crates and browser bindings:
182
232
 
183
- - Adding functionality to the service worker to enable triggering requests towards the shared worker, to retrieve resources when swarm references are present in a website, alternatively, achieving the same by overwriting navigation bar contents when an onclick event is detected to be a swarm reference
184
- - Simultaneous manifest fork lookups
185
- - Multi-threading through web-workers
186
- - Adding the swarm ACT feature
187
- - Wallet related functionality such as using cheques
188
- - Penetration testing against service worker replacement and other injection types of attacks
189
- - Penetration testing loaded websites access to keys in indexeddb / loading single executable files
190
- - Refinements in error propagation, reliability, robustness, status updates in ongoing processes
233
+ - `libp2p` and `libp2p-stream` for peer identity, transport, multiplexing, stream protocols, identify, ping, autonat / dcutr support, and browser WebSocket transport.
234
+ - `async-std` and `async-lock` for async runtime primitives that work in the browser Wasm target.
235
+ - `wasm-bindgen`, `wasm-bindgen-futures`, `js-sys`, and `web-sys` for JavaScript, DOM, Service Worker, browser API, and Promise integration.
236
+ - `web3`, `alloy`, `alloy-signer-local`, and `ethers` for wallet, signing, ABI, and on-chain contract interaction.
237
+ - `indexed_db_futures` for browser IndexedDB persistence.
238
+ - `tar` and `mime_guess` for collection upload handling and MIME inference.
239
+ - `getrandom` with the `wasm_js` backend for browser-compatible randomness.
240
+ - `base64`, `hex`, `byteorder`, and numeric / cryptographic helper crates for protocol encoding and Swarm data structures.
241
+ - `tokio` and `tower-http` for the local development server used outside the Wasm target.
191
242
 
243
+ ### Concurrency and memory limitations
244
+
245
+ The browser runtime enables a high level of concurrency between Swarm tasks by combining libp2p streams, async channels, local futures, bounded upload and retrieval concurrency, and protocol-specific retry loops. This allows many protocol messages and chunk operations to be in flight at the same time even though the Wasm runtime itself is not using native threads.
192
246
 
247
+ The current browser architecture is still constrained by the WebAssembly execution environment. A tab-local runtime shares the browser's single-threaded Wasm event loop unless browser and build settings enable more advanced worker-based execution. Memory is also constrained by the WebAssembly address space and by practical browser limits.
193
248
 
249
+ Moving parts of the runtime into dedicated workers could improve isolation, memory headroom, and CPU parallelism in the future. That change would need to preserve browser transport support, Service Worker communication, secure vault boundaries, and compatibility with mobile browsers.
194
250
 
251
+ ## [Planned development]
195
252
 
253
+ - Further hardening of Service Worker replacement, iframe boundaries, route handling, and injected-content attack surfaces.
254
+ - Additional security review around loaded websites, IndexedDB access, secure vault access, upload identities, postage state, and cheque signer material.
255
+ - Better reliability, error propagation, status reporting, and recovery for long-running retrieval, upload, settlement, and connection processes.
256
+ - Improved network profile management, bootnode handling, peer quality tracking, and dial retry behavior.
257
+ - More complete and stable JavaScript package documentation and examples for the `Weeb3No103` wrapper.
258
+ - Continued improvements to BZZ path handling, streaming media retrieval, byte-range serving, and manifest fork lookup performance.
259
+ - Worker-based partitioning or multithreading where browser support and the project architecture make it practical.
260
+ - Additional Swarm feature coverage, including ACT and other protocol features not yet fully implemented.
261
+ - Continued wallet, postage, chequebook, and swap UX refinements.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@lat-murmeldjur/weeb_3",
3
3
  "type": "module",
4
4
  "description": "A Swarm client for browsers",
5
- "version": "0.0.316001",
5
+ "version": "0.0.319002",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
package/weeb_3.d.ts CHANGED
@@ -91,8 +91,12 @@ export class Weeb3No103 {
91
91
  retrieve_bytes(address: string): Promise<Uint8Array>;
92
92
  retrieve_chunk(address: string): Promise<Uint8Array>;
93
93
  start(bootstrap_nodes: BootstrapNode[], network_id: string): void;
94
+ switchMainnet(): Promise<object>;
94
95
  switchNetwork(mode: string): Promise<object>;
96
+ switchTestnet(): Promise<object>;
97
+ switch_mainnet(): Promise<object>;
95
98
  switch_network(mode: string): Promise<object>;
99
+ switch_testnet(): Promise<object>;
96
100
  upload(file: File, encryption: boolean, index_string: string, add_to_feed: boolean, feed_topic: string): Promise<object>;
97
101
  uploadPrerequisites(depth: number, validity_days: number): Promise<object>;
98
102
  upload_prerequisites(depth: number, validity_days: number): Promise<object>;
@@ -111,30 +115,10 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
111
115
  export interface InitOutput {
112
116
  readonly memory: WebAssembly.Memory;
113
117
  readonly __wbg_bootstrapnode_free: (a: number, b: number) => void;
114
- readonly __wbg_weeb3_free: (a: number, b: number) => void;
115
118
  readonly __wbg_weeb3no103_free: (a: number, b: number) => void;
116
- readonly __wbg_wings_free: (a: number, b: number) => void;
117
119
  readonly bootstrapnode_multiaddr: (a: number) => [number, number];
118
120
  readonly bootstrapnode_new: (a: number, b: number, c: number) => number;
119
121
  readonly bootstrapnode_usable: (a: number) => number;
120
- readonly weeb3_acquire: (a: number, b: number, c: number) => any;
121
- readonly weeb3_acquire_feed: (a: number, b: number, c: number, d: number, e: number) => any;
122
- readonly weeb3_change_bootnode_address: (a: number, b: number, c: number, d: number, e: number, f: number) => any;
123
- readonly weeb3_get_connections: (a: number) => any;
124
- readonly weeb3_get_current_logs: (a: number) => any;
125
- readonly weeb3_get_network_id: (a: number) => any;
126
- readonly weeb3_get_ongoing_connections: (a: number) => any;
127
- readonly weeb3_interface_log: (a: number, b: number, c: number) => void;
128
- readonly weeb3_new: (a: number, b: number) => number;
129
- readonly weeb3_post_push_chunk: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => any;
130
- readonly weeb3_post_upload: (a: number, b: any, c: number, d: number, e: number, f: number, g: number, h: number) => any;
131
- readonly weeb3_reset_stamp: (a: number) => any;
132
- readonly weeb3_retrieve_bytes: (a: number, b: number, c: number) => any;
133
- readonly weeb3_retrieve_chunk_bytes: (a: number, b: number, c: number) => any;
134
- readonly weeb3_run: (a: number, b: number, c: number) => any;
135
- readonly weeb3_set_network_id: (a: number, b: number, c: number) => any;
136
- readonly weeb3_toggle_transfer_pause: (a: number) => any;
137
- readonly weeb3_transfer_paused: (a: number) => number;
138
122
  readonly weeb3no103_acquireFeed: (a: number, b: number, c: number, d: number, e: number) => any;
139
123
  readonly weeb3no103_acquireFeedBytes: (a: number, b: number, c: number, d: number, e: number) => any;
140
124
  readonly weeb3no103_acquire_feed: (a: number, b: number, c: number, d: number, e: number) => any;
@@ -172,6 +156,7 @@ export interface InitOutput {
172
156
  readonly weeb3no103_readyState: (a: number, b: number, c: number) => any;
173
157
  readonly weeb3no103_ready_state: (a: number, b: number, c: number) => any;
174
158
  readonly weeb3no103_renderInterface: (a: number, b: any) => any;
159
+ readonly weeb3no103_render_interface: (a: number, b: any) => any;
175
160
  readonly weeb3no103_resetStamp: (a: number) => any;
176
161
  readonly weeb3no103_reset_stamp: (a: number) => any;
177
162
  readonly weeb3no103_retrieve: (a: number, b: number, c: number) => any;
@@ -180,28 +165,51 @@ export interface InitOutput {
180
165
  readonly weeb3no103_retrieve_bytes: (a: number, b: number, c: number) => any;
181
166
  readonly weeb3no103_retrieve_chunk: (a: number, b: number, c: number) => any;
182
167
  readonly weeb3no103_start: (a: number, b: number, c: number, d: number, e: number) => void;
168
+ readonly weeb3no103_switchMainnet: (a: number) => any;
183
169
  readonly weeb3no103_switchNetwork: (a: number, b: number, c: number) => any;
170
+ readonly weeb3no103_switchTestnet: (a: number) => any;
171
+ readonly weeb3no103_switch_mainnet: (a: number) => any;
184
172
  readonly weeb3no103_switch_network: (a: number, b: number, c: number) => any;
173
+ readonly weeb3no103_switch_testnet: (a: number) => any;
185
174
  readonly weeb3no103_upload: (a: number, b: any, c: number, d: number, e: number, f: number, g: number, h: number) => any;
186
175
  readonly weeb3no103_uploadPrerequisites: (a: number, b: number, c: number) => any;
187
176
  readonly weeb3no103_upload_prerequisites: (a: number, b: number, c: number) => any;
188
177
  readonly weeb3no103_feed_topic: (a: number, b: number, c: number) => any;
189
- readonly weeb3no103_render_interface: (a: number, b: any) => any;
190
178
  readonly interweeb: (a: number, b: number) => any;
179
+ readonly __wbg_weeb3_free: (a: number, b: number) => void;
180
+ readonly __wbg_wings_free: (a: number, b: number) => void;
181
+ readonly weeb3_acquire: (a: number, b: number, c: number) => any;
182
+ readonly weeb3_acquire_feed: (a: number, b: number, c: number, d: number, e: number) => any;
183
+ readonly weeb3_change_bootnode_address: (a: number, b: number, c: number, d: number, e: number, f: number) => any;
184
+ readonly weeb3_get_connections: (a: number) => any;
185
+ readonly weeb3_get_current_logs: (a: number) => any;
186
+ readonly weeb3_get_network_id: (a: number) => any;
187
+ readonly weeb3_get_ongoing_connections: (a: number) => any;
188
+ readonly weeb3_interface_log: (a: number, b: number, c: number) => void;
189
+ readonly weeb3_new: (a: number, b: number) => number;
190
+ readonly weeb3_post_push_chunk: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => any;
191
+ readonly weeb3_post_upload: (a: number, b: any, c: number, d: number, e: number, f: number, g: number, h: number) => any;
192
+ readonly weeb3_reset_stamp: (a: number) => any;
193
+ readonly weeb3_retrieve_bytes: (a: number, b: number, c: number) => any;
194
+ readonly weeb3_retrieve_chunk_bytes: (a: number, b: number, c: number) => any;
195
+ readonly weeb3_run: (a: number, b: number, c: number) => any;
196
+ readonly weeb3_set_network_id: (a: number, b: number, c: number) => any;
197
+ readonly weeb3_toggle_transfer_pause: (a: number) => any;
198
+ readonly weeb3_transfer_paused: (a: number) => number;
191
199
  readonly __wbg_requestarguments_free: (a: number, b: number) => void;
192
200
  readonly requestarguments_method: (a: number) => [number, number];
193
201
  readonly requestarguments_params: (a: number) => any;
194
- readonly wasm_bindgen__convert__closures_____invoke__h39453673aeb618ab: (a: number, b: number, c: any) => [number, number];
195
- readonly wasm_bindgen__convert__closures_____invoke__h380c4e5ad668e007: (a: number, b: number, c: any) => [number, number];
196
- readonly wasm_bindgen__convert__closures_____invoke__h38bb2d7626f4cfa1: (a: number, b: number, c: any, d: any) => void;
197
- readonly wasm_bindgen__convert__closures_____invoke__hff68d30d9ca887d6: (a: number, b: number, c: any) => void;
198
- readonly wasm_bindgen__convert__closures_____invoke__h24b02f9c177e71f4: (a: number, b: number, c: any) => void;
199
- readonly wasm_bindgen__convert__closures_____invoke__h7595764d8075eff9: (a: number, b: number, c: any) => void;
200
- readonly wasm_bindgen__convert__closures_____invoke__h24b02f9c177e71f4_4: (a: number, b: number, c: any) => void;
201
- readonly wasm_bindgen__convert__closures_____invoke__h24b02f9c177e71f4_6: (a: number, b: number, c: any) => void;
202
- readonly wasm_bindgen__convert__closures_____invoke__h096c301d37cdbb45: (a: number, b: number) => void;
203
- readonly wasm_bindgen__convert__closures_____invoke__h6f4ab657709ae694: (a: number, b: number) => void;
204
- readonly wasm_bindgen__convert__closures_____invoke__hbc64d0ffa7547e63: (a: number, b: number) => void;
202
+ readonly wasm_bindgen__convert__closures_____invoke__hd044c415605327d3: (a: number, b: number, c: any) => [number, number];
203
+ readonly wasm_bindgen__convert__closures_____invoke__he561fc60712dccf3: (a: number, b: number, c: any) => [number, number];
204
+ readonly wasm_bindgen__convert__closures_____invoke__h9288ef3fe9915859: (a: number, b: number, c: any, d: any) => void;
205
+ readonly wasm_bindgen__convert__closures_____invoke__h32ae8b24e9ba2070: (a: number, b: number, c: any) => void;
206
+ readonly wasm_bindgen__convert__closures_____invoke__h0a32fbc1945885b3: (a: number, b: number, c: any) => void;
207
+ readonly wasm_bindgen__convert__closures_____invoke__h11c7dfb27aa38104: (a: number, b: number, c: any) => void;
208
+ readonly wasm_bindgen__convert__closures_____invoke__h0a32fbc1945885b3_4: (a: number, b: number, c: any) => void;
209
+ readonly wasm_bindgen__convert__closures_____invoke__h0a32fbc1945885b3_6: (a: number, b: number, c: any) => void;
210
+ readonly wasm_bindgen__convert__closures_____invoke__h8fe36b0e7e1e898d: (a: number, b: number) => void;
211
+ readonly wasm_bindgen__convert__closures_____invoke__h44a7023f2fe3c61c: (a: number, b: number) => void;
212
+ readonly wasm_bindgen__convert__closures_____invoke__hb6b3ef33145d000c: (a: number, b: number) => void;
205
213
  readonly __wbindgen_malloc: (a: number, b: number) => number;
206
214
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
207
215
  readonly __wbindgen_exn_store: (a: number) => void;