'handleNostrLoggedIn', 'nostrLoggedOut' => 'handleNostrLoggedOut', ]; public function mount(): void { if (NostrAuth::check()) { $this->currentPubkey = NostrAuth::pubkey(); $this->currentPleb = EinundzwanzigPleb::query() ->with([ 'paymentEvents' => fn ($query) => $query->where('year', date('Y')), 'profile', ]) ->where('pubkey', $this->currentPubkey)->first(); if ($this->currentPleb) { $this->email = $this->currentPleb->email; if ($this->currentPleb->nip05_handle) { $this->nip05Handle = $this->currentPleb->nip05_handle; // Get all NIP-05 handles for the current pubkey $this->nip05VerifiedHandles = $this->getNip05HandlesForPubkey($this->currentPubkey); if (count($this->nip05VerifiedHandles) > 0) { $this->nip05Verified = true; $this->nip05VerifiedHandle = $this->nip05VerifiedHandles[0]; // Check if verified handle differs from database handle if (! in_array($this->nip05Handle, $this->nip05VerifiedHandles, true)) { $this->nip05HandleMismatch = true; } } } $this->no = $this->currentPleb->no_email; $this->showEmail = ! $this->no; $this->amountToPay = config('app.env') === 'production' ? 21000 : 1; if ($this->currentPleb->paymentEvents->count() < 1) { $this->createPaymentEvent(); $this->currentPleb->load('paymentEvents'); } $this->loadEvents(); $this->listenForPayment(); } } } public function updatedNo(): void { $this->showEmail = ! $this->no; $this->currentPleb->update([ 'no_email' => $this->no, ]); } public function updatedFax(): void { $this->js('alert("Markus Turm wird sich per Fax melden!")'); } public function updatedNip05Handle(): void { $this->nip05Handle = strtolower($this->nip05Handle); } public function saveEmail(): void { $this->validate([ 'email' => 'required|email', ]); $this->currentPleb->update([ 'email' => $this->email, ]); Flux::toast('E-Mail Adresse gespeichert.'); } public function saveNip05Handle(): void { $this->validate([ 'nip05Handle' => 'required|string|max:255|regex:/^[a-z0-9_-]+$/|unique:einundzwanzig_plebs,nip05_handle', ]); $nip05Handle = strtolower($this->nip05Handle); $this->currentPleb->update([ 'nip05_handle' => $nip05Handle, ]); Flux::toast('NIP-05 Handle gespeichert.'); } public function pay($comment): mixed { $paymentEvent = $this->currentPleb ->paymentEvents() ->where('year', date('Y')) ->first(); if ($paymentEvent->btc_pay_invoice) { return redirect()->away('https://pay.einundzwanzig.space/i/'.$paymentEvent->btc_pay_invoice); } try { $response = \Illuminate\Support\Facades\Http::withHeaders([ 'Authorization' => 'token '.config('services.btc_pay.api_key'), ])->post( 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices', [ 'amount' => $this->amountToPay, 'metadata' => [ 'orderId' => $comment, 'orderUrl' => url()->route('association.profile'), 'itemDesc' => 'Mitgliedsbeitrag '.date('Y').' von nostr:'.$this->currentPleb->npub, 'posData' => [ 'event' => $paymentEvent->event_id, 'pubkey' => $this->currentPleb->pubkey, 'npub' => $this->currentPleb->npub, ], ], 'checkout' => [ 'expirationMinutes' => 60 * 24, 'redirectURL' => url()->route('association.profile'), 'redirectAutomatically' => true, 'defaultLanguage' => 'de', ], ], )->throw(); $paymentEvent->btc_pay_invoice = $response->json()['id']; $paymentEvent->save(); return redirect()->away($response->json()['checkoutLink']); } catch (\Exception $e) { Flux::toast( 'Fehler beim Erstellen der Rechnung. Bitte versuche es später erneut: '.$e->getMessage(), variant: 'danger', ); return redirect()->route('association.profile'); } } public function listenForPayment(): void { $paymentEvent = $this->currentPleb ->paymentEvents() ->where('year', date('Y')) ->first(); if ($paymentEvent->btc_pay_invoice) { $response = \Illuminate\Support\Facades\Http::withHeaders([ 'Authorization' => 'token '.config('services.btc_pay.api_key'), ]) ->get( 'https://pay.einundzwanzig.space/api/v1/stores/98PF86BoMd3C8P1nHHyFdoeznCwtcm5yehcAgoCYDQ2a/invoices/'.$paymentEvent->btc_pay_invoice, ); if ($response->json()['status'] === 'Expired') { $paymentEvent->btc_pay_invoice = null; $paymentEvent->paid = false; $paymentEvent->save(); } if ($response->json()['status'] === 'Settled') { $paymentEvent->paid = true; $paymentEvent->save(); $this->currentYearIsPaid = true; } } if ($paymentEvent->paid) { $this->currentYearIsPaid = true; } $paymentEvent = $paymentEvent->refresh(); $this->payments = $this->currentPleb ->paymentEvents() ->where('paid', true) ->get(); } public function save($type): void { $this->form->validate(); if (! $this->form->check) { $this->js('alert("Du musst den Statuten zustimmen.")'); return; } $this->currentPleb ->update([ 'association_status' => $type, ]); } public function createPaymentEvent(): void { $note = new NostrEvent; $note->setKind(32121); $note->setContent( 'Dieses Event dient der Zahlung des Mitgliedsbeitrags für das Jahr '.date( 'Y', ).'. Bitte bezahle den Betrag von '.number_format($this->amountToPay, 0, ',', '.').' Satoshis.', ); $note->setTags([ ['d', $this->currentPleb->pubkey.','.date('Y')], ['zap', 'daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6', config('services.relay'), '1'], ]); $signer = new Sign; $signer->signEvent($note, config('services.nostr')); $eventMessage = new EventMessage($note); $relayUrl = config('services.relay'); $relay = new Relay($relayUrl); $relay->setMessage($eventMessage); $result = $relay->send(); $this->currentPleb->paymentEvents()->create([ 'year' => date('Y'), 'event_id' => $result->eventId, 'amount' => $this->amountToPay, ]); } public function loadEvents(): void { $subscription = new Subscription; $subscriptionId = $subscription->setId(); $filter1 = new Filter; $filter1->setKinds([32121]); $filter1->setAuthors(['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6']); $filters = [$filter1]; $requestMessage = new RequestMessage($subscriptionId, $filters); $relays = [ new Relay(config('services.relay')), ]; $relaySet = new RelaySet; $relaySet->setRelays($relays); $request = new Request($relaySet, $requestMessage); $response = $request->send(); $this->events = collect($response[config('services.relay')]) ->map(function ($event) { if (! isset($event->event)) { return false; } return [ 'id' => $event->event->id, 'kind' => $event->event->kind, 'content' => $event->event->content, 'pubkey' => $event->event->pubkey, 'tags' => $event->event->tags, 'created_at' => $event->event->created_at, ]; }) ->filter() ->unique('id') ->toArray(); } public function copyRelayUrl(): void { $relayUrl = 'wss://nostr.einundzwanzig.space'; $this->js("navigator.clipboard.writeText('{$relayUrl}')"); Flux::toast('Relay-Adresse in die Zwischenablage kopiert!'); } public function copyWatchtowerUrl(): void { $watchtowerUrl = '03a09f56bba3d2c200cc55eda2f1f069564a97c1fb74345e1560e2868a8ab3d7d0@62.171.139.240:9911'; $this->js("navigator.clipboard.writeText('{$watchtowerUrl}')"); Flux::toast('Watchtower-Adresse in die Zwischenablage kopiert!'); } } ?>
Exklusive Schreib-Rechte auf Premium Nostr Relay von Einundzwanzig.
@if($currentPleb && $currentPleb->association_status->value > 1 && $currentYearIsPaid)Ein Outbox-Relay ist wie ein Postbote für deine Nostr-Nachrichten. Es speichert und verteilt deine Posts. Um unser Relay nutzen zu können, musst du es in deinem Nostr-Client hinzufügen.
Gehe in deinem Nostr-Client zu den Einstellungen (meistens "Settings" oder "Relays") und füge folgende Outbox-Relay-Adresse hinzu:
wss://nostr.einundzwanzig.space
Wichtige Hinweise: Du kannst deine Posts auf mehreren Relays gleichzeitig veröffentlichen. So stellst du sicher, dass deine Inhalte auch über unser Relay erreichbar sind.
Verifiziere deine Identität mit einem menschenlesbaren Nostr-Namen.
Regeln für dein Handle: Nur Kleinbuchstaben (a-z), Zahlen (0-9) und die Zeichen "-" und "_" sind erlaubt. Dein Handle wird automatisch kleingeschrieben.
Du hast {{ count($nip05VerifiedHandles) }} aktive Handles für deinen Pubkey!
@if($nip05HandleMismatch)Die Synchronisation zu {{ $nip05Handle }}@einundzwanzig.space wird automatisch im Hintergrund durchgeführt.
@endifDeine aktivierten Handles:
Dein Handle {{ $nip05Handle }}@einundzwanzig.space ist noch nicht aktiv.
Das Handle ist gespeichert, aber noch nicht in der NIP-05 Konfiguration veröffentlicht. Der Vorstand wird dies bald aktivieren.
Nutze unseren Watchtower zum Schutz deiner Lightning Channel.
Ein Watchtower überwacht deine Lightning Channel und schützt sie, falls deine Node offline ist. Wenn du die Zahlung von Channel-Closing-Transaktionen verpasst, kümmert sich der Watchtower darum und verhindert den Verlust deiner Sats.
Um unseren Watchtower zu nutzen, füge folgende URI in deiner Lightning Node Konfiguration hinzu:
03a09f56bba3d2c200cc55eda2f1f069564a97c1fb74345e1560e2868a8ab3d7d0@62.171.139.240:9911
Einrichtung für gängige Lightning Clients:
watchtower-client Plugin mit der URIWichtig: Der Watchtower überwacht deine Channel passiv. Er hat keinen Zugriff auf deine privaten Schlüssel oder dein Guthaben.
@if($currentPleb->profile?->name) {{ $currentPleb->profile->name }} @endif
{{ $currentPleb->pubkey }}
{{ $currentPleb->npub }}
{{ $currentPleb->nip05_handle }}
Perfekt für mobile Android Geräte. Eine App, in der man alle Keys/nsecs verwalten kann.
Browser-Erweiterung in die man seinen Key/nsec eingeben kann. Pro Alby-Konto ein nsec.
Browser-Erweiterung für Chrome Browser. Multi-Key fähig.
Browser-Erweiterung für Firefox Browser. Multi-Key fähig.
Profil in der Datenbank vorhanden.
Nur Personen können Mitglied werden und zahlen 21.000 Satoshis im Jahr. Firmen melden sich bitte direkt an den Vorstand.
Falls du möchtest, kannst du hier eine E-Mail Adresse hinterlegen, damit der Verein dich darüber informieren kann, wenn es Neuigkeiten gibt.
Am besten eine anonymisierte E-Mail Adresse verwenden. Wir sichern diese Adresse AES-256 verschlüsselt in der Datenbank ab.
@if($currentYearIsPaid) Du bist derzeit ein Mitglied des Vereins. Das aktuelle Jahr ist bezahlt. @else Du wirst nach Zahlung des Vereinsbeitrages zum Mitglied. Das aktuelle Jahr ist noch nicht bezahlt. @endif
Nostr Event für die Zahlung des Mitgliedsbeitrags: {{ $currentPleb->paymentEvents->last()->event_id }}
{{ $latestEvent['content'] }}
Unser Nostr-Relay konnte derzeit nicht erreicht werden, um eine Zahlung zu initialisieren. Bitte versuche es später noch einmal.
|
Satoshis
|
Jahr
|
Event-ID
|
Quittung
|
|---|---|---|---|
|
{{ $payment->amount }}
|
{{ $payment->year }}
|
{{ $payment->event_id }}
|
@if($payment->btc_pay_invoice)
|