Skip to content

feat: pay push --confidential / confidential mpp charges#381

Open
lgalabru wants to merge 7 commits into
mainfrom
feat/confidential-transfers
Open

feat: pay push --confidential / confidential mpp charges#381
lgalabru wants to merge 7 commits into
mainfrom
feat/confidential-transfers

Conversation

@lgalabru

Copy link
Copy Markdown
Collaborator

Adds a --confidential flag to pay push for Token-2022 confidential (amount-hidden) transfers, settled via the gateway-paid bundle flow in pay-kit PR #181.

Changes

  • pay push --confidential CLI flag → StablecoinSendRequest.confidentialApiSendRequest.confidential (serialized only when set, so normal sends are byte-identical).
  • Consume the confidential pay-kit branch (PR Package #181) + solana 4.0 line; point litesvm at the loosen-solana-address-constraint fork.
  • Drop the unused multi_delegator session path.
  • Tests: serialization coverage for the confidential request flag.

Depends on solana-foundation/pay-kit#181 (the feat/confidential-transfers branch). The git deps + litesvm patch track that branch until it merges.

🤖 Generated with Claude Code

lgalabru added 5 commits June 20, 2026 14:37
…al pay-kit

solana-mpp removed the multi_delegator program/client API (operated-voucher
pull sessions). Remove its usage from pay:

- pay-core: MultiDelegateChain trait + RpcMultiDelegateChain, handle_pull_setup
  / run_pull_setup, the open-channel batcher, and the operated-voucher pull
  path in server/client session.rs (+ tests).
- CLI/server: operated-voucher wiring; the config/strategy now errors cleanly.
- rename build_open_payment_channel_tx -> build_open_payment_channel_transaction
  (new BuildOpenPaymentChannelTransactionParams signature).

Operated-voucher pull setup is no longer supported; push mode and
payment-channel client-voucher pull are preserved.

Wire solana-mpp/x402 to the local solana-4.0 pay-kit checkout and enable the
`confidential` feature. NOTE: the [patch] uses local absolute paths for dev;
repoint to a pushed pay-kit branch (+ litesvm fork) before CI/merge.
Plumb a `confidential` flag from the send/push command through
StablecoinSendRequest into the gateway's /v1/send request body. When set
(and the mint is CT-capable), the gateway issues a confidential MPP
challenge and the client settles it as a Token-2022 confidential transfer
bundle (handled by solana-mpp's confidential feature).

Client-side only; the gateway must honour the `confidential` request field
to issue confidential challenges (separate agent-gateway work).
…traint)

Replaces the local-path litesvm [patch.crates-io] with the pushed fork
branch (github.com/lgalabru/litesvm) while the upstream PR is open.
)

Replaces the local-path [patch] with the pushed pay-kit branch so pay builds
the confidential-transfer + solana-4.0 work from git. Flip back to main once
PR #181 merges.
Confirms ApiSendRequest serializes confidential:true when set and omits it
otherwise, so non-confidential sends are byte-identical.
@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
payment-debugger Ready Ready Preview, Comment Jun 21, 2026 2:54am

Request Review

@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a --confidential flag to pay push/send for Token-2022 confidential (amount-hidden) transfers, routing through the gateway-paid bundle flow. It also drops the previously unused multi_delegator pull-session code path and bumps the solana-mpp/solana-x402 dependencies to the feat/confidential-transfers branch.

  • --confidential CLI flag is threaded from SendCommandStablecoinSendRequest.confidentialApiSendRequest.confidential, serialized only when true so normal sends remain byte-identical; covered by a new unit test.
  • The multi_delegator session path and its 746-line integration test file are removed; validate_client_voucher_pull_open now explicitly rejects the legacy token-account delegation shape with a migration-hint error.
  • Cargo.toml adds a [patch.crates-io] entry for a personal litesvm fork (loosen-solana-address-constraint branch) to allow litesvm 0.13 to coexist with zk-sdk 7 confidential-proof crates.

Confidence Score: 5/5

The confidential flag addition is self-contained and additive; it only changes the serialized request when explicitly set, so all existing send paths are unaffected.

The core feature change — threading a boolean flag from CLI to API — is minimal and well-tested. The multi_delegator removal is a straightforward deletion of unused code. The one issue found (check ordering in validate_client_voucher_pull_open leading to a less-helpful error message for legacy clients) is non-functional and affects only the removed path that was already unused in production.

rust/crates/core/src/server/session.rs — the check order in validate_client_voucher_pull_open gives a confusing error to legacy token-account delegation callers; rust/Cargo.toml — mutable branch pins for solana-mpp/x402 and the personal litesvm fork (noted in prior review threads).

Important Files Changed

Filename Overview
rust/crates/cli/src/commands/send.rs Adds --confidential flag to SendCommand and threads it through to send_stablecoin; no logic changes otherwise.
rust/crates/core/src/client/send.rs Adds confidential: bool to StablecoinSendRequest and ApiSendRequest; serialized only when true to keep normal sends byte-identical. Includes a serialization unit test.
rust/crates/core/src/server/session.rs Removes the multi-delegator pull-session code path; replaces with validate_client_voucher_pull_open. Check order gives a less-helpful error to legacy token-account delegation clients (see inline comment).
rust/Cargo.toml Bumps solana-mpp/x402 to the feat/confidential-transfers branch (mutable ref); patches litesvm via a personal fork branch — both already noted in prior review threads.
rust/crates/core/tests/session_surfpool_sdk_tests.rs File deleted — removes integration tests for the now-removed multi_delegator/pull-session code path.
rust/crates/core/tests/surfpool_tests.rs No visible logic change; tests continue to cover MPP charge, replay protection, session open/voucher/close, and build_credential flows.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI as CLI (pay push --confidential)
    participant Core as pay-core send
    participant API as pay-api gateway
    participant Chain as Solana (Token-2022)

    CLI->>Core: "StablecoinSendRequest { confidential: true }"
    Core->>API: "POST /v1/send { ..., "confidential": true }"
    API-->>Core: 402 + confidential MPP challenge
    Core->>Core: parse challenge, select by balance, build credential
    Core->>API: POST /v1/send + Authorization header (retry)
    API->>Chain: submit confidential bundle (gateway-paid)
    Chain-->>API: transaction confirmed
    API-->>Core: "{ receipt: { reference: txSig } }"
    Core-->>CLI: "SendResult { signature, amount_raw, ... }"
    CLI->>CLI: print "Sent X USDC to recipient"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI as CLI (pay push --confidential)
    participant Core as pay-core send
    participant API as pay-api gateway
    participant Chain as Solana (Token-2022)

    CLI->>Core: "StablecoinSendRequest { confidential: true }"
    Core->>API: "POST /v1/send { ..., "confidential": true }"
    API-->>Core: 402 + confidential MPP challenge
    Core->>Core: parse challenge, select by balance, build credential
    Core->>API: POST /v1/send + Authorization header (retry)
    API->>Chain: submit confidential bundle (gateway-paid)
    Chain-->>API: transaction confirmed
    API-->>Core: "{ receipt: { reference: txSig } }"
    Core-->>CLI: "SendResult { signature, amount_raw, ... }"
    CLI->>CLI: print "Sent X USDC to recipient"
Loading

Reviews (3): Last reviewed commit: "fix(deps): pull confidential pay-kit (no..." | Re-trigger Greptile

Comment thread rust/Cargo.toml
Comment on lines +108 to 117
solana-mpp = { git = "https://github.com/solana-foundation/pay-kit", branch = "feat/confidential-transfers", default-features = false, features = [
"client",
"server",
"confidential",
] }

# Solana x402 (lives in the pay-kit workspace alongside solana-mpp)
solana-x402 = { git = "https://github.com/solana-foundation/pay-kit", branch = "main", package = "solana-x402", default-features = false, features = [
solana-x402 = { git = "https://github.com/solana-foundation/pay-kit", branch = "feat/confidential-transfers", package = "solana-x402", default-features = false, features = [
"client",
] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Mutable branch references for production dependencies

Both solana-mpp and solana-x402 are pinned to branch = "feat/confidential-transfers" rather than a fixed rev =. The Cargo.lock does capture the commit hash at lock time, but any cargo update will silently pull whatever is at the HEAD of that branch at that moment — including force-pushed rewrites or last-minute breaking changes. Given the feature branch is still in review (PR #181), this is a concrete risk window. Consider locking to the current HEAD rev instead, e.g., rev = "abc1234", until the upstream branch stabilises or merges.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Intentional and temporary: solana-mpp/solana-x402 track pay-kit PR #181's feature branch until it merges, then move to a pinned release/rev. Noted in the Cargo.toml comment and the dev-shims section of confidential-transfers.md.

Comment thread rust/Cargo.toml
Comment on lines +133 to +135
[patch.crates-io]
litesvm = { git = "https://github.com/lgalabru/litesvm.git", branch = "loosen-solana-address-constraint" }
litesvm-token = { git = "https://github.com/lgalabru/litesvm.git", branch = "loosen-solana-address-constraint" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Personal fork pinned to a mutable branch in [patch.crates-io]

The litesvm / litesvm-token patch points to lgalabru/litesvm.git on a personal fork with branch = "loosen-solana-address-constraint". Personal forks can be renamed, deleted, or go stale; using a rev = pin would at least guarantee the exact commit is fetched regardless of branch mutations. This affects test builds (surfpool_tests, session_surfpool_sdk_tests).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Temporary dev shim: the fork only loosens litesvm's solana-address pin so litesvm can coexist with the zk-sdk 7 proof crates (no newer litesvm release exists). Pending the upstream litesvm PR; documented in confidential-transfers.md §6.1.

@lgalabru lgalabru changed the title feat: pay push --confidential (Token-2022 confidential transfers) feat: pay push --confidential / confidential mpp charges Jun 21, 2026
…re std

Bump solana-mpp to pick up the no-entrypoint fix for spl-associated-token-account
(resolves the linux 'duplicate symbol: entrypoint' link error vs surfpool's
bundled programs). Force five8_core 0.1.2's std feature so its 'impl Error for
DecodeError' stays enabled through the re-resolve (solana-keypair/signature
depend on it).
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.

1 participant