Fix some ui bugs

This commit is contained in:
Jon Staab
2026-06-11 15:26:06 -07:00
parent 129697fccb
commit 287e599753
31 changed files with 1038 additions and 749 deletions
+48 -32
View File
@@ -1,4 +1,4 @@
import type { ISigner } from "@welshman/signer"
import { pubkey, signer, nip44EncryptToSelf } from "@welshman/app"
import type { Hex, QuorumMember } from "./protocol"
// ── Quorum & shard records ────────────────────────────────────────────────────
@@ -23,6 +23,34 @@ export type ShardRecord = {
encryptedShard: string
}
// ── Display model ─────────────────────────────────────────────────────────────
export type QuorumStatusKind = "complete" | "sending" | "failed" | "pending"
/**
* A quorum as shown in the UI — either a completed quorum or a still-pending DKG
* invite. Derived from protocol events in the repository, so it appears as soon as
* the invite is created (optimistically) and persists across reloads, even if the
* invite was never delivered to any relay.
*/
export type DisplayedQuorum = {
/** Stable id used for selection: the quorum pubkey once complete, else the invite id */
id: string
/** Set once DKG completes */
quorumPubkey?: Hex
/** The kind 7050 invite id (always set; the origin of the quorum) */
inviteId: Hex
members: QuorumMember[]
threshold: number
complete: boolean
status: QuorumStatusKind
statusLabel: string
/** Members who have broadcast round 1 (the creator always counts) */
joined: number
declined: number
createdAt: number
}
// ── Session helpers ───────────────────────────────────────────────────────────
/** Proof-of-knowledge from a round-1 message */
@@ -98,44 +126,32 @@ export type SigningSession = {
}
// ── Shard / polynomial encryption ────────────────────────────────────────────
// Shards and polynomials are self-encrypted: NIP-44 encrypt(myPubkey, ...).
// The signer derives the conversation key from (myPrivkey, myPubkey), which is
// unique to the key and opaque to any other party.
// Shards and polynomials are self-encrypted via the active session's signer:
// NIP-44 encrypt(myPubkey, ...). The signer derives the conversation key from
// (myPrivkey, myPubkey), which is unique to the key and opaque to any other
// party. The signer store is typed non-optional but is undefined at runtime
// when there is no active session, hence the guards.
export async function encryptShard(
shard: bigint,
myPubkey: Hex,
signer: ISigner,
): Promise<string> {
if (!signer.nip44) { throw new Error("Signer does not support NIP-44") }
return signer.nip44.encrypt(myPubkey, shard.toString(16))
export async function encryptShard(shard: bigint): Promise<string> {
return nip44EncryptToSelf(shard.toString(16))
}
export async function decryptShard(
encryptedShard: string,
myPubkey: Hex,
signer: ISigner,
): Promise<bigint> {
if (!signer.nip44) { throw new Error("Signer does not support NIP-44") }
const hex = await signer.nip44.decrypt(myPubkey, encryptedShard)
export async function decryptShard(encryptedShard: string): Promise<bigint> {
const $pubkey = pubkey.get()
const $signer = signer.get()
if (!$pubkey || !$signer) { throw new Error("Cannot decrypt without an active signer") }
const hex = await $signer.nip44.decrypt($pubkey, encryptedShard)
return BigInt("0x" + hex)
}
export async function encryptPoly(
poly: bigint[],
myPubkey: Hex,
signer: ISigner,
): Promise<string> {
if (!signer.nip44) { throw new Error("Signer does not support NIP-44") }
return signer.nip44.encrypt(myPubkey, JSON.stringify(poly.map(c => c.toString(16))))
export async function encryptPoly(poly: bigint[]): Promise<string> {
return nip44EncryptToSelf(JSON.stringify(poly.map(c => c.toString(16))))
}
export async function decryptPoly(
encryptedPoly: string,
myPubkey: Hex,
signer: ISigner,
): Promise<bigint[]> {
if (!signer.nip44) { throw new Error("Signer does not support NIP-44") }
const json = await signer.nip44.decrypt(myPubkey, encryptedPoly)
export async function decryptPoly(encryptedPoly: string): Promise<bigint[]> {
const $pubkey = pubkey.get()
const $signer = signer.get()
if (!$pubkey || !$signer) { throw new Error("Cannot decrypt without an active signer") }
const json = await $signer.nip44.decrypt($pubkey, encryptedPoly)
return (JSON.parse(json) as string[]).map(h => BigInt("0x" + h))
}