feat: implement Stellar sequence number management#52
Conversation
DeFiVC
left a comment
There was a problem hiding this comment.
PR Review: feat: implement Stellar sequence number management
Author: Joeloo1 (Agboola Joel) | Closes: #8 | State: OPEN | Mergeable: MERGEABLE (BLOCKED by CI)
Review Checklist
| Item | Status |
|---|---|
| Git Identity | ✅ DeFiVC defivc1@email.com |
| Linked Issue | ✅ Closes #8 — matches requirements |
| Code Quality | |
| CI Status | ❌ Lint failure (2 errors) |
| Merge Conflicts | ✅ None |
Blocking Issues
❌ CI Lint Failure — 2 errors in src/modules/rewards/reward.service.ts:
- Line 86:
catch (e) {}— Empty block statement (no-empty) - Line 208:
catch (e) {}— Empty block statement (no-empty)
These are the catch (e) {} blocks in the bad_seq error handling where the account sequence is fetched. The empty catch blocks must be fixed — either remove the unused variable and add a comment explaining why the error is intentionally swallowed, or handle it properly.
Code Issues
1. Duplicated bad_seq handling — src/modules/rewards/reward.service.ts:80-88 and src/modules/rewards/reward.service.ts:200-212
The same error handling logic appears twice. Extract this into a helper function to reduce duplication.
2. Sequence cache initial value discrepancy — src/stellar/sequence-cache.ts:8-14
The first call returns the current sequence number (seq), but subsequent calls return seq + 1. The issue spec says getNextSequence should return the next sequence number. Fix: change return seq.toString() to return (seq + 1n).toString() on line 12.
Minor Nits
- Tests don't cover retry logic —
tests/unit/stellar-sequence.test.tsonly tests theSequenceCacheandwithAccountLockutilities, not the actual retry logic ininvokeContract/sendPayment. Consider adding integration-style tests that verify the retry behavior.
What's Good
- Excellent implementation of the sequence number cache with proper atomic locking
- Account-level serialization via
async-lockprevents race conditions - Retry logic with cache invalidation on
bad_seqerrors is well-designed - Good unit tests for the core cache and lock functionality
- Fixed
Object.setPrototypeOfinerrors.tsto usenew.target.prototype(correct ES6 pattern) - The
bad_seqhandling at the API level (settingtxHash = "pending_indexer_confirmation") is a pragmatic approach
- Fix empty catch block lint errors in reward.service.ts - Extract duplicated bad_seq handling into handleBadSeqError() helper - Fix sequence cache to consistently return next sequence number - Update tests to match corrected sequence cache behavior Resolves CI lint failures and code quality issues
- Import StellarError from utils/errors - Add explicit type annotation (err: unknown) to catch blocks - Split compound condition for proper TypeScript type narrowing
Update test to expect 'Invalid signature' instead of 'Signature verification failed' to match the actual error thrown by the auth service.
- Use importActual to preserve Horizon and rpc exports - Add missing STELLAR_HORIZON_URL and STELLAR_SOROBAN_RPC_URL to config mocks - Fixes concurrent-safety and process-reward-claim test failures
There was a problem hiding this comment.
PR Review: feat: implement Stellar sequence number management
Author: Joeloo1 | Closes: #8 | CI: ✅ Green | Conflicts: ✅ None
Blocking Issues
None. Previous lint failures (no-empty in catch blocks) have been resolved — CI passes fully.
Code Issues
None
Minor Nits
None.
What's Good
- Core design is solid: local in-memory sequence cache with atomic increment + per-account async-lock serialization correctly prevents the race condition described in #8
- Retry logic with cache invalidation in
transactions.tsis well-structured — 3 retries with fresh sequence from Horizon on each bad_seq - Concurrency test is excellent: verifies monotonic sequences, lock serialization (maxConcurrent=1), and single Horizon call across 10 concurrent transactions
- Good test updates: switched from full mock to
vi.importActualpattern, added config mocks, added dedicatedstellar-sequence.test.ts Object.setPrototypeOffix inerrors.tsusingnew.target.prototypeis the correct ES6 pattern for proper subclassing- Pragmatic
pending_indexer_confirmationapproach for bad_seq at the API level — acknowledges the tx may succeed on-chain without blocking the user
The sequence management, locking, and retry logic are well-implemented. The issues above are code quality improvements rather than functional bugs. Approving."
Closes #8