You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Public runtime configuration for the Chimera wallet. Edits to the JSON files in this repo change wallet behaviour without an app release.
Files
File
URL
Used by
dev.json
…/refs/heads/main/dev.json
Development builds and EAS internal dev variant
preview.json
…/refs/heads/main/preview.json
Preview / QA builds (prod-shaped artifact, separate runtime env tag)
staging.json
…/refs/heads/main/staging.json
Staging builds
prod.json
…/refs/heads/main/prod.json
Released production builds
Each file shares the same schema. The wallet picks the URL based on the build env (--env=dev|preview|staging|prod).
Banner copy lives under banners/content/<contentId>/<locale>.md. Banner images live under banners/images/.
Fetch + cache behaviour
Step
Behaviour
Cache TTL
5 minutes
Stale-while-revalidate
App boots from the last cached JSON; a background fetch refreshes it
Fetch failure
App keeps using the last cached JSON; no user-visible error
First launch
Built-in code defaults apply until the first fetch lands
Apply cadence
UI consumers re-render automatically when the cache updates
Precedence — code defaults vs. remote config
Feature flags (the features block) are evaluated through six precedence layers, highest wins:
Runtime override — set by dev-tools 5-tap menu (persisted on device)
Remote config — this repo
Brand defaults — secondfi in packages/config/feature-flags-defaults.ts
Environment defaults — development vs production
Platform defaults — mobile / web / extension
Code defaults — the safest baseline
A flag omitted from a remote JSON keeps whichever lower-precedence value applied. Setting features.earn: false in prod.json is the canonical kill-switch for the Earn tab.
Non-feature-flag fields (hardwareWallets, swap, ramp, earn, dapps, cards, secondfi, allowedLinks, banners, disableSigning, maintenance) have no code-defaults layer — they are read directly from the remote JSON.
Schema reference
Each section below describes:
Wire format — the JSON shape
Read by — the wallet code paths that consume the field
Effect — what flipping / setting / omitting the field does to the running app
Read-only mode. A warning banner ("disable signing") is rendered at the top of the dashboard. Send / swap / receive flows that build or submit transactions surface the banner and refuse to sign. Used as an emergency switch when chimera's signing backend is suspected of producing bad transactions.
{ ledger?: DeviceTransports, trezor?: DeviceTransports } where DeviceTransports = { usb?: PlatformCells, ble?: PlatformCells } and PlatformCells = { extension?, android?, ios? }. Each leaf cell is a boolean. Web shares the extension cell.
The matching pill is shown on the device list; the user can connect that device over that transport on that platform.
Effect when cell is false / unset
Strict opt-in — the pill is hidden. If a device has no transport enabled for the current platform, the entire device entry is hidden.
Notes
A device-local dev-tools override (5-tap menu) can flip individual cells without redeploying remote config. The override is per-cell — unset override cells fall through to remote config.
Each device gets a stable installation ID hashed to a 0..99 bucket. The flag evaluates true when the bucket is below rolloutPercentage. A given installation always sees the same answer until the percentage changes.
Flag inventory
Navigation tabs
Flag
Effect when true
earn
Earn tab visible in the bottom tab bar. Also gated by the remote earn.gauntlet.enable field (see below).
card
Card tab visible.
portfolio
Portfolio tab visible.
Card sub-features (inside the Card tab)
Flag
Effect when true
cardSpendingInsights
Spending-insights screen unlocked from the card dashboard.
cardLimits
Card limits screen unlocked.
cardEarn
Earn-on-card affordance unlocked.
Chain-specific
Flag
Effect when true
cardanoStaking
Delegation + governance entry points unlocked on Cardano.
earnDefi
DeFi earn opportunities surface in the Earn tab (Liqwid, Lenfi, etc.).
Earn strategies
Flag
Effect when true
earnStrategyCurveRusdy
Curve rUSDY vault visible.
earnStrategyGtUsda
Aera gtUSDa vault visible. Additionally requiresearn.gauntlet.enable: true because the vault is powered by the Gauntlet backend.
Core wallet
Flag
Effect when true
send
Send button + flow available on the dashboard.
receive
Receive button + flow available.
addWallet
"Add wallet" affordance in the wallet picker.
swap
Swap quick-action + flow available.
buyCrypto
Ramps on-ramp ("Buy") quick-action available.
sellCrypto
Ramps off-ramp ("Sell") flow available.
activity
Activity tab / list available.
Onboarding
Flag
Effect when true
createWallet
"Create a new wallet" flow visible during onboarding.
restoreWallet
"Restore a wallet" (seed phrase) flow visible.
socialLogin
Web3Auth social-login flow visible.
connectHardwareWallet
Hardware-wallet onboarding flow visible.
Additional
Flag
Effect when true
dappConnector
DApp connector (CIP-30) is injected. On the extension, the content script reads this flag from chrome.storage before injecting any provider.
discover
Discover (DApp browser) tab visible.
midnightAirdrop
Midnight NIGHT-claim entry point surfaces in Settings.
escrowRedeemPrimary
NIGHT redeem builds via the self-built escrow path first, falling back to Midnight /build on error. Default off — Midnight is primary.
submitNightClaimViaMidnight
NIGHT claim submissions go through Midnight's /thaws/{addr}/transactions endpoint regardless of which build path produced the tx.
addressBook
Address-book entries in settings + send flow.
transactionFilters
Filter pills on the activity / transaction history view.
pushNotifications
Push-notification permission prompt + handlers active. Defaults: on for mobile, off for web/extension.
portfolioChart
Time-series chart on the portfolio screen.
Developer tools (local-only — not honoured from remote config in prod)
Flag
Effect when true
devTools
Settings → Developer Tools menu visible. Enabled in dev builds; in prod, requires the 5-tap unlock.
cardMockData
Card screens render fixture data instead of hitting the card backend.
browserExtraIdentities
Browser's "Show as" identity picker exposes Eternl + Lace in addition to SecondFi + Yoroi.
txSimulation
Transaction-simulation step runs before signing.
encryptedBackupExport
Encrypted-backup export affordance on the recovery-phrase screen. (The import side via deep link is always on.)
The feature / chain is visible but disabled. A "we're working on it" banner renders inline on the dashboard chain page and the quick-action button for the feature is greyed out.
Effect when false / omitted
Normal behaviour.
Difference vs. features.<x>: false
A feature flag hides the surface. Maintenance shows the surface with a warning. Use maintenance when you want users to know the feature exists but is temporarily unavailable.
Only the listed providers participate in quote aggregation. Omit one to silently drop it from the comparator. Empty array → no swap providers.
partners
{ [providerId]: string }
SwapProvider → swap SDK initialisation
Partner-id / referrer string passed to each DEX for revenue-share attribution.
authTokens
{ [providerId]: string }
SwapProvider → swap SDK initialisation
Per-provider API auth token. Only set for providers that require one (e.g. dexhunter).
initialPair.tokenIn / initialPair.tokenOut
Routing token id (. = native ADA; <policyId>.<assetNameHex> for Cardano tokens)
SwapProvider
Pre-fills the swap form's "from" / "to" tokens on first open. Once the user changes either side manually, the pre-fill is sticky for the rest of the session.
excludedTokens
string[] (routing token ids)
Token picker
Listed tokens are hidden from the swap token picker. Used to suppress scam / known-broken tokens.
verifiedTokens
string[] (routing token ids)
Token picker
Listed tokens render with a "verified" checkmark badge in the picker. Visual hint only — does not affect swap routing.
Ramp flow (/ramp Expo Router route) and RampsService
Effect when populated
Only the listed providers are offered on the buy / sell crypto screen. The order in the array drives the display order.
Effect when empty / omitted
No ramp providers offered — Buy / Sell buttons show "no providers available".
earn
{
"earn": {
"gauntlet": {
"enable": true
}
}
}
Wire format
{ gauntlet?: { enable?: boolean } }
Read by
getEarnGauntletEnabled() → ConfigProvider pushes the value into the earn-backend client module (isEarnGauntletEnabled()) and folds it into the features.earn evaluation layer.
Effect when true
The Earn tab is allowed (subject to other gates), earn-backend-client calls hit https://earn.api.dev.secondfi.io, and the Aera gtUSDa vault becomes eligible (still needs features.earnStrategyGtUsda: true).
Effect when false / omitted
The Earn tab is hidden (overrides the brand default earn: true), and every earn-backend call short-circuits with EarnBackendDisabledError. undefined is treated as false — explicit opt-in is required.
DApp browser refuses to load any URL that starts with one of these prefixes. Used as a kill-switch for known-phishing sites.
recommended
Array of recommended-dapp records
Surface in the Discover tab as featured DApps. logo is a filename under banners/images/ (path relative to this repo). origins is the set of URLs that should be treated as the same DApp. isSingleAddress: true makes the connector only inject the active account (no multi-address enumeration).
filters
{ <filter-label>: <category[]> }
Defines the category pills in the Discover tab and which category values they each match.
"emurgo" | "wirex" (any other value → undefined → fallback)
Picks the ZeroDev paymaster that sponsors SecondFi smart-account gas. Switching between wirex and emurgo changes which provider absorbs gas fees for ERC-4337 user-ops.
smartAccount.usdcDepositRequired
boolean
When true, smart-account creation gates the user on depositing USDC first (the deposit funds the account's initial state). When false, the account is created without a deposit prerequisite.
Exact tokens allowed as the source asset when topping up the card. The picker only shows tokens in this list.
topUp.chainIds
string[] of CAIP-2 chain ids
Additionally allows the native asset on each listed chain (ETH on eip155:1, SOL on solana:…, etc.). Non-native ERC-20s on those chains must still be in tokenIds to surface.
topUp.minAmount
number (USD)
Minimum top-up amount enforced on the amount-entry screen, source picker (sources below the floor are greyed out), and submit validation. A positive number sets the floor; 0, a negative number, a non-finite value, or omitting the field disables the minimum entirely (the in-app fallback is 0).
tokenIds / chainIds are read by the card top-up asset picker — omitting both disables the picker (no fundable assets). minAmount is read by the card top-up amount and source screens.
When a push notification arrives with an open_url action, the URL is matched against this allowlist by prefix. Unmatched URLs are dropped with a Notification open_url dropped — not in allowedLinks log line. Trust boundary — push payloads originate outside the remote-config control plane, so the allowlist is the trust gate.
Not for banner CTAs
Banners live in the same JSON, so an allowlist check against them would be circular. Banner CTAs are not validated against this list.
Stable identifier. Used as the dismissal key — re-using an id on a new banner means returning users won't see it if they dismissed the previous one.
contentId
string
Folder name under banners/content/<contentId>/. The app loads <contentId>/<locale>.md, falling back to en-US.md. The Markdown body becomes the banner copy: first heading → title, body → description, [cta]: <label> → button text.
type
"info" | "warning" | "error" | "success"
Drives the banner colour / icon.
imageUrl
repository-relative path
Asset under banners/images/. Loaded via the same raw-githubusercontent URL as the JSON.
ctaLink
string
Either an Expo Router path (must start with /, e.g. /ramp, /(tabs)/portfolio) or a full external URL (https://…). Internal paths navigate via router.push; external URLs open the browser.
startDate / endDate
ISO 8601 UTC timestamp
Optional. Banner is filtered out before startDate and after endDate.
isDismissible
boolean
If false, the banner has no close button and stays visible until removed from remote config.
priorityWeight
number
Banners are sorted descending by weight, so higher numbers appear first.
slot
"home" (currently the only value)
Which mount point renders the banner. Surfaces opt in by mounting <RemoteBanners slot="..."/> and filtering. Defaults to "home" when omitted.
Per-platform overrides for any of: contentId, type, imageUrl, ctaLink, startDate, endDate, isDismissible, priorityWeight, slot. Overrides are shallow-merged on top of the base banner. Useful for platform-specific copy or weight tweaks.
Banner Markdown format
banners/content/<contentId>/<locale>.md:
# Banner title
Banner body text.
[cta]: CTA label
Locales matching the user's selected language are tried first; falls back to en-US.md.
Trigger a 5-tap on the About screen to unlock dev tools.
Settings → Developer Tools → Feature Flags.
Every flag is listed with its evaluated value and source (runtime / remote / brand / environment / platform / code).
Long-press a row to set a per-device runtime override (highest precedence; persists across launches).
Security considerations
Public repo — never commit secrets that grant write access to backend services. Partner ids, API keys with read-only or referrer-only scope, and rate-limited public tokens are fine.
Trust boundary — allowedLinks is the only field that gates content originating outside this repo (push notifications). Treat changes to that field carefully.
Banner CTAs — links inside banners[].ctaLink are not validated against allowedLinks (they originate from the same writer). Anyone with write access here can route users to arbitrary URLs via a banner.
Rate limit — each device fetches ~12 times per hour (5-minute cache).
Versioning
Use Conventional Commits so the history reads as a changelog:
feat: enable earn.gauntlet on prod
fix: disable swap kill-switch on staging
perf: bump midnightAirdrop rollout to 50%
revert: roll back gauntlet enable on prod