@microcosmmoney/portal-react 2.1.1 → 2.2.1

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.
@@ -6,40 +6,34 @@ exports.MicrocosmAssetsSummary = MicrocosmAssetsSummary;
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const auth_react_1 = require("@microcosmmoney/auth-react");
8
8
  const RANK_COLOR = {
9
- Recruit: 'text-neutral-500',
10
- Prospect: 'text-neutral-400',
11
- Miner: 'text-cyan-300',
12
- Commander: 'text-white',
13
- Pioneer: 'text-cyan-400',
14
- Warden: 'text-cyan-300',
15
- Admiral: 'text-cyan-300',
16
- };
17
- const RANK_BG = {
18
- Recruit: 'bg-neutral-800',
19
- Prospect: 'bg-neutral-800',
20
- Miner: 'bg-cyan-950/50',
21
- Commander: 'bg-white/10',
22
- Pioneer: 'bg-cyan-950/50',
23
- Warden: 'bg-cyan-950/50',
24
- Admiral: 'bg-cyan-950/50',
9
+ recruit: 'text-neutral-500', prospect: 'text-neutral-400', miner: 'text-cyan-300',
10
+ commander: 'text-white', pioneer: 'text-cyan-400', warden: 'text-cyan-300', admiral: 'text-cyan-300',
25
11
  };
26
12
  function MicrocosmAssetsSummary({ basePath = '', onNavigate }) {
27
13
  const { balance: mccData, loading: mccLoading } = (0, auth_react_1.useMCC)(120000);
28
14
  const { balance: mcdData, loading: mcdLoading } = (0, auth_react_1.useMCD)(120000);
29
15
  const { data: levelData } = (0, auth_react_1.useUserLevel)();
16
+ const { data: wallets } = (0, auth_react_1.useWallets)();
17
+ const { data: locks } = (0, auth_react_1.useMCCLocks)();
18
+ const { data: marketData } = (0, auth_react_1.useMarketData)();
30
19
  const resolvePath = (p) => basePath ? `${basePath.replace(/\/$/, '')}${p}` : p;
31
20
  const mccBalance = mccData?.balance ?? 0;
21
+ const mccPrice = marketData?.price_usd ?? 0;
22
+ const mccUsdValue = mccPrice > 0 ? mccBalance * mccPrice : 0;
32
23
  const mcdAmount = parseFloat(mcdData?.available_balance ?? '0');
33
24
  const mcdReceived = parseFloat(mcdData?.total_balance ?? '0');
34
25
  const mcdSpent = parseFloat(mcdData?.frozen_balance ?? '0');
26
+ const walletCount = Array.isArray(wallets) ? wallets.length : 0;
27
+ const activeLocks = Array.isArray(locks) ? locks.filter((l) => l.status === 'locked') : [];
28
+ const lockedAmount = activeLocks.reduce((sum, l) => sum + (l.amount || 0), 0);
35
29
  const rank = levelData?.level ?? null;
36
- const nextRank = null;
30
+ const nextRank = levelData?.next_level ?? null;
37
31
  const progress = levelData?.upgrade_progress?.percentage ?? 0;
38
- const requirementsMet = undefined;
39
- const fmt = (n) => n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
40
- return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg overflow-hidden h-full hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6 space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "block group cursor-pointer", onClick: () => onNavigate?.(resolvePath('/mcc/wallet')), role: "button", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onNavigate?.(resolvePath('/mcc/wallet')), children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono tracking-wider mb-1", children: "MCC_BALANCE" }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold font-mono text-cyan-400", children: mccLoading
41
- ? (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" })
42
- : fmt(mccBalance) }), (0, jsx_runtime_1.jsx)("div", { className: "text-neutral-500 text-xs font-mono mt-1", children: "on-chain balance (API)" })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "h-px bg-neutral-700" }), (0, jsx_runtime_1.jsx)("div", { className: "block group cursor-pointer", onClick: () => onNavigate?.(resolvePath('/mcc/mcd')), role: "button", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onNavigate?.(resolvePath('/mcc/mcd')), children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono tracking-wider mb-1", children: "MCD_BALANCE" }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold font-mono text-cyan-400", children: mcdLoading
43
- ? (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" })
44
- : fmt(mcdAmount) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-neutral-500 text-xs font-mono mt-1 space-x-3", children: [(0, jsx_runtime_1.jsxs)("span", { children: ["Income: ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: fmt(mcdReceived) })] }), (0, jsx_runtime_1.jsxs)("span", { children: ["Spent: ", (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: fmt(mcdSpent) })] })] })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "h-px bg-neutral-700" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono tracking-wider mb-2", children: "USER_RANK" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: `px-2.5 py-1 rounded text-sm font-bold font-mono ${RANK_COLOR[rank ?? ''] ?? 'text-neutral-500'} ${RANK_BG[rank ?? ''] ?? 'bg-neutral-800'}`, children: rank || 'N/A' }), nextRank && ((0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-500 text-xs font-mono", children: ["\u2192 ", nextRank] }))] }), nextRank && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-1.5 text-xs font-mono", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-500", children: "upgrade_progress" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-400", children: [progress.toFixed(1), "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-800 rounded-full h-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-2 rounded-full transition-all", style: { width: `${Math.min(progress, 100)}%` } }) }), requirementsMet && ((0, jsx_runtime_1.jsx)("div", { className: "mt-2 space-y-1", children: Object.entries(requirementsMet).map(([req, met]) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-[11px] font-mono", children: [(0, jsx_runtime_1.jsx)("span", { className: met ? 'text-white' : 'text-neutral-600', children: met ? '[✓]' : '[ ]' }), (0, jsx_runtime_1.jsx)("span", { className: met ? 'text-neutral-400' : 'text-neutral-600', children: req.replace(/_/g, ' ') })] }, req))) }))] })), !nextRank && rank && ((0, jsx_runtime_1.jsx)("div", { className: "bg-black border border-cyan-400/30 rounded p-2 text-center", children: (0, jsx_runtime_1.jsx)("div", { className: "text-cyan-400 font-bold text-xs font-mono", children: "MAX LEVEL" }) }))] })] }) }));
32
+ const fmt = (n, d = 2) => n.toLocaleString('en-US', { minimumFractionDigits: d, maximumFractionDigits: d });
33
+ const rankColor = RANK_COLOR[(rank ?? '').toLowerCase()] ?? 'text-neutral-500';
34
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 hover:border-cyan-400/50 transition-colors cursor-pointer h-full", onClick: () => onNavigate?.(resolvePath('/mcc/wallet')), role: "button", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onNavigate?.(resolvePath('/mcc/wallet')), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsxs)("svg", { className: "w-3.5 h-3.5 text-neutral-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }), (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })] }), (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-2xl font-bold font-mono text-cyan-400", children: mccLoading
35
+ ? (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" })
36
+ : fmt(mccBalance, 3) }), mccUsdValue > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-500 font-mono mt-1", children: ["\u2248 $", fmt(mccUsdValue)] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 hover:border-cyan-400/50 transition-colors cursor-pointer h-full", onClick: () => onNavigate?.(resolvePath('/mcc/mcd')), role: "button", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onNavigate?.(resolvePath('/mcc/mcd')), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-3.5 h-3.5 text-neutral-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" }) }), (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-2xl font-bold font-mono text-white", children: mcdLoading
37
+ ? (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" })
38
+ : fmt(mcdAmount) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-[10px] text-neutral-500 font-mono mt-1", children: ["in: ", fmt(mcdReceived, 0), " out: ", fmt(mcdSpent, 0)] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 hover:border-cyan-400/50 transition-colors", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-3.5 h-3.5 text-neutral-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }), (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-2xl font-bold font-mono text-white", children: fmt(lockedAmount, 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-4 hover:border-cyan-400/50 transition-colors", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-3.5 h-3.5 text-neutral-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }), (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-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-4 hover:border-cyan-400/50 transition-colors", 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 ${rankColor}`, children: rank || '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(progress, 100)}%` } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-[10px] text-neutral-500 font-mono mt-1", children: [progress.toFixed(0), "% \u2192 ", nextRank] })] }))] })] }));
45
39
  }
@@ -1,6 +1,39 @@
1
1
  "use strict";
2
2
  // AI-generated · AI-managed · AI-maintained
3
3
  'use client';
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
4
37
  Object.defineProperty(exports, "__esModule", { value: true });
5
38
  exports.MicrocosmDashboardOverview = MicrocosmDashboardOverview;
6
39
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -8,14 +41,15 @@ const react_1 = require("react");
8
41
  const market_overview_bar_1 = require("./market-overview-bar");
9
42
  const quick_actions_1 = require("./quick-actions");
10
43
  const assets_summary_1 = require("./assets-summary");
11
- const price_chart_1 = require("./price-chart");
12
- const minting_stats_1 = require("./minting-stats");
13
- const mining_weight_1 = require("./mining-weight");
14
- const my_mining_1 = require("./my-mining");
15
- const ecosystem_stats_1 = require("./ecosystem-stats");
16
- const mcc_token_stats_1 = require("./mcc-token-stats");
17
- const mcd_stats_1 = require("./mcd-stats");
18
- const lock_periods_1 = require("./lock-periods");
44
+ // Lazy load below-fold components — they won't execute until rendered
45
+ const MicrocosmPriceChart = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./price-chart'))).then(m => ({ default: m.MicrocosmPriceChart })));
46
+ const MicrocosmMyMining = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./my-mining'))).then(m => ({ default: m.MicrocosmMyMining })));
47
+ const MicrocosmMiningWeight = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./mining-weight'))).then(m => ({ default: m.MicrocosmMiningWeight })));
48
+ const MicrocosmMintingStats = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./minting-stats'))).then(m => ({ default: m.MicrocosmMintingStats })));
49
+ const MicrocosmEcosystemStats = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./ecosystem-stats'))).then(m => ({ default: m.MicrocosmEcosystemStats })));
50
+ const MicrocosmMCCTokenStats = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./mcc-token-stats'))).then(m => ({ default: m.MicrocosmMCCTokenStats })));
51
+ const MicrocosmMCDStats = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./mcd-stats'))).then(m => ({ default: m.MicrocosmMCDStats })));
52
+ const MicrocosmLockPeriods = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./lock-periods'))).then(m => ({ default: m.MicrocosmLockPeriods })));
19
53
  class SafeRender extends react_1.Component {
20
54
  constructor() {
21
55
  super(...arguments);
@@ -24,6 +58,38 @@ class SafeRender extends react_1.Component {
24
58
  static getDerivedStateFromError() { return { hasError: true }; }
25
59
  render() { return this.state.hasError ? null : this.props.children; }
26
60
  }
61
+ /** Skeleton placeholder matching card dimensions */
62
+ function CardSkeleton({ height = 'h-48' }) {
63
+ return ((0, jsx_runtime_1.jsx)("div", { className: `bg-neutral-900 border border-neutral-700 rounded-lg ${height} animate-pulse`, children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6 space-y-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-3 bg-neutral-800 rounded w-24" }), (0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-40" }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 bg-neutral-800 rounded w-32" })] }) }));
64
+ }
65
+ function ChartSkeleton() {
66
+ return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg h-[420px] animate-pulse", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6 space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-8" }), (0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-8" }), (0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-10" })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-[340px] bg-neutral-800 rounded" })] }) }));
67
+ }
68
+ /** Renders children only when the container enters the viewport */
69
+ function LazySection({ children, fallback }) {
70
+ const [visible, setVisible] = (0, react_1.useState)(false);
71
+ const ref = (0, react_1.useRef)(null);
72
+ (0, react_1.useEffect)(() => {
73
+ const el = ref.current;
74
+ if (!el)
75
+ return;
76
+ // If IntersectionObserver not supported, render immediately
77
+ if (typeof IntersectionObserver === 'undefined') {
78
+ setVisible(true);
79
+ return;
80
+ }
81
+ const observer = new IntersectionObserver(([entry]) => {
82
+ if (entry.isIntersecting) {
83
+ setVisible(true);
84
+ observer.disconnect();
85
+ }
86
+ }, { rootMargin: '200px' } // Start loading 200px before entering viewport
87
+ );
88
+ observer.observe(el);
89
+ return () => observer.disconnect();
90
+ }, []);
91
+ return ((0, jsx_runtime_1.jsx)("div", { ref: ref, children: visible ? children : fallback }));
92
+ }
27
93
  function MicrocosmDashboardOverview({ basePath = '', onNavigate, showHeader = true, headerText = 'SHARED NETWORK · SHARED FUTURE', }) {
28
- return ((0, jsx_runtime_1.jsxs)("div", { className: "max-w-7xl mx-auto font-mono p-6 space-y-6", children: [showHeader && ((0, jsx_runtime_1.jsx)("div", { className: "text-center", children: (0, jsx_runtime_1.jsx)("h1", { className: "text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-cyan-200", children: headerText }) })), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(market_overview_bar_1.MicrocosmMarketBar, {}) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(quick_actions_1.MicrocosmQuickActions, { basePath: basePath, onNavigate: onNavigate }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(assets_summary_1.MicrocosmAssetsSummary, { basePath: basePath, onNavigate: onNavigate }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(price_chart_1.MicrocosmPriceChart, {}) }), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(my_mining_1.MicrocosmMyMining, { detailsPath: `${basePath}/mcc/mining`, onNavigate: onNavigate }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(mining_weight_1.MicrocosmMiningWeight, {}) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(minting_stats_1.MicrocosmMintingStats, {}) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(ecosystem_stats_1.MicrocosmEcosystemStats, {}) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(mcc_token_stats_1.MicrocosmMCCTokenStats, {}) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(mcd_stats_1.MicrocosmMCDStats, {}) })] }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(lock_periods_1.MicrocosmLockPeriods, {}) })] }));
94
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "max-w-7xl mx-auto font-mono p-6 space-y-6", children: [showHeader && ((0, jsx_runtime_1.jsx)("div", { className: "text-center", children: (0, jsx_runtime_1.jsx)("h1", { className: "text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-cyan-200", children: headerText }) })), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(market_overview_bar_1.MicrocosmMarketBar, {}) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(quick_actions_1.MicrocosmQuickActions, { basePath: basePath, onNavigate: onNavigate }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(assets_summary_1.MicrocosmAssetsSummary, { basePath: basePath, onNavigate: onNavigate }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(ChartSkeleton, {}), children: (0, jsx_runtime_1.jsx)(MicrocosmPriceChart, {}) }) }), (0, jsx_runtime_1.jsx)(LazySection, { fallback: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" })] }), children: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), children: (0, jsx_runtime_1.jsx)(MicrocosmMyMining, { detailsPath: `${basePath}/mcc/mining`, onNavigate: onNavigate }) }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), children: (0, jsx_runtime_1.jsx)(MicrocosmMiningWeight, {}) }) })] }) }), (0, jsx_runtime_1.jsx)(LazySection, { fallback: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" })] }), children: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), children: (0, jsx_runtime_1.jsx)(MicrocosmMintingStats, {}) }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, { height: "h-56" }), children: (0, jsx_runtime_1.jsx)(MicrocosmEcosystemStats, {}) }) })] }) }), (0, jsx_runtime_1.jsx)(LazySection, { fallback: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(CardSkeleton, {}), (0, jsx_runtime_1.jsx)(CardSkeleton, {})] }), children: (0, jsx_runtime_1.jsxs)("div", { className: "grid lg:grid-cols-2 gap-6", children: [(0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, {}), children: (0, jsx_runtime_1.jsx)(MicrocosmMCCTokenStats, {}) }) }), (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, {}), children: (0, jsx_runtime_1.jsx)(MicrocosmMCDStats, {}) }) })] }) }), (0, jsx_runtime_1.jsx)(LazySection, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, {}), children: (0, jsx_runtime_1.jsx)(SafeRender, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(CardSkeleton, {}), children: (0, jsx_runtime_1.jsx)(MicrocosmLockPeriods, {}) }) }) })] }));
29
95
  }
@@ -15,16 +15,26 @@ function formatCompact(value) {
15
15
  function MicrocosmMarketBar() {
16
16
  const { data, loading } = (0, auth_react_1.useMarketData)();
17
17
  if (loading || !data) {
18
- return ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 mb-6", children: Array.from({ length: 5 }).map((_, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 animate-pulse", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-3 bg-neutral-800 rounded w-16 mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-24" })] }, i))) }));
18
+ return ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3 mb-6", children: Array.from({ length: 6 }).map((_, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 animate-pulse", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-3 bg-neutral-800 rounded w-16 mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "h-6 bg-neutral-800 rounded w-24" })] }, i))) }));
19
19
  }
20
20
  const priceChange24h = data.price_change_24h ?? 0;
21
21
  const isPositive = priceChange24h >= 0;
22
+ const buys = data.buys_24h ?? 0;
23
+ const sells = data.sells_24h ?? 0;
24
+ const trades = buys + sells;
22
25
  const stats = [
23
- { label: 'MCC_PRICE', value: `$${(data.price_usd ?? 0).toFixed(4)}`, color: 'text-cyan-400' },
24
- { label: '24H_CHANGE', value: `${isPositive ? '+' : ''}${priceChange24h.toFixed(2)}%`, color: isPositive ? 'text-white' : 'text-red-400' },
26
+ {
27
+ label: 'MCC_PRICE',
28
+ value: `$${(data.price_usd ?? 0).toFixed(4)}`,
29
+ sub: `${isPositive ? '~+' : '~'}${priceChange24h.toFixed(2)}%`,
30
+ subColor: isPositive ? 'text-cyan-400' : 'text-red-400',
31
+ color: 'text-cyan-400',
32
+ },
25
33
  { label: '24H_VOLUME', value: `$${formatCompact(data.volume_24h ?? 0)}`, color: 'text-cyan-300' },
26
- { label: 'LIQUIDITY', value: `$${formatCompact(data.liquidity_usd ?? 0)}`, color: 'text-cyan-400' },
27
- { label: 'FDV', value: `$${formatCompact(data.fdv ?? 0)}`, color: 'text-white' },
34
+ { label: 'LIQUIDITY', value: (data.liquidity_usd ?? 0) > 0 ? `$${formatCompact(data.liquidity_usd)}` : '-', color: 'text-white' },
35
+ { label: 'FDV', value: (data.fdv ?? 0) > 0 ? `$${formatCompact(data.fdv)}` : '-', color: 'text-white' },
36
+ { label: '24H_TRADES', value: `${trades}`, color: 'text-cyan-400' },
37
+ { label: 'BUY/SELL', value: `${buys}/${sells}`, color: 'text-white' },
28
38
  ];
29
- return ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 mb-6", children: stats.map((stat) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 hover:border-cyan-400/50 transition-colors", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono mb-1 tracking-wider", children: stat.label }), (0, jsx_runtime_1.jsx)("div", { className: `text-xl font-bold font-mono ${stat.color}`, children: stat.value })] }, stat.label))) }));
39
+ return ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3 mb-6", children: stats.map((stat) => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg p-4 hover:border-cyan-400/50 transition-colors", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-[10px] font-mono mb-1 tracking-wider", children: stat.label }), (0, jsx_runtime_1.jsx)("div", { className: `text-xl font-bold font-mono ${stat.color}`, children: stat.value }), stat.sub && ((0, jsx_runtime_1.jsx)("div", { className: `text-xs font-mono mt-0.5 ${stat.subColor || 'text-neutral-500'}`, children: stat.sub }))] }, stat.label))) }));
30
40
  }
@@ -6,8 +6,18 @@ exports.MicrocosmMintingStats = MicrocosmMintingStats;
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const auth_react_1 = require("@microcosmmoney/auth-react");
8
8
  function MicrocosmMintingStats() {
9
- const { data, loading } = (0, auth_react_1.useMiningRatio)();
10
- return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg h-full hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsx)("div", { className: "p-6", children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" }) })) : data ? ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 font-mono tracking-wider mb-1", children: "total_minted" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold font-mono text-white", children: [(data.total_minted ?? 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }), " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 font-mono tracking-wider mb-1", children: "current_rate" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold font-mono text-cyan-400", children: ["1:", (data.usdc_per_mcc ?? 0).toFixed(2)] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2 text-sm font-mono", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "next_halving" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white", children: [(Math.ceil((data.total_minted ?? 0) / 100000000 + 1) * 100000000 - (data.total_minted ?? 0)).toLocaleString('en-US', { maximumFractionDigits: 0 }), " MCC"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-800 rounded-full h-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-2 rounded-full transition-all", style: {
11
- width: `${((data.total_minted ?? 0) % 100000000) / 100000000 * 100}%`,
12
- } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mt-2 text-xs text-neutral-500 font-mono", children: [(0, jsx_runtime_1.jsxs)("span", { children: ["phase: ", data.current_stage ?? 1] }), (0, jsx_runtime_1.jsx)("span", { children: "threshold: 100M" })] })] })] })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-center py-8 text-neutral-500 font-mono", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-cyan-400", children: "warning:" }), " no minting data"] })) }) }));
9
+ const { data: mccStats, loading } = (0, auth_react_1.useMCCStats)();
10
+ const { data: marketData } = (0, auth_react_1.useMarketData)();
11
+ const s = mccStats;
12
+ const totalMinted = s?.circulating_supply ?? 0;
13
+ const currentStage = s?.current_phase ?? 0;
14
+ const miningRate = s?.current_mining_rate ?? 0;
15
+ const nextHalving = s?.next_halving_at ?? 100000000;
16
+ const price = marketData?.price_usd ?? 0;
17
+ const fmt = (n) => n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
18
+ return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg h-full hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsx)("div", { className: "p-6", children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-cyan-400", children: "\u26A1" }), (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-xs font-mono tracking-wider", children: "MINTING_STATS" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 font-mono tracking-wider mb-1", children: "total_minted" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold font-mono text-white", children: [totalMinted > 0 ? fmt(totalMinted) : '0', " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 font-mono tracking-wider mb-1", children: "mining_price" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold font-mono text-cyan-400", children: ["$", price > 0 ? (price * 2).toFixed(4) : '--'] }), (0, jsx_runtime_1.jsx)("div", { className: "text-[10px] text-neutral-500 font-mono", children: "market \u00D7 2" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-800 rounded p-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2 text-sm font-mono", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "next_halving" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white", children: [nextHalving > totalMinted
19
+ ? (nextHalving - totalMinted).toLocaleString('en-US', { maximumFractionDigits: 0 })
20
+ : 'N/A', " MCC"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-700 rounded-full h-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-2 rounded-full transition-all", style: {
21
+ width: nextHalving > 0 ? `${Math.min((totalMinted % nextHalving) / nextHalving * 100, 100)}%` : '0%',
22
+ } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mt-2 text-xs text-neutral-500 font-mono", children: [(0, jsx_runtime_1.jsxs)("span", { children: ["phase: ", currentStage, " | rate: ", miningRate > 0 ? `${miningRate}:1` : '--'] }), (0, jsx_runtime_1.jsxs)("span", { children: ["threshold: ", (nextHalving / 1e6).toFixed(0), "M"] })] })] })] })) }) }));
13
23
  }
@@ -18,7 +18,9 @@ function MicrocosmPriceChart() {
18
18
  const raw = data;
19
19
  const items = Array.isArray(raw) ? raw : raw?.records ?? [];
20
20
  const chartData = items.map((item) => ({
21
- time: typeof item.timestamp === 'number' ? item.timestamp * 1000 : new Date(item.timestamp).getTime(),
21
+ time: typeof item.timestamp === 'number'
22
+ ? (item.timestamp < 1e12 ? item.timestamp * 1000 : item.timestamp)
23
+ : new Date(item.timestamp).getTime(),
22
24
  price: item.price ?? item.close ?? 0,
23
25
  }));
24
26
  const prices = chartData.map((d) => d.price);
@@ -30,9 +32,9 @@ function MicrocosmPriceChart() {
30
32
  return d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
31
33
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
32
34
  };
33
- return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg overflow-hidden h-full flex flex-col hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6 flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between mb-4", children: (0, jsx_runtime_1.jsx)("div", { className: "flex gap-1 bg-black p-0.5 rounded", children: timeRanges.map((tr) => ((0, jsx_runtime_1.jsx)("button", { onClick: () => setRange(tr.value), className: `px-2.5 py-1 text-[10px] font-mono font-bold rounded transition-colors ${range === tr.value
35
+ return ((0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg overflow-hidden hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between mb-4", children: (0, jsx_runtime_1.jsx)("div", { className: "flex gap-1 bg-black p-0.5 rounded", children: timeRanges.map((tr) => ((0, jsx_runtime_1.jsx)("button", { onClick: () => setRange(tr.value), className: `px-2.5 py-1 text-[10px] font-mono font-bold rounded transition-colors ${range === tr.value
34
36
  ? 'bg-cyan-700 text-white'
35
- : 'text-neutral-500 hover:text-neutral-300'}`, children: tr.label }, tr.value))) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 min-h-[200px]", children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "h-full bg-neutral-800 rounded animate-pulse" })) : chartData.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "h-full flex items-center justify-center text-neutral-500 font-mono text-sm", children: "No price data available" })) : ((0, jsx_runtime_1.jsx)(recharts_1.ResponsiveContainer, { width: "100%", height: "100%", children: (0, jsx_runtime_1.jsxs)(recharts_1.AreaChart, { data: chartData, margin: { top: 5, right: 5, left: -15, bottom: 0 }, children: [(0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsxs)("linearGradient", { id: "mcPriceGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [(0, jsx_runtime_1.jsx)("stop", { offset: "5%", stopColor: "#22d3ee", stopOpacity: 0.3 }), (0, jsx_runtime_1.jsx)("stop", { offset: "95%", stopColor: "#22d3ee", stopOpacity: 0 })] }) }), (0, jsx_runtime_1.jsx)(recharts_1.CartesianGrid, { vertical: false, strokeDasharray: "3 3", stroke: "#404040" }), (0, jsx_runtime_1.jsx)(recharts_1.XAxis, { dataKey: "time", tick: { fill: '#737373', fontSize: 10, fontFamily: 'monospace' }, tickLine: false, axisLine: false, tickFormatter: formatTime }), (0, jsx_runtime_1.jsx)(recharts_1.YAxis, { tick: { fill: '#737373', fontSize: 10, fontFamily: 'monospace' }, tickLine: false, axisLine: false, tickFormatter: (v) => `$${v.toFixed(3)}`, domain: [minPrice, maxPrice] }), (0, jsx_runtime_1.jsx)(recharts_1.Tooltip, { contentStyle: {
37
+ : 'text-neutral-500 hover:text-neutral-300'}`, children: tr.label }, tr.value))) }) }), (0, jsx_runtime_1.jsx)("div", { className: "h-[360px]", children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "h-full bg-neutral-800 rounded animate-pulse" })) : chartData.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "h-full flex items-center justify-center text-neutral-500 font-mono text-sm", children: "No price data available" })) : ((0, jsx_runtime_1.jsx)(recharts_1.ResponsiveContainer, { width: "100%", height: "100%", children: (0, jsx_runtime_1.jsxs)(recharts_1.AreaChart, { data: chartData, margin: { top: 5, right: 5, left: -15, bottom: 0 }, children: [(0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsxs)("linearGradient", { id: "mcPriceGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [(0, jsx_runtime_1.jsx)("stop", { offset: "5%", stopColor: "#22d3ee", stopOpacity: 0.3 }), (0, jsx_runtime_1.jsx)("stop", { offset: "95%", stopColor: "#22d3ee", stopOpacity: 0 })] }) }), (0, jsx_runtime_1.jsx)(recharts_1.CartesianGrid, { vertical: false, strokeDasharray: "3 3", stroke: "#404040" }), (0, jsx_runtime_1.jsx)(recharts_1.XAxis, { dataKey: "time", tick: { fill: '#737373', fontSize: 10, fontFamily: 'monospace' }, tickLine: false, axisLine: false, tickFormatter: formatTime }), (0, jsx_runtime_1.jsx)(recharts_1.YAxis, { tick: { fill: '#737373', fontSize: 10, fontFamily: 'monospace' }, tickLine: false, axisLine: false, tickFormatter: (v) => `$${v.toFixed(3)}`, domain: [minPrice, maxPrice] }), (0, jsx_runtime_1.jsx)(recharts_1.Tooltip, { contentStyle: {
36
38
  backgroundColor: '#171717',
37
39
  border: '1px solid #404040',
38
40
  borderRadius: '6px',
@@ -4,18 +4,41 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.MicrocosmQuickActions = MicrocosmQuickActions;
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
- const actions = [
8
- { label: 'Mining', path: '/mcc/mining', color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30' },
9
- { label: 'Jupiter Trade', href: 'https://jup.ag/swap/USDT-MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb', color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30', external: true },
10
- { label: 'Market Data', path: '/market', color: 'text-white border-neutral-700 hover:bg-neutral-800' },
7
+ const MCC_MINT = 'MCCn6eqiTGzaiPKECg3viPmkdkS9YmkguqKvRcTxCsb';
8
+ const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
9
+ const POOL_ID = '4AiaTd9bAWf3u8ScZWhXadJF1roc8bJKEKvaDudKacZd';
10
+ const exchanges = [
11
+ {
12
+ label: 'Raydium',
13
+ href: `https://raydium.io/swap/?inputMint=${MCC_MINT}&outputMint=${USDC_MINT}`,
14
+ color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
15
+ icon: '💧',
16
+ },
17
+ {
18
+ label: 'Jupiter',
19
+ href: `https://jup.ag/swap/USDT-${MCC_MINT}`,
20
+ color: 'text-white border-neutral-700 hover:bg-neutral-800',
21
+ icon: '🔄',
22
+ },
23
+ {
24
+ label: 'BirdEye',
25
+ href: `https://birdeye.so/token/${MCC_MINT}?chain=solana`,
26
+ color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
27
+ icon: '👁',
28
+ },
29
+ {
30
+ label: 'GMGN',
31
+ href: `https://gmgn.ai/sol/token/${MCC_MINT}`,
32
+ color: 'text-white border-neutral-700 hover:bg-neutral-800',
33
+ icon: '📊',
34
+ },
35
+ {
36
+ label: 'DexScreener',
37
+ href: `https://dexscreener.com/solana/${POOL_ID}`,
38
+ color: 'text-cyan-300 border-cyan-400/30 hover:bg-cyan-950/30',
39
+ icon: '📈',
40
+ },
11
41
  ];
12
42
  function MicrocosmQuickActions({ basePath = '', onNavigate }) {
13
- const resolvePath = (p) => basePath ? `${basePath.replace(/\/$/, '')}${p}` : p;
14
- return ((0, jsx_runtime_1.jsx)("div", { className: "mb-6", children: (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3", children: actions.map((action) => {
15
- const content = ((0, jsx_runtime_1.jsx)("div", { className: `bg-neutral-900 border ${action.color} rounded-lg p-4 flex items-center gap-3 cursor-pointer active:scale-[0.98] transition-colors`, children: (0, jsx_runtime_1.jsx)("span", { className: "font-mono text-sm font-bold tracking-wider", children: action.label }) }));
16
- if ('external' in action && action.external) {
17
- return ((0, jsx_runtime_1.jsx)("a", { href: action.href, target: "_blank", rel: "noopener noreferrer", children: content }, action.label));
18
- }
19
- return ((0, jsx_runtime_1.jsx)("div", { onClick: () => onNavigate?.(resolvePath(action.path)), role: "button", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onNavigate?.(resolvePath(action.path)), children: content }, action.label));
20
- }) }) }));
43
+ return ((0, jsx_runtime_1.jsx)("div", { className: "mb-6", children: (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-5 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-4 flex items-center gap-3 cursor-pointer active:scale-[0.98] transition-colors`, children: [(0, jsx_runtime_1.jsx)("span", { className: "text-lg", children: ex.icon }), (0, jsx_runtime_1.jsx)("span", { className: "font-mono text-sm font-bold tracking-wider", children: ex.label })] }) }, ex.label))) }) }));
21
44
  }
@@ -0,0 +1,4 @@
1
+ export interface MicrocosmFragmentPageProps {
2
+ onNavigate?: (path: string) => void;
3
+ }
4
+ export declare function MicrocosmFragmentPage({ onNavigate }: MicrocosmFragmentPageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ // AI-generated · AI-managed · AI-maintained
3
+ 'use client';
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.MicrocosmFragmentPage = MicrocosmFragmentPage;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const auth_react_1 = require("@microcosmmoney/auth-react");
9
+ const fmt = (num, decimals = 2) => num.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
10
+ const fmtMCC = (lamports) => fmt(lamports / 1000000000, 2);
11
+ function Spinner() {
12
+ return (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" });
13
+ }
14
+ function Modal({ open, onClose, children }) {
15
+ if (!open)
16
+ return null;
17
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center", onClick: onClose, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 bg-black/60" }), (0, jsx_runtime_1.jsx)("div", { className: "relative bg-neutral-900 border border-neutral-700 rounded-lg p-6 max-w-md w-full mx-4 font-mono", onClick: e => e.stopPropagation(), children: children })] }));
18
+ }
19
+ function MicrocosmFragmentPage({ onNavigate }) {
20
+ const { user } = (0, auth_react_1.useAuth)();
21
+ const { data: wallets } = (0, auth_react_1.useWallets)();
22
+ const primaryWallet = wallets?.[0]?.wallet_address;
23
+ const { data: vaults, loading: vLoading, refresh: refreshVaults } = (0, auth_react_1.useFragmentVaults)();
24
+ const { data: holdings, loading: hLoading, refresh: refreshHoldings } = (0, auth_react_1.useFragmentHoldings)(primaryWallet);
25
+ const { buy, loading: actionLoading } = (0, auth_react_1.useFragmentAction)();
26
+ const [buyDialogOpen, setBuyDialogOpen] = (0, react_1.useState)(false);
27
+ const [selectedVault, setSelectedVault] = (0, react_1.useState)(null);
28
+ const [buyAmount, setBuyAmount] = (0, react_1.useState)('');
29
+ const [refreshing, setRefreshing] = (0, react_1.useState)(false);
30
+ const [actionError, setActionError] = (0, react_1.useState)(null);
31
+ const [actionSuccess, setActionSuccess] = (0, react_1.useState)(null);
32
+ const loading = vLoading || hLoading;
33
+ const handleRefresh = (0, react_1.useCallback)(async () => {
34
+ setRefreshing(true);
35
+ await Promise.all([refreshVaults(), refreshHoldings()]);
36
+ setRefreshing(false);
37
+ }, [refreshVaults, refreshHoldings]);
38
+ const handleBuy = async () => {
39
+ if (!selectedVault)
40
+ return;
41
+ const amount = parseInt(buyAmount);
42
+ if (isNaN(amount) || amount <= 0) {
43
+ setActionError('Please enter a valid amount');
44
+ return;
45
+ }
46
+ try {
47
+ setActionError(null);
48
+ await buy({ nft_mint: selectedVault.nft_mint, amount });
49
+ setActionSuccess(`Successfully purchased ${amount} fragments`);
50
+ setBuyDialogOpen(false);
51
+ setSelectedVault(null);
52
+ setBuyAmount('');
53
+ handleRefresh();
54
+ }
55
+ catch (err) {
56
+ setActionError(err instanceof Error ? err.message : 'Purchase failed');
57
+ }
58
+ };
59
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "max-w-7xl mx-auto font-mono space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { className: "text-2xl font-bold text-white", children: "Fragment" }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-400 text-sm mt-1", children: "NFT fractionalization protocol" })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleRefresh, disabled: refreshing, className: "flex items-center gap-2 px-3 py-1.5 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 disabled:opacity-50 bg-transparent", children: [(0, jsx_runtime_1.jsx)("svg", { className: `w-4 h-4 ${refreshing ? 'animate-spin' : ''}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) }), "Refresh"] })] }), actionError && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 bg-red-500/10 border border-red-500/30 rounded text-red-400 text-sm", children: actionError })), actionSuccess && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 bg-cyan-400/10 border border-cyan-400/30 rounded text-cyan-400 text-sm", children: actionSuccess })), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-sm mb-4", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "MY_HOLDINGS" })] }), loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(Spinner, {}) })) : holdings && holdings.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: holdings.map((h, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-2 bg-cyan-400/20 rounded border border-cyan-400/30", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-5 w-5 text-cyan-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z" }) }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "font-bold text-white font-mono", children: ["Vault #", h.vault_id] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-400", children: [(h.percentage ?? 0).toFixed(2), "% ownership"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-right", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-lg font-bold text-white font-mono", children: fmt(h.fragment_amount ?? 0, 0) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400", children: "fragments" })] })] }, i))) })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "no fragment holdings" }))] }) }), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-sm mb-4", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "FRAGMENT_VAULTS" })] }), loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(Spinner, {}) })) : vaults && vaults.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-4", children: vaults.map((v) => {
60
+ const soldPct = v.total_fragments > 0 ? (v.fragments_sold / v.total_fragments) * 100 : 0;
61
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-start mb-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-2 bg-cyan-400/20 rounded border border-cyan-400/30", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-6 w-6 text-cyan-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "font-bold text-white", children: [v.nft_type ?? 'Territory', " NFT"] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-400", children: [(v.nft_mint ?? '').slice(0, 8), "...", (v.nft_mint ?? '').slice(-4)] })] })] }), (0, jsx_runtime_1.jsx)("span", { className: `px-2 py-0.5 rounded text-xs ${v.is_active ? 'bg-white/20 text-white' : 'bg-neutral-700/50 text-neutral-400'}`, children: v.is_active ? 'OPEN' : 'CLOSED' })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4 mb-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: "total_fragments" }), (0, jsx_runtime_1.jsx)("div", { className: "text-lg font-bold text-white font-mono", children: fmt(v.total_fragments ?? 0, 0) })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: "price_per_fragment" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-lg font-bold text-cyan-400 font-mono", children: [fmtMCC(v.price_per_fragment ?? 0), " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: "sold" }), (0, jsx_runtime_1.jsx)("div", { className: "text-lg font-bold text-cyan-300 font-mono", children: fmt(v.fragments_sold ?? 0, 0) })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: "available" }), (0, jsx_runtime_1.jsx)("div", { className: "text-lg font-bold text-white font-mono", children: fmt((v.total_fragments ?? 0) - (v.fragments_sold ?? 0), 0) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "sale_progress" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-mono text-white", children: [soldPct.toFixed(1), "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-700 rounded-full h-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-2 rounded-full transition-all", style: { width: `${Math.min(soldPct, 100)}%` } }) })] }), v.is_active && (v.fragments_sold ?? 0) < (v.total_fragments ?? 0) && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-end", children: (0, jsx_runtime_1.jsx)("button", { onClick: () => { setSelectedVault(v); setBuyDialogOpen(true); setActionError(null); }, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded font-mono", children: "Buy Fragments" }) }))] }, v.vault_id));
62
+ }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "no fragment vaults available" }))] }) }), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-sm mb-4", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "PROTOCOL_INFO" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-white mb-2", children: "What is Fragmentation?" }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-400", children: "Fragment allows NFT owners to split Territory NFTs into tradeable fragments, enabling shared ownership and community buyout mechanics." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-white mb-2", children: "Fragment Holder Rights" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-neutral-400", children: [(0, jsx_runtime_1.jsx)("li", { children: "Proportional ownership of the underlying NFT" }), (0, jsx_runtime_1.jsx)("li", { children: "Participate in buyout proposals" }), (0, jsx_runtime_1.jsx)("li", { children: "Trade fragments freely on the market" })] })] })] })] }) }), (0, jsx_runtime_1.jsx)(Modal, { open: buyDialogOpen, onClose: () => setBuyDialogOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold text-white", children: "Buy Fragments" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400 mt-1", children: selectedVault ? `Purchase fragments from ${selectedVault.nft_type ?? 'Territory'} NFT vault` : 'Select a vault' })] }), selectedVault && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Unit Price" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-cyan-400 font-bold font-mono", children: [fmtMCC(selectedVault.price_per_fragment ?? 0), " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Available" }), (0, jsx_runtime_1.jsx)("span", { className: "text-white font-bold font-mono", children: fmt((selectedVault.total_fragments ?? 0) - (selectedVault.fragments_sold ?? 0), 0) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "purchase_amount" }), (0, jsx_runtime_1.jsx)("input", { type: "number", step: "1", min: "1", value: buyAmount, onChange: e => setBuyAmount(e.target.value), placeholder: "Enter amount", className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 outline-none focus:border-cyan-400" })] }), buyAmount && parseInt(buyAmount) > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Total Price" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white font-bold font-mono", children: [fmtMCC((selectedVault.price_per_fragment ?? 0) * parseInt(buyAmount)), " MCC"] })] }) }))] })), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-3 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => { setBuyDialogOpen(false); setBuyAmount(''); }, className: "px-4 py-2 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 bg-transparent", children: "Cancel" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleBuy, disabled: actionLoading || !buyAmount, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: actionLoading ? 'Processing...' : 'Confirm Purchase' })] })] }) })] }));
63
+ }
@@ -0,0 +1,4 @@
1
+ export interface MicrocosmLendingPageProps {
2
+ onNavigate?: (path: string) => void;
3
+ }
4
+ export declare function MicrocosmLendingPage({ onNavigate }: MicrocosmLendingPageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ // AI-generated · AI-managed · AI-maintained
3
+ 'use client';
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.MicrocosmLendingPage = MicrocosmLendingPage;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const auth_react_1 = require("@microcosmmoney/auth-react");
9
+ const fmt = (num, decimals = 2) => num.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
10
+ const fmtMCC = (lamports) => fmt(lamports / 1000000000, 2);
11
+ const COLLATERAL_TYPES = {
12
+ Station: { value: 1000, label: 'Station' },
13
+ Matrix: { value: 15000, label: 'Matrix' },
14
+ Sector: { value: 200000, label: 'Sector' },
15
+ System: { value: 2500000, label: 'System' },
16
+ };
17
+ function Spinner() {
18
+ return (0, jsx_runtime_1.jsx)("span", { className: "inline-block w-5 h-5 border-2 border-cyan-400 border-t-transparent rounded-full animate-spin" });
19
+ }
20
+ function Modal({ open, onClose, children }) {
21
+ if (!open)
22
+ return null;
23
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center", onClick: onClose, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 bg-black/60" }), (0, jsx_runtime_1.jsx)("div", { className: "relative bg-neutral-900 border border-neutral-700 rounded-lg p-6 max-w-md w-full mx-4 font-mono max-h-[90vh] overflow-y-auto", onClick: e => e.stopPropagation(), children: children })] }));
24
+ }
25
+ function MicrocosmLendingPage({ onNavigate }) {
26
+ const { user } = (0, auth_react_1.useAuth)();
27
+ const { data: wallets } = (0, auth_react_1.useWallets)();
28
+ const primaryWallet = wallets?.[0]?.wallet_address;
29
+ const { data: pool, loading: poolLoading, refresh: refreshPool } = (0, auth_react_1.useLendingPool)();
30
+ const { data: stats, loading: statsLoading, refresh: refreshStats } = (0, auth_react_1.useLendingStats)();
31
+ const { data: lpData, loading: lpLoading, refresh: refreshLP } = (0, auth_react_1.useLendingLPBalance)(primaryWallet);
32
+ const { data: oracle, refresh: refreshOracle } = (0, auth_react_1.useLendingOracle)();
33
+ const { data: nfts, refresh: refreshNFTs } = (0, auth_react_1.useTerritoryNFTs)(primaryWallet);
34
+ const { deposit, withdraw, borrow, repay, loading: actionLoading } = (0, auth_react_1.useLendingAction)();
35
+ const [refreshing, setRefreshing] = (0, react_1.useState)(false);
36
+ const [actionError, setActionError] = (0, react_1.useState)(null);
37
+ const [actionSuccess, setActionSuccess] = (0, react_1.useState)(null);
38
+ const [depositOpen, setDepositOpen] = (0, react_1.useState)(false);
39
+ const [withdrawOpen, setWithdrawOpen] = (0, react_1.useState)(false);
40
+ const [borrowOpen, setBorrowOpen] = (0, react_1.useState)(false);
41
+ const [repayOpen, setRepayOpen] = (0, react_1.useState)(false);
42
+ const [depositAmount, setDepositAmount] = (0, react_1.useState)('');
43
+ const [withdrawAmount, setWithdrawAmount] = (0, react_1.useState)('');
44
+ const [selectedNFT, setSelectedNFT] = (0, react_1.useState)('');
45
+ const [borrowAmount, setBorrowAmount] = (0, react_1.useState)('');
46
+ const [repayAmount, setRepayAmount] = (0, react_1.useState)('');
47
+ const loading = poolLoading || statsLoading || lpLoading;
48
+ const poolData = pool ?? stats;
49
+ const handleRefresh = (0, react_1.useCallback)(async () => {
50
+ setRefreshing(true);
51
+ await Promise.all([refreshPool(), refreshStats(), refreshLP(), refreshOracle(), refreshNFTs()]);
52
+ setRefreshing(false);
53
+ }, [refreshPool, refreshStats, refreshLP, refreshOracle, refreshNFTs]);
54
+ const handleDeposit = async () => {
55
+ const amount = parseFloat(depositAmount);
56
+ if (isNaN(amount) || amount <= 0) {
57
+ setActionError('Enter a valid amount');
58
+ return;
59
+ }
60
+ try {
61
+ setActionError(null);
62
+ await deposit({ wallet: primaryWallet ?? '', amount: amount * 1000000000 });
63
+ setActionSuccess(`Deposited ${fmt(amount)} MCC`);
64
+ setDepositOpen(false);
65
+ setDepositAmount('');
66
+ handleRefresh();
67
+ }
68
+ catch (err) {
69
+ setActionError(err instanceof Error ? err.message : 'Deposit failed');
70
+ }
71
+ };
72
+ const handleWithdraw = async () => {
73
+ const amount = parseFloat(withdrawAmount);
74
+ if (isNaN(amount) || amount <= 0) {
75
+ setActionError('Enter a valid amount');
76
+ return;
77
+ }
78
+ try {
79
+ setActionError(null);
80
+ await withdraw({ wallet: primaryWallet ?? '', lp_amount: amount * 1000000000 });
81
+ setActionSuccess(`Withdrew ${fmt(amount)} MCC`);
82
+ setWithdrawOpen(false);
83
+ setWithdrawAmount('');
84
+ handleRefresh();
85
+ }
86
+ catch (err) {
87
+ setActionError(err instanceof Error ? err.message : 'Withdraw failed');
88
+ }
89
+ };
90
+ const handleBorrow = async () => {
91
+ if (!selectedNFT) {
92
+ setActionError('Select an NFT');
93
+ return;
94
+ }
95
+ const amount = parseFloat(borrowAmount);
96
+ if (isNaN(amount) || amount <= 0) {
97
+ setActionError('Enter a valid amount');
98
+ return;
99
+ }
100
+ const nft = (nfts ?? []).find((n) => n.mint === selectedNFT);
101
+ if (!nft) {
102
+ setActionError('NFT not found');
103
+ return;
104
+ }
105
+ const nftType = nft.nft_type || 'Station';
106
+ const maxBorrow = COLLATERAL_TYPES[nftType]?.value ?? 1000;
107
+ if (amount > maxBorrow) {
108
+ setActionError(`Max borrow: ${fmt(maxBorrow)} MCC`);
109
+ return;
110
+ }
111
+ try {
112
+ setActionError(null);
113
+ await borrow({ wallet: primaryWallet ?? '', amount: amount * 1000000000, nft_mint: nft.mint, duration_type: 1 });
114
+ setActionSuccess(`Borrowed ${fmt(amount)} MCC`);
115
+ setBorrowOpen(false);
116
+ setSelectedNFT('');
117
+ setBorrowAmount('');
118
+ handleRefresh();
119
+ }
120
+ catch (err) {
121
+ setActionError(err instanceof Error ? err.message : 'Borrow failed');
122
+ }
123
+ };
124
+ const handleRepay = async () => {
125
+ const amount = parseFloat(repayAmount);
126
+ if (isNaN(amount) || amount <= 0) {
127
+ setActionError('Enter a valid amount');
128
+ return;
129
+ }
130
+ try {
131
+ setActionError(null);
132
+ await repay({ wallet: primaryWallet ?? '', nft_mint: '', amount: amount * 1000000000 });
133
+ setActionSuccess(`Repaid ${fmt(amount)} MCC`);
134
+ setRepayOpen(false);
135
+ setRepayAmount('');
136
+ handleRefresh();
137
+ }
138
+ catch (err) {
139
+ setActionError(err instanceof Error ? err.message : 'Repay failed');
140
+ }
141
+ };
142
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "max-w-7xl mx-auto font-mono space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { className: "text-2xl font-bold text-white tracking-wider", children: "Lending" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400", children: "MCC collateralized lending protocol" })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleRefresh, disabled: refreshing, className: "flex items-center gap-2 px-3 py-1.5 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 disabled:opacity-50 bg-transparent", children: [(0, jsx_runtime_1.jsx)("svg", { className: `w-4 h-4 ${refreshing ? 'animate-spin' : ''}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) }), "Refresh"] })] }), actionError && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 bg-red-500/10 border border-red-500/30 rounded text-red-400 text-sm", children: actionError })), actionSuccess && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 bg-cyan-400/10 border border-cyan-400/30 rounded text-cyan-400 text-sm", children: actionSuccess })), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4 mb-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-cyan-400/20 rounded-xl border border-cyan-400/30", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-8 w-8 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 14v3m4-3v3m4-3v3M3 21h18M3 10h18M3 7l9-4 9 4M4 10h16v11H4V10z" }) }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: "pool_name" }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-white", children: "MCC Lending Pool" })] })] }), loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(Spinner, {}) })) : poolData ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4 mb-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "total_deposits" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xl font-bold text-white font-mono", children: fmtMCC(poolData.total_deposits ?? 0) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "MCC" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 text-cyan-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "total_borrowed" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xl font-bold text-cyan-400 font-mono", children: fmtMCC(poolData.total_borrows ?? 0) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "MCC" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "deposit_apr" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold text-white font-mono", children: [(poolData.supply_apr_percent ?? 0).toFixed(2), "%"] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "annualized" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 text-cyan-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "borrow_apr" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-xl font-bold text-cyan-400 font-mono", children: [(poolData.borrow_apr_percent ?? 0).toFixed(2), "%"] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "annualized" })] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: "utilization_rate" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-mono text-white", children: [(poolData.utilization_rate_percent ?? 0).toFixed(1), "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-neutral-700 rounded-full h-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-cyan-400 h-2 rounded-full transition-all", style: { width: `${Math.min(poolData.utilization_rate_percent ?? 0, 100)}%` } }) })] })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "pool data unavailable" }))] }) }), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-sm tracking-wider", children: "MY_DEPOSITS" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => { setDepositOpen(true); setActionError(null); }, className: "px-3 py-1.5 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded", children: "+ Deposit" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { setWithdrawOpen(true); setActionError(null); }, disabled: !lpData || (lpData.lp_balance ?? 0) <= 0, className: "px-3 py-1.5 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 disabled:opacity-50 bg-transparent", children: "- Withdraw" })] })] }), lpData && (lpData.lp_balance ?? 0) > 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: "lp_token_balance" }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-white font-mono", children: fmtMCC(lpData.lp_balance ?? 0) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "LP Token" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: "deposit_value" }), (0, jsx_runtime_1.jsx)("div", { className: "text-2xl font-bold text-white font-mono", children: fmtMCC(lpData.lp_value_in_mcc ?? lpData.lp_balance ?? 0) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "MCC" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: "earned_interest" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-2xl font-bold text-cyan-400 font-mono", children: ["+", fmtMCC(Math.max(0, (lpData.lp_value_in_mcc ?? lpData.lp_balance ?? 0) - (lpData.lp_balance ?? 0)))] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-500 mt-1", children: "MCC" })] })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "no deposits yet \u2014 deposit MCC to earn interest" }))] }) }), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 text-sm tracking-wider", children: "MY_LOANS" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { setBorrowOpen(true); setActionError(null); }, disabled: !nfts || nfts.length === 0, className: "px-3 py-1.5 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: "+ New Loan" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-neutral-500 font-mono text-sm", children: "no active loans \u2014 pledge Territory NFT to borrow MCC" })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "bg-neutral-900 border border-neutral-700 rounded-lg hover:border-cyan-400/50 transition-colors", children: (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-sm mb-4", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "PROTOCOL_INFO" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-white mb-2", children: "Loan Rules" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-neutral-400", children: [(0, jsx_runtime_1.jsx)("li", { children: "Collateral: Territory NFT (Station/Matrix/Sector/System)" }), (0, jsx_runtime_1.jsx)("li", { children: "Max LTV: 100% of NFT valuation" }), (0, jsx_runtime_1.jsx)("li", { children: "Interest: variable rate based on pool utilization" }), (0, jsx_runtime_1.jsx)("li", { children: "Duration: 3 / 7 / 30 days with auto-renewal" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-white mb-2", children: "Liquidation Rules" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-neutral-400", children: [(0, jsx_runtime_1.jsx)("li", { children: "LTV exceeds 90%: liquidation warning" }), (0, jsx_runtime_1.jsx)("li", { children: "Loan overdue or 2+ missed payments: liquidation eligible" }), (0, jsx_runtime_1.jsx)("li", { children: "Collateral NFT seized upon liquidation" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-white mb-2", children: "NFT Valuation" }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4 mt-2", children: Object.entries(COLLATERAL_TYPES).map(([key, val]) => ((0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-neutral-400 text-xs", children: val.label }), (0, jsx_runtime_1.jsx)("div", { className: "text-white font-bold font-mono", children: fmt(val.value) }), (0, jsx_runtime_1.jsx)("div", { className: "text-neutral-500 text-xs", children: "MCC" })] }, key))) })] })] })] }) }), (0, jsx_runtime_1.jsx)(Modal, { open: depositOpen, onClose: () => setDepositOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold text-white", children: "Deposit MCC" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400 mt-1", children: "Earn interest by providing liquidity to the lending pool" })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-cyan-400/10 border border-cyan-400/30 rounded", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-sm text-cyan-400", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium mb-1", children: "Earnings Info" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-xs text-cyan-400/70", children: [(0, jsx_runtime_1.jsxs)("li", { children: ["Current APR: ", (poolData?.supply_apr_percent ?? 0).toFixed(2), "%"] }), (0, jsx_runtime_1.jsx)("li", { children: "Interest accrues in real-time" }), (0, jsx_runtime_1.jsx)("li", { children: "Withdraw anytime" })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "amount (MCC)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", step: "0.01", value: depositAmount, onChange: e => setDepositAmount(e.target.value), placeholder: "Enter amount", className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 outline-none focus:border-cyan-400" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-3 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setDepositOpen(false), className: "px-4 py-2 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 bg-transparent", children: "Cancel" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleDeposit, disabled: actionLoading || !depositAmount, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: actionLoading ? 'Processing...' : 'Confirm Deposit' })] })] }) }), (0, jsx_runtime_1.jsx)(Modal, { open: withdrawOpen, onClose: () => setWithdrawOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold text-white", children: "Withdraw MCC" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400 mt-1", children: "Withdraw deposited MCC from the lending pool" })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Withdrawable" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white font-bold font-mono", children: [fmtMCC(lpData?.lp_value_in_mcc ?? lpData?.lp_balance ?? 0), " MCC"] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "amount (MCC)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", step: "0.01", value: withdrawAmount, onChange: e => setWithdrawAmount(e.target.value), placeholder: "Enter amount", className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 outline-none focus:border-cyan-400" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-3 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setWithdrawOpen(false), className: "px-4 py-2 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 bg-transparent", children: "Cancel" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleWithdraw, disabled: actionLoading || !withdrawAmount, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: actionLoading ? 'Processing...' : 'Confirm Withdraw' })] })] }) }), (0, jsx_runtime_1.jsx)(Modal, { open: borrowOpen, onClose: () => setBorrowOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold text-white", children: "New Loan" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400 mt-1", children: "Borrow MCC using Territory NFT as collateral" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "select_nft" }), (0, jsx_runtime_1.jsxs)("select", { value: selectedNFT, onChange: e => setSelectedNFT(e.target.value), className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white outline-none focus:border-cyan-400", children: [(0, jsx_runtime_1.jsx)("option", { value: "", children: "Select Territory NFT..." }), (nfts ?? []).map((nft) => ((0, jsx_runtime_1.jsxs)("option", { value: nft.mint, children: [nft.name, " (", COLLATERAL_TYPES[nft.nft_type]?.label ?? nft.nft_type, ")"] }, nft.mint)))] })] }), selectedNFT && (() => {
143
+ const nft = (nfts ?? []).find((n) => n.mint === selectedNFT);
144
+ const nftType = nft?.nft_type || 'Station';
145
+ const maxVal = COLLATERAL_TYPES[nftType]?.value ?? 1000;
146
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 bg-neutral-800 rounded border border-neutral-700", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Collateral Value" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white font-bold font-mono", children: [fmt(maxVal), " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: "Max Borrow" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white font-bold font-mono", children: [fmt(maxVal), " MCC"] })] })] }));
147
+ })(), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "borrow_amount (MCC)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", step: "0.01", value: borrowAmount, onChange: e => setBorrowAmount(e.target.value), placeholder: "Enter amount", className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 outline-none focus:border-cyan-400" })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-cyan-400/10 border border-cyan-400/30 rounded", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-sm text-cyan-400", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium mb-1", children: "Borrow Notice" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-xs text-cyan-400/70", children: [(0, jsx_runtime_1.jsx)("li", { children: "NFT will be locked as collateral" }), (0, jsx_runtime_1.jsxs)("li", { children: ["Current borrow APR: ", (poolData?.borrow_apr_percent ?? 0).toFixed(2), "%"] }), (0, jsx_runtime_1.jsx)("li", { children: "Failure to repay may result in NFT liquidation" })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-3 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setBorrowOpen(false), className: "px-4 py-2 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 bg-transparent", children: "Cancel" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleBorrow, disabled: actionLoading || !selectedNFT || !borrowAmount, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: actionLoading ? 'Processing...' : 'Confirm Borrow' })] })] }) }), (0, jsx_runtime_1.jsx)(Modal, { open: repayOpen, onClose: () => setRepayOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold text-white", children: "Repay Loan" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-neutral-400 mt-1", children: "Repay borrowed MCC to release collateral" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-xs text-neutral-400 tracking-wider", children: "repay_amount (MCC)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", step: "0.01", value: repayAmount, onChange: e => setRepayAmount(e.target.value), placeholder: "Enter amount", className: "w-full px-3 py-2 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 outline-none focus:border-cyan-400" })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 bg-cyan-400/10 border border-cyan-400/30 rounded", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-sm text-cyan-400", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium mb-1", children: "After Full Repay" }), (0, jsx_runtime_1.jsxs)("ul", { className: "list-disc list-inside space-y-1 text-xs text-cyan-400/70", children: [(0, jsx_runtime_1.jsx)("li", { children: "Collateral NFT returned to your wallet" }), (0, jsx_runtime_1.jsx)("li", { children: "Loan record marked as repaid" })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-3 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setRepayOpen(false), className: "px-4 py-2 text-sm border border-neutral-700 rounded text-neutral-400 hover:bg-neutral-800 bg-transparent", children: "Cancel" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleRepay, disabled: actionLoading || !repayAmount, className: "px-4 py-2 text-sm bg-cyan-700 hover:bg-cyan-600 text-white rounded disabled:opacity-50", children: actionLoading ? 'Processing...' : 'Confirm Repay' })] })] }) })] }));
148
+ }
package/dist/index.d.ts CHANGED
@@ -39,3 +39,7 @@ export { MicrocosmEcosystemStats } from './components/dashboard/ecosystem-stats'
39
39
  export { MicrocosmMCCTokenStats } from './components/dashboard/mcc-token-stats';
40
40
  export { MicrocosmMCDStats } from './components/dashboard/mcd-stats';
41
41
  export { MicrocosmLockPeriods } from './components/dashboard/lock-periods';
42
+ export { MicrocosmFragmentPage } from './components/fragment/fragment-page';
43
+ export type { MicrocosmFragmentPageProps } from './components/fragment/fragment-page';
44
+ export { MicrocosmLendingPage } from './components/lending/lending-page';
45
+ export type { MicrocosmLendingPageProps } from './components/lending/lending-page';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MicrocosmLockPeriods = exports.MicrocosmMCDStats = exports.MicrocosmMCCTokenStats = exports.MicrocosmEcosystemStats = exports.MicrocosmMyMining = exports.MicrocosmMiningWeight = exports.MicrocosmMintingStats = exports.MicrocosmPriceChart = exports.MicrocosmAssetsSummary = exports.MicrocosmQuickActions = exports.MicrocosmMarketBar = exports.MicrocosmDashboardOverview = exports.KPIRadialChart = exports.VoteResultBar = exports.MiningProgressBar = exports.TerritoryCard = exports.TerminalTooltip = exports.TerminalInput = exports.TerminalCountdown = exports.TerminalDialog = exports.TerminalTabs = exports.TerminalTable = exports.TerminalProgress = exports.TerminalDataRow = exports.TerminalBadge = exports.TerminalEmpty = exports.TerminalError = exports.TerminalLoading = exports.TerminalPageHeader = exports.TerminalCommand = exports.StatBox = exports.TerminalCard = exports.resolveMenuPath = exports.getAllMenuItems = exports.microcosmMenuGroups = exports.dashboardMenu = exports.web3OsMenu = exports.blockchainMenu = exports.MicrocosmMenuSection = void 0;
3
+ exports.MicrocosmLendingPage = exports.MicrocosmFragmentPage = exports.MicrocosmLockPeriods = exports.MicrocosmMCDStats = exports.MicrocosmMCCTokenStats = exports.MicrocosmEcosystemStats = exports.MicrocosmMyMining = exports.MicrocosmMiningWeight = exports.MicrocosmMintingStats = exports.MicrocosmPriceChart = exports.MicrocosmAssetsSummary = exports.MicrocosmQuickActions = exports.MicrocosmMarketBar = exports.MicrocosmDashboardOverview = exports.KPIRadialChart = exports.VoteResultBar = exports.MiningProgressBar = exports.TerritoryCard = exports.TerminalTooltip = exports.TerminalInput = exports.TerminalCountdown = exports.TerminalDialog = exports.TerminalTabs = exports.TerminalTable = exports.TerminalProgress = exports.TerminalDataRow = exports.TerminalBadge = exports.TerminalEmpty = exports.TerminalError = exports.TerminalLoading = exports.TerminalPageHeader = exports.TerminalCommand = exports.StatBox = exports.TerminalCard = exports.resolveMenuPath = exports.getAllMenuItems = exports.microcosmMenuGroups = exports.dashboardMenu = exports.web3OsMenu = exports.blockchainMenu = exports.MicrocosmMenuSection = void 0;
4
4
  // AI-generated · AI-managed · AI-maintained
5
5
  var menu_section_1 = require("./components/menu-section");
6
6
  Object.defineProperty(exports, "MicrocosmMenuSection", { enumerable: true, get: function () { return menu_section_1.MicrocosmMenuSection; } });
@@ -66,3 +66,7 @@ var mcd_stats_1 = require("./components/dashboard/mcd-stats");
66
66
  Object.defineProperty(exports, "MicrocosmMCDStats", { enumerable: true, get: function () { return mcd_stats_1.MicrocosmMCDStats; } });
67
67
  var lock_periods_1 = require("./components/dashboard/lock-periods");
68
68
  Object.defineProperty(exports, "MicrocosmLockPeriods", { enumerable: true, get: function () { return lock_periods_1.MicrocosmLockPeriods; } });
69
+ var fragment_page_1 = require("./components/fragment/fragment-page");
70
+ Object.defineProperty(exports, "MicrocosmFragmentPage", { enumerable: true, get: function () { return fragment_page_1.MicrocosmFragmentPage; } });
71
+ var lending_page_1 = require("./components/lending/lending-page");
72
+ Object.defineProperty(exports, "MicrocosmLendingPage", { enumerable: true, get: function () { return lending_page_1.MicrocosmLendingPage; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microcosmmoney/portal-react",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "description": "Microcosm Portal UI components for React/Next.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -17,8 +17,8 @@
17
17
  "recharts": ">=2.0.0"
18
18
  },
19
19
  "dependencies": {
20
- "@microcosmmoney/auth-core": "^2.2.1",
21
- "@microcosmmoney/auth-react": "^2.2.2",
20
+ "@microcosmmoney/auth-core": "file:../auth-core",
21
+ "@microcosmmoney/auth-react": "file:../auth-react",
22
22
  "lucide-react": ">=0.300.0"
23
23
  },
24
24
  "devDependencies": {