@microcosmmoney/portal-react 3.13.1 → 3.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +13 -0
- package/dist/index.js +27 -1
- package/dist/main-portal/components/dashboard/EcosystemStatsCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/EcosystemStatsCard.js +37 -0
- package/dist/main-portal/components/dashboard/LockPeriodsCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/LockPeriodsCard.js +16 -0
- package/dist/main-portal/components/dashboard/MCCPriceChart.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MCCPriceChart.js +74 -0
- package/dist/main-portal/components/dashboard/MCCTokenStatsCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MCCTokenStatsCard.js +39 -0
- package/dist/main-portal/components/dashboard/MCDStatsCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MCDStatsCard.js +39 -0
- package/dist/main-portal/components/dashboard/MarketOverviewBar.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MarketOverviewBar.js +141 -0
- package/dist/main-portal/components/dashboard/MiningWeightCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MiningWeightCard.js +56 -0
- package/dist/main-portal/components/dashboard/MintingStatsCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MintingStatsCard.js +29 -0
- package/dist/main-portal/components/dashboard/MyAssetsSummary.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MyAssetsSummary.js +69 -0
- package/dist/main-portal/components/dashboard/MyMiningCard.d.ts +1 -0
- package/dist/main-portal/components/dashboard/MyMiningCard.js +46 -0
- package/dist/main-portal/components/dashboard/QuickActions.d.ts +1 -0
- package/dist/main-portal/components/dashboard/QuickActions.js +49 -0
- package/dist/main-portal/components/dashboard/UserDashboardPage.d.ts +1 -0
- package/dist/main-portal/components/dashboard/UserDashboardPage.js +36 -0
- package/dist/main-portal/components/mainnet/wave-text.d.ts +8 -0
- package/dist/main-portal/components/mainnet/wave-text.js +50 -0
- package/dist/main-portal/hooks/useMarketData.d.ts +9 -0
- package/dist/main-portal/hooks/useMarketData.js +32 -0
- package/dist/main-portal/hooks/usePriceHistory.d.ts +9 -0
- package/dist/main-portal/hooks/usePriceHistory.js +36 -0
- package/dist/main-portal/lib/api/dexscreener.d.ts +126 -0
- package/dist/main-portal/lib/api/dexscreener.js +139 -0
- package/dist/main-portal/lib/api/geckoterminal.d.ts +10 -0
- package/dist/main-portal/lib/api/geckoterminal.js +43 -0
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.default = MyAssetsSummary;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const WalletContext_1 = require("../../contexts/WalletContext");
|
|
8
|
+
const useMarketData_1 = require("../../hooks/useMarketData");
|
|
9
|
+
const api_1 = require("../../lib/api");
|
|
10
|
+
const blockchain_1 = require("../../lib/api/blockchain");
|
|
11
|
+
const navigation_1 = require("../../i18n/navigation");
|
|
12
|
+
const lucide_react_1 = require("lucide-react");
|
|
13
|
+
function MyAssetsSummary() {
|
|
14
|
+
const { mcdAmount, mcdTotalReceived, mcdTotalSpent, lockPeriods, userRank, nextRank, progressPercent, nextLevelRequirement, } = (0, WalletContext_1.useWallet)();
|
|
15
|
+
const { data: marketData } = (0, useMarketData_1.useMarketData)();
|
|
16
|
+
const [onChainMCC, setOnChainMCC] = (0, react_1.useState)(null);
|
|
17
|
+
const [mccLoading, setMccLoading] = (0, react_1.useState)(true);
|
|
18
|
+
const [walletCount, setWalletCount] = (0, react_1.useState)(0);
|
|
19
|
+
const loadOnChainMCC = (0, react_1.useCallback)(async () => {
|
|
20
|
+
setMccLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
const listRes = await (0, api_1.fetchApi)('/auth/wallet/list');
|
|
23
|
+
if (!listRes.success || !listRes.data?.wallets) {
|
|
24
|
+
setOnChainMCC(0);
|
|
25
|
+
setMccLoading(false);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const wallets = listRes.data.wallets;
|
|
29
|
+
setWalletCount(wallets.length);
|
|
30
|
+
if (wallets.length === 0) {
|
|
31
|
+
setOnChainMCC(0);
|
|
32
|
+
setMccLoading(false);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const results = await Promise.allSettled(wallets.map(w => (0, blockchain_1.getMCCBalance)(w.wallet_address)));
|
|
36
|
+
let total = 0;
|
|
37
|
+
for (const r of results) {
|
|
38
|
+
if (r.status === 'fulfilled' && r.value)
|
|
39
|
+
total += r.value.balance;
|
|
40
|
+
}
|
|
41
|
+
setOnChainMCC(total);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
setOnChainMCC(0);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setMccLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}, []);
|
|
50
|
+
(0, react_1.useEffect)(() => {
|
|
51
|
+
loadOnChainMCC();
|
|
52
|
+
}, [loadOnChainMCC]);
|
|
53
|
+
const mccDisplay = onChainMCC ?? 0;
|
|
54
|
+
const mccUsdValue = marketData?.price ? mccDisplay * marketData.price : 0;
|
|
55
|
+
const activeLocks = Array.isArray(lockPeriods) ? lockPeriods.filter((p) => p.status === 'locked') : [];
|
|
56
|
+
const lockedAmount = activeLocks.reduce((sum, l) => sum + (l.amount || 0), 0);
|
|
57
|
+
const getRankColor = (rank) => {
|
|
58
|
+
if (!rank)
|
|
59
|
+
return 'text-neutral-500';
|
|
60
|
+
const map = {
|
|
61
|
+
miner: 'text-cyan-300',
|
|
62
|
+
commander: 'text-white', pioneer: 'text-cyan-400', warden: 'text-cyan-300', admiral: 'text-cyan-300',
|
|
63
|
+
};
|
|
64
|
+
return map[rank.toLowerCase()] || 'text-neutral-400';
|
|
65
|
+
};
|
|
66
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2 sm:gap-3", children: [(0, jsx_runtime_1.jsx)(navigation_1.Link, { href: "/mcc/wallet", className: "block group", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-2.5 sm:p-4 hover:border-cyan-400/50 dash-card h-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { className: "w-3.5 h-3.5 text-neutral-400" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-[10px] font-mono tracking-wider", children: "MCC_BALANCE" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-base sm:text-2xl font-bold font-mono text-cyan-400", children: mccLoading
|
|
67
|
+
? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-5 h-5 animate-spin inline" })
|
|
68
|
+
: mccDisplay.toLocaleString('en-US', { minimumFractionDigits: 3, maximumFractionDigits: 3 }) }), mccUsdValue > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-500 font-mono mt-1", children: ["\u2248 $", mccUsdValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })] }))] }) }), (0, jsx_runtime_1.jsx)(navigation_1.Link, { href: "/mcc/mcd", className: "block group", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-2.5 sm:p-4 hover:border-cyan-400/50 dash-card h-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.TrendingUp, { className: "w-3.5 h-3.5 text-neutral-400" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-[10px] font-mono tracking-wider", children: "MCD_BALANCE" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-base sm:text-2xl font-bold font-mono text-white", children: mcdAmount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-[10px] text-neutral-500 font-mono mt-1", children: ["in: ", mcdTotalReceived.toLocaleString('en-US', { maximumFractionDigits: 0 }), " out: ", mcdTotalSpent.toLocaleString('en-US', { maximumFractionDigits: 0 })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-2.5 sm:p-4 hover:border-cyan-400/50 dash-card", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Lock, { className: "w-3.5 h-3.5 text-neutral-400" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-[10px] font-mono tracking-wider", children: "LOCKED" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-base sm:text-2xl font-bold font-mono text-white", children: lockedAmount.toLocaleString('en-US', { maximumFractionDigits: 0 }) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-[10px] text-neutral-500 font-mono mt-1", children: [activeLocks.length, " lock period", activeLocks.length !== 1 ? 's' : ''] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-2.5 sm:p-4 hover:border-cyan-400/50 dash-card", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Wallet, { className: "w-3.5 h-3.5 text-neutral-400" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-[10px] font-mono tracking-wider", children: "WALLETS" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-base sm:text-2xl font-bold font-mono text-white", children: walletCount })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-2.5 sm:p-4 hover:border-cyan-400/50 dash-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono tracking-wider mb-2", children: "RANK" }), (0, jsx_runtime_1.jsx)("div", { className: `text-lg font-bold font-mono ${getRankColor(userRank)}`, children: userRank || 'N/A' }), nextRank && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-800 rounded-full h-1.5", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-1.5 rounded-full transition-all", style: { width: `${Math.min(progressPercent, 100)}%` } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-[10px] text-neutral-500 font-mono mt-1", children: [nextLevelRequirement ? `${nextLevelRequirement.have}/${nextLevelRequirement.need} ${nextLevelRequirement.tier}` : `${progressPercent.toFixed(0)}%`, " \u2192 ", nextRank] })] }))] })] }));
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function MyMiningCard(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
'use client';
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.default = MyMiningCard;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const card_1 = require("../ui/card");
|
|
9
|
+
const api_1 = require("../../lib/api");
|
|
10
|
+
const lucide_react_1 = require("lucide-react");
|
|
11
|
+
const navigation_1 = require("../../i18n/navigation");
|
|
12
|
+
function MyMiningCard() {
|
|
13
|
+
const [stats, setStats] = (0, react_1.useState)(null);
|
|
14
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
15
|
+
const loadStats = (0, react_1.useCallback)(async () => {
|
|
16
|
+
try {
|
|
17
|
+
const json = await (0, api_1.fetchApi)('/mining/my-stats');
|
|
18
|
+
if (json.success && json.data) {
|
|
19
|
+
setStats(json.data);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// ignore
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
setLoading(false);
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
(0, react_1.useEffect)(() => { loadStats(); }, [loadStats]);
|
|
30
|
+
const fmt = (v) => v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
31
|
+
const formatDateTime = (iso) => {
|
|
32
|
+
if (!iso)
|
|
33
|
+
return '-';
|
|
34
|
+
const d = new Date(iso);
|
|
35
|
+
return d.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
|
36
|
+
};
|
|
37
|
+
const items = stats ? [
|
|
38
|
+
{ label: 'total_mined', value: fmt(stats.total_mined), icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Coins, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
39
|
+
{ label: 'total_paid', value: fmt(stats.total_paid), icon: (0, jsx_runtime_1.jsx)(lucide_react_1.DollarSign, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
40
|
+
{ label: 'mining_count', value: `${stats.mining_count}`, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Hash, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
41
|
+
{ label: 'last_30d', value: fmt(stats.last_30d_mined), icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
42
|
+
{ label: 'active_days', value: `${stats.active_days_30d}`, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Timer, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
43
|
+
{ label: 'last_mined', value: formatDateTime(stats.last_mined_at), icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Clock, { className: "w-3.5 h-3.5 text-cyan-400" }) },
|
|
44
|
+
] : [];
|
|
45
|
+
return ((0, jsx_runtime_1.jsx)(card_1.Card, { className: "bg-neutral-900 border-neutral-700 h-full hover:border-cyan-400/50 dash-card", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "p-3 sm:p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3 sm:mb-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Pickaxe, { className: "w-4 h-4 text-cyan-400" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-[10px] sm:text-xs font-mono tracking-wider", children: "MY_MINING" })] }), (0, jsx_runtime_1.jsxs)(navigation_1.Link, { href: "/mcc/mining", className: "flex items-center gap-1 text-xs text-neutral-500 hover:text-cyan-400 font-mono", children: ["details ", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 12 })] })] }), loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-5 h-5 animate-spin text-cyan-400" }) })) : !stats || stats.mining_count === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "no mining records" })) : ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 gap-2 sm:gap-3", children: items.map((s) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-2 sm:p-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-1", children: [s.icon, (0, jsx_runtime_1.jsx)("span", { className: "text-[9px] sm:text-[10px] text-neutral-400 font-mono tracking-wider", children: s.label })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-sm sm:text-xl font-bold font-mono text-white truncate", children: s.value })] }, s.label))) }))] }) }));
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function QuickActions(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
'use client';
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.default = QuickActions;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const lucide_react_1 = require("lucide-react");
|
|
8
|
+
const dexscreener_1 = require("../../lib/api/dexscreener");
|
|
9
|
+
const exchanges = [
|
|
10
|
+
{
|
|
11
|
+
label: 'OKX DEX',
|
|
12
|
+
href: dexscreener_1.OKX_DEX_URL,
|
|
13
|
+
icon: lucide_react_1.Repeat,
|
|
14
|
+
color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: 'Raydium',
|
|
18
|
+
href: dexscreener_1.RAYDIUM_POOL_URL,
|
|
19
|
+
icon: lucide_react_1.Droplets,
|
|
20
|
+
color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
label: 'Jupiter',
|
|
24
|
+
href: dexscreener_1.JUPITER_TRADE_URL,
|
|
25
|
+
icon: lucide_react_1.Repeat,
|
|
26
|
+
color: 'text-white border-neutral-700 hover:bg-neutral-800',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: 'BirdEye',
|
|
30
|
+
href: dexscreener_1.BIRDEYE_TOKEN_URL,
|
|
31
|
+
icon: lucide_react_1.Eye,
|
|
32
|
+
color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'GMGN',
|
|
36
|
+
href: dexscreener_1.GMGN_TOKEN_URL,
|
|
37
|
+
icon: lucide_react_1.BarChart3,
|
|
38
|
+
color: 'text-white border-neutral-700 hover:bg-neutral-800',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: 'DexScreener',
|
|
42
|
+
href: dexscreener_1.DEXSCREENER_URL,
|
|
43
|
+
icon: lucide_react_1.LineChart,
|
|
44
|
+
color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
function QuickActions() {
|
|
48
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "mb-3 sm:mb-6", children: (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-3 xs:grid-cols-3 sm:grid-cols-4 lg:grid-cols-6 gap-2 sm:gap-3", children: exchanges.map((ex) => ((0, jsx_runtime_1.jsx)("a", { href: ex.href, target: "_blank", rel: "noopener noreferrer", children: (0, jsx_runtime_1.jsxs)("div", { className: `bg-neutral-900 border ${ex.color} rounded-lg p-2.5 sm:p-4 flex items-center gap-2 sm:gap-3 cursor-pointer active:scale-[0.98] dash-card`, children: [(0, jsx_runtime_1.jsx)(ex.icon, { size: 16, className: "shrink-0 sm:w-5 sm:h-5" }), (0, jsx_runtime_1.jsx)("span", { className: "font-mono text-xs sm:text-sm font-bold tracking-wider truncate", children: ex.label })] }) }, ex.label))) }) }));
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function UserDashboardPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
'use client';
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.default = UserDashboardPage;
|
|
9
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
10
|
+
const WalletContext_1 = require("../../contexts/WalletContext");
|
|
11
|
+
const lucide_react_1 = require("lucide-react");
|
|
12
|
+
const card_1 = require("../ui/card");
|
|
13
|
+
const MarketOverviewBar_1 = __importDefault(require("./MarketOverviewBar"));
|
|
14
|
+
const QuickActions_1 = __importDefault(require("./QuickActions"));
|
|
15
|
+
const EcosystemStatsCard_1 = __importDefault(require("./EcosystemStatsCard"));
|
|
16
|
+
const MyAssetsSummary_1 = __importDefault(require("./MyAssetsSummary"));
|
|
17
|
+
const MCCPriceChart_1 = __importDefault(require("./MCCPriceChart"));
|
|
18
|
+
const MintingStatsCard_1 = __importDefault(require("./MintingStatsCard"));
|
|
19
|
+
const MiningWeightCard_1 = __importDefault(require("./MiningWeightCard"));
|
|
20
|
+
const LockPeriodsCard_1 = __importDefault(require("./LockPeriodsCard"));
|
|
21
|
+
const MyMiningCard_1 = __importDefault(require("./MyMiningCard"));
|
|
22
|
+
const MCCTokenStatsCard_1 = __importDefault(require("./MCCTokenStatsCard"));
|
|
23
|
+
const MCDStatsCard_1 = __importDefault(require("./MCDStatsCard"));
|
|
24
|
+
const wave_text_1 = require("../mainnet/wave-text");
|
|
25
|
+
const next_intl_1 = require("next-intl");
|
|
26
|
+
function UserDashboardPage() {
|
|
27
|
+
const t = (0, next_intl_1.useTranslations)('mccDashboard');
|
|
28
|
+
const { loading, error } = (0, WalletContext_1.useWallet)();
|
|
29
|
+
if (loading) {
|
|
30
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center min-h-[60vh] font-mono", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center space-y-4", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-8 h-8 animate-spin mx-auto text-cyan-400" }), (0, jsx_runtime_1.jsx)("div", { className: "text-neutral-500", children: "loading user_data..." })] }) }));
|
|
31
|
+
}
|
|
32
|
+
if (error) {
|
|
33
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center min-h-[60vh] font-mono", children: (0, jsx_runtime_1.jsx)(card_1.Card, { className: "bg-red-500/10 border-red-500/20", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-red-400 mb-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertTriangle, { className: "w-5 h-5" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: error })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-500 text-sm", children: t('refreshRetry') })] }) }) }));
|
|
34
|
+
}
|
|
35
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "max-w-7xl mx-auto font-mono px-3 py-4 space-y-3 xs:px-4 xs:space-y-4 sm:px-6 sm:py-6 sm:space-y-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-center", children: (0, jsx_runtime_1.jsx)(wave_text_1.WaveText, { text: "SHARED NETWORK \u00B7 SHARED FUTURE", className: "text-lg 2xs:text-xl xs:text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-[var(--font-bebas)] tracking-tight" }) }), (0, jsx_runtime_1.jsx)(MarketOverviewBar_1.default, {}), (0, jsx_runtime_1.jsx)(QuickActions_1.default, {}), (0, jsx_runtime_1.jsx)(MyAssetsSummary_1.default, {}), (0, jsx_runtime_1.jsx)(MCCPriceChart_1.default, {}), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-3 sm:gap-6", children: [(0, jsx_runtime_1.jsx)(MyMiningCard_1.default, {}), (0, jsx_runtime_1.jsx)(MiningWeightCard_1.default, {})] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-3 sm:gap-6", children: [(0, jsx_runtime_1.jsx)(MintingStatsCard_1.default, {}), (0, jsx_runtime_1.jsx)(EcosystemStatsCard_1.default, {})] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-3 sm:gap-6", children: [(0, jsx_runtime_1.jsx)(MCCTokenStatsCard_1.default, {}), (0, jsx_runtime_1.jsx)(MCDStatsCard_1.default, {})] }), (0, jsx_runtime_1.jsx)(LockPeriodsCard_1.default, {}), (0, jsx_runtime_1.jsxs)("div", { className: "text-center py-4 space-y-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-cyan-400/60 font-mono", children: "Data refreshes every 4 hours \u00B7 For real-time data, please check on-chain directly" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-cyan-400/60 font-mono", children: "\u6570\u636E\u6BCF 4 \u5C0F\u65F6\u66F4\u65B0 \u00B7 \u5373\u65F6\u6570\u636E\u8BF7\u76F4\u63A5\u67E5\u8BE2\u94FE\u4E0A" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-cyan-400/60 font-mono", children: "\u30C7\u30FC\u30BF\u306F4\u6642\u9593\u3054\u3068\u306B\u66F4\u65B0 \u00B7 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30C7\u30FC\u30BF\u306F\u30AA\u30F3\u30C1\u30A7\u30FC\u30F3\u3067\u78BA\u8A8D" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-cyan-400/60 font-mono", children: "\uB370\uC774\uD130\uB294 4\uC2DC\uAC04\uB9C8\uB2E4 \uAC31\uC2E0 \u00B7 \uC2E4\uC2DC\uAC04 \uB370\uC774\uD130\uB294 \uC628\uCCB4\uC778\uC5D0\uC11C \uD655\uC778" })] })] }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface WaveTextProps {
|
|
2
|
+
text?: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
color?: "cyan" | "red" | "gold" | "green";
|
|
5
|
+
delay?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function WaveText({ text, className, color, delay }: WaveTextProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
"use client";
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.WaveText = WaveText;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const framer_motion_1 = require("framer-motion");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
function WaveText({ text = "", className = "", color = "cyan", delay = 0.1 }) {
|
|
10
|
+
const [characters, setCharacters] = (0, react_1.useState)([]);
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
if (text) {
|
|
13
|
+
setCharacters(Array.from(text));
|
|
14
|
+
}
|
|
15
|
+
}, [text]);
|
|
16
|
+
if (!characters.length)
|
|
17
|
+
return null;
|
|
18
|
+
const colorMap = {
|
|
19
|
+
cyan: {
|
|
20
|
+
gradient: "linear-gradient(180deg, #67e8f9 0%, #22d3ee 100%)",
|
|
21
|
+
shadow: "0 0 20px rgba(34, 211, 238, 0.3)",
|
|
22
|
+
},
|
|
23
|
+
red: {
|
|
24
|
+
gradient: "linear-gradient(180deg, #dc2626 0%, #991b1b 100%)",
|
|
25
|
+
shadow: "0 0 20px rgba(220, 38, 38, 0.3)",
|
|
26
|
+
},
|
|
27
|
+
gold: {
|
|
28
|
+
gradient: "linear-gradient(180deg, #fbbf24 0%, #f59e0b 100%)",
|
|
29
|
+
shadow: "0 0 20px rgba(245, 158, 11, 0.3)",
|
|
30
|
+
},
|
|
31
|
+
green: {
|
|
32
|
+
gradient: "linear-gradient(180deg, #34d399 0%, #10b981 100%)",
|
|
33
|
+
shadow: "0 0 20px rgba(16, 185, 129, 0.3)",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const colors = colorMap[color];
|
|
37
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: `inline-flex flex-wrap gap-[1px] ${className}`, children: characters.map((char, index) => ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { className: "relative inline-block font-semibold text-transparent bg-clip-text", style: {
|
|
38
|
+
background: colors.gradient,
|
|
39
|
+
WebkitBackgroundClip: "text",
|
|
40
|
+
textShadow: colors.shadow,
|
|
41
|
+
}, animate: {
|
|
42
|
+
y: [0, -4, 0],
|
|
43
|
+
opacity: [0.5, 1, 0.5],
|
|
44
|
+
}, transition: {
|
|
45
|
+
duration: 2,
|
|
46
|
+
ease: "easeInOut",
|
|
47
|
+
repeat: Infinity,
|
|
48
|
+
delay: index * delay,
|
|
49
|
+
}, children: char === " " ? "\u00A0" : char }, `${char}-${index}`))) }));
|
|
50
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type MCCMarketData } from '../lib/api/dexscreener';
|
|
2
|
+
interface UseMarketDataReturn {
|
|
3
|
+
data: MCCMarketData | null;
|
|
4
|
+
loading: boolean;
|
|
5
|
+
error: string | null;
|
|
6
|
+
refresh: () => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function useMarketData(): UseMarketDataReturn;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
'use client';
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.useMarketData = useMarketData;
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const dexscreener_1 = require("../lib/api/dexscreener");
|
|
8
|
+
function useMarketData() {
|
|
9
|
+
const [data, setData] = (0, react_1.useState)(null);
|
|
10
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
11
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
12
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
13
|
+
try {
|
|
14
|
+
setError(null);
|
|
15
|
+
const marketData = await (0, dexscreener_1.fetchMCCMarketData)();
|
|
16
|
+
if (marketData) {
|
|
17
|
+
setData(marketData);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
setError(String(err));
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
(0, react_1.useEffect)(() => {
|
|
28
|
+
// 非即时数据: 页面加载读一次缓存, 不轮询 (后端 scheduler 每4h刷新)
|
|
29
|
+
refresh();
|
|
30
|
+
}, [refresh]);
|
|
31
|
+
return { data, loading, error, refresh };
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { OHLCVData, PriceTimeRange } from '../lib/api/geckoterminal';
|
|
2
|
+
interface UsePriceHistoryReturn {
|
|
3
|
+
data: OHLCVData[] | null;
|
|
4
|
+
loading: boolean;
|
|
5
|
+
error: string | null;
|
|
6
|
+
refresh: () => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function usePriceHistory(range?: PriceTimeRange): UsePriceHistoryReturn;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// AI-generated · AI-managed · AI-maintained
|
|
3
|
+
'use client';
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.usePriceHistory = usePriceHistory;
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
function usePriceHistory(range = '7D') {
|
|
8
|
+
const [data, setData] = (0, react_1.useState)(null);
|
|
9
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
10
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
11
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
12
|
+
try {
|
|
13
|
+
setError(null);
|
|
14
|
+
const response = await fetch(`/api/stats/price-history?range=${range}`);
|
|
15
|
+
const result = await response.json();
|
|
16
|
+
if (result.success && result.data) {
|
|
17
|
+
setData(result.data);
|
|
18
|
+
}
|
|
19
|
+
else if (result.error) {
|
|
20
|
+
setError(result.error);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
setError(String(err));
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
}, [range]);
|
|
30
|
+
(0, react_1.useEffect)(() => {
|
|
31
|
+
setLoading(true);
|
|
32
|
+
// 非即时数据: 页面加载读一次缓存, 不轮询 (后端 scheduler 每4h刷新)
|
|
33
|
+
refresh();
|
|
34
|
+
}, [refresh]);
|
|
35
|
+
return { data, loading, error, refresh };
|
|
36
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export interface HourlyVolume {
|
|
2
|
+
hour: string;
|
|
3
|
+
buyVolume: number;
|
|
4
|
+
sellVolume: number;
|
|
5
|
+
totalVolume: number;
|
|
6
|
+
tradeCount: number;
|
|
7
|
+
}
|
|
8
|
+
export interface HeatmapCell {
|
|
9
|
+
dow: number;
|
|
10
|
+
hour: number;
|
|
11
|
+
volume: number;
|
|
12
|
+
tradeCount: number;
|
|
13
|
+
}
|
|
14
|
+
export interface MCCMarketData {
|
|
15
|
+
price: number;
|
|
16
|
+
priceChange: {
|
|
17
|
+
h1: number;
|
|
18
|
+
h24: number;
|
|
19
|
+
};
|
|
20
|
+
volume: {
|
|
21
|
+
h1: number;
|
|
22
|
+
h24: number;
|
|
23
|
+
};
|
|
24
|
+
txns: {
|
|
25
|
+
h1: {
|
|
26
|
+
buys: number;
|
|
27
|
+
sells: number;
|
|
28
|
+
};
|
|
29
|
+
h24: {
|
|
30
|
+
buys: number;
|
|
31
|
+
sells: number;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
liquidityUsd: number;
|
|
35
|
+
fdvUsd: number;
|
|
36
|
+
marketCapUsd: number;
|
|
37
|
+
dailyStats: {
|
|
38
|
+
tradeCount: number;
|
|
39
|
+
miningCount: number;
|
|
40
|
+
marketMakingCount: number;
|
|
41
|
+
buyVolume: number;
|
|
42
|
+
sellVolume: number;
|
|
43
|
+
};
|
|
44
|
+
hourlyVolumes: HourlyVolume[];
|
|
45
|
+
weeklyHeatmap: HeatmapCell[];
|
|
46
|
+
updatedAt: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function fetchMCCMarketData(): Promise<MCCMarketData | null>;
|
|
49
|
+
export interface CustodyVaultInfo {
|
|
50
|
+
index: number;
|
|
51
|
+
vaultPda: string;
|
|
52
|
+
gasPayer: string;
|
|
53
|
+
usdcBalance: number;
|
|
54
|
+
mccBalance: number;
|
|
55
|
+
gasPayerSol: number;
|
|
56
|
+
gasConsumed: number;
|
|
57
|
+
txCount24h: number;
|
|
58
|
+
status: "active" | "idle";
|
|
59
|
+
}
|
|
60
|
+
export interface CustodyVaultSummary {
|
|
61
|
+
totalUsdc: number;
|
|
62
|
+
totalMcc: number;
|
|
63
|
+
totalGasConsumed: number;
|
|
64
|
+
totalTx24h: number;
|
|
65
|
+
totalTrades24h: number;
|
|
66
|
+
activeVaults: number;
|
|
67
|
+
avgGasPerTx: number;
|
|
68
|
+
totalProfit: number;
|
|
69
|
+
}
|
|
70
|
+
export interface CustodyAgentRoles {
|
|
71
|
+
minerActive: boolean;
|
|
72
|
+
traderActive: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface EcosystemMining {
|
|
75
|
+
total_usd: number;
|
|
76
|
+
total_mcc: number;
|
|
77
|
+
total_count: number;
|
|
78
|
+
}
|
|
79
|
+
export interface EcosystemBuyback {
|
|
80
|
+
total_usd: number;
|
|
81
|
+
total_mcc: number;
|
|
82
|
+
total_count: number;
|
|
83
|
+
pool_usd_balance: number;
|
|
84
|
+
}
|
|
85
|
+
export interface EcosystemLp {
|
|
86
|
+
mcc_allocated: number;
|
|
87
|
+
usdc_balance: number;
|
|
88
|
+
}
|
|
89
|
+
export interface EcosystemEpoch {
|
|
90
|
+
current_epoch: number;
|
|
91
|
+
epoch_minted: number;
|
|
92
|
+
epoch_yield: number;
|
|
93
|
+
mining_vault_mcc: number;
|
|
94
|
+
}
|
|
95
|
+
export interface CustodyVaultData {
|
|
96
|
+
vaults: CustodyVaultInfo[];
|
|
97
|
+
summary: CustodyVaultSummary;
|
|
98
|
+
agentRoles: CustodyAgentRoles;
|
|
99
|
+
mining: EcosystemMining;
|
|
100
|
+
buyback: EcosystemBuyback;
|
|
101
|
+
lp: EcosystemLp;
|
|
102
|
+
epoch: EcosystemEpoch;
|
|
103
|
+
updatedAt: string;
|
|
104
|
+
}
|
|
105
|
+
export declare function fetchCustodyVaultData(): Promise<CustodyVaultData | null>;
|
|
106
|
+
export declare const SOLSCAN_LINKS: {
|
|
107
|
+
mccToken: string;
|
|
108
|
+
mcdToken: string;
|
|
109
|
+
miningVault: string;
|
|
110
|
+
buybackVault: string;
|
|
111
|
+
teamVault: string;
|
|
112
|
+
poolPda: string;
|
|
113
|
+
cpmmPool: string;
|
|
114
|
+
custodyProgram: string;
|
|
115
|
+
programId: string;
|
|
116
|
+
transaction: (sig: string) => string;
|
|
117
|
+
account: (address: string) => string;
|
|
118
|
+
};
|
|
119
|
+
/** Official Market Making Custody Vault PDAs (#0-#9) */
|
|
120
|
+
export declare const CUSTODY_VAULT_ADDRESSES: readonly ["8GgSjyrnXfxzF9A2ptTVbwr5x7HbApBZAiNfLtasZymG", "GPGfHSzEMQG1w5fCGXoM4Qyq4AJKe2jEoE5Bp7FTEvvv", "Ay6nzAC1iNqNtBDqkWvjfkZRVJaw61v4tkNKs1h5QEsx", "8H4N2rT9JT3xxxVqFRiSECHY9dcbU51KjxsEfsBJSr5N", "8TzH83qkXUn2uifjVSFsfaBzpKvpf2h1FnKkP6gx33xo", "AkCWQ1Cgef3kD33YZN6RcbNdcG2uzGPqTm298DsRpEBh", "2ts8u1L21vZsJRHmB9SvGYw715bRp9wfM9gj9P8VZhah", "FtuVwEijmLiKLFriSQaQ5mQVexHpDEjGYojiCaXzNhrp", "HJiPgHoWrjmV8cguayJu6ggaBa2Kue5cbcdnt3T3eKbe", "2H1uXk3wwrhkxssKj5dKSK8cUVq5BxeLAvgfF2CweVoc"];
|
|
121
|
+
export declare const RAYDIUM_POOL_URL = "https://raydium.io/swap/?inputMint=MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb&outputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
122
|
+
export declare const JUPITER_TRADE_URL = "https://jup.ag/tokens/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
123
|
+
export declare const BIRDEYE_TOKEN_URL = "https://birdeye.so/token/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb?chain=solana";
|
|
124
|
+
export declare const GMGN_TOKEN_URL = "https://gmgn.ai/sol/token/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
125
|
+
export declare const OKX_DEX_URL = "https://web3.okx.com/zh-hans/token/solana/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
126
|
+
export declare const DEXSCREENER_URL = "https://dexscreener.com/solana/4AiaTd9bAWf3u8ScZWhXadJF1roc8bJKEKvaDudKacZd";
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEXSCREENER_URL = exports.OKX_DEX_URL = exports.GMGN_TOKEN_URL = exports.BIRDEYE_TOKEN_URL = exports.JUPITER_TRADE_URL = exports.RAYDIUM_POOL_URL = exports.CUSTODY_VAULT_ADDRESSES = exports.SOLSCAN_LINKS = void 0;
|
|
4
|
+
exports.fetchMCCMarketData = fetchMCCMarketData;
|
|
5
|
+
exports.fetchCustodyVaultData = fetchCustodyVaultData;
|
|
6
|
+
async function fetchMCCMarketData() {
|
|
7
|
+
try {
|
|
8
|
+
const response = await fetch('/api/stats/market');
|
|
9
|
+
if (!response.ok)
|
|
10
|
+
return null;
|
|
11
|
+
const json = await response.json();
|
|
12
|
+
if (!json.success || !json.data)
|
|
13
|
+
return null;
|
|
14
|
+
const d = json.data;
|
|
15
|
+
return {
|
|
16
|
+
price: d.price || 0,
|
|
17
|
+
priceChange: {
|
|
18
|
+
h1: d.price_change_h1 || 0,
|
|
19
|
+
h24: d.price_change_24h || 0,
|
|
20
|
+
},
|
|
21
|
+
volume: {
|
|
22
|
+
h1: d.volume?.h1 || 0,
|
|
23
|
+
h24: d.volume?.h24 || 0,
|
|
24
|
+
},
|
|
25
|
+
txns: {
|
|
26
|
+
h1: d.txns?.h1 || { buys: 0, sells: 0 },
|
|
27
|
+
h24: d.txns?.h24 || { buys: 0, sells: 0 },
|
|
28
|
+
},
|
|
29
|
+
liquidityUsd: d.liquidity_usd || 0,
|
|
30
|
+
fdvUsd: d.fdv_usd || 0,
|
|
31
|
+
marketCapUsd: d.market_cap_usd || 0,
|
|
32
|
+
dailyStats: {
|
|
33
|
+
tradeCount: d.daily_stats?.trade_count || 0,
|
|
34
|
+
miningCount: d.daily_stats?.mining_count || 0,
|
|
35
|
+
marketMakingCount: d.daily_stats?.buyback_count || 0,
|
|
36
|
+
buyVolume: d.daily_stats?.buy_volume || 0,
|
|
37
|
+
sellVolume: d.daily_stats?.sell_volume || 0,
|
|
38
|
+
},
|
|
39
|
+
hourlyVolumes: (d.hourly_volumes || []).map((h) => ({
|
|
40
|
+
hour: h.hour,
|
|
41
|
+
buyVolume: h.buy_volume || 0,
|
|
42
|
+
sellVolume: h.sell_volume || 0,
|
|
43
|
+
totalVolume: h.total_volume || 0,
|
|
44
|
+
tradeCount: h.trade_count || 0,
|
|
45
|
+
})),
|
|
46
|
+
weeklyHeatmap: (d.weekly_heatmap || []).map((h) => ({
|
|
47
|
+
dow: h.dow || 1,
|
|
48
|
+
hour: h.hour || 0,
|
|
49
|
+
volume: h.volume || 0,
|
|
50
|
+
tradeCount: h.trade_count || 0,
|
|
51
|
+
})),
|
|
52
|
+
updatedAt: d.updated_at || '',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('Failed to fetch MCC market data:', error);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function fetchCustodyVaultData() {
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch('/api/stats/custody-vaults');
|
|
63
|
+
if (!response.ok)
|
|
64
|
+
return null;
|
|
65
|
+
const json = await response.json();
|
|
66
|
+
if (!json.success || !json.data)
|
|
67
|
+
return null;
|
|
68
|
+
const d = json.data;
|
|
69
|
+
return {
|
|
70
|
+
vaults: (d.vaults || []).map((v) => ({
|
|
71
|
+
index: v.index || 0,
|
|
72
|
+
vaultPda: v.vault_pda || "",
|
|
73
|
+
gasPayer: v.gas_payer || "",
|
|
74
|
+
usdcBalance: v.usdc_balance || 0,
|
|
75
|
+
mccBalance: v.mcc_balance || 0,
|
|
76
|
+
gasPayerSol: v.gas_payer_sol || 0,
|
|
77
|
+
gasConsumed: v.gas_consumed || 0,
|
|
78
|
+
txCount24h: v.tx_count_24h || 0,
|
|
79
|
+
status: v.status === "active" ? "active" : "idle",
|
|
80
|
+
})),
|
|
81
|
+
summary: {
|
|
82
|
+
totalUsdc: d.summary?.total_usdc || 0,
|
|
83
|
+
totalMcc: d.summary?.total_mcc || 0,
|
|
84
|
+
totalGasConsumed: d.summary?.total_gas_consumed || 0,
|
|
85
|
+
totalTx24h: d.summary?.total_tx_24h || 0,
|
|
86
|
+
totalTrades24h: d.summary?.total_trades_24h || 0,
|
|
87
|
+
activeVaults: d.summary?.active_vaults || 0,
|
|
88
|
+
avgGasPerTx: d.summary?.avg_gas_per_tx || 0,
|
|
89
|
+
totalProfit: d.summary?.total_profit || 0,
|
|
90
|
+
},
|
|
91
|
+
agentRoles: {
|
|
92
|
+
minerActive: !!d.agent_roles?.miner_active,
|
|
93
|
+
traderActive: !!d.agent_roles?.trader_active,
|
|
94
|
+
},
|
|
95
|
+
mining: d.mining || { total_usd: 0, total_mcc: 0, total_count: 0 },
|
|
96
|
+
buyback: d.buyback || { total_usd: 0, total_mcc: 0, total_count: 0, pool_usd_balance: 0 },
|
|
97
|
+
lp: d.lp || { mcc_allocated: 0, usdc_balance: 0 },
|
|
98
|
+
epoch: d.epoch || { current_epoch: 0, epoch_minted: 0, epoch_yield: 0, mining_vault_mcc: 0 },
|
|
99
|
+
updatedAt: d.updated_at || '',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('Failed to fetch custody vault data:', error);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ── Solscan Links ──
|
|
108
|
+
exports.SOLSCAN_LINKS = {
|
|
109
|
+
mccToken: "https://solscan.io/token/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb",
|
|
110
|
+
mcdToken: "https://solscan.io/token/MCDAhpfpKrsvXd1i95jToVd5SRL2xrZbeEriBbBJAn2",
|
|
111
|
+
miningVault: "https://solscan.io/account/63CtMuLQTjTRctGXKEEzHu2zFWh9pbckbMDd3sqb8p3H",
|
|
112
|
+
buybackVault: "https://solscan.io/account/C4NDtuAVkGaLyGdJNARfvguHFFuKpDf8XPGkYb6QV1Ha",
|
|
113
|
+
teamVault: "https://solscan.io/account/TEA5FQrMTkmHoYCGpYfA2973xeXJ3UXHUe12oHdYoYb",
|
|
114
|
+
poolPda: "https://solscan.io/account/GSBWtaX9WcBh8jUcmbXtQ1afQPHKSUKvsTxkqpJU3G9S",
|
|
115
|
+
cpmmPool: "https://solscan.io/account/4AiaTd9bAWf3u8ScZWhXadJF1roc8bJKEKvaDudKacZd",
|
|
116
|
+
custodyProgram: "https://solscan.io/account/CUS3ZFhcYqAj95ZTbjYu1yMT8DLdAQo8kTYova4NJJtr",
|
|
117
|
+
programId: "https://solscan.io/account/REDEh89TzpwCtoWQuuNPtxskrVoUDQgowR7e7sZpWj9",
|
|
118
|
+
transaction: (sig) => `https://solscan.io/tx/${sig}`,
|
|
119
|
+
account: (address) => `https://solscan.io/account/${address}`,
|
|
120
|
+
};
|
|
121
|
+
/** Official Market Making Custody Vault PDAs (#0-#9) */
|
|
122
|
+
exports.CUSTODY_VAULT_ADDRESSES = [
|
|
123
|
+
"8GgSjyrnXfxzF9A2ptTVbwr5x7HbApBZAiNfLtasZymG",
|
|
124
|
+
"GPGfHSzEMQG1w5fCGXoM4Qyq4AJKe2jEoE5Bp7FTEvvv",
|
|
125
|
+
"Ay6nzAC1iNqNtBDqkWvjfkZRVJaw61v4tkNKs1h5QEsx",
|
|
126
|
+
"8H4N2rT9JT3xxxVqFRiSECHY9dcbU51KjxsEfsBJSr5N",
|
|
127
|
+
"8TzH83qkXUn2uifjVSFsfaBzpKvpf2h1FnKkP6gx33xo",
|
|
128
|
+
"AkCWQ1Cgef3kD33YZN6RcbNdcG2uzGPqTm298DsRpEBh",
|
|
129
|
+
"2ts8u1L21vZsJRHmB9SvGYw715bRp9wfM9gj9P8VZhah",
|
|
130
|
+
"FtuVwEijmLiKLFriSQaQ5mQVexHpDEjGYojiCaXzNhrp",
|
|
131
|
+
"HJiPgHoWrjmV8cguayJu6ggaBa2Kue5cbcdnt3T3eKbe",
|
|
132
|
+
"2H1uXk3wwrhkxssKj5dKSK8cUVq5BxeLAvgfF2CweVoc",
|
|
133
|
+
];
|
|
134
|
+
exports.RAYDIUM_POOL_URL = "https://raydium.io/swap/?inputMint=MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb&outputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
135
|
+
exports.JUPITER_TRADE_URL = "https://jup.ag/tokens/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
136
|
+
exports.BIRDEYE_TOKEN_URL = "https://birdeye.so/token/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb?chain=solana";
|
|
137
|
+
exports.GMGN_TOKEN_URL = "https://gmgn.ai/sol/token/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
138
|
+
exports.OKX_DEX_URL = "https://web3.okx.com/zh-hans/token/solana/MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb";
|
|
139
|
+
exports.DEXSCREENER_URL = "https://dexscreener.com/solana/4AiaTd9bAWf3u8ScZWhXadJF1roc8bJKEKvaDudKacZd";
|