Support any NIP-55 external signer (Amber, Cambium, ...)#1092
Support any NIP-55 external signer (Amber, Cambium, ...)#1092TheCryptoDonkey wants to merge 2 commits into
Conversation
The external-signer client previously hardcoded Amber: the login button only appeared when Amber was installed, signing intents were pinned to its package, and content-provider calls used its authority. Installed NIP-55 signers are now discovered via the nostrsigner: scheme (already declared in the manifest queries block), the signer that serves the login is persisted on the credential, and all subsequent requests are routed to it. Provider responses are read from the result column per NIP-55, falling back to the legacy signature column that only Amber duplicates. Amber-only behaviour is unchanged, including previously persisted logins.
When several NIP-55 signers are installed the get_public_key intent is launched unpinned so Android shows its chooser. Primal exports its own nostrsigner: activity (its external-signer provider feature), so without this it appears in that chooser and offers itself as a signer to sign into itself. Exclude Primal own signer components via EXTRA_EXCLUDE_COMPONENTS.
|
Tested end-to-end on an Android 13 (API 33) emulator against a real NIP-46 bunker, not just source-verified: Single signer (Cambium only, Amber not installed) — the login button reads "Login with Cambium" (same shape Amber-only users see today). Login completes: Primal's Multiple signers (Cambium + Amber both installed) — the button reads "Login with external signer", and tapping it shows Android's chooser. Login via Cambium from the chooser completes end-to-end (feed + wallet sign_events all signed remotely). Self-exclusion (latest commit) — before the last commit, Primal appeared in its own chooser (it exports a Two interop issues surfaced during testing were on the signer side, not this PR, and are fixed in Cambium (noted here for anyone testing against a spec-minimal signer): (1) Primal's |
Primal's Android app currently hardcodes Amber as the only NIP-55 external signer: the login button only appears when Amber is installed, signing intents are pinned to Amber's package, and content-provider calls use Amber's authority. Any other NIP-55 signer is invisible to it, even though the manifest already declares the generic
nostrsigner:scheme in its<queries>block.This PR generalises the external-signer client so any installed NIP-55 signer works — Amber, Cambium (which proxies requests to a hardware signer over NIP-46, so no keys ever live on the phone), and whatever ships next — while keeping the Amber-only experience identical to today.
What changes
queryIntentActivitieson thenostrsigner:scheme (the<queries>declaration already covers it — no manifest change). Primal's own signer activity is excluded, and the existing Amber version gate (>= 3.0.4) still applies to Amber specifically.get_public_keyintent is left unpinned, so Android's own disambiguation dialog lets the user pick. The chosen signer reports its package in thepackageresult extra (Amber already does this), which is then pinned for every subsequent request.signerPackageName, nullable). Existing external-signer logins deserialise unchanged and resolve to Amber. Since it is per credential, two accounts can even use two different signer apps.NostrNotaryandNip04MessageCipherroute content-provider queries and the visible-intent fallback to the credential's signer instead of the hardcoded Amber package/authority.resultcolumn per the spec, falling back to Amber's legacysignaturecolumn. Previously nip04 encrypt/decrypt read onlysignature, which is an Amber-specific duplication — spec-compliant signers were silently treated as failures.AmberLauncher.kt→SignerLauncher.ktandAmberContentResolver.kt→SignerContentResolver.kt, with function names to match (signEventWithSigner, etc.), since they no longer talk exclusively to Amber.Behaviour notes
current_userhandling).