# API: hyper-p2p-crdt-grow-only-set **Protocol:** `crdt-grow-only-set/v1` **Export:** `{ HyperP2PCrdtGrowOnlySet, PROTOCOL }` ## Overview `HyperP2PCrdtGrowOnlySet` implements a **grow-only set (G-Set)** CRDT: elements are stringified, stored in a local `Set`, and merged monotonically from peers. Local `add()` gossips new elements; remote sync messages union into the same set. The class extends `bare-events` `EventEmitter` but does not emit application events in the current implementation. Call `ready()` with a `topic` to join Hyperswarm and receive gossip; without `topic`, the CRDT works in-process only. ## Constructor ```js const { HyperP2PCrdtGrowOnlySet, PROTOCOL } = require('hyper-p2p-crdt-grow-only-set') const set = new HyperP2PCrdtGrowOnlySet(opts) ``` | Option | Type | Default | Description | |--------|------|---------|-------------| | `topic` | `string` \| `Buffer` \| `null` | `null` | Hyperswarm topic; required for P2P sync via `ready()` | | `keyPair` | Hypercore `KeyPair` | `hypercore-crypto.keyPair()` | Swarm identity | ## Methods ### `add(el)` Adds an element if not already present. - **Parameters:** `el` — any value coerced with `String(el)`; must not be `null`/`undefined` - **Returns:** `boolean` — `true` if newly added, `false` if duplicate (no gossip) - **Throws:** `Error: el required` when `el == null` - **Side effects:** increments `stats.ops`, sends wire message on new insert ### `has(el)` - **Returns:** `boolean` — membership in the merged set - **Throws:** — ### `values()` - **Returns:** `string[]` — snapshot of all elements (spread of internal `Set`) - **Throws:** — ### `async ready()` Joins Hyperswarm when `topic` is set and swarm not yet initialized. - **Returns:** `Promise` (same instance) - **Throws:** `Error: topic is required for createSwarm` from shared helper if topic invalid at join time - **Idempotent:** returns immediately if `swarm` already exists or `topic` is missing ### `async close()` Destroys swarm, clears `_peerMsgs`. - **Returns:** `Promise` - **Throws:** — (swarm destroy errors swallowed) ### `getStats()` - **Returns:** | Field | Type | Description | |-------|------|-------------| | `ops` | `number` | Local `add` operations that changed state | | `gossipIn` | `number` | Inbound sync messages applied | | `gossipOut` | `number` | Outbound sync messages sent | | `size` | `number` | Current element count | | `protocol` | `string` | `crdt-grow-only-set/v1` | ## Events No events are emitted by the current implementation. The instance is an `EventEmitter` for forward compatibility. ## getStats() See **Methods → `getStats()`** above. Counters are shallow-copied; safe to log in tests. ## Wire (P2P) Transport: Hyperswarm connection → Protomux channel `crdt-grow-only-set/v1` → `compact-encoding` JSON via `initModuleSwarm` / `gossipSend`. | Message `type` | Fields | Direction | Behavior | |----------------|--------|-----------|----------| | `crdt-grow-only-set-sync` | `el: string` | bidirectional | Union `el` into local `_added`; increments `gossipIn` on receive | Ignored: messages with wrong `type`, missing `el`, or null payload. ## Errors | Message | Source | |---------|--------| | `el required` | `add()` when `el == null` | | `topic is required for createSwarm` | `initModuleSwarm` → `createSwarm` without topic | | `{label} is required` | Not used in this module | Shared validation helpers live in [`../../../_shared/lib/errors.js`](../../../_shared/lib/errors.js). ## Testing ```bash cd modules/state-crdts/hyper-p2p-crdt-grow-only-set npm install && npm test ``` Use distinct `keyPair` / topics per test peer. Example: ```bash bare examples/basic.js TOPIC=$(openssl rand -hex 32) && bare examples/basic.js $TOPIC ``` Two-node: run two processes with the same `topic`, call `add` on each, then `values()` after gossip settles.