feat: cream terminal redesign, English-only UI, autopilot launch fixes

- Redesign dashboard into a cream-paper + vermilion IBM Plex Mono terminal
  (live L2 order book, cost/liq map, WS K-line, signal matrix, orchestration
  topology, risk radar, execution log, current positions, equity curve)
- Convert all user-facing UI and backend strings/prompts from Chinese to
  English (multi-language retained, default English)
- Add /api/statistics/full endpoint + full-stats frontend wiring
- Fix Autopilot launch: reuse the existing trader instead of creating
  duplicates (eliminates repeat ~35s create cost and stale-trader 404s);
  launch sends 5m scan interval
- Fix unreadable toasts: cream theme with high-contrast text + per-type accent
- Silence background dashboard polls (getTraderConfig) to stop error-toast spam
This commit is contained in:
tinkle-community
2026-06-30 16:03:52 +08:00
parent eba28bcf0e
commit 110bf52908
149 changed files with 6835 additions and 3611 deletions

View File

@@ -1,10 +1,10 @@
export interface EncryptedPayload {
wrappedKey: string // RSA-OAEP(K)
iv: string // 12 bytes
ciphertext: string // AES-GCM 输出(含 tag)
aad?: string // 可选:额外认证数据
kid?: string // 可选:服务端公钥标识
ts?: number // 可选unix 秒,用于重放保护
ciphertext: string // AES-GCM output (includes tag)
aad?: string // optional: additional authenticated data
kid?: string // optional: server public key identifier
ts?: number // optional: unix seconds, used for replay protection
}
export interface CryptoConfig {
@@ -64,7 +64,7 @@ export class CryptoService {
const pemContents = pem
.substring(headerIndex + pemHeader.length, footerIndex)
.replace(/\s+/g, '') // 移除所有空白字符(包括换行符、空格等)
.replace(/\s+/g, '') // Remove all whitespace (including newlines, spaces, etc.)
const binaryDerString = atob(pemContents)
const binaryDer = new Uint8Array(binaryDerString.length)
@@ -95,7 +95,7 @@ export class CryptoService {
)
}
// 1. 生成 256-bit AES 密钥
// 1. Generate a 256-bit AES key
const aesKey = await crypto.subtle.generateKey(
{
name: 'AES-GCM',
@@ -105,10 +105,10 @@ export class CryptoService {
['encrypt']
)
// 2. 生成 12 字节随机 IV
// 2. Generate a random 12-byte IV
const iv = crypto.getRandomValues(new Uint8Array(12))
// 3. 准备 AAD (额外认证数据)
// 3. Prepare AAD (additional authenticated data)
const ts = Math.floor(Date.now() / 1000)
const aadObject = {
userId: userId || '',
@@ -119,7 +119,7 @@ export class CryptoService {
const aadString = JSON.stringify(aadObject)
const aadBytes = new TextEncoder().encode(aadString)
// 4. 使用 AES-GCM 加密数据
// 4. Encrypt the data with AES-GCM
const plaintextBytes = new TextEncoder().encode(plaintext)
const ciphertext = await crypto.subtle.encrypt(
{
@@ -132,10 +132,10 @@ export class CryptoService {
plaintextBytes
)
// 5. 导出 AES 密钥
// 5. Export the AES key
const rawAesKey = await crypto.subtle.exportKey('raw', aesKey)
// 6. 使用 RSA-OAEP 加密 AES 密钥
// 6. Encrypt the AES key with RSA-OAEP
const wrappedKey = await crypto.subtle.encrypt(
{
name: 'RSA-OAEP',
@@ -144,7 +144,7 @@ export class CryptoService {
rawAesKey
)
// 7. 编码为 base64url
// 7. Encode as base64url
return {
wrappedKey: this.arrayBufferToBase64Url(wrappedKey),
iv: this.arrayBufferToBase64Url(iv.buffer),
@@ -187,7 +187,7 @@ export class CryptoService {
// anti-pattern (it implied an unauthenticated decryption oracle existed).
}
// 生成混淆字符串(用于剪贴板混淆)
// Generate an obfuscation string (used for clipboard obfuscation)
export function generateObfuscation(): string {
const bytes = new Uint8Array(32)
crypto.getRandomValues(bytes)
@@ -196,7 +196,7 @@ export function generateObfuscation(): string {
)
}
// 验证私钥格式
// Validate private key format
export function validatePrivateKeyFormat(
value: string,
expectedLength: number = 64