Wallets: expected-days drain, copy/paste, three-column selectable balances, rename and destroy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Opus 5.5 committed 2026-11-03 23:05:13 +08:00
1 parent 783f73989d
commit 2b781acd82
10 files changed
+178 -22

No files matched your search

+57 -1
View File
@@ -238,7 +238,10 @@ namespace Decentralized
Holdings(l, w, a => true);
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
l.AddSeparator();
l.BeginRow(8f, TextAnchor.MiddleLeft);
l.AddLabel(L.T("poin.deposit", d.Address("poinbase")));
l.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(d.Address("poinbase")); _message = L.T("hw.copied.addr", d.Address("poinbase")); Open(); });
l.End();
}, r =>
{
r.AddHeader(L.T("trade.h"));
@@ -276,7 +279,7 @@ namespace Decentralized
{
var d = Session.Data;
b.AddLabel(L.T("wallets.count", d.Wallets.Count, Tuning.WalletMax));
var cols = new[] { 130f, 130f, 120f, 110f, 220f };
var cols = new[] { 100f, 110f, 85f, 70f, 375f };
TableHeader(b, cols, L.T("wallets.col.name"), L.T("wallets.col.addr"), L.T("col.value"), L.T("wallets.col.taint"), "");
for (int i = 0; i < d.Wallets.Count; i++)
{
@@ -290,12 +293,62 @@ namespace Decentralized
b.BeginPanel(cols[4], 30f, TextAnchor.MiddleLeft, 2f, 0f);
b.BeginRow(4f);
b.AddButton(L.T("wallets.open"), () => WalletWindow.Open(w));
b.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(w.Address); _message = L.T("hw.copied.addr", w.Address); Open(); });
b.AddButton(L.T("wallets.rename"), () => { _renamePick = w.Address; _renameText = w.Label ?? ""; _message = null; Open(); });
if (idx != d.Current) b.AddButton(L.T("wallets.use"), () => { d.Current = idx; Session.Save(); Open(); });
else b.AddLabel(L.T("wallets.current"));
if (idx > 0) b.AddButton(_destroyPick == w.Address ? L.T("wallets.destroy.sure") : L.T("wallets.destroy"), () => DestroyWallet(w));
b.End();
b.End();
b.End();
}
if (_renamePick != null) RenameRow(b);
}
private static string _destroyPick, _renamePick, _renameText = "";
/// <summary>改名:表格下方一行输入框;留空恢复默认名。</summary>
private static void RenameRow(CustomUIBuilder b)
{
var w = Session.Data.Own(_renamePick);
if (w == null) { _renamePick = null; return; }
b.AddSeparator();
b.BeginRow(8f, TextAnchor.MiddleLeft);
b.AddLabel(L.T("wallets.rename.h", w.Address));
b.BeginPanel(220f, -1f, TextAnchor.MiddleLeft, 0f, 0f);
b.AddInput(WalletWindow.NameOf(w), _renameText, s => _renameText = s, "rename", s => _renameText = s);
b.End();
b.AddButton(L.T("wallets.rename.ok"), () =>
{
string name = (_renameText ?? "").Trim();
w.Label = name.Length == 0 ? null : name.Length > 16 ? name.Substring(0, 16) : name;
_renamePick = null;
Session.Save();
WalletWindow.RefreshDevice(w, true);
Open();
});
b.AddButton(L.T("black.edit.cancel"), () => { _renamePick = null; Open(); });
b.End();
}
/// <summary>销毁钱包(主钱包不能销毁):要先把币转走;点两次确认。之后回到这个地址的退款、回款、混币提回改进当前钱包。</summary>
private static void DestroyWallet(Wallet w)
{
var d = Session.Data;
int idx = d.Wallets.IndexOf(w);
if (idx <= 0) return;
if (w.Balances.Values.Any(v => v > 1e-9) || w.Frozen.Values.Any(v => v > 1e-9)) { _destroyPick = null; _message = L.T("wallets.destroy.notempty", WalletWindow.NameOf(w)); Open(); return; }
if (_destroyPick != w.Address) { _destroyPick = w.Address; _message = null; Open(); return; }
_destroyPick = null;
string name = WalletWindow.NameOf(w);
WalletWindow.Close(w);
var current = d.Hot;
d.Wallets.RemoveAt(idx);
d.Current = Math.Max(0, d.Wallets.IndexOf(current));
Log.Info($"销毁硬件钱包 {w.Address}{(w.Poisoned ? "(被投毒)" : "")}");
Session.Save();
_message = L.T("wallets.destroyed", name, w.Address);
Open();
}
/// <summary>硬件钱包拖到终端上:添加一个钱包(被投毒的钱包看起来一样)。</summary>
@@ -618,7 +671,10 @@ namespace Decentralized
var p = WalletWindow.Pending;
b.AddHeader(L.T("black.pay.confirm"));
b.AddLabel(p.Summary);
b.BeginRow(8f, TextAnchor.MiddleLeft);
b.AddLabel(L.T("black.pay.to", p.Address));
b.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(p.Address); _message = L.T("hw.copied.addr", p.Address); Open(); });
b.End();
b.AddLabel(L.T("black.pay.amount", WalletWindow.Amt(p.Amount), p.Asset, Fmt.Credits(p.Amount * Session.Price(p.Asset))));
b.BeginRow();
b.AddButton(L.T("black.pay.wallet"), () => WalletWindow.OpenForBill(p));