3.7 KiB
3.7 KiB
NIP-59 (Gift Wrap) Implementation
The Nip59 class provides utilities for implementing the Gift Wrap protocol (NIP-59), allowing secure event wrapping and unwrapping. This implementation works with any signer that supports encryption, making it versatile for different authentication methods.
Key Features
- Event wrapping (encryption) for specific recipients
- Event unwrapping (decryption) of received wrapped events
- Automatic ephemeral wrapper generation
- Caching of previously unwrapped events
- Compatible with all signer implementations
Basic Usage
import { Nip59 } from '@welshman/signer'
import { makeEvent, DIRECT_MESSAGE } from '@welshman/util'
// Create a NIP-59 instance from any signer
const nip59 = Nip59.fromSigner(mySigner)
// Wrap an event — returns the gift-wrap SignedEvent to publish
const wrappedEvent = await nip59.wrap(
recipientPubkey,
makeEvent(DIRECT_MESSAGE, {
content: "Secret message",
tags: [["p", recipientPubkey]]
})
)
// Unwrap a received event
const unwrapped = await nip59.unwrap(receivedWrappedEvent)
Wrapping Process
The wrapping process involves multiple steps:
- Create the rumor (original event)
- Create the seal (encrypted rumor)
- Create the wrap (encrypted seal)
export const wrap = async (
signer: ISigner,
wrapper: ISigner,
pubkey: string,
template: StampedEvent,
tags: string[][] = []
) => {
const author = await signer.getPubkey()
const rumor = await prep(template, author)
const seal = await getSeal(signer, pubkey, rumor)
const wrap = await getWrap(wrapper, pubkey, seal, tags)
return wrap
}
API Reference
Constructor & Factory Methods
class Nip59 {
// Constructor
constructor(signer: ISigner, wrapper?: ISigner)
// Factory Methods
static fromSigner(signer: ISigner): Nip59
static fromSecret(secret: string): Nip59
// Instance Methods
/**
* Wraps an event for a specific recipient
* @param pubkey Recipient's public key
* @param template The event to wrap
* @param tags Additional tags for the wrap event (optional)
* @returns Promise<SignedEvent> The gift-wrap event to publish
*/
wrap(
pubkey: string,
template: StampedEvent,
tags?: string[][]
): Promise<SignedEvent>
/**
* Unwraps a received wrapped event
* @param event The wrapped event to decrypt
* @returns Promise<HashedEvent> The original unwrapped event
*/
unwrap(event: SignedEvent): Promise<HashedEvent>
/**
* Creates a new instance with a specific wrapper signer
* @param wrapper Signer to use for wrapping events
* @returns Nip59 New instance with the specified wrapper
*/
withWrapper(wrapper: ISigner): Nip59
}
Detailed Examples
Basic Wrapping & Unwrapping
import { Nip59, Nip01Signer } from '@welshman/signer'
import { makeEvent, DIRECT_MESSAGE } from '@welshman/util'
async function example() {
// Create NIP-59 instance
const signer = new Nip01Signer(mySecret)
const nip59 = Nip59.fromSigner(signer)
// Create and wrap an event — returns the gift-wrap SignedEvent to publish
const event = makeEvent(DIRECT_MESSAGE, {
content: "Secret message",
tags: [["p", recipientPubkey]]
})
const wrappedEvent = await nip59.wrap(recipientPubkey, event)
// Later, unwrap a received event
const unwrapped = await nip59.unwrap(receivedEvent)
}
Custom Wrapper Signer
import { Nip59, Nip01Signer } from '@welshman/signer'
// Create with specific wrapper
const nip59 = new Nip59(
mainSigner,
Nip01Signer.ephemeral() // Custom wrapper
)
// Or add wrapper to existing instance
const nip59WithWrapper = nip59.withWrapper(
Nip01Signer.ephemeral()
)