+
+
+ Crypto — one deposit address for all {SUPPORTED_EVM_CHAINS.length} EVM networks, plus{' '}
+ {OTHER_SUPPORTED_CHAINS.map(chainDisplayName).join(' and ')}:
+
+
+ {[...SUPPORTED_EVM_CHAINS, ...OTHER_SUPPORTED_CHAINS].map((chain) => (
+
+ ))}
+
+
+
+
Tokens:
+
+ {getSupportedTokens('EVM').map((token) => (
+
+ ))}
+
+
+ USDC & USDT on every network · ETH on EVM networks · Tron is USDT-only
+
+
+
+
Banks & local payment apps:
+
+ {FIAT_RAILS.map((rail) => (
+ -
+ {rail.flag}
+ {rail.name}
+
+ {rail.currency} · {rail.region}
+
+
+ ))}
+
+
+
Deposits are free — Peanut covers the gas.
+
+ )
+}
diff --git a/src/constants/faq.consts.ts b/src/constants/faq.consts.ts
new file mode 100644
index 000000000..327cd1c93
--- /dev/null
+++ b/src/constants/faq.consts.ts
@@ -0,0 +1,32 @@
+import { OTHER_SUPPORTED_CHAINS, SUPPORTED_EVM_CHAINS } from '@/constants/rhino.consts'
+import { chainDisplayName } from '@/utils/chain-display.utils'
+
+/**
+ * The "which networks, tokens and banks?" landing FAQ item. Question, fiat-rail
+ * facts and plain-text answer live here (server-safe, feeds the FAQPage JSON-LD
+ * via getLandingContent); the rich chip UI is rendered client-side by
+ * SupportedRailsFaqAnswer, matched by id. Chain names derive from rhino.consts
+ * and the visible rails render from FIAT_RAILS, so the public answer and the
+ * on-page UI share one source and can't drift from what the app supports.
+ */
+export const SUPPORTED_RAILS_FAQ_ID = 'supported-rails'
+
+export const FIAT_RAILS = [
+ { flag: '🇺🇸', name: 'ACH & Wire', currency: 'USD', region: 'United States' },
+ { flag: '🇪🇺', name: 'SEPA', currency: 'EUR', region: '36 countries' },
+ { flag: '🇬🇧', name: 'Faster Payments', currency: 'GBP', region: 'United Kingdom' },
+ { flag: '🇲🇽', name: 'SPEI', currency: 'MXN', region: 'Mexico' },
+ { flag: '🇦🇷', name: 'Mercado Pago', currency: 'ARS', region: 'Argentina' },
+ { flag: '🇧🇷', name: 'Pix', currency: 'BRL', region: 'Brazil' },
+] as const
+
+const EVM_CHAIN_LIST = SUPPORTED_EVM_CHAINS.map(chainDisplayName).join(', ')
+const OTHER_CHAIN_LIST = OTHER_SUPPORTED_CHAINS.map(chainDisplayName).join(' and ')
+const FIAT_RAIL_LIST = FIAT_RAILS.map((rail) => `${rail.name} (${rail.currency}, ${rail.region})`).join(', ')
+
+export const SUPPORTED_RAILS_FAQ_QUESTION = 'Which networks, tokens and banks does Peanut support?'
+
+export const SUPPORTED_RAILS_FAQ_ANSWER =
+ `Crypto: deposit and withdraw USDC and USDT on ${SUPPORTED_EVM_CHAINS.length} EVM networks with a single address (${EVM_CHAIN_LIST}), plus ${OTHER_CHAIN_LIST}. ETH is also supported on EVM networks; Tron is USDT-only. ` +
+ `Banks & local payment apps: ${FIAT_RAIL_LIST}. ` +
+ 'Deposits are free — Peanut covers the gas.'
diff --git a/src/lib/landingContent.ts b/src/lib/landingContent.ts
index 58984f8cb..95c77a853 100644
--- a/src/lib/landingContent.ts
+++ b/src/lib/landingContent.ts
@@ -5,6 +5,11 @@
// component or route handler, never inside a 'use client' file.
import { readSingletonContentLocalized } from '@/lib/content'
+import {
+ SUPPORTED_RAILS_FAQ_ANSWER,
+ SUPPORTED_RAILS_FAQ_ID,
+ SUPPORTED_RAILS_FAQ_QUESTION,
+} from '@/constants/faq.consts'
import type { Locale } from '@/i18n/types'
interface LandingFrontmatter {
@@ -40,7 +45,30 @@ const DEFAULTS: LandingContent = {
marqueeMessages: [],
}
+// Code-defined FAQ item advertising supported networks/tokens/bank rails.
+// Lives in code (not the content MD) because its facts derive from
+// rhino.consts — the same constants the add-money flow renders — so the
+// public answer can't drift from what the app actually supports.
+// LandingPageClient swaps in the rich chip UI by this id.
+const SUPPORTED_RAILS_QUESTION = {
+ id: SUPPORTED_RAILS_FAQ_ID,
+ question: SUPPORTED_RAILS_FAQ_QUESTION,
+ answer: SUPPORTED_RAILS_FAQ_ANSWER,
+}
+
+// Insert right after the "What is Peanut?" question (falls back to the end).
+function withSupportedRails(questions: LandingContent['faqData']['questions']) {
+ const idx = questions.findIndex((q) => /what is peanut\??/i.test(q.question))
+ const at = idx === -1 ? questions.length : idx + 1
+ return [...questions.slice(0, at), SUPPORTED_RAILS_QUESTION, ...questions.slice(at)]
+}
+
export function getLandingContent(locale: Locale = 'en'): LandingContent {
+ const base = readLandingContent(locale)
+ return { ...base, faqData: { ...base.faqData, questions: withSupportedRails(base.faqData.questions) } }
+}
+
+function readLandingContent(locale: Locale): LandingContent {
const content = readSingletonContentLocalized