Skip to content

feat(blockchain): signer mode + signer_address pass-through (DEV-132)#7

Merged
0xkkkn merged 2 commits into
mainfrom
feat/dev-132-sdk-signer-mode
May 7, 2026
Merged

feat(blockchain): signer mode + signer_address pass-through (DEV-132)#7
0xkkkn merged 2 commits into
mainfrom
feat/dev-132-sdk-signer-mode

Conversation

@0xkkkn

@0xkkkn 0xkkkn commented May 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Two commits combined:

  1. feat(blockchain): add signer mode to PrivaraBlockchain (DEV-132) (e36b90d)

    • Adds BlockchainConfig.signer?: Account — alternative signer mode that sends a regular EOA tx via WalletClient instead of a ZeroDev UserOperation.
    • Constructor of PrivaraBlockchain requires exactly one of signer or serializedSessionKey; throws on conflict or missing config.
    • Calldata encoding and Privara.transactions.report reporting are unchanged across modes.
    • Version 0.1.0 → 0.2.0.
  2. feat(blockchain): pass signer_address to backend in signer mode (DEV-132) (555401b)

    • In signer mode, BlockchainInvoices.createAndSubmit forwards the signer EOA's address as signer_address to POST /api/v1/invoices. Required so the backend uses that address as the FHE sender (matching the on-chain msg.sender); otherwise the contract reverts with InvalidSigner.
    • Adds PrivaraBlockchain.getSignerAddress(): string | undefined.
    • Legacy session-key mode omits the field — behavior unchanged.
    • Version 0.2.0 → 0.2.1.

Why

Phase 1 of the "Drop Session Keys via Backend-Caller Pattern" plan. Backend pays gas with its own KMS-backed EOA; the user's main passkey wallet is the encrypted owner (sole entity that can redeem). No contract changes — see tasks/agents-sdk.md for context.

Test plan

  • npm run typecheck — clean
  • npm test — 57/57 ✅ (signer happy path, legacy backwards-compat, conflict throw, missing-config throw, identical-calldata, lazy-cache, signer_address pass-through, legacy-mode omit, getSignerAddress)
  • npm run build — clean dts/cjs/esm
  • E2E on Arbitrum Sepolia: on-chain tx 0xa064357..., from = signer EOA, to = ConfidentialEscrow, status success

Linked

  • Linear: DEV-132
  • Backend PR: PrivaraXYZ/platform-backend#new (paired)

0xkkkn added 2 commits May 7, 2026 17:41
Adds an alternative signer mode that accepts a viem `Account` and sends a
regular EOA transaction via `WalletClient` instead of a ZeroDev UserOperation.
Designed for backend-caller patterns where the backend (e.g. KMS-backed)
creates invoices and pays gas itself, while the user's main wallet is the
encrypted owner.

Public surface:
- `BlockchainConfig.signer?: Account` (legacy `serializedSessionKey` stays
  optional and continues to work)
- `createWalletClientFromSigner(config)` factory
- Constructor of `PrivaraBlockchain` requires exactly one of `signer` or
  `serializedSessionKey`; throws on conflict or missing config

Calldata encoding and `Privara.transactions.report` reporting are unchanged
across modes. Unit tests cover signer happy path, legacy backwards-compat,
constructor validation, identical-calldata across modes, lazy client cache.

Version bumped 0.1.0 -> 0.2.0.

Note on E2E: an end-to-end on-chain confirmation against the current /dev
backend is blocked by an upstream backend issue. `ConfidentialEscrow.create`
calls `verifyInput(input, msg.sender)` and the backend's FHE worker currently
encrypts with `userAddress = walletAddress` taken from the auth context.
Either path (legacy session-key or signer mode) reverts with `InvalidSigner`
when the actual `msg.sender` differs from that auth-bound `walletAddress`.
The SDK side is verified at unit-test level and by simulation; the on-chain
green path requires the backend to use the actual caller (backend EOA) as the
FHE sender. See ReineiraOS/tasks/agents-backend-frontend.md for the required
backend change.
…132)

When `PrivaraBlockchain` is configured in signer mode, `createAndSubmit`
now sends the signer EOA's address as `signer_address` in the body of
`POST /api/v1/invoices`. The backend (DEV-132 backend change) uses this
as the FHE sender bound into the Fhenix verifier signature. Without it
the on-chain transaction reverts with `InvalidSigner` because the actual
msg.sender (backend EOA) does not match the address baked into the
signature (which would default to walletAddress from auth context).

In legacy session-key mode `signer_address` is omitted — behavior unchanged.

Adds `PrivaraBlockchain.getSignerAddress(): string | undefined`.

Bumped 0.2.0 -> 0.2.1.
@0xkkkn
0xkkkn requested a review from a team as a code owner May 7, 2026 15:18
@0xkkkn
0xkkkn merged commit 9865bb4 into main May 7, 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.

1 participant