mirror of
https://github.com/Such-Software/smirk-website.git
synced 2026-10-17 05:51:28 +02:00
add ToS to website
This commit is contained in:
@@ -26,6 +26,10 @@ export default function RootLayout({
|
|||||||
Privacy Policy
|
Privacy Policy
|
||||||
</a>
|
</a>
|
||||||
<span className="text-zinc-700">•</span>
|
<span className="text-zinc-700">•</span>
|
||||||
|
<a href="/terms" className="hover:text-[#fbeb0a] transition-colors">
|
||||||
|
Terms of Service
|
||||||
|
</a>
|
||||||
|
<span className="text-zinc-700">•</span>
|
||||||
<span>
|
<span>
|
||||||
Made & Hosted by{" "}
|
Made & Hosted by{" "}
|
||||||
<a
|
<a
|
||||||
|
|||||||
+70
-90
@@ -6,7 +6,7 @@ import Link from 'next/link';
|
|||||||
import {
|
import {
|
||||||
getMe,
|
getMe,
|
||||||
getLinkedSocials,
|
getLinkedSocials,
|
||||||
registerSocial,
|
initiateLink,
|
||||||
unlinkSocial,
|
unlinkSocial,
|
||||||
getMyUsername,
|
getMyUsername,
|
||||||
setUsername,
|
setUsername,
|
||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
type LinkedSocial,
|
type LinkedSocial,
|
||||||
} from '@/lib/api';
|
} from '@/lib/api';
|
||||||
|
|
||||||
type LinkStep = 'idle' | 'entering' | 'verifying';
|
type LinkStep = 'idle' | 'linking' | 'waiting';
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const [user, setUser] = useState<MeResponse | null>(null);
|
const [user, setUser] = useState<MeResponse | null>(null);
|
||||||
@@ -31,10 +31,9 @@ export default function SettingsPage() {
|
|||||||
|
|
||||||
// Telegram linking state
|
// Telegram linking state
|
||||||
const [linkStep, setLinkStep] = useState<LinkStep>('idle');
|
const [linkStep, setLinkStep] = useState<LinkStep>('idle');
|
||||||
const [telegramUsername, setTelegramUsername] = useState('');
|
const [deepLink, setDeepLink] = useState<string | null>(null);
|
||||||
const [verificationCode, setVerificationCode] = useState<string | null>(null);
|
|
||||||
const [botLink, setBotLink] = useState<string | null>(null);
|
|
||||||
const [linkError, setLinkError] = useState<string | null>(null);
|
const [linkError, setLinkError] = useState<string | null>(null);
|
||||||
|
const [polling, setPolling] = useState(false);
|
||||||
|
|
||||||
const token = typeof window !== 'undefined' ? localStorage.getItem('smirk_token') : null;
|
const token = typeof window !== 'undefined' ? localStorage.getItem('smirk_token') : null;
|
||||||
|
|
||||||
@@ -81,25 +80,51 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStartLink = () => {
|
const handleStartLink = async () => {
|
||||||
setLinkStep('entering');
|
if (!token) return;
|
||||||
|
setLinkStep('linking');
|
||||||
setLinkError(null);
|
setLinkError(null);
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmitUsername = async () => {
|
|
||||||
if (!token || !telegramUsername.trim()) return;
|
|
||||||
|
|
||||||
setLinkError(null);
|
|
||||||
try {
|
try {
|
||||||
const result = await registerSocial(token, 'telegram', telegramUsername.trim());
|
const result = await initiateLink(token, 'telegram');
|
||||||
setVerificationCode(result.verification_code);
|
setDeepLink(result.deep_link);
|
||||||
setBotLink(result.bot_link);
|
setLinkStep('waiting');
|
||||||
setLinkStep('verifying');
|
// Start polling for verification
|
||||||
|
startPolling();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLinkError(err instanceof Error ? err.message : 'Failed to start verification');
|
setLinkError(err instanceof Error ? err.message : 'Failed to initiate link');
|
||||||
|
setLinkStep('idle');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const startPolling = () => {
|
||||||
|
if (polling) return;
|
||||||
|
setPolling(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Polling effect for verification status
|
||||||
|
useEffect(() => {
|
||||||
|
if (!polling || !token) return;
|
||||||
|
|
||||||
|
const interval = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const socialsData = await getLinkedSocials(token);
|
||||||
|
setSocials(socialsData.socials);
|
||||||
|
const telegram = socialsData.socials.find((s) => s.platform === 'telegram');
|
||||||
|
if (telegram?.verified) {
|
||||||
|
// Success! Stop polling and reset state
|
||||||
|
setPolling(false);
|
||||||
|
setLinkStep('idle');
|
||||||
|
setDeepLink(null);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore polling errors, keep trying
|
||||||
|
}
|
||||||
|
}, 3000); // Poll every 3 seconds
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [polling, token]);
|
||||||
|
|
||||||
const handleUnlink = async (platform: string) => {
|
const handleUnlink = async (platform: string) => {
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
if (!confirm(`Unlink ${platform}?`)) return;
|
if (!confirm(`Unlink ${platform}?`)) return;
|
||||||
@@ -114,27 +139,9 @@ export default function SettingsPage() {
|
|||||||
|
|
||||||
const handleCancelLink = () => {
|
const handleCancelLink = () => {
|
||||||
setLinkStep('idle');
|
setLinkStep('idle');
|
||||||
setTelegramUsername('');
|
setDeepLink(null);
|
||||||
setVerificationCode(null);
|
|
||||||
setBotLink(null);
|
|
||||||
setLinkError(null);
|
setLinkError(null);
|
||||||
};
|
setPolling(false);
|
||||||
|
|
||||||
const handleVerificationDone = async () => {
|
|
||||||
if (!token) return;
|
|
||||||
// Refresh socials to check if verified
|
|
||||||
try {
|
|
||||||
const socialsData = await getLinkedSocials(token);
|
|
||||||
setSocials(socialsData.socials);
|
|
||||||
const telegram = socialsData.socials.find((s) => s.platform === 'telegram');
|
|
||||||
if (telegram?.verified) {
|
|
||||||
handleCancelLink();
|
|
||||||
} else {
|
|
||||||
setLinkError('Verification not complete. Send the code to the bot and try again.');
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
setLinkError('Failed to check verification status');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -271,9 +278,11 @@ export default function SettingsPage() {
|
|||||||
<div>
|
<div>
|
||||||
<p className="font-medium">Telegram</p>
|
<p className="font-medium">Telegram</p>
|
||||||
{telegramSocial?.verified ? (
|
{telegramSocial?.verified ? (
|
||||||
<p className="text-sm text-green-400">@{telegramSocial.username}</p>
|
<p className="text-sm text-green-400">
|
||||||
|
{telegramSocial.username ? `@${telegramSocial.username}` : telegramSocial.display_name || 'Linked'}
|
||||||
|
</p>
|
||||||
) : telegramSocial?.pending_verification ? (
|
) : telegramSocial?.pending_verification ? (
|
||||||
<p className="text-sm text-yellow-400">Pending: @{telegramSocial.username}</p>
|
<p className="text-sm text-yellow-400">Verification pending</p>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm text-zinc-500">Not linked</p>
|
<p className="text-sm text-zinc-500">Not linked</p>
|
||||||
)}
|
)}
|
||||||
@@ -298,68 +307,33 @@ export default function SettingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Link flow UI */}
|
{/* Link flow UI */}
|
||||||
{linkStep === 'entering' && (
|
{linkStep === 'linking' && (
|
||||||
<div className="mt-4 pt-4 border-t border-zinc-800">
|
<div className="mt-4 pt-4 border-t border-zinc-800">
|
||||||
<label className="block text-sm text-zinc-400 mb-2">
|
<div className="flex items-center gap-2">
|
||||||
Enter your Telegram username
|
<div className="animate-spin w-5 h-5 border-2 border-[#fbeb0a] border-t-transparent rounded-full" />
|
||||||
</label>
|
<span className="text-zinc-400">Setting up link...</span>
|
||||||
<div className="flex gap-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={telegramUsername}
|
|
||||||
onChange={(e) => setTelegramUsername(e.target.value)}
|
|
||||||
placeholder="@username"
|
|
||||||
className="flex-1 px-3 py-2 bg-zinc-800 border border-zinc-700 rounded-lg text-white placeholder:text-zinc-500 focus:outline-none focus:border-[#fbeb0a]"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={handleSubmitUsername}
|
|
||||||
disabled={!telegramUsername.trim()}
|
|
||||||
className="px-4 py-2 bg-[#fbeb0a] text-black font-medium rounded-lg hover:bg-[#d4c708] disabled:opacity-50"
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleCancelLink}
|
|
||||||
className="px-4 py-2 border border-zinc-700 rounded-lg hover:border-zinc-500"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{linkError && <p className="mt-2 text-sm text-red-400">{linkError}</p>}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{linkStep === 'verifying' && verificationCode && (
|
{linkStep === 'waiting' && deepLink && (
|
||||||
<div className="mt-4 pt-4 border-t border-zinc-800">
|
<div className="mt-4 pt-4 border-t border-zinc-800">
|
||||||
<div className="bg-zinc-800 rounded-lg p-4 mb-4">
|
<p className="text-sm text-zinc-400 mb-4">
|
||||||
<p className="text-sm text-zinc-400 mb-2">Your verification code:</p>
|
Click the button below to open Telegram and link your account automatically:
|
||||||
<p className="text-2xl font-mono font-bold text-[#fbeb0a]">{verificationCode}</p>
|
</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ol className="text-sm text-zinc-400 space-y-2 mb-4">
|
<div className="flex gap-2 mb-4">
|
||||||
<li>
|
|
||||||
1. Open{' '}
|
|
||||||
<a
|
<a
|
||||||
href={botLink || 'https://t.me/smirk_wallet_bot'}
|
href={deepLink}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-[#0088cc] hover:underline"
|
className="flex items-center gap-2 px-4 py-2 bg-[#0088cc] text-white font-medium rounded-lg hover:bg-[#0077b3]"
|
||||||
>
|
>
|
||||||
@smirk_wallet_bot
|
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
|
||||||
</a>{' '}
|
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69a.2.2 0 00-.05-.18c-.06-.05-.14-.03-.21-.02-.09.02-1.49.95-4.22 2.79-.4.27-.76.41-1.08.4-.36-.01-1.04-.2-1.55-.37-.63-.2-1.12-.31-1.08-.66.02-.18.27-.36.74-.55 2.92-1.27 4.86-2.11 5.83-2.51 2.78-1.16 3.35-1.36 3.73-1.36.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z" />
|
||||||
on Telegram
|
</svg>
|
||||||
</li>
|
Open Telegram
|
||||||
<li>2. Send: <code className="bg-zinc-700 px-2 py-0.5 rounded">/verify {verificationCode}</code></li>
|
</a>
|
||||||
<li>3. Click "I've verified" below</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<button
|
|
||||||
onClick={handleVerificationDone}
|
|
||||||
className="px-4 py-2 bg-[#fbeb0a] text-black font-medium rounded-lg hover:bg-[#d4c708]"
|
|
||||||
>
|
|
||||||
I've verified
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
onClick={handleCancelLink}
|
onClick={handleCancelLink}
|
||||||
className="px-4 py-2 border border-zinc-700 rounded-lg hover:border-zinc-500"
|
className="px-4 py-2 border border-zinc-700 rounded-lg hover:border-zinc-500"
|
||||||
@@ -367,6 +341,12 @@ export default function SettingsPage() {
|
|||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2 text-sm text-zinc-500">
|
||||||
|
<div className="animate-spin w-4 h-4 border-2 border-zinc-500 border-t-transparent rounded-full" />
|
||||||
|
<span>Waiting for verification...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{linkError && <p className="mt-2 text-sm text-red-400">{linkError}</p>}
|
{linkError && <p className="mt-2 text-sm text-red-400">{linkError}</p>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,302 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
export default function Terms() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex flex-col items-center p-8">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-8 flex flex-col items-center">
|
||||||
|
<Link href="/" className="logo-glow mb-4">
|
||||||
|
<Image
|
||||||
|
src="/logo.svg"
|
||||||
|
alt="Smirk"
|
||||||
|
width={80}
|
||||||
|
height={80}
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
<h1 className="creepster-text text-3xl">Terms of Service</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="max-w-2xl w-full bg-zinc-900/50 rounded-2xl p-8 space-y-8">
|
||||||
|
<p className="text-zinc-400 text-sm">
|
||||||
|
Last Updated: January 31, 2026
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-zinc-300 text-lg leading-relaxed">
|
||||||
|
BY ACCESSING OR USING SMIRK WALLET, YOU AGREE TO BE BOUND BY THESE TERMS OF SERVICE.
|
||||||
|
IF YOU DO NOT AGREE, DO NOT USE OUR SERVICES.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Section 1 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">1. Eligibility</h2>
|
||||||
|
<p className="text-zinc-300 mb-4">
|
||||||
|
You represent and warrant that you:
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-2 text-zinc-400 ml-4 list-disc list-inside">
|
||||||
|
<li>Are of legal age to form a binding contract in your jurisdiction</li>
|
||||||
|
<li>Have not previously been suspended or removed from using our Services</li>
|
||||||
|
<li>Have full power and authority to enter into this agreement</li>
|
||||||
|
<li>Will not use these services in violation of any applicable laws</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 2 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">2. Account & Wallet Security</h2>
|
||||||
|
<p className="text-zinc-300 mb-4">
|
||||||
|
When you create a Smirk wallet, you agree to:
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-3 text-zinc-400">
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Secure Your Recovery Phrase:</strong> You are solely
|
||||||
|
responsible for backing up and protecting your 24-word recovery phrase (mnemonic).
|
||||||
|
This phrase is the only way to recover your wallet.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Password Protection:</strong> Maintain the security
|
||||||
|
of your wallet password and restrict access to your devices.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Promptly Report Issues:</strong> Notify us if you
|
||||||
|
discover or suspect any security breaches related to your account.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Accept Responsibility:</strong> Take responsibility
|
||||||
|
for all activities that occur under your wallet, including any authorized or
|
||||||
|
unauthorized access.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 3 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">3. Description of Services</h2>
|
||||||
|
|
||||||
|
<h3 className="text-lg font-semibold text-white mt-6 mb-3">3.1 Non-Custodial Wallet</h3>
|
||||||
|
<p className="text-zinc-400 mb-4">
|
||||||
|
Smirk is a <strong className="text-white">non-custodial</strong> multi-cryptocurrency
|
||||||
|
wallet supporting Bitcoin (BTC), Litecoin (LTC), Monero (XMR), Wownero (WOW), and
|
||||||
|
Grin (GRIN). Your private spend keys are generated and stored locally on your device.
|
||||||
|
They are never transmitted to our servers. We cannot access, freeze, or seize your funds.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-lg font-semibold text-white mt-6 mb-3">3.2 Social Tipping</h3>
|
||||||
|
<p className="text-zinc-400 mb-4">
|
||||||
|
Smirk enables you to send cryptocurrency tips to users on social platforms (Telegram,
|
||||||
|
Discord, etc.) and via public tip links. Tips are encrypted and can only be claimed
|
||||||
|
by the intended recipient (or anyone with the link for public tips).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-lg font-semibold text-white mt-6 mb-3">3.3 No Recovery Phrase Retrieval</h3>
|
||||||
|
<p className="text-zinc-400 mb-4">
|
||||||
|
Our Services do not store your recovery phrase or unencrypted private keys. Therefore,
|
||||||
|
we cannot assist you with recovery phrase retrieval.
|
||||||
|
</p>
|
||||||
|
<div className="bg-zinc-800/50 rounded-xl p-4 text-zinc-300">
|
||||||
|
<strong className="text-[#fbeb0a]">WARNING:</strong> IF YOU LOSE YOUR RECOVERY PHRASE,
|
||||||
|
YOU WILL PERMANENTLY LOSE ACCESS TO YOUR FUNDS. THERE IS NO WAY TO RECOVER THEM.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-lg font-semibold text-white mt-6 mb-3">3.4 Transaction Processing</h3>
|
||||||
|
<p className="text-zinc-400 mb-4">
|
||||||
|
All cryptocurrency transactions are processed by their respective decentralized
|
||||||
|
networks (Bitcoin, Litecoin, Monero, Wownero, Grin). We do not control these networks
|
||||||
|
and cannot guarantee transaction speed, confirmation, or reversal. Once a transaction
|
||||||
|
is broadcast, it cannot be cancelled or modified.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 4 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">4. Fees</h2>
|
||||||
|
<ul className="space-y-3 text-zinc-400">
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Service Fees:</strong> Access to Smirk wallet is
|
||||||
|
currently free. We may introduce fees for certain services in the future.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-white">Network Fees:</strong> All cryptocurrency transactions
|
||||||
|
require network fees (miner fees) paid to the respective blockchain network. These
|
||||||
|
fees are not collected by Smirk and are displayed before you confirm any transaction.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 5 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">5. Acceptable Use</h2>
|
||||||
|
<p className="text-zinc-300 mb-4">You agree that you will NOT:</p>
|
||||||
|
<ul className="space-y-2 text-zinc-400 ml-4 list-disc list-inside">
|
||||||
|
<li>Use our Services to engage in illegal activities including fraud, money laundering,
|
||||||
|
or terrorist financing</li>
|
||||||
|
<li>Attempt to interfere with, disrupt, or overburden our Services</li>
|
||||||
|
<li>Use automated means (bots, scrapers) to access our Services without permission</li>
|
||||||
|
<li>Attempt to circumvent any security measures or access controls</li>
|
||||||
|
<li>Introduce viruses, malware, or other harmful code</li>
|
||||||
|
<li>Impersonate others or provide false information</li>
|
||||||
|
<li>Use our Services to harass, abuse, or harm others</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 6 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">6. Taxes</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
It is your sole responsibility to determine what taxes apply to your cryptocurrency
|
||||||
|
transactions and to report and remit the correct tax to the appropriate tax authority.
|
||||||
|
Smirk is not responsible for determining, collecting, reporting, or remitting any
|
||||||
|
taxes arising from your use of our Services.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 7 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">7. Assumption of Risk</h2>
|
||||||
|
<p className="text-zinc-300 mb-4">
|
||||||
|
You acknowledge and agree that there are risks associated with using cryptocurrency
|
||||||
|
and Internet-based services, including but not limited to:
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-2 text-zinc-400 ml-4 list-disc list-inside">
|
||||||
|
<li>Price volatility and potential loss of value</li>
|
||||||
|
<li>Risk of hardware, software, and Internet connection failures</li>
|
||||||
|
<li>Risk of malicious software or phishing attacks</li>
|
||||||
|
<li>Risk of unauthorized access to your devices or accounts</li>
|
||||||
|
<li>Irreversibility of cryptocurrency transactions</li>
|
||||||
|
<li>Regulatory changes that may affect cryptocurrency use</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-zinc-400 mt-4">
|
||||||
|
Smirk is not responsible for any losses arising from forgotten recovery phrases,
|
||||||
|
incorrect addresses, server failures, phishing attacks, or any other unauthorized
|
||||||
|
third-party activities.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 8 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">8. Discontinuance of Services</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
We may, in our sole discretion and without liability to you, modify or discontinue
|
||||||
|
any portion of our Services at any time. You are solely responsible for maintaining
|
||||||
|
a backup of your recovery phrase outside of the Services. If you have your recovery
|
||||||
|
phrase, you can always access your funds using any compatible wallet software, even
|
||||||
|
if Smirk discontinues its Services.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 9 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">9. Disclaimer of Warranties</h2>
|
||||||
|
<p className="text-zinc-400 uppercase text-sm leading-relaxed">
|
||||||
|
OUR SERVICES ARE PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS.
|
||||||
|
TO THE MAXIMUM EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||||
|
NON-INFRINGEMENT. WE DO NOT WARRANT THAT OUR SERVICES WILL BE UNINTERRUPTED,
|
||||||
|
ERROR-FREE, OR SECURE.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 10 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">10. Limitation of Liability</h2>
|
||||||
|
<p className="text-zinc-400 uppercase text-sm leading-relaxed">
|
||||||
|
TO THE MAXIMUM EXTENT PERMITTED BY LAW, SMIRK AND ITS DIRECTORS, EMPLOYEES, AND
|
||||||
|
AGENTS SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL,
|
||||||
|
OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, DATA, OR FUNDS,
|
||||||
|
ARISING FROM YOUR USE OF OR INABILITY TO USE OUR SERVICES.
|
||||||
|
</p>
|
||||||
|
<p className="text-zinc-400 uppercase text-sm leading-relaxed mt-4">
|
||||||
|
IN NO EVENT SHALL OUR AGGREGATE LIABILITY EXCEED ONE HUNDRED DOLLARS ($100 USD).
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 11 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">11. Indemnification</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
You agree to defend, indemnify, and hold harmless Smirk and its officers, directors,
|
||||||
|
employees, and agents from any claims, damages, losses, or expenses arising from:
|
||||||
|
(a) your use of our Services; (b) your violation of these Terms; (c) your violation
|
||||||
|
of any rights of any third party; or (d) any content you submit through our Services.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 12 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">12. Privacy</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
Please refer to our{' '}
|
||||||
|
<Link href="/privacy" className="text-[#fbeb0a] hover:underline">
|
||||||
|
Privacy Policy
|
||||||
|
</Link>
|
||||||
|
{' '}for information about how we collect, use, and protect your information.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 13 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">13. Modifications to Terms</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
We reserve the right to modify these Terms at any time. We will provide notice of
|
||||||
|
material changes by updating the "Last Updated" date at the top of these Terms.
|
||||||
|
Your continued use of our Services after any changes constitutes your acceptance of
|
||||||
|
the new Terms.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 14 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">14. Governing Law</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
These Terms shall be governed by and construed in accordance with the laws of the
|
||||||
|
jurisdiction where Smirk operates, without regard to conflict of law principles.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Section 15 */}
|
||||||
|
<section>
|
||||||
|
<h2 className="text-xl font-bold text-[#fbeb0a] mb-4">15. Severability</h2>
|
||||||
|
<p className="text-zinc-400">
|
||||||
|
If any provision of these Terms is found to be invalid or unenforceable, the remaining
|
||||||
|
provisions shall remain in full force and effect.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Summary */}
|
||||||
|
<section className="border border-zinc-700 rounded-xl p-6">
|
||||||
|
<h2 className="text-lg font-bold text-white mb-4">Quick Summary</h2>
|
||||||
|
<ul className="space-y-2 text-zinc-400">
|
||||||
|
<li><strong className="text-[#fbeb0a]">Non-Custodial:</strong> You control your keys. We cannot access or recover your funds.</li>
|
||||||
|
<li><strong className="text-[#fbeb0a]">Your Responsibility:</strong> Back up your recovery phrase. Losing it means losing your funds forever.</li>
|
||||||
|
<li><strong className="text-[#fbeb0a]">Irreversible:</strong> Cryptocurrency transactions cannot be cancelled or reversed.</li>
|
||||||
|
<li><strong className="text-[#fbeb0a]">No Guarantees:</strong> We provide the service as-is. Use at your own risk.</li>
|
||||||
|
<li><strong className="text-[#fbeb0a]">Be Legal:</strong> Don't use Smirk for illegal activities.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Contact */}
|
||||||
|
<section className="bg-zinc-800/50 rounded-xl p-6">
|
||||||
|
<h2 className="text-lg font-bold text-[#fbeb0a] mb-4">Questions?</h2>
|
||||||
|
<p className="text-zinc-300">
|
||||||
|
If you have questions about these Terms of Service, please contact us through our
|
||||||
|
official channels or at the support email provided in the extension.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Back link */}
|
||||||
|
<div className="pt-4 text-center">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="text-[#fbeb0a] hover:underline"
|
||||||
|
>
|
||||||
|
← Back to Smirk
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
+36
-1
@@ -87,12 +87,20 @@ export interface RegisterSocialResponse {
|
|||||||
|
|
||||||
export interface LinkedSocial {
|
export interface LinkedSocial {
|
||||||
platform: string;
|
platform: string;
|
||||||
username: string;
|
username: string | null;
|
||||||
|
display_name: string | null;
|
||||||
|
platform_user_id: string | null;
|
||||||
verified: boolean;
|
verified: boolean;
|
||||||
verified_at: string | null;
|
verified_at: string | null;
|
||||||
pending_verification: boolean;
|
pending_verification: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InitiateLinkResponse {
|
||||||
|
deep_link: string;
|
||||||
|
code: string;
|
||||||
|
expires_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LinkedSocialsResponse {
|
export interface LinkedSocialsResponse {
|
||||||
socials: LinkedSocial[];
|
socials: LinkedSocial[];
|
||||||
}
|
}
|
||||||
@@ -119,6 +127,33 @@ export async function registerSocial(
|
|||||||
return res.json();
|
return res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate social link via deep link flow.
|
||||||
|
*
|
||||||
|
* Returns a deep link that opens the bot. User clicks the link,
|
||||||
|
* bot extracts their info automatically, no manual username entry.
|
||||||
|
*/
|
||||||
|
export async function initiateLink(
|
||||||
|
token: string,
|
||||||
|
platform: string
|
||||||
|
): Promise<InitiateLinkResponse> {
|
||||||
|
const res = await fetch(`${API_URL}/api/v1/socials/initiate-link`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ platform }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const data = await res.json().catch(() => ({}));
|
||||||
|
throw new Error(data.error || 'Failed to initiate link');
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
export async function getLinkedSocials(token: string): Promise<LinkedSocialsResponse> {
|
export async function getLinkedSocials(token: string): Promise<LinkedSocialsResponse> {
|
||||||
const res = await fetch(`${API_URL}/api/v1/socials/me`, {
|
const res = await fetch(`${API_URL}/api/v1/socials/me`, {
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
|||||||
Reference in New Issue
Block a user