rename client, update docs/skills
tests / tests (push) Failing after 5m4s

This commit is contained in:
2026-06-18 19:31:14 +00:00
parent dfeb7a747b
commit fe5c11b00f
92 changed files with 1811 additions and 5268 deletions
+80
View File
@@ -0,0 +1,80 @@
import {get, writable} from "svelte/store"
import {TaskQueue, uniq, now} from "@welshman/lib"
import {getPubkeyTagValues, getRelaysFromList, prep} from "@welshman/util"
import type {TrustedEvent, SignedEvent, EventTemplate} from "@welshman/util"
import {Nip59} from "@welshman/signer"
import {MergedThunk, Thunks} from "./thunk.js"
import type {ThunkOptions} from "./thunk.js"
import {User} from "../user.js"
import {MessagingRelayLists} from "./messagingRelayLists.js"
import type {IApp} from "../app.js"
export type SendWrappedOptions = Omit<
ThunkOptions,
"event" | "relays" | "recipient" | "app" | "user"
> & {
event: EventTemplate
recipients: string[]
}
/**
* Per-app wrap (NIP-59) state: the unwrap queue plus failure/dedup
* tracking. Scoped to `app.user`, so an app only ever unwraps its own user's
* messages into its own repository — which is what keeps DM history from being
* merged across identities. The repository subscription that feeds it lives in
* `appPolicyWraps`.
*/
export class Wraps {
failedUnwraps = new Set<string>()
queue: TaskQueue<TrustedEvent>
constructor(readonly app: IApp) {
this.queue = new TaskQueue<TrustedEvent>({
batchSize: 50,
batchDelay: 30,
processItem: async (wrap: TrustedEvent) => {
const signer = this.app.user?.signer
const recipient = this.app.user?.pubkey
// Only unwrap messages addressed to our user
if (!signer || !recipient || !getPubkeyTagValues(wrap.tags).includes(recipient)) {
return
}
try {
const rumor = await Nip59.fromSigner(signer).unwrap(wrap as SignedEvent)
this.app.wrapManager.add({wrap: wrap as SignedEvent, rumor, recipient})
} catch (e) {
this.failedUnwraps.add(wrap.id)
}
},
})
}
enqueue = (wrap: TrustedEvent) => {
if (this.failedUnwraps.has(wrap.id)) return
if (this.app.wrapManager.getRumor(wrap.id)) return
this.queue.push(wrap)
}
// NIP-59: wrap an event for each recipient (using their messaging relays) and
// publish the wraps as the app's user.
publish = async ({event, recipients, ...options}: SendWrappedOptions) => {
const user = User.require(this.app)
// Stabilize the event id across the different wraps
const stableEvent = prep(event, user.pubkey, now())
return new MergedThunk(
await Promise.all(
uniq(recipients).map(async recipient => {
const relays = getRelaysFromList(await this.app.use(MessagingRelayLists).load(recipient))
return this.app.use(Thunks).publish({event: stableEvent, relays, recipient, ...options})
}),
),
)
}
}