remove wallet functionality
This commit is contained in:
@@ -1,9 +1,6 @@
|
|||||||
# API origin. Leave empty for same-origin/local Vite proxy.
|
# API origin. Leave empty for same-origin/local Vite proxy.
|
||||||
VITE_API_URL=
|
VITE_API_URL=
|
||||||
|
|
||||||
# Reown / WalletConnect project id. Required for WalletConnect QR/mobile login.
|
|
||||||
VITE_WALLETCONNECT_PROJECT_ID=
|
|
||||||
|
|
||||||
# Public production deploy disables admin routes.
|
# Public production deploy disables admin routes.
|
||||||
VITE_DISABLE_ADMIN=false
|
VITE_DISABLE_ADMIN=false
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ This file is the first-stop context for AI coding agents working in this repo.
|
|||||||
|
|
||||||
- Project: Arkie Library Frontend / ARK database web UI.
|
- Project: Arkie Library Frontend / ARK database web UI.
|
||||||
- Package name: `ark-database-web`.
|
- Package name: `ark-database-web`.
|
||||||
- Stack: React 18, TypeScript, Vite, Tailwind CSS, React Router, RainbowKit/Wagmi.
|
- Stack: React 18, TypeScript, Vite, Tailwind CSS, React Router.
|
||||||
- Backend API is expected at `/api`; uploaded assets under `/uploads`.
|
- Backend API is expected at `/api`; uploaded assets under `/uploads`.
|
||||||
|
|
||||||
## Branch rules
|
## Branch rules
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-alpine AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG VITE_WALLETCONNECT_PROJECT_ID=
|
|
||||||
ARG VITE_API_URL=
|
ARG VITE_API_URL=
|
||||||
ARG VITE_ADMIN_UI_PREFIX=
|
ARG VITE_ADMIN_UI_PREFIX=
|
||||||
ARG VITE_ADMIN_ONLY=
|
ARG VITE_ADMIN_ONLY=
|
||||||
ARG VITE_DISABLE_ADMIN=
|
ARG VITE_DISABLE_ADMIN=
|
||||||
ENV VITE_WALLETCONNECT_PROJECT_ID=$VITE_WALLETCONNECT_PROJECT_ID
|
|
||||||
ENV VITE_API_URL=$VITE_API_URL
|
ENV VITE_API_URL=$VITE_API_URL
|
||||||
ENV VITE_ADMIN_UI_PREFIX=$VITE_ADMIN_UI_PREFIX
|
ENV VITE_ADMIN_UI_PREFIX=$VITE_ADMIN_UI_PREFIX
|
||||||
ENV VITE_ADMIN_ONLY=$VITE_ADMIN_ONLY
|
ENV VITE_ADMIN_ONLY=$VITE_ADMIN_ONLY
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Arkie Library Frontend
|
# Arkie Library Frontend
|
||||||
|
|
||||||
React + Vite frontend for the ARK Library / ARK database site. The app serves public resource browsing, search, favorites, wallet login UI, and an optional admin UI for resource management.
|
React + Vite frontend for the ARK Library / ARK database site. The app serves public resource browsing, search, favorites, and an optional admin UI for resource management.
|
||||||
|
|
||||||
## Tech stack
|
## Tech stack
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ React + Vite frontend for the ARK Library / ARK database site. The app serves pu
|
|||||||
- Vite 5
|
- Vite 5
|
||||||
- React Router
|
- React Router
|
||||||
- Tailwind CSS
|
- Tailwind CSS
|
||||||
- RainbowKit / Wagmi / Viem for wallet connection
|
|
||||||
- Gitea Actions deploy workflow on `main`
|
- Gitea Actions deploy workflow on `main`
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
@@ -54,7 +53,6 @@ Create a local `.env` only when needed. Do not commit secrets. See `.env.example
|
|||||||
| Variable | Purpose |
|
| Variable | Purpose |
|
||||||
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `VITE_API_URL` | API/upload origin. Empty means same-origin and Vite dev proxy handles local `/api` and `/uploads`. Production deploy currently uses `https://api.ark-library.com`. |
|
| `VITE_API_URL` | API/upload origin. Empty means same-origin and Vite dev proxy handles local `/api` and `/uploads`. Production deploy currently uses `https://api.ark-library.com`. |
|
||||||
| `VITE_WALLETCONNECT_PROJECT_ID` | Reown / WalletConnect project id. Needed for QR/mobile wallet connection. |
|
|
||||||
| `VITE_DISABLE_ADMIN` | When set to `"true"`, public build redirects admin routes away. Production public deploy sets this to `"true"`. |
|
| `VITE_DISABLE_ADMIN` | When set to `"true"`, public build redirects admin routes away. Production public deploy sets this to `"true"`. |
|
||||||
| `VITE_ADMIN_ONLY` | When set to `"true"`, builds the admin-only app entry instead of the public app. |
|
| `VITE_ADMIN_ONLY` | When set to `"true"`, builds the admin-only app entry instead of the public app. |
|
||||||
| `VITE_ADMIN_UI_PREFIX` | Optional admin UI base path. If absent in admin-only mode, code uses the secret prefix from `src/adminPaths.ts`. |
|
| `VITE_ADMIN_UI_PREFIX` | Optional admin UI base path. If absent in admin-only mode, code uses the secret prefix from `src/adminPaths.ts`. |
|
||||||
|
|||||||
7847
package-lock.json
generated
7847
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,14 +13,10 @@
|
|||||||
"test:watch": "vitest"
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rainbow-me/rainbowkit": "^2.2.11",
|
|
||||||
"@tanstack/react-query": "^5.100.9",
|
|
||||||
"lucide-react": "^0.460.0",
|
"lucide-react": "^0.460.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^6.28.0"
|
||||||
"viem": "^2.48.11",
|
|
||||||
"wagmi": "^2.19.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
|
|||||||
15
src/App.tsx
15
src/App.tsx
@@ -1,4 +1,3 @@
|
|||||||
import { lazy, Suspense } from "react";
|
|
||||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||||
import { I18nProvider } from "./i18n";
|
import { I18nProvider } from "./i18n";
|
||||||
import { PublicLayout } from "./layouts/PublicLayout";
|
import { PublicLayout } from "./layouts/PublicLayout";
|
||||||
@@ -14,12 +13,6 @@ import { AdminRouterModeProvider } from "./adminRouterMode";
|
|||||||
import { ImageLightboxProvider } from "./components/messageStream/overlays/ImageLightbox";
|
import { ImageLightboxProvider } from "./components/messageStream/overlays/ImageLightbox";
|
||||||
import { VideoPlayerProvider } from "./components/messageStream/overlays/VideoPlayer";
|
import { VideoPlayerProvider } from "./components/messageStream/overlays/VideoPlayer";
|
||||||
|
|
||||||
const WalletPage = lazy(() =>
|
|
||||||
import("./pages/Wallet").then((module) => ({
|
|
||||||
default: module.WalletPage,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
const adminEnabled = import.meta.env.VITE_DISABLE_ADMIN !== "true";
|
const adminEnabled = import.meta.env.VITE_DISABLE_ADMIN !== "true";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
@@ -36,14 +29,6 @@ export default function App() {
|
|||||||
<Route path="/category/:slug" element={<CategoryPage />} />
|
<Route path="/category/:slug" element={<CategoryPage />} />
|
||||||
<Route path="/search" element={<SearchPage />} />
|
<Route path="/search" element={<SearchPage />} />
|
||||||
<Route path="/resource/:id" element={<PostRedirect />} />
|
<Route path="/resource/:id" element={<PostRedirect />} />
|
||||||
<Route
|
|
||||||
path="/wallet"
|
|
||||||
element={
|
|
||||||
<Suspense fallback={null}>
|
|
||||||
<WalletPage />
|
|
||||||
</Suspense>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route path="/about" element={<AboutPage />} />
|
<Route path="/about" element={<AboutPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
|||||||
@@ -1,127 +0,0 @@
|
|||||||
import { ConnectButton } from "@rainbow-me/rainbowkit";
|
|
||||||
import { useAccount, useDisconnect, useSignMessage } from "wagmi";
|
|
||||||
import { useCallback, useEffect, useState } from "react";
|
|
||||||
import { postJSON, apiBase } from "../api";
|
|
||||||
import {
|
|
||||||
clearWalletToken,
|
|
||||||
getWalletToken,
|
|
||||||
setWalletToken,
|
|
||||||
} from "../walletToken";
|
|
||||||
import { useI18n } from "../i18n";
|
|
||||||
|
|
||||||
export function WalletLoginControls() {
|
|
||||||
const { t } = useI18n();
|
|
||||||
const { address, isConnected } = useAccount();
|
|
||||||
const { disconnectAsync } = useDisconnect();
|
|
||||||
const { signMessageAsync, isPending: signing } = useSignMessage();
|
|
||||||
const [busy, setBusy] = useState(false);
|
|
||||||
const [err, setErr] = useState<string | null>(null);
|
|
||||||
const [sessionOk, setSessionOk] = useState(false);
|
|
||||||
|
|
||||||
const checkSession = useCallback(async () => {
|
|
||||||
const tok = getWalletToken();
|
|
||||||
if (!tok || !address) {
|
|
||||||
setSessionOk(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const r = await fetch(`${apiBase}/api/auth/wallet/me`, {
|
|
||||||
headers: { Authorization: `Bearer ${tok}` },
|
|
||||||
});
|
|
||||||
if (!r.ok) {
|
|
||||||
clearWalletToken();
|
|
||||||
setSessionOk(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const j = (await r.json()) as { wallet: string };
|
|
||||||
setSessionOk(j.wallet?.toLowerCase() === address.toLowerCase());
|
|
||||||
} catch {
|
|
||||||
setSessionOk(false);
|
|
||||||
}
|
|
||||||
}, [address]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
void checkSession();
|
|
||||||
}, [checkSession]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!address) clearWalletToken();
|
|
||||||
}, [address]);
|
|
||||||
|
|
||||||
const signIn = async () => {
|
|
||||||
if (!address) return;
|
|
||||||
setErr(null);
|
|
||||||
setBusy(true);
|
|
||||||
try {
|
|
||||||
const nonceRes = await postJSON<{ message: string }>(
|
|
||||||
"/api/auth/wallet/nonce",
|
|
||||||
{ address },
|
|
||||||
);
|
|
||||||
const sig = await signMessageAsync({ message: nonceRes.message });
|
|
||||||
const out = await postJSON<{ token: string }>("/api/auth/wallet/verify", {
|
|
||||||
address,
|
|
||||||
message: nonceRes.message,
|
|
||||||
signature: sig,
|
|
||||||
});
|
|
||||||
setWalletToken(out.token);
|
|
||||||
setSessionOk(true);
|
|
||||||
} catch (e) {
|
|
||||||
setErr(String(e));
|
|
||||||
} finally {
|
|
||||||
setBusy(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const signOut = async () => {
|
|
||||||
clearWalletToken();
|
|
||||||
setSessionOk(false);
|
|
||||||
await disconnectAsync();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!import.meta.env.VITE_WALLETCONNECT_PROJECT_ID) {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className="text-xs text-amber-500/90 max-w-[220px] text-right leading-tight"
|
|
||||||
title={t("walletMissingProjectId")}
|
|
||||||
>
|
|
||||||
{t("walletSetupNeeded")}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-end gap-1 min-w-[200px]">
|
|
||||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
|
||||||
<ConnectButton chainStatus="icon" showBalance={false} />
|
|
||||||
{isConnected && address ? (
|
|
||||||
sessionOk ? (
|
|
||||||
<span className="text-xs text-ark-gold2 whitespace-nowrap">
|
|
||||||
{t("walletSignedIn")}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
disabled={busy || signing}
|
|
||||||
onClick={() => void signIn()}
|
|
||||||
className="rounded-lg border border-ark-gold bg-ark-gold/10 px-3 py-1.5 text-xs font-medium text-ark-gold2 hover:bg-ark-gold/20 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
{busy || signing ? "…" : t("signInWallet")}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
{isConnected && sessionOk ? (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => void signOut()}
|
|
||||||
className="text-xs text-neutral-500 hover:text-white"
|
|
||||||
>
|
|
||||||
{t("walletLogout")}
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
{err ? (
|
|
||||||
<p className="text-xs text-red-400 max-w-xs text-right">{err}</p>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
33
src/i18n.tsx
33
src/i18n.tsx
@@ -33,7 +33,6 @@ const zhDict: Dict = {
|
|||||||
preview: "预览",
|
preview: "预览",
|
||||||
download: "下载",
|
download: "下载",
|
||||||
share: "分享",
|
share: "分享",
|
||||||
profile: "个人中心",
|
|
||||||
langLabel: "语言",
|
langLabel: "语言",
|
||||||
admin: "后台",
|
admin: "后台",
|
||||||
login: "登录",
|
login: "登录",
|
||||||
@@ -67,21 +66,6 @@ const zhDict: Dict = {
|
|||||||
total: "总资料",
|
total: "总资料",
|
||||||
views: "浏览",
|
views: "浏览",
|
||||||
downloads: "下载",
|
downloads: "下载",
|
||||||
wallet: "钱包",
|
|
||||||
walletPageTitle: "钱包登录",
|
|
||||||
walletPageIntro:
|
|
||||||
"连接 Web3 钱包以使用会员相关功能。采用标准签名登录,不发送交易、不消耗 gas。",
|
|
||||||
walletStepExtension:
|
|
||||||
"电脑已安装浏览器扩展钱包(如 MetaMask)时,可直接连接。",
|
|
||||||
walletStepQR:
|
|
||||||
"电脑未安装钱包时:在连接窗口选择 WalletConnect,用手机钱包扫描 QR Code。",
|
|
||||||
walletStepSign: "连接成功后,点击「签署登录」并在钱包内签名即可完成验证。",
|
|
||||||
signInWallet: "签署登录",
|
|
||||||
walletSignedIn: "已验证登录",
|
|
||||||
walletLogout: "退出钱包",
|
|
||||||
walletMissingProjectId:
|
|
||||||
"请配置 VITE_WALLETCONNECT_PROJECT_ID(Reown Cloud),否则无法使用 WalletConnect/扫码。",
|
|
||||||
walletSetupNeeded: "钱包扫码未启用(请在服务器配置环境变量)",
|
|
||||||
lang_zh_CN: "中文",
|
lang_zh_CN: "中文",
|
||||||
lang_en: "English",
|
lang_en: "English",
|
||||||
lang_ja: "日本語",
|
lang_ja: "日本語",
|
||||||
@@ -158,7 +142,6 @@ const enDict: Dict = {
|
|||||||
preview: "Preview",
|
preview: "Preview",
|
||||||
download: "Download",
|
download: "Download",
|
||||||
share: "Share",
|
share: "Share",
|
||||||
profile: "Profile",
|
|
||||||
langLabel: "Language",
|
langLabel: "Language",
|
||||||
admin: "Admin",
|
admin: "Admin",
|
||||||
login: "Sign in",
|
login: "Sign in",
|
||||||
@@ -192,22 +175,6 @@ const enDict: Dict = {
|
|||||||
total: "Total items",
|
total: "Total items",
|
||||||
views: "Views",
|
views: "Views",
|
||||||
downloads: "Downloads",
|
downloads: "Downloads",
|
||||||
wallet: "Wallet",
|
|
||||||
walletPageTitle: "Wallet sign-in",
|
|
||||||
walletPageIntro:
|
|
||||||
"Connect a Web3 wallet for member features. This uses a standard signed message — no transaction and no gas.",
|
|
||||||
walletStepExtension:
|
|
||||||
"On desktop with a browser extension (e.g. MetaMask), connect directly.",
|
|
||||||
walletStepQR:
|
|
||||||
"On desktop without an extension: choose WalletConnect in the modal and scan the QR code with your mobile wallet.",
|
|
||||||
walletStepSign:
|
|
||||||
'After connecting, tap "Sign in" and approve the message in your wallet to verify.',
|
|
||||||
signInWallet: "Sign in",
|
|
||||||
walletSignedIn: "Signed in",
|
|
||||||
walletLogout: "Disconnect",
|
|
||||||
walletMissingProjectId:
|
|
||||||
"Set VITE_WALLETCONNECT_PROJECT_ID (free on Reown Cloud). Required for WalletConnect / QR login.",
|
|
||||||
walletSetupNeeded: "Wallet QR login disabled (set env on server)",
|
|
||||||
lang_zh_CN: "Chinese",
|
lang_zh_CN: "Chinese",
|
||||||
lang_en: "English",
|
lang_en: "English",
|
||||||
lang_ja: "Japanese",
|
lang_ja: "Japanese",
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ type PublicNavWhich =
|
|||||||
| "browseLatest"
|
| "browseLatest"
|
||||||
| "browseRecommended"
|
| "browseRecommended"
|
||||||
| "browsePopular"
|
| "browsePopular"
|
||||||
| "wallet"
|
|
||||||
| "about";
|
| "about";
|
||||||
|
|
||||||
function navIsActive(
|
function navIsActive(
|
||||||
@@ -43,8 +42,6 @@ function navIsActive(
|
|||||||
return pathname === "/browse" && sp.get("sort") === "recommended";
|
return pathname === "/browse" && sp.get("sort") === "recommended";
|
||||||
case "browsePopular":
|
case "browsePopular":
|
||||||
return pathname === "/browse" && sp.get("sort") === "popular";
|
return pathname === "/browse" && sp.get("sort") === "popular";
|
||||||
case "wallet":
|
|
||||||
return pathname === "/wallet";
|
|
||||||
case "about":
|
case "about":
|
||||||
return pathname === "/about";
|
return pathname === "/about";
|
||||||
default:
|
default:
|
||||||
@@ -240,13 +237,6 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("popular")}
|
{t("popular")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to="/wallet"
|
|
||||||
className={navClassName(na("wallet"))}
|
|
||||||
aria-current={na("wallet") ? "page" : undefined}
|
|
||||||
>
|
|
||||||
{t("wallet")}
|
|
||||||
</Link>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
|
<div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
|
||||||
@@ -344,14 +334,6 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("popular")}
|
{t("popular")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to="/wallet"
|
|
||||||
className={navClassName(na("wallet"))}
|
|
||||||
aria-current={na("wallet") ? "page" : undefined}
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
>
|
|
||||||
{t("wallet")}
|
|
||||||
</Link>
|
|
||||||
<Link
|
<Link
|
||||||
to="/about"
|
to="/about"
|
||||||
className={navClassName(na("about"))}
|
className={navClassName(na("about"))}
|
||||||
@@ -376,12 +358,6 @@ export function PublicLayout() {
|
|||||||
>
|
>
|
||||||
{t("footerAbout")}
|
{t("footerAbout")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to="/wallet"
|
|
||||||
className="rounded-sm outline-none hover:text-ark-gold2 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg"
|
|
||||||
>
|
|
||||||
{t("profile")}
|
|
||||||
</Link>
|
|
||||||
{import.meta.env.VITE_DISABLE_ADMIN !== "true" ? (
|
{import.meta.env.VITE_DISABLE_ADMIN !== "true" ? (
|
||||||
<Link
|
<Link
|
||||||
to={`${adminUiPrefix}/login`}
|
to={`${adminUiPrefix}/login`}
|
||||||
@@ -443,7 +419,7 @@ function BottomNavIcon({
|
|||||||
}: {
|
}: {
|
||||||
to: string;
|
to: string;
|
||||||
label: string;
|
label: string;
|
||||||
icon: "home" | "document" | "heart" | "profile" | "update";
|
icon: "home" | "document" | "heart" | "update";
|
||||||
active: boolean;
|
active: boolean;
|
||||||
}) {
|
}) {
|
||||||
const src = active
|
const src = active
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
|
||||||
|
|
||||||
const adminOnly = import.meta.env.VITE_ADMIN_ONLY === "true";
|
const adminOnly = import.meta.env.VITE_ADMIN_ONLY === "true";
|
||||||
|
|
||||||
void (async () => {
|
void (async () => {
|
||||||
@@ -23,9 +20,7 @@ void (async () => {
|
|||||||
const { default: App } = await import("./App");
|
const { default: App } = await import("./App");
|
||||||
ReactDOM.createRoot(root).render(
|
ReactDOM.createRoot(root).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<QueryClientProvider client={queryClient}>
|
<App />
|
||||||
<App />
|
|
||||||
</QueryClientProvider>
|
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
|
|
||||||
import { WagmiProvider } from "wagmi";
|
|
||||||
import "@rainbow-me/rainbowkit/styles.css";
|
|
||||||
import { WalletLoginControls } from "../../components/WalletLoginControls";
|
|
||||||
import { useI18n } from "../../i18n";
|
|
||||||
import { wagmiConfig } from "../../wagmiConfig";
|
|
||||||
|
|
||||||
export function WalletPage() {
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="mx-auto max-w-lg space-y-6">
|
|
||||||
<h1 className="text-2xl font-bold">{t("walletPageTitle")}</h1>
|
|
||||||
<p className="text-neutral-300 text-sm leading-relaxed">
|
|
||||||
{t("walletPageIntro")}
|
|
||||||
</p>
|
|
||||||
<ul className="text-sm text-neutral-400 space-y-2 list-disc pl-5">
|
|
||||||
<li>{t("walletStepExtension")}</li>
|
|
||||||
<li>{t("walletStepQR")}</li>
|
|
||||||
<li>{t("walletStepSign")}</li>
|
|
||||||
</ul>
|
|
||||||
<div className="rounded-2xl border border-ark-line bg-ark-panel p-6 space-y-4">
|
|
||||||
{import.meta.env.VITE_WALLETCONNECT_PROJECT_ID ? (
|
|
||||||
<WagmiProvider config={wagmiConfig}>
|
|
||||||
<RainbowKitProvider
|
|
||||||
theme={darkTheme({
|
|
||||||
accentColor: "#d4af37",
|
|
||||||
accentColorForeground: "#0a0a0a",
|
|
||||||
borderRadius: "medium",
|
|
||||||
})}
|
|
||||||
modalSize="wide"
|
|
||||||
>
|
|
||||||
<WalletLoginControls />
|
|
||||||
</RainbowKitProvider>
|
|
||||||
</WagmiProvider>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="text-sm text-amber-500/90 leading-relaxed"
|
|
||||||
title={t("walletMissingProjectId")}
|
|
||||||
>
|
|
||||||
{t("walletSetupNeeded")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@@ -3,7 +3,6 @@
|
|||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_API_URL: string;
|
readonly VITE_API_URL: string;
|
||||||
readonly VITE_API_PREFIX?: string;
|
readonly VITE_API_PREFIX?: string;
|
||||||
readonly VITE_WALLETCONNECT_PROJECT_ID: string;
|
|
||||||
readonly VITE_ADMIN_UI_PREFIX?: string;
|
readonly VITE_ADMIN_UI_PREFIX?: string;
|
||||||
/** When `"true"`, bundle admin UI only (no public pages); use with `VITE_ADMIN_UI_PREFIX` or default secret prefix. */
|
/** When `"true"`, bundle admin UI only (no public pages); use with `VITE_ADMIN_UI_PREFIX` or default secret prefix. */
|
||||||
readonly VITE_ADMIN_ONLY?: string;
|
readonly VITE_ADMIN_ONLY?: string;
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
|
|
||||||
import { arbitrum, bsc, mainnet, polygon, sepolia } from "wagmi/chains";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a free Project ID: https://cloud.reown.com (WalletConnect / Reown)
|
|
||||||
* Without it, WalletConnect (mobile / QR on desktop) will not work; browser extensions may still work in some setups.
|
|
||||||
*/
|
|
||||||
const projectId = import.meta.env.VITE_WALLETCONNECT_PROJECT_ID || "";
|
|
||||||
|
|
||||||
export const wagmiConfig = getDefaultConfig({
|
|
||||||
appName: "ARK Database",
|
|
||||||
projectId: projectId || "00000000000000000000000000000000",
|
|
||||||
chains: [mainnet, bsc, arbitrum, polygon, sepolia],
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
const KEY = "ark_wallet_token";
|
|
||||||
|
|
||||||
export function getWalletToken() {
|
|
||||||
return localStorage.getItem(KEY) || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setWalletToken(t: string) {
|
|
||||||
localStorage.setItem(KEY, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function clearWalletToken() {
|
|
||||||
localStorage.removeItem(KEY);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user