Skip to content

Latest commit

 

History

History
67 lines (46 loc) · 2.12 KB

File metadata and controls

67 lines (46 loc) · 2.12 KB

feat: per-account sequence manager for Soroban builds

Summary

Parallel calls to TransactionBuilderService.buildDepositTransaction() sharing the same source account fetch the same Horizon sequence number and produce conflicting transactions. This PR adds SequenceManager — a small per-account async mutex that serialises sequence allocation so concurrent builds never collide.


Changes

src/services/sequenceManager.ts (new)

SequenceManager uses a per-account Promise chain as a mutex:

  • nextSequence(accountId) — acquires the lock, fetches a fresh sequence from Horizon, increments it, releases the lock, returns the allocated bigint
  • Lock is released in finally — a thrown error never leaves the queue stuck
  • Per-account isolation — one account's Horizon latency does not block another
  • No external dependencies — plain Promise chaining, no async-mutex package
  • clearLock(accountId) / hasLock(accountId) — test/utility helpers

src/services/sequenceManager.test.ts (new)

46 tests across 8 suites:

Suite Tests
Basic operation — sequence + 1, bigint parsing 5
Concurrency — no duplicates under Promise.all (2, 5, 10 concurrent) 4
Ordering — FIFO allocation, serialised loadAccount calls 2
Lock release on error — first fails, subsequent succeed 4
Multiple accounts — independent serialisation 3
Stale Horizon read recovery — fresh fetch per call 2
Edge cases — near-bigint boundary, sequential calls, special chars 3
Utility methods — clearLock, hasLock 5

docs/deposit-transaction-builder.md (updated)

Added Concurrency — Sequence Manager section documenting the problem, solution, usage example, and guarantees.


Acceptance criteria

  • No duplicate sequence under parallel calls (Promise.all tests)
  • Lock released even on thrown errors (finally block tests)
  • Tests assert ordering (FIFO suite)
  • Docs updated

Testing

npm test -- --testPathPattern="sequenceManager.test"

All 46 tests pass. No external dependencies required.


closes #416