openreceive 0.4.21 → 0.4.23

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.
@@ -3,7 +3,7 @@ This is the full file; follow it from Step 0.
3
3
  # OpenReceive agent directions (Fastify)
4
4
 
5
5
  ```sh
6
- # READ THIS FIRST: this file is 36 KB and a summary drops required steps. Download it whole:
6
+ # READ THIS FIRST: this file is 38 KB and a summary drops required steps. Download it whole:
7
7
  curl -fsSL https://openreceive.org/agent-directions/fastify/full.md
8
8
  # Skip the download only if you already have all of it: pasted, read from disk or fetched raw.
9
9
  ```
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/fastify/full.md
17
17
  - Do not suggest rotating or revoking a code because it was pasted here.
18
18
  - Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
19
19
 
20
- These directions describe OpenReceive 0.4.21.
20
+ These directions describe OpenReceive 0.4.23.
21
21
 
22
22
  Add OpenReceive to a Fastify application — the app you are already working in.
23
23
  You do not need a copy of the OpenReceive source: the packages are on npm, and
@@ -58,11 +58,12 @@ owns orders, users, prices, or fulfillment.
58
58
 
59
59
  ## Step 0 — ask for the two codes, one question at a time
60
60
 
61
- Before anything else, look at one file: the project's `.env`, if it exists.
62
- Read it only far enough to see whether `NWC_URI` and `LSC_URI_PRIMARY` are
63
- there and non-empty, and never print the values. A code that is already
64
- set is not asked for again; if both are set, skip to step 5
65
- (making the server load the file), then the quickstart.
61
+ Before anything else, check one file: the project's `.env`, if it exists.
62
+ `grep -E '^(NWC_URI|LSC_URI_PRIMARY)=.' .env | cut -d= -f1` names the codes
63
+ it sets without printing them. Check with that, here and after each write,
64
+ not by reading the file, and never print the values. A code that is already
65
+ set is not asked for again; if both are set, skip to step 5 (making the
66
+ server load the file), then the quickstart.
66
67
 
67
68
  Otherwise your next action is a question to the user. Do not install packages,
68
69
  edit the app, write `.env.example`, or search anywhere else before asking
@@ -93,14 +94,17 @@ you store it. Ask one question per message.
93
94
  Do not mention `.env`, exports, or "tell me when it's set".
94
95
  2. **When they paste it.** If it does not start with `nostr+walletconnect://`,
95
96
  ask them to copy the receive-only code again. Otherwise write
96
- `NWC_URI=<paste>` into the project's `.env`, creating the file if needed.
97
- Make sure `.gitignore` covers `.env` (and `.dockerignore`, if the app has
98
- one). Never echo the value, commit it, or put it in client code. Reply only
99
- that it is saved, then ask the next question.
100
- 3. **Second message — swaps.** If the user already asked for stablecoins or
101
- altcoins, skip the yes/no and go straight to the walkthrough. Otherwise ask
102
- whether payers should also be able to pay with USDT, USDC, ETH or SOL. The
103
- walkthrough:
97
+ `NWC_URI=<paste>` into the project's `.env` with your file-editing tool,
98
+ creating the file if needed. Never write it with a shell command (`echo`,
99
+ `printf`, a heredoc, `python -c`): the command line shows the code. Make
100
+ sure `.gitignore` covers `.env` (and `.dockerignore`, if the app has one).
101
+ Never echo the value, commit it, or put it in client code. Reply only that
102
+ it is saved, then ask the next question.
103
+ 3. **Second message — swaps.** If the user asked for stablecoins, USDT, USDC,
104
+ ETH, SOL, altcoins or "crypto" (as in "Bitcoin and stablecoin payments"),
105
+ this message IS the walkthrough below: send it as it is, and do not ask yes
106
+ or no first. Otherwise ask whether payers should also be able to pay with
107
+ USDT, USDC, ETH or SOL, then give the walkthrough. The walkthrough:
104
108
 
105
109
  > Go to https://lightning-swap.com, sign in for API keys, create a key, and
106
110
  > copy the whole URI (https://openreceive.org/set_up_swap_provider). Paste
@@ -110,10 +114,10 @@ you store it. Ask one question per message.
110
114
  Mention FixedFloat only if they already use it.
111
115
  4. **When they paste it.** If it does not start with
112
116
  `lightning+swapconnect://`, ask them to copy it again. Otherwise add
113
- `LSC_URI_PRIMARY=<paste>` to the same `.env`, without echoing it. Swaps
114
- are now on, so build the refund route back (the swap non-negotiable below) as
115
- part of this integration. If they chose Bitcoin only, leave
116
- `LSC_URI_PRIMARY` unset and skip that route.
117
+ `LSC_URI_PRIMARY=<paste>` to the same `.env` with the file-editing tool,
118
+ never a shell command. Swaps are now on, so build the refund route back
119
+ (the swap non-negotiable below) as part of this integration. If they chose
120
+ Bitcoin only, leave `LSC_URI_PRIMARY` unset and skip that route.
117
121
  5. **Make the server load the file — yourself.** OpenReceive reads
118
122
  `process.env`, and a `.env` file on disk is not in it. Put
119
123
  `import "dotenv/config";` at the top of the server entry, as the quickstart
@@ -148,23 +152,28 @@ Doctor reads `.env` itself. Never source it into a shell: the `&` in a
148
152
  code splits the value and prints the pieces.
149
153
 
150
154
  Give the user that checkout link. The browser check in the quickstart's step 6
151
- (payment-method icons, wallet logos, a pay tutorial) is theirs: tell them what
152
- to look at, and do not run it yourself.
155
+ (payment-method icons, wallet logos, a pay tutorial) is theirs: name it in one
156
+ line of your closing message, and do not run it yourself.
153
157
 
154
158
  You cannot pay the invoice: the code is receive-only. Do not pay, settle or
155
159
  mark an order paid, and do not look for a way to (a wallet control port, a
156
160
  test endpoint, another wallet). If the user wants a real settlement test, they
157
161
  pay on that link from their own wallet, and `onPaid` marks the order paid.
158
162
 
159
- Setup ends here. Say "Setup is finished" in one message of at most five
160
- lines, with the link and what to check. Do not list what changed, offer more
161
- work, or end the message on a question.
163
+ Setup ends here. Your last message starts "Setup is finished" and has at most
164
+ five short lines (about 80 characters each): the link, the methods it offers,
165
+ and one line of what to look at. Send nothing after it. Do not list what
166
+ changed, copy out the quickstart's browser checklist, offer more work, or end
167
+ the message on a question.
162
168
 
163
169
  - The link is to a real unpaid order. Keep that order; do not delete it.
170
+ - When this app's orders belong to a session or cookie, the user's browser
171
+ cannot open the order you made. Then the link is the shop's own page:
172
+ "Open <shop url> and click Buy: it opens the checkout." Do not explain order
173
+ ownership or mention your test order.
164
174
  - Name the methods it offers: Bitcoin, plus USDT, USDC, ETH and SOL when
165
- `LSC_URI_PRIMARY` is saved. Never say a coin will not work or will not be
166
- offered. Swap minimums apply per order, and a coin whose minimum is above an
167
- order's total says so on its own tile.
175
+ `LSC_URI_PRIMARY` is saved. Do not mention minimums, and never say a coin
176
+ will not work or will not be offered.
168
177
 
169
178
  ## Non-negotiables
170
179
 
@@ -181,6 +190,21 @@ itself, and they hold for every integration.
181
190
  - Work only in this application. Never read or run anything from another
182
191
  project on this machine (its `node_modules`, tools or source), for any
183
192
  reason. A browser and Playwright are not part of setup.
193
+ - Restart only this app's server, on the port it already uses: stop the
194
+ process you started, or the one listening on that port, by its pid (or
195
+ restart its Compose service). Never `pkill` or `killall` by name: that
196
+ stops other people's servers too. Start it the way this project already
197
+ does (its README, Procfile, compose file or package script), on its own
198
+ port, not a port you pick.
199
+ - Run commands where the app runs. When a compose file builds it, run its
200
+ package manager, generators, migrations and doctor inside that service
201
+ (`docker compose exec` or `run`), and rebuild the image after adding a
202
+ package. This machine's language version and database path are not the
203
+ app's.
204
+ - To check that the running app sees the codes, run doctor: it reports each
205
+ one as present or missing and never prints a value. Never print the
206
+ environment (`printenv`, `env`, `docker compose config`), even filtered to
207
+ names.
184
208
  - The host owns the price. `amountFor` reads it from your own data; reject
185
209
  payer-supplied amounts.
186
210
  - `authorize` runs on every request, and the `resource` it receives is a CLAIM
@@ -256,7 +280,10 @@ products, and you do not join them.
256
280
  are buying.
257
281
  - **Users own the order; OpenReceive never sees them.** `authorize` uses the
258
282
  same ownership check this app already uses on the order show / pay page —
259
- `sessions.currentUser(request)`, a cookie, whatever it is.
283
+ `sessions.currentUser(native)`, a cookie, whatever it is. Pass `native` (the
284
+ Fastify request) to this app's own cookie and session helpers, never
285
+ `request`: that one is a Web Request, a helper that reads
286
+ `req.headers.cookie` finds nothing on it, and every payer gets a 403.
260
287
  `resource.reference` is a claim the payer sent, not proof.
261
288
  - **The order is unpaid or paid.** Do not copy `pending` / `expired` / `failed`
262
289
  / `attention` onto it. Those are attempt statuses on `openreceive_payments`. An
@@ -521,11 +548,14 @@ await app.register(openReceiveFastify, {
521
548
  // Your own access check: may this caller do this action to this reference?
522
549
  // `resource.reference` is your own order id, sent back by the payer's
523
550
  // browser — a claim, not proof — already validated as a non-empty string.
524
- // `native` is the untouched Fastify request, so a session decorated by
525
- // @fastify/session (or whatever this app uses) is readable here too.
526
- authorize: async ({ action, request, resource }) =>
551
+ // `native` is the untouched Fastify request: pass it to this app's own
552
+ // cookie and session helpers, and a session decorated by @fastify/session
553
+ // (or whatever this app uses) is readable on it. `request` is a Web
554
+ // Request, so a helper that reads `req.headers.cookie` finds nothing on it
555
+ // and every payer gets a 403.
556
+ authorize: async ({ action, native, resource }) =>
527
557
  orders.viewerMay(
528
- await sessions.currentUser(request),
558
+ await sessions.currentUser(native),
529
559
  resource.reference,
530
560
  action,
531
561
  ),
@@ -541,7 +571,7 @@ await app.register(openReceiveFastify, {
541
571
  ```
542
572
 
543
573
  Register the plugin after whichever plugin gives you sessions or auth
544
- decorations, because `authorize` sees the same request object. The plugin
574
+ decorations, because `native` is that same request object. The plugin
545
575
  handles shutdown for you. It registers an `onClose` hook that closes the
546
576
  wallet client together with the app, so you have no `ready`/`close` pair to
547
577
  manage. A deploy health check awaits `fastify.ready()` instead.
@@ -3,7 +3,7 @@ This is the full file; follow it from Step 0.
3
3
  # OpenReceive agent directions (Laravel)
4
4
 
5
5
  ```sh
6
- # READ THIS FIRST: this file is 42 KB and a summary drops required steps. Download it whole:
6
+ # READ THIS FIRST: this file is 45 KB and a summary drops required steps. Download it whole:
7
7
  curl -fsSL https://openreceive.org/agent-directions/laravel/full.md
8
8
  # Skip the download only if you already have all of it: pasted, read from disk or fetched raw.
9
9
  ```
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/laravel/full.md
17
17
  - Do not suggest rotating or revoking a code because it was pasted here.
18
18
  - Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
19
19
 
20
- These directions describe OpenReceive 0.4.21.
20
+ These directions describe OpenReceive 0.4.23.
21
21
 
22
22
  Add OpenReceive to a Laravel application — the app you are already working in.
23
23
  You do not need a copy of the OpenReceive source: the package is on Packagist
@@ -59,11 +59,12 @@ owns orders, users, prices, or fulfillment.
59
59
 
60
60
  ## Step 0 — ask for the two codes, one question at a time
61
61
 
62
- Before anything else, look at one file: the project's `.env`, if it exists.
63
- Read it only far enough to see whether `NWC_URI` and `LSC_URI_PRIMARY` are
64
- there and non-empty, and never print the values. A code that is already
65
- set is not asked for again; if both are set, skip to step 5
66
- (making the server load the file), then the quickstart.
62
+ Before anything else, check one file: the project's `.env`, if it exists.
63
+ `grep -E '^(NWC_URI|LSC_URI_PRIMARY)=.' .env | cut -d= -f1` names the codes
64
+ it sets without printing them. Check with that, here and after each write,
65
+ not by reading the file, and never print the values. A code that is already
66
+ set is not asked for again; if both are set, skip to step 5 (making the
67
+ server load the file), then the quickstart.
67
68
 
68
69
  Otherwise your next action is a question to the user. Do not install the package,
69
70
  edit the app, write `.env.example`, or search anywhere else before asking
@@ -94,14 +95,17 @@ you store it. Ask one question per message.
94
95
  Do not mention `.env`, exports, or "tell me when it's set".
95
96
  2. **When they paste it.** If it does not start with `nostr+walletconnect://`,
96
97
  ask them to copy the receive-only code again. Otherwise write
97
- `NWC_URI=<paste>` into the project's `.env`, creating the file if needed.
98
- Make sure `.gitignore` covers `.env` (and `.dockerignore`, if the app has
99
- one). Never echo the value, commit it, or put it in client code. Reply only
100
- that it is saved, then ask the next question.
101
- 3. **Second message — swaps.** If the user already asked for stablecoins or
102
- altcoins, skip the yes/no and go straight to the walkthrough. Otherwise ask
103
- whether payers should also be able to pay with USDT, USDC, ETH or SOL. The
104
- walkthrough:
98
+ `NWC_URI=<paste>` into the project's `.env` with your file-editing tool,
99
+ creating the file if needed. Never write it with a shell command (`echo`,
100
+ `printf`, a heredoc, `python -c`): the command line shows the code. Make
101
+ sure `.gitignore` covers `.env` (and `.dockerignore`, if the app has one).
102
+ Never echo the value, commit it, or put it in client code. Reply only that
103
+ it is saved, then ask the next question.
104
+ 3. **Second message — swaps.** If the user asked for stablecoins, USDT, USDC,
105
+ ETH, SOL, altcoins or "crypto" (as in "Bitcoin and stablecoin payments"),
106
+ this message IS the walkthrough below: send it as it is, and do not ask yes
107
+ or no first. Otherwise ask whether payers should also be able to pay with
108
+ USDT, USDC, ETH or SOL, then give the walkthrough. The walkthrough:
105
109
 
106
110
  > Go to https://lightning-swap.com, sign in for API keys, create a key, and
107
111
  > copy the whole URI (https://openreceive.org/set_up_swap_provider). Paste
@@ -111,16 +115,21 @@ you store it. Ask one question per message.
111
115
  Mention FixedFloat only if they already use it.
112
116
  4. **When they paste it.** If it does not start with
113
117
  `lightning+swapconnect://`, ask them to copy it again. Otherwise add
114
- `LSC_URI_PRIMARY=<paste>` to the same `.env`, without echoing it. Swaps
115
- are now on, so build the refund route back (the swap non-negotiable below) as
116
- part of this integration. If they chose Bitcoin only, leave
117
- `LSC_URI_PRIMARY` unset and skip that route.
118
+ `LSC_URI_PRIMARY=<paste>` to the same `.env` with the file-editing tool,
119
+ never a shell command. Swaps are now on, so build the refund route back
120
+ (the swap non-negotiable below) as part of this integration. If they chose
121
+ Bitcoin only, leave `LSC_URI_PRIMARY` unset and skip that route.
118
122
  5. **Make the server load the file — yourself.** Laravel loads
119
123
  `.env` itself. If the app runs `php artisan config:cache`, run
120
124
  `php artisan config:clear` (or re-cache) after writing the file: a cached
121
125
  config never reads `.env` again. When the app is started with Docker
122
- Compose, give the service `env_file: .env`. Restart the server after
123
- writing the file.
126
+ Compose, give the service `env_file: .env`. A Compose variable reaches
127
+ artisan commands, but not the web server: `php artisan serve` hands
128
+ requests only what `.env` holds, and php-fpm clears the environment by
129
+ default. So make the running app read the codes too: keep them in the
130
+ `.env` the server reads (an image that copies `.env.example` over it
131
+ drops them), start `php artisan serve` with `--no-reload`, or set
132
+ `clear_env = no` for php-fpm. Restart the server after writing the file.
124
133
 
125
134
  Do not invent placeholder URIs. Start the quickstart only once `NWC_URI` is
126
135
  saved and `LSC_URI_PRIMARY` is saved or explicitly declined. The first boot
@@ -151,22 +160,28 @@ check; fix it before going on.
151
160
 
152
161
  Give the user that checkout link. The browser check in the quickstart's
153
162
  "Render the checkout" section (payment-method icons, wallet logos, a pay
154
- tutorial) is theirs: tell them what to look at, and do not run it yourself.
163
+ tutorial) is theirs: name it in one line of your closing message, and do not
164
+ run it yourself.
155
165
 
156
166
  You cannot pay the invoice: the code is receive-only. Do not pay, settle or
157
167
  mark an order paid, and do not look for a way to (a wallet control port, a
158
168
  test endpoint, another wallet). If the user wants a real settlement test, they
159
169
  pay on that link from their own wallet, and `onPaid` marks the order paid.
160
170
 
161
- Setup ends here. Say "Setup is finished" in one message of at most five
162
- lines, with the link and what to check. Do not list what changed, offer more
163
- work, or end the message on a question.
171
+ Setup ends here. Your last message starts "Setup is finished" and has at most
172
+ five short lines (about 80 characters each): the link, the methods it offers,
173
+ and one line of what to look at. Send nothing after it. Do not list what
174
+ changed, copy out the quickstart's browser checklist, offer more work, or end
175
+ the message on a question.
164
176
 
165
177
  - The link is to a real unpaid order. Keep that order; do not delete it.
178
+ - When this app's orders belong to a session or cookie, the user's browser
179
+ cannot open the order you made. Then the link is the shop's own page:
180
+ "Open <shop url> and click Buy: it opens the checkout." Do not explain order
181
+ ownership or mention your test order.
166
182
  - Name the methods it offers: Bitcoin, plus USDT, USDC, ETH and SOL when
167
- `LSC_URI_PRIMARY` is saved. Never say a coin will not work or will not be
168
- offered. Swap minimums apply per order, and a coin whose minimum is above an
169
- order's total says so on its own tile.
183
+ `LSC_URI_PRIMARY` is saved. Do not mention minimums, and never say a coin
184
+ will not work or will not be offered.
170
185
 
171
186
  ## Non-negotiables
172
187
 
@@ -183,6 +198,22 @@ itself, and they hold for every integration.
183
198
  - Work only in this application. Never read or run anything from another
184
199
  project on this machine (its `node_modules`, tools or source), for any
185
200
  reason. A browser and Playwright are not part of setup.
201
+ - Restart only this app's server, on the port it already uses: stop the
202
+ process you started, or the one listening on that port, by its pid (or
203
+ restart its Compose service). Never `pkill` or `killall` by name: that
204
+ stops other people's servers too. Start it the way this project already
205
+ does (its README, Procfile, compose file or package script), on its own
206
+ port, not a port you pick.
207
+ - Run commands where the app runs. When a compose file builds it, run its
208
+ package manager, generators, migrations and doctor inside that service
209
+ (`docker compose exec` or `run`), and rebuild the image after adding a
210
+ package. This machine's language version and database path are not the
211
+ app's.
212
+ - To check that the running app sees the codes, run doctor: it reports each
213
+ one as present or missing and never prints a value. Never print the
214
+ environment (`printenv`, `env`, `docker compose config`), even filtered to
215
+ names. Doctor runs as an artisan command, so also open the checkout page:
216
+ the web server can miss a code that doctor sees (step 5).
186
217
  - The host owns the price. `amountFor` reads it from your own data; reject
187
218
  payer-supplied amounts.
188
219
  - `authorize` runs on every request, and the `resource` it receives is a CLAIM
@@ -386,16 +417,34 @@ PHP extensions:
386
417
  `pdo_sqlite`).
387
418
 
388
419
  `php -m` lists what your build has. To add gmp on Debian/Ubuntu, run
389
- `apt-get install php8.2-gmp`. In the official Docker image, run
390
- `docker-php-ext-install gmp`.
420
+ `apt-get install php8.2-gmp`. The official `php` Docker images do not ship
421
+ it, and `docker-php-ext-install gmp` alone fails without the GMP headers. Add
422
+ both to the Dockerfile, before the step that installs the app's Composer
423
+ packages, and rebuild the image:
424
+
425
+ ```dockerfile
426
+ RUN apt-get update && apt-get install -y --no-install-recommends libgmp-dev \
427
+ && docker-php-ext-install gmp \
428
+ && rm -rf /var/lib/apt/lists/*
429
+ ```
430
+
431
+ Run `composer require` with a PHP that has gmp. On a machine without one,
432
+ use the rebuilt image with the project mounted, then rebuild again so the
433
+ image installs the new lock:
434
+ `docker compose run --rm --no-deps -v "$PWD":/app web composer require openreceive/laravel -W`.
435
+ Never pass `--ignore-platform-req=ext-gmp` or `--ignore-platform-reqs`:
436
+ Composer then installs a package that fails as soon as it talks to the
437
+ wallet.
391
438
 
392
439
  Add the Laravel package:
393
440
 
394
441
  ```sh
395
- composer require openreceive/laravel
442
+ composer require openreceive/laravel -W
396
443
  ```
397
444
 
398
- That is the whole install. `openreceive/laravel` depends on
445
+ `-W` lets Composer move Guzzle to 7.x: the wallet client's WebSocket
446
+ middleware needs Guzzle 7, and a Laravel 13 app can lock Guzzle 8. That is
447
+ the whole install. `openreceive/laravel` depends on
399
448
  `openreceive/openreceive`, the engine. So the default wallet client works with
400
449
  nothing else added. It is built from `NWC_URI`. Package discovery registers the
401
450
  service provider. If your app brings its own NWC client, bind