第十阶段 stage 2(一):交易对改为 X/CRC 池,任意币互换经 CRC 两跳路由,币价表改为 CRC 价格

This commit is contained in:
ZHU MINCHAO committed 2026-11-05 07:09:05 +08:00
1 parent 75fb6d6b2a
commit 3758049dcb
14 files changed
+196 -48

No files matched your search

+76 -21
View File
@@ -231,9 +231,6 @@ namespace Decentralized
b.AddLabel(L.T("aml.taint", (int)Math.Round(taintRatio * 100)), taintRatio > 0.05 ? "aml_note" : "aml_dim");
}
private static readonly float[] StableWBase = new[] { 80f, 100f, 220f };
private static float[] StableW => Sc(StableWBase);
private static string StableStatus(Stablecoins st, string asset, int day)
{
double p = st.Price(asset);
@@ -242,15 +239,78 @@ namespace Decentralized
return p < 0.99 ? L.T("stable.depeg") : L.T("stable.ok");
}
/// <summary>稳定币行情:价格与状态(脱锚、预兆)。</summary>
private static void StableTable(CustomUIBuilder b)
private static readonly float[] PriceWBase = new[] { 100f, 160f };
private static float[] PriceW => Sc(PriceWBase);
private static readonly string[] SwapCoins = { Assets.PSC, Assets.CRC, Assets.CRT, Assets.CRA, Assets.SPARK };
private static string _swapFrom = Assets.CRC, _swapTo = Assets.PSC;
/// <summary>币价表:各币在 DEX 池里以 CRC 计的价格。</summary>
private static void PriceTable(CustomUIBuilder b)
{
var st = Session.Data.Stable;
int day = StoreStation.GetDayCounter();
var m = Session.Data.Market;
b.AddSeparator();
TableHeader(b, StableW, L.T("col.asset"), L.T("col.peg"), L.T("col.status"));
foreach (var a in new[] { Assets.CRC, Assets.CRT, Assets.CRA })
TableRow(b, StableW, a, Fmt.Num(st.Price(a)), StableStatus(st, a, day));
TableHeader(b, PriceW, L.T("col.asset"), L.T("col.crcprice"));
foreach (var a in SwapCoins.Where(x => x != Assets.CRC))
TableRow(b, PriceW, a, Fmt.Num(m.DexPool(a).Price));
}
/// <summary>互换:任意币对任意币,实际经 CRC 路由;预览显示得到数量、经过几个池、损耗。</summary>
private static void SwapBlock(CustomUIBuilder b)
{
var m = Session.Data.Market;
Action<string, string, bool> picker = (label, cur, from) =>
{
b.AddLabel(label);
b.BeginRow(4f);
foreach (var c in SwapCoins)
{
var coin = c;
PledgerSkin.Pick(b, coin, coin == cur, () =>
{
if (from) { _swapFrom = coin; if (_swapTo == coin) _swapTo = SwapCoins.First(x => x != coin); }
else { _swapTo = coin; if (_swapFrom == coin) _swapFrom = SwapCoins.First(x => x != coin); }
Open();
}, _picked);
}
b.End();
};
AmountRow(b);
picker(L.T("swap.pay"), _swapFrom, true);
picker(L.T("swap.get"), _swapTo, false);
double v;
bool ok = double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out v) && v > 0;
var q = ok ? m.Quote(_swapFrom, _swapTo, v) : null;
if (q != null) b.AddLabel(L.T("swap.preview", Fmt.Num(q.Out), _swapTo, q.Hops, (q.Impact * 100).ToString("0.0", CultureInfo.InvariantCulture)), "swap_preview_dim");
b.AddButton(L.T("swap.go"), () => Swap());
}
/// <summary>互换:DEX 是合约调用,要在硬件钱包上签名。</summary>
private static void Swap()
{
if (!ReadAmount(out double v)) return;
string from = _swapFrom, to = _swapTo;
var q = Session.Data.Market.Quote(from, to, v);
if (q == null) { _message = L.T("swap.same"); Open(); return; }
var w = Session.Data.Hot;
if (w.Avail(from) + 1e-9 < v) { _message = L.T(frozenPay(w, from) ? "msg.frozen" : "msg.balance"); Open(); return; }
_message = L.T("hw.wait");
Open();
WalletWindow.OpenForBill(new WalletWindow.Bill { Contract = true, Asset = from, Amount = v, Summary = L.T("hw.swap", Fmt.Num(v), from, Fmt.Num(q.Out), to), Execute = pw => DoSwap(from, to, v, pw) });
}
private static void DoSwap(string from, string to, double v, Wallet w)
{
if (w.Avail(from) + 1e-9 < v) { _message = L.T(frozenPay(w, from) ? "msg.frozen" : "msg.balance"); Open(); return; }
double got = Session.Data.Market.Swap(from, to, v);
if (got <= 0) { _message = L.T("swap.same"); Open(); return; }
double spent = v * Session.Price(from);
CandleChart.Trade(from, spent); CandleChart.Trade(to, spent);
w.Add(from, -v);
w.Add(to, got);
w.RecordBuy(to, got, spent);
_message = L.T("msg.trade", Fmt.Num(v), from, Fmt.Num(got), to);
Session.Save();
Open();
}
private static void TradeRows(CustomUIBuilder b, Venue venue)
@@ -1193,14 +1253,13 @@ namespace Decentralized
l.AddSeparator();
l.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price))));
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
StableTable(l);
PriceTable(l);
l.AddSeparator();
CandleChart.AddPicker(l, "web3", Assets.PSC, Open, _picked);
}, r =>
{
r.AddHeader(L.T("trade.h"));
AmountRow(r);
TradeRows(r, Venue.Dex);
SwapBlock(r);
if (Unlock.BlackUnlocked && BlackMarket.DeskOpen(StoreReputation.GetBMReputation())) PoneroBlock(r);
});
}
@@ -2311,18 +2370,14 @@ namespace Decentralized
Open();
}
/// <summary>交易:Poinbase 是托管账户,直接成交;DEX 是合约调用,要在硬件钱包上签名。</summary>
/// <summary>交易:Poinbase 是托管账户,直接成交。</summary>
private static void Trade(Pool p, bool buy)
{
if (!ReadAmount(out double v)) return;
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;
var w = Session.Data.Poinbase;
string pay = buy ? p.Quote : p.Base;
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, w); return; }
double quote = buy ? v / p.Price : v * p.Price;
_message = L.T("hw.wait");
Open();
WalletWindow.OpenForBill(new WalletWindow.Bill { Contract = true, Asset = pay, Amount = v, Summary = L.T("hw.swap", Fmt.Num(v), pay, Fmt.Num(quote), get), Execute = pw => DoTrade(p, buy, v, pw) });
DoTrade(p, buy, v, w);
}
private static void DoTrade(Pool p, bool buy, double v, Wallet w)