Background
Spec 4 Path A shipped in #281 — claim now works end-to-end with honest Torque attribution, but the user has no SignTxCard moment (the chat tool invocation is the consent). Path B was deferred as a post-judges follow-up per the amendment in docs/superpowers/specs/2026-05-15-claim-phase-2-design.md.
What to do
Extend @sip-protocol/sdk (in ~/local-dev/sip-protocol/packages/sdk) with two new exported primitives:
```ts
export async function buildClaimStealthPaymentTx(params: Omit<SolanaClaimParams, 'connection'> & { connection: Connection }):
Promise<{ serializedTx: string; stealthAddress: string; mint: string }>
export async function broadcastClaimStealthPaymentTx(connection: Connection, signedTxBase64: string):
Promise<{ txSignature: string; destinationAddress: string; amount: bigint; explorerUrl: string }>
```
Keep the existing atomic `claimStealthPayment(...)` as a convenience wrapper that calls build then broadcast internally. Strict API superset — no breaking change for any current consumer.
Then in sipher's `packages/agent/src/tools/claim.ts`, change `executeClaim` to:
- Call `buildClaimStealthPaymentTx` → get `serializedTx`
- Return `status: 'awaiting_signature'` + `serializedTx` to the tool-signing wrapper
- SignTxCard appears in chat → user signs as fee payer
- POST `/api/tool-signing/:flagId/confirm` triggers `broadcastClaimStealthPaymentTx`
- Return `status: 'confirmed'` + claim tx sig
Why
- UX symmetry with send/swap (consent ceremony via SignTxCard)
- Better SDK API design — splittable build/broadcast benefits CLI, web app, future integrations
- Acknowledges the privacy-aware framing that visible tx confirmation is valuable UX even if not cryptographically gating
Cost
- 4-6 days (SDK PR + npm publish + sipher consumer PR + frontend SignTxCard tweak for claim's two-signer flow)
- Coordination across `sip-protocol/sip-protocol` (SDK) and `sip-protocol/sipher` (consumer)
References
Acceptance
- SDK exports `buildClaimStealthPaymentTx` + `broadcastClaimStealthPaymentTx` as separate primitives
- Existing `claimStealthPayment` still works (no breaking change)
- sipher `executeClaim` uses the split API, emits `tool_signing_required` SSE
- Frontend SignTxCard handles claim's two-signer flow (stealth keypair server-side, fee payer client-side)
- Torque attribution still uses claim-tx-sig (same as Path A — should be free since broadcast returns the sig)
Background
Spec 4 Path A shipped in #281 — claim now works end-to-end with honest Torque attribution, but the user has no SignTxCard moment (the chat tool invocation is the consent). Path B was deferred as a post-judges follow-up per the amendment in
docs/superpowers/specs/2026-05-15-claim-phase-2-design.md.What to do
Extend
@sip-protocol/sdk(in~/local-dev/sip-protocol/packages/sdk) with two new exported primitives:```ts
export async function buildClaimStealthPaymentTx(params: Omit<SolanaClaimParams, 'connection'> & { connection: Connection }):
Promise<{ serializedTx: string; stealthAddress: string; mint: string }>
export async function broadcastClaimStealthPaymentTx(connection: Connection, signedTxBase64: string):
Promise<{ txSignature: string; destinationAddress: string; amount: bigint; explorerUrl: string }>
```
Keep the existing atomic `claimStealthPayment(...)` as a convenience wrapper that calls build then broadcast internally. Strict API superset — no breaking change for any current consumer.
Then in sipher's `packages/agent/src/tools/claim.ts`, change `executeClaim` to:
Why
Cost
References
Acceptance