Skip to content

Account Subentry Capacity Guard #591

Description

@Kingsman-99

Description

Stellar accounts have a hard protocol limit on the number of subentries (trustlines, offers, data entries, and signers) they can hold, gated by the account's minimum balance reserve. The SDK does not currently warn callers when an account is approaching this limit, leading to silent op_low_reserve failures when invoice splits attempt to add new trustlines or data entries to a near-full account. A subentry capacity guard would pre-check available slots before any operation that increases subentry count.

Technical Context

New module src/account/subentryGuard.ts exposing checkSubentryCapacity(accountId: string, requiredSlots: number): Promise<SubentryCapacityResult>. Loads account data via Horizon.Server.loadAccount() from @stellar/stellar-sdk. Reserve calculation follows the protocol formula: (2 + numSubentries + numSponsoring − numSponsored) × baseReserve. SubentryCapacityResult and SubentryCapacityError interfaces in src/types.ts. Integrated as a pre-flight step in src/payments/splitExecutor.ts.

Acceptance Criteria

  • checkSubentryCapacity returns { available: number; used: number; limit: number; canAccommodate: boolean } derived from live Horizon account data
  • The guard correctly accounts for sponsored subentries using the account's num_sponsoring and num_sponsored Horizon response fields
  • When canAccommodate is false, splitExecutor throws a SubentryCapacityError that names the specific account ID and the number of additional reserve XLM needed
  • Callers can opt out by passing { skipCapacityCheck: true } to splitExecutor, which bypasses the guard entirely without altering other pre-flight checks
  • Tests mock Horizon.Server.loadAccount and cover a well-funded account, an account exactly at capacity, a sponsored-subentry account, and the skip-flag bypass path
  • All CI checks (npm test, npm run build, ESLint/TypeScript) pass and the branch has no merge conflicts

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions