diff --git a/composer.json b/composer.json index dec8e07..206f5b1 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "livewire/volt": "^1.6", "openspout/openspout": "^4.24", "power-components/livewire-powergrid": "^5.10", + "simplesoftwareio/simple-qrcode": "^4.2", "spatie/image": "^3.7", "spatie/laravel-google-fonts": "^1.4", "spatie/laravel-medialibrary": "^11.9", diff --git a/composer.lock b/composer.lock index 455b2dd..5d3f3e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0eb579a82f9d6b1b37ea98f73debb4a0", + "content-hash": "c0d4ad4f35c733ba8e694a6d0c7ff836", "packages": [ { "name": "akuechler/laravel-geoly", @@ -110,6 +110,60 @@ }, "time": "2024-07-15T14:28:34+00:00" }, + { + "name": "bacon/bacon-qr-code", + "version": "2.0.8", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22", + "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22", + "shasum": "" + }, + "require": { + "dasprid/enum": "^1.0.3", + "ext-iconv": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phly/keep-a-changelog": "^2.1", + "phpunit/phpunit": "^7 | ^8 | ^9", + "spatie/phpunit-snapshot-assertions": "^4.2.9", + "squizlabs/php_codesniffer": "^3.4" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "type": "library", + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "support": { + "issues": "https://github.com/Bacon/BaconQrCode/issues", + "source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8" + }, + "time": "2022-12-07T17:46:57+00:00" + }, { "name": "bitwasp/bech32", "version": "v0.0.1", @@ -550,6 +604,56 @@ ], "time": "2024-09-19T14:15:21+00:00" }, + { + "name": "dasprid/enum", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90", + "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90", + "shasum": "" + }, + "require": { + "php": ">=7.1 <9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "support": { + "issues": "https://github.com/DASPRiD/Enum/issues", + "source": "https://github.com/DASPRiD/Enum/tree/1.0.6" + }, + "time": "2024-08-09T14:30:48+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -5493,6 +5597,74 @@ ], "time": "2024-06-11T12:45:25+00:00" }, + { + "name": "simplesoftwareio/simple-qrcode", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/SimpleSoftwareIO/simple-qrcode.git", + "reference": "916db7948ca6772d54bb617259c768c9cdc8d537" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SimpleSoftwareIO/simple-qrcode/zipball/916db7948ca6772d54bb617259c768c9cdc8d537", + "reference": "916db7948ca6772d54bb617259c768c9cdc8d537", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "^2.0", + "ext-gd": "*", + "php": ">=7.2|^8.0" + }, + "require-dev": { + "mockery/mockery": "~1", + "phpunit/phpunit": "~9" + }, + "suggest": { + "ext-imagick": "Allows the generation of PNG QrCodes.", + "illuminate/support": "Allows for use within Laravel." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "SimpleSoftwareIO\\QrCode\\QrCodeServiceProvider" + ], + "aliases": { + "QrCode": "SimpleSoftwareIO\\QrCode\\Facades\\QrCode" + } + } + }, + "autoload": { + "psr-4": { + "SimpleSoftwareIO\\QrCode\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Simple Software LLC", + "email": "support@simplesoftware.io" + } + ], + "description": "Simple QrCode is a QR code generator made for Laravel.", + "homepage": "https://www.simplesoftware.io/#/docs/simple-qrcode", + "keywords": [ + "Simple", + "generator", + "laravel", + "qrcode", + "wrapper" + ], + "support": { + "issues": "https://github.com/SimpleSoftwareIO/simple-qrcode/issues", + "source": "https://github.com/SimpleSoftwareIO/simple-qrcode/tree/4.2.0" + }, + "time": "2021-02-08T20:43:55+00:00" + }, { "name": "simplito/bigint-wrapper-php", "version": "1.0.0", diff --git a/config/services.php b/config/services.php index e381dbf..b6dc748 100644 --- a/config/services.php +++ b/config/services.php @@ -15,6 +15,7 @@ return [ */ 'relay' => env('NOSTR_RELAY'), + 'nostr' => env('NOSTR_P'), 'postmark' => [ 'token' => env('POSTMARK_TOKEN'), diff --git a/database/migrations/2024_09_30_074429_add_payment_fields_to_einundzwanzig_plebs_table.php b/database/migrations/2024_09_30_074429_add_payment_fields_to_einundzwanzig_plebs_table.php new file mode 100644 index 0000000..acd487d --- /dev/null +++ b/database/migrations/2024_09_30_074429_add_payment_fields_to_einundzwanzig_plebs_table.php @@ -0,0 +1,28 @@ +string('payment_event', 255 * 2)->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('einundzwanzig_plebs', function (Blueprint $table) { + // + }); + } +}; diff --git a/docker-compose.yml b/docker-compose.yml index 08eb7c1..c62b2d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -67,7 +67,7 @@ services: timeout: 5s relay: ports: - - "7000" + - "7000:7000" volumes: - ./relay:/usr/src/app/db - ./relay/config.toml:/usr/src/app/config.toml diff --git a/package.json b/package.json index 86f936d..5b566d9 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "flatpickr": "^4.6.13", "laravel-echo": "^1.16.1", "laravel-vite-plugin": "^1.0", + "nostr-tools": "^2.7.2", "postcss": "^8.4.41", "pusher-js": "^8.4.0-rc2", "tailwindcss": "^3.4.10", - "vite": "^5.0" + "vite": "^5.0", + "webln": "^0.3.2" } } diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000..b1d79ac Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 0000000..537891f Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..120c7b5 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/einundzwanzig-alpha.jpg b/public/einundzwanzig-alpha.jpg new file mode 100644 index 0000000..d4a1b92 Binary files /dev/null and b/public/einundzwanzig-alpha.jpg differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000..1c664ba Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000..9d50fb5 Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico index e69de29..c0afeb7 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/resources/js/app.js b/resources/js/app.js index 1d958cd..03e84c6 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -2,6 +2,7 @@ import {Alpine, Livewire} from '../../vendor/livewire/livewire/dist/livewire.esm import nostrApp from "./nostrApp.js"; import nostrLogin from "./nostrLogin.js"; +import nostrZap from "./nostrZap.js"; import electionAdminCharts from "./electionAdminCharts.js"; import './bootstrap'; @@ -19,6 +20,7 @@ Alpine.store('nostr', { Alpine.data('nostrApp', nostrApp); Alpine.data('nostrLogin', nostrLogin); +Alpine.data('nostrZap', nostrZap); Alpine.data('electionAdminCharts', electionAdminCharts); Livewire.start(); diff --git a/resources/js/nostrZap.js b/resources/js/nostrZap.js new file mode 100644 index 0000000..98b7be1 --- /dev/null +++ b/resources/js/nostrZap.js @@ -0,0 +1,58 @@ +import NDK, {NDKEvent} from "@nostr-dev-kit/ndk"; +import { + nip57, +} from "nostr-tools"; + +export default (livewireComponent) => ({ + + invoice: livewireComponent.entangle('invoice', true), + + async zap(message, sender, amountToPay) { + const ndk = new NDK({ + explicitRelayUrls: ['wss://simple-relay.steuernsindraub21.xyz'], + enableOutboxModel: false, + }); + // Now connect to specified relays + await ndk.connect(); + const event = await ndk.fetchEvent({ + kinds: [32121], + authors: ['daf83d92768b5d0005373f83e30d4203c0b747c170449e02fea611a0da125ee6'] + }); + const amount = amountToPay * 1000; + console.log('event', event); + + const zapEndpoint = 'https://getalby.com/lnurlp/portaleinundzwanzig/callback'; + + const zapEvent = nip57.makeZapRequest({ + profile: sender, + event: event.id, + amount: amount, + relays: ['wss://simple-relay.steuernsindraub21.xyz'], + comment: message, + }); + console.log('zapEvent', zapEvent); + + const signedEvent = await window.nostr.signEvent(zapEvent); + console.log('signedEvent', signedEvent); + + let url = `${zapEndpoint}?amount=${amount}&nostr=${encodeURIComponent( + JSON.stringify(signedEvent) + )}`; + url = `${url}&comment=${encodeURIComponent(message)}`; + console.log('url', url); + + const res = await fetch(url); + const { pr: invoice, reason, status } = await res.json(); + + if (invoice) { + console.log('invoice', invoice); + this.invoice = invoice; + } else if (status === "ERROR") { + throw new Error(reason ?? "Unable to fetch invoice"); + } else { + throw new Error("Other error"); + } + + }, + +}); diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index 3cfd959..1f6a12a 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -28,7 +28,7 @@ }
Nostr Event für die Zahlung des + Mitgliedsbeitrags: {{ $currentPleb->payment_event }}
+{{ $events[0]['content'] }}
+|
+ Satoshis
+ |
+
+
+ ||
|---|---|---|
|
+ {{ collect(json_decode(collect($payment['tags'])->firstWhere('0', 'description')[1], true, 512, JSON_THROW_ON_ERROR)['tags'])->firstWhere('0', 'amount')[1] / 1000 }}
+ |
+
+ {{ $payment['content'] }}
+ |
+
+ {{ $payment['id'] }}
+ |
+