feat: Four SDK enhancements — sponsorship reserve, expiry guard, cursor tracker, XDR decoder - #572
Open
lekescrew22 wants to merge 5 commits into
Open
Conversation
Extends StellarSplitTxBuilder.build() and .submit() to accept an optional expiresAt timestamp. When provided, translates the invoice expiry into transaction timebounds via TransactionBuilder.setTimeout(), causing the ledger to reject submissions after the deadline has passed. Adds checkInvoiceExpiry() pre-submission check to preflightChecker.ts and PaymentExpiredError to errors.ts.
… check Adds checkSponsorReserve() to verify sponsoring accounts have sufficient XLM reserve before building sponsored-reserve onboarding transactions. Queries Horizon loadAccount() for subentry_count and num_sponsored, computes required reserve against BASE_RESERVE, and throws InsufficientSponsorReserveError on shortfall. Adds InsufficientSponsorReserveError to errors.ts and SponsorshipConfig / SponsorReserveCheckResult to types.ts. Exposes checkSponsorshipReserve() convenience wrapper in sponsorship.ts.
Adds cursorTracker.ts with getCursor(streamId) / setCursor(streamId, token) for persisting the last-processed paging token across process restarts. Integrates cursor persistence into stream.ts (polling), sse.ts (SSE URL with ?cursor= param), and subscription.ts (createInvoiceSubscription). Supports injectable CursorPersistence backend for production use.
Adds decodeXDR() that translates base64-encoded Stellar XDR into structured JSON objects safe for logging, audit trails, and developer UIs. Decodes TransactionEnvelope, TransactionResult, TransactionMeta, and LedgerEntry using @stellar/stellar-sdk xdr namespace. Integrates with auditLogger.ts via logWithXdr() and logAndDecodeXdr() methods that auto-detect and decode XDR payloads in audit entries.
|
@lekescrew22 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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 #502
Closes #504
Closes #506
Closes #507
Summary
This PR delivers four independent SDK enhancements that improve transaction safety, stream reliability, and developer observability.
1. Sponsorship Reserve Verifier
Problem: The SDK's sponsorship feature builds BeginSponsoringFutureReserves / EndSponsoringFutureReserves operation pairs but does not verify in advance that the sponsoring account has sufficient XLM reserve to cover the new ledger entries it will sponsor.
Solution: Added
checkSponsorReserve()insrc/preflightChecker.tsthat queries Horizon'sloadAccount()forsubentry_countandnum_sponsored, computes the required reserve increase againstBASE_RESERVE, and throwsInsufficientSponsorReserveErroron shortfall. A convenience wrappercheckSponsorshipReserve()is exported fromsrc/sponsorship.ts.Files:
src/errors.ts,src/types.ts,src/sponsorship.ts,src/preflightChecker.ts2. Invoice Expiry Guard with Timebounds
Problem: Invoices carry an
expiresAttimestamp but the SDK does not enforce this at the ledger level, only through SDK-side checks.Solution: Extended
StellarSplitTxBuilder.build()and.submit()to accept an optional{ expiresAt, invoiceId }parameter. When provided, translates the invoice expiry into transaction timebounds viaTransactionBuilder.setTimeout(), causing the ledger to reject submissions after the deadline has passed. AddedcheckInvoiceExpiry()pre-submission check andPaymentExpiredError.Files:
src/txBuilder.ts,src/preflightChecker.ts,src/errors.ts3. SSE Cursor Position Tracker
Problem: Long-running SDK processes discard the SSE cursor on process exit, causing duplicate event processing on every restart.
Solution: New
cursorTracker.tswithgetCursor(streamId)/setCursor(streamId, token)for persisting the last-processed paging token. Integrated intostream.ts(polling resume from stored cursor),sse.ts(SSE URL with?cursor=param), andsubscription.ts(createInvoiceSubscription). Supports injectableCursorPersistencebackend for production persistence.Files:
src/cursorTracker.ts(new),src/stream.ts,src/sse.ts,src/subscription.ts4. XDR Decoder for Structured Logging
Problem: Stellar's XDR binary format is opaque to API consumers and log-aggregation tools. Engineers must use external converters to understand logged transactions.
Solution: Added
decodeXDR()insrc/xdrDecoder.tsthat translates base64-encoded XDR into structured JSON using the@stellar/stellar-sdkxdr namespace. DecodesTransactionEnvelope,TransactionResult,TransactionMeta, andLedgerEntry. Integrated intoauditLogger.tsvialogWithXdr()andlogAndDecodeXdr()methods that auto-detect and decode XDR payloads.Files:
src/xdrDecoder.ts(new),src/auditLogger.ts,src/types.tsTypecheck
All changes pass
npx tsc --noEmitwith no new errors introduced (only pre-existing error in client.ts unrelated to these changes).