feat(client): wire Privy signer through SentinelClient#24
Merged
Sentinel-Bluebuilder merged 1 commit intomasterfrom Apr 27, 2026
Merged
feat(client): wire Privy signer through SentinelClient#24Sentinel-Bluebuilder merged 1 commit intomasterfrom
Sentinel-Bluebuilder merged 1 commit intomasterfrom
Conversation
…adcast) The PrivyCosmosSigner adapter shipped in #23 produced a cosmjs OfflineDirectSigner but consumers had to hand-build a SigningStargateClient to use it. This wires it into SentinelClient directly: new SentinelClient({ signer: privySigner, rpcUrl }) await client.getBalance() // works — uses signer's address await client.getClient() // works — passes signer to SigningStargateClient getWallet() now resolves in this order: 1. per-call mnemonic (override) 2. constructor-supplied signer (Privy raw-sign, Keplr, etc.) 3. constructor-supplied mnemonic (the original path) Tunnel handshake constraint: connect() / autoConnect() / connectPlan() throw a helpful "VPN connect/disconnect requires a mnemonic" error when only a signer is supplied, because the WireGuard/V2Ray handshake signs locally with the raw secp256k1 privkey before any chain TX. Privy's raw-sign endpoint cannot reach into that primitive without a handshake refactor (deferred — out of scope here). The error message points to docs/PRIVY-INTEGRATION.md for the full table. Tests: test/privy-client-integration.test.mjs — 12 assertions covering signer-mode getWallet shape, address parity with mnemonic mode, helpful error for missing auth, and rejection of all three connect entry points in signer-only mode. Existing privy-cosmos-signer.test.mjs (20) still passes; smoke test 670/671 passing (the one pre-existing SDK_VERSION mismatch is unrelated). Docs: docs/PRIVY-INTEGRATION.md gains a "Tunnel connect/disconnect — Mode A only" section with the operation-by-mode table, plus a SentinelClient usage example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SentinelClient({ signer })— accept a pre-built cosmjsOfflineDirectSigner(e.g.PrivyCosmosSigner.fromRawSign(...)) directly.getWallet(),getClient(), andgetBalance()work without a mnemonic.SentinelClient({ mnemonic })callers unchanged.connect,autoConnect,connectPlan) throw a helpful error in signer-only mode and point to the docs — the WireGuard/V2Ray handshake still requires a raw cosmos privkey, which Privy's raw-sign endpoint cannot expose.Context
PR #23 shipped the
PrivyCosmosSigneradapter (Mode A mnemonic + Mode B raw-sign). This PR is the follow-up "integrate it fully" pass: instead of asking consumers to hand-build aSigningStargateClient,SentinelClientnow accepts the signer directly and routes it everywheregetWallet()is consumed.The handshake constraint is the one piece we can't unify yet —
v3protocol.js#initHandshakeV3callsSecp256k1.createSignature(msgHash, cosmosPrivKey)with the raw 32-byte privkey, which Mode B doesn't have. Lifting this requires either (a) refactoring the handshake to call out tosignRawSecp256k1, or (b) the consumer providing both a mnemonic-derived signer for tunnel ops and a Privy signer for chain ops. Documented as future work; not in this PR.Changes
client.js—getWallet()resolves: per-call mnemonic → constructor signer → constructor mnemonic. New_requireMnemonicForTunnel()guardsconnect/autoConnect/connectPlan.test/privy-client-integration.test.mjs(new) — 12 assertions: signer-mode shape, address parity, helpful error for missing auth, rejection of all three connect paths in signer-only mode.docs/PRIVY-INTEGRATION.md— adds operation-by-mode table, "Tunnel connect/disconnect — Mode A only" section,SentinelClientusage example, test list.Test plan
node test/privy-client-integration.test.mjs— 12/12 passnode test/privy-cosmos-signer.test.mjs— 20/20 still pass (no regression on feat(auth): Privy embedded wallet → Cosmos signer adapter #23)npm test(smoke) — 670/671 pass; the 1 failure (SDK_VERSION is 1.0.0) pre-exists on master, unrelated to this diffnpm run test:exports— 401 exports load cleanly