Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions docs/feature-ideas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# AccBot — Nápady na nové funkce

Přehled potenciálních vylepšení na základě kompletní analýzy celého codebase (iOS, Android, .NET backend, Docker, Avalonia wizard).

---

## Quick Wins (malý effort, okamžitá hodnota)

### 1. Streak counter — série úspěšných nákupů
Zobrazit na Dashboardu počet po sobě jdoucích úspěšných DCA exekucí ("Jsi na 47denní sérii!"). Milestone badges za 7, 30, 100, 365, 1000 dní.

**Proč:** DCA je o dlouhodobé disciplíně. Vizuální série motivují ke konzistenci — stejná psychologie jako Duolingo streaky nebo GitHub contribution graph. Udržuje uživatele v aplikaci.

### 2. Sats-per-dollar indikátor
Ukázat, kolik satoshi (nebo crypto jednotek) uživatel dostane za 1 $/1 EUR dnes vs. jeho historický průměr. "Dnes: 1 823 sats/€ — o 12 % více než tvůj průměr!"

**Proč:** Dělá abstraktní čísla hmatatelná. Posiluje pocit, že nakupovat při dip je výhodné. Jednoduchý výpočet z aktuální ceny vs. průměrná nákupní cena.

### 3. Exchange API health indikátor
Zobrazit stav API burzy na Exchange Management — zelená/žlutá/červená. Logovat timestamp posledního úspěšného API callu.

**Proč:** Když nákup selže, uživatel neví, jestli je problém v jeho credentials nebo na straně burzy. Proaktivní status šetří čas při debugování.

### 4. Šablony plánů v onboardingu
Předpřipravené šablony: "Konzervativní BTC Spořič" (týdenní, classic), "Agresivní Dip Buyer" (denní, F&G strategie), "Multi-Coin Diverzifikátor" (více plánů). Setup na jedno kliknutí.

**Proč:** Snižuje rozhodovací paralýzu u nových uživatelů. Zrychluje onboarding — uživatel nemusí rozumět všem parametrům hned.

---

## Strategické funkce (střední effort, vysoký dopad)

### 5. DCA vs. Lump Sum porovnání
"Co kdyby?" karta ukazující, jak DCA strategie performovala vs. investování stejné celkové částky najednou v den prvního nákupu. Zobrazit rozdíl v ROI %.

**Proč:** Validuje uživatelův přístup k DCA během volatilních trhů. Edukační — pomáhá pochopit, kdy DCA vítězí a kdy ne. Potřebuje historickou cenu v den prvního nákupu + aktuální hodnotu portfolia.

### 6. Projekce akumulace
Na základě aktuálního nastavení plánu (částka, frekvence) projektovat dopředu: "Při tomto tempu budeš mít X BTC za 1/5/10 let." Volitelně overlay cenových scénářů (medvědí/neutrální/býčí).

**Proč:** Vizualizace cíle pohání motivaci. Uživatelé chtějí vidět konečný bod své strategie. Čistě matematický výpočet + jednoduchá UI karta.

### 7. Bohatší týdenní/měsíční souhrn
Periodická souhrnná karta (nebo push notifikace) s: celkem investováno tento týden/měsíc, nakoupeno crypto, průměrná cena, nejlepší/nejhorší nákup, změna portfolia.

**Proč:** Uživatelé chtějí periodické check-iny bez nutnosti otevírat appku denně. Typ `weeklySummary` notifikace už existuje jako toggle, ale samotná generace souhrnu by mohla být mnohem bohatší.

### 8. Export pro daňové účely
Export transakcí ve formátech kompatibilních s daňovým software (CoinTracker CSV, Koinly CSV, generický FIFO/LIFO report). Zobrazit realizované/nerealizované zisky.

**Proč:** Daňová compliance je hlavní bolest crypto uživatelů. Aktuální CSV export je generický — formáty specifické pro daňové nástroje přidávají reálnou hodnotu. V ČR relevantní s ohledem na 3leté daňové osvobození.

### 9. Kontrola fiat zůstatku na burze
Kontrolovat fiat zůstatek na burze před exekucí. Pokud je nedostatečný, varovat uživatele předem ("Tvůj EUR zůstatek dojde za ~3 dny").

**Proč:** Funkce "low balance warning" už existuje, ale je založená na odhadech. Skutečná kontrola zůstatku přes API by byla přesnější a spolehlivější.

### 10. Price alerty
Volitelné cenové alerty: "Upozorni mě, když BTC klesne pod X €" nebo "Alert, když BTC je >20 % pod ATH." Mohlo by triggerovat manuální "Buy Now" prompt.

**Proč:** Doplňuje DCA o oportunistické nakupování. Uživatelé už ceny sledují — integrace přímo do appky šetří přepínání mezi apps.

### 11. Návrhy na rebalancování
Pokud má uživatel více crypto plánů, zobrazit rozložení alokace (60 % BTC, 30 % ETH, 10 % SOL) a navrhnout rebalancování, pokud drift překročí práh.

**Proč:** Multi-crypto DCA uživatelé potřebují povědomí o alokaci. Pasivní rebalancování je přirozené rozšíření DCA strategie.

---

## Ambiciózní funkce (velký effort, diferenciující)

### 12. Historická DCA simulace
Před vytvořením plánu simulovat: "Kdyby ses DCAčkoval za 100 €/týden do BTC poslední 2 roky, měl bys X BTC v hodnotě Y € (Z % ROI)." S reálnými historickými daty.

**Proč:** Pomáhá novým uživatelům rozhodnout se o částkách a frekvencích. Silný onboarding nástroj. Potřebuje historická cenová data + simulační engine.

### 13. Home screen widgety (iOS/Android)
Widgety na domovskou obrazovku: hodnota portfolia, odpočet do další exekuce, streak counter, dnešní sats-per-euro.

**Proč:** Pasivní engagement bez otevírání appky. Vysoká hodnota pro denní DCA uživatele. Ale velký scope — platformově specifické implementace.

### 14. Execution log / Debug konzole
Detailní log každého pokusu o DCA exekuci: timestamp, odpověď burzy, order ID, fill cena, poplatky, chyby. Zobrazitelný v Settings > Debug.

**Proč:** Když něco nefunguje, uživatelé potřebují troubleshootovat. Aktuálně se chyby zobrazují na transakcích, ale celý execution flow není viditelný.

### 15. Sdílení DCA journey
"Sdílej svou DCA cestu" — vygenerovat sdílitelnou kartu/obrázek se statistikami (celkem akumulováno, streak, ROI) bez odhalení absolutních částek. Privacy-first sdílení.

**Proč:** Organický růst. Bitcoin komunita ráda sdílí svůj stacking progress. Anonymizované statistiky (jen %) zachovávají soukromí.

---

## Shrnutí priorit

| Priorita | Feature | Effort | Dopad |
|----------|---------|--------|-------|
| 1 | Streak counter | Malý | Vysoký |
| 2 | Sats-per-dollar | Malý | Střední |
| 3 | Exchange health | Malý | Střední |
| 4 | Šablony plánů | Malý | Vysoký |
| 5 | DCA vs Lump Sum | Střední | Vysoký |
| 6 | Projekce akumulace | Střední | Vysoký |
| 7 | Bohatší souhrny | Střední | Střední |
| 8 | Daňový export | Střední | Vysoký |
| 9 | Fiat balance check | Střední | Střední |
| 10 | Price alerty | Střední | Střední |
| 11 | Rebalancování | Střední | Střední |
| 12 | Historická simulace | Velký | Vysoký |
| 13 | Widgety | Velký | Vysoký |
| 14 | Debug konzole | Malý-Střední | Střední |
| 15 | Sdílení journey | Střední | Střední |
35 changes: 35 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,41 @@ <h3 data-i18n="features_qr_title">QR Code Setup</h3>
<div style="text-align:center;font-size:0.75rem;color:var(--text-muted);margin-top:12px">Point camera at QR code<br>Scanning will happen automatically</div>
</div>
</div>

<!-- Encrypted Backup -->
<div class="feature-block reveal">
<div class="feature-text">
<h3 data-i18n="features_backup_title">Encrypted Backup</h3>
<p data-i18n="features_backup_desc">Back up your DCA plans, transaction history, and optionally API credentials with a single tap. Backups are encrypted with your password using AES-256-GCM. Restore on a new phone in seconds — no account needed, no data lost.</p>
</div>
<div class="feature-visual">
<div class="mock-card">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
<span style="font-size:0.875rem;font-weight:600">accbot-backup-2026-03.enc</span>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px">
<span style="font-size:0.625rem;background:rgba(247,147,26,0.12);color:var(--accent);padding:2px 8px;border-radius:4px;font-weight:600">AES-256-GCM</span>
<span style="font-size:0.625rem;background:var(--surface-alt);color:var(--text-muted);padding:2px 8px;border-radius:4px">Password-encrypted</span>
</div>
<div style="font-size:0.6875rem;color:var(--text-muted);display:flex;flex-direction:column;gap:4px">
<div style="display:flex;align-items:center;gap:6px">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
<span>3 DCA plans</span>
</div>
<div style="display:flex;align-items:center;gap:6px">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
<span>847 transactions</span>
</div>
<div style="display:flex;align-items:center;gap:6px">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
<span>API credentials (optional)</span>
</div>
</div>
</div>
</div>
</div>

</div>
</section>

Expand Down
3 changes: 3 additions & 0 deletions docs/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
"features_qr_title": "Nastavení přes QR kód",
"features_qr_desc": "Skenujte API klíče a adresy peněženek fotoaparátem. Žádné ruční zadávání dlouhých alfanumerických řetězců.",

"features_backup_title": "Šifrovaná záloha",
"features_backup_desc": "Zálohujte DCA plány, historii transakcí a volitelně i API přihlašovací údaje jedním klepnutím. Zálohy jsou šifrovány vaším heslem pomocí AES-256-GCM. Obnovení na novém telefonu je otázka pár sekund — žádný účet, žádná ztráta dat.",

"exchanges_title": "Podporované burzy",
"exchanges_subtitle": "Připojte se k libovolné ze 7 hlavních burz. Vytvořte více DCA plánů napříč různými burzami a obchodními páry.",

Expand Down
3 changes: 3 additions & 0 deletions docs/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
"features_qr_title": "QR Code Setup",
"features_qr_desc": "Scan your API keys and wallet addresses with your camera. No more error-prone manual entry of long alphanumeric strings.",

"features_backup_title": "Encrypted Backup",
"features_backup_desc": "Back up your DCA plans, transaction history, and optionally API credentials with a single tap. Backups are encrypted with your password using AES-256-GCM. Restore on a new phone in seconds — no account needed, no data lost.",

"exchanges_title": "Supported Exchanges",
"exchanges_subtitle": "Connect to any of 7 major exchanges. Create multiple DCA plans across different exchanges and trading pairs.",

Expand Down
166 changes: 166 additions & 0 deletions scripts/sideload-ipa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env python3
"""Install .ipa on iPad via Sideloader CLI using wexpect PTY emulation.

Usage:
python scripts/sideload-ipa.py <apple_id> <password>
# Triggers 2FA, then polls 2fa-code.txt for the code.
# Write "resend" to 2fa-code.txt to request SMS resend.
"""

import os
import sys
import re
import time
import wexpect

LOCALAPPDATA = os.environ["LOCALAPPDATA"]
SIDELOADER = os.path.join(LOCALAPPDATA, "Sideloader", "sideloader-cli-x86_64-windows-msvc.exe")
SCRIPT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
IPA = os.path.join(SCRIPT_DIR, "ipa-download", "AccBot-unsigned.ipa")
TFA_FILE = os.path.join(SCRIPT_DIR, "2fa-code.txt")

os.environ["SIDELOADER_ANISETTE_URL"] = "http://localhost:6969"

if len(sys.argv) < 3:
print(f"Usage: {sys.argv[0]} <apple_id> <password>")
sys.exit(1)

apple_id = sys.argv[1]
password = sys.argv[2]

if not os.path.isfile(SIDELOADER):
print(f"ERROR: Sideloader not found: {SIDELOADER}")
sys.exit(1)
if not os.path.isfile(IPA):
print(f"ERROR: IPA not found: {IPA}")
sys.exit(1)

# Clean up old 2FA file
if os.path.exists(TFA_FILE):
os.remove(TFA_FILE)

cmd = f'"{SIDELOADER}" install -i "{IPA}"'
print(f"Running Sideloader...")
sys.stdout.flush()

child = wexpect.spawn(cmd, timeout=300)
all_output = ""

def wait_and_log(patterns, timeout=60):
global all_output
idx = child.expect(patterns, timeout=timeout)
all_output += str(child.before or "")
return idx

# Apple ID
idx = wait_and_log(["Apple ID:", wexpect.EOF, wexpect.TIMEOUT], timeout=30)
if idx == 0:
child.sendline(apple_id)
print("Sent Apple ID")
sys.stdout.flush()
else:
print(f"Failed at Apple ID prompt")
sys.exit(1)

# Password
idx = wait_and_log(["password", "Password", wexpect.EOF, wexpect.TIMEOUT], timeout=30)
if idx in (0, 1):
child.sendline(password)
print("Sent password")
sys.stdout.flush()
else:
print(f"Failed at password prompt")
sys.exit(1)

# Check if 2FA or direct success
idx = wait_and_log([
"code", # 0 - 2FA
"DeveloperSession created successfully", # 1 - no 2FA
"correct password", # 2
wexpect.EOF, # 3
wexpect.TIMEOUT # 4
], timeout=60)

if idx == 0:
print("2FA_NEEDED")
sys.stdout.flush()

# Poll for 2FA code file — support "resend" command
print(f"Waiting for 2FA code in {TFA_FILE} ...")
sys.stdout.flush()
deadline = time.time() + 180 # 3 min timeout
tfa_code = None
while time.time() < deadline:
if os.path.exists(TFA_FILE):
with open(TFA_FILE, "r") as f:
content = f.read().strip()
if content:
os.remove(TFA_FILE)
if content.lower() == "resend":
print("Sending 'resend' to Sideloader...")
sys.stdout.flush()
child.sendline("resend")
# Wait for re-send confirmation, then keep polling
time.sleep(3)
print("Resend requested. Waiting for new code...")
sys.stdout.flush()
continue
else:
tfa_code = content
break
time.sleep(1)

if not tfa_code:
print("ERROR: 2FA code not provided within 3 minutes.")
sys.exit(2)

print(f"Sending 2FA code...")
sys.stdout.flush()
child.sendline(tfa_code)

# Wait for login success
idx2 = wait_and_log([
"DeveloperSession created successfully",
"correct password",
"ERROR",
wexpect.EOF,
wexpect.TIMEOUT
], timeout=60)
if idx2 != 0:
print(f"Login failed after 2FA.\n{all_output}")
sys.exit(1)
print("Login successful!")
sys.stdout.flush()
elif idx == 1:
print("Login successful (no 2FA)!")
sys.stdout.flush()
elif idx == 2:
print("ERROR: Wrong password!")
sys.exit(1)
else:
print(f"Login failed.\n{all_output}")
sys.exit(1)

# Wait for install to complete
print("Installing (signing + uploading to device)...")
sys.stdout.flush()
try:
child.expect(wexpect.EOF, timeout=300)
all_output += str(child.before or "")
except (wexpect.TIMEOUT, wexpect.EOF):
all_output += str(child.before or "")

# Print cleaned output
clean = re.sub(r'\x1b\[[0-9;]*m', '', all_output)
clean = re.sub(r'\x1b\[\?25[lh]', '', clean)
clean = re.sub(r'\x1b\[K', '', clean)
for line in clean.split('\n'):
line = line.strip()
if line:
print(f" {line}")

if "error" in all_output.lower() and "installed" not in all_output.lower():
print("\nInstallation failed.")
sys.exit(1)
else:
print("\nDone!")