diff --git a/src/app/_components/token-metadata-viewer/index.tsx b/src/app/_components/token-metadata-viewer/index.tsx new file mode 100644 index 0000000..c79fddd --- /dev/null +++ b/src/app/_components/token-metadata-viewer/index.tsx @@ -0,0 +1,89 @@ +'use client' + +import { useEffect, useState } from 'react' + +interface Props { + metadataUrl: string +} + +export default function TokenMetadataViewer({ metadataUrl }: Props) { + const [error, setError] = useState(null) + const [imagePreview, setImagePreview] = useState(null) + const [json, setJson] = useState(null) + const [imageError, setImageError] = useState(false) + + const normalizeIpfsUrl = (url: string) => { + if (url.startsWith('ipfs://')) { + return url.replace('ipfs://', 'https://ipfs.io/ipfs/') + } + return url + } + + useEffect(() => { + if (!metadataUrl) return + + const url = normalizeIpfsUrl(metadataUrl) + + fetch(url) + .then(async (res) => { + const contentType = res.headers.get('Content-Type') || '' + if (contentType.includes('application/json')) { + const data = await res.json() + setJson(data) + } else if (contentType.includes('image/')) { + setImagePreview(url) + setError('Received image instead of JSON metadata') + } else { + throw new Error(`Unexpected content type: ${contentType}`) + } + }) + .catch((err) => { + console.error('Metadata fetch error:', err) + setError(err.message) + }) + }, [metadataUrl]) + + return ( +
+

Metadata

+

+ + {metadataUrl} + +

+ + {error && ( +

+ Failed to load metadata: {error} +

+ )} + + {imagePreview && !imageError && ( +
+

Image found instead of JSON:

+ Token metadata image setImageError(true)} + /> +
+ )} + + {imageError && ( +

Preview not available

+ )} + + {json && ( +
+          {JSON.stringify(json, null, 2)}
+        
+ )} +
+ ) +} \ No newline at end of file diff --git a/src/app/_components/token-verification-form/index.tsx b/src/app/_components/token-verification-form/index.tsx new file mode 100644 index 0000000..3f66e4e --- /dev/null +++ b/src/app/_components/token-verification-form/index.tsx @@ -0,0 +1,250 @@ +'use client' + +import { useState } from 'react' +import TokenLoader from '@/app/token-verify/TokenLoader' + +export default function TokenVerificationForm() { + const [formData, setFormData] = useState({ + tokenId: '', + ticker: '', + projectName: '', + description: '', + website: '', + logoUrl: '', + contactInfo: '', + email: '', + links: '', + submitterName: '', + agreed: false, + }) + + const handleChange = ( + e: React.ChangeEvent + ) => { + const { name, value, type, checked } = e.target as any + setFormData((prev) => ({ + ...prev, + [name]: type === 'checkbox' ? checked : value, + })) + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + const { tokenId, ticker, projectName, description, email, agreed } = formData + + if (!tokenId || !ticker || !projectName || !description || !email || !agreed) { + alert('Please fill in all required fields and agree to the terms.') + return + } + + const TELEGRAM_BOT_TOKEN = process.env.NEXT_PUBLIC_TELEGRAM_BOT_TOKEN! + const TELEGRAM_CHAT_ID = process.env.NEXT_PUBLIC_TELEGRAM_CHAT_ID! + + const message = ` +🟦 *New token verification request* +🔹 *Token ID:* ${formData.tokenId} +🔹 *Ticker:* ${formData.ticker} +🔹 *Project Name:* ${formData.projectName} +🔹 *Description:* ${formData.description} +🔹 *Website:* ${formData.website || '-'} +🔹 *Logo:* ${formData.logoUrl || '-'} +🔹 *Contact Info:* ${formData.contactInfo || '-'} +🔹 *Additional Links:* ${formData.links || '-'} +🔹 *Submitter:* ${formData.submitterName || '-'} +📧 *Email:* ${formData.email} +` + + try { + const res = await fetch(`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chat_id: TELEGRAM_CHAT_ID, + text: message, + parse_mode: 'Markdown', + }), + }) + + if (res.ok) { + alert('Request submitted successfully!') + // Reset form after successful submission + setFormData({ + tokenId: '', + ticker: '', + projectName: '', + description: '', + website: '', + logoUrl: '', + contactInfo: '', + email: '', + links: '', + submitterName: '', + agreed: false, + }) + } else { + alert('Error sending to Telegram.') + } + } catch (error) { + console.error('Telegram error:', error) + alert('Connection error with Telegram.') + } + } + + return ( +
+

+ Token Verification Request +

+ + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +