第十阶段 stage 2(二):CRA 部分抵押(储备、抵押率、挪用与崩盘线、劫掠补储备)、官方铸造与销毁排队、官方跑路、质押多币种入口
This commit is contained in:
1 parent
3758049dcb
commit
d0dfa93226
17 files changed
+493
-117
No files matched your search
@@ -2234,7 +2234,15 @@ namespace Decentralized
|
||||
}
|
||||
}
|
||||
l.AddSeparator();
|
||||
l.AddLabel(L.T("mint.reserve", (st.Ratio * 100).ToString("0", CultureInfo.InvariantCulture), (st.C * 100).ToString("0", CultureInfo.InvariantCulture)), "mint_reserve_dim");
|
||||
l.AddLabel(L.T("spark.price", Fmt.Num(st.Spark)));
|
||||
var mine = st.Orders.Where(o => d.Own(o.Wallet) != null).ToList();
|
||||
if (mine.Count > 0)
|
||||
{
|
||||
l.AddSeparator();
|
||||
l.AddLabel(L.T("mint.queue"));
|
||||
foreach (var o in mine) l.AddLabel(L.T("mint.order", L.T(o.Mint ? "cra.mint" : "cra.burn"), Fmt.Num(o.Cra), o.Due), "mint_order_dim");
|
||||
}
|
||||
}, r =>
|
||||
{
|
||||
r.AddHeader(L.T("stake.ops", WalletWindow.NameOf(w)));
|
||||
@@ -2242,19 +2250,35 @@ namespace Decentralized
|
||||
r.AddLabel(L.T("stake.avail2", Fmt.Num(w.Avail(Assets.SPARK))), "stake_avail2_dim");
|
||||
AmountRow(r);
|
||||
r.AddSpace(4f);
|
||||
r.AddLabel(L.T("stake.coin"));
|
||||
r.BeginRow(4f);
|
||||
foreach (var c in StakeCoins)
|
||||
{
|
||||
var coin = c;
|
||||
PledgerSkin.Pick(r, coin, coin == _stakeCoin, () => { _stakeCoin = coin; Open(); }, _picked);
|
||||
}
|
||||
r.End();
|
||||
r.BeginRow(6f);
|
||||
r.AddButton(L.T("stake.do"), () => StakeCall(true));
|
||||
r.AddButton(L.T("stake.undo"), () => StakeCall(false));
|
||||
r.End();
|
||||
r.AddSeparator();
|
||||
r.AddHeader(L.T("spark.h"));
|
||||
r.AddHeader(L.T("mint.h"));
|
||||
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double mv) && mv > 0)
|
||||
{
|
||||
st.Collateral(mv, out double needCrc, out double needSpark);
|
||||
r.AddLabel(L.T("mint.need", Fmt.Num(needCrc), Fmt.Num(needSpark)), "mint_need_dim");
|
||||
}
|
||||
r.BeginRow(6f);
|
||||
r.AddButton(L.T("spark.mint"), () => SparkCall(true));
|
||||
r.AddButton(L.T("spark.burn"), () => SparkCall(false));
|
||||
r.AddButton(L.T("cra.mint"), () => MintCall(true));
|
||||
r.AddButton(L.T("cra.burn"), () => MintCall(false));
|
||||
r.End();
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly string[] StakeCoins = { Assets.CRA, Assets.CRC, Assets.CRT, Assets.SPARK };
|
||||
private static string _stakeCoin = Assets.CRA;
|
||||
|
||||
/// <summary>手续费用钱包里价值最高的那种币付。</summary>
|
||||
private static string BestFeeAsset(Wallet w) =>
|
||||
w.Balances.Where(k => k.Value > 1e-9 && Session.Price(k.Key) > 0).OrderByDescending(k => k.Value * Session.Price(k.Key)).Select(k => k.Key).FirstOrDefault() ?? Assets.PSC;
|
||||
@@ -2264,42 +2288,57 @@ namespace Decentralized
|
||||
if (!ReadAmount(out double v)) return;
|
||||
var d = Session.Data;
|
||||
var w = d.Hot;
|
||||
if (into ? w.Avail(Assets.CRA) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
string coin = into ? _stakeCoin : Assets.CRA;
|
||||
if (into ? w.Avail(coin) + 1e-9 < v : (d.Staking.Of(w.Address)?.Amount ?? 0) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
var q = into && coin != Assets.CRA ? d.Market.Quote(coin, Assets.CRA, v) : null;
|
||||
_message = L.T("hw.wait");
|
||||
Open();
|
||||
WalletWindow.OpenForBill(new WalletWindow.Bill
|
||||
{
|
||||
Contract = true, Asset = Assets.CRA, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w),
|
||||
Summary = L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
||||
Contract = true, Asset = coin, Amount = v, Spend = into ? v : 0, FeeAsset = into ? null : BestFeeAsset(w),
|
||||
Summary = into && q != null ? L.T("stake.sum.via", Fmt.Num(v), coin, Fmt.Num(q.Out)) : L.T(into ? "stake.sum.in" : "stake.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
||||
Execute = pw =>
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
bool ok = into ? d.Staking.Stake(pw, v, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
||||
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(v), day + Tuning.CraUnlockDays) : L.T("msg.balance");
|
||||
double cra = v;
|
||||
if (into && coin != Assets.CRA)
|
||||
{
|
||||
if (pw.Avail(coin) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
double spent = v * Session.Price(coin);
|
||||
cra = d.Market.Swap(coin, Assets.CRA, v);
|
||||
pw.Add(coin, -v); pw.Add(Assets.CRA, cra); pw.RecordBuy(Assets.CRA, cra, spent);
|
||||
CandleChart.Trade(coin, spent); CandleChart.Trade(Assets.CRA, spent);
|
||||
}
|
||||
bool ok = into ? d.Staking.Stake(pw, cra, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
||||
_message = ok ? L.T(into ? "stake.done.in" : "stake.done.out", Fmt.Num(cra), day + Tuning.CraUnlockDays) : L.T("msg.balance");
|
||||
Session.Save();
|
||||
Open();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private static void SparkCall(bool mint)
|
||||
/// <summary>官方一级市场:存入 CRC 和 SPARK 铸造 CRA(铸出后直接进质押),或销毁 CRA 换回两者。排队等待,官方可能不兑现。</summary>
|
||||
private static void MintCall(bool mint)
|
||||
{
|
||||
if (!ReadAmount(out double v)) return;
|
||||
var d = Session.Data;
|
||||
var w = d.Hot;
|
||||
string pay = mint ? Assets.CRA : Assets.SPARK, get = mint ? Assets.SPARK : Assets.CRA;
|
||||
if (w.Avail(pay) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||
double quote = mint ? v * d.Stable.Cra / d.Stable.Spark * (1 - Tuning.SparkFee) : v * d.Stable.Spark / d.Stable.Cra * (1 - Tuning.SparkFee);
|
||||
var st = d.Stable;
|
||||
st.Collateral(v, out double needCrc, out double needSpark);
|
||||
bool enough = mint ? w.Avail(Assets.CRC) + 1e-9 >= needCrc && w.Avail(Assets.SPARK) + 1e-9 >= needSpark : w.Avail(Assets.CRA) + 1e-9 >= v;
|
||||
if (!enough) { _message = L.T("msg.balance"); Open(); return; }
|
||||
int minD = Tuning.CraMintDaysMin, maxD = Tuning.CraMintDaysMax;
|
||||
_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),
|
||||
Contract = true, Asset = mint ? Assets.CRC : Assets.CRA, Amount = mint ? needCrc : v, Spend = mint ? needCrc : v,
|
||||
Summary = mint ? L.T("mint.sum.in", Fmt.Num(v), Fmt.Num(needCrc), Fmt.Num(needSpark), minD, maxD) : L.T("mint.sum.out", Fmt.Num(v), Tuning.CraUnlockDays),
|
||||
Execute = pw =>
|
||||
{
|
||||
double got = mint ? d.Stable.Mint(pw, v) : d.Stable.Burn(pw, v);
|
||||
if (got >= 0) { double cr = v * Session.Price(pay); CandleChart.Trade(Assets.SPARK, cr); CandleChart.Trade(Assets.CRA, cr); }
|
||||
_message = got < 0 ? L.T("msg.balance") : L.T("msg.trade", Fmt.Num(v), pay, Fmt.Num(got), get);
|
||||
int day = StoreStation.GetDayCounter();
|
||||
var o = mint ? st.RequestMint(pw, v, day, d.Rng) : st.RequestBurn(pw, v, day);
|
||||
_message = o == null ? L.T("msg.balance") : L.T(mint ? "mint.done.in" : "mint.done.out", o.Due);
|
||||
Session.Save();
|
||||
Open();
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user