Files
welshman/docs/signer/nip-07.md
T
2025-02-25 14:07:44 -08:00

92 lines
2.3 KiB
Markdown

# NIP-07 Signer
The `Nip07Signer` implements the `ISigner` interface by delegating signing operations to a NIP-07 compatible browser extension (like nos2x or Alby). It provides a way to interact with user's keys that are securely stored in their browser extension.
## Browser Detection
```typescript
import { getNip07 } from '@welshman/signer'
// Check if a NIP-07 provider is available
if (getNip07()) {
// Browser has a compatible extension installed
}
```
## Usage
```typescript
import { Nip07Signer } from '@welshman/signer'
// Create a new signer instance
const signer = new Nip07Signer()
// The extension will prompt the user for permission
// when operations are performed
```
## Complete Example
```typescript
import { Nip07Signer, getNip07 } from '@welshman/signer'
import { createEvent, NOTE } from '@welshman/util'
async function example() {
// Check for NIP-07 provider
if (!getNip07()) {
throw new Error('No NIP-07 provider found. Please install a Nostr browser extension.')
}
// Create signer
const signer = new Nip07Signer()
try {
// Get public key (will prompt user)
const pubkey = await signer.getPubkey()
console.log('Public key:', pubkey)
// Create and sign an event (will prompt user)
const event = createEvent(NOTE, {
content: "Hello via browser extension!",
tags: [["t", "test"]]
})
const signedEvent = await signer.sign(event)
console.log('Signed event:', signedEvent)
// Encrypt a message (will prompt user)
const recipientPubkey = "..."
const encrypted = await signer.nip44.encrypt(recipientPubkey, "Secret message")
console.log('Encrypted message:', encrypted)
} catch (error) {
// Handle user rejection or other errors
console.error('Operation failed:', error)
}
}
```
## Request Serialization
The signer implements a lock mechanism to prevent concurrent calls to the extension:
```typescript
class Nip07Signer implements ISigner {
#lock = Promise.resolve()
#then = async <T>(f: (ext: Nip07) => T | Promise<T>) => {
const promise = this.#lock.then(() => {
const ext = getNip07()
if (!ext) throw new Error("Nip07 is not enabled")
return f(ext)
})
// Reset lock after completion or error
this.#lock = promise.then(
() => undefined,
() => undefined
)
return promise
}
}
```