Commit Graph

22 Commits

Author SHA1 Message Date
davide c0193ae440 feat(ui): add Quit to File menu; hide Wallet item when no wallet is open
- File → Esci (separator + Quit at the bottom) calls IClassicDesktopStyleApplicationLifetime.Shutdown()
- Wallet menu item and mobile button now use IsVisible instead of IsEnabled:
  they disappear entirely on the wizard/setup screen and reappear once a
  wallet is open, avoiding a confusing greyed-out entry
2026-06-21 22:34:59 +02:00
davide 4a97172346 feat(ui): Wallet menu overlay — info, xpub, and password-protected seed reveal
Add a Wallet menu item (between File and Settings) that opens an in-app
overlay showing wallet metadata: file name, network, type (HD seed / xprv /
WIF / watch-only), script kind, derivation path, master fingerprint, and
account xpub.

Includes a seed section: if the wallet has no seed, a note is shown; if it
has one and is unencrypted the seed is revealed directly; if encrypted the
user must enter the wallet file password before the mnemonic is displayed.
The revealed seed is shown in a danger-coloured bordered box with a warning.
Closing the overlay (backdrop, Close button, or Esc) always clears the
password input and hides the seed.

Also adds the private-key password-prompt overlay and its localization keys
(shared UI scaffolding used by the following commit).
2026-06-21 22:27:55 +02:00
davide b13b66160c feat(ui): donate tab in Help overlay
Help button now shows a two-tab overlay:
- Info: existing about/version content
- Donate: donate flow to the dev address (plm1qdq3…) with free amount
  input, prepare preview, and confirm-and-broadcast button

New MainWindowViewModel.Donate.cs partial: DonateAmount / DonatePreview
/ HasPendingDonate observable properties, PrepareDonateCommand (builds
the tx with hardcoded dev address via the existing TransactionFactory),
ConfirmDonateCommand (broadcasts and syncs). Donate state is reset on
overlay close. Six-language Loc keys added (help.tab.info/donate,
donate.desc/dev.address/amount/prepare/confirm).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:40:02 +02:00
davide 5d2d0ad312 feat(ui): two-column desktop layout for Send/Receive, fixed window size
Send tab: Recipient and Amount cards side-by-side on desktop using a
two-column Grid, making full use of the available window width.
Summary card and action buttons remain full-width below both columns.
Mobile retains the original vertical stack.

Receive tab: QR card on the left (auto-width), address card expands
to fill the right column on desktop — standard fintech wallet pattern.
Mobile retains QR above, address below.

Window enlarged to 1020×680 (from 900×620) and fixed with CanResize=False;
Min/Max dimensions match so the resize handle never appears.
2026-06-16 15:04:10 +02:00
davide 3d5a226a5a docs: translate all code comments to English (language policy)
Translate every Italian /// XML doc comment, <!-- --> XAML comment, and
// inline comment to English across all source files (Core, App, tests).
Add the language policy to CLAUDE.md (conversation Italian; all code
and docs English). Update one test assertion that checked an Italian
exception message that was also translated.
2026-06-16 14:40:11 +02:00
davide 4b82a0852c feat(ui): restructure transaction details + clearer coinbase identification
Transaction details overlay redesigned from a flat 12-row grid into a
scannable layout: a header with the net amount in focus plus SPV/status
badges, then three labeled cards (Overview, Amounts & fees, Technical
details), with inputs/outputs as carded rows. Adds a .section heading
style and tx.sect.* localization keys (6 languages).

Coinbase transactions are now explicitly identified: an amber "Coinbase"
badge in the header, and the misleading "From: —" / "coinbase —" replaced
with "Newly generated (mining)" (localized). Exposes IsCoinbase on the
details view model; no consensus/logic change, presentation only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:21:50 +02:00
davide 14ae39c5aa feat(ui): wallet name field in creation wizard
The last wizard step (password) now shows an optional name field.
The name becomes the filename: <name>.wallet.json in the wallets
directory. Invalid filename characters are replaced with '_'.

If left empty, the existing auto-name logic applies (default.wallet.json,
wallet-2.wallet.json, …). If the chosen name already exists the wizard
shows an error instead of overwriting.

The name field is visually separated from the encryption section by a
distinct background panel and a horizontal divider.
2026-06-15 15:05:53 +02:00
davide 4dc37f1b42 feat(ui): wizard flows for xpub/xprv and WIF import
Add two new import paths to the setup wizard:

- "Importa xpub / xprv": accepts any SLIP-132 key (xpub/ypub/zpub or
  xprv/yprv/zprv), auto-detects script type from the version prefix,
  and saves a watch-only or fully-spendable HD account accordingly.

- "Importa chiave WIF": accepts one or more WIF private keys (one per
  line), goes through script-type selection, and saves an ImportedKeyAccount.

WizardFlowKind enum (New, Restore, ImportXkey, ImportWif) governs which
steps are shown; WizardBack() updated for all four flows. OpenLoaded()
updated to accept IWalletAccount and display wallet kind tags
(watch-only / imported) in the network info line.

Localization keys added for all six languages (it/en/es/fr/pt/de).
ViewModel._account changed from HdAccount? to IWalletAccount?.
2026-06-15 14:23:08 +02:00
davide 002c854497 feat(wallet): add P2PKH, P2SH-P2WPKH, and P2TR (Taproot/BIP86) address types
- ScriptKind.Taproot (BIP86, purpose 86', P2WPKH → witness v1 bech32m plm1p)
  derivation wired in DerivationPaths and ChainProfiles (xprv/xpub headers,
  no SLIP-132 standard for P2TR); NBitcoin ScriptPubKeyType.TaprootBIP86
- Wizard step StepScriptType inserted between passphrase and password: 4 radio
  buttons (Legacy / Wrapped SegWit / Native SegWit★ / Taproot), localized in
  6 languages; CreateOrRestore now uses SelectedScriptKind instead of hardcoded
  NativeSegwit; back navigation updated accordingly
- BIP86 golden-vector tests (Bip86TaprootTests): output key verified against
  official Bitcoin BIP86 addresses, plm1p prefix asserted
2026-06-15 12:03:52 +02:00
davide 200c12651b feat(ui): hardcode mainnet, remove network selector
Drop the mainnet/testnet/regtest ComboBox from the wizard and fix
Net to always return NetKind.Mainnet. Core profiles and CLI --net
flag are untouched; the wallet file still records the network name.
2026-06-15 10:35:40 +02:00
davide bfee0dde03 feat(android): QR code scanner for Send address field
Camera2 + ZXing.Net 0.16.9 activity (ScannerActivity) that captures JPEG
frames at ~2.5 fps and decodes QR codes without Xamarin dependencies.
Result is returned to MainActivity via OnActivityResult/TaskCompletionSource.
PlatformServices.ScanQrAsync seam wires Android head to shared App layer;
ScanQrCommand in the Send ViewModel strips BIP21 URI scheme/query parameters.
CAMERA permission and uses-feature added to AndroidManifest.
2026-06-15 10:19:29 +02:00
davide 4c0edde4f7 feat(ui): mobile polish — tab bar icons, server overlay, status text
Tab bar: replace plain Header strings with icon+label StackPanels
(≡ ↑ ↓ ⊙ ⊕); style TabStrip with UniformGrid so all five tabs share
the full width equally; center content and add touch padding. Icons
are visible only on mobile (IsMobile binding); desktop keeps text only.

Server settings overlay: dual layout for host/port/TLS input (vertical
on mobile: host full-width, port+TLS side by side) and for action
buttons (stacked full-width on mobile). Known-server list item shows
host on one line and tcp/ssl ports on the line below on mobile.

Connection status bar: simplify to "connesso" / "non connesso" —
remove the "a host:port" suffix from the connected state and
consolidate all disconnected/error/cert-changed states to conn.none.
2026-06-14 22:05:30 +02:00
davide 0f8a764a44 feat(storage): add WalletLock to prevent concurrent wallet access
Introduces an exclusive file lock (FileShare.None on wallet.json.lock)
held for the duration of a wallet session. A second instance trying to
open the same file receives null from TryAcquire and sees a localized
error message; UnauthorizedAccessException (OS permission issues)
propagates separately so the UI can show a distinct message.
The .lock file is deleted on Dispose (best-effort); the real guard is
the open FileStream, which the OS releases automatically on crash.
2026-06-13 20:34:06 +02:00
davide 865daa137d feat(app): version in window title and Help overlay
- csproj: add <Version>0.9.0</Version> as single source of truth
- AppVersion reads Major.Minor.Build from the assembly; WindowTitle
  exposes "Palladium Wallet 0.9.0" bound to Window.Title
- Menu Help → in-app overlay (same pattern as settings/server overlays)
  showing app name, version and a short description; backdrop tap and
  Esc close it
- i18n: menu.help, help.title, help.info in all 6 languages
2026-06-12 12:01:25 +02:00
davide 4735490759 feat(app): transaction detail overlay with full on-chain data
Double-clicking a history row opens an in-app overlay (same pattern as
address/server/settings overlays) that shows all available data for a
transaction. The overlay appears immediately with a spinner; data is
fetched from the server in the background and rendered once ready.
Backdrop tap and Esc close it; a pending fetch is cancelled.

New Core type — TransactionInspector (Core/Wallet/):
- FetchAsync() downloads the raw tx, all parent txs (parallel requests,
  one round-trip instead of N sequential), and the block header
- Reconstructs inputs (amounts, addresses, is-mine), outputs, fee,
  virtual size, RBF flag, block timestamp, confirmations

New App types:
- TransactionDetails record: full parsed data (fee, net, I/O lists,
  counterparty addresses, coinbase detection…)
- TransactionDetailsViewModel: pre-formats all strings in the current
  locale and unit (status, date, signed amounts, sat/vB rate…)
- TxIoRow record: one row in the input/output tables
- MineColorConverter: bool → brush (MediumSeaGreen for own addresses)

ViewModel changes:
- ShowTransactionDetailsAsync / CloseTransactionDetailsCommand
- BuildTransactionDetailsAsync (also public for future RBF/CPFP use)
- CancellationTokenSource so opening a new tx cancels the previous fetch
- All server work runs on Task.Run to keep the UI thread free

XAML: history rows get DoubleTapped handler, Hand cursor, hint label,
txid now uses TextTrimming instead of SelectableTextBlock.

i18n: 24 new tx.* / history.hint keys in all 6 languages.
2026-06-12 11:48:33 +02:00
davide 4c7e8696cb feat(app): copy-to-clipboard button for receive address
Adds a "Copy" button next to the receive address in the Receive tab.
Uses Avalonia's Clipboard API (async, code-behind) and calls
NotifyAddressCopied() to show the existing addr.copied status message.
New i18n key receive.copy in all 6 languages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 10:47:01 +02:00
davide 7f2759b2fc feat(app): multi-wallet chooser, confirm-password, encrypt toggle
Multi-wallet (§8):
- AppPaths.WalletFiles(net) enumerates all *.wallet.json in the wallets
  dir; WizardStartOpen shows a chooser step when more than one is found
- New StepChooseWallet + ChooseWalletCommand; Back from StepOpen returns
  to chooser (or to StepStart when only one wallet)
- WalletFileEntry record for the chooser ItemsControl

Password step (Electrum style):
- ConfirmPasswordInput: password must be typed twice before creating
- EncryptWallet checkbox (default true); when unchecked, password is
  null (plaintext file) with an explicit warning
- Validation: empty password with encryption on → msg.password.required;
  mismatch → msg.password.mismatch
- ConfirmPasswordInput cleared on wallet open and wizard back

AppPaths:
- DefaultDataRoot() is now platform-aware: %APPDATA%\PalladiumWallet on
  Windows, ~/.palladium-wallet on Linux/macOS (matches §8 convention)
- Legacy root fallback removed (no prior releases to migrate from)

i18n: wiz.choose.title, wiz.password.confirm, wiz.password.encrypt,
wiz.password.encrypt.hint, msg.choose.wallet, msg.password.required,
msg.password.mismatch — all 6 languages
2026-06-12 10:13:17 +02:00
davide f3bf4cf94a feat(app): first-run data location wizard step
On first launch (no data yet, no portable dir, no pointer file),
the wizard now shows a new step-0 screen asking where to store
wallets, config and certificates.

AppPaths changes:
- DefaultDataRoot() → ~/.PalladiumWallet (home, always writable)
- IsDataLocationConfigured() → true when portable / override / pointer
  already written / legacy or default already has data
- ConfigureDataLocation(root) writes a bootstrap pointer file and
  creates the directory
- DataRoot() resolution order: override → portable → pointer → legacy
  (has data) → default

ViewModel: new StepDataLocation step, UseDefaultDataLocationCommand,
ApplyDataLocation(root) (also called from View's folder picker).

View: new wizard panel with description, default-path display, two
buttons (use default / choose folder); folder picker via
StorageProvider.OpenFolderPickerAsync.

Loc: add wiz.data.* keys (6 languages); fix fallback language "it"→"en";
update test assertion accordingly.
2026-06-12 09:25:04 +02:00
davide 28cb4ce6ae feat(app): server settings as in-app overlay, split host/port fields
- Moves server configuration from the wallet panel into an overlay
  (Impostazioni → Server), same pattern as the address detail overlay
- Splits the single "host:port" text box into separate Host and Port
  fields; port changes auto-toggle the TLS checkbox when the typed
  port matches a known SSL/TCP port, and vice-versa
- Adds DisconnectAsync() so changing server/TLS reconnects to the new
  endpoint instead of reusing the old socket
- Adds i18n keys (IT/EN/ES/FR/PT/DE) for the new overlay
- Removes the server row from the main wallet panel; connection status
  indicator (green/red dot) is now shown in the wallet header
2026-06-12 09:02:19 +02:00
davide fe320584eb feat(app): navbar restructure, contacts tab and address info window
- Reorder tabs: Storico / Invia / Ricevi / Indirizzi / Contatti
- Invia: ComboBox to quick-fill recipient from saved contacts
- Contatti: new tab to add/remove contacts (name + address), persisted
  to the wallet file via WalletDocument.Contacts
- Indirizzi: clicking any address (left or right click) opens a modal
  window with derivation path, public key and private key as selectable
  text (no copy button needed — user selects and copies manually);
  AddressRow now carries PubKey, PrivKey, DerivPath pre-computed
- AddressInfoWindow: new Window with SelectableTextBlock per field,
  private key section hidden for watch-only wallets
- Loc: adds tab.contacts, addr.*, contacts.*, send.from.contact keys
  in all 6 languages
2026-06-11 21:39:36 +02:00
davide 71a604c8a5 feat(i18n): add ES, FR, PT, DE languages and fix live switching
Add Spanish, French, Portuguese, German translations to all UI strings.

Fix language switching in Avalonia compiled bindings: instead of firing
PropertyChanged("Item[]") on a singleton (which Avalonia ignores when the
object reference is unchanged), Loc.SwitchTo() now creates a new Loc
instance for the selected language and replaces both Loc.Instance and the
ViewModel's _loc field. OnPropertyChanged("Loc") then forces Avalonia to
re-evaluate all {Binding Loc[key]} bindings with the new instance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 18:41:31 +02:00
davide 75583f7a69 feat(app): settings menu with language and display unit
Add global AppConfig (config.json, blueprint §8) persisting language
and amount unit. CoinAmount gains unit-aware formatting and parsing
(PLM, mPLM, µPLM, sat), applied everywhere amounts are shown or
entered, including the send form. New Loc i18n layer (it/en) with
live-updating XAML bindings covering menu, wizard, wallet panel and
status messages.

The Impostazioni menu opens a dropdown with separate Lingua and Unità
entries (radio-checked submenus, applied and saved on click), ready to
host future settings.
2026-06-11 16:23:06 +02:00