mirror of
https://github.com/Such-Software/smirk-website.git
synced 2026-11-13 09:14:03 +01:00
feat: initialize smirk-website with connect flow
- Next.js 16 with TypeScript and Tailwind CSS - Single-asset authentication (user picks favorite coin to sign) - Logo with glow animation - Coin picker UI with all 5 assets - API client for backend auth endpoints - TypeScript types for window.smirk extension API
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// API client for Smirk backend
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
|
||||
export interface ChallengeResponse {
|
||||
challenge: string;
|
||||
challenge_id: string;
|
||||
expires_at: string;
|
||||
}
|
||||
|
||||
export interface AuthResponse {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
expires_in: number;
|
||||
user: {
|
||||
id: string;
|
||||
telegram_id: number | null;
|
||||
telegram_username: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MeResponse {
|
||||
id: string;
|
||||
username: string | null;
|
||||
telegram_id: number | null;
|
||||
telegram_username: string | null;
|
||||
}
|
||||
|
||||
export async function getChallenge(origin: string): Promise<ChallengeResponse> {
|
||||
const res = await fetch(`${API_URL}/api/v1/auth/website/challenge`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ origin }),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const error = await res.json().catch(() => ({ message: 'Request failed' }));
|
||||
throw new Error(error.message || 'Failed to get challenge');
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function verifySignature(
|
||||
challengeId: string,
|
||||
signature: { asset: string; signature: string; public_key: string }
|
||||
): Promise<AuthResponse> {
|
||||
const res = await fetch(`${API_URL}/api/v1/auth/website/verify`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
challenge_id: challengeId,
|
||||
signature,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const error = await res.json().catch(() => ({ message: 'Request failed' }));
|
||||
throw new Error(error.message || 'Failed to verify signature');
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function getMe(token: string): Promise<MeResponse> {
|
||||
const res = await fetch(`${API_URL}/api/v1/auth/me`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to get user info');
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
Reference in New Issue
Block a user