openreceive-rails 0.4.13 → 0.4.14

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c17784f21721177e139d27349d7fa0367f2e6f90cce005e5dd61906ac5fae96a
4
- data.tar.gz: f285c9fb57805628956740699f078115672f1485916784fbc2e4b6d8738b1578
3
+ metadata.gz: e427ecbaa9d1cbb7007ea7799ff14eeef1a88b5e9b354d79dc9ad1c2d1fc4c53
4
+ data.tar.gz: e5a92ea94f6edb67a171c03d1bd1367bd66973d672bfd9cdf4f6eb16a52c9307
5
5
  SHA512:
6
- metadata.gz: 16634ea35e356230c34b4da9ecf58bc8c089835d1b919692e41ddda40ef127fbddc23e5aa3090ba62835f90ba23b393d562a9006df015cbb5a84c2c16ec0ee35
7
- data.tar.gz: 5d70f67f044bfa1003fb963da3e3e8ffe620f27517662d8fd1199ae0972906c7fcc1172196b8b8704d9c4354485700e2732dcf7d99ea818772cb19999a045296
6
+ metadata.gz: 2c2a061b4ce15de084a423ee8f440e4bcaf6ac2ce0b156855daae25492ac1df0a51d788739e3008c81c08faeb924cdb8faa83c1ca7f6e1b29e3919b0a139b93f
7
+ data.tar.gz: 933f003c11889f222970ca79353b04a468b9076f82466a6d3f9f76790b0b9d267c483b135f81852ddeb03f0c0e79e2dcf60291e09cab6c699dc2b8cef087c737
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.14 - 2026-10-04
4
+
5
+ Fixes two 0.4.13 reconciliation regressions. A host-clock attempt could be
6
+ skipped indefinitely: with one scan-window slot taken, selection moved its
7
+ cursor past the whole batch and dropped the batch's host-clock attempts. The
8
+ cursor now moves only past attempts it has queued. And a wallet that answers
9
+ only one history page per slice re-read the same overlap page forever; an
10
+ overlap answered alone is now spent, and the next slice reads the unseen page
11
+ first. Both are pinned by new `reconcile-progress.json` vectors. The bundled
12
+ integration skill also documents the plain-HTML checkout's way back to a swap
13
+ refund (`resume-payment-hash`, `resumable`, the `openreceive-state` event).
14
+
3
15
  ## 0.4.13 - 2026-10-01
4
16
 
5
17
  Reconciliation no longer livelocks on a slow wallet. A wallet-history page
@@ -5,6 +5,6 @@ module OpenReceive
5
5
  # top-level `::Rails` framework constant — engine code always references the framework as
6
6
  # `::Rails` to avoid shadowing.
7
7
  module Rails
8
- VERSION = "0.4.13"
8
+ VERSION = "0.4.14"
9
9
  end
10
10
  end
@@ -82,15 +82,29 @@ module OpenReceive
82
82
  candidates = OpenReceivePayment.reconcilable_attempts
83
83
  end
84
84
  unless candidates.empty?
85
- last = candidates.last
86
- scheduler["cursor"] = candidates.length < Server::RECONCILE_BATCH_SIZE ? nil : last.slice("created_at", "payment_hash")
87
85
  queued = windows.flat_map { |w| w.fetch("attempts").map { |a| a.fetch("payment_hash") } }
88
- cohort = candidates.reject { |a| queued.include?(a.fetch("payment_hash")) }
89
86
  # A host-clock attempt's window spans the whole wallet history. It
90
87
  # gets its own window, so it never drags wallet-timed attempts into
91
- # that walk; one the cap leaves out returns on cursor wrap.
92
- cohort.partition { |a| a["created_at_source"] == "wallet" }.each do |group|
93
- windows << ReconcileScan.new_window(group, observed_at, overlap_seconds) unless group.empty? || windows.length >= 2
88
+ # that walk. Candidates are taken in keyset order, and the cursor
89
+ # moves only past those already queued or admitted: one whose clock
90
+ # source has no free slot stops the selection and is read again next
91
+ # time, never skipped.
92
+ cohorts = {}
93
+ taken = 0
94
+ candidates.each do |attempt|
95
+ unless queued.include?(attempt.fetch("payment_hash"))
96
+ wallet = attempt["created_at_source"] == "wallet"
97
+ break if !cohorts.key?(wallet) && windows.length + cohorts.length >= 2
98
+
99
+ (cohorts[wallet] ||= []) << attempt
100
+ end
101
+ taken += 1
102
+ end
103
+ # A short batch taken whole already reached the ledger's tail: wrap now.
104
+ tail = taken == candidates.length && candidates.length < Server::RECONCILE_BATCH_SIZE
105
+ scheduler["cursor"] = tail ? nil : candidates[taken - 1].slice("created_at", "payment_hash")
106
+ [true, false].each do |wallet|
107
+ windows << ReconcileScan.new_window(cohorts[wallet], observed_at, overlap_seconds) if cohorts.key?(wallet)
94
108
  end
95
109
  end
96
110
  end
@@ -27,6 +27,15 @@ module OpenReceive
27
27
  anchor = resumed ? window["anchor_offset"] : nil
28
28
  replaying = !anchor.nil?
29
29
  previous = window["fingerprint"]
30
+ # The last answered page was the overlap re-read. A slice that ends here
31
+ # spends the overlap, so the next slice reads the unseen page first: a
32
+ # wallet answering one page per slice still advances. The fingerprint
33
+ # stays, to catch a wallet that ignores offset.
34
+ overlap_only = false
35
+ continued = lambda do
36
+ window["anchor_offset"] = nil if overlap_only
37
+ [results.values, false, false]
38
+ end
30
39
  max_pages.times do |page_number|
31
40
  break if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
32
41
 
@@ -47,9 +56,11 @@ module OpenReceive
47
56
  # that never answers stays visible.
48
57
  raise if page_number.zero? || Process.clock_gettime(Process::CLOCK_MONOTONIC) < deadline
49
58
 
50
- return [results.values, false, false]
59
+ return continued.call
51
60
  end
52
- return [results.values, false, false] if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
61
+ return continued.call if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
62
+
63
+ overlap_only = false
53
64
 
54
65
  rows = page.fetch("transactions")
55
66
  physical = rows.length + page.fetch("skipped_rows", 0)
@@ -73,6 +84,7 @@ module OpenReceive
73
84
  unless physical.zero?
74
85
  window["anchor_offset"] = offset
75
86
  window["fingerprint"] = fingerprint
87
+ overlap_only = true
76
88
  next
77
89
  end
78
90
  end
@@ -100,7 +112,7 @@ module OpenReceive
100
112
  previous = fingerprint
101
113
  return [results.values, true, false] if expected.all? { |hash| %w[settled expired failed].include?(window.fetch("observations").dig(hash, "status")) }
102
114
  end
103
- [results.values, false, false]
115
+ continued.call
104
116
  end
105
117
  end
106
118
  end
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (BTCPay Server)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Connect a BTCPay Server store to a receive-only NWC wallet with the OpenReceive
6
6
  plugin, and optionally let payers pay BTCPay invoices with USDT, USDC, ETH or
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Django)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Django project — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the Python package is on PyPI
@@ -167,15 +167,19 @@ itself, and they hold for every integration.
167
167
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
168
168
  after leaving your page to fetch an address from another wallet. Three things
169
169
  must exist or that money is unreachable through your UI: a per-order URL your
170
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
171
- order-summary route to restore the order from, and the ATTEMPT.
170
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
171
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
172
+ restore the order from, and the ATTEMPT.
172
173
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
173
174
  reference alone opens on the method grid. Re-picking the same coin
174
175
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
175
176
  and the shadow invoice behind a swap lasts about half an hour, after which the
176
177
  same click mints a NEW deposit address and the refund is off-screen. Keep the
177
178
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
178
- such window. https://openreceive.org/guides/swap-refunds.md
179
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
180
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
181
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
182
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
179
183
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
180
184
  the price from `amount_for` and both drop-ins render it above the
181
185
  amount. Without it the checkout is a QR and "$1.00" with no sign of what the
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (FastAPI)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a FastAPI application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the engine is on PyPI
@@ -157,15 +157,19 @@ itself, and they hold for every integration.
157
157
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
158
158
  after leaving your page to fetch an address from another wallet. Three things
159
159
  must exist or that money is unreachable through your UI: a per-order URL your
160
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
161
- order-summary route to restore the order from, and the ATTEMPT.
160
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
161
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
162
+ restore the order from, and the ATTEMPT.
162
163
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
163
164
  reference alone opens on the method grid. Re-picking the same coin
164
165
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
165
166
  and the shadow invoice behind a swap lasts about half an hour, after which the
166
167
  same click mints a NEW deposit address and the refund is off-screen. Keep the
167
168
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
168
- such window. https://openreceive.org/guides/swap-refunds.md
169
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
170
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
171
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
172
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
169
173
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
170
174
  the price from `amount_for` and both drop-ins render it above the amount.
171
175
  Without it the checkout is a QR and "$1.00" with no sign of what the dollar
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Fastify)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Fastify application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the packages are on npm, and
@@ -149,15 +149,19 @@ itself, and they hold for every integration.
149
149
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
150
150
  after leaving your page to fetch an address from another wallet. Three things
151
151
  must exist or that money is unreachable through your UI: a per-order URL your
152
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
153
- order-summary route to restore the order from, and the ATTEMPT.
152
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
153
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
154
+ restore the order from, and the ATTEMPT.
154
155
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
155
156
  reference alone opens on the method grid. Re-picking the same coin
156
157
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
157
158
  and the shadow invoice behind a swap lasts about half an hour, after which the
158
159
  same click mints a NEW deposit address and the refund is off-screen. Keep the
159
160
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
160
- such window. https://openreceive.org/guides/swap-refunds.md
161
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
162
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
163
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
164
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
161
165
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
162
166
  the price from `amountFor` and both drop-ins render it above the amount.
163
167
  Without it the checkout is a QR and "$1.00" with no sign of what the dollar
@@ -375,7 +379,9 @@ there is nothing else to generate. Details:
375
379
  No ORM? You can pass a bare driver handle (`pg`, `node:sqlite`,
376
380
  `better-sqlite3`) as the `db` in step 4. The scaffold has no flavor for it.
377
381
  Instead of scaffolding, run the same DDL once yourself, using
378
- `paymentsSchemaSql(dialect)` from `@openreceive/http`.
382
+ `paymentsSchemaSql(dialect)` from `@openreceive/http`. Your adapter already
383
+ pulls that package in, but this import is yours, so install it too:
384
+ `npm install @openreceive/http`.
379
385
 
380
386
  ### 3. Add wallet credentials
381
387
 
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Laravel)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Laravel application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the package is on Packagist
@@ -158,15 +158,19 @@ itself, and they hold for every integration.
158
158
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
159
159
  after leaving your page to fetch an address from another wallet. Three things
160
160
  must exist or that money is unreachable through your UI: a per-order URL your
161
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
162
- order-summary route to restore the order from, and the ATTEMPT.
161
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
162
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
163
+ restore the order from, and the ATTEMPT.
163
164
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
164
165
  reference alone opens on the method grid. Re-picking the same coin
165
166
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
166
167
  and the shadow invoice behind a swap lasts about half an hour, after which the
167
168
  same click mints a NEW deposit address and the refund is off-screen. Keep the
168
169
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
169
- such window. https://openreceive.org/guides/swap-refunds.md
170
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
171
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
172
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
173
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
170
174
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
171
175
  the price from `amountFor` and both drop-ins render it above the
172
176
  amount. Without it the checkout is a QR and "$1.00" with no sign of what the
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Next.js)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Next.js App Router application — the app you are already
6
6
  working in. You do not need a copy of the OpenReceive source: the packages are
@@ -149,15 +149,19 @@ itself, and they hold for every integration.
149
149
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
150
150
  after leaving your page to fetch an address from another wallet. Three things
151
151
  must exist or that money is unreachable through your UI: a per-order URL your
152
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
153
- order-summary route to restore the order from, and the ATTEMPT.
152
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
153
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
154
+ restore the order from, and the ATTEMPT.
154
155
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
155
156
  reference alone opens on the method grid. Re-picking the same coin
156
157
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
157
158
  and the shadow invoice behind a swap lasts about half an hour, after which the
158
159
  same click mints a NEW deposit address and the refund is off-screen. Keep the
159
160
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
160
- such window. https://openreceive.org/guides/swap-refunds.md
161
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
162
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
163
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
164
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
161
165
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
162
166
  the price from `amountFor` and both drop-ins render it above the amount.
163
167
  Without it the checkout is a QR and "$1.00" with no sign of what the dollar
@@ -381,7 +385,9 @@ there is nothing else to generate. Details:
381
385
  No ORM? You can pass a bare driver handle (`pg`, `node:sqlite`,
382
386
  `better-sqlite3`) as the `db` in step 4. The scaffold has no flavor for it.
383
387
  Instead of scaffolding, run the same DDL once yourself, using
384
- `paymentsSchemaSql(dialect)` from `@openreceive/http`.
388
+ `paymentsSchemaSql(dialect)` from `@openreceive/http`. Your adapter already
389
+ pulls that package in, but this import is yours, so install it too:
390
+ `npm install @openreceive/http`.
385
391
 
386
392
  ### 3. Add wallet credentials
387
393
 
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Node.js)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Node application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the packages are on npm, and the
@@ -146,15 +146,19 @@ itself, and they hold for every integration.
146
146
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
147
147
  after leaving your page to fetch an address from another wallet. Three things
148
148
  must exist or that money is unreachable through your UI: a per-order URL your
149
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
150
- order-summary route to restore the order from, and the ATTEMPT.
149
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
150
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
151
+ restore the order from, and the ATTEMPT.
151
152
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
152
153
  reference alone opens on the method grid. Re-picking the same coin
153
154
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
154
155
  and the shadow invoice behind a swap lasts about half an hour, after which the
155
156
  same click mints a NEW deposit address and the refund is off-screen. Keep the
156
157
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
157
- such window. https://openreceive.org/guides/swap-refunds.md
158
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
159
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
160
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
161
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
158
162
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
159
163
  the price from `amountFor` and both drop-ins render it above the amount.
160
164
  Without it the checkout is a QR and "$1.00" with no sign of what the dollar
@@ -366,7 +370,9 @@ there is nothing else to generate. Details:
366
370
  No ORM? You can pass a bare driver handle (`pg`, `node:sqlite`,
367
371
  `better-sqlite3`) as the `db` in step 4. The scaffold has no flavor for it.
368
372
  Instead of scaffolding, run the same DDL once yourself, using
369
- `paymentsSchemaSql(dialect)` from `@openreceive/http`.
373
+ `paymentsSchemaSql(dialect)` from `@openreceive/http`. Your adapter already
374
+ pulls that package in, but this import is yours, so install it too:
375
+ `npm install @openreceive/http`.
370
376
 
371
377
  ### 3. Add wallet credentials
372
378
 
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (PHP)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a PHP application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the engine is on Packagist
@@ -171,7 +171,9 @@ itself, and they hold for every integration.
171
171
  and the shadow invoice behind a swap lasts about half an hour, after which the
172
172
  same click mints a NEW deposit address and the refund is off-screen. Keep the
173
173
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
174
- such window. https://openreceive.org/guides/swap-refunds.md
174
+ such window. On the element: the `resume-payment-hash` attribute, fed from
175
+ the `openreceive-state` event (`event.detail.state.payment_hash`).
176
+ https://openreceive.org/guides/swap-refunds.md
175
177
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
176
178
  the price from `amountFor` and the drop-in renders it above the amount.
177
179
  Without it the checkout is a QR and "$1.00" with no sign of what the dollar
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Rails)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Add OpenReceive to a Rails application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the gem is on RubyGems, the
@@ -153,15 +153,19 @@ itself, and they hold for every integration.
153
153
  late becomes `refund_required`, and the payer claims it on a SECOND VISIT,
154
154
  after leaving your page to fetch an address from another wallet. Three things
155
155
  must exist or that money is unreachable through your UI: a per-order URL your
156
- server serves (`/checkout/:reference` — `syncUrl` on the drop-ins), your own
157
- order-summary route to restore the order from, and the ATTEMPT.
156
+ server serves (`/checkout/:reference` — `syncUrl` on `<Checkout>`, `sync-url`
157
+ or `resumable` on `<openreceive-checkout>`), your own order-summary route to
158
+ restore the order from, and the ATTEMPT.
158
159
  `/checkouts/prepare` returns no attempts, so a checkout rebuilt from the
159
160
  reference alone opens on the method grid. Re-picking the same coin
160
161
  (`POST /swaps`) re-serves the committed attempt — but only while it is live,
161
162
  and the shadow invoice behind a swap lasts about half an hour, after which the
162
163
  same click mints a NEW deposit address and the refund is off-screen. Keep the
163
164
  `payment_hash` and reopen the attempt with `POST /swaps/status`, which has no
164
- such window. https://openreceive.org/guides/swap-refunds.md
165
+ such window. On the drop-ins: `resumePaymentHash`, fed from `onState`, on
166
+ `<Checkout>`; the `resume-payment-hash` attribute, fed from the
167
+ `openreceive-state` event (`event.detail.state.payment_hash`), on
168
+ `<openreceive-checkout>`. https://openreceive.org/guides/swap-refunds.md
165
169
  - Show the payer WHAT THEY ARE BUYING. Return an optional `description` beside
166
170
  the price from `config.amount_for` and both drop-ins render it above the
167
171
  amount. Without it the checkout is a QR and "$1.00" with no sign of what the
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (WordPress + WooCommerce)
2
2
 
3
- These directions describe OpenReceive 0.4.13.
3
+ These directions describe OpenReceive 0.4.14.
4
4
 
5
5
  Install and configure the OpenReceive gateway in the existing WooCommerce
6
6
  store. Preserve its theme, checkout, customer accounts, order model and prices.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openreceive-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.13
4
+ version: 0.4.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenReceive
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.4.13
18
+ version: 0.4.14
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.4.13
25
+ version: 0.4.14
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: openreceive-server
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 0.4.13
32
+ version: 0.4.14
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 0.4.13
39
+ version: 0.4.14
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rails
42
42
  requirement: !ruby/object:Gem::Requirement