oor: add OOR_REJECT_USER_BALANCE typed reject code + classifier - #807
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new client-facing typed error, ErrUserBalanceExceeded, which is returned when an OOR submit is rejected due to a recipient's aggregate VTXO balance exceeding the operator's limit. It maps the new OOR_REJECT_USER_BALANCE rejection code in ClassifySubmitError, updates the protobuf definitions, and adds comprehensive unit tests. Feedback on the tests suggests replacing require.NotErrorIs with require.False and errors.Is to ensure compatibility with older versions of the testify library.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| require.NotErrorIs(t, balance, &ErrOutputPolicyViolation{}) | ||
| require.NotErrorIs(t, policy, &ErrUserBalanceExceeded{}) |
There was a problem hiding this comment.
The testify library does not standardly support NotErrorIs in many of its widely-used versions, which can lead to compilation failures depending on the project's testify dependency version. It is safer and more backward-compatible to use require.False with errors.Is instead.
| require.NotErrorIs(t, balance, &ErrOutputPolicyViolation{}) | |
| require.NotErrorIs(t, policy, &ErrUserBalanceExceeded{}) | |
| require.False(t, errors.Is(balance, &ErrOutputPolicyViolation{})) | |
| require.False(t, errors.Is(policy, &ErrUserBalanceExceeded{})) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3e00b43677
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case oorpb.OORRejectCode_OOR_REJECT_USER_BALANCE: | ||
| return &ErrUserBalanceExceeded{ | ||
| Reason: rejected.Reason, | ||
| } |
There was a problem hiding this comment.
Carry the balance reject code to callers
When arkd returns OOR_REJECT_USER_BALANCE on the async SubmitPackage response, the only production consumer I found (darepod/server.go's registerOOREventRoutes) calls this classifier and immediately flattens the result to classified.Error() in OutboxErrorEvent.ErrorReason; GetOORSession/ListOORSessions then expose only that string. That means swapdk/custodial callers still cannot route on the new transient code with errors.As or the enum without string-matching the failure reason, which is the recovery split this code is meant to provide. Please persist/expose the reject code (or a typed failure cause) through the session status/daemon API instead of only constructing a local typed error here.
Useful? React with 👍 / 👎.
|
@claude review this |
|
Claude finished @Roasbeef's task in 1m 30s —— View job PR Review:
|
In this commit, we append OOR_REJECT_USER_BALANCE to the out-of-round submit rejection enum. The new value gives the server a distinct wire code for recipient aggregate-balance rejections without changing any existing enum numbers. The generated Go bindings are refreshed in the same commit so clients can classify the new code without hand-editing generated files.
In this commit, we route OOR_REJECT_USER_BALANCE onto a dedicated ErrUserBalanceExceeded sentinel. This lets wallets and custodial senders distinguish a transient balance-limit rejection from a terminal output-policy rejection without parsing the reason string. The balance error documents that callers can retain value and retry once the recipient spends or refreshes below the operator limit. The classifier tests pin the mapping and assert that balance and output-policy errors do not alias each other.
3e00b43 to
744b4df
Compare
In this PR, we add a dedicated typed reject code for the operator's per-user
balance cap on the OOR path, plus the client-side classifier that routes it.
The arkd server rejects an OOR submit that would push a recipient mailbox
over its
MaxUserBalance, but until now it borrowedOOR_REJECT_OUTPUT_POLICYon the wire to avoid a proto change. That left a custodial sender (e.g.
swapdk) unable to tell a balance rejection from a per-VTXO policy rejection
without string-matching the reason, and the two want opposite recovery.
A per-VTXO policy rejection is permanent for a given output shape, so the
caller must restructure the outputs. A balance rejection is transient: it
clears once the recipient spends or refreshes its balance down, so a
custodian should retain the value and retry later rather than restructuring.
We add
OOR_REJECT_USER_BALANCEto theOORRejectCodeenum and teachClassifySubmitErrorto map it onto a new typedErrUserBalanceExceeded,documented as transient, so a wallet routes recovery on the code alone. A
classifier test pins the mapping and asserts the balance and output-policy
errors don't alias each other.
The arkd server side that emits this code (and the end-to-end itest) lives in
the darepo PR that bumps this submodule.