Skip to content

feat: decouple fee payment from sequence number management#23

Merged
marcelosalloum merged 12 commits intomainfrom
feat/fee-payer
Mar 26, 2026
Merged

feat: decouple fee payment from sequence number management#23
marcelosalloum merged 12 commits intomainfrom
feat/fee-payer

Conversation

@marcelosalloum
Copy link
Copy Markdown
Collaborator

What

  • Replace single feePayer param with separate signer (source account) and feeBumpSigner (fee payer) on both Charge and Channel servers
  • Rename push-mode credential type from "signature" to "hash" per MPP spec draft-stellar-charge-00
  • Remove feePayerKey from schema and client progress events
  • Replace closeKey with signer + feeBumpSigner on Channel server and standalone close() function
  • Add resolveKeypair utility, exported from all server subpaths

Why

Servers commonly use a pool of accounts for sequence numbers and a single dedicated account to pay fees via FeeBumpTransaction. The old feePayer parameter conflated both roles, making it impossible to separate fee payment from transaction signing. This decoupling is standard practice in Stellar infrastructure (see x402 facilitator pattern).

The type: "signature"type: "hash" rename aligns with MPP spec PR #199 which specifies type="hash" for push-mode credentials.

Breaking changes

Before After
charge({ feePayer: kp }) charge({ signer: kp, feeBumpSigner?: kp2 })
channel({ closeKey: kp }) channel({ signer: kp, feeBumpSigner?: kp2 })
close({ closeKey: kp }) close({ signer: kp, feeBumpSigner?: kp2 })
type: "signature" (push mode) type: "hash"
feePayerKey in schema/events Removed

Example

// Before
stellar.charge({
  recipient: 'G...',
  currency: USDC_SAC_TESTNET,
  feePayer: Keypair.fromSecret('S...'),  // paid fees AND provided sequence number
})

// After — separate concerns
stellar.charge({
  recipient: 'G...',
  currency: USDC_SAC_TESTNET,
  signer: Keypair.fromSecret('S...'),         // source account (sequence number)
  feeBumpSigner: Keypair.fromSecret('S...'),  // pays all fees via FeeBumpTransaction
})

@marcelosalloum marcelosalloum self-assigned this Mar 26, 2026
@marcelosalloum marcelosalloum marked this pull request as ready for review March 26, 2026 22:43
Copilot AI review requested due to automatic review settings March 26, 2026 22:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Decouples Stellar fee payment (fee-bump) from sequence-number management across the SDK’s Charge and Channel servers, aligns push-mode credential naming with the latest spec draft, and introduces a shared keypair resolution utility exported through public entrypoints.

Changes:

  • Replace feePayer / closeKey with signer (source account) and optional feeBumpSigner (fee payer) on server APIs and channel close helpers.
  • Rename push-mode credential payload type from "signature" to "hash" and remove feePayerKey from schema and client progress events.
  • Add and export resolveKeypair(Keypair|string) across SDK/server entrypoints; update docs/examples accordingly.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sdk/src/signers.ts Adds resolveKeypair helper for Keypair-or-secret-string normalization.
sdk/src/signers.test.ts Unit tests for resolveKeypair.
sdk/src/server/index.ts Re-exports resolveKeypair from the server entrypoint.
sdk/src/server/Charge.ts Splits sponsorship signer vs fee-bump signer; updates push-mode to "hash"; removes feePayerKey; adds fee-bump wrapping.
sdk/src/server/Charge.test.ts Updates parameter acceptance tests; updates hash-dedup tests for "hash" type.
sdk/src/integration.test.ts Updates credential type validation to "hash".
sdk/src/index.ts Re-exports resolveKeypair from the root SDK entrypoint.
sdk/src/client/Charge.ts Removes feePayerKey progress/event plumbing; renames push credential payload to "hash".
sdk/src/channel/server/index.ts Re-exports resolveKeypair from channel server entrypoint.
sdk/src/channel/server/Channel.ts Replaces closeKey with signer and adds optional fee-bump wrapping for close/open + standalone close().
sdk/src/channel/server/Channel.test.ts Updates tests for signer requirement and adds acceptance for feeBumpSigner.
sdk/src/Methods.ts Updates credential schema discriminator to "hash" and removes feePayerKey from methodDetails schema.
sdk/src/Methods.test.ts Updates schema tests for "hash" and removes feePayerKey assertion.
examples/channel-close.ts Updates example to use signer instead of closeKey.
README.md Updates public API docs/events and describes signer vs fee-bump signer roles.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sagpatil sagpatil self-requested a review March 26, 2026 23:46
@marcelosalloum marcelosalloum merged commit a540183 into main Mar 26, 2026
2 checks passed
@marcelosalloum marcelosalloum deleted the feat/fee-payer branch March 26, 2026 23:47
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.

3 participants