Skip to content

Quote a batch without an intent and report account economics - #375

Merged
ctfbruce merged 11 commits into
mainfrom
feat/quotes-and-economics
Oct 5, 2026
Merged

ctfbruce merged 11 commits into
mainfrom
feat/quotes-and-economics

Conversation

@ctfbruce

@ctfbruce ctfbruce commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Behaviour

  • POST /payment/quote takes the body of PUT /payment/intent, under the same authentication and request quota, and prices it with the single pricing function the intent uses. It writes nothing: no transaction, order, auth key, run or retry row, and no capacity is reserved. A batch the intent would refuse is still answered 200 with every problem on the order it concerns (field errors in the existing shape) and no total; a malformed body, an unsupported method, a chain method while blockchain payments are disabled and a missing credential keep the intent's status.
  • The intent response gains quote, the stored prices in the same shape, so a client can compare an earlier quote with what was charged; both carry the pricing rule's name (bw-s-ceil-ms-v1).
  • GET /me gains economics: the payment methods admitted now, whether chain payments are enabled and whether usage allowances are offered (not yet).
  • GET /me/orders pages the caller's own intents, newest first, with their orders, settlement (pending, credited, refunded, as run details report it) and the admitted run; another account's intents are never listed, and a foreign cursor yields an empty page.
  • API contract 1.15; the Go client gains Quote and Orders, and Whoami returns the new field. Scoped credentials: measurements:read quotes, account:read reads the history.

Proof

  • Real-SQLite tests: a quote writes nothing (row counts of five tables unchanged in the serving connection and in the reopened file; no transaction id or auth key in the body); the intent's quote equals the earlier quote and the stored prices; every problem of a six-order batch is reported on its order while the intent stops at the first; the kept refusals; /me economics; history paging with ownership and a foreign cursor; the client's body, version requirement and decoding; the access matrix and the contract-exercise test extended; the generated bindings match the pinned generator.

Limits

GitHub issues #214 and #215.

Candidate CI

Run 37284748943 on c0b3876: 16 of 16 lanes and required succeeded. Run 37289538171 on 7717bca (the branch with #373's corrected head merged forward): 16 of 16 lanes and required succeeded. Correction 97b85f4: a quote and an intent now report an out-of-range start_time and a policy the executor cannot currently serve (for example require_icmp without ICMP) as per-order field errors, through the same checks the submission applies, so a clean quote no longer promises admission for a request already known to be invalid; the quote still reserves nothing and the submission still validates again; the Go client's Quote description no longer refers to a price the high-level submission does not return. Run 37302452972 on 97b85f4: 16 of 16 lanes and required succeeded. The branch then took the receipts branch (be51d25, run 37307041399 green) and the payout branch with the corrected adapter (55daed3), so that the composed tree builds its tests against the payment handler constructor that reports a configuration error; Run 37308476427 on 55daed3: 16 of 16 lanes and required succeeded.

A client could only learn a batch's price by creating a payment intent,
and could not see which payment features a dispatcher offers or page its
own intents. POST /payment/quote prices a batch with the same function
the intent uses and stops there: it writes nothing and issues no auth
key; a batch the intent would refuse is quoted with every problem on the
order it concerns and no total. The intent response carries the same
quote of the prices it stored, so a client can compare the two exactly.
GET /me reports the payment methods admitted now, whether chain payments
are enabled and whether allowances are offered; GET /me/orders pages the
account's intents with their orders, settlements and admitted runs. The
API contract moves to 1.15 and the Go client gains Quote and Orders.

GitHub issues #214 and #215.
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 08:48
@ctfbruce ctfbruce added the Review Implementation is ready for review and required validation. label Oct 5, 2026
TheodorAdrienIsaak Mattli added 2 commits October 5, 2026 11:21
Brings in the maintenance pass that retries only local settlements and
scans pending orders fairly, so this branch builds on the same settlement
behaviour its order history reads.

GitHub issues #214 and #215.
…work

Compose the corrected receipts and transfers head with the corrected
Sui adapter head (prepared transfers with a persisted identity, coin
selection without repeated objects) as the base of the payout
reservation and refund change, which uses both.

GitHub issue #80.
Executor payouts zeroed the balance after the transfer, so earnings
credited in between were lost; refunds and payouts held a SQL
transaction across the chain call, and a transaction-wide refund wrote
order states unconditionally and refunded credited orders.

Give payouts and refunds one lifecycle: prepare the transfer (a chain
read), commit the local decision together with a reserved chain
transfer row carrying the digest, the signed transaction and its
signature, broadcast the signed transaction under a two-minute bound,
and record the outcome by a conditional write: sent, failed (a failed
payout releases its amount in the same write) or unknown. Reconcile
sent, unknown and stale reserved rows on the payout loop's ticker with
one lookup: confirmed with the expected effects, failed, or resubmitted
once from the identical stored bytes when the chain does not know the
transaction; anything unverified stays unknown. A payout reserves
exactly the balance it read and is refused while another is open;
refunds change the transaction status and each outstanding order
conditionally, with a refund settlement row, before the chain call.
The maintenance pass settles chain refunds of failed runs through the
same lifecycle and never selects an order with a refund transfer again.

GitHub issues #80 and #81.
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 11:02
@ctfbruce ctfbruce added In progress Implementation is active. and removed Review Implementation is ready for review and required validation. labels Oct 5, 2026
TheodorAdrienIsaak Mattli added 2 commits October 5, 2026 13:05
Bring the adapter branch at its corrected head, which validates a
listed coin's object id before normalizing it, under the payout and
refund lifecycle, so that the composed tree carries the correction the
transfer tests run against.

GitHub issues #80 and #81.
A quote priced an order whose start timestamp was impossible, or whose
policy required ICMP from an executor without it, without any error,
although the submission refuses both deterministically; the quote's
contract is to report every problem the dispatcher would report. Apply
the existing start-timestamp validation and the read-only capability
check in the pricing path, so that a quote and an intent report these
problems alike as per-order field errors; the quote still reserves
nothing and the submission still validates again. Correct the Go
client's description of Quote: the high-level submission does not
expose the intent's quote, so callers compare prices through the quote
itself or the raw intent response.

GitHub issues #214 and #215.
@ctfbruce ctfbruce added Review Implementation is ready for review and required validation. and removed In progress Implementation is active. labels Oct 5, 2026
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 11:31
Bring the receipts and transfers branch at its corrected head
(dispatcher schema 22) under the quotes and economics change, keeping
both version notes: the schema 22 paragraph and the API 1.15 paragraph
describe different boundaries and land on the same lines.

GitHub issues #214 and #215.
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 12:04
@ctfbruce ctfbruce added In progress Implementation is active. and removed Review Implementation is ready for review and required validation. labels Oct 5, 2026
TheodorAdrienIsaak Mattli added 2 commits October 5, 2026 14:08
After a refund decision was committed, the transfer lifecycle returned
no outcome to its caller, so a buyer refused during maintenance was told
the payment had been refunded even when the transfer failed or its
outcome was unknown, and later requests repeated it. Return the
recorded outcome and word the refusal as sent, pending confirmation, or
recorded but not sent and owed; a repeated request reads the refund
transfer's state. The order stays unspendable after the decision.

A reconciliation lookup ran under the daemon's lifetime context on an
SDK path with no deadline, so one lookup that never completed stopped
every later row and all payouts. Bound each lookup; a timeout is
recorded as an unknown outcome with the reservation kept, and the pass
continues with the next row.

GitHub issues #80 and #81.
Bring the payout and refund branch at its corrected head, which carries
the corrected adapter and the listener fixture built for its payment
handler constructor, under the quotes and economics change, so that the
composed tree builds and tests as one.

GitHub issues #214 and #215.
@ctfbruce ctfbruce added Review Implementation is ready for review and required validation. and removed In progress Implementation is active. labels Oct 5, 2026
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 12:34
TheodorAdrienIsaak Mattli added 2 commits October 5, 2026 15:47
Include the accepted runtime, deployment, monitoring and SDK updates alongside payout reservation and refund reconciliation.

GitHub issues #80 and #81.
Keep quote pricing and account economics together with the current payout recovery, runtime, deployment and SDK updates.

GitHub issues #214 and #215.
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 14:02
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 14:17
@ctfbruce
ctfbruce merged commit 0bbeed9 into main Oct 5, 2026
16 checks passed
@vincent10400094
vincent10400094 deleted the feat/quotes-and-economics branch October 8, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review Implementation is ready for review and required validation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant