KOL count: 29 → 25 across marketing/SEO copy
Backend KOL_FEEDS trimmed from 29 to 25 (dead feeds removed).
Sync all hardcoded count mentions:
- layout.tsx JSON-LD, page.tsx (metric + comparison + copy)
- kol/page.tsx, KolPageClient.tsx ("and 26 more" → "and 22 more")
- glossary/page.tsx, opengraph-image.tsx
- public/llms.txt, llms-full.txt
- drop removed KOLs (Dragonfly Capital, Nic Carter) from named lists
Bundles other in-flight frontend work already in the working tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+73
-5
@@ -5,11 +5,18 @@ import type {
|
||||
} from '@/types'
|
||||
import type { SignedEnvelope } from './signedRequest'
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
|
||||
function getServerApiBase() {
|
||||
return (
|
||||
process.env.API_BASE_URL ||
|
||||
process.env.INTERNAL_API_URL ||
|
||||
process.env.NEXT_PUBLIC_API_URL ||
|
||||
'http://localhost:8000'
|
||||
)
|
||||
}
|
||||
|
||||
function getApiOrigin() {
|
||||
return typeof window === 'undefined'
|
||||
? `${BASE_URL}/api`
|
||||
? `${getServerApiBase()}/api`
|
||||
: '/api/proxy/api'
|
||||
}
|
||||
|
||||
@@ -29,6 +36,53 @@ async function fetchJson<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
return res.json() as Promise<T>
|
||||
}
|
||||
|
||||
export interface PostListResponse {
|
||||
items: TrumpPost[]
|
||||
total: number
|
||||
page: number
|
||||
limit: number
|
||||
counts: {
|
||||
all: number
|
||||
actionable: number
|
||||
buy: number
|
||||
short: number
|
||||
off_topic: number
|
||||
}
|
||||
source_counts: {
|
||||
source: string
|
||||
count: number
|
||||
latest: string | null
|
||||
}[]
|
||||
}
|
||||
|
||||
export async function getPostsPage(
|
||||
limit = 20,
|
||||
page = 1,
|
||||
source?: string,
|
||||
filters?: {
|
||||
sourceIn?: string[]
|
||||
sourceNotIn?: string[]
|
||||
archiveOnly?: boolean
|
||||
sentiment?: 'bullish' | 'bearish' | 'neutral'
|
||||
signal?: 'buy' | 'short' | 'actionable'
|
||||
aiScoredOnly?: boolean
|
||||
},
|
||||
): Promise<PostListResponse> {
|
||||
const params = new URLSearchParams({
|
||||
limit: String(limit),
|
||||
page: String(page),
|
||||
})
|
||||
if (source) params.set('source', source)
|
||||
if (filters?.sourceIn?.length) params.set('source_in', filters.sourceIn.join(','))
|
||||
if (filters?.sourceNotIn?.length) params.set('source_not_in', filters.sourceNotIn.join(','))
|
||||
if (filters?.archiveOnly) params.set('archive_only', 'true')
|
||||
if (filters?.sentiment) params.set('sentiment', filters.sentiment)
|
||||
if (filters?.signal) params.set('signal', filters.signal)
|
||||
if (filters?.aiScoredOnly) params.set('ai_scored_only', 'true')
|
||||
const q = `/posts-paged?${params.toString()}`
|
||||
return fetchJson<PostListResponse>(q)
|
||||
}
|
||||
|
||||
export async function getPosts(limit = 20, page = 1, source?: string): Promise<TrumpPost[]> {
|
||||
const q = `/posts?limit=${limit}&page=${page}` + (source ? `&source=${encodeURIComponent(source)}` : '')
|
||||
return fetchJson<TrumpPost[]>(q)
|
||||
@@ -139,6 +193,11 @@ export interface UserPublic {
|
||||
circuit_breaker_reason?: string | null
|
||||
/** Master Auto-Trade gate. false (default) = signals shown, not traded. */
|
||||
auto_trade?: boolean
|
||||
/** Per-system enable flags. bot_engine gates System-1 (Trump) on
|
||||
* trump_enabled and System-2 (Macro) on macro_enabled. Auto-Trade ON
|
||||
* with trump_enabled=false still does NOT open on a Trump signal. */
|
||||
trump_enabled?: boolean
|
||||
macro_enabled?: boolean
|
||||
}
|
||||
|
||||
export interface SignalSource {
|
||||
@@ -403,11 +462,14 @@ export async function setManualWindow(
|
||||
|
||||
// ── KOL module ────────────────────────────────────────────────────
|
||||
export async function getKolPosts(opts: {
|
||||
handle?: string; source?: string; limit?: number; page?: number
|
||||
} = {}): Promise<{ items: KolPostSummary[]; page: number; limit: number }> {
|
||||
handle?: string; source?: string; signalsOnly?: boolean; ticker?: string; days?: number; limit?: number; page?: number
|
||||
} = {}): Promise<{ items: KolPostSummary[]; page: number; limit: number; total: number }> {
|
||||
const p = new URLSearchParams()
|
||||
if (opts.handle) p.set('handle', opts.handle)
|
||||
if (opts.source) p.set('source', opts.source)
|
||||
if (opts.signalsOnly) p.set('signals_only', 'true')
|
||||
if (opts.ticker) p.set('ticker', opts.ticker)
|
||||
if (opts.days) p.set('days', String(opts.days))
|
||||
p.set('limit', String(opts.limit ?? 50))
|
||||
p.set('page', String(opts.page ?? 1))
|
||||
return fetchJson(`/kol/posts?${p.toString()}`)
|
||||
@@ -520,7 +582,13 @@ export interface TelegramStatus {
|
||||
export interface TelegramInitResp {
|
||||
code: string; deep_link: string; expires_in_seconds: number
|
||||
}
|
||||
export async function getTelegramStatus(wallet: string): Promise<TelegramStatus> {
|
||||
export async function getTelegramStatus(wallet: string, env?: SignedEnvelope): Promise<TelegramStatus> {
|
||||
// Pass signature when available so the backend returns full binding details.
|
||||
// Without it the endpoint returns only `bound: boolean` to prevent third-party de-anonymisation.
|
||||
if (env) {
|
||||
const qs = new URLSearchParams({ timestamp: String(env.timestamp), signature: env.signature })
|
||||
return fetchJson<TelegramStatus>(`/telegram/${wallet}/status?${qs}`)
|
||||
}
|
||||
return fetchJson<TelegramStatus>(`/telegram/${wallet}/status`)
|
||||
}
|
||||
// SignedEnvelope is already imported at the top of this file. Below we
|
||||
|
||||
Reference in New Issue
Block a user