163 lines
3.1 KiB
Markdown
163 lines
3.1 KiB
Markdown
# Encryptable
|
|
|
|
The Encryptable module provides a system for handling encrypted Nostr events, particularly useful for private content like muted lists, bookmarks, or other encrypted user data.
|
|
|
|
## Core Types
|
|
|
|
### Encrypt Function
|
|
```typescript
|
|
type Encrypt = (x: string) => Promise<string>
|
|
```
|
|
|
|
### Encryptable Updates
|
|
```typescript
|
|
type EncryptableUpdates = {
|
|
content?: string
|
|
tags?: string[][]
|
|
}
|
|
```
|
|
|
|
### Decrypted Event
|
|
```typescript
|
|
type DecryptedEvent = TrustedEvent & {
|
|
plaintext: EncryptableUpdates
|
|
}
|
|
```
|
|
|
|
## Encryptable Class
|
|
|
|
```typescript
|
|
class Encryptable<T extends EventTemplate> {
|
|
constructor(
|
|
readonly event: Partial<T>, // Base event template
|
|
readonly updates: EncryptableUpdates // Plaintext updates
|
|
)
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Encryption
|
|
```typescript
|
|
// Create encryptable event
|
|
const encryptable = new Encryptable(
|
|
{ kind: 10000 }, // Base event
|
|
{ content: "secret content" } // Plaintext updates
|
|
)
|
|
|
|
// Encrypt and get final event
|
|
const event = await encryptable.reconcile(encryptFn)
|
|
```
|
|
|
|
### Private Lists
|
|
```typescript
|
|
// Create private mute list
|
|
const muteList = new Encryptable(
|
|
{
|
|
kind: 10000, // Mute list kind
|
|
tags: [] // Public tags
|
|
},
|
|
{
|
|
content: JSON.stringify(['pubkey1', 'pubkey2']), // Private content
|
|
tags: [['p', 'pubkey1'], ['p', 'pubkey2']] // Private tags
|
|
}
|
|
)
|
|
|
|
// Encrypt for publishing
|
|
const encrypted = await muteList.reconcile(async (content) => {
|
|
return await nip04.encrypt(pubkey, content)
|
|
})
|
|
```
|
|
|
|
### Updating Encrypted Content
|
|
```typescript
|
|
// Create encryptable from existing event
|
|
const existing = {
|
|
kind: 10000,
|
|
content: encryptedContent,
|
|
tags: publicTags
|
|
}
|
|
|
|
// Add new encrypted content
|
|
const updated = new Encryptable(
|
|
existing,
|
|
{
|
|
content: JSON.stringify(newContent),
|
|
tags: newPrivateTags
|
|
}
|
|
)
|
|
|
|
const final = await updated.reconcile(encrypt)
|
|
```
|
|
|
|
## Helper Functions
|
|
|
|
### Create Decrypted Event
|
|
```typescript
|
|
import { asDecryptedEvent } from '@welshman/util'
|
|
|
|
// Add plaintext content to event
|
|
const decrypted = asDecryptedEvent(
|
|
event,
|
|
{
|
|
content: decryptedContent,
|
|
tags: decryptedTags
|
|
}
|
|
)
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Private Bookmarks
|
|
```typescript
|
|
// Create private bookmark list
|
|
const bookmarks = new Encryptable(
|
|
{
|
|
kind: 10003,
|
|
tags: [['d', 'bookmarks']] // Public identifier
|
|
},
|
|
{
|
|
content: JSON.stringify([
|
|
{ id: 'note1', title: 'Secret Note' }
|
|
])
|
|
}
|
|
)
|
|
|
|
// Encrypt for publishing
|
|
const event = await bookmarks.reconcile(async (content) => {
|
|
return await myEncryptionFunction(content)
|
|
})
|
|
```
|
|
|
|
### Encrypted Group Membership
|
|
```typescript
|
|
// Create private group member list
|
|
const members = new Encryptable(
|
|
{
|
|
kind: 30000,
|
|
tags: [['d', 'group-members']]
|
|
},
|
|
{
|
|
tags: members.map(m => ['p', m.pubkey, m.role])
|
|
}
|
|
)
|
|
|
|
const encrypted = await members.reconcile(encrypt)
|
|
```
|
|
|
|
### Updating Private Content
|
|
```typescript
|
|
function updatePrivateList(event: DecryptedEvent, newItems: string[]) {
|
|
return new Encryptable(
|
|
event,
|
|
{
|
|
content: JSON.stringify(newItems)
|
|
}
|
|
)
|
|
}
|
|
|
|
// Usage
|
|
const updated = updatePrivateList(existingEvent, newItems)
|
|
const final = await updated.reconcile(encrypt)
|
|
```
|