Repository navigation
Quote a batch without an intent and report account economics - #375
Merged
Merged
Conversation
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
marked this pull request as ready for review
October 5, 2026 08:48
added 2 commits
October 5, 2026 11:21
…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
marked this pull request as draft
October 5, 2026 11:02
added 2 commits
October 5, 2026 13:05
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
marked this pull request as ready for review
October 5, 2026 11:31
ctfbruce
marked this pull request as draft
October 5, 2026 12:04
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.
ctfbruce
marked this pull request as ready for review
October 5, 2026 12:34
added 2 commits
October 5, 2026 15:47
ctfbruce
marked this pull request as draft
October 5, 2026 14:02
ctfbruce
marked this pull request as ready for review
October 5, 2026 14:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Behaviour
POST /payment/quotetakes the body ofPUT /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.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 /megainseconomics: the payment methods admitted now, whether chain payments are enabled and whether usage allowances are offered (not yet).GET /me/orderspages 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.QuoteandOrders, andWhoamireturns the new field. Scoped credentials:measurements:readquotes,account:readreads the history.Proof
quoteequals 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;/meeconomics; 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
requiredsucceeded. Run 37289538171 on 7717bca (the branch with #373's corrected head merged forward): 16 of 16 lanes andrequiredsucceeded. Correction 97b85f4: a quote and an intent now report an out-of-rangestart_timeand a policy the executor cannot currently serve (for examplerequire_icmpwithout 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'sQuotedescription no longer refers to a price the high-level submission does not return. Run 37302452972 on 97b85f4: 16 of 16 lanes andrequiredsucceeded. 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 andrequiredsucceeded.