Skip to content

Implement transaction submission idempotency strategy - #169

Merged
El-swaggerito merged 2 commits into
Axionvera:mainfrom
martinshub-tech:security/idempotency-strategy
Jul 21, 2026
Merged

Implement transaction submission idempotency strategy#169
El-swaggerito merged 2 commits into
Axionvera:mainfrom
martinshub-tech:security/idempotency-strategy

Conversation

@martinshub-tech

Copy link
Copy Markdown
Contributor

Closes #153

Description

This PR designs and implements a robust transaction submission idempotency strategy for the Stellar PocketPay SDK. It resolves the risk of duplicate payments/submissions during network drops and transaction timeouts by introducing status polling, transaction hash tracking, timebounds enforcement, and classification of retryable vs. non-retryable errors.

Key Changes

  • Enriched PocketPayError: Added transactionHash?: string and retryable?: boolean parameters to the SDK's core error class to expose relevant context to consumers during failures.
  • Error Classification (src/errors/index.ts): Introduced a classification helper that categorizes errors based on Stellar transaction result codes, HTTP statuses, and network/socket timeouts.
    • Retryable: Rate limits (429), server overloads (503).
    • Non-Retryable: Specific Stellar codes (e.g. tx_bad_auth, tx_bad_seq, tx_insufficient_balance).
    • Unknown Status: Socket/network drops and Gateway Timeouts (504).
  • Idempotent Submission & Status Polling (src/network/idempotency.ts):
    • submitTransactionIdempotently: Automatically handles timeout/unknown status outcomes by falling back to polling.
    • pollTransactionStatus: Queries Horizon for the transaction by its hash. It references the transaction's maxTime bounds and throws a clean TX_EXPIRED (retryable) error if the transaction fails to make it to the ledger before it expires.
  • Integration: Updated sendXLM in src/payments/index.ts to submit payments idempotently.
  • Documentation (docs/idempotency.md): Created a detailed consumer integration guide explaining duplicate submission risks and showing how to use the automated and manual helpers.
  • Updated Error Guide (docs/error-handling.md): Documented the new error properties and status codes.

Verification & Tests

Written a full suite of tests in tests/idempotency.test.ts covering:

  • Success on immediate submission.
  • Success on polling after timeout.
  • Immediate exit with TX_EXPIRED when transaction maxTime bounds are exceeded.
  • Non-retryable classification for on-chain reject codes.
  • Retryable classification for rate limits.

Ran all test suites successfully:

$ npm test
✓ tests/config.test.ts (7 tests)
✓ tests/idempotency.test.ts (9 tests)
✓ tests/fund.test.ts (22 tests)
✓ tests/utils.test.ts (34 tests)
✓ tests/payments.test.ts (7 tests)
✓ tests/wallet.test.ts (8 tests)

Test Files  6 passed (6)
     Tests  87 passed (87)

@El-swaggerito

Copy link
Copy Markdown
Contributor

This PR cannot be merged automatically because it has merge conflicts.

Please update the branch with the latest base branch and resolve the conflicts.

After the conflicts are resolved and checks pass, the automation can review it again.

@El-swaggerito
El-swaggerito merged commit ffbe510 into Axionvera:main Jul 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add SDK transaction submission idempotency strategy

2 participants