Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 25 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
# Node Environment variables
MAX_ROOM_SIZE=500
# ==============================================================================
# Conduit SDK Environment Configuration
# ==============================================================================

# Stellar Network Selection ('testnet' | 'mainnet' | 'local')
NEXT_PUBLIC_NETWORK=testnet
CONDUIT_NETWORK=testnet

# Stellar Secret Key for signing transactions (e.g. S...)
# WARNING: Keep private keys secure; never expose to browser client bundles
STELLAR_SECRET=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Custom Soroban RPC Endpoint URL (optional; defaults to network default)
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
RPC_URL=https://soroban-testnet.stellar.org

# Soroban Contract Addresses (optional overrides)
CONDUIT_FACTORY_ADDRESS=CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
CONDUIT_GOVERNOR_ADDRESS=CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CONDUIT_TOKEN_ADDRESS=native

# Example Scripts / CLI Parameters
STREAM_ID=1
ADDRESS=GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
NEXT_PUBLIC_ADDRESS=GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ All notable changes are documented here. Format based on [Keep a Changelog](http
- `FactoryModule.streamAddress()` now caches resolved stream→contract-address lookups in-memory, since the mapping is fixed at stream creation and never changes. Eliminates redundant RPC round trips on every `StreamsModule` read/write operation (`get`, `withdraw`, `cancel`, `pause`, `resume`, `topUp`, `clawback`) and on each page of `list()`, which previously re-resolved the same address for every stream on every call.
- `buildBatchTransactions()` (the RPC-prepared batch path) now simulates all operations in a batch concurrently instead of one at a time, cutting the wall-clock time of an N-operation batch from N sequential RPC round trips to one.

### Removed
- Removed orphaned `RoomManager` (`src/room-manager.js`) and `src/server.js` WebSocket server, along with unused `dotenv` production dependency (#442).
- Removed unused `GraphSyncAgent` (`src/graph-sync-agent.ts`) dead code (#443).

### Documentation
- Removed non-existent `contracts/*-abi.ts` entry from `docs/architecture.md` module map (#440).
- Replaced orphaned `MAX_ROOM_SIZE` `.env.example` with a comprehensive SDK environment configuration template and updated `README.md` (#441).
- Added an API reference section for `GraphQLIndexer`, which was previously exported but undocumented.
- Added a "Wallet Adapters" API reference section documenting `KeypairWalletAdapter`.
- Documented `ConduitClient`'s `pauseStream()`, `unpauseStream()`, and `setWallet()` convenience methods in `docs/api.md`, and fixed `setWallet()`'s JSDoc block, which had been orphaned above `pauseStream()`/`unpauseStream()` and left `setWallet()` itself undocumented.
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,9 +678,15 @@ See [`CONTRIBUTING.md`](./CONTRIBUTING.md). For the module map and call flow, se

## Configuration

The RoomManager limits can be configured via environment variables.

* `MAX_ROOM_SIZE`: Maximum number of clients allowed in a single room (default: Infinity).
The SDK can be configured via environment variables or explicit constructor options in `ConduitClient`. A template is provided in [`.env.example`](./.env.example).

* `STELLAR_SECRET`: Stellar secret key for signing transactions (keep secure; server-side only).
* `NEXT_PUBLIC_NETWORK` / `CONDUIT_NETWORK`: Stellar network selection (`testnet`, `mainnet`, or `local`).
* `SOROBAN_RPC_URL` / `RPC_URL`: Optional custom Soroban RPC endpoint override.
* `CONDUIT_FACTORY_ADDRESS`: Optional override for deployed DripFactory contract address.
* `CONDUIT_GOVERNOR_ADDRESS`: Optional override for deployed DripGovernor contract address.
* `CONDUIT_TOKEN_ADDRESS`: Optional default token contract address or `'native'`.
* `STREAM_ID` / `ADDRESS`: Parameters for example scripts and CLI integration.

---

Expand Down
117 changes: 0 additions & 117 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -567,123 +567,6 @@ immediately if the lock is free, or queues behind the current holder otherwise.

---

## `RoomManager` (Server Utility)

> **Added in issue #367 (module 33)** — performance-optimised WebSocket room manager used by `src/server.js`.

```javascript
const { RoomManager } = require('./src/room-manager');
```

### Constructor

```javascript
new RoomManager(options?)
```

| Option | Type | Default | Notes |
|--------|------|---------|-------|
| `maxRoomSize` | `number` | `Infinity` | Maximum number of simultaneous clients per room |

---

### `join(clientId, roomId, ws) → { ok, reason? }`

Add a client to a room.

| Param | Type | Notes |
|-------|------|-------|
| `clientId` | `string` | Unique client identifier |
| `roomId` | `string` | Target room |
| `ws` | `object` | WebSocket-like object with a `send(data)` method |

**Returns:**
- `{ ok: true }` — client joined (or re-joined, updating the socket reference)
- `{ ok: false, reason: 'ROOM_FULL' }` — room has reached `maxRoomSize`

**Performance note:** Re-joining an existing client (same `clientId`) only updates the socket reference and never increments the room size.

---

### `leave(clientId, roomId)`

Remove a client from a specific room. Automatically deletes the room if it becomes empty,
and removes the client's room-tracking entry if they are no longer in any room.

---

### `disconnectClient(clientId)`

Remove a client from **every** room it belongs to in a single sweep. More efficient than
calling `leave()` per room when a connection drops.

```javascript
// On WebSocket close:
ws.on('close', () => roomManager.disconnectClient(clientId));
```

---

### `broadcast(roomId, data)`

Fan-out a message to every client currently in a room. Iterates the internal `Map`
exactly once — callers do not need to fetch and loop the room themselves.

```javascript
roomManager.broadcast('lobby', JSON.stringify({ type: 'chat', text: 'hello' }));
```

| Param | Type | Notes |
|-------|------|-------|
| `roomId` | `string` | Target room (no-op if the room does not exist) |
| `data` | `string \| Buffer` | Passed verbatim to each `ws.send()` |

---

### `getRoomSize(roomId) → number`

O(1) accessor returning the number of clients currently in a room. Returns `0` if the
room does not exist.

```javascript
const size = roomManager.getRoomSize('lobby'); // e.g. 4
```

---

### `getClients(roomId) → Map<string, ws>`

Return the live `Map<clientId, ws>` for a room. Returns an empty `Map` if the room does
not exist — never returns `null` or `undefined`.

```javascript
for (const [clientId, ws] of roomManager.getClients('lobby')) {
ws.send(JSON.stringify({ type: 'roster', clientId }));
}
```

> **Note:** The returned `Map` is a live reference to the internal data structure. Do not
> mutate it directly — use `join()`, `leave()`, and `disconnectClient()` instead.

---

### Error frame format

When `handleJoin` (from `server.js`) rejects a join due to capacity, it sends the
following JSON frame to the rejected client's socket before returning:

```json
{
"type": "error",
"payload": {
"message": "Room is full",
"code": "ROOM_FULL"
}
}
```

---

## `Module36` (Feature #36)

Stream snapshot diff engine implementing Feature #36. Uses LRU-memoized comparisons to avoid recomputing deltas for repeated identical stream state comparisons; actual speedup is workload-dependent (proportional to cache hit rate).
Expand Down
1 change: 0 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ indexer.ts — GraphQLIndexer: query() + subscribe() (WebSocket, SSE fal
dashboard/transaction-history.ts
— framework-agnostic reducer + selectors for the Transaction History view
(normalisation, filtering, sorting, pagination — see "Selector memoisation" below)
contracts/*-abi.ts — generated-style ABI/method-name constants per contract
```

`ConduitClient` is a thin composition root — it resolves the RPC URL (`config.rpcUrl ??
Expand Down
27 changes: 1 addition & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
"vitest": "^4.1.10"
},
"dependencies": {
"dotenv": "^16.6.1",
"tslib": "^2.8.1"
},
"sideEffects": false
Expand Down
1 change: 0 additions & 1 deletion rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ const sharedOutput = {
'src/constants.ts',
'src/indexer.ts',
'src/fee-estimator.ts',
'src/graph-sync-agent.ts',
'src/nonce-manager.ts',
'src/nonce/NonceManager.ts',
'src/relayer/WebSocketRelayer.ts',
Expand Down
45 changes: 0 additions & 45 deletions src/graph-sync-agent.ts

This file was deleted.

Loading