Fix admin delete hanging on "Deleting…" with Amber signer
Compute event id locally in CapacitorAmberSigner.signEvent instead of relying on Amber to echo it back. Amber (NIP-55) commonly returns only a bare `signature` for kind:5 deletions and kind:1985 moderation labels, leaving id empty — which failed the malformed-event check or emitted a bad event that stalled the relay forever (the "stuck on Deleting…" symptom). The id is a deterministic NIP-01 hash of the signed fields, so we derive it ourselves, making signature-only responses work for every kind including admin takedowns. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
26245f3d05
commit
977d71dc60
2 changed files with 27 additions and 5 deletions
|
|
@ -72,7 +72,14 @@ export function useDeleteEntity() {
|
|||
|
||||
// Admin takedown of someone else's content: also publish a client-side
|
||||
// moderation label so the app hides it even if relays won't honor a
|
||||
// cross-author NIP-09 deletion.
|
||||
// cross-author NIP-09 deletion. This label is what actually hides the
|
||||
// content across SkateSpots (see useAdminModeration), so it MUST succeed —
|
||||
// we await it and let a failure surface to the caller as an error.
|
||||
//
|
||||
// NOTE: this requires a SECOND Amber approval. Both signatures now compute
|
||||
// their event id locally (see CapacitorAmberSigner.signEvent), so a
|
||||
// signature-only Amber response no longer produces an empty id that stalls
|
||||
// the publish forever — the previous "stuck on Deleting…" cause.
|
||||
if (isAdmin && !isOwner) {
|
||||
const labelTags: string[][] = [
|
||||
['L', MODERATION_LABEL_NAMESPACE],
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
import type { NostrEvent, NostrSigner } from '@nostrify/nostrify';
|
||||
import { Capacitor, registerPlugin } from '@capacitor/core';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { nip19, getEventHash } from 'nostr-tools';
|
||||
|
||||
const AMBER_PACKAGE = 'com.greenart7c3.nostrsigner';
|
||||
|
||||
|
|
@ -242,13 +242,28 @@ export class CapacitorAmberSigner implements NostrSigner {
|
|||
|
||||
// Merge Amber's response over the original event so required fields are
|
||||
// never lost, then verify the essentials are present before returning.
|
||||
const merged: NostrEvent = {
|
||||
const pubkey = signed.pubkey ?? this.pubkey;
|
||||
const base = {
|
||||
kind: signed.kind ?? event.kind,
|
||||
content: signed.content ?? event.content,
|
||||
tags: signed.tags ?? event.tags,
|
||||
created_at: signed.created_at ?? event.created_at,
|
||||
pubkey: signed.pubkey ?? this.pubkey,
|
||||
id: signed.id ?? '',
|
||||
pubkey,
|
||||
};
|
||||
|
||||
// CRITICAL: Amber (NIP-55) commonly returns ONLY the `signature` for events
|
||||
// like kind:5 deletions and kind:1985 labels — no `id` and no full event
|
||||
// JSON. Previously we left `id: ''`, which failed the malformed-event check
|
||||
// below (or emitted a bad event that stalled the relay forever). The event
|
||||
// id is a deterministic NIP-01 hash of these fields, so we compute it
|
||||
// ourselves instead of depending on Amber to echo it back. This makes
|
||||
// signature-only responses work for EVERY kind — including admin takedowns.
|
||||
const id =
|
||||
signed.id && signed.id.length === 64 ? signed.id : getEventHash(base);
|
||||
|
||||
const merged: NostrEvent = {
|
||||
...base,
|
||||
id,
|
||||
sig: signed.sig,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue