Delete readmes, update docs
This commit is contained in:
@@ -1,73 +0,0 @@
|
||||
# @welshman/app [](https://npmjs.com/package/@welshman/app)
|
||||
|
||||
Utilities for dealing with svelte stores when using welshman.
|
||||
|
||||
```typescript
|
||||
import {ctx, setContext} from '@welshman/lib'
|
||||
import {getNip07} from '@welshman/signer'
|
||||
import {throttled} from '@welshman/store'
|
||||
import {createEvent, NOTE} from '@welshman/util'
|
||||
import {
|
||||
getDefaultNetContext,
|
||||
getDefaultAppContext,
|
||||
signer,
|
||||
pubkey,
|
||||
publishThunk,
|
||||
load,
|
||||
initStorage,
|
||||
storageAdapters,
|
||||
freshness,
|
||||
plaintext,
|
||||
repository,
|
||||
tracker,
|
||||
} from '@welshman/app'
|
||||
|
||||
// Set up app config
|
||||
setContext({
|
||||
net: getDefaultNetContext(),
|
||||
app: getDefaultAppContext(),
|
||||
})
|
||||
|
||||
// Log in via NIP 07
|
||||
addSession({method: 'nip07', pubkey: await getNip07().getPubkey()})
|
||||
|
||||
// Signer is ready to go
|
||||
const event = signer.get().encrypt(/* ... */)
|
||||
|
||||
// This will fetch the user's profile automatically, and return an observable that updates
|
||||
// automatically. Several different stores exist that are ready to go, including handles,
|
||||
// zappers, relaySelections, relays, follows, mutes.
|
||||
const profile = deriveProfile(pubkey.get())
|
||||
|
||||
// A global router helps make intelligent relay selections
|
||||
const router = ctx.app.router
|
||||
|
||||
// Publish is done using thunks, which optimistically publish to the local database, deferring
|
||||
// signing and publishing for instant user feedback. Progress is reported as relays accept/reject the event
|
||||
const thunk = publishThunk({
|
||||
relays: router.FromUser().getUrls(),
|
||||
event: createEvent(NOTE, {content: "hi"}),
|
||||
delay: 3000,
|
||||
})
|
||||
|
||||
// Thunks can be aborted until after `delay`, allowing for soft-undo
|
||||
thunk.controller.abort()
|
||||
|
||||
// Subscriptions automatically infer relays using `router` if not provided. If the request can be cached,
|
||||
// results from the local repository are returned immediately. `subscribe` and `load` are both available
|
||||
const events = await load({filters: [{kinds: [NOTE]}])
|
||||
|
||||
// Some commands are included
|
||||
const thunk = follow('97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322')
|
||||
|
||||
// Stores can be easily synchronized with indexeddb. Freshness keeps track of how stale the caches are,
|
||||
// plaintext maps encrypted events to their decrypted content, repository and tracker hold events and
|
||||
// event/relay mappings, respectively.
|
||||
const ready = initStorage("my-db", 1, {
|
||||
relays: {keyPath: "url", store: throttled(3000, relays)},
|
||||
handles: {keyPath: "nip05", store: throttled(3000, handles)},
|
||||
freshness: storageAdapters.fromObjectStore(freshness, {throttle: 3000}),
|
||||
plaintext: storageAdapters.fromObjectStore(plaintext, {throttle: 3000}),
|
||||
events: storageAdapters.fromRepositoryAndTracker(repository, tracker, {throttle: 3000}),
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,103 @@
|
||||
import {get, derived} from 'svelte/store'
|
||||
import {batch, fromPairs} from '@welshman/lib'
|
||||
import {PROFILE, FOLLOWS, MUTES, RELAYS, INBOX_RELAYS, getPubkeyTagValues, getListTags} from '@welshman/util'
|
||||
import {throttled, withGetter} from '@welshman/store'
|
||||
import {RepositoryUpdate} from '@welshman/relay'
|
||||
import {getAll, bulkPut, bulkDelete} from './storage.js'
|
||||
import {relays} from './relays.js'
|
||||
import {handles, onHandle} from './handles.js'
|
||||
import {zappers, onZapper} from './zappers.js'
|
||||
import {plaintext} from './plaintext.js'
|
||||
import {freshness} from './freshness.js'
|
||||
import {repository} from './core.js'
|
||||
import {sessions} from './session.js'
|
||||
import {userFollows} from './user.js'
|
||||
|
||||
export const defaultStorageAdapters = {
|
||||
relays: {
|
||||
keyPath: "url",
|
||||
init: async () => relays.set(await getAll("relays")),
|
||||
sync: () => throttled(3000, relays).subscribe($relays => bulkPut("relays", $relays)),
|
||||
},
|
||||
handles: {
|
||||
keyPath: "nip05",
|
||||
init: async () => handles.set(await getAll("handles")),
|
||||
sync: () => onHandle(batch(300, $handles => bulkPut("handles", $handles))),
|
||||
},
|
||||
zappers: {
|
||||
keyPath: "lnurl",
|
||||
init: async () => zappers.set(await getAll("zappers")),
|
||||
sync: () => onZapper(batch(300, $zappers => bulkPut("zappers", $zappers))),
|
||||
},
|
||||
freshness: {
|
||||
keyPath: "key",
|
||||
init: async () => {
|
||||
const items = await getAll("freshness")
|
||||
|
||||
freshness.set(fromPairs(items.map(item => [item.key, item.value])))
|
||||
},
|
||||
sync: () => {
|
||||
const interval = setInterval(() => {
|
||||
bulkPut(
|
||||
"freshness",
|
||||
Object.entries(freshness.get()).map(([key, value]) => ({key, value})),
|
||||
)
|
||||
}, 10_000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
},
|
||||
},
|
||||
plaintext: {
|
||||
keyPath: "key",
|
||||
init: async () => {
|
||||
const items = await getAll("plaintext")
|
||||
|
||||
plaintext.set(fromPairs(items.map(item => [item.key, item.value])))
|
||||
},
|
||||
sync: () => {
|
||||
const interval = setInterval(() => {
|
||||
bulkPut(
|
||||
"plaintext",
|
||||
Object.entries(plaintext.get()).map(([key, value]) => ({key, value})),
|
||||
)
|
||||
}, 10_000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
},
|
||||
},
|
||||
events: {
|
||||
keyPath: "id",
|
||||
init: async () => repository.load(await getAll("events")),
|
||||
sync: () => {
|
||||
const userFollowPubkeys = withGetter(
|
||||
derived(userFollows, l => new Set(getPubkeyTagValues(getListTags(l))))
|
||||
)
|
||||
|
||||
const onUpdate = async ({added, removed}: RepositoryUpdate) => {
|
||||
const sessionKeys = new Set(Object.keys(sessions.get()))
|
||||
const metaKinds = [PROFILE, FOLLOWS, MUTES, RELAYS, INBOX_RELAYS]
|
||||
|
||||
if (removed.size > 0) {
|
||||
await bulkDelete("events", Array.from(removed))
|
||||
}
|
||||
|
||||
if (added.length > 0) {
|
||||
await bulkPut(
|
||||
"events",
|
||||
added.filter(e => {
|
||||
if (sessionKeys.has(e.pubkey)) return true
|
||||
if (e.tags.some(t => sessionKeys.has(t[1]))) return true
|
||||
if (metaKinds.includes(e.kind) && userFollowPubkeys.get()?.has(e.pubkey)) return true
|
||||
|
||||
return false
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
repository.on("update", onUpdate)
|
||||
|
||||
return () => repository.off("update", onUpdate)
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {readable, derived, type Readable, type Subscriber} from "svelte/store"
|
||||
import {indexBy, remove, type Maybe, now} from "@welshman/lib"
|
||||
import {indexBy, remove, now} from "@welshman/lib"
|
||||
import {withGetter} from "@welshman/store"
|
||||
import {getFreshness, setFreshnessThrottled} from "./freshness.js"
|
||||
|
||||
@@ -15,7 +15,7 @@ export const collection = <T>({
|
||||
load?: (key: string, relays: string[]) => Promise<any>
|
||||
}) => {
|
||||
const indexStore = withGetter(derived(store, $items => indexBy(getKey, $items)))
|
||||
const pending = new Map<string, Promise<Maybe<T>>>()
|
||||
const pending = new Map<string, Promise<T | void>>()
|
||||
const loadAttempts = new Map<string, number>()
|
||||
|
||||
let subscribers: Subscriber<T>[] = []
|
||||
@@ -76,7 +76,7 @@ export const collection = <T>({
|
||||
return fresh
|
||||
}
|
||||
|
||||
const deriveItem = (key: Maybe<string>, relays: string[] = []) => {
|
||||
const deriveItem = (key: string | undefined, relays: string[] = []) => {
|
||||
if (!key) {
|
||||
return readable(undefined)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./adapters.js"
|
||||
export * from "./context.js"
|
||||
export * from "./core.js"
|
||||
export * from "./collection.js"
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# @welshman/dvm [](https://npmjs.com/package/@welshman/dvm)
|
||||
|
||||
Utilities for building nostr DVMs.
|
||||
|
||||
# Request example
|
||||
|
||||
```javascript
|
||||
import type {Publish, Subscription} from '@welshman/net'
|
||||
import {makeDvmRequest, DVMEvent} from '@welshman/dvm'
|
||||
|
||||
const req = makeDvmRequest({
|
||||
// Create and sign a dvm request event, including any desired tags
|
||||
event: createAndSign({kind: 5300}),
|
||||
// Publish and subscribe to these relays
|
||||
relays: ['wss://relay.damus.io', 'wss://dvms.f7z.io'],
|
||||
// Timeout defaults to 30 seconds
|
||||
timeout: 30_000,
|
||||
// Auto close on first result (defaults to true)
|
||||
autoClose: true,
|
||||
// Listen for and emit `progress` events
|
||||
reportProgress: true,
|
||||
})
|
||||
|
||||
// Listen for progress, result, etc
|
||||
req.emitter.on(DVMEvent.Progress, (url, event) => console.log(event))
|
||||
req.emitter.on(DVMEvent.Result, (url, event) => console.log(event))
|
||||
```
|
||||
|
||||
# Handler example
|
||||
|
||||
```javascript
|
||||
import {bytesToHex} from '@noble/hashes/utils'
|
||||
import {generateSecretKey} from 'nostr-tools'
|
||||
import {createEvent} from '@welshman/util'
|
||||
import {subscribe} from '@welshman/net'
|
||||
import {DVM} from '@welshman/dvm'
|
||||
|
||||
// Your DVM's private key. Store this somewhere safe
|
||||
// const hexPrivateKey = bytesToHex(generateSecretKey())
|
||||
const hexPrivateKey = '9cd387a3aa0c1abc2ef517c8402f29c069b4174e02a426491aec7566501bee67'
|
||||
|
||||
// Tags that we'll return as content discovery suggestions
|
||||
const tags = []
|
||||
|
||||
// Populate the tags with music by Ainsley Costello
|
||||
const sub = subscribe({
|
||||
timeout: 30_000,
|
||||
relays: ["wss://relay.wavlake.com"],
|
||||
filters: [{
|
||||
kinds: [31337],
|
||||
'#p': ['8806372af51515bf4aef807291b96487ea1826c966a5596bca86697b5d8b23bc'],
|
||||
}],
|
||||
})
|
||||
|
||||
// Push event ids to our suggestions
|
||||
sub.on('event', (url, e) => tags.push(["e", e.id, url]))
|
||||
|
||||
const dvm = new DVM({
|
||||
// The private key used to sign events
|
||||
sk: hexPrivateKey,
|
||||
// Relays that the DVM will listen on
|
||||
relays: ['wss://relay.damus.io', 'wss://dvms.f7z.io'],
|
||||
// Only listen to requests tagging our dvm
|
||||
requireMention: true,
|
||||
// Expire results after 1 hour (the default)
|
||||
expireAfter: 60 * 60,
|
||||
// Handlers for various kinds
|
||||
handlers: {
|
||||
5300: dvm => ({
|
||||
handleEvent: async function* (event) {
|
||||
// DVM responses are stringified into the content
|
||||
const content = JSON.stringify(tags)
|
||||
|
||||
// Yield our response. Kind 7000 can be used for partial results too
|
||||
yield createEvent(event.kind + 1000, {content})
|
||||
},
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
// Enable logging
|
||||
dvm.logEvents = true
|
||||
|
||||
// When you're ready
|
||||
dvm.start()
|
||||
|
||||
// When you're done
|
||||
dvm.stop()
|
||||
```
|
||||
@@ -1,3 +0,0 @@
|
||||
# @welshman/editor [](https://npmjs.com/package/@welshman/editor)
|
||||
|
||||
A batteries-included nostr-editor.
|
||||
@@ -1,34 +0,0 @@
|
||||
# @welshman/feeds [](https://npmjs.com/package/@welshman/feeds)
|
||||
|
||||
A custom feed compiler and loader for nostr. Read the spec on [wikifreedia](https://wikifreedia.xyz/cip-01/97c70a44366a6535c1).
|
||||
|
||||
# Example
|
||||
|
||||
```javascript
|
||||
// Define a feed using set operations
|
||||
const feed = intersectionFeed(
|
||||
unionFeed(
|
||||
dvmFeed({
|
||||
kind: 5300,
|
||||
pubkey: '19b78ccfa7c5e31e6bacbb3f2a1703f64b62017702e584440bf29a7e16263e8c',
|
||||
}),
|
||||
listFeed("10003:19ba654f26afd4930fd3d51baf4e26f1413b7aeec7190cd6c0cdf4d2f14cec6b:"),
|
||||
)
|
||||
wotFeed({min: 0.1}),
|
||||
scopeFeed("global"),
|
||||
)
|
||||
|
||||
// Create a controller, providing required context via FeedOptions
|
||||
const controller = new FeedController({
|
||||
feed,
|
||||
request,
|
||||
requestDVM,
|
||||
getPubkeysForScope,
|
||||
getPubkeysForWOTRange,
|
||||
onEvent: event => console.log("Event", event),
|
||||
onExhausted: () => console.log("Exhausted"),
|
||||
})
|
||||
|
||||
// Load notes using the feed
|
||||
const events = await controller.load(10)
|
||||
```
|
||||
@@ -1,13 +0,0 @@
|
||||
# @welshman/lib [](https://npmjs.com/package/@welshman/lib)
|
||||
|
||||
Some general-purpose utilities for use in @welshman apps.
|
||||
|
||||
Includes:
|
||||
|
||||
- LRU cache implementation
|
||||
- TaskQueue for throttling work to avoid locking up the UI
|
||||
- URL normalization (taken from normalize-url)
|
||||
- A global `ctx` variable which can be used for global configuration
|
||||
- CustomPromise, which provides an error type, and `defer` utility
|
||||
- Ramda-like utilities, but without auto-currying
|
||||
- Utils for throttling, working with nil, json, fetch, deep equals, etc.
|
||||
@@ -11,13 +11,6 @@ describe("Tools", () => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
describe("Basic Utils", () => {
|
||||
it("should check for nil values", () => {
|
||||
expect(T.isNil(null)).toBe(true)
|
||||
expect(T.isNil(undefined)).toBe(true)
|
||||
expect(T.isNil(0)).toBe(false)
|
||||
expect(T.isNil("")).toBe(false)
|
||||
})
|
||||
|
||||
it("should handle ifLet", () => {
|
||||
const fn = vi.fn()
|
||||
T.ifLet(undefined, fn)
|
||||
|
||||
+711
-651
File diff suppressed because it is too large
Load Diff
@@ -1,61 +0,0 @@
|
||||
# @welshman/net [](https://npmjs.com/package/@welshman/net)
|
||||
|
||||
Utilities having to do with connection management and nostr messages.
|
||||
|
||||
```typescript
|
||||
import {ctx, setContext} from '@welshman/lib'
|
||||
import {type TrustedEvent, createEvent, NOTE} from '@welshman/util'
|
||||
import {subscribe, publish, getDefaultNetContext} from '@welshman/net'
|
||||
|
||||
// Sets up customizable event valdation, handlers, etc
|
||||
setContext(getDefaultNetContext())
|
||||
|
||||
// Send a subscription
|
||||
const sub = subscribe({
|
||||
relays: ['wss://relay.example.com/'],
|
||||
filters: [{kinds: [1], limit: 1}],
|
||||
closeOnEose: true,
|
||||
timeout: 10000,
|
||||
})
|
||||
|
||||
sub.on(SubscriptionEvent.Event, (url: string, event: TrustedEvent) => {
|
||||
console.log(url, event)
|
||||
sub.close()
|
||||
})
|
||||
|
||||
// Publish an event
|
||||
const pub = publish({
|
||||
relays: ['wss://relay.example.com/'],
|
||||
event: createEvent(NOTE, {content: 'hi'}),
|
||||
})
|
||||
|
||||
pub.emitter.on('*', (status: PublishStatus, url: string) => {
|
||||
console.log(status, url)
|
||||
})
|
||||
|
||||
// The Tracker class can tell you which relays an event was read from or published to
|
||||
console.log(ctx.net.tracker.getRelays(event.id))
|
||||
```
|
||||
|
||||
The main reason this module exists is to support different backends via Executor and different `target` classes. For example, to add a local relay that automatically gets used:
|
||||
|
||||
```typescript
|
||||
import {setContext} from '@welshman/lib'
|
||||
import {LOCAL_RELAY_URL, Relay, Repository} from '@welshman/util'
|
||||
import {getDefaultNetContext, Multi, Local, Relays, Executor} from '@welshman/net'
|
||||
|
||||
const repository = new Repository()
|
||||
|
||||
const relay = new Relay(repository)
|
||||
|
||||
setContext(getDefaultNetContext({
|
||||
getExecutor: (relays: string[]) => {
|
||||
return new Executor(
|
||||
new Multi([
|
||||
new Local(relay),
|
||||
new Relays(remoteUrls.map(url => ctx.net.pool.get(url))),
|
||||
])
|
||||
)
|
||||
},
|
||||
}))
|
||||
```
|
||||
@@ -166,3 +166,5 @@ export class MultiPublish extends EventEmitter {
|
||||
this.removeAllListeners()
|
||||
}
|
||||
}
|
||||
|
||||
export const publish = (options: MultiPublishOptions) => new MultiPublish(options)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# @welshman/net [](https://npmjs.com/package/@welshman/net)
|
||||
|
||||
Utilities having to do with connection management and nostr messages.
|
||||
|
||||
```typescript
|
||||
import {ctx, setContext} from '@welshman/lib'
|
||||
import {type TrustedEvent, createEvent, NOTE} from '@welshman/util'
|
||||
import {subscribe, publish, getDefaultNetContext} from '@welshman/net'
|
||||
|
||||
// Sets up customizable event valdation, handlers, etc
|
||||
setContext(getDefaultNetContext())
|
||||
|
||||
// Send a subscription
|
||||
const sub = subscribe({
|
||||
relays: ['wss://relay.example.com/'],
|
||||
filters: [{kinds: [1], limit: 1}],
|
||||
closeOnEose: true,
|
||||
timeout: 10000,
|
||||
})
|
||||
|
||||
sub.on(SubscriptionEvent.Event, (url: string, event: TrustedEvent) => {
|
||||
console.log(url, event)
|
||||
sub.close()
|
||||
})
|
||||
|
||||
// Publish an event
|
||||
const pub = publish({
|
||||
relays: ['wss://relay.example.com/'],
|
||||
event: createEvent(NOTE, {content: 'hi'}),
|
||||
})
|
||||
|
||||
pub.emitter.on('*', (status: PublishStatus, url: string) => {
|
||||
console.log(status, url)
|
||||
})
|
||||
|
||||
// The Tracker class can tell you which relays an event was read from or published to
|
||||
console.log(ctx.net.tracker.getRelays(event.id))
|
||||
```
|
||||
|
||||
The main reason this module exists is to support different backends via Executor and different `target` classes. For example, to add a local relay that automatically gets used:
|
||||
|
||||
```typescript
|
||||
import {setContext} from '@welshman/lib'
|
||||
import {LOCAL_RELAY_URL, Relay, Repository} from '@welshman/util'
|
||||
import {getDefaultNetContext, Multi, Local, Relays, Executor} from '@welshman/net'
|
||||
|
||||
const repository = new Repository()
|
||||
|
||||
const relay = new Relay(repository)
|
||||
|
||||
setContext(getDefaultNetContext({
|
||||
getExecutor: (relays: string[]) => {
|
||||
return new Executor(
|
||||
new Multi([
|
||||
new Local(relay),
|
||||
new Relays(remoteUrls.map(url => ctx.net.pool.get(url))),
|
||||
])
|
||||
)
|
||||
},
|
||||
}))
|
||||
```
|
||||
@@ -29,6 +29,11 @@ const getDay = (ts: number) => Math.floor(ts / DAY)
|
||||
|
||||
export let repositorySingleton: Repository<TrustedEvent>
|
||||
|
||||
export type RepositoryUpdate = {
|
||||
added: TrustedEvent[]
|
||||
removed: Set<string>
|
||||
}
|
||||
|
||||
export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
||||
eventsById = new Map<string, E>()
|
||||
eventsByWrap = new Map<string, E>()
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# @welshman/signer [](https://npmjs.com/package/@welshman/signer)
|
||||
|
||||
Implementations of signer utilities and classes.
|
||||
|
||||
## Nips supported
|
||||
|
||||
- NIP 01 (private key login)
|
||||
- NIP 07
|
||||
- NIP 46
|
||||
- NIP 55
|
||||
- NIP 59 (gift wrapping, works with any signer that supports encryption)
|
||||
|
||||
## Examples
|
||||
|
||||
### NIP 01
|
||||
|
||||
```typescript
|
||||
import {makeSecret, Nip01Signer} from '@welshman/signer'
|
||||
|
||||
const signer = Nip01Signer.fromSecret(makeSecret())
|
||||
```
|
||||
|
||||
### NIP 07
|
||||
|
||||
```typescript
|
||||
import {getNip07, Nip07Signer} from '@welshman/signer'
|
||||
|
||||
if (getNip07()) {
|
||||
const signer = new Nip07Signer()
|
||||
}
|
||||
```
|
||||
|
||||
### NIP 55
|
||||
|
||||
```typescript
|
||||
import {getNip07, Nip07Signer} from '@welshman/signer'
|
||||
|
||||
if (getNip07()) {
|
||||
const signer = new Nip07Signer()
|
||||
}
|
||||
```
|
||||
|
||||
### NIP 46
|
||||
|
||||
```typescript
|
||||
import {createEvent, NOTE} from '@welshman/util'
|
||||
import {makeSecret, Nip46Broker, Nip46Signer} from '@welshman/signer'
|
||||
|
||||
const clientSecret = makeSecret()
|
||||
const relays = ['wss://relay.signer.example/']
|
||||
const broker = Nip46Broker.get({relays, clientSecret})
|
||||
const signer = new Nip46Signer(broker)
|
||||
const ncUrl = broker.makeNostrconnectUrl({name: "My app"})
|
||||
const abortController = new AbortController()
|
||||
|
||||
let response
|
||||
try {
|
||||
response = await broker.waitForNostrconnect(url, abortController)
|
||||
} catch (e: any) {
|
||||
if (e?.error) {
|
||||
showWarning(`Received error from signer: ${e.error}`)
|
||||
} else if (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
if (response) {
|
||||
// Now we know the bunker's pubkey and can do stuff with the signer
|
||||
const signerPubkey = response.event.pubkey
|
||||
|
||||
// Next time we want to use our signer, we can instantiate it like so:
|
||||
const newBroker = Nip46Broker.get({relays, clientSecret, signerPubkey})
|
||||
const newSigner = new Nip46Signer(newBroker)
|
||||
}
|
||||
```
|
||||
|
||||
### Using signers
|
||||
|
||||
```typescript
|
||||
import {createEvent, NOTE, DIRECT_MESSAGE} from '@welshman/util'
|
||||
|
||||
const signer = // Create your signer...
|
||||
const nip59 = Nip59.fromSigner(signer)
|
||||
|
||||
// Sign an event
|
||||
const event = await signer.sign(createEvent(NOTE, {content: "hi"}))
|
||||
|
||||
// Wrap a NIP 17 DM
|
||||
const rumor = await nip59.wrap(recipientPubkey, createEvent(DIRECT_MESSAGE, {content: "hi"}))
|
||||
|
||||
// Note that it returns a rumor; be sure to publish the `wrap`
|
||||
const wrap = rumor.wrap
|
||||
```
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
partition,
|
||||
first,
|
||||
} from "@welshman/lib"
|
||||
import {Maybe} from "@welshman/lib"
|
||||
import {Repository} from "@welshman/relay"
|
||||
import {matchFilters, getIdAndAddress, getIdFilters, Filter, TrustedEvent} from "@welshman/util"
|
||||
|
||||
@@ -142,7 +141,7 @@ export const adapter = <Source, Target>({
|
||||
|
||||
export type DeriveEventsMappedOptions<T> = {
|
||||
filters: Filter[]
|
||||
eventToItem: (event: TrustedEvent) => Maybe<T | T[] | Promise<T | T[]>>
|
||||
eventToItem: (event: TrustedEvent) => T | T[] | Promise<T | T[]> | undefined
|
||||
itemToEvent: (item: T) => TrustedEvent
|
||||
throttle?: number
|
||||
includeDeleted?: boolean
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# @welshman/util [](https://npmjs.com/package/@welshman/util)
|
||||
|
||||
Some nostr-specific utilities. For the most part, these will not have side effects or manage state. Includes:
|
||||
|
||||
- Event kind constants
|
||||
- A nostr address class
|
||||
- Utilities for working with nostr filters and tags
|
||||
- Helpers for working with zap events and lightning invoices
|
||||
- A `Encryptable` for ensuring payloads get encrypted
|
||||
- An implementation of an in-memory relay, backed by an events repository
|
||||
- Utilities for building events, validating signatures, and checking event type (replaceable, etc.)
|
||||
- Types and utilities for NIP 89 handlers
|
||||
- Types and utilities for NIP 51 lists
|
||||
- Types and utilities for NIP 01 profile metadata
|
||||
- Types and utilities for NIP 11 relay profiles
|
||||
Reference in New Issue
Block a user