Add a feature request template and a config.yml (blank issues disabled,
security reports routed to SECURITY.md) alongside the existing bug report
template, plus a PR template with a checklist matching the project's
security rules. Point the app's "Report a bug" button at the new GitHub
template now that the repo is hosted there instead of the old self-hosted
tracker.
Previously the server settings overlay had only "Connect and sync" and
"Reset certs" — peer discovery had no button and only ran implicitly
when reopening the dialog while connected. Add a dedicated "Sincronizza"
button wired to DiscoverServersCommand, and make it work even without
an active connection by opening a short-lived connection to a candidate
server just to query its peer list, then closing it without touching
the wallet's connection state.
Extract confirmation-threshold logic into UtxoSpendability (shared by
TransactionFactory and WalletSynchronizer) and use it to compute
ImmatureSats, so coinbase/under-confirmed amounts are shown separately
from spendable balance in the GUI and CLI instead of being lumped into
"confirmed".
When IsSyncing and the user requests a different server, cancel the
running CancellationTokenSource instead of silently ignoring the click.
OperationCanceledException is caught separately (not an error), and
ConnectAndSync restarts automatically with the new server after the
cancelled task unwinds.
The "Connect" button no longer has IsEnabled="{Binding !IsSyncing}":
it is always clickable, and clicking it with the same server sets
_resyncRequested as before. CancellationToken is now passed to both
ElectrumClient.ConnectAsync and WalletSynchronizer.SyncOnceAsync.
Adds a "Report a bug" / "Segnala un bug" button (6 languages) in
Help → Info that opens the issue tracker in the system browser via
TopLevel.Launcher (cross-platform: desktop + Android).
URL points to the current self-hosted repo; a TODO comment marks
the constant for easy update once the project moves to GitHub.
Adds .github/ISSUE_TEMPLATE/bug_report.yml — GitHub issue form with
structured fields for version, platform, network, repro steps,
expected behavior, and logs.
Input rows switch to a two-line layout (full prev-txid:index on the first
line, address + amount on the second) so nothing is cut by a fixed 160px
column. Output address column gets TextWrapping instead of TextTrimming.
Overlay grows to MaxWidth=660/MaxHeight=800 for better desktop use; the
same XAML wraps naturally on narrow mobile screens.
Removes the Shorten() helper that was masking input references.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SPV is the only verification method the wallet uses, so showing it as a
badge adds no information — if a transaction appears confirmed, it has
already passed Merkle verification.
- Remove the SPV chip from the transaction detail overlay
- Remove the Verificata column from the history list (desktop and mobile)
- Drop VerifiedText property from TransactionDetailsViewModel
- Drop the Verificata field from HistoryRow
- Remove the orphaned tx.verified loc key
The wizard already covers opening existing wallets; a separate file-picker
entry in the menu duplicates that flow without adding value. Remove the menu
item, its click handler, the OpenFromPath VM method, and the loc key.
- 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
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).
- AppConfig stores LastServerHost/Port/UseSsl; restored on next launch
so the wallet reconnects to the last-used server instead of defaulting
to the first bootstrap entry
- Added ConnectionStatusShort for the status bar (short label only);
ConnectionStatus retains the full "Connesso a ip:porta" shown in the
server settings overlay
- Removed TLS checkbox (SSL still used internally, just not exposed in UI)
- Removed "Discover servers" button (discovery now runs automatically on panel open)
- ConnectionStatus now includes host:port when connected ("Connesso a ip:porta")
- Replaced status ellipse+text with a single TextBlock
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>
- UniformGrid Columns="5" on TabStrip so all 5 tabs always stay on one
row on Android (Rows="1" alone did not auto-calculate columns at
measure time on the Android Avalonia renderer)
- Contacts tab header was using hardcoded FontSize=13/Width=24/Spacing=4
instead of the TabFontSize/TabIconSize/TabSpacing ViewModel bindings,
making it visually larger than the other four tabs on mobile
- ContentPresenter Margin="0,0,0,4" in Controls.axaml pushes the tab
header content above the 2 px selection indicator, which is drawn at
the absolute bottom of the template Panel and was overlapping the label
- TabItem horizontal padding 4→8 px and TabSpacing 2→4 for both
desktop and mobile to give more breathing room between tab items
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.
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.
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>
Replace raw Fluent defaults + inline hex with a semantic design system,
themed for both light/dark (follows system variant).
- Styles/Theme.axaml: semantic brushes (surface/text/border/status) per
variant via ThemeDictionaries; override Fluent SystemAccentColor to brand
blue (#2563EB) and ControlCornerRadius=8; blue->indigo balance gradient.
- Styles/Controls.axaml: reusable classes (card, balance-hero, chip, ghost),
type scale (amount with tabular figures, mono, h1, label), button/input
polish, tab selected-in-blue, list hover/selected tints, card hover-lift.
- MainView: balance shown as gradient hero card; dashboard tabs use Material
SVG Path icons (Fill tracks TabItem selection) instead of Unicode glyphs;
all hardcoded colors (LimeGreen/IndianRed/Orange/Gray/#99000000) and
generic Fluent surface brushes mapped to semantic tokens; app background,
stronger modal scrim, status bar top border.
Palette derived from the logo (blue=trust, green=money). Build clean, app
starts with no binding errors.
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.
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?.
On mobile the server settings panel now fills the entire screen
(no MaxWidth/MaxHeight/Margin constraints, no rounded corners) using
a desktop-only Border.desktop-overlay style so inline values never
fight the style system. Input font sizes increased (11→13/15px),
known-server list taller (200→300px) and server hostname larger (13→15px).
Desktop layout unchanged.
UnconfirmedText (pending/unconfirmed balance) now wraps instead of
clipping horizontally. Contact name in mobile list gets CharacterEllipsis
trimming for arbitrarily long user-defined names.
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.
Replace the mobile-only custom bottom Grid nav bar with a single styled
TabStrip that works the same on both platforms: icon + label headers,
gray background, UniformGrid for equal-width columns.
Also adds the 📷 scan button in the Send address field (visible on mobile,
triggers ScanQrCommand wired in the previous commit).
Avalonia's TabStrip ignores HorizontalAlignment overrides when placed at
Bottom, causing the items to cluster left. Replace it with a dedicated
Grid (ColumnDefinitions="*,*,*,*,*") that guarantees 5 equal columns
across the full width. The built-in TabStrip is hidden on mobile; buttons
in the custom bar call SelectTabCommand to drive SelectedTabIndex on the
TabControl.
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.
Add IsMobile property and BoolToTabPlacementConverter; wire
TabStripPlacement to move tabs to the bottom on mobile (standard
Android pattern). Hide the desktop menu bar on mobile and expose
Settings/Help via a compact header row instead.
Replace fixed-width multi-column grids with dual desktop/mobile
templates in History, Addresses and Contacts lists; adapt Send,
Receive and the add-contact form for narrow screens. Remove hard-coded
Width from all five overlays (560–640 px) in favour of MaxWidth +
Margin="16" so they never overflow a 360 px screen; add ScrollViewer
to Address info, Server settings and Settings overlays.
Desktop layout is unchanged: all differences are gated on the
IsMobile/IsDesktop bool, which is a platform constant (false on desktop).
The Avalonia UI code (App, Views, ViewModels, Localization, Assets) now
lives in src/App as a plain library (no OutputType). Two thin heads
reference it:
- src/App.Desktop/ — WinExe, Avalonia.Desktop, hosts MainView in a
MainWindow; carries Program.cs and app.manifest (moved from src/App)
- src/App.Android/ — net10.0-android, Avalonia.Android, MainActivity/
MainApplication; targets API 23+, EmbedAssembliesIntoApk=true so the
apk is self-contained for sideloading
All event handlers and TopLevel-dependent calls (file picker, clipboard,
folder picker) moved from MainWindow.axaml.cs into the new shared
MainView.axaml.cs (UserControl), using TopLevel.GetTopLevel(this) so
they work on both platforms. Esc/Back key handling is also in MainView.
MainWindow becomes a thin shell that hosts MainView.
Framework bump: all projects move to net10.0; Cli and Tests follow.
- 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
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.
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>
Add logo.png (source) and logo.ico (multi-size: 256/128/64/48/32/16)
generated with Pillow. Remove avalonia-logo.ico (Avalonia template
placeholder). Update MainWindow.axaml Icon and csproj ApplicationIcon
to point to the new files.
Adds QRCoder 1.8.0 and generates a PNG QR code in-memory each time
the receive address changes (OnReceiveAddressChanged). The bitmap is
displayed in the Receive tab inside a white-background border with
pixel-perfect scaling (BitmapInterpolationMode=None). Previous bitmap
is disposed to avoid memory leaks.
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
- ConnectAndSync() no longer bails early when no wallet is open:
connection is established immediately after the wizard completes
(Electrum-style), sync starts only once an account is available
- KeepAlive tick no longer requires IsWalletOpen so the connection is
maintained and auto-reconnected at all times
- WalletSynchronizer is lazily created on first sync (not on connect)
to avoid a null-ref guard on _synchronizer
- Connection status indicator (dot + text) moved from wallet header to
the status bar (always visible); tapping it still opens the server
settings overlay
- Menu "Rete" removed: Discover and ResetCerts are inside the server
settings overlay; redundant top-level menu entry eliminated
- "Server" button in settings overlay is no longer gated on IsWalletOpen
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.
The green/red dot + status text in the wallet header is now tappable:
opens the server settings overlay directly. Added Hand cursor and
tooltip (server title) to signal interactivity.
Status text uses SystemAccentColor instead of Gray.
The Impostazioni menu now opens a single overlay (same pattern as
address/server overlays) instead of nested OS popup menus, which are
slow to respond under WSLg.
The overlay groups language (RadioButton) and unit (RadioButton) in one
panel, with a button to open the server overlay. Esc and backdrop tap
close it. OpenServerSettings() closes the settings overlay first so the
two overlays never stack.
- 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
The address detail panel is now rendered as a modal overlay inside
MainWindow instead of a separate top-level Window, avoiding the
create/destroy cost of a dialog and working better under WSLg.
Backdrop tap and Esc both close the overlay.
- 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
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>
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.
Startup now follows the blueprint §15 flow, one field per screen with
Avanti/Indietro: initial choice (open / create / restore), seed display
with write-it-down warning, seed confirmation by re-typing, mnemonic
validation on restore, optional BIP39 passphrase, and wallet file
password as the final step. Opening an encrypted file from the menu
routes to the same password step.