README.md

Nostr Signer Capacitor Plugin

This Capacitor plugin allows your application to interact with Nostr signer apps on the Android platform using intents, following the NIP-55 specification.

Install

npm install nostr-signer-capacitor-plugin
npx cap sync

Requirements

  • Android: minSdkVersion 23 or higher.

  • Java 21 (JDK 21) for building Android with Gradle.

  • Capacitor 7.x.

Version

Current version: 0.0.5

0.0.5 (2025-09-22)

  • Bumped Android minSdkVersion to 23 to align with Capacitor Android requirements.

  • Added Android unit tests (Robolectric) covering Content Resolver flows and rejected-provider fallback.

  • Added npm scripts:

    • test:ts – runs TypeScript/Jest tests

    • test:android – runs Android unit tests (testDebugUnitTest)

    • test:all (default npm test) – runs both suites

  • Added GitHub Actions workflow at .github/workflows/ci.yml to run JS and Android unit tests in CI.

Testing

Run TypeScript tests:

npm run test:ts

Run Android unit tests:

cd android
./gradlew clean testDebugUnitTest --no-daemon --stacktrace --info --console=plain

Run all tests:

npm test

Usage

Import the Plugin

import NostrSignerPlugin from 'nostr-signer-capacitor-plugin';

Set the Signer Package Name

Before using the plugin on Android, you need to set the package name of the external signer app.

await NostrSignerPlugin.setPackageName({ packageName: 'com.example.signer' });

Check if External Signer is Installed

const { installed } = await NostrSignerPlugin.isExternalSignerInstalled();
if (!installed) {
  console.log('External signer app is not installed.');
}

Get a List of Installed External Signers

try {
  const result = await NostrSignerPlugin.getInstalledSignerApps();
  signerApps = result.apps;
  console.log('Installed Signer Apps:', signerApps);
} catch (error) {
  console.error('Error getting installed signer apps:', error);
}

The AppInfo object has the following fields"

export interface AppInfo {
  name: string;        // The name of the app as it appears in the System launcher
  packageName: string; // The package name of the app - pass this to setPackageName
  iconData: string;    // the base 64 encoded string of the app's icon
  iconUrl: string;    // the url to app's icon
}

Get Public Key

try {
  const { npub } = await NostrSignerPlugin.getPublicKey();
  console.log('Public Key:', npub);
} catch (error) {
  console.error('Error getting public key:', error);
}

Sign Event

const event = {
  kind: 1,
  content: 'Hello, Nostr!',
  tags: [],
  created_at: Math.floor(Date.now() / 1000),
};

try {
  const { event: signedEventJson } = await NostrSignerPlugin.signEvent({
    eventJson: JSON.stringify(event),
  });
  const signedEvent = JSON.parse(signedEventJson);
  console.log('Signed Event:', signedEvent);
} catch (error) {
  console.error('Error signing event:', error);
}

NIP-04 Encrypt

try {
  const { result: encryptedText } = await NostrSignerPlugin.nip04Encrypt({
    pubKey: 'recipient_public_key',
    plainText: 'Secret message',
  });
  console.log('Encrypted Text:', encryptedText);
} catch (error) {
  console.error('Error encrypting message:', error);
}

NIP-04 Decrypt

try {
  const { result: decryptedText } = await NostrSignerPlugin.nip04Decrypt({
    pubKey: 'sender_public_key',
    encryptedText: 'encrypted_text',
  });
  console.log('Decrypted Text:', decryptedText);
} catch (error) {
  console.error('Error decrypting message:', error);
}

NIP-44 Encrypt

try {
  const { result: encryptedText } = await NostrSignerPlugin.nip44Encrypt({
    pubKey: 'recipient_public_key',
    plainText: 'Secret message',
  });
  console.log('Encrypted Text (NIP-44):', encryptedText);
} catch (error) {
  console.error('Error encrypting message (NIP-44):', error);
}

NIP-44 Decrypt

try {
  const { result: decryptedText } = await NostrSignerPlugin.nip44Decrypt({
    pubKey: 'sender_public_key',
    encryptedText: 'encrypted_text',
  });
  console.log('Decrypted Text (NIP-44):', decryptedText);
} catch (error) {
  console.error('Error decrypting message (NIP-44):', error);
}

Decrypt Zap Event

try {
  const { result: decryptedEventJson } = await NostrSignerPlugin.decryptZapEvent({
    eventJson: JSON.stringify(encryptedEvent),
  });
  const decryptedEvent = JSON.parse(decryptedEventJson);
  console.log('Decrypted Zap Event:', decryptedEvent);
} catch (error) {
  console.error('Error decrypting zap event:', error);
}

API

  • getInstalledSignerApps(...)

  • setPackageName(...)

  • isExternalSignerInstalled()

  • getPublicKey()

  • signEvent(...)

  • nip04Encrypt(...)

  • nip04Decrypt(...)

  • nip44Encrypt(...)

  • nip44Decrypt(...)

  • decryptZapEvent(...)

getInstalledSignerApps(...)

getInstalledSignerApps() => Promise<{ apps: AppInfo[] }>

Returns a list of AppInfo objects which contain information about which Signer apps are installed.

Returns: Promise<{ apps: AppInfop[] }>

setPackageName(...)

setPackageName(options: { packageName: string; }) => Promise<void>

Sets the package name of the external Nostr signer app. This is required on Android to specify which app to interact with.

ParamTypeDescriptionoptions{ packageName: string; }An object containing the package name string.


isExternalSignerInstalled()

isExternalSignerInstalled() => Promise<{ installed: boolean; }>

Checks if the external Nostr signer app is installed on the device.

Returns: Promise<{ installed: boolean; }>

An object indicating whether the signer app is installed.


getPublicKey()

getPublicKey() => Promise<{ npub: string; }>

Requests the public key from the Nostr signer app or extension.

Returns: Promise<{ npub: string; }>

An object containing the public key in npub format.


signEvent(...)

signEvent(options: { eventJson: string; }) => Promise<{ event: string; }>

Requests the signer app to sign a Nostr event.

ParamTypeDescriptionoptions{ eventJson: string; }An object containing the event in JSON string format.

Returns: Promise<{ event: string; }>

An object containing the signed event in JSON string format.


nip04Encrypt(...)

nip04Encrypt(options: { plainText: string; pubKey: string; }) => Promise<{ result: string; }>

Encrypts a message using NIP-04 encryption.

ParamTypeDescriptionoptions{ plainText: string; pubKey: string; }An object containing the plaintext and the recipient's public key.

Returns: Promise<{ result: string; }>

An object containing the encrypted text.


nip04Decrypt(...)

nip04Decrypt(options: { encryptedText: string; pubKey: string; }) => Promise<{ result: string; }>

Decrypts a message using NIP-04 decryption.

ParamTypeDescriptionoptions{ encryptedText: string; pubKey: string; }An object containing the encrypted text and the sender's public key.

Returns: Promise<{ result: string; }>

An object containing the decrypted plaintext.


nip44Encrypt(...)

nip44Encrypt(options: { plainText: string; pubKey: string; }) => Promise<{ result: string; }>

Encrypts a message using NIP-44 encryption.

ParamTypeDescriptionoptions{ plainText: string; pubKey: string; }An object containing the plaintext and the recipient's public key.

Returns: Promise<{ result: string; }>

An object containing the encrypted text.


nip44Decrypt(...)

nip44Decrypt(options: { encryptedText: string; pubKey: string; }) => Promise<{ result: string; }>

Decrypts a message using NIP-44 decryption.

ParamTypeDescriptionoptions{ encryptedText: string; pubKey: string; }An object containing the encrypted text and the sender's public key.

Returns: Promise<{ result: string; }>

An object containing the decrypted plaintext.


decryptZapEvent(...)

decryptZapEvent(options: { eventJson: string; }) => Promise<{ result: string; }>

Decrypts a zap event.

ParamTypeDescriptionoptions{ eventJson: string; }An object containing the encrypted zap event in JSON string format.

Returns: Promise<{ result: string; }>

An object containing the decrypted zap event in JSON string format.


Notes

  • On Android, the plugin communicates with external signer apps using intents and the Content Resolver as per NIP-55.

  • Ensure that the external signer app or browser extension supports the required NIP specifications.

License

MIT License

Repository Details

name / identifier

nostr-signer-capacitor-plugin

nostr clone url

nostr://npub1ehhfg09mr8z34wz85ek46a6rww4f7c7jsujxhdvmpqnl5hnrwsqq2szjqv/nostr-signer-capacitor-plugin
just install ngit and run
git clone nostr://...

description

Nostr Signer Capcitor Plugin

signer
capacitor-plugin
nostr

grasp servers

none

git servers

https://github.com/chebizarro/nostr-signer-capacitor-plugin.git

maintainers

relays

none

earliest unique commit

60f61e1f41b85683e140d999cf11c3d9a833337a

gitworkshop.dev logo GitWorkshop.dev