{"id":48217651,"url":"https://github.com/bmmmm/db-wallet","last_synced_at":"2026-04-04T19:01:41.377Z","repository":{"id":328249107,"uuid":"1114801747","full_name":"bmmmm/db-wallet","owner":"bmmmm","description":"Drink tracking wallet for friends of bitcircus101.de and Datenburg e.V. Bonn.","archived":false,"fork":false,"pushed_at":"2025-12-20T23:12:41.000Z","size":105,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-22T09:43:52.092Z","etag":null,"topics":["bonn","hackspace"],"latest_commit_sha":null,"homepage":"https://bmmmm.github.io/db-wallet/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bmmmm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-11T22:54:03.000Z","updated_at":"2025-12-20T23:12:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bmmmm/db-wallet","commit_stats":null,"previous_names":["bmmmm/db-wallet"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bmmmm/db-wallet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmmmm%2Fdb-wallet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmmmm%2Fdb-wallet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmmmm%2Fdb-wallet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmmmm%2Fdb-wallet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bmmmm","download_url":"https://codeload.github.com/bmmmm/db-wallet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmmmm%2Fdb-wallet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31409471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bonn","hackspace"],"created_at":"2026-04-04T19:01:40.723Z","updated_at":"2026-04-04T19:01:41.320Z","avatar_url":"https://github.com/bmmmm.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# db-wallet\n\nEin leichtes, komplett browserbasiertes Getränke-Wallet für Freund:innen vom\nHackspace [bitcircus101.de](https://bitcircus101.de) in Bonn und der\n[Datenburg e.V. Bonn](https://datenburg.org/) – **kein Backend, kein Server**.\nAlle Daten liegen ausschließlich lokal im Browser (`localStorage`) und lassen\nsich per Export/Import zwischen Geräten übertragen.\n\n## Demo\n\n- Live-Demo (GitHub Pages): https://bmmmm.github.io/db-wallet/\n  - Das ist das Deployment aus dem Original-Repo und dient hier als Beispiel.\n\n## Schnellstart\n\n1. `index.html` öffnen.\n2. Namen für die Nutzer:in eingeben (oder leer lassen für Zufall) → weiter zu\n   `wallet.html#\u003cname\u003e` (z. B. `wallet.html#peter`).\n3. Optional: Theme am Seitenende wählen; Auswahl wird gespeichert.\n4. Optional: In `wallet.html` → Export → „QR-Code (kurz) anzeigen“ (kompakt,\n   minuten-genau, merge-fähig). Tipp: QR-Code antippen → PNG downloaden; der\n   Link unter dem QR ist zum Kopieren markiert.\n\n## Funktionen\n\n- Buchen: Getränke hinzufügen, Tagesstatistik inkl. Diagramm/Log/Raw.\n- Korrigieren: letzte Buchung rückgängig (Löschmarker im Log, syncbar), danach komplette Neuberechnung aus dem Log.\n- Bezahlen: Offene Getränke ausgleichen; Zahlungen sichtbar im Log.\n- Guthaben: Gutschriften aufladen und abbauen wie Vorrat.\n- Historie: Diagramm (inkl. Tages-Drinkcount in `[n]`), Log mit IDs/Ranges\n  inklusive Löschmarker, Raw-Daten pro Nutzer:in/alle.\n- Statistik: Offen/Guthaben werden ausgeblendet, wenn sie 0 sind.\n- Verwaltung: Einträge bearbeiten/löschen, Nutzer:innen einzeln oder gesammelt\n  löschen.\n- Migration: v1-Wallets können für robusten QR-Export auf v2 migriert werden.\n- Import/Export: Link (auto-merge), kompakter QR-Code oder JSON-Datei; Export\n  enthält auch Theme + Wallet-ID gegen Namens-Kollisionen.\n\n## Action Codes (QR)\n\nAction Codes können **lokal (wallet-gebunden)** oder **global (wallet-agnostisch)**\nsein. Der Scope wird beim Erstellen/Bearbeiten gewählt. Beim Scannen erfolgt\n**sofort** eine Buchung (ohne Reload):\n\n- Typ **Trinken**: bucht ein Drink-Event.\n- Typ **Guthaben**: bucht eine Gutschrift.\n\nWichtig:\n\n- Verwaltung erfolgt inline per Buttons (New action code, Bearbeiten, Löschen).\n- Die Mengenfrage im Inline-Formular passt sich dem Typ an (trinken vs gutschreiben).\n- Pro Code ist der Scope wählbar: 🔒 Lokal (wallet‑gebunden) oder 🌍 Global.\n- Lokale Action Codes sind an eine Wallet gebunden (Ziel-WalletId steckt im QR).\n- Globale Action Codes sind stateless und wirken auf das aktuell geöffnete Wallet.\n- Öffnest du `wallet.html#acg:…` direkt, wird bei mehreren Wallets eine Auswahl\n  angezeigt; bei genau einem Wallet wird automatisch gebucht.\n- Beim Bearbeiten (Name/Menge/Typ) wird der QR bei Bedarf neu erzeugt; alte Codes\n  werden dann **ungültig** und werden beim Einlösen strikt abgelehnt.\n- Der Betrag wird aus dem gespeicherten Action Code gelesen (nicht aus\n  manipulierbaren QR-Feldern).\n- QR-Payloads sind schlank gehalten; ältere Payloads bleiben kompatibel.\n\n### Globale Action Codes (deterministisch)\n\nGlobale Action Codes (`#acg:...`) sind rein datengetrieben:\n\n- deterministisch: gleiche Eingaben → gleicher Link\n- keine Speicherung, keine Secrets\n- Validierung: Typ `d/g`, Menge `1..100`\n- wenn kein Wallet geöffnet ist, wird eine Hinweis‑Meldung angezeigt\n- wirkt nur beim Scannen/Öffnen des Links, nicht automatisch\n\n## Sync Status (Top-Row)\n\nDie Wallet zeigt einen rein lokalen Sync-Status an, um den Stand zwischen\nGeräten (z. B. Laptop ↔ Handy) sichtbar zu machen. Es gibt **keinen**\nHintergrund-Sync: Synchronisieren passiert ausschließlich durch Export/Import.\n\n### Wie Syncing funktioniert\n\n- Export/Import (Link/QR/JSON) ist der einzige Weg, Daten zwischen Geräten zu\n  übertragen.\n- Für die Sync-Anzeige zählen ausschließlich **Events** (nicht Getränkemengen).\n  **1 Event = 1 Schritt** auf der Timeline – unabhängig davon, ob ein Event `+1`\n  oder `+10` enthält.\n\n### Wie man die Sync-Zeile liest (Mental Model)\n\nDie ASCII-Timeline basiert auf der Anzahl der Events:\n\n- `===|`: fester Marker für „zuletzt sicher gemeinsam“ (die `=` wachsen nicht)\n- Zeichen nach `|`: lokale Divergenz in Event-Schritten (1 Zeichen = 1 Event)\n- Die Anzahl der abweichenden lokalen Events wird zusätzlich separat als `Δ`\n  angezeigt (kein `ΔR`).\n\nBeispiele:\n\n- `Sync: ===|` → identisch\n- `Sync: ===|MMMM` → lokal 4 Events weiter\n- `Sync: …==|MMMMMMMMMMMMMMMMMMMMMMMM` → Divergenz gekürzt (rechts priorisiert)\n\n### Ampel-Logik \u0026 Reset\n\n- Grün: Sync aktuell (≤ 5 Tage)\n- Gelb: Sync alt (6–10 Tage)\n- Rot: Sync veraltet (≥ 11 Tage) → Klick führt zur Export-Sektion\n- Button „✅ passt“: manueller Vertrauens-Reset (setzt den Sync-Stand auf\n  „gleich“ auf diesem Gerät, ohne Export/Import).\n\n## Geräte-Bewusstsein (pro Wallet, synchronisiert)\n\nPro Wallet gibt es eine synchronisierte Geräte-Liste (mit `deviceKey`, Symbol,\n`lastSeenAt`), die bei Export/Import mitgesendet und deterministisch gemerged\nwird:\n\n- Maximal 6 Geräte pro Wallet (älteste Einträge werden automatisch entfernt).\n- Pro Wallet ist jedes Symbol (`L/M/D/K/T/*`) eindeutig und wird per Buttons in\n  der Top-Row zugewiesen (keine Texteingabe, keine Prompts).\n- Das lokale Geräte-Symbol zeigt die eigene Device-ID direkt daneben (mobile-tauglich,\n  kein Hover nötig).\n\n## Code-Aufteilung (Stage 1)\n\nEin Teil der UI-Logik wurde aus `wallet-ui.js` in kleinere Dateien ausgelagert,\ndamit agentic coding / Review einfacher ist:\n\n- `wallet-device-ui.js`: Geräte-Symbol-Picker in der Top-Row (inkl. sichtbarer Device-ID)\n- `wallet-sync-ui.js`: Sync-Status-Zeile (Ampel, Timeline, „✅ passt“)\n- `wallet-export-ui.js`: Export-UI (Link, QR, JSON, QR-Session-Cache)\n- `wallet-history-ui.js`: History-Ansicht (Diagramm/Log/Raw, Log-Tools)\n\nHinweis: `wallet.html` lädt diese Dateien vor `wallet-ui.js`.\n\n## Architektur (Core vs UI)\n\nCore (Logik/Codec/Storage):\n- `wallet-helpers.js`, `wallet-storage.js`, `wallet-import-v2.js`\n- `wallet-summary.js`, `wallet-sync.js`, `migration.js`\n- `action-codes.js` (Normalisierung, Merge, Hash encode/decode)\n- `hash-router.js` (Hash-Parsing)\n\nUI (DOM + Interaktion):\n- `index-ui.js`, `wallet-ui.js`\n- `wallet-device-ui.js`, `wallet-history-ui.js`, `wallet-export-ui.js`, `wallet-sync-ui.js`\n- `import-preview.js`, `theme.js`\n\nTools:\n- `self-check.js` (Konsole: `window.dbWalletSelfCheck.run()`)\n\n## Self-Check\n\nIm Browser (z. B. `wallet.html`) in der Konsole ausführen:\n\n```\nwindow.dbWalletSelfCheck.run()\n```\n\nDer Self-Check prüft u. a. Storage-Roundtrip, Import v2, Migration, Hash-Parsing,\nSummary-Parität, Tombstones/Undo und Action-Code-Payloads.\n\n## Datenmodell Hinweise\n\n- `wallet.deviceId` (Export/Sync-Metadatum) und `wallet.seq` (Event-Zähler pro Device-Key)\n  bleiben getrennt; eine Zusammenlegung wäre nicht rückwärtskompatibel.\n\n## Dateien\n\n| Datei                                          | Zweck                                                                     |\n| ---------------------------------------------- | ------------------------------------------------------------------------- |\n| [`index.html`](./index.html)                   | Startseite, Nutzer:innenwahl, Import/Export, Theme-Wahl                   |\n| [`wallet.html`](./wallet.html)                 | Drinks, Guthaben, Zahlungen, Historie/Raw, Theme-Wahl                     |\n| [`index-ui.js`](./index-ui.js)                 | UI-Logik der Startseite (Routing, Liste, Import)                          |\n| [`wallet-ui.js`](./wallet-ui.js)               | Wallet-Composer/Entry (DOM-Wiring, Hash-Routing, Module initialisieren)   |\n| [`wallet-device-ui.js`](./wallet-device-ui.js) | Geräte-Symbol-Picker (Top-Row, sichtbare Device-ID)                       |\n| [`wallet-sync-ui.js`](./wallet-sync-ui.js)     | Sync-Status UI (Ampel + ASCII-Timeline + „✅ passt“)                       |\n| [`wallet-export-ui.js`](./wallet-export-ui.js) | Export UI (Link/QR/JSON, QR-Session-Cache, PNG-Download)                  |\n| [`wallet-helpers.js`](./wallet-helpers.js)     | Helper (Base64URL, gzip, Storage-Safety, Registry)                        |\n| [`wallet-storage.js`](./wallet-storage.js)     | Wallet-Storage/Model (load/save, deviceKey, devices-Liste)                |\n| [`wallet-import-v2.js`](./wallet-import-v2.js) | Import/Export-Codec v2 + Hash-Import (inkl. Action Codes)                 |\n| [`wallet-summary.js`](./wallet-summary.js)     | Berechnung von Total/Offen/Guthaben/Diagramm (pure)                       |\n| [`wallet-sync.js`](./wallet-sync.js)           | Sync-Status Helfer (Ampel + ASCII-Timeline; lokal)                        |\n| [`action-codes.js`](./action-codes.js)         | Action Codes UI + Hash-Encoding/Decoding                                  |\n| [`wallet-history-ui.js`](./wallet-history-ui.js) | History-UI (Diagramm/Log/Raw, Log-Tools)                                 |\n| [`hash-router.js`](./hash-router.js)           | Hash-Parsing (ac/import/i2/i2u)                                           |\n| [`self-check.js`](./self-check.js)             | In-Browser Self-Check (Konsole)                                           |\n| [`theme.js`](./theme.js)                       | Theme-Logik (Auswahl + Speicherung)                                       |\n| [`import-preview.js`](./import-preview.js)     | Import-Auswahl (persist/preview) + Preview-Flow                           |\n| [`themes.css`](./themes.css)                   | Theme-Paletten (CSS-Variablen)                                            |\n| [`colors.html`](./colors.html)                 | Vorschau aller 5 Themes mit Farbbalken \u0026 UI-Beispielen                    |\n| [`colors.css`](./colors.css)                   | Styles für die Theme-Vorschau                                             |\n| [`style.css`](./style.css)                     | Basis-UI, responsive Layout                                               |\n| [`qrcodegen.js`](./qrcodegen.js)               | QR-Code-Generator (Nayuki)                                                |\n| [`migration.js`](./migration.js)               | Migration v1 → v2 (für QR-Export)                                         |\n\n## Deployment (statisch, „Pages“-Style)\n\ndb-wallet ist eine reine Static-Webapp (HTML/CSS/JS) und kann auf vielen\nOpen-Source-freundlichen „Pages“-Diensten deployed werden.\n\n### Hosted „Pages“-Dienste (GitHub-Pages-ähnlich)\n\n- **Codeberg Pages** (Forgejo-basiert): https://codeberg.page/\n- **GitLab Pages** (gitlab.com oder self-hosted GitLab): https://docs.gitlab.com/ee/user/project/pages/\n\n### Self-hosted (Forgejo / Gitea)\n\nForgejo/Gitea bringen üblicherweise kein integriertes „Pages“-Feature wie GitHub/GitLab mit.\nTypischer Setup:\n\n1. Repo in **Forgejo** (https://forgejo.org/) oder **Gitea** (https://about.gitea.com/)\n2. CI (Forgejo Actions / Woodpecker / Drone) baut die Static Site (falls nötig)\n3. Deploy auf einen separaten Static Host (z. B. Nginx/Caddy oder S3/MinIO)\n\nTipp: Wenn du keinen Build brauchst, reicht auch simples Hosting des Repo-Roots als Static-Verzeichnis.\n\nEs sind **keine** Build-Schritte, **keine** Server-Komponenten und **keine**\nAPI-Keys notwendig.\n\nBeispiel-URL (GitHub Pages):  \nhttps://bmmmm.github.io/db-wallet/\n\nViel Spaß mit deinem minimalistischen, schnellen Getränke-Wallet 🍹🚀\n\n## LLM Notes (for quick repo understanding)\n\n- File map (core vs UI): Core/codec/storage in `wallet-helpers.js`, `wallet-storage.js`, `wallet-import-v2.js`, `wallet-summary.js`, `wallet-sync.js`, `migration.js`, `action-codes.js`, `hash-router.js`. UI in `index-ui.js`, `wallet-ui.js`, `wallet-device-ui.js`, `wallet-sync-ui.js`, `wallet-export-ui.js`, `wallet-history-ui.js`, `import-preview.js`, `theme.js`.\n- Invariants: storage prefix `db-wallet:`, registry key `db-wallet:registry`, hash formats `#\u003cuserId\u003e`, `#import:`, `#i2:`, `#i2u:`, `#ac:`, `#acg:`; event schema `{id,t,n?,ts,ref?}` with tombstones `t:\"x\"` + `ref`; action code SOFT/HARD limits 6/10; global `#acg:` deterministic and stateless.\n- Entrypoints \u0026 flow: `index.html` → `index-ui.js` (list/create/import) and `wallet.html` → `wallet-ui.js` (hash classify → load wallet → compute summary → render UI); `hash-router.js` is the single classifier/parser for hashes.\n- Where to edit: storage/model in `wallet-storage.js`; summary/tombstones in `wallet-summary.js`; action-code encode/decode + UI in `action-codes.js`; hash parsing in `hash-router.js`; UI wiring in `index-ui.js` / `wallet-ui.js` / `wallet-history-ui.js`.\n- Quick manual checks: open `index.html` → create/open wallet → add drinks/pay → undo (tombstone) → export/import v2 → local/global action codes → open `wallet.html#acg:…` with 1+ wallets → `window.dbWalletSelfCheck.run()`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbmmmm%2Fdb-wallet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbmmmm%2Fdb-wallet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbmmmm%2Fdb-wallet/lists"}