Gwallet Admin

Management Console

Quick KYC Lookup

`; } catch (e) { el.innerHTML = '

Error loading KYC data

'; } } async function lookupKYC() { const addr = document.getElementById('kyc-addr').value; if (!addr) return; try { const kyc = await api('/api/v1/kyc/status?address=' + addr); const el = document.getElementById('kyc-result'); if (!kyc) { el.innerHTML = '

No KYC record found

'; return; } const imgBase = `https://amzon-aws-gwalletapp.s3.ap-east-1.amazonaws.com/kyc/${addr}`; el.innerHTML = `
${kyc.wallet_address}
${kyc.full_name || '-'}
${kyc.country || '-'}
${kyc.status}
${new Date(kyc.submitted_at).toLocaleString()}
${kyc.rejection_reason ? `
${kyc.rejection_reason}
` : ''}

Front ID

Back ID

Selfie

`; } catch (e) { document.getElementById('kyc-result').innerHTML = `

${e.message}

`; } } async function approveKYC(addr) { try { await api('/api/v1/admin/kyc/approve', { method: 'POST', body: JSON.stringify({ wallet_address: addr }) }); toast('KYC approved ✅'); lookupKYC(); } catch (e) { toast('Error: ' + e.message); } } async function rejectKYC(addr) { const reason = prompt('Rejection reason:'); if (!reason) return; try { await api('/api/v1/admin/kyc/reject', { method: 'POST', body: JSON.stringify({ wallet_address: addr, reason }) }); toast('KYC rejected ❌'); lookupKYC(); } catch (e) { toast('Error: ' + e.message); } } // ──────────────── Token Launch ──────────────── async function loadTokens() { const el = document.getElementById('tab-tokens'); el.innerHTML = '

Token Launch Review

Loading...

'; try { // 加载所有代币(包括 pending)— 用 admin/kyc/list 的模式,但 token/list 只返回 deployed/migrated // 需要先加载 pending 的,再加载已部署的 let allTokens = []; try { const deployed = await api('/api/v1/token/list'); allTokens = allTokens.concat(deployed); } catch(e) {} // 也查 admin list(通过 KYC list 端点方式已有,但 token 没有 admin list 端点) // 直接展示已有数据 + pending approve UI let rows = allTokens.map(t => ` ${t.symbol} ${t.token_name} ${t.creator_address.slice(0,8)}...${t.creator_address.slice(-4)} ${t.chain_id.toUpperCase()} ${t.status} ${t.contract_address ? `${t.contract_address.slice(0,10)}...` : '-'} ${t.status === 'pending_review' ? ` ` : ''} `).join(''); if (!rows) rows = 'No token launches yet'; el.innerHTML = `

Token Launch Review

${rows}
SymbolNameCreatorChainStatusContractActions

Quick Token Lookup

`; } catch (e) { el.innerHTML = `

${e.message}

`; } } async function lookupToken() { const id = document.getElementById('token-id').value; if (!id) return; try { const token = await api('/api/v1/token/status?id=' + id); const el = document.getElementById('token-result'); if (!token) { el.innerHTML = '

Token not found

'; return; } el.innerHTML = `
${token.id}
${token.symbol}
${token.token_name}
${token.creator_address}
${token.total_supply}
${token.chain_id}
${token.status}
${token.contract_address || 'Not deployed'}
${token.rejection_reason ? `
${token.rejection_reason}
` : ''} ${token.status === 'pending_review' ? `
` : ''}
`; } catch (e) { document.getElementById('token-result').innerHTML = `

${e.message}

`; } } async function approveToken(tokenId) { if (!confirm('Approve and deploy this token? This will trigger on-chain deployment.')) return; try { const result = await api('/api/v1/admin/token/approve', { method: 'POST', body: JSON.stringify({ token_id: tokenId }), }); toast('Token approved! Status: ' + result.status + (result.contract_address ? ' Contract: ' + result.contract_address : '')); loadTokens(); } catch (e) { toast('Error: ' + e.message); } } async function rejectToken(tokenId) { const reason = prompt('Rejection reason:'); if (!reason) return; try { await api('/api/v1/admin/token/reject', { method: 'POST', body: JSON.stringify({ token_id: tokenId, reason }), }); toast('Token rejected'); loadTokens(); } catch (e) { toast('Error: ' + e.message); } } // ──────────────── Announcements ──────────────── async function loadAnnouncements() { const el = document.getElementById('tab-announcements'); el.innerHTML = '

Announcements

Loading...

'; try { const announcements = await api('/api/v1/announcements'); let rows = announcements.map(a => ` ${a.title} ${a.category} ${a.pinned ? '📌' : ''} ${new Date(a.published_at).toLocaleDateString()} `).join(''); el.innerHTML = `

Announcements

${rows || ''}
TitleCategoryPinnedPublished
No announcements
`; } catch (e) { el.innerHTML = `

${e.message}

`; } } function showNewAnnouncement() { document.getElementById('new-announcement').style.display = 'block'; } async function createAnnouncement() { const title = document.getElementById('ann-title').value; const content = document.getElementById('ann-content').value; const category = document.getElementById('ann-category').value; if (!title || !content) { toast('Title and content required'); return; } try { await api('/api/v1/admin/announcements', { method: 'POST', body: JSON.stringify({ title, content, category, pinned: false }), }); toast('Announcement published ✅'); document.getElementById('ann-title').value = ''; document.getElementById('ann-content').value = ''; document.getElementById('new-announcement').style.display = 'none'; loadAnnouncements(); } catch (e) { toast('Error: ' + e.message); } }