@microcosmmoney/portal-react 3.13.6 → 3.13.8
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.
|
@@ -54,12 +54,13 @@ const STABLECOIN_VAULTS = {
|
|
|
54
54
|
usdc: new web3_js_1.PublicKey("5L8vPTvGH14keLq4R6CGGvSFksZFjb7bRPXarCwZbmUA"),
|
|
55
55
|
usdt: new web3_js_1.PublicKey("BnHA9jSm88wzQS4c2nCgTXch1Byzc3FWn2G7Wgrvazy3"),
|
|
56
56
|
};
|
|
57
|
-
const
|
|
58
|
-
const SOLANA_RPC = process.env.NEXT_PUBLIC_HELIUS_RPC_URL || process.env.NEXT_PUBLIC_SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
57
|
+
const SOLANA_RPC = process.env.NEXT_PUBLIC_HELIUS_RPC_URL || process.env.NEXT_PUBLIC_SOLANA_RPC_URL || "";
|
|
59
58
|
const COIN_INFO = {
|
|
60
59
|
usdc: { symbol: 'USDC', name: 'USD Coin', icon: '💵' },
|
|
61
60
|
usdt: { symbol: 'USDT', name: 'Tether', icon: '💴' },
|
|
62
61
|
};
|
|
62
|
+
const STATUS_POLL_INTERVAL_MS = 1500;
|
|
63
|
+
const STATUS_POLL_TIMEOUT_MS = 30 * 60 * 1000;
|
|
63
64
|
function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
64
65
|
const t = (0, next_intl_1.useTranslations)("miningModal");
|
|
65
66
|
const { publicKey, sendTransaction, connected } = (0, wallet_adapter_react_1.useWallet)();
|
|
@@ -76,10 +77,11 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
76
77
|
const [stablecoinBalance, setStablecoinBalance] = (0, react_1.useState)(null);
|
|
77
78
|
const [loadingBalance, setLoadingBalance] = (0, react_1.useState)(false);
|
|
78
79
|
const [solanaPayUrl, setSolanaPayUrl] = (0, react_1.useState)("");
|
|
79
|
-
const [
|
|
80
|
-
const [
|
|
81
|
-
const
|
|
82
|
-
const
|
|
80
|
+
const [backendStatus, setBackendStatus] = (0, react_1.useState)("created");
|
|
81
|
+
const [showCloseConfirm, setShowCloseConfirm] = (0, react_1.useState)(false);
|
|
82
|
+
const [pollElapsedSec, setPollElapsedSec] = (0, react_1.useState)(0);
|
|
83
|
+
const pollIntervalRef = (0, react_1.useRef)(null);
|
|
84
|
+
const pollStartTsRef = (0, react_1.useRef)(0);
|
|
83
85
|
const isMobile = typeof window !== "undefined" ? (0, solana_pay_1.isMobileDevice)() : false;
|
|
84
86
|
const loadStablecoinBalance = (0, react_1.useCallback)(async () => {
|
|
85
87
|
if (!publicKey || !connected) {
|
|
@@ -107,70 +109,58 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
107
109
|
} }, [isOpen, loadStablecoinBalance]);
|
|
108
110
|
(0, react_1.useEffect)(() => { if (isOpen && connected)
|
|
109
111
|
loadStablecoinBalance(); }, [stablecoin, isOpen, connected, loadStablecoinBalance]);
|
|
110
|
-
(0, react_1.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const response = await (0, api_1.confirmMiningPayment)({ request_id: request.request_id, tx_signature: signature, mcc_amount: request.mcc_amount, usdc_amount: request.usdc_amount_with_discount, stablecoin_type: stablecoin });
|
|
115
|
-
if (!response.success || !response.data)
|
|
116
|
-
throw new Error(response.error || t("errorConfirmPayment"));
|
|
117
|
-
setConfirmationResult(response.data);
|
|
118
|
-
setStep("success");
|
|
119
|
-
}
|
|
120
|
-
catch (err) {
|
|
121
|
-
setError(err instanceof Error ? err.message : t("errorConfirmPayment"));
|
|
122
|
-
setStep("error");
|
|
123
|
-
}
|
|
124
|
-
finally {
|
|
125
|
-
setLoading(false);
|
|
112
|
+
const stopStatusPolling = (0, react_1.useCallback)(() => {
|
|
113
|
+
if (pollIntervalRef.current !== null) {
|
|
114
|
+
clearInterval(pollIntervalRef.current);
|
|
115
|
+
pollIntervalRef.current = null;
|
|
126
116
|
}
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
}, []);
|
|
118
|
+
(0, react_1.useEffect)(() => () => { stopStatusPolling(); }, [stopStatusPolling]);
|
|
119
|
+
const startStatusPolling = (0, react_1.useCallback)((requestId) => {
|
|
120
|
+
stopStatusPolling();
|
|
121
|
+
pollStartTsRef.current = Date.now();
|
|
122
|
+
setPollElapsedSec(0);
|
|
123
|
+
const tick = async () => {
|
|
124
|
+
const elapsed = Date.now() - pollStartTsRef.current;
|
|
125
|
+
setPollElapsedSec(Math.floor(elapsed / 1000));
|
|
126
|
+
if (elapsed > STATUS_POLL_TIMEOUT_MS) {
|
|
127
|
+
stopStatusPolling();
|
|
135
128
|
return;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
if (!
|
|
140
|
-
setError(t("errorExtractPayer"));
|
|
141
|
-
setStep("error");
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const response = await (0, api_1.getMiningRequestStatus)(requestId);
|
|
132
|
+
if (!response.success || !response.data)
|
|
142
133
|
return;
|
|
134
|
+
const data = response.data;
|
|
135
|
+
setBackendStatus(data.status);
|
|
136
|
+
if (data.payment_tx_signature)
|
|
137
|
+
setTxSignature(data.payment_tx_signature);
|
|
138
|
+
if (data.status === "completed") {
|
|
139
|
+
stopStatusPolling();
|
|
140
|
+
setConfirmationResult({
|
|
141
|
+
onchain_tx_signature: data.onchain_tx_signature || "",
|
|
142
|
+
mcc_distributed: data.mcc_distributed || { user: 0, lp_reserve: 0, magistrate: 0, station_mcd: 0 },
|
|
143
|
+
status: "completed",
|
|
144
|
+
});
|
|
145
|
+
setStep("success");
|
|
143
146
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
catch { }
|
|
147
|
+
else if (data.status === "failed") {
|
|
148
|
+
stopStatusPolling();
|
|
149
|
+
setError(data.error || t("errorMintRequest"));
|
|
150
|
+
setStep("error");
|
|
151
|
+
}
|
|
152
|
+
else if (data.status === "expired") {
|
|
153
|
+
stopStatusPolling();
|
|
154
|
+
setError(t("errorPaymentTimeout"));
|
|
155
|
+
setStep("error");
|
|
155
156
|
}
|
|
156
|
-
setStep("confirming");
|
|
157
|
-
await confirmPayment(request, signature);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
setError(t("errorPaymentTimeout"));
|
|
161
|
-
setStep("error");
|
|
162
157
|
}
|
|
163
|
-
|
|
164
|
-
catch (err) {
|
|
165
|
-
if (!monitorAbortRef.current) {
|
|
166
|
-
setError(err instanceof Error ? err.message : t("errorMonitorFailed"));
|
|
167
|
-
setStep("error");
|
|
158
|
+
catch {
|
|
168
159
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
};
|
|
160
|
+
};
|
|
161
|
+
tick();
|
|
162
|
+
pollIntervalRef.current = window.setInterval(tick, STATUS_POLL_INTERVAL_MS);
|
|
163
|
+
}, [stopStatusPolling, t]);
|
|
174
164
|
const handleSubmit = async () => {
|
|
175
165
|
if (!userDetails || !mccAmount || parseFloat(mccAmount) <= 0) {
|
|
176
166
|
setError(t("errorInvalidAmount"));
|
|
@@ -189,18 +179,28 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
189
179
|
}
|
|
190
180
|
}
|
|
191
181
|
catch { }
|
|
192
|
-
const {
|
|
193
|
-
|
|
182
|
+
const { Keypair, PublicKey } = await Promise.resolve().then(() => __importStar(require("@solana/web3.js")));
|
|
183
|
+
const refKeypair = Keypair.generate();
|
|
184
|
+
const reference = refKeypair.publicKey;
|
|
194
185
|
const response = await (0, api_1.createMiningRequest)({ mcc_amount: parseFloat(mccAmount) * 1000000000, stablecoin_type: stablecoin, reference: reference.toBase58() });
|
|
195
186
|
if (!response.success || !response.data)
|
|
196
187
|
throw new Error(response.error || t("errorCreateRequest"));
|
|
197
188
|
setMiningRequest(response.data);
|
|
198
|
-
const vault = STABLECOIN_VAULTS[stablecoin]
|
|
199
|
-
const
|
|
200
|
-
|
|
189
|
+
const vault = STABLECOIN_VAULTS[stablecoin];
|
|
190
|
+
const mint = STABLECOIN_MINTS[stablecoin];
|
|
191
|
+
const payUrl = (0, solana_pay_1.createSolanaPayUrl)({
|
|
192
|
+
recipient: vault,
|
|
193
|
+
amount: response.data.usdc_amount_with_discount / 1000000,
|
|
194
|
+
splToken: mint,
|
|
195
|
+
reference,
|
|
196
|
+
label: "Microcosm Mining",
|
|
197
|
+
message: `Mine ${mccAmount} MCC`,
|
|
198
|
+
});
|
|
199
|
+
setSolanaPayUrl(payUrl);
|
|
200
|
+
setBackendStatus("created");
|
|
201
201
|
if (isMobile) {
|
|
202
202
|
setStep("qrPayment");
|
|
203
|
-
|
|
203
|
+
startStatusPolling(response.data.request_id);
|
|
204
204
|
}
|
|
205
205
|
else {
|
|
206
206
|
setStep("paymentMethod");
|
|
@@ -214,8 +214,12 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
214
214
|
setLoading(false);
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
|
-
const handleSelectQrPayment = () => {
|
|
218
|
-
|
|
217
|
+
const handleSelectQrPayment = () => {
|
|
218
|
+
if (!miningRequest)
|
|
219
|
+
return;
|
|
220
|
+
setStep("qrPayment");
|
|
221
|
+
startStatusPolling(miningRequest.request_id);
|
|
222
|
+
};
|
|
219
223
|
const handleSelectBrowserPayment = async () => {
|
|
220
224
|
if (!connected || !publicKey) {
|
|
221
225
|
setError(t("errorConnectWallet"));
|
|
@@ -258,14 +262,23 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
258
262
|
const transferIx = createTransferCheckedInstruction(userAta, mint, vault, publicKey, request.usdc_amount_with_discount, 6);
|
|
259
263
|
const connection = new web3_js_1.Connection(SOLANA_RPC, "confirmed");
|
|
260
264
|
const transaction = new web3_js_1.Transaction().add(transferIx);
|
|
261
|
-
const { blockhash
|
|
265
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
262
266
|
transaction.recentBlockhash = blockhash;
|
|
263
267
|
transaction.feePayer = publicKey;
|
|
264
268
|
const signature = await sendTransaction(transaction, connection);
|
|
265
269
|
setTxSignature(signature);
|
|
266
270
|
setStep("confirming");
|
|
267
|
-
|
|
268
|
-
|
|
271
|
+
const confirmResponse = await (0, api_1.confirmMiningPayment)({
|
|
272
|
+
request_id: request.request_id,
|
|
273
|
+
tx_signature: signature,
|
|
274
|
+
mcc_amount: request.mcc_amount,
|
|
275
|
+
usdc_amount: request.usdc_amount_with_discount,
|
|
276
|
+
stablecoin_type: stablecoin,
|
|
277
|
+
});
|
|
278
|
+
if (!confirmResponse.success || !confirmResponse.data)
|
|
279
|
+
throw new Error(confirmResponse.error || t("errorConfirmPayment"));
|
|
280
|
+
setConfirmationResult(confirmResponse.data);
|
|
281
|
+
setStep("success");
|
|
269
282
|
}
|
|
270
283
|
catch (err) {
|
|
271
284
|
setError(err instanceof Error ? err.message : t("errorMiningFailed"));
|
|
@@ -276,8 +289,10 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
276
289
|
setLoading(false);
|
|
277
290
|
}
|
|
278
291
|
};
|
|
279
|
-
const
|
|
280
|
-
|
|
292
|
+
const isMiningInProgress = step === "qrPayment" && (backendStatus === "submitted" || backendStatus === "distributing");
|
|
293
|
+
const performClose = (0, react_1.useCallback)(() => {
|
|
294
|
+
stopStatusPolling();
|
|
295
|
+
setShowCloseConfirm(false);
|
|
281
296
|
setStep("input");
|
|
282
297
|
setMccAmount("");
|
|
283
298
|
setMiningRequest(null);
|
|
@@ -285,12 +300,17 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
285
300
|
setError("");
|
|
286
301
|
setConfirmationResult(null);
|
|
287
302
|
setSolanaPayUrl("");
|
|
288
|
-
|
|
289
|
-
setQrMonitoring(false);
|
|
290
|
-
setQrPayerAddress("");
|
|
303
|
+
setBackendStatus("created");
|
|
291
304
|
if (onSuccess)
|
|
292
305
|
onSuccess();
|
|
293
306
|
onClose();
|
|
307
|
+
}, [stopStatusPolling, onClose, onSuccess]);
|
|
308
|
+
const handleClose = () => {
|
|
309
|
+
if (isMiningInProgress) {
|
|
310
|
+
setShowCloseConfirm(true);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
performClose();
|
|
294
314
|
};
|
|
295
315
|
if (!isOpen)
|
|
296
316
|
return null;
|
|
@@ -298,5 +318,27 @@ function MiningModal({ isOpen, onClose, userDetails, onSuccess }) {
|
|
|
298
318
|
const ci = COIN_INFO[stablecoin];
|
|
299
319
|
const OrderSummary = () => ((0, jsx_runtime_1.jsxs)("div", { className: "p-3 rounded bg-neutral-800 border border-neutral-700 space-y-2 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: t("mintQuantity") }), (0, jsx_runtime_1.jsxs)("span", { className: "text-white font-bold font-mono", children: [(miningRequest.mcc_amount / 1000000000).toLocaleString(), " MCC"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: t("payAmount") }), (0, jsx_runtime_1.jsxs)("span", { className: "text-cyan-400 font-bold font-mono", children: [paymentAmount, " ", ci.symbol] })] })] }));
|
|
300
320
|
const TxLink = ({ sig, label }) => ((0, jsx_runtime_1.jsxs)("a", { href: `https://solscan.io/tx/${sig}`, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 text-xs text-cyan-400 hover:underline", children: [label || `${sig.slice(0, 16)}...${sig.slice(-16)}`, " ", (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "w-3 h-3" })] }));
|
|
301
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-50 flex items-end 2xs:items-center justify-center bg-black/50 backdrop-blur-sm font-mono", children: (0, jsx_runtime_1.jsx)("div", { className: "relative w-full max-w-2xl mx-0 2xs:mx-3 xs:mx-4 max-h-[95vh] 2xs:max-h-[90vh] overflow-y-auto rounded-t-2xl 2xs:rounded-xl", children: (0, jsx_runtime_1.jsxs)(terminal_1.TerminalCard, { filename: "mining_request.json", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4 2xs:mb-5 xs:mb-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-base 2xs:text-lg xs:text-xl font-bold text-white mb-1", children: t("title") }), (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] 2xs:text-xs text-neutral-400 tracking-wider", children: t("subtitle") })] }), (0, jsx_runtime_1.jsx)("button", { onClick: handleClose, disabled: loading, className: "text-neutral-400 hover:text-white transition-colors p-1 min-w-[44px] min-h-[44px] flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-5 h-5" }) })] }), step === "input" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [ratioInfo && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 rounded bg-neutral-800 border border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-3 gap-4 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("currentPhase") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-white font-bold font-mono", children: ["Phase ", ratioInfo.current_stage] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1 flex items-center gap-1", children: [t("techBonus"), (0, jsx_runtime_1.jsx)("span", { className: "cursor-help text-neutral-500 hover:text-cyan-400", title: t("techBonusTooltip"), children: "?" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-cyan-400 font-bold font-mono", children: "0%" })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("mintPrice") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-cyan-400 font-bold font-mono", children: ["1 MCC \u2248 ", (ratioInfo.usdc_per_mcc * 4).toFixed(2), " USD"] })] })] }) })), (0, jsx_runtime_1.jsx)("div", { className: "p-4 rounded bg-cyan-400/20 border border-cyan-400/50", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-5 h-5 text-cyan-400 flex-shrink-0 mt-0.5" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-cyan-400 font-bold text-sm mb-1", children: t("solanaOnly") }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-300 text-xs leading-relaxed", children: t("solanaOnlyDescMining") })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("label", { className: "block text-xs text-neutral-400 tracking-wider mb-2", children: [t("paymentMethod"), " ", (0, jsx_runtime_1.jsxs)("span", { className: "text-cyan-400", children: ["(", t("paymentMethodHint"), ")"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setShowStablecoinDropdown(!showStablecoinDropdown), className: "w-full px-4 py-3 bg-neutral-800 border border-neutral-600 rounded text-white flex items-center justify-between hover:border-neutral-500 transition-colors", children: [(0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { children: ci.icon }), (0, jsx_runtime_1.jsx)("span", { children: ci.symbol }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-400 text-sm", children: ["(", ci.name, ")"] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: `w-4 h-4 transition-transform ${showStablecoinDropdown ? 'rotate-180' : ''}` })] }), showStablecoinDropdown && ((0, jsx_runtime_1.jsx)("div", { className: "absolute z-10 w-full mt-1 bg-neutral-900 border border-neutral-700 rounded shadow-lg", children: Object.keys(COIN_INFO).map(type => ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => { setStablecoin(type); setShowStablecoinDropdown(false); }, className: `w-full px-4 py-3 text-left flex items-center gap-2 hover:bg-neutral-800 transition-colors ${stablecoin === type ? 'bg-neutral-800 text-cyan-400' : 'text-white'}`, children: [(0, jsx_runtime_1.jsx)("span", { children: COIN_INFO[type].icon }), (0, jsx_runtime_1.jsx)("span", { children: COIN_INFO[type].symbol }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-400 text-sm", children: ["(", COIN_INFO[type].name, ")"] })] }, type))) }))] }), connected && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2 flex items-center justify-between text-xs", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: t("stablecoinEqual") }), (0, jsx_runtime_1.jsx)("span", { className: `font-medium ${stablecoinBalance === null ? 'text-neutral-400' : stablecoinBalance === 0 ? 'text-red-400' : 'text-white'}`, children: loadingBalance ? t("loading") : stablecoinBalance === null ? t("balanceUnknown") : t("balance", { amount: stablecoinBalance.toFixed(2), symbol: ci.symbol }) })] }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: "block text-xs text-neutral-400 tracking-wider mb-2", children: t("mintAmountLabel", { symbol: "MCC" }) }), (0, jsx_runtime_1.jsx)("input", { type: "number", inputMode: "decimal", value: mccAmount, onChange: e => setMccAmount(e.target.value), placeholder: t("inputPlaceholder", { symbol: "MCC" }), className: "w-full px-3 2xs:px-4 py-3 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 focus:outline-none focus:border-cyan-400 text-base", min: "0", step: "0.01" })] }), mccAmount && parseFloat(mccAmount) > 0 && ratioInfo && ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-cyan-400/20 border border-cyan-400/50 space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-2", children: t("estimatedPayment") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-2xl font-bold text-cyan-400 font-mono", children: [(parseFloat(mccAmount) * ratioInfo.usdc_per_mcc * 4).toFixed(2), " ", ci.symbol] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pt-3 border-t border-cyan-400/30", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: t("youWillReceive") }), (0, jsx_runtime_1.jsxs)("span", { className: "text-lg font-bold text-white font-mono", children: [parseFloat(mccAmount).toFixed(4), " MCC"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 mt-1", children: t("mccToWallet") })] })] })), error && (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 p-3 rounded bg-red-500/20 border border-red-500/50 text-red-500 text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4" }), error] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-3", children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleClose, className: "flex-1 px-4 py-3 border border-neutral-700 text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 bg-transparent rounded transition-colors", children: t("cancel") }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleSubmit, disabled: loading || !mccAmount || parseFloat(mccAmount) <= 0, className: "flex-1 px-4 py-3 bg-cyan-700 hover:bg-cyan-600 text-white rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2", children: [loading && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-4 h-4 animate-spin" }), loading ? t("processing") : t("confirmMint")] })] })] })), step === "paymentMethod" && miningRequest && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsx)("div", { className: "p-3 rounded bg-cyan-500/10 border border-cyan-500/30 text-xs text-cyan-300", children: t("stablecoinReminder", { symbol: ci.symbol }) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider uppercase mb-1", children: t("selectPaymentMethod") }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSelectQrPayment, className: "w-full p-4 rounded border border-neutral-700 bg-neutral-800/30 hover:bg-cyan-400/10 hover:border-cyan-400/70 focus:bg-cyan-400/10 focus:border-cyan-400 focus:outline-none transition-all text-left group", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-lg bg-neutral-700/50 group-hover:bg-cyan-400/20 group-focus:bg-cyan-400/20 transition-colors flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.QrCode, { className: "w-6 h-6 text-neutral-400 group-hover:text-cyan-400 group-focus:text-cyan-400 transition-colors" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-300 group-hover:text-white group-focus:text-white font-bold text-sm transition-colors", children: t("mobileQrScan") }), (0, jsx_runtime_1.jsx)("span", { className: "px-1.5 py-0.5 rounded text-[10px] font-bold bg-cyan-400/20 text-cyan-400 tracking-wider", children: t("recommended") })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-500 group-hover:text-neutral-400 group-focus:text-neutral-400 text-xs mt-1 leading-relaxed transition-colors", children: t("mobileQrDesc") })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.Smartphone, { className: "w-5 h-5 text-neutral-500 group-hover:text-cyan-400 group-focus:text-cyan-400 transition-colors flex-shrink-0" })] }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSelectBrowserPayment, disabled: !connected, className: "w-full p-4 rounded border border-neutral-700 bg-neutral-800/30 hover:bg-cyan-400/10 hover:border-cyan-400/70 focus:bg-cyan-400/10 focus:border-cyan-400 focus:outline-none transition-all text-left group disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-neutral-800/30 disabled:hover:border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-lg bg-neutral-700/50 group-hover:bg-cyan-400/20 group-focus:bg-cyan-400/20 transition-colors flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Monitor, { className: "w-6 h-6 text-neutral-400 group-hover:text-cyan-400 group-focus:text-cyan-400 transition-colors" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-300 group-hover:text-white group-focus:text-white font-bold text-sm transition-colors", children: t("browserExtension") }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-500 group-hover:text-neutral-400 group-focus:text-neutral-400 text-xs mt-1 leading-relaxed transition-colors", children: connected ? t("browserExtConnected") : t("browserExtNotConnected") })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.Monitor, { className: "w-5 h-5 text-neutral-500 group-hover:text-cyan-400 group-focus:text-cyan-400 transition-colors flex-shrink-0" })] }) }), error && (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 p-3 rounded bg-red-500/20 border border-red-500/50 text-red-500 text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4" }), error] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => { setStep("input"); setError(""); }, className: "w-full px-4 py-2 text-neutral-400 hover:text-neutral-300 text-sm transition-colors", children: ["\u2190 ", t("goBack")] })] })), step === "qrPayment" && miningRequest && solanaPayUrl && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-3 2xs:space-y-4", children: [(0, jsx_runtime_1.jsx)(terminal_1.TerminalBadge, { variant: "info", children: t("waitingQrPayment") }), (0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsxs)("div", { className: "p-2 2xs:p-3 rounded bg-amber-500/10 border border-amber-500/30", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-xs 2xs:text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Shield, { className: "w-4 h-4 text-amber-400 flex-shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "text-amber-400 font-bold", children: t("confirmPayWithSymbol", { symbol: ci.symbol }) })] }), (0, jsx_runtime_1.jsxs)("p", { className: "text-neutral-400 text-[10px] 2xs:text-xs mt-1 ml-6", children: [t("insufficientBalance", { symbol: ci.symbol }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { monitorAbortRef.current = true; setStep("input"); setQrMonitoring(false); }, className: "text-cyan-400 hover:underline ml-1", children: t("switchToken") })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center space-y-3 2xs:space-y-4", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-neutral-400 text-xs 2xs:text-sm text-center", children: t("scanQrToPayDesktop") }), (0, jsx_runtime_1.jsx)("div", { className: "bg-white p-3 2xs:p-4 xs:p-5 rounded-xl", children: (0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: solanaPayUrl, size: 200, level: "H", includeMargin: false, className: "w-[160px] h-[160px] 2xs:w-[180px] 2xs:h-[180px] xs:w-[220px] xs:h-[220px] sm:w-[280px] sm:h-[280px]", imageSettings: { src: "/mcc-logo-40.png", x: undefined, y: undefined, height: 40, width: 40, excavate: true } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-[10px] 2xs:text-xs", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-3 h-3 animate-spin" }), t("waitingQrScan")] })] }), qrMonitoring && (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2 text-cyan-400 text-xs 2xs:text-sm py-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-4 h-4 animate-spin" }), t("monitoringOnchain")] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => { monitorAbortRef.current = true; setStep(isMobile ? "input" : "paymentMethod"); setQrMonitoring(false); setError(""); }, className: "w-full px-4 py-2 text-neutral-400 hover:text-neutral-300 text-xs 2xs:text-sm transition-colors min-h-[44px]", children: ["\u2190 ", t("goBack")] })] })), step === "payment" && miningRequest && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(terminal_1.TerminalBadge, { variant: "info", children: t("waitingPayment") }), (0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-8 h-8 animate-spin text-cyan-400" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-center text-neutral-400 text-sm", children: t("processingTransfer", { symbol: ci.symbol }) })] })), step === "confirming" && txSignature && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(terminal_1.TerminalBadge, { variant: "warning", children: t("verifying") }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-8 h-8 animate-spin text-cyan-400" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-center text-neutral-400 text-sm mb-2", children: t("verifyingTransaction") }), (0, jsx_runtime_1.jsxs)("div", { className: "p-3 rounded bg-neutral-800 border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("txSignature") }), (0, jsx_runtime_1.jsxs)("div", { className: "font-mono text-xs text-cyan-400 break-all", children: [txSignature.slice(0, 16), "...", txSignature.slice(-16)] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-2", children: (0, jsx_runtime_1.jsx)(TxLink, { sig: txSignature, label: t("viewOnExplorer") }) })] })] })), step === "success" && confirmationResult && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("div", { className: "w-16 h-16 rounded-full bg-white/10 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { className: "w-8 h-8 text-white" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-xl font-bold text-center text-white", children: t("mintSuccess") }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-white/10 border border-neutral-700 space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("youReceived") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-3xl font-bold text-white font-mono", children: ["+", (confirmationResult.mcc_distributed.user / 1000000000).toLocaleString(), " MCC"] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 mt-1", children: t("sentToWallet") })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pt-3 border-t border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("paymentTx", { symbol: ci.symbol }) }), (0, jsx_runtime_1.jsx)(TxLink, { sig: txSignature })] })] }), confirmationResult.onchain_tx_signature && ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-neutral-800 border border-neutral-700 space-y-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: t("onchainDistribution") }), (0, jsx_runtime_1.jsx)(TxLink, { sig: confirmationResult.onchain_tx_signature })] })), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-3", children: (0, jsx_runtime_1.jsx)("button", { onClick: handleClose, className: "flex-1 px-4 py-3 bg-cyan-700 hover:bg-cyan-600 text-white rounded transition-colors", children: t("doneAndRefresh") }) })] })), step === "error" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-8 h-8 text-red-500" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-xl font-bold text-center text-red-500", children: t("mintFailed") }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 rounded bg-red-500/20 border border-red-500/50", children: (0, jsx_runtime_1.jsx)("p", { className: "text-red-500 text-sm whitespace-pre-line", children: error }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { setStep("input"); setError(""); }, className: "w-full px-4 py-3 border border-neutral-700 text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 bg-transparent rounded transition-colors", children: t("back") })] }))] }) }) }));
|
|
321
|
+
const statusLabel = () => {
|
|
322
|
+
switch (backendStatus) {
|
|
323
|
+
case "created": return t("waitingQrScan");
|
|
324
|
+
case "submitted": return t("paymentReceivedConfirming");
|
|
325
|
+
case "distributing": return t("distributingMcc");
|
|
326
|
+
case "completed": return t("mintSuccess");
|
|
327
|
+
case "failed": return t("mintFailed");
|
|
328
|
+
case "expired": return t("errorPaymentTimeout");
|
|
329
|
+
default: return "";
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
const statusProgress = () => {
|
|
333
|
+
switch (backendStatus) {
|
|
334
|
+
case "created": return 25;
|
|
335
|
+
case "submitted": return 55;
|
|
336
|
+
case "distributing": return 80;
|
|
337
|
+
case "completed": return 100;
|
|
338
|
+
case "failed":
|
|
339
|
+
case "expired": return 0;
|
|
340
|
+
default: return 10;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-50 flex items-end 2xs:items-center justify-center bg-black/50 backdrop-blur-sm font-mono", children: (0, jsx_runtime_1.jsx)("div", { className: "relative w-full max-w-2xl mx-0 2xs:mx-3 xs:mx-4 max-h-[95vh] 2xs:max-h-[90vh] overflow-y-auto rounded-t-2xl 2xs:rounded-xl", children: (0, jsx_runtime_1.jsxs)(terminal_1.TerminalCard, { filename: "mining_request.json", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4 2xs:mb-5 xs:mb-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-base 2xs:text-lg xs:text-xl font-bold text-white mb-1", children: t("title") }), (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] 2xs:text-xs text-neutral-400 tracking-wider", children: t("subtitle") })] }), (0, jsx_runtime_1.jsx)("button", { onClick: handleClose, disabled: loading, className: "text-neutral-400 hover:text-white transition-colors p-1 min-w-[44px] min-h-[44px] flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-5 h-5" }) })] }), showCloseConfirm && ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/70 backdrop-blur-sm p-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-neutral-900 border-2 border-red-500/60 rounded-xl p-5 max-w-md w-full space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertTriangle, { className: "w-6 h-6 text-red-400 flex-shrink-0 mt-0.5" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-white font-bold text-lg mb-2", children: t("closeWarningTitle") }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-300 text-sm leading-relaxed", children: t("closeWarningBody") })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-3", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setShowCloseConfirm(false), className: "flex-1 px-4 py-3 bg-cyan-700 hover:bg-cyan-600 text-white rounded transition-colors font-bold", children: t("closeWarningStay") }), (0, jsx_runtime_1.jsx)("button", { onClick: performClose, className: "flex-1 px-4 py-3 border border-red-500/60 text-red-400 hover:bg-red-500/10 rounded transition-colors", children: t("closeWarningLeave") })] })] }) })), step === "input" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [ratioInfo && ((0, jsx_runtime_1.jsx)("div", { className: "p-3 rounded bg-neutral-800 border border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-3 gap-4 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("currentPhase") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-white font-bold font-mono", children: ["Phase ", ratioInfo.current_stage] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1 flex items-center gap-1", children: [t("techBonus"), (0, jsx_runtime_1.jsx)("span", { className: "cursor-help text-neutral-500 hover:text-cyan-400", title: t("techBonusTooltip"), children: "?" })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-cyan-400 font-bold font-mono", children: "0%" })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("mintPrice") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-cyan-400 font-bold font-mono", children: ["1 MCC \u2248 ", (ratioInfo.usdc_per_mcc * 4).toFixed(2), " USD"] })] })] }) })), (0, jsx_runtime_1.jsx)("div", { className: "p-4 rounded bg-cyan-400/20 border border-cyan-400/50", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-5 h-5 text-cyan-400 flex-shrink-0 mt-0.5" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-cyan-400 font-bold text-sm mb-1", children: t("solanaOnly") }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-300 text-xs leading-relaxed", children: t("solanaOnlyDescMining") })] })] }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("label", { className: "block text-xs text-neutral-400 tracking-wider mb-2", children: [t("paymentMethod"), " ", (0, jsx_runtime_1.jsxs)("span", { className: "text-cyan-400", children: ["(", t("paymentMethodHint"), ")"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setShowStablecoinDropdown(!showStablecoinDropdown), className: "w-full px-4 py-3 bg-neutral-800 border border-neutral-600 rounded text-white flex items-center justify-between hover:border-neutral-500 transition-colors", children: [(0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { children: ci.icon }), (0, jsx_runtime_1.jsx)("span", { children: ci.symbol }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-400 text-sm", children: ["(", ci.name, ")"] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: `w-4 h-4 transition-transform ${showStablecoinDropdown ? 'rotate-180' : ''}` })] }), showStablecoinDropdown && ((0, jsx_runtime_1.jsx)("div", { className: "absolute z-10 w-full mt-1 bg-neutral-900 border border-neutral-700 rounded shadow-lg", children: Object.keys(COIN_INFO).map(type => ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => { setStablecoin(type); setShowStablecoinDropdown(false); }, className: `w-full px-4 py-3 text-left flex items-center gap-2 hover:bg-neutral-800 transition-colors ${stablecoin === type ? 'bg-neutral-800 text-cyan-400' : 'text-white'}`, children: [(0, jsx_runtime_1.jsx)("span", { children: COIN_INFO[type].icon }), (0, jsx_runtime_1.jsx)("span", { children: COIN_INFO[type].symbol }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-400 text-sm", children: ["(", COIN_INFO[type].name, ")"] })] }, type))) }))] }), connected && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2 flex items-center justify-between text-xs", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400", children: t("stablecoinEqual") }), (0, jsx_runtime_1.jsx)("span", { className: `font-medium ${stablecoinBalance === null ? 'text-neutral-400' : stablecoinBalance === 0 ? 'text-red-400' : 'text-white'}`, children: loadingBalance ? t("loading") : stablecoinBalance === null ? t("balanceUnknown") : t("balance", { amount: stablecoinBalance.toFixed(2), symbol: ci.symbol }) })] }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: "block text-xs text-neutral-400 tracking-wider mb-2", children: t("mintAmountLabel", { symbol: "MCC" }) }), (0, jsx_runtime_1.jsx)("input", { type: "number", inputMode: "decimal", value: mccAmount, onChange: e => setMccAmount(e.target.value), placeholder: t("inputPlaceholder", { symbol: "MCC" }), className: "w-full px-3 2xs:px-4 py-3 bg-neutral-800 border border-neutral-600 rounded text-white placeholder-neutral-400 focus:outline-none focus:border-cyan-400 text-base", min: "0", step: "0.01" })] }), mccAmount && parseFloat(mccAmount) > 0 && ratioInfo && ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-cyan-400/20 border border-cyan-400/50 space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-2", children: t("estimatedPayment") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-2xl font-bold text-cyan-400 font-mono", children: [(parseFloat(mccAmount) * ratioInfo.usdc_per_mcc * 4).toFixed(2), " ", ci.symbol] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pt-3 border-t border-cyan-400/30", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-neutral-400 tracking-wider", children: t("youWillReceive") }), (0, jsx_runtime_1.jsxs)("span", { className: "text-lg font-bold text-white font-mono", children: [parseFloat(mccAmount).toFixed(4), " MCC"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 mt-1", children: t("mccToWallet") })] })] })), error && (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 p-3 rounded bg-red-500/20 border border-red-500/50 text-red-500 text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4" }), error] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-3", children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleClose, className: "flex-1 px-4 py-3 border border-neutral-700 text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 bg-transparent rounded transition-colors", children: t("cancel") }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleSubmit, disabled: loading || !mccAmount || parseFloat(mccAmount) <= 0, className: "flex-1 px-4 py-3 bg-cyan-700 hover:bg-cyan-600 text-white rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2", children: [loading && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-4 h-4 animate-spin" }), loading ? t("processing") : t("confirmMint")] })] })] })), step === "paymentMethod" && miningRequest && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsx)("div", { className: "p-3 rounded bg-cyan-500/10 border border-cyan-500/30 text-xs text-cyan-300", children: t("stablecoinReminder", { symbol: ci.symbol }) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider uppercase mb-1", children: t("selectPaymentMethod") }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSelectQrPayment, className: "w-full p-4 rounded border-2 border-cyan-400/50 bg-cyan-400/5 hover:bg-cyan-400/10 hover:border-cyan-400/70 transition-all text-left group", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-lg bg-cyan-400/20 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.QrCode, { className: "w-6 h-6 text-cyan-400" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-white font-bold text-sm", children: t("mobileQrScan") }), (0, jsx_runtime_1.jsx)("span", { className: "px-1.5 py-0.5 rounded text-[10px] font-bold bg-cyan-400/20 text-cyan-400 tracking-wider", children: t("recommended") })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-400 text-xs mt-1 leading-relaxed", children: t("mobileQrDesc") })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.Smartphone, { className: "w-5 h-5 text-neutral-500 group-hover:text-cyan-400 transition-colors flex-shrink-0" })] }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSelectBrowserPayment, disabled: !connected, className: "w-full p-4 rounded border border-neutral-700 bg-neutral-800/50 hover:bg-neutral-800 hover:border-neutral-600 transition-all text-left group disabled:opacity-40 disabled:cursor-not-allowed", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-lg bg-neutral-700/50 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Monitor, { className: "w-6 h-6 text-neutral-400" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-neutral-300 font-bold text-sm", children: t("browserExtension") }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-500 text-xs mt-1 leading-relaxed", children: connected ? t("browserExtConnected") : t("browserExtNotConnected") })] })] }) }), error && (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 p-3 rounded bg-red-500/20 border border-red-500/50 text-red-500 text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4" }), error] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => { setStep("input"); setError(""); }, className: "w-full px-4 py-2 text-neutral-400 hover:text-neutral-300 text-sm transition-colors", children: ["\u2190 ", t("goBack")] })] })), step === "qrPayment" && miningRequest && solanaPayUrl && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-3 2xs:space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p-3 rounded bg-amber-500/15 border-2 border-amber-500/50 flex items-start gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertTriangle, { className: "w-5 h-5 text-amber-400 flex-shrink-0 mt-0.5" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-amber-400 font-bold text-sm mb-1", children: t("doNotClose") }), (0, jsx_runtime_1.jsx)("p", { className: "text-neutral-300 text-xs leading-relaxed", children: t("doNotCloseDesc") })] })] }), (0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-xs", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-neutral-400 tracking-wider", children: statusLabel() }), (0, jsx_runtime_1.jsxs)("span", { className: "text-neutral-500 font-mono", children: [pollElapsedSec, "s"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-2 w-full rounded-full bg-neutral-800 overflow-hidden", children: (0, jsx_runtime_1.jsx)("div", { className: "h-full bg-gradient-to-r from-cyan-500 to-cyan-300 transition-all duration-500 ease-out", style: { width: `${statusProgress()}%` } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-4 gap-1 text-[10px] text-neutral-500", children: [(0, jsx_runtime_1.jsx)("div", { className: `text-center ${backendStatus !== "created" ? "text-cyan-400 font-bold" : ""}`, children: t("stepScan") }), (0, jsx_runtime_1.jsx)("div", { className: `text-center ${backendStatus === "submitted" || backendStatus === "distributing" || backendStatus === "completed" ? "text-cyan-400 font-bold" : ""}`, children: t("stepPaid") }), (0, jsx_runtime_1.jsx)("div", { className: `text-center ${backendStatus === "distributing" || backendStatus === "completed" ? "text-cyan-400 font-bold" : ""}`, children: t("stepDistributing") }), (0, jsx_runtime_1.jsx)("div", { className: `text-center ${backendStatus === "completed" ? "text-cyan-400 font-bold" : ""}`, children: t("stepDone") })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center space-y-3 2xs:space-y-4", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-neutral-400 text-xs 2xs:text-sm text-center", children: t("scanQrToPayDesktop") }), (0, jsx_runtime_1.jsx)("div", { className: "bg-white p-3 2xs:p-4 xs:p-5 rounded-xl", children: (0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: solanaPayUrl, size: 200, level: "H", includeMargin: false, className: "w-[160px] h-[160px] 2xs:w-[180px] 2xs:h-[180px] xs:w-[220px] xs:h-[220px] sm:w-[280px] sm:h-[280px]", imageSettings: { src: "/mcc-logo-40.png", x: undefined, y: undefined, height: 40, width: 40, excavate: true } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-neutral-400 text-[10px] 2xs:text-xs", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-3 h-3 animate-spin" }), backendStatus === "created" ? t("waitingQrScan") : t("monitoringOnchain")] })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => { stopStatusPolling(); setStep(isMobile ? "input" : "paymentMethod"); setError(""); }, className: "w-full px-4 py-2 text-neutral-400 hover:text-neutral-300 text-xs 2xs:text-sm transition-colors min-h-[44px]", children: ["\u2190 ", t("goBack")] })] })), step === "payment" && miningRequest && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(terminal_1.TerminalBadge, { variant: "info", children: t("waitingPayment") }), (0, jsx_runtime_1.jsx)(OrderSummary, {}), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-8 h-8 animate-spin text-cyan-400" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-center text-neutral-400 text-sm", children: t("processingTransfer", { symbol: ci.symbol }) })] })), step === "confirming" && txSignature && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)(terminal_1.TerminalBadge, { variant: "warning", children: t("verifying") }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "w-8 h-8 animate-spin text-cyan-400" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-center text-neutral-400 text-sm mb-2", children: t("verifyingTransaction") }), (0, jsx_runtime_1.jsxs)("div", { className: "p-3 rounded bg-neutral-800 border border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("txSignature") }), (0, jsx_runtime_1.jsxs)("div", { className: "font-mono text-xs text-cyan-400 break-all", children: [txSignature.slice(0, 16), "...", txSignature.slice(-16)] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-2", children: (0, jsx_runtime_1.jsx)(TxLink, { sig: txSignature, label: t("viewOnExplorer") }) })] })] })), step === "success" && confirmationResult && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("div", { className: "w-16 h-16 rounded-full bg-white/10 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { className: "w-8 h-8 text-white" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-xl font-bold text-center text-white", children: t("mintSuccess") }), (0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-white/10 border border-neutral-700 space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("youReceived") }), (0, jsx_runtime_1.jsxs)("div", { className: "text-3xl font-bold text-white font-mono", children: ["+", (confirmationResult.mcc_distributed.user / 1000000000).toLocaleString(), " MCC"] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 mt-1", children: t("sentToWallet") })] }), txSignature && ((0, jsx_runtime_1.jsxs)("div", { className: "pt-3 border-t border-neutral-700", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider mb-1", children: t("paymentTx", { symbol: ci.symbol }) }), (0, jsx_runtime_1.jsx)(TxLink, { sig: txSignature })] }))] }), confirmationResult.onchain_tx_signature && ((0, jsx_runtime_1.jsxs)("div", { className: "p-4 rounded bg-neutral-800 border border-neutral-700 space-y-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-xs text-neutral-400 tracking-wider", children: t("onchainDistribution") }), (0, jsx_runtime_1.jsx)(TxLink, { sig: confirmationResult.onchain_tx_signature })] })), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-3", children: (0, jsx_runtime_1.jsx)("button", { onClick: performClose, className: "flex-1 px-4 py-3 bg-cyan-700 hover:bg-cyan-600 text-white rounded transition-colors", children: t("doneAndRefresh") }) })] })), step === "error" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-8", children: (0, jsx_runtime_1.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-8 h-8 text-red-500" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-xl font-bold text-center text-red-500", children: t("mintFailed") }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 rounded bg-red-500/20 border border-red-500/50", children: (0, jsx_runtime_1.jsx)("p", { className: "text-red-500 text-sm whitespace-pre-line", children: error }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { setStep("input"); setError(""); }, className: "w-full px-4 py-3 border border-neutral-700 text-neutral-400 hover:bg-neutral-800 hover:text-neutral-300 bg-transparent rounded transition-colors", children: t("back") })] }))] }) }) }));
|
|
302
344
|
}
|
|
@@ -43,12 +43,22 @@ export declare const getX402MiningHistory: (limit?: number, offset?: number) =>
|
|
|
43
43
|
}>>;
|
|
44
44
|
export declare const getMiningRequestStatus: (requestId: string) => Promise<APIResponse<{
|
|
45
45
|
request_id: string;
|
|
46
|
-
status: "
|
|
46
|
+
status: "created" | "submitted" | "distributing" | "completed" | "failed" | "expired";
|
|
47
47
|
mcc_amount: number;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
payment_amount: number;
|
|
49
|
+
stablecoin_type: string;
|
|
50
|
+
payer_wallet?: string;
|
|
51
|
+
payment_tx_signature?: string;
|
|
52
|
+
onchain_tx_signature?: string;
|
|
53
|
+
mcc_distributed?: {
|
|
54
|
+
user: number;
|
|
55
|
+
lp_reserve: number;
|
|
56
|
+
magistrate: number;
|
|
57
|
+
station_mcd: number;
|
|
58
|
+
};
|
|
59
|
+
error?: string;
|
|
60
|
+
created_at?: string;
|
|
61
|
+
updated_at?: string;
|
|
52
62
|
}>>;
|
|
53
63
|
export interface MiningPreflightResult {
|
|
54
64
|
ready: boolean;
|
|
@@ -39,7 +39,7 @@ const getX402MiningHistory = (limit = 20, offset = 0) => {
|
|
|
39
39
|
};
|
|
40
40
|
exports.getX402MiningHistory = getX402MiningHistory;
|
|
41
41
|
const getMiningRequestStatus = (requestId) => {
|
|
42
|
-
return (0, core_1.fetchApi)(`/blockchain-service/mining/request/${requestId}`);
|
|
42
|
+
return (0, core_1.fetchApi)(`/blockchain-service/mining/request/${requestId}/status`);
|
|
43
43
|
};
|
|
44
44
|
exports.getMiningRequestStatus = getMiningRequestStatus;
|
|
45
45
|
const getPublicMiningPreflight = async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microcosmmoney/portal-react",
|
|
3
|
-
"version": "3.13.
|
|
3
|
+
"version": "3.13.8",
|
|
4
4
|
"description": "Microcosm Portal UI components for React/Next.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -82,4 +82,4 @@
|
|
|
82
82
|
"type": "git",
|
|
83
83
|
"url": "https://github.com/MicrocosmMoney/Microcosm"
|
|
84
84
|
}
|
|
85
|
-
}
|
|
85
|
+
}
|