Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)
    Ring Platform Logo

    Loading documentation...

    Preparing Ring Platform content

    Ring Platform Logo

    Loading documentation...

    Preparing Ring Platform content

    Ring Platform Logo

    Loading documentation...

    Preparing Ring Platform content

    Ring Oracle

    Ring Oracle is the server-only rate facade at @/lib/ring-oracle. It gives payment, wallet, membership, public-pool, and store code one vocabulary for project value instead of hard-coding token or fiat symbols.

    Use Founder / Developer in the docs sidebar to filter this page. Founders see the operator journey and checkout behavior; developers see verified modules, routes, payloads, and smoke commands.

    Three denominations, no symbol aliases

    DenominationMeaningConfigured identity
    credit_balanceProject-owned ledger unitcredit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency
    native_tokenClone-native tokentokens.nativeToken.symbol
    main_currencyProject settlement fiatstore.mainCurrency

    ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.

    Conversion API is intentionally narrower

    GET and POST /api/prices/conversion accept only native_token and main_currency. credit_balance uses the credit accounting surface, and legacy RING / USD request aliases return HTTP 400.

    Why this matters for your clone

    Consistent money language

    Wallet, checkout, membership, and community funding resolve project value through the same denomination model.

    Operational FX feed

    ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.

    Truthful checkout

    The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.

    Operator journey

    1. Choose the clone’s money identities

    Set the project main currency, supported fiat presentment currencies, supported crypto symbols, native token, and credit accounting rate in ring-config.json. Ring Oracle reads those project identities; product code does not need a special case.

    Architecture

    SurfaceVerified pathResponsibility
    Facadelib/ring-oracle/index.tsServer-only export surface for every rate family
    Denominationslib/value-denomination.tsExact ValueDenomination triad and validation
    Desk oraclefeatures/wallet/services/native-token-oracle.tsNative ↔ main rate, signed quotes, audit log
    Chainlink bridgefeatures/wallet/services/native-token-chainlink-oracle.tsAllowlisted external EVM token feeds
    Fiat FXlib/fx/fx-feed-service.ts, lib/fx/fx-rates-overlay.tsProvider resolution, persistent cache, live overlay

    Related documentation

    Related documentation

    PaymentConductor

    Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.

    Multi-Vendor Store

    Same-workflow: catalog display, checkout presentment, and server-side charge creation.

    Wallet & Credit System

    Deep-dive: Token Desk quotes, credit accounting, and native-token balances.

    Ring Oracle

    Ring Oracle is the server-only rate facade at @/lib/ring-oracle. It gives payment, wallet, membership, public-pool, and store code one vocabulary for project value instead of hard-coding token or fiat symbols.

    Use Founder / Developer in the docs sidebar to filter this page. Founders see the operator journey and checkout behavior; developers see verified modules, routes, payloads, and smoke commands.

    Three denominations, no symbol aliases

    DenominationMeaningConfigured identity
    credit_balanceProject-owned ledger unitcredit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency
    native_tokenClone-native tokentokens.nativeToken.symbol
    main_currencyProject settlement fiatstore.mainCurrency

    ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.

    Conversion API is intentionally narrower

    GET and POST /api/prices/conversion accept only native_token and main_currency. credit_balance uses the credit accounting surface, and legacy RING / USD request aliases return HTTP 400.

    Why this matters for your clone

    Consistent money language

    Wallet, checkout, membership, and community funding resolve project value through the same denomination model.

    Operational FX feed

    ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.

    Truthful checkout

    The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.

    Operator journey

    1. Choose the clone’s money identities

    Set the project main currency, supported fiat presentment currencies, supported crypto symbols, native token, and credit accounting rate in ring-config.json. Ring Oracle reads those project identities; product code does not need a special case.

    Architecture

    SurfaceVerified pathResponsibility
    Facadelib/ring-oracle/index.tsServer-only export surface for every rate family
    Denominationslib/value-denomination.tsExact ValueDenomination triad and validation
    Desk oraclefeatures/wallet/services/native-token-oracle.tsNative ↔ main rate, signed quotes, audit log
    Chainlink bridgefeatures/wallet/services/native-token-chainlink-oracle.tsAllowlisted external EVM token feeds
    Fiat FXlib/fx/fx-feed-service.ts, lib/fx/fx-rates-overlay.tsProvider resolution, persistent cache, live overlay

    Related documentation

    Related documentation

    PaymentConductor

    Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.

    Multi-Vendor Store

    Same-workflow: catalog display, checkout presentment, and server-side charge creation.

    Wallet & Credit System

    Deep-dive: Token Desk quotes, credit accounting, and native-token balances.

    Ring Oracle

    Ring Oracle is the server-only rate facade at @/lib/ring-oracle. It gives payment, wallet, membership, public-pool, and store code one vocabulary for project value instead of hard-coding token or fiat symbols.

    Use Founder / Developer in the docs sidebar to filter this page. Founders see the operator journey and checkout behavior; developers see verified modules, routes, payloads, and smoke commands.

    Three denominations, no symbol aliases

    DenominationMeaningConfigured identity
    credit_balanceProject-owned ledger unitcredit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency
    native_tokenClone-native tokentokens.nativeToken.symbol
    main_currencyProject settlement fiatstore.mainCurrency

    ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.

    Conversion API is intentionally narrower

    GET and POST /api/prices/conversion accept only native_token and main_currency. credit_balance uses the credit accounting surface, and legacy RING / USD request aliases return HTTP 400.

    Why this matters for your clone

    Consistent money language

    Wallet, checkout, membership, and community funding resolve project value through the same denomination model.

    Operational FX feed

    ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.

    Truthful checkout

    The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.

    Operator journey

    1. Choose the clone’s money identities

    Set the project main currency, supported fiat presentment currencies, supported crypto symbols, native token, and credit accounting rate in ring-config.json. Ring Oracle reads those project identities; product code does not need a special case.

    Architecture

    SurfaceVerified pathResponsibility
    Facadelib/ring-oracle/index.tsServer-only export surface for every rate family
    Denominationslib/value-denomination.tsExact ValueDenomination triad and validation
    Desk oraclefeatures/wallet/services/native-token-oracle.tsNative ↔ main rate, signed quotes, audit log
    Chainlink bridgefeatures/wallet/services/native-token-chainlink-oracle.tsAllowlisted external EVM token feeds
    Fiat FXlib/fx/fx-feed-service.ts, lib/fx/fx-rates-overlay.tsProvider resolution, persistent cache, live overlay

    Related documentation

    Related documentation

    PaymentConductor

    Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.

    Multi-Vendor Store

    Same-workflow: catalog display, checkout presentment, and server-side charge creation.

    Wallet & Credit System

    Deep-dive: Token Desk quotes, credit accounting, and native-token balances.

    RING/USD

    2. Select the FX feed

    ring-config.fx resolves providers in this order:

    1. fx.byMainCurrency[store.mainCurrency]
    2. NBU when the main currency is UAH
    3. fx.default for other main currencies

    The shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.

    3. Operate desk and FX rates

    Open /admin/web3/settings as a superadmin to update the native-token desk rate, inspect the resolved fiat FX provider and last fetch time, or force an FX refresh. The UI reads GET /api/admin/web3/settings and GET /api/admin/fx; it writes with the corresponding POST routes.

    4. Schedule the feed route

    Production schedulers call GET /api/cron/fx-feed-refresh. Set CRON_SECRET and send it as a Bearer token. The route records the run through ProcessConductor under pipeline ID fx-feed-refresh; feed staleness still follows the configured refreshHours.

    5. Understand buyer presentment

    The left navigation rail switches between main_currency (the buyer’s last fiat preference) and native_token only. The checkout droplist follows that mode: fiat lists configured SupportedCurrencies; native lists configured SupportedCrypto.

    The review step converts product lines and totals through convertPrice / displayPrice. Card and PayPal remain fiat charges: checkout carries a fiat paymentCurrency, and the server recomputes the charge from the main-currency order total before calling PaymentConductor.

    A crypto amount in the checkout review is presentment, not proof that the card gateway will charge crypto. The payment rail and paymentCurrency decide settlement.

    Credit accounting
    lib/payments/credit-balance.ts
    Credit unit ↔ main accounting helpers
    FX pipelinelib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.tsProcessConductor handler, ID, and cron path
    Conversion APIapp/api/prices/conversion/route.tsPublic native ↔ main rate and conversion contract
    SSR hydrateapp/layout.tsxAuthenticatedAppShell warms and reads rates
    Client providercomponents/providers/app-client-shell.tsxPasses initialExchangeRates to store currency context
    Store currency contextfeatures/store/currency-context.tsxDisplay mode, conversion, formatting, preferences
    Checkout presentmentfeatures/store/components/checkout/prebilling-page.tsxFiat/crypto droplist and fiat paymentCurrency
    Checkout chargeapp/_actions/store-checkout-payment.tsServer-side fiat recomputation for card/PayPal

    Facade rule

    Server code imports rates from the facade, not from implementation modules:

    @/lib/ring-oracle imports server-only. Client components receive serializable rate data through AuthenticatedAppShell, AppClientShell, or the client-safe getLiveExchangeRates server action.

    FX refresh flow

    1. 1

      Configure provider resolution

      Provider IDs are nbu, open_er_api, and frankfurter. A hard guard replaces NBU with open_er_api whenever the main currency is not UAH.

    2. 2

      Protect and invoke the cron route

      The authorization check is conditional on CRON_SECRET, so production deployments must configure it. The response includes ProcessConductor runId plus refresh metadata; a disabled feed reports a successful skipped run. Rates persist under platform_settings id fx_feed (same hybrid JSONB pattern as the desk oracle). Ship k8s/cronjob-fx-feed-refresh.yaml for hourly cluster refresh.

    3. 3

      Inspect or force refresh as an admin

      GET /api/admin/fx returns resolved feed configuration, overrides, fetch time, a rate sample, and resolved rates for platform admins. POST /api/admin/fx accepts { "force": true } and refreshes the feed. Desk-rate reads and writes remain on the superadmin-only /api/admin/web3/settings route.

    Conversion API contract

    Read supported pairs

    GET /api/prices/conversion returns denominations: ["native_token", "main_currency"], both direction pairs, rates and inverse rates, source metadata, and limits from 0.000001 through 1000000.

    Convert an amount

    amount must be a positive decimal string, and from must differ from to. The response includes denomination IDs, configured display currencies, source amount, converted amount, exchange rate, timestamp, confidence, zero conversion fee, and source metadata.

    No backward compatibility aliases

    { "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.

    SSR and checkout boundaries

    1. 1

      Hydrate rates on the server

      AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.

    2. 2

      Seed and refresh the client provider

      AppClientShell passes the serializable rates to StorePaymentMethodsProvider. The provider starts from that SSR seed, then calls getLiveExchangeRates() after hydration to keep browser conversion aligned with server checkout.

    3. 3

      Keep display and charge currencies separate

      StorePaymentMethodsProvider.displayMode is only main_currency | native_token. PrebillingPage derives the droplist from getSupportedCurrencies() or getSupportedCrypto(), while preserving a fiat paymentCurrency for card and PayPal. submitStoreCheckoutPayment validates that fiat against the supported presentment pool and recomputes the amount server-side.

    Smoke verification

    Run the shipped smk46_ smoke from ring-platform.org:

    The smoke verifies pipeline registration, provider resolution and refresh, the native ↔ main service round-trip, optional conversion GET / POST contracts, HTTP 400 for legacy RING / USD, and cron response behavior.

    RING/USD

    2. Select the FX feed

    ring-config.fx resolves providers in this order:

    1. fx.byMainCurrency[store.mainCurrency]
    2. NBU when the main currency is UAH
    3. fx.default for other main currencies

    The shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.

    3. Operate desk and FX rates

    Open /admin/web3/settings as a superadmin to update the native-token desk rate, inspect the resolved fiat FX provider and last fetch time, or force an FX refresh. The UI reads GET /api/admin/web3/settings and GET /api/admin/fx; it writes with the corresponding POST routes.

    4. Schedule the feed route

    Production schedulers call GET /api/cron/fx-feed-refresh. Set CRON_SECRET and send it as a Bearer token. The route records the run through ProcessConductor under pipeline ID fx-feed-refresh; feed staleness still follows the configured refreshHours.

    5. Understand buyer presentment

    The left navigation rail switches between main_currency (the buyer’s last fiat preference) and native_token only. The checkout droplist follows that mode: fiat lists configured SupportedCurrencies; native lists configured SupportedCrypto.

    The review step converts product lines and totals through convertPrice / displayPrice. Card and PayPal remain fiat charges: checkout carries a fiat paymentCurrency, and the server recomputes the charge from the main-currency order total before calling PaymentConductor.

    A crypto amount in the checkout review is presentment, not proof that the card gateway will charge crypto. The payment rail and paymentCurrency decide settlement.

    Credit accounting
    lib/payments/credit-balance.ts
    Credit unit ↔ main accounting helpers
    FX pipelinelib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.tsProcessConductor handler, ID, and cron path
    Conversion APIapp/api/prices/conversion/route.tsPublic native ↔ main rate and conversion contract
    SSR hydrateapp/layout.tsxAuthenticatedAppShell warms and reads rates
    Client providercomponents/providers/app-client-shell.tsxPasses initialExchangeRates to store currency context
    Store currency contextfeatures/store/currency-context.tsxDisplay mode, conversion, formatting, preferences
    Checkout presentmentfeatures/store/components/checkout/prebilling-page.tsxFiat/crypto droplist and fiat paymentCurrency
    Checkout chargeapp/_actions/store-checkout-payment.tsServer-side fiat recomputation for card/PayPal

    Facade rule

    Server code imports rates from the facade, not from implementation modules:

    @/lib/ring-oracle imports server-only. Client components receive serializable rate data through AuthenticatedAppShell, AppClientShell, or the client-safe getLiveExchangeRates server action.

    FX refresh flow

    1. 1

      Configure provider resolution

      Provider IDs are nbu, open_er_api, and frankfurter. A hard guard replaces NBU with open_er_api whenever the main currency is not UAH.

    2. 2

      Protect and invoke the cron route

      The authorization check is conditional on CRON_SECRET, so production deployments must configure it. The response includes ProcessConductor runId plus refresh metadata; a disabled feed reports a successful skipped run. Rates persist under platform_settings id fx_feed (same hybrid JSONB pattern as the desk oracle). Ship k8s/cronjob-fx-feed-refresh.yaml for hourly cluster refresh.

    3. 3

      Inspect or force refresh as an admin

      GET /api/admin/fx returns resolved feed configuration, overrides, fetch time, a rate sample, and resolved rates for platform admins. POST /api/admin/fx accepts { "force": true } and refreshes the feed. Desk-rate reads and writes remain on the superadmin-only /api/admin/web3/settings route.

    Conversion API contract

    Read supported pairs

    GET /api/prices/conversion returns denominations: ["native_token", "main_currency"], both direction pairs, rates and inverse rates, source metadata, and limits from 0.000001 through 1000000.

    Convert an amount

    amount must be a positive decimal string, and from must differ from to. The response includes denomination IDs, configured display currencies, source amount, converted amount, exchange rate, timestamp, confidence, zero conversion fee, and source metadata.

    No backward compatibility aliases

    { "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.

    SSR and checkout boundaries

    1. 1

      Hydrate rates on the server

      AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.

    2. 2

      Seed and refresh the client provider

      AppClientShell passes the serializable rates to StorePaymentMethodsProvider. The provider starts from that SSR seed, then calls getLiveExchangeRates() after hydration to keep browser conversion aligned with server checkout.

    3. 3

      Keep display and charge currencies separate

      StorePaymentMethodsProvider.displayMode is only main_currency | native_token. PrebillingPage derives the droplist from getSupportedCurrencies() or getSupportedCrypto(), while preserving a fiat paymentCurrency for card and PayPal. submitStoreCheckoutPayment validates that fiat against the supported presentment pool and recomputes the amount server-side.

    Smoke verification

    Run the shipped smk46_ smoke from ring-platform.org:

    The smoke verifies pipeline registration, provider resolution and refresh, the native ↔ main service round-trip, optional conversion GET / POST contracts, HTTP 400 for legacy RING / USD, and cron response behavior.

    RING/USD

    2. Select the FX feed

    ring-config.fx resolves providers in this order:

    1. fx.byMainCurrency[store.mainCurrency]
    2. NBU when the main currency is UAH
    3. fx.default for other main currencies

    The shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.

    3. Operate desk and FX rates

    Open /admin/web3/settings as a superadmin to update the native-token desk rate, inspect the resolved fiat FX provider and last fetch time, or force an FX refresh. The UI reads GET /api/admin/web3/settings and GET /api/admin/fx; it writes with the corresponding POST routes.

    4. Schedule the feed route

    Production schedulers call GET /api/cron/fx-feed-refresh. Set CRON_SECRET and send it as a Bearer token. The route records the run through ProcessConductor under pipeline ID fx-feed-refresh; feed staleness still follows the configured refreshHours.

    5. Understand buyer presentment

    The left navigation rail switches between main_currency (the buyer’s last fiat preference) and native_token only. The checkout droplist follows that mode: fiat lists configured SupportedCurrencies; native lists configured SupportedCrypto.

    The review step converts product lines and totals through convertPrice / displayPrice. Card and PayPal remain fiat charges: checkout carries a fiat paymentCurrency, and the server recomputes the charge from the main-currency order total before calling PaymentConductor.

    A crypto amount in the checkout review is presentment, not proof that the card gateway will charge crypto. The payment rail and paymentCurrency decide settlement.

    Credit accounting
    lib/payments/credit-balance.ts
    Credit unit ↔ main accounting helpers
    FX pipelinelib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.tsProcessConductor handler, ID, and cron path
    Conversion APIapp/api/prices/conversion/route.tsPublic native ↔ main rate and conversion contract
    SSR hydrateapp/layout.tsxAuthenticatedAppShell warms and reads rates
    Client providercomponents/providers/app-client-shell.tsxPasses initialExchangeRates to store currency context
    Store currency contextfeatures/store/currency-context.tsxDisplay mode, conversion, formatting, preferences
    Checkout presentmentfeatures/store/components/checkout/prebilling-page.tsxFiat/crypto droplist and fiat paymentCurrency
    Checkout chargeapp/_actions/store-checkout-payment.tsServer-side fiat recomputation for card/PayPal

    Facade rule

    Server code imports rates from the facade, not from implementation modules:

    @/lib/ring-oracle imports server-only. Client components receive serializable rate data through AuthenticatedAppShell, AppClientShell, or the client-safe getLiveExchangeRates server action.

    FX refresh flow

    1. 1

      Configure provider resolution

      Provider IDs are nbu, open_er_api, and frankfurter. A hard guard replaces NBU with open_er_api whenever the main currency is not UAH.

    2. 2

      Protect and invoke the cron route

      The authorization check is conditional on CRON_SECRET, so production deployments must configure it. The response includes ProcessConductor runId plus refresh metadata; a disabled feed reports a successful skipped run. Rates persist under platform_settings id fx_feed (same hybrid JSONB pattern as the desk oracle). Ship k8s/cronjob-fx-feed-refresh.yaml for hourly cluster refresh.

    3. 3

      Inspect or force refresh as an admin

      GET /api/admin/fx returns resolved feed configuration, overrides, fetch time, a rate sample, and resolved rates for platform admins. POST /api/admin/fx accepts { "force": true } and refreshes the feed. Desk-rate reads and writes remain on the superadmin-only /api/admin/web3/settings route.

    Conversion API contract

    Read supported pairs

    GET /api/prices/conversion returns denominations: ["native_token", "main_currency"], both direction pairs, rates and inverse rates, source metadata, and limits from 0.000001 through 1000000.

    Convert an amount

    amount must be a positive decimal string, and from must differ from to. The response includes denomination IDs, configured display currencies, source amount, converted amount, exchange rate, timestamp, confidence, zero conversion fee, and source metadata.

    No backward compatibility aliases

    { "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.

    SSR and checkout boundaries

    1. 1

      Hydrate rates on the server

      AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.

    2. 2

      Seed and refresh the client provider

      AppClientShell passes the serializable rates to StorePaymentMethodsProvider. The provider starts from that SSR seed, then calls getLiveExchangeRates() after hydration to keep browser conversion aligned with server checkout.

    3. 3

      Keep display and charge currencies separate

      StorePaymentMethodsProvider.displayMode is only main_currency | native_token. PrebillingPage derives the droplist from getSupportedCurrencies() or getSupportedCrypto(), while preserving a fiat paymentCurrency for card and PayPal. submitStoreCheckoutPayment validates that fiat against the supported presentment pool and recomputes the amount server-side.

    Smoke verification

    Run the shipped smk46_ smoke from ring-platform.org:

    The smoke verifies pipeline registration, provider resolution and refresh, the native ↔ main service round-trip, optional conversion GET / POST contracts, HTTP 400 for legacy RING / USD, and cron response behavior.

    1. Docs
    2. /Features
    3. /Ring Oracle

    Updated Aug 4, 20266 min listen

    1. Docs
    2. /Features
    3. /Ring Oracle

    Updated Aug 4, 20266 min listen

    1. Docs
    2. /Features
    3. /Ring Oracle

    Updated Aug 4, 20266 min listen