第十阶段 stage 2(三):Poinbase 资金页(入金、出金、确认进度条)、银行页只读、Poinbase 接收所有币

This commit is contained in:
ZHU MINCHAO committed 2026-11-05 07:19:38 +08:00
1 parent d0dfa93226
commit e3e5ec2d6e
14 files changed
+344 -84

No files matched your search

+2
View File
@@ -59,6 +59,8 @@ namespace Decentralized.Domain
public const double CraEmbezzleMin = 0.4, CraEmbezzleMax = 0.8, CraLoot = 0.09;
public const int CraMintDaysMin = 1, CraMintDaysMax = 2;
public const double CraRugPerDepeg = 1;
/// <summary>Poinbase 出金到钱包的确认动画:基础秒数,加每个确认的秒数(确认数同 PLEDGER 的 TxConfirm*)。</summary>
public const double FundsBaseSecs = 1.2, FundsConfSecs = 0.6;
public const double CraSpiralWeekly = 0.03;
public const int CraWarnLeadMin = 4, CraWarnLeadMax = 7;
public static readonly double[] CraSpiralPath = { 0.85, 0.30, 0.02 };
+2
View File
@@ -234,6 +234,8 @@ namespace Decentralized.Domain
["FakeSignChance"] = Tuning.FakeSignChance,
["FakeSupportChance"] = Tuning.FakeSupportChance,
["FakeTransferShare"] = Tuning.FakeTransferShare,
["FundsBaseSecs"] = Tuning.FundsBaseSecs,
["FundsConfSecs"] = Tuning.FundsConfSecs,
["HalvingDays"] = Tuning.HalvingDays,
["HalvingPassMax"] = Tuning.HalvingPassMax,
["HalvingPassMin"] = Tuning.HalvingPassMin,
+1
View File
@@ -183,6 +183,7 @@ namespace Decentralized
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Perp fund 0 (test)", () => { Session.Data.Perps.InsuranceFund = 0; Log.Info("测试:保险基金清零"); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "SPARK x0.3 (test)", () => { var st = Session.Data.Stable; st.Spark *= 0.3; Log.Info($"测试:SPARK 价格 {st.Spark:0.00}"); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Wallet gift: CRC, CRA, PSC (test)", () => { var w = Session.Data.Hot; w.Add(Assets.CRA, 1000); w.Add(Assets.CRC, 1000); w.Add(Assets.CRT, 3000); w.Add(Assets.PSC, 20); w.Basis += 5000; Log.Info($"测试:{WalletWindow.NameOf(w)} CRA {w.Get(Assets.CRA):0}"); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Poinbase gift: CRC, PSC (test)", () => { var pb = Session.Data.Poinbase; pb.Add(Assets.CRC, 5000); pb.Add(Assets.PSC, 30); pb.Basis += 8000; Log.Info($"测试:Poinbase CRC {pb.Get(Assets.CRC):0}"); });
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "CRA spiral warning (test)", () =>
{
var st = Session.Data.Stable; int day = StoreStation.GetDayCounter();
+113
View File
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Decentralized.Domain;
using UnityEngine;
namespace Decentralized
{
/// <summary>
/// Poinbase 的出金:转到钱包地址。托管账户发起,几秒钟的确认动画(模拟交易所触发合约执行)走完才落地;
/// 手续费固定中间档,从转出的币里扣。动画走完前币还在账户里,中途存档、退出都不会丢币。
/// 地址格式或校验位不对拒绝;自己的钱包到账;别的格式正确的地址按黑洞处理(币就没了)。
/// </summary>
internal static class Funds
{
internal sealed class Tx
{
public int Id, Confs;
public string Asset, To;
public double Amount, Fee;
public float Start, Total;
public bool Finished;
}
internal static readonly List<Tx> Active = new List<Tx>();
private static int seq;
/// <summary>地址检查:返回 null 表示可以转,否则是错误文案的键。</summary>
internal static string Check(string to)
{
var d = Session.Data;
to = ChainAddress.Normalize(to ?? "");
if (!ChainAddress.Valid(to)) return "funds.err.addr";
if (ChainAddress.Same(to, d.Address("poinbase"))) return "funds.err.self";
if (d.Own(to) == null && WalletWindow.Known(to)) return "funds.err.known";
return null;
}
private static bool Congested
{
get { var d = Session.Data; int day = StoreStation.GetDayCounter(); return day >= d.CongestedFrom && day <= d.CongestedUntil; }
}
/// <summary>开始一笔出金。余额不足或手续费吃掉全部数额返回错误键,成功返回 null。</summary>
internal static string Start(string asset, double amount, string to)
{
var d = Session.Data;
var err = Check(to);
if (err != null) return err;
var pb = d.Poinbase;
if (pb.Avail(asset) + 1e-9 < amount) return pb.Frozen.ContainsKey(asset) ? "msg.frozen" : "msg.balance";
double price = Session.Price(asset);
double fee = price > 0 ? TxRules.FeeCredits(FeeTier.Normal, Congested, d.Gas) / price : 0;
if (fee >= amount) return "funds.err.fee";
double value = amount * price;
int confs = TxRules.Confirmations(value);
Active.Add(new Tx
{
Id = ++seq, Asset = asset, To = ChainAddress.Normalize(to), Amount = amount, Fee = fee, Confs = confs,
Start = Time.unscaledTime, Total = (float)(Tuning.FundsBaseSecs + confs * Tuning.FundsConfSecs),
});
WalletDriver.Ensure();
return null;
}
internal static float Progress(Tx t) => t.Total <= 0 ? 1 : Mathf.Clamp01((Time.unscaledTime - t.Start) / t.Total);
internal static int Conf(Tx t) => Math.Max(1, Math.Min(t.Confs, 1 + (int)((Time.unscaledTime - t.Start) / Math.Max(0.01f, t.Total) * t.Confs)));
internal static string StatusText(Tx t) => L.T("funds.confirm", Conf(t), t.Confs);
/// <summary>每帧:更新开着的窗口里的进度条,走完的落地。</summary>
internal static void Tick()
{
if (Active.Count == 0) return;
var m = CustomUIManager.Instance;
foreach (var t in Active.ToList())
{
if (Time.unscaledTime - t.Start >= t.Total) { Finish(t); continue; }
m?.GetElement(TerminalWindow.Id, "funds_status_" + t.Id)?.SetText(StatusText(t));
m?.GetElement(TerminalWindow.Id, "funds_prog_" + t.Id)?.SetProgress(Progress(t));
}
}
private static void Finish(Tx t)
{
if (t.Finished) return;
t.Finished = true;
Active.Remove(t);
Log.Guard("出金落地", () =>
{
var d = Session.Data;
var pb = d.Poinbase;
double amt = Math.Min(t.Amount, pb.Avail(t.Asset));
double fee = Math.Min(t.Fee, amt);
if (fee > 0) Wallet.Transfer(pb, new Wallet(), t.Asset, fee, Session.Price);
double net = amt - fee;
var own = d.Own(t.To);
Wallet.Transfer(pb, own ?? new Wallet(), t.Asset, net, Session.Price);
if (own != null)
{
TxRules.Record(own.History, new TxRecord { Addr = d.Address("poinbase"), Asset = t.Asset, Amount = net, Day = StoreStation.GetDayCounter(), In = true });
WalletWindow.RefreshDevice(own, true);
}
else Log.Info($"出金转进没人用的地址 {t.To}:{net} {t.Asset}");
Session.Save();
TerminalWindow.Refresh(own != null
? L.T("funds.done", Fmt.Num(net), t.Asset, WalletWindow.NameOf(own))
: L.T("funds.done.void", Fmt.Num(net), t.Asset));
});
}
}
}
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Credits
bank.rent.k,Miete
bank.rent.v,"{0}, fällig in {1} Tg."
bank.crc.k,Poinbase-Konto (CRC)
bank.ops,Ein-/Auszahlung
poin.account.h,Poinbase-Konto
trade.h,Handel
web3.wallet.h,On-Chain-Wallet
@@ -378,12 +377,9 @@ hw.wait,Auf der Wallet bestätigen.
hw.swap,Tausch {0} {1} → ca. {2} {3}
tab.wallets,Wallets
hw.wallet.n,Wallet {0}
hw.err.poinbase,Poinbase akzeptiert nur CRC und PSC.
hw.review.own,Eigene Wallet: {0}
hw.review.poinbase,Poinbase-Einzahlungsadresse
poin.deposit,Einzahlungsadresse: {0}
poin.out,Auszahlen an {0}
poin.out.done,{0} {1} an {2} ausgezahlt.
wallets.count,Wallets {0}/{1}
wallets.col.name,Name
wallets.col.addr,Adresse
@@ -919,3 +915,18 @@ nightlog.cra.burned,"{0} CRA eingelöst: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Der Herausgeber hat nicht reagiert: Der Auftrag ({1}) über {0} CRA ist verloren.
news.crawarn.desc,"Jemand zählt die Reserve der Revolution nach; gestaktes CRA lässt sich womöglich nicht vollständig einlösen. Das Entsperren dauert vier Tage; manche sagen, es sei Zeit zu handeln."
news.cralow.desc,Die Reservedeckung wird knapp; die Revolution hat den CRA-Staking-Zins auf einen Bruchteil gesenkt.
poin.sub.funds,Guthaben
funds.receive,Einzahlen
funds.send,Auszahlen
funds.bank,Bankkonto
funds.wallet,Wallet
funds.to,Zieladresse
funds.go,Senden
funds.sending,Sende {0} {1} an {2}
funds.confirm,Bestätigung {0}/{1}
funds.done,{0} {1} sind in {2} angekommen.
funds.done.void,"{0} {1} gesendet; die Adresse hat keinen Besitzer, die Coins sind weg."
funds.err.addr,Ungültige Adresse.
funds.err.self,Das ist die Einzahlungsadresse von Poinbase.
funds.err.known,Diese Adresse akzeptiert nur Zahlungen gegen Rechnung.
funds.err.fee,Der Betrag deckt die Gebühr nicht.
1 # Probably Decentralized localization table: German (de)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Credits
bank.rent.k,Rent
bank.rent.v,"{0}, due in {1} days"
bank.crc.k,Poinbase account (CRC)
bank.ops,Deposit / withdraw
poin.account.h,Poinbase account
trade.h,Trade
web3.wallet.h,On-chain wallet
@@ -378,12 +377,9 @@ hw.wait,Confirm on the wallet.
hw.swap,Swap {0} {1} → about {2} {3}
tab.wallets,Wallets
hw.wallet.n,Wallet {0}
hw.err.poinbase,Poinbase only accepts CRC and PSC.
hw.review.own,Own wallet: {0}
hw.review.poinbase,Poinbase deposit address
poin.deposit,Deposit address: {0}
poin.out,Withdraw to {0}
poin.out.done,{0} {1} withdrawn to {2}.
wallets.count,Wallets {0}/{1}
wallets.col.name,Name
wallets.col.addr,Address
@@ -919,3 +915,18 @@ nightlog.cra.burned,"Redeemed {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,The issuer did not respond: the {1} order of {0} CRA is lost.
news.crawarn.desc,"Someone is counting the Revolution's reserve, and staked CRA may not be redeemable in full. Unlocking takes four days; some say it is time to move."
news.cralow.desc,"The reserve ratio is running low, and the Revolution has cut the CRA staking rate to a fraction."
poin.sub.funds,Funds
funds.receive,Receive
funds.send,Send
funds.bank,Bank account
funds.wallet,Wallet
funds.to,To address
funds.go,Send
funds.sending,Sending {0} {1} to {2}
funds.confirm,Confirmation {0}/{1}
funds.done,{0} {1} arrived in {2}.
funds.done.void,{0} {1} sent; the address has no owner and the coins are gone.
funds.err.addr,Invalid address.
funds.err.self,That is the Poinbase deposit address.
funds.err.known,That address only accepts payments against a bill.
funds.err.fee,The amount does not cover the fee.
1 # Probably Decentralized localization table: English (en)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Créditos
bank.rent.k,Renta
bank.rent.v,"{0}, vence en {1} día(s)"
bank.crc.k,Cuenta de Poinbase (CRC)
bank.ops,Depósito / retiro
poin.account.h,Cuenta de Poinbase
trade.h,Comercio
web3.wallet.h,Billetera en cadena
@@ -378,12 +377,9 @@ hw.wait,Confirma en la billetera.
hw.swap,Canjear {0} {1} → aprox. {2} {3}
tab.wallets,Billeteras
hw.wallet.n,Billetera {0}
hw.err.poinbase,Poinbase solo acepta CRC y PSC.
hw.review.own,Billetera propia: {0}
hw.review.poinbase,Dirección de depósito de Poinbase
poin.deposit,Dirección de depósito: {0}
poin.out,Retirar a {0}
poin.out.done,Se retiraron {0} {1} a {2}.
wallets.count,Billeteras {0}/{1}
wallets.col.name,Nombre
wallets.col.addr,Dirección
@@ -919,3 +915,18 @@ nightlog.cra.burned,"{0} CRA redimidos: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,El emisor no respondió: la orden ({1}) de {0} CRA se perdió.
news.crawarn.desc,Alguien está contando la reserva de la Revolución y quizá los CRA apostados no se puedan redimir por completo. Desbloquear tarda cuatro días; algunos dicen que es hora de actuar.
news.cralow.desc,La cobertura de la reserva se agota y la Revolución ha recortado el tipo de apuesta de CRA a una fracción.
poin.sub.funds,Fondos
funds.receive,Depósito
funds.send,Retiro
funds.bank,Cuenta bancaria
funds.wallet,Monedero
funds.to,Dirección de destino
funds.go,Enviar
funds.sending,Enviando {0} {1} a {2}
funds.confirm,Confirmación {0}/{1}
funds.done,{0} {1} llegaron a {2}.
funds.done.void,{0} {1} enviados; la dirección no tiene dueño y las monedas se perdieron.
funds.err.addr,Dirección no válida.
funds.err.self,Esa es la dirección de depósito de Poinbase.
funds.err.known,Esa dirección solo acepta pagos contra una factura.
funds.err.fee,La cantidad no cubre la comisión.
1 # Probably Decentralized localization table: Spanish (es)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Crédits
bank.rent.k,Loyer
bank.rent.v,"{0}, échéance dans {1} jour(s)"
bank.crc.k,Compte Poinbase (CRC)
bank.ops,Dépôt / Retrait
poin.account.h,Compte Poinbase
trade.h,Trading
web3.wallet.h,Portefeuille on-chain
@@ -378,12 +377,9 @@ hw.wait,Confirmez sur le portefeuille.
hw.swap,Échanger {0} {1} → environ {2} {3}
tab.wallets,Portefeuilles
hw.wallet.n,Portefeuille {0}
hw.err.poinbase,Poinbase n'accepte que le CRC et le PSC.
hw.review.own,Portefeuille personnel : {0}
hw.review.poinbase,Adresse de dépôt Poinbase
poin.deposit,Adresse de dépôt : {0}
poin.out,Retirer vers {0}
poin.out.done,{0} {1} retirés vers {2}.
wallets.count,Portefeuilles {0}/{1}
wallets.col.name,Nom
wallets.col.addr,Adresse
@@ -919,3 +915,18 @@ nightlog.cra.burned,"{0} CRA rachetés : +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,L'émetteur n'a pas répondu : l'ordre ({1}) de {0} CRA est perdu.
news.crawarn.desc,Quelqu'un fait l'inventaire de la réserve de la Révolution ; les CRA stakés pourraient ne pas être remboursés en totalité. Le déblocage prend quatre jours ; certains disent qu'il est temps d'agir.
news.cralow.desc,La couverture de la réserve s'amenuise ; la Révolution a réduit le taux de staking du CRA à une fraction.
poin.sub.funds,Fonds
funds.receive,Dépôt
funds.send,Retrait
funds.bank,Compte bancaire
funds.wallet,Portefeuille
funds.to,Adresse de destination
funds.go,Envoyer
funds.sending,Envoi de {0} {1} vers {2}
funds.confirm,Confirmation {0}/{1}
funds.done,{0} {1} sont arrivés dans {2}.
funds.done.void,"{0} {1} envoyés ; l'adresse n'a pas de propriétaire, les pièces sont perdues."
funds.err.addr,Adresse invalide.
funds.err.self,C'est l'adresse de dépôt de Poinbase.
funds.err.known,Cette adresse n'accepte que les paiements d'une facture.
funds.err.fee,Le montant ne couvre pas les frais.
1 # Probably Decentralized localization table: French (fr)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,クレジット
bank.rent.k,家賃
bank.rent.v,{0}、期日:{1}日後
bank.crc.k,Poinbase口座(CRC)
bank.ops,入出金
poin.account.h,Poinbase口座
trade.h,取引
web3.wallet.h,オンチェーンウォレット
@@ -378,12 +377,9 @@ hw.wait,ウォレットで確認してください。
hw.swap,スワップ {0} {1} → 約 {2} {3}
tab.wallets,ウォレット
hw.wallet.n,ウォレット {0}
hw.err.poinbase,PoinbaseはCRCおよびPSCの入金のみ受け付けています。
hw.review.own,自身のウォレット:{0}
hw.review.poinbase,Poinbase入金アドレス
poin.deposit,入金アドレス:{0}
poin.out,{0} へ出金
poin.out.done,{0} {1} を {2} に出金しました。
wallets.count,ウォレット {0}/{1}
wallets.col.name,名前
wallets.col.addr,アドレス
@@ -919,3 +915,18 @@ nightlog.cra.burned,{0} CRA を償還:+{1} CRC、+{2} SPARK({3})。
nightlog.cra.lost,発行元から応答がありません:{0} CRA の{1}注文は失われました。
news.crawarn.desc,革命軍の準備金を数え直す者がいる。ステークした CRA は全額償還できないかもしれない。解除には四日かかる。動くなら今だという声もある。
news.cralow.desc,準備率が危うくなり、革命軍は CRA のステーキング日利を元の数分の一に引き下げた。
poin.sub.funds,資金
funds.receive,入金
funds.send,出金
funds.bank,銀行口座
funds.wallet,ウォレット
funds.to,送金先アドレス
funds.go,送信
funds.sending,{0} {1} を {2} に送金中
funds.confirm,承認 {0}/{1}
funds.done,{0} {1} が {2} に着金しました。
funds.done.void,{0} {1} を送金しました。アドレスに持ち主がおらず、コインは戻りません。
funds.err.addr,アドレスが正しくありません。
funds.err.self,Poinbase 自身の入金アドレスです。
funds.err.known,そのアドレスは請求書に対する支払いのみ受け付けます。
funds.err.fee,金額が手数料に満たません。
Can't render this file because it contains an unexpected character in line 507 and column 24.
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Kredyty
bank.rent.k,Czynsz
bank.rent.v,"{0}, termin: {1} d."
bank.crc.k,Konto Poinbase (CRC)
bank.ops,Wpłata / wypłata
poin.account.h,Konto Poinbase
trade.h,Handel
web3.wallet.h,Portfel on-chain
@@ -378,12 +377,9 @@ hw.wait,Potwierdź na portfelu.
hw.swap,Wymiana {0} {1} → około {2} {3}
tab.wallets,Portfele
hw.wallet.n,Portfel {0}
hw.err.poinbase,Poinbase akceptuje tylko CRC i PSC.
hw.review.own,Własny portfel: {0}
hw.review.poinbase,Adres wpłaty Poinbase
poin.deposit,Adres wpłaty: {0}
poin.out,Wypłać na {0}
poin.out.done,Wypłacono {0} {1} na {2}.
wallets.count,Portfele {0}/{1}
wallets.col.name,Nazwa
wallets.col.addr,Adres
@@ -919,3 +915,18 @@ nightlog.cra.burned,"Umorzono {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Emitent nie odpowiedział: zlecenie ({1}) na {0} CRA przepadło.
news.crawarn.desc,"Ktoś liczy rezerwę Rewolucji i zastakowane CRA mogą nie zostać w pełni wypłacone. Odblokowanie trwa cztery dni; niektórzy mówią, że czas działać."
news.cralow.desc,"Pokrycie rezerwy maleje, a Rewolucja obniżyła stopę stakingu CRA do ułamka."
poin.sub.funds,Środki
funds.receive,Wpłata
funds.send,Wypłata
funds.bank,Konto bankowe
funds.wallet,Portfel
funds.to,Adres odbiorcy
funds.go,Wyślij
funds.sending,Wysyłanie {0} {1} na {2}
funds.confirm,Potwierdzenie {0}/{1}
funds.done,{0} {1} dotarło do {2}.
funds.done.void,"Wysłano {0} {1}; adres nie ma właściciela, monety przepadły."
funds.err.addr,Nieprawidłowy adres.
funds.err.self,To adres wpłat Poinbase.
funds.err.known,Ten adres przyjmuje tylko płatności za rachunek.
funds.err.fee,Kwota nie pokrywa opłaty.
1 # Probably Decentralized localization table: Polish (pl)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -145,7 +145,6 @@ bank.cash.k,Кредиты
bank.rent.k,Аренда
bank.rent.v,"{0}, оплата через {1} дн."
bank.crc.k,Счёт Poinbase (CRC)
bank.ops,Депозит / вывод
poin.account.h,Счёт Poinbase
trade.h,Торговля
web3.wallet.h,Ончейн-кошелёк
@@ -378,12 +377,9 @@ hw.wait,Подтвердите на кошельке.
hw.swap,Обмен {0} {1} → около {2} {3}
tab.wallets,Кошельки
hw.wallet.n,Кошелёк {0}
hw.err.poinbase,Poinbase принимает только CRC и PSC.
hw.review.own,Свой кошелёк: {0}
hw.review.poinbase,Адрес депозита Poinbase
poin.deposit,Адрес депозита: {0}
poin.out,Вывести на {0}
poin.out.done,{0} {1} выведено на {2}.
wallets.count,Кошельки {0}/{1}
wallets.col.name,Название
wallets.col.addr,Адрес
@@ -919,3 +915,18 @@ nightlog.cra.burned,"Погашено {0} CRA: +{1} CRC, +{2} SPARK ({3})."
nightlog.cra.lost,Эмитент не ответил: заявка ({1}) на {0} CRA потеряна.
news.crawarn.desc,"Кто-то пересчитывает резерв Революции, и CRA в стейкинге могут не выкупить полностью. Разблокировка занимает четыре дня; кое-кто говорит, что пора действовать."
news.cralow.desc,"Покрытие резерва тает, и Революция снизила ставку по стейкингу CRA до малой доли."
poin.sub.funds,Средства
funds.receive,Ввод
funds.send,Вывод
funds.bank,Банковский счёт
funds.wallet,Кошелёк
funds.to,Адрес получателя
funds.go,Отправить
funds.sending,Отправка {0} {1} на {2}
funds.confirm,Подтверждение {0}/{1}
funds.done,{0} {1} поступили в {2}.
funds.done.void,"{0} {1} отправлены; у адреса нет владельца, монеты потеряны."
funds.err.addr,Неверный адрес.
funds.err.self,Это адрес пополнения Poinbase.
funds.err.known,Этот адрес принимает только оплату по счёту.
funds.err.fee,Сумма не покрывает комиссию.
1 # Probably Decentralized localization table: Russian (ru)
145 bank.rent.k
146 bank.rent.v
147 bank.crc.k
bank.ops
148 poin.account.h
149 trade.h
150 web3.wallet.h
377 hw.swap
378 tab.wallets
379 hw.wallet.n
hw.err.poinbase
380 hw.review.own
381 hw.review.poinbase
382 poin.deposit
poin.out
poin.out.done
383 wallets.count
384 wallets.col.name
385 wallets.col.addr
915 nightlog.cra.lost
916 news.crawarn.desc
917 news.cralow.desc
918 poin.sub.funds
919 funds.receive
920 funds.send
921 funds.bank
922 funds.wallet
923 funds.to
924 funds.go
925 funds.sending
926 funds.confirm
927 funds.done
928 funds.done.void
929 funds.err.addr
930 funds.err.self
931 funds.err.known
932 funds.err.fee
+15 -4
View File
@@ -144,7 +144,6 @@ bank.cash.k,"信用点"
bank.rent.k,"房租"
bank.rent.v,"{0},{1} 天后支付"
bank.crc.k,"Poinbase 账户(CRC)"
bank.ops,"存取"
poin.account.h,"Poinbase 账户"
trade.h,"交易"
web3.wallet.h,"链上钱包"
@@ -377,12 +376,9 @@ hw.wait,等待钱包确认。
hw.swap,"兑换 {0} {1} → 约 {2} {3}"
tab.wallets,钱包
hw.wallet.n,"钱包 {0}"
hw.err.poinbase,Poinbase 仅支持充值 CRC 与 PSC。
hw.review.own,"自己的钱包:{0}"
hw.review.poinbase,Poinbase 充值地址
poin.deposit,"充值地址:{0}"
poin.out,"提到{0}"
poin.out.done,"{0} {1} 已提到{2}。"
wallets.count,"钱包 {0}/{1}"
wallets.col.name,名称
wallets.col.addr,地址
@@ -918,3 +914,18 @@ nightlog.cra.burned,销毁 {0} CRA:收回 {1} CRC、{2} SPARK({3})。
nightlog.cra.lost,官方没有回应:{0} CRA 的{1}单丢失。
news.crawarn.desc,有人在清点革命军的储备,质押的 CRA 恐怕兑付不了。解锁需要四天,有人说该动手了。
news.cralow.desc,储备覆盖率告急,革命军把 CRA 质押日息降到了原来的零头。
poin.sub.funds,资金
funds.receive,入金
funds.send,出金
funds.bank,银行账户
funds.wallet,钱包
funds.to,收款地址
funds.go,发送
funds.sending,正在转出 {0} {1} 到 {2}
funds.confirm,确认 {0}/{1}
funds.done,{0} {1} 已到账:{2}。
funds.done.void,已转出 {0} {1};该地址没有主人,币回不来了。
funds.err.addr,地址格式或校验位不对。
funds.err.self,这是 Poinbase 自己的充值地址。
funds.err.known,该地址只接受对应账单的付款。
funds.err.fee,数额不够付手续费。
1 # Probably Decentralized 本地化表:简体中文(zh)
144 bank.rent.k
145 bank.rent.v
146 bank.crc.k
bank.ops
147 poin.account.h
148 trade.h
149 web3.wallet.h
376 hw.swap
377 tab.wallets
378 hw.wallet.n
hw.err.poinbase
379 hw.review.own
380 hw.review.poinbase
381 poin.deposit
poin.out
poin.out.done
382 wallets.count
383 wallets.col.name
384 wallets.col.addr
914 nightlog.cra.lost
915 news.crawarn.desc
916 news.cralow.desc
917 poin.sub.funds
918 funds.receive
919 funds.send
920 funds.bank
921 funds.wallet
922 funds.to
923 funds.go
924 funds.sending
925 funds.confirm
926 funds.done
927 funds.done.void
928 funds.err.addr
929 funds.err.self
930 funds.err.known
931 funds.err.fee
+103 -49
View File
@@ -201,24 +201,10 @@ namespace Decentralized
{
var ps = PlayerStore.Instance;
var w = new[] { 180f, 220f };
Columns(b, l =>
{
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.Poinbase.Get(Assets.CRC)));
}, r =>
{
r.AddHeader(L.T("bank.ops"));
AmountRow(r);
AmlPreview(r);
r.AddSpace(6f);
r.AddButton(L.T("trade.deposit"), Deposit);
r.Last?.SetPreferredSize(RightW - 30f, 28f * F);
r.AddSpace(4f);
r.AddButton(L.T("trade.withdraw"), Withdraw);
r.Last?.SetPreferredSize(RightW - 30f, 28f * F);
});
b.AddHeader(L.T("entry.bank"));
TableRow(b, w, L.T("bank.cash.k"), ps.playerCash.ToString());
TableRow(b, w, L.T("bank.rent.k"), L.T("bank.rent.v", Session.Rent(), ps.GetRentDayCounter()));
TableRow(b, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Poinbase.Get(Assets.CRC)));
}
/// <summary>提取前的合规审查提示:仅保留账户污点比例(额度与命中概率按设计不公开)。</summary>
@@ -338,11 +324,11 @@ namespace Decentralized
{
any = true;
string asset = kv.Key;
bool selected = (_page == Page.Poinbase && asset == _poinAsset);
bool selected = (_page == Page.Poinbase && _poinTab == PoinTab.Funds && asset == _fundsAsset);
TableRow(b, HoldW.Sum() + 8f, HoldW, HoldAligns,
new[] { kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key) },
selected,
() => { if (_page == Page.Poinbase) { _poinAsset = asset; Open(); } });
() => { if (_page == Page.Poinbase && _poinTab == PoinTab.Funds) { _fundsAsset = asset; if (asset != Assets.CRC) _fundsBank = false; Open(); } });
}
if (!any) b.AddLabel(L.T(w == Session.Data.Poinbase ? "poin.empty" : "wallet.empty"), "hold_empty_dim");
foreach (var kv in w.Frozen.OrderBy(k => k.Key).Where(k => show(k.Key)))
@@ -350,8 +336,8 @@ namespace Decentralized
}
/// <summary>Poinbase:合规交易所。左边账户持仓,右边交易;信用点的存取在银行。</summary>
private enum PoinTab { Spot, Perp }
private static PoinTab _poinTab = PoinTab.Spot;
private enum PoinTab { Funds, Spot, Perp }
private static PoinTab _poinTab = PoinTab.Funds;
private static void ExchangePage(CustomUIBuilder b, Venue venue)
{
@@ -366,6 +352,7 @@ namespace Decentralized
}
b.End();
if (_poinTab == PoinTab.Perp) { PerpPage(b); return; }
if (_poinTab == PoinTab.Funds) { FundsPage(b); return; }
Columns(b, l =>
{
CandleChart.AddPicker(l, "poin", Assets.PSC, Open, _picked);
@@ -373,29 +360,108 @@ namespace Decentralized
l.AddHeader(L.T("poin.account.h"));
Holdings(l, w, a => true);
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
l.AddSeparator();
l.BeginRow(8f, TextAnchor.MiddleLeft);
l.AddLabel(L.T("poin.deposit", d.Address("poinbase")), "deposit_dim");
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"));
AmountRow(r);
TradeRows(r, venue);
r.AddSeparator();
r.BeginRow(4f);
foreach (var a in new[] { Assets.CRC, Assets.PSC })
{
var asset = a;
PledgerSkin.Pick(r, asset, asset == _poinAsset, () => { _poinAsset = asset; Open(); }, _picked);
}
r.End();
r.AddButton(L.T("poin.out", WalletWindow.NameOf(d.Hot)), PoinbaseOut);
});
}
private static string _poinAsset = Assets.CRC;
private enum FundsMode { Receive, Send }
private static FundsMode _fundsMode = FundsMode.Receive;
private static string _fundsAsset = Assets.CRC, _fundsTo = "";
private static bool _fundsBank = true;
/// <summary>资金页:入金和出金,先选币种。CRC 可以走银行账户或钱包,其他币只能走钱包。</summary>
private static void FundsPage(CustomUIBuilder b)
{
var d = Session.Data;
var w = d.Poinbase;
if (_fundsAsset != Assets.CRC) _fundsBank = false;
Columns(b, l =>
{
l.AddHeader(L.T("poin.account.h"));
Holdings(l, w, a => true);
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
}, r =>
{
r.BeginRow(4f);
foreach (FundsMode m in Enum.GetValues(typeof(FundsMode)))
{
var mode = m;
PledgerSkin.Pick(r, L.T("funds." + m.ToString().ToLowerInvariant()), mode == _fundsMode, () => { _fundsMode = mode; _message = null; Open(); }, _picked);
}
r.End();
r.BeginRow(4f);
foreach (var c in SwapCoins)
{
var coin = c;
PledgerSkin.Pick(r, coin, coin == _fundsAsset, () => { _fundsAsset = coin; if (coin != Assets.CRC) _fundsBank = false; Open(); }, _picked);
}
r.End();
if (_fundsAsset == Assets.CRC)
{
r.BeginRow(4f);
PledgerSkin.Pick(r, L.T("funds.bank"), _fundsBank, () => { _fundsBank = true; Open(); }, _picked);
PledgerSkin.Pick(r, L.T("funds.wallet"), !_fundsBank, () => { _fundsBank = false; Open(); }, _picked);
r.End();
}
r.AddSeparator();
if (_fundsMode == FundsMode.Receive)
{
if (_fundsBank)
{
AmountRow(r);
r.AddButton(L.T("trade.deposit"), Deposit);
}
else
{
r.AddLabel(L.T("poin.deposit", d.Address("poinbase")), "deposit_dim");
r.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(d.Address("poinbase")); _message = L.T("hw.copied.addr", d.Address("poinbase")); Open(); });
}
return;
}
if (_fundsBank)
{
AmountRow(r);
AmlPreview(r);
r.AddButton(L.T("trade.withdraw"), Withdraw);
return;
}
r.AddLabel(L.T("funds.to"));
r.BeginPanel(RightW - 30f, -1f, TextAnchor.MiddleCenter, 0f, 0f);
_clear.Add(r.Last.image);
r.AddInput("0x", _fundsTo, s => _fundsTo = s, "funds_to", s => _fundsTo = s);
r.End();
if (d.Wallets.Count > 0)
{
r.BeginRow(4f);
foreach (var ow in d.Wallets)
{
var own = ow;
PledgerSkin.Pick(r, WalletWindow.NameOf(own), ChainAddress.Same(_fundsTo, own.Address), () => { _fundsTo = own.Address; Open(); }, _picked);
}
r.End();
}
AmountRow(r);
r.AddButton(L.T("funds.go"), FundsSend);
foreach (var t in Funds.Active)
{
r.AddLabel(L.T("funds.sending", Fmt.Num(t.Amount), t.Asset, ChainAddress.Short(t.To)), "funds_sending_dim");
r.AddLabel(Funds.StatusText(t), "funds_status_" + t.Id);
r.AddProgressBar(Funds.Progress(t), "funds_prog_" + t.Id);
}
});
}
private static void FundsSend()
{
if (!ReadAmount(out double v)) return;
string err = Funds.Start(_fundsAsset, v, _fundsTo);
_message = err != null ? L.T(err) : null;
Open();
}
private static string _perpProduct = "PSC";
private static bool _perpLong = true;
@@ -1079,18 +1145,6 @@ namespace Decentralized
}
/// <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)
{
+3 -3
View File
@@ -329,7 +329,7 @@ namespace Decentralized
if (bill.Asset != dev.Asset) return L.T("hw.err.asset", bill.Asset);
if (v + 1e-9 < bill.Amount) return L.T("hw.err.short", Amt(bill.Amount), bill.Asset);
}
else if (IsPoinbase(to)) { if (dev.Asset != Assets.CRC && dev.Asset != Assets.PSC) return L.T("hw.err.poinbase"); }
else if (IsPoinbase(to)) { }
else if (Session.Data.Own(to) == null && Known(to)) return L.T("hw.err.nobill");
return null;
}
@@ -337,7 +337,7 @@ namespace Decentralized
private static Bill Match(string to) => Pending != null && !Pending.Contract && ChainAddress.Same(Pending.Address, to) ? Pending : null;
/// <summary>有过往来的地址(平台、商家、混币器、兑换处):没有账单时对方不收。</summary>
private static bool Known(string to)
internal static bool Known(string to)
{
var d = Session.Data;
return d.Addresses.Values.Any(a => ChainAddress.Same(a, to)) || d.Black.Sellers.Any(s => ChainAddress.Same(s.Name, to));
@@ -612,7 +612,7 @@ namespace Decentralized
instance = null;
}
private void Update() => Log.Guard("钱包动画", WalletWindow.Tick);
private void Update() { Log.Guard("钱包动画", WalletWindow.Tick); Log.Guard("出金动画", Funds.Tick); }
}
/// <summary>✓ 键上的按住计时:按满 1.2 秒签名,鼠标挪开或松手就重来。进度用游戏自带的按住圆环显示。</summary>