javascript-solid-server 0.0.106 → 0.0.108
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/PAY.md +30 -4
- package/README.md +79 -1
- package/bin/jss.js +8 -0
- package/package.json +1 -1
- package/src/config.js +8 -0
- package/src/handlers/pay.js +341 -18
- package/src/server.js +18 -1
- package/src/webledger.js +43 -15
- package/src/webrtc/index.js +159 -0
- package/test/pay.test.js +145 -0
- package/test/webledger.test.js +62 -0
- package/test/webrtc.test.js +212 -0
- package/test-webrtc-smoke.mjs +90 -0
package/PAY.md
CHANGED
|
@@ -9,13 +9,15 @@ JSS has a built-in payment system. Resources under `/pay/*` cost satoshis to acc
|
|
|
9
9
|
```
|
|
10
10
|
User (Nostr keypair)
|
|
11
11
|
│
|
|
12
|
-
├── POST /pay/.deposit → credit sat balance
|
|
13
|
-
├── GET /pay/.balance → check balance
|
|
12
|
+
├── POST /pay/.deposit → credit sat balance (multi-chain: txo:tbtc3:, txo:tbtc4:, etc.)
|
|
13
|
+
├── GET /pay/.balance → check balance (includes per-chain balances)
|
|
14
14
|
├── GET /pay/* → spend 1 sat, get resource
|
|
15
15
|
├── POST /pay/.buy → spend sats, get tokens (Bitcoin TX)
|
|
16
16
|
├── POST /pay/.withdraw → spend balance, get tokens back
|
|
17
17
|
├── POST /pay/.sell → list tokens for sale
|
|
18
|
-
|
|
18
|
+
├── POST /pay/.swap → buy someone's sell order
|
|
19
|
+
├── GET /pay/.pool → AMM pool state (multi-chain)
|
|
20
|
+
└── POST /pay/.pool → AMM: swap, add-liquidity, remove-liquidity
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
All state lives in two places:
|
|
@@ -59,6 +61,17 @@ Response:
|
|
|
59
61
|
|
|
60
62
|
The `token` field is only present when `--pay-token` is configured. `rate` is sats per token.
|
|
61
63
|
|
|
64
|
+
When `--pay-chains` is configured, the response also includes:
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"chains": [
|
|
68
|
+
{ "id": "tbtc3", "unit": "tbtc3", "name": "Bitcoin Testnet3" },
|
|
69
|
+
{ "id": "tbtc4", "unit": "tbtc4", "name": "Bitcoin Testnet4" }
|
|
70
|
+
],
|
|
71
|
+
"pool": "/pay/.pool"
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
62
75
|
### GET /pay/.balance
|
|
63
76
|
**Requires NIP-98 auth.**
|
|
64
77
|
|
|
@@ -280,9 +293,10 @@ jss token info PODS
|
|
|
280
293
|
|
|
281
294
|
| File | Contents |
|
|
282
295
|
|------|----------|
|
|
283
|
-
| `/.well-known/webledgers/webledgers.json` |
|
|
296
|
+
| `/.well-known/webledgers/webledgers.json` | Balances per DID — multi-currency array format (webledgers.org spec) |
|
|
284
297
|
| `/.well-known/webledgers/replay.json` | Seen MRC20 state hashes (replay protection) |
|
|
285
298
|
| `/.well-known/webledgers/offers.json` | Open sell orders (secondary market) |
|
|
299
|
+
| `/.well-known/webledgers/pool.json` | AMM pool state (reserves, LP shares, k) |
|
|
286
300
|
| `/.well-known/token/<ticker>.json` | MRC20 token trail (state chain, keys, UTXO) |
|
|
287
301
|
|
|
288
302
|
## Source Files
|
|
@@ -330,6 +344,18 @@ jss token info PODS
|
|
|
330
344
|
6. POST /pay/.swap → buys the 50 PODS, seller gets 750 sats credited
|
|
331
345
|
```
|
|
332
346
|
|
|
347
|
+
### Cross-chain AMM trading
|
|
348
|
+
```
|
|
349
|
+
1. Configure pod: jss start --pay --pay-chains "tbtc3,tbtc4"
|
|
350
|
+
2. User A deposits: POST /pay/.deposit "txo:tbtc3:<txid>:<vout>" → gets tbtc3 balance
|
|
351
|
+
3. User B deposits: POST /pay/.deposit "txo:tbtc4:<txid>:<vout>" → gets tbtc4 balance
|
|
352
|
+
4. User A adds liquidity: POST /pay/.pool { "action": "add-liquidity", "tbtc3": 1000, "tbtc4": 5000 }
|
|
353
|
+
5. User B swaps: POST /pay/.pool { "action": "swap", "sell": "tbtc4", "amount": 500 }
|
|
354
|
+
→ receives ~90 tbtc3 (constant product formula, 0.3% fee)
|
|
355
|
+
6. User A removes liquidity: POST /pay/.pool { "action": "remove-liquidity", "all": true }
|
|
356
|
+
→ gets back proportional share of both currencies + earned fees
|
|
357
|
+
```
|
|
358
|
+
|
|
333
359
|
### Full exit
|
|
334
360
|
```
|
|
335
361
|
1. POST /pay/.withdraw { "all": true } → converts entire balance to portable tokens
|
package/README.md
CHANGED
|
@@ -158,9 +158,12 @@ jss --help # Show help
|
|
|
158
158
|
| `--pay-address <addr>` | Address for receiving deposits | - |
|
|
159
159
|
| `--pay-token <ticker>` | Token to sell (enables primary market + withdrawal) | - |
|
|
160
160
|
| `--pay-rate <n>` | Sats per token for buy/withdraw | 1 |
|
|
161
|
+
| `--pay-chains <ids>` | Multi-chain deposits + AMM (e.g. "tbtc3,tbtc4") | - |
|
|
161
162
|
| `--mongo` | Enable MongoDB-backed /db/ route | false |
|
|
162
163
|
| `--mongo-url <url>` | MongoDB connection URL | mongodb://localhost:27017 |
|
|
163
164
|
| `--mongo-database <name>` | MongoDB database name | solid |
|
|
165
|
+
| `--webrtc` | Enable WebRTC signaling server | false |
|
|
166
|
+
| `--webrtc-path <path>` | WebRTC signaling WebSocket path | /.webrtc |
|
|
164
167
|
| `-q, --quiet` | Suppress logs | false |
|
|
165
168
|
|
|
166
169
|
### Environment Variables
|
|
@@ -194,6 +197,7 @@ export JSS_PAY_RATE=10
|
|
|
194
197
|
export JSS_MONGO=true
|
|
195
198
|
export JSS_MONGO_URL=mongodb://localhost:27017
|
|
196
199
|
export JSS_MONGO_DATABASE=solid
|
|
200
|
+
export JSS_WEBRTC=true
|
|
197
201
|
jss start
|
|
198
202
|
```
|
|
199
203
|
|
|
@@ -822,6 +826,42 @@ curl -X DELETE http://localhost:3000/db/alice/notes/1 \
|
|
|
822
826
|
|
|
823
827
|
Supported formats: `50MB`, `1GB`, `500KB`, `1TB`
|
|
824
828
|
|
|
829
|
+
## WebRTC Signaling
|
|
830
|
+
|
|
831
|
+
Peer-to-peer communication via WebRTC, using JSS as the signaling server. Once peers are connected, all media and data flows directly between them.
|
|
832
|
+
|
|
833
|
+
```bash
|
|
834
|
+
jss start --webrtc
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### How It Works
|
|
838
|
+
|
|
839
|
+
1. Both peers connect to `wss://your.pod/.webrtc` (WebID auth required)
|
|
840
|
+
2. Caller sends an SDP offer targeting the callee's WebID
|
|
841
|
+
3. JSS relays the offer/answer and ICE candidates between peers
|
|
842
|
+
4. Once a direct path is found, the peer-to-peer connection is established
|
|
843
|
+
5. JSS steps out — video, audio, files, and data flow directly between peers
|
|
844
|
+
|
|
845
|
+
### Protocol
|
|
846
|
+
|
|
847
|
+
Messages are JSON over WebSocket:
|
|
848
|
+
|
|
849
|
+
```js
|
|
850
|
+
// Send an offer to another user
|
|
851
|
+
{ "type": "offer", "to": "https://bob.example/profile/card#me", "sdp": "..." }
|
|
852
|
+
|
|
853
|
+
// Receive an offer from another user
|
|
854
|
+
{ "type": "offer", "from": "https://alice.example/profile/card#me", "sdp": "..." }
|
|
855
|
+
|
|
856
|
+
// ICE candidate exchange
|
|
857
|
+
{ "type": "candidate", "to": "https://bob.example/profile/card#me", "candidate": {...} }
|
|
858
|
+
|
|
859
|
+
// Hang up
|
|
860
|
+
{ "type": "hangup", "to": "https://bob.example/profile/card#me" }
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
On connect, peers receive a list of online users and get notified when others join or leave.
|
|
864
|
+
|
|
825
865
|
## HTTP 402 Paid Access
|
|
826
866
|
|
|
827
867
|
Monetize API endpoints with per-request satoshi payments. Resources under `/pay/*` require NIP-98 authentication and a positive balance.
|
|
@@ -834,11 +874,16 @@ jss start --pay --pay-cost 10 --pay-address your-address --pay-token PODS --pay-
|
|
|
834
874
|
|
|
835
875
|
| Method | Path | Description |
|
|
836
876
|
|--------|------|-------------|
|
|
837
|
-
| GET | `/pay/.info` | Public: cost, token info,
|
|
877
|
+
| GET | `/pay/.info` | Public: cost, token info, chains, pool |
|
|
838
878
|
| GET | `/pay/.balance` | Check your balance (NIP-98 auth) |
|
|
839
879
|
| POST | `/pay/.deposit` | Deposit sats via TXO URI or MRC20 state proof |
|
|
840
880
|
| POST | `/pay/.buy` | Buy tokens with sat balance (requires `--pay-token`) |
|
|
841
881
|
| POST | `/pay/.withdraw` | Withdraw balance as portable tokens (requires `--pay-token`) |
|
|
882
|
+
| GET | `/pay/.offers` | List open sell orders (secondary market) |
|
|
883
|
+
| POST | `/pay/.sell` | Create a sell order (requires `--pay-token`) |
|
|
884
|
+
| POST | `/pay/.swap` | Execute a swap against a sell order |
|
|
885
|
+
| GET | `/pay/.pool` | AMM pool state (requires `--pay-chains`) |
|
|
886
|
+
| POST | `/pay/.pool` | AMM swap, add/remove liquidity |
|
|
842
887
|
| GET | `/pay/*` | Paid resource access (deducts balance) |
|
|
843
888
|
|
|
844
889
|
### How It Works
|
|
@@ -879,6 +924,39 @@ curl -X POST -H "Authorization: Nostr <base64-event>" \
|
|
|
879
924
|
|
|
880
925
|
Deposit verification uses the mempool API (default: testnet4). The `X-Balance` and `X-Cost` headers are returned on successful paid requests. Buy and withdraw return portable MRC20 proofs with Bitcoin anchor data for independent verification.
|
|
881
926
|
|
|
927
|
+
### Secondary Market
|
|
928
|
+
|
|
929
|
+
Users can trade tokens peer-to-peer through the pod. Sell orders are created via `/pay/.sell` and filled via `/pay/.swap`. The pod acts as escrow — transferring tokens on the Bitcoin-anchored MRC20 trail and settling sats in the webledger.
|
|
930
|
+
|
|
931
|
+
### Multi-Chain AMM
|
|
932
|
+
|
|
933
|
+
Enable multi-chain deposits and an automated market maker:
|
|
934
|
+
|
|
935
|
+
```bash
|
|
936
|
+
jss start --pay --pay-chains "tbtc3,tbtc4"
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
Deposits detect the chain from the TXO URI prefix (`txo:tbtc3:txid:vout`). Each chain's balance is tracked separately. The AMM uses a constant-product formula (x × y = k) with a 0.3% fee.
|
|
940
|
+
|
|
941
|
+
```bash
|
|
942
|
+
# Add liquidity
|
|
943
|
+
curl -X POST -H "Authorization: Nostr <token>" \
|
|
944
|
+
-H "Content-Type: application/json" \
|
|
945
|
+
http://localhost:3000/pay/.pool \
|
|
946
|
+
-d '{"action": "add-liquidity", "tbtc3": 1000, "tbtc4": 5000}'
|
|
947
|
+
|
|
948
|
+
# Swap
|
|
949
|
+
curl -X POST -H "Authorization: Nostr <token>" \
|
|
950
|
+
-H "Content-Type: application/json" \
|
|
951
|
+
http://localhost:3000/pay/.pool \
|
|
952
|
+
-d '{"action": "swap", "sell": "tbtc3", "amount": 100}'
|
|
953
|
+
|
|
954
|
+
# Check pool state
|
|
955
|
+
curl http://localhost:3000/pay/.pool
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
Supported chains: `btc`, `tbtc3`, `tbtc4`, `ltc`, `signet`.
|
|
959
|
+
|
|
882
960
|
## Authentication
|
|
883
961
|
|
|
884
962
|
### Simple Tokens (Development)
|
package/bin/jss.js
CHANGED
|
@@ -65,6 +65,9 @@ program
|
|
|
65
65
|
.option('--no-nostr', 'Disable Nostr relay')
|
|
66
66
|
.option('--nostr-path <path>', 'Nostr relay WebSocket path (default: /relay)')
|
|
67
67
|
.option('--nostr-max-events <n>', 'Max events in relay memory (default: 1000)', parseInt)
|
|
68
|
+
.option('--webrtc', 'Enable WebRTC signaling server')
|
|
69
|
+
.option('--no-webrtc', 'Disable WebRTC signaling server')
|
|
70
|
+
.option('--webrtc-path <path>', 'WebRTC signaling WebSocket path (default: /.webrtc)')
|
|
68
71
|
.option('--activitypub', 'Enable ActivityPub federation')
|
|
69
72
|
.option('--no-activitypub', 'Disable ActivityPub federation')
|
|
70
73
|
.option('--ap-username <name>', 'ActivityPub username (default: me)')
|
|
@@ -87,6 +90,7 @@ program
|
|
|
87
90
|
.option('--pay-address <addr>', 'Address for receiving deposits')
|
|
88
91
|
.option('--pay-token <ticker>', 'Token to sell (enables primary market)')
|
|
89
92
|
.option('--pay-rate <n>', 'Sats per token for primary market (default: 1)', parseInt)
|
|
93
|
+
.option('--pay-chains <chains>', 'Comma-separated chain IDs for multi-chain deposits/AMM (e.g. "tbtc3,tbtc4")')
|
|
90
94
|
.option('--mongo', 'Enable MongoDB-backed /db/ route')
|
|
91
95
|
.option('--no-mongo', 'Disable MongoDB-backed /db/ route')
|
|
92
96
|
.option('--mongo-url <url>', 'MongoDB connection URL (default: mongodb://localhost:27017)')
|
|
@@ -141,6 +145,8 @@ program
|
|
|
141
145
|
nostr: config.nostr,
|
|
142
146
|
nostrPath: config.nostrPath,
|
|
143
147
|
nostrMaxEvents: config.nostrMaxEvents,
|
|
148
|
+
webrtc: config.webrtc,
|
|
149
|
+
webrtcPath: config.webrtcPath,
|
|
144
150
|
activitypub: config.activitypub,
|
|
145
151
|
apUsername: config.apUsername,
|
|
146
152
|
apDisplayName: config.apDisplayName,
|
|
@@ -159,6 +165,7 @@ program
|
|
|
159
165
|
payAddress: config.payAddress,
|
|
160
166
|
payToken: config.payToken,
|
|
161
167
|
payRate: config.payRate,
|
|
168
|
+
payChains: config.payChains,
|
|
162
169
|
mongo: config.mongo,
|
|
163
170
|
mongoUrl: config.mongoUrl,
|
|
164
171
|
mongoDatabase: config.mongoDatabase,
|
|
@@ -184,6 +191,7 @@ program
|
|
|
184
191
|
if (config.solidosUi) console.log(' SolidOS UI: enabled (modern interface)');
|
|
185
192
|
if (config.git) console.log(' Git: enabled (clone/push support)');
|
|
186
193
|
if (config.nostr) console.log(` Nostr: enabled (${config.nostrPath})`);
|
|
194
|
+
if (config.webrtc) console.log(` WebRTC: enabled (${config.webrtcPath || '/.webrtc'})`);
|
|
187
195
|
if (config.activitypub) console.log(` ActivityPub: enabled (@${config.apUsername || 'me'})`);
|
|
188
196
|
if (config.singleUser) console.log(` Single-user: ${config.singleUserName || 'me'} (registration disabled)`);
|
|
189
197
|
else if (config.inviteOnly) console.log(' Registration: invite-only');
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -54,6 +54,10 @@ export const defaults = {
|
|
|
54
54
|
nostrPath: '/relay',
|
|
55
55
|
nostrMaxEvents: 1000,
|
|
56
56
|
|
|
57
|
+
// WebRTC signaling
|
|
58
|
+
webrtc: false,
|
|
59
|
+
webrtcPath: '/.webrtc',
|
|
60
|
+
|
|
57
61
|
// ActivityPub federation
|
|
58
62
|
activitypub: false,
|
|
59
63
|
apUsername: 'me',
|
|
@@ -90,6 +94,7 @@ export const defaults = {
|
|
|
90
94
|
payAddress: null,
|
|
91
95
|
payToken: null,
|
|
92
96
|
payRate: 1,
|
|
97
|
+
payChains: null, // comma-separated chain IDs, e.g. "tbtc3,tbtc4"
|
|
93
98
|
|
|
94
99
|
// MongoDB-backed /db/ route
|
|
95
100
|
mongo: false,
|
|
@@ -133,6 +138,8 @@ const envMap = {
|
|
|
133
138
|
JSS_NOSTR: 'nostr',
|
|
134
139
|
JSS_NOSTR_PATH: 'nostrPath',
|
|
135
140
|
JSS_NOSTR_MAX_EVENTS: 'nostrMaxEvents',
|
|
141
|
+
JSS_WEBRTC: 'webrtc',
|
|
142
|
+
JSS_WEBRTC_PATH: 'webrtcPath',
|
|
136
143
|
JSS_ACTIVITYPUB: 'activitypub',
|
|
137
144
|
JSS_AP_USERNAME: 'apUsername',
|
|
138
145
|
JSS_AP_DISPLAY_NAME: 'apDisplayName',
|
|
@@ -152,6 +159,7 @@ const envMap = {
|
|
|
152
159
|
JSS_PAY_ADDRESS: 'payAddress',
|
|
153
160
|
JSS_PAY_TOKEN: 'payToken',
|
|
154
161
|
JSS_PAY_RATE: 'payRate',
|
|
162
|
+
JSS_PAY_CHAINS: 'payChains',
|
|
155
163
|
JSS_MONGO: 'mongo',
|
|
156
164
|
JSS_MONGO_URL: 'mongoUrl',
|
|
157
165
|
JSS_MONGO_DATABASE: 'mongoDatabase',
|