feat: add admin panel with multi-chain support and notification system

- Add full admin REST API: auth, API keys, chains, chain tokens, wallets,
  orders, RPC nodes, settings, dashboard stats, notifications
- Add JWT-based admin authentication and API key auth middleware
- Add multi-chain listeners: BSC, ETH, Polygon, Plasma, EVM WebSocket
- Add RPC node health check job with automatic failover
- Add Telegram notification channel for order events
- Add installer for first-run database initialization
- Add new DB models: admin_user, api_key, chain, chain_token,
  rpc_node, settings, notification_channel
- Add order statistics aggregation (daily/monthly/by-chain)
- Serve built admin SPA from embedded www/ assets
- Add comprehensive test coverage for all new features
This commit is contained in:
line-6000
2026-04-22 02:28:31 +08:00
parent 097c716714
commit 6bb47d4b00
247 changed files with 9933 additions and 1279 deletions
+33 -2
View File
@@ -27,7 +27,6 @@ func SetupTestDatabases(t testing.TB) func() {
viper.Set("callback_retry_base_seconds", 1)
viper.Set("queue_concurrency", 4)
viper.Set("queue_poll_interval_ms", 50)
viper.Set("api_auth_token", "test-token")
config.HTTPAccessLog = false
config.SQLDebug = false
@@ -38,12 +37,44 @@ func SetupTestDatabases(t testing.TB) func() {
mainDB := mustOpenSQLite(t, filepath.Join(t.TempDir(), "main.db"))
runtimeDB := mustOpenSQLite(t, filepath.Join(t.TempDir(), "runtime.db"))
mustMigrate(t, mainDB, &mdb.Orders{}, &mdb.WalletAddress{})
mustMigrate(t, mainDB,
&mdb.Orders{},
&mdb.WalletAddress{},
&mdb.ApiKey{},
&mdb.Setting{},
&mdb.NotificationChannel{},
&mdb.Chain{},
&mdb.ChainToken{},
&mdb.RpcNode{},
&mdb.AdminUser{},
)
mustMigrate(t, runtimeDB, &mdb.TransactionLock{})
dao.Mdb = mainDB
dao.RuntimeDB = runtimeDB
// Seed all standard chains as enabled so IsChainEnabled checks pass.
for _, network := range []string{
mdb.NetworkTron, mdb.NetworkSolana, mdb.NetworkEthereum,
mdb.NetworkBsc, mdb.NetworkPolygon, mdb.NetworkPlasma,
} {
mainDB.Create(&mdb.Chain{Network: network, Enabled: true})
}
// Seed two universal api_keys rows. Both usable for EPAY/GMPAY
// flows; the numeric PID 1001 row lets legacy tests that submit
// `pid=1001` still match.
mainDB.Create(&mdb.ApiKey{
Name: "test-default",
Pid: "test-token", SecretKey: "test-token",
Status: mdb.ApiKeyStatusEnable,
})
mainDB.Create(&mdb.ApiKey{
Name: "test-pid-1001",
Pid: "1001", SecretKey: "test-token",
Status: mdb.ApiKeyStatusEnable,
})
return func() {
closeDB(t, runtimeDB)
closeDB(t, mainDB)