Multiple hardware wallets: per-wallet devices, wallets page, Poinbase custodial account, PLEDGER item with supply-chain poisoning
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
add61a6b5e
commit
783f73989d
19 files changed
+557
-199
No files matched your search
@@ -13,7 +13,7 @@ namespace Decentralized
|
||||
public static class TerminalWindow
|
||||
{
|
||||
public const string Id = "pd_terminal";
|
||||
private enum Page { Home, Bank, Poinbase, Web3 }
|
||||
private enum Page { Home, Bank, Poinbase, Web3, Wallets }
|
||||
|
||||
private static Page _page = Page.Home;
|
||||
private sealed class EditPrice { public GameItem Item; public BmSale Sale; public string Id; public long Ref; }
|
||||
@@ -35,7 +35,6 @@ namespace Decentralized
|
||||
string name = L.T("tab." + p.ToString().ToLowerInvariant());
|
||||
b.AddButton(page == _page ? $"[{name}]" : name, () => { _page = page; _message = null; _edit = null; Open(); });
|
||||
}
|
||||
b.AddButton(L.T("tab.wallet"), WalletWindow.Open);
|
||||
b.End();
|
||||
b.AddSeparator();
|
||||
b.BeginScroll(540);
|
||||
@@ -45,6 +44,7 @@ namespace Decentralized
|
||||
case Page.Bank: BankPage(b); break;
|
||||
case Page.Poinbase: ExchangePage(b, Venue.Exchange); break;
|
||||
case Page.Web3: Web3Page(b); break;
|
||||
case Page.Wallets: WalletsPage(b); break;
|
||||
default: break;
|
||||
}
|
||||
b.End();
|
||||
@@ -76,7 +76,7 @@ namespace Decentralized
|
||||
private static void HomePage(CustomUIBuilder b)
|
||||
{
|
||||
var d = Session.Data;
|
||||
double chain = d.Hot.Value(Session.Price);
|
||||
double chain = d.ChainValue(Session.Price);
|
||||
b.AddLabel(L.T("home.summary", PlayerStore.Instance.playerCash, Fmt.Credits(chain)));
|
||||
b.AddSpace(6f);
|
||||
b.BeginRow(8f, TextAnchor.UpperCenter);
|
||||
@@ -144,7 +144,7 @@ namespace Decentralized
|
||||
l.AddHeader(L.T("entry.bank"));
|
||||
TableRow(l, w, L.T("bank.cash.k"), ps.playerCash.ToString());
|
||||
TableRow(l, w, L.T("bank.rent.k"), L.T("bank.rent.v", Session.Rent(), ps.GetRentDayCounter()));
|
||||
TableRow(l, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Hot.Get(Assets.CRC)));
|
||||
TableRow(l, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Poinbase.Get(Assets.CRC)));
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("bank.ops"));
|
||||
@@ -164,14 +164,15 @@ namespace Decentralized
|
||||
double recent = d.Exchange.History.Where(h => h.Key > day - Tuning.AmlWindowDays).Sum(h => h.Value);
|
||||
b.AddSeparator();
|
||||
b.AddLabel(L.T("aml.window", Tuning.AmlWindowDays, Fmt.Credits(recent), Fmt.Credits(Tuning.AmlCumRents * rent)));
|
||||
double total = d.Hot.Value(Session.Price);
|
||||
double taintRatio = total > 0 ? d.Hot.Taint / total : 0;
|
||||
var pb = d.Poinbase;
|
||||
double total = pb.Value(Session.Price);
|
||||
double taintRatio = total > 0 ? pb.Taint / total : 0;
|
||||
b.AddLabel(L.T("aml.taint", (int)Math.Round(taintRatio * 100)));
|
||||
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double v) && v > 0)
|
||||
{
|
||||
double value = Math.Min(v, d.Hot.Get(Assets.CRC)) * Session.Price(Assets.CRC);
|
||||
double taint = total > 0 ? d.Hot.Taint * Math.Min(1, value / total) : 0;
|
||||
double chance = Exchange.HitChance(value, taint, recent, rent, d.Hot.Flagged);
|
||||
double value = Math.Min(v, pb.Get(Assets.CRC)) * Session.Price(Assets.CRC);
|
||||
double taint = total > 0 ? pb.Taint * Math.Min(1, value / total) : 0;
|
||||
double chance = Exchange.HitChance(value, taint, recent, rent, pb.Flagged);
|
||||
b.AddLabel(L.T("aml.chance", (int)Math.Round(chance * 100)));
|
||||
}
|
||||
}
|
||||
@@ -221,7 +222,7 @@ namespace Decentralized
|
||||
any = true;
|
||||
TableRow(b, HoldW, kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key));
|
||||
}
|
||||
if (!any) b.AddLabel(L.T("wallet.empty"));
|
||||
if (!any) b.AddLabel(L.T(w == Session.Data.Poinbase ? "poin.empty" : "wallet.empty"));
|
||||
foreach (var kv in w.Frozen.OrderBy(k => k.Key).Where(k => show(k.Key)))
|
||||
b.AddLabel(L.T("wallet.frozen", kv.Key, Fmt.Num(kv.Value), w.FrozenUntil.TryGetValue(kv.Key, out var u) ? u : 0));
|
||||
}
|
||||
@@ -229,19 +230,87 @@ namespace Decentralized
|
||||
/// <summary>Poinbase:合规交易所。左边账户持仓,右边交易;信用点的存取在银行。</summary>
|
||||
private static void ExchangePage(CustomUIBuilder b, Venue venue)
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
var d = Session.Data;
|
||||
var w = d.Poinbase;
|
||||
Columns(b, l =>
|
||||
{
|
||||
l.AddHeader(L.T("poin.account.h"));
|
||||
Holdings(l, w, a => a == Assets.CRC || a == Assets.PSC);
|
||||
Holdings(l, w, a => true);
|
||||
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
|
||||
l.AddSeparator();
|
||||
l.AddLabel(L.T("poin.deposit", d.Address("poinbase")));
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("trade.h"));
|
||||
AmountRow(r);
|
||||
TradeRows(r, venue);
|
||||
r.AddSeparator();
|
||||
r.BeginRow();
|
||||
foreach (var a in new[] { Assets.CRC, Assets.PSC })
|
||||
{
|
||||
var asset = a;
|
||||
r.AddButton(asset == _poinAsset ? $"[{asset}]" : asset, () => { _poinAsset = asset; Open(); });
|
||||
}
|
||||
r.End();
|
||||
r.AddButton(L.T("poin.out", WalletWindow.NameOf(d.Hot)), PoinbaseOut);
|
||||
});
|
||||
}
|
||||
|
||||
private static string _poinAsset = Assets.CRC;
|
||||
|
||||
/// <summary>Poinbase 提到当前钱包:托管账户直接转,不用签名。污点按比例随币走。</summary>
|
||||
private static void PoinbaseOut()
|
||||
{
|
||||
if (!ReadAmount(out double v)) return;
|
||||
var d = Session.Data;
|
||||
if (d.Poinbase.Avail(_poinAsset) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
Wallet.Transfer(d.Poinbase, d.Hot, _poinAsset, v, Session.Price);
|
||||
_message = L.T("poin.out.done", Fmt.Num(v), _poinAsset, WalletWindow.NameOf(d.Hot));
|
||||
Session.Save();
|
||||
WalletWindow.RefreshDevice(d.Hot);
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>钱包页:全部硬件钱包,连接(设为当前)、打开实体钱包。</summary>
|
||||
private static void WalletsPage(CustomUIBuilder b)
|
||||
{
|
||||
var d = Session.Data;
|
||||
b.AddLabel(L.T("wallets.count", d.Wallets.Count, Tuning.WalletMax));
|
||||
var cols = new[] { 130f, 130f, 120f, 110f, 220f };
|
||||
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++)
|
||||
{
|
||||
var w = d.Wallets[i];
|
||||
int idx = i;
|
||||
b.BeginRow(2f);
|
||||
Cell(b, cols[0], (idx == d.Current ? "● " : "") + WalletWindow.NameOf(w));
|
||||
Cell(b, cols[1], w.Address);
|
||||
Cell(b, cols[2], Fmt.Credits(w.Value(Session.Price)));
|
||||
Cell(b, cols[3], Fmt.Credits(w.Taint));
|
||||
b.BeginPanel(cols[4], 30f, TextAnchor.MiddleLeft, 2f, 0f);
|
||||
b.BeginRow(4f);
|
||||
b.AddButton(L.T("wallets.open"), () => WalletWindow.Open(w));
|
||||
if (idx != d.Current) b.AddButton(L.T("wallets.use"), () => { d.Current = idx; Session.Save(); Open(); });
|
||||
else b.AddLabel(L.T("wallets.current"));
|
||||
b.End();
|
||||
b.End();
|
||||
b.End();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>硬件钱包拖到终端上:添加一个钱包(被投毒的钱包看起来一样)。</summary>
|
||||
public static bool CanAddWallet() => Session.Data != null && Session.Data.Wallets.Count < Tuning.WalletMax;
|
||||
|
||||
public static void AddWallet(bool poisoned)
|
||||
{
|
||||
var w = Session.Data.AddWallet(poisoned);
|
||||
Log.Info($"添加硬件钱包 {w.Address}{(poisoned ? "(被投毒)" : "")}");
|
||||
Session.Save();
|
||||
_page = Page.Wallets;
|
||||
_message = L.T("wallets.added", WalletWindow.NameOf(w), w.Address);
|
||||
Open();
|
||||
}
|
||||
|
||||
/// <summary>Web3:链上钱包与去中心化交易。</summary>
|
||||
private static void Web3Page(CustomUIBuilder b)
|
||||
{
|
||||
@@ -265,7 +334,7 @@ namespace Decentralized
|
||||
}
|
||||
Columns(b, l =>
|
||||
{
|
||||
l.AddHeader(L.T("web3.wallet.h"));
|
||||
l.AddHeader(L.T("web3.wallet.h") + " " + WalletWindow.NameOf(w));
|
||||
Holdings(l, w, a => true);
|
||||
l.AddSeparator();
|
||||
l.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price))));
|
||||
@@ -389,7 +458,7 @@ namespace Decentralized
|
||||
GoodHead(c, g, L.T("black.stock", offer.Qty));
|
||||
c.AddLabel(L.T("black.price", offer.Price * count) + (count > 1 ? " ×" + count : ""));
|
||||
c.AddFlexibleSpace();
|
||||
c.AddButton(L.T("black.buy"), () => { string asset = _payAsset; BeginPay(d.Address("platform"), ItemName(offer.Item) + (count > 1 ? " ×" + count : ""), asset, offer.Price * count, () => BuyOffer(offer, count, asset)); });
|
||||
c.AddButton(L.T("black.buy"), () => { string asset = _payAsset; BeginPay(d.Address("platform"), ItemName(offer.Item) + (count > 1 ? " ×" + count : ""), asset, offer.Price * count, pw => BuyOffer(offer, count, asset, pw)); });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -412,7 +481,7 @@ namespace Decentralized
|
||||
b.AddButton(L.T("black.sell.all"), () =>
|
||||
{
|
||||
string asset = _payAsset; double mult = _sellMult;
|
||||
BeginPay(d.Address("platform"), L.T("black.sell.all") + L.T("pay.listfee", mult.ToString("0.0", CultureInfo.InvariantCulture)), asset, BlackDelivery.Sellable().Sum(it => BlackMarket.ListFee(BlackMarket.ListPriceOf(BlackDelivery.RefValue(it), mult))), () => ListAll(asset, mult));
|
||||
BeginPay(d.Address("platform"), L.T("black.sell.all") + L.T("pay.listfee", mult.ToString("0.0", CultureInfo.InvariantCulture)), asset, BlackDelivery.Sellable().Sum(it => BlackMarket.ListFee(BlackMarket.ListPriceOf(BlackDelivery.RefValue(it), mult))), pw => ListAll(asset, mult, pw));
|
||||
});
|
||||
b.AddSeparator();
|
||||
var items = BlackDelivery.Sellable();
|
||||
@@ -437,7 +506,7 @@ namespace Decentralized
|
||||
|
||||
private static readonly System.Collections.Generic.Dictionary<BmGood, GameItem> SellCards = new System.Collections.Generic.Dictionary<BmGood, GameItem>();
|
||||
|
||||
private static void ListAll(string asset, double mult)
|
||||
private static void ListAll(string asset, double mult, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
int n = 0;
|
||||
@@ -446,7 +515,7 @@ namespace Decentralized
|
||||
string id = BlackDelivery.SellId(it);
|
||||
if (id == null) continue;
|
||||
var u = Items.IsGpu(it) ? Items.ToUnit(it) : null;
|
||||
var s = d.Black.List(id, u?.Model, u?.FakeOf, u?.Health ?? 0, BlackDelivery.RefValue(it), mult, d.Hot, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
var s = d.Black.List(id, u?.Model, u?.FakeOf, u?.Health ?? 0, BlackDelivery.RefValue(it), mult, pw, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
if (s == null) break;
|
||||
it.Destroy();
|
||||
n++;
|
||||
@@ -456,13 +525,13 @@ namespace Decentralized
|
||||
Open();
|
||||
}
|
||||
|
||||
private static void ListItem(GameItem it, double mult, string asset)
|
||||
private static void ListItem(GameItem it, double mult, string asset, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
string id = BlackDelivery.SellId(it);
|
||||
if (id == null) { Open(); return; }
|
||||
var u = Items.IsGpu(it) ? Items.ToUnit(it) : null;
|
||||
var s = d.Black.List(id, u?.Model, u?.FakeOf, u?.Health ?? 0, BlackDelivery.RefValue(it), mult, d.Hot, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
var s = d.Black.List(id, u?.Model, u?.FakeOf, u?.Health ?? 0, BlackDelivery.RefValue(it), mult, pw, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
if (s == null) { _message = d.Black.ActiveListings >= Tuning.BmMaxListings ? L.T("black.sell.full", Tuning.BmMaxListings) : L.T("msg.balance"); Open(); return; }
|
||||
it.Destroy();
|
||||
_message = L.T("black.sell.listed", ItemName(id), s.ListPrice);
|
||||
@@ -496,7 +565,7 @@ namespace Decentralized
|
||||
{
|
||||
if (!ok) return;
|
||||
string asset = _payAsset; var mode = _mode;
|
||||
BeginPay(seller.Name, ItemName(listing.Item) + (count > 1 ? " ×" + count : ""), asset, BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, count), mode), () => PlaceOrder(listing, count, asset, mode));
|
||||
BeginPay(seller.Name, ItemName(listing.Item) + (count > 1 ? " ×" + count : ""), asset, BlackMarket.Pay(BlackMarket.OrderTotal(listing.Price, count), mode), pw => PlaceOrder(listing, count, asset, mode, pw));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -533,10 +602,10 @@ namespace Decentralized
|
||||
private static string ItemName(string id) => BlackDelivery.ItemName(id);
|
||||
|
||||
/// <summary>开账单:收款地址、币种、金额(按信用点等值折成币),付款在硬件钱包里做。</summary>
|
||||
private static void BeginPay(string address, string summary, string asset, double credits, Action execute) =>
|
||||
private static void BeginPay(string address, string summary, string asset, double credits, Action<Wallet> execute) =>
|
||||
BillFor(address, summary, asset, credits / Session.Price(asset), execute);
|
||||
|
||||
private static void BillFor(string address, string summary, string asset, double amount, Action execute)
|
||||
private static void BillFor(string address, string summary, string asset, double amount, Action<Wallet> execute)
|
||||
{
|
||||
WalletWindow.Pending = new WalletWindow.Bill { Address = address, Summary = summary, Asset = asset, Amount = WalletWindow.RoundUp(amount), Execute = execute };
|
||||
_message = null;
|
||||
@@ -557,7 +626,7 @@ namespace Decentralized
|
||||
b.End();
|
||||
}
|
||||
|
||||
private static void BuyOffer(BmOffer o, int count, string asset)
|
||||
private static void BuyOffer(BmOffer o, int count, string asset, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
string item = o.Item, model = o.Model, fake = o.FakeOf;
|
||||
@@ -565,7 +634,7 @@ namespace Decentralized
|
||||
int bought = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!d.Black.Buy(o, d.Hot, asset, Session.Price)) break;
|
||||
if (!d.Black.Buy(o, pw, asset, Session.Price)) break;
|
||||
Items.Give(BlackDelivery.Make(item, model, fake, health));
|
||||
bought++;
|
||||
}
|
||||
@@ -575,10 +644,10 @@ namespace Decentralized
|
||||
Open();
|
||||
}
|
||||
|
||||
private static void PlaceOrder(BmListing l, int count, string asset, PayMode mode)
|
||||
private static void PlaceOrder(BmListing l, int count, string asset, PayMode mode, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
var o = d.Black.Place(l, count, mode, d.Hot, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
var o = d.Black.Place(l, count, mode, pw, asset, StoreStation.GetDayCounter(), Session.Price);
|
||||
if (o == null) { _message = L.T("msg.balance"); Open(); return; }
|
||||
_message = L.T("black.ordered", ItemName(o.Item) + (o.Count > 1 ? " ×" + o.Count : ""), o.DueDay);
|
||||
Session.Save();
|
||||
@@ -625,16 +694,16 @@ namespace Decentralized
|
||||
_edit = null;
|
||||
string asset = _payAsset;
|
||||
BeginPay(d.Address("platform"), ItemName(e.Id) + L.T(e.Sale != null ? "pay.repricefee" : "pay.listfee", mult.ToString("0.00", CultureInfo.InvariantCulture)), asset, fee,
|
||||
() => { if (e.Sale != null) RepriceSale(e.Sale, mult, asset); else ListItem(e.Item, mult, asset); });
|
||||
pw => { if (e.Sale != null) RepriceSale(e.Sale, mult, asset, pw); else ListItem(e.Item, mult, asset, pw); });
|
||||
});
|
||||
b.AddButton(L.T("black.edit.cancel"), () => { _edit = null; _message = null; Open(); });
|
||||
b.End();
|
||||
}
|
||||
|
||||
private static void RepriceSale(BmSale s, double mult, string asset)
|
||||
private static void RepriceSale(BmSale s, double mult, string asset, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
if (!d.Black.Reprice(s, mult, d.Hot, asset, StoreStation.GetDayCounter(), Session.Price)) { _message = L.T("msg.balance"); Open(); return; }
|
||||
if (!d.Black.Reprice(s, mult, pw, asset, StoreStation.GetDayCounter(), Session.Price)) { _message = L.T("msg.balance"); Open(); return; }
|
||||
_message = L.T("black.sell.repriced", ItemName(s.Item), s.ListPrice);
|
||||
Session.Save();
|
||||
Open();
|
||||
@@ -701,16 +770,16 @@ namespace Decentralized
|
||||
bool into = _deskIn; string other = _deskAsset;
|
||||
string asset = into ? other : Assets.Ponero;
|
||||
_web3Tab = Web3Tab.Trade;
|
||||
BillFor(d.Address("desk"), L.T("pay.swap", Fmt.Num(dv), asset), asset, dv, () => DeskSwap(dv, into, other));
|
||||
BillFor(d.Address("desk"), L.T("pay.swap", Fmt.Num(dv), asset), asset, dv, pw => DeskSwap(dv, into, other, pw));
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeskSwap(double v, bool into, string other)
|
||||
private static void DeskSwap(double v, bool into, string other, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
_deskIn = into; _deskAsset = other;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
double got = _deskIn ? d.Black.ToPonero(d.Hot, _deskAsset, v, day, Session.Price) : d.Black.FromPonero(d.Hot, _deskAsset, v, day, Session.Price);
|
||||
double got = _deskIn ? d.Black.ToPonero(pw, _deskAsset, v, day, Session.Price) : d.Black.FromPonero(pw, _deskAsset, v, day, Session.Price);
|
||||
if (got < 0) { _message = L.T("black.desk.fail"); Open(); return; }
|
||||
// 从 Ponero 出来的币来源不明:出金审查按"来自混币器"加重
|
||||
if (!_deskIn) d.Mixer.LastReturnDay = day;
|
||||
@@ -774,17 +843,17 @@ namespace Decentralized
|
||||
{
|
||||
if (!ReadAmount(out double mv)) return;
|
||||
string asset = _mixAsset; int rounds = _mixRounds;
|
||||
BillFor(d.Address("mixer"), L.T("pay.mix", Fmt.Num(mv), asset), asset, mv, () => MixDeposit(mv, asset, rounds));
|
||||
BillFor(d.Address("mixer"), L.T("pay.mix", Fmt.Num(mv), asset), asset, mv, pw => MixDeposit(mv, asset, rounds, pw));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static void MixDeposit(double v, string asset, int rounds)
|
||||
private static void MixDeposit(double v, string asset, int rounds, Wallet pw)
|
||||
{
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (d.Hot.Avail(asset) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
var dep = d.Mixer.Deposit(d.Hot, asset, v, rounds, day, Session.Price);
|
||||
if (pw.Avail(asset) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
var dep = d.Mixer.Deposit(pw, asset, v, rounds, day, Session.Price);
|
||||
_message = dep == null ? L.T("mixer.min", Tuning.MixerMin) : L.T("mixer.done", Fmt.Num(v), asset, dep.ReadyDay);
|
||||
Session.Save();
|
||||
Open();
|
||||
@@ -825,7 +894,7 @@ namespace Decentralized
|
||||
int credits = (int)Math.Floor(v);
|
||||
if (credits <= 0 || PlayerStore.Instance.playerCash < credits) { _message = L.T("msg.balance"); Open(); return; }
|
||||
ModHelper.AddCredit(-credits, false);
|
||||
var w = Session.Data.Hot;
|
||||
var w = Session.Data.Poinbase;
|
||||
w.Add(Assets.CRC, credits / Session.Data.Stable.Crc);
|
||||
w.RecordBuy(Assets.CRC, credits / Session.Data.Stable.Crc, credits);
|
||||
w.Basis += credits;
|
||||
@@ -838,8 +907,8 @@ namespace Decentralized
|
||||
{
|
||||
if (!ReadAmount(out double v)) return;
|
||||
var d = Session.Data;
|
||||
if (d.Hot.Get(Assets.CRC) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
var r = d.Exchange.Cashout(d.Hot, v, Session.Price, StoreStation.GetDayCounter(), Session.Rent(), d.Mixer.RecentlyMixed(StoreStation.GetDayCounter()), d.Rng);
|
||||
if (d.Poinbase.Avail(Assets.CRC) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
var r = d.Exchange.Cashout(d.Poinbase, v, Session.Price, StoreStation.GetDayCounter(), Session.Rent(), d.Mixer.RecentlyMixed(StoreStation.GetDayCounter()), d.Rng);
|
||||
int got = (int)Math.Floor(r.Received - r.Tax);
|
||||
ModHelper.AddCredit(got, true);
|
||||
_message = L.T("msg.cashout", got, Fmt.Credits(r.Tax));
|
||||
@@ -857,19 +926,18 @@ namespace Decentralized
|
||||
private static void Trade(Pool p, bool buy)
|
||||
{
|
||||
if (!ReadAmount(out double v)) return;
|
||||
var w = Session.Data.Hot;
|
||||
var w = p.Venue == Venue.Dex ? Session.Data.Hot : Session.Data.Poinbase;
|
||||
string pay = buy ? p.Quote : p.Base, get = buy ? p.Base : p.Quote;
|
||||
if (w.Avail(pay) + 1e-9 < v) { _message = L.T(frozenPay(w, pay) ? "msg.frozen" : "msg.balance"); Open(); return; }
|
||||
if (p.Venue != Venue.Dex) { DoTrade(p, buy, v); return; }
|
||||
if (p.Venue != Venue.Dex) { DoTrade(p, buy, v, w); return; }
|
||||
double quote = buy ? v / p.Price : v * p.Price;
|
||||
_message = L.T("hw.wait");
|
||||
Open();
|
||||
WalletWindow.OpenForBill(new WalletWindow.Bill { Contract = true, Summary = L.T("hw.swap", Fmt.Num(v), pay, Fmt.Num(quote), get), Execute = () => DoTrade(p, buy, v) });
|
||||
WalletWindow.OpenForBill(new WalletWindow.Bill { Contract = true, Summary = L.T("hw.swap", Fmt.Num(v), pay, Fmt.Num(quote), get), Execute = pw => DoTrade(p, buy, v, pw) });
|
||||
}
|
||||
|
||||
private static void DoTrade(Pool p, bool buy, double v)
|
||||
private static void DoTrade(Pool p, bool buy, double v, Wallet w)
|
||||
{
|
||||
var w = Session.Data.Hot;
|
||||
string pay = buy ? p.Quote : p.Base, get = buy ? p.Base : p.Quote;
|
||||
if (w.Avail(pay) + 1e-9 < v) { _message = L.T(frozenPay(w, pay) ? "msg.frozen" : "msg.balance"); Open(); return; }
|
||||
double got = buy ? p.BuyBase(v) : p.SellBase(v);
|
||||
|
||||
Reference in new issue
Block a user