npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nostr-connect/connect

v0.4.0

Published

Nostr Connect SDK for TypeScript is a library that allows you to easily integrate Nostr Connect into your web application.

Downloads

110

Readme

🔌 Nostr Connect SDK for TypeScript

Nostr Connect SDK for TypeScript is a library that allows you to easily integrate Nostr Connect into your web application.

📦 Installation

You can install the SDK using npm or yarn:

npm install @nostr-connect/connect
# or with yarn
yarn add @nostr-connect/connect

📖 Usage

  1. 👩‍💻 For Apps developers
  2. 🔐 For Wallet & Remote Signer developers

👩‍💻 For Apps developers

Create an ephemeral key

To use the SDK, you need to create an ephemeral key. This key is used to authenticate your user and to create a session.

import { generatePrivateKey } from 'nostr-tools';

const sk = generatePrivateKey();

Create a Nostr Connect instance

To create a Nostr Connect instance, you need to provide the ephemeral key and the Nostr Connect URL.

import { Connect } from '@nostr-connect/connect';


const connect = new Connect({ secretKey: sk, relay: 'wss://nostr.vulpem.com' });
connect.events.on('connect', ( walletPubkey:string ) => {
  console.log('connected with wallet: ' + walletPubkey);
});
await connect.init();

Generate a ConnectURI and display it to the user

const connectURI = new ConnectURI({
  target: webPK,
  relay: 'wss://nostr.vulpem.com',
  metadata: {
    name: 'My Website',
    description: 'lorem ipsum dolor sit amet',
    url: 'https://vulpem.com',
    icons: ['https://vulpem.com/1000x860-p-500.422be1bc.png'],
  },
});

const uri = connectURI.toString();

Start making requests

// send the get_public_key message to the mobile app 
const pubkey = await connect.getPublicKey();

// send the sign_event message to the mobile app
const sig = await connect.signEvent(event);

🔐 For Wallet developers

🤓 Define your methods

As per NIP-46, the Signer app MUST implement the following RPC methods:

  • get_public_key
  • sign_event

You need to define these methods in your app, each method must return a Promise that resolves to the expected result.

The NostrSigner class provides access to the Nostr public key via this.self.pubkey, the Nostr private key via this.self.secret and the full Nostr event that originated the current request. You can access the event using the this.event property.

It's best to ask approval from the user before signing an event. To do so, you can emit an event to the UI and wait for the user to approve or reject the request.

import { NostrSigner } from '@nostr-connect/connect';
import { getPublicKey, signEvent, nip06 } from 'nostr-tools';

const sk = nip06.privateKeyFromSeedWords(myWords);

class MobileHandler extends NostrSigner {

  async get_public_key(): Promise<string> {
    return getPublicKey(sk);
  }

  async sign_event(event: Event): Promise<string> {
    if (!this.event) throw new Error('No origin event');

    // emit event to the UI to show a modal
    this.events.emit('sign_event_request', event);

    // wait for the user to approve or reject the request
    return new Promise((resolve, reject) => {
      
      // listen for user accept 
      this.events.on('sign_event_approve', () => {
        resolve(signEvent(event, this.self.secret));
      });

      // or reject
      this.events.on('sign_event_reject', () => {
        reject(new Error('User rejected request'));
      });
    });
  }
}

📱 Create a MobileHandler instance

Generate a key to identify the remote signer, it is used to be reached by the apps. At the moment it's your duty to persist locally a list of the apps that are allowed to connect to your remote signer.

// random key
const secretKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
// create a new instance of the MobileHandler 
const handler = new MobileHandler({ secretKey });

// define how to consume the sign_event_request events
remoteHandler.events.on('sign_event_request',
  (event: Event) => {
    // ⚠️⚠️⚠️ IMPORTANT: always check if the app is connected 

    // do your UI stuff here to ask the user to approve or reject the request    

    // UI components can accept the sign
    //this.events.emit('sign_event_approve');
    
    // or reject 
    //this.events.emit('sign_event_reject');
  }
);

// 📡 Listen for incoming requests
await remoteHandler.listen();

🔌 Intercept ConnectURI

Allow user to scan the QR code and extract the ConnectURI, intercept it via deep linking or let use manually copy-paste the URI.

// Show to the user the pubkey
const { target, relay, metadata } = ConnectURI.fromURI(text);

// if he consents send the connect message
await connectURI.approve(key);
// if rejects could be polite to notify the app of the rejection
await connectURI.reject(key);