Repository navigation
fix(batch): re-read a channel whose authorization is refused with a plain 402 - #91
Merged
Merged
Conversation
…lain 402 The chain was read only before a top-up, so a reclaimed channel whose record still had deposit to spare got an authorization signed into it on every call; the gateway refuses those at verify with a plain 402 (blockrun-sol src/lib/batch/payment.ts fail()) and every call paid exact, forever. On a first-send authorization answered not_charged / payment_required (no admission cooldown), recheckRefusedChannel() reads the channel: open and the wallet's → kept; closing/closed/foreign → channel_unusable re-read; gone at finalized and confirmed → queueReclaimed() (the anchored wait now shared with prepareTopUp). resync() runs at once, so one-call-per-run processes finish the wait. The scheme rewrites the record without reclaimAnchorHeight while it builds and settles a payment, so buildPayment() captures the saved anchor first and carries it on SentPayment. Tests: refused reclaimed channel waits then reopens; one call per process still drops it; a live channel refused for another reason is kept and paid into again; a closed channel is dropped with no wait. Three fail on main.
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.
Closes the known gap noted in 3.24.8 (and the P2 from the #90 review).
Problem
The SDK reads the channel on-chain only before a top-up. A reclaimed channel (PayAI closes channels idle for 72h) whose local record still has deposit to spare gets an authorization signed into it on every call. The gateway rejects it at verify and answers with a plain 402 with no receipt (
blockrun-solsrc/lib/batch/payment.ts,fail()). The SDK classifies that asnot_charged/payment_requiredand pays exact, so every later call pays exact (1.5–4.5×) until the channel file is deleted by hand.Change
payWith: when the first send of an authorization is refused with a plain 402 (payment_required, no admission cooldown), the newrecheckRefusedChannel()reads that channel:channel_unusablere-read (closed → record dropped)queueReclaimed(), the anchored wait from fix(batch): drop a reclaimed channel on the SDK's own chain evidence, not the 402's openSlot #90, now shared withprepareTopUp: exact for about 2 minutes, then the record is dropped and the next call opens a fresh channelresync()runs right away, so a process that makes one call per run still finishes the wait.reclaimAnchorHeightwhile it builds and settles a payment. SobuildPayment()reads the saved anchor first and carries it onSentPayment.reclaimAnchor. A test caught this: without it, every short-lived run started a new wait.Tests
getBlockHeight.npm test: 954 passed, 12 skipped. Build, lint and typecheck are clean.grep -c router-core dist/index.d.ts→ 0.Docs:
docs/solana-batch.md, CLAUDE.md batch section, CHANGELOG (Unreleased).