Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Preparing Ring Platform content
Preparing Ring Platform content
Preparing Ring Platform content
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.
| Denomination | Meaning | Configured identity |
|---|---|---|
credit_balance | Project-owned ledger unit | credit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency |
native_token | Clone-native token | tokens.nativeToken.symbol |
main_currency | Project settlement fiat | store.mainCurrency |
ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.
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.
Wallet, checkout, membership, and community funding resolve project value through the same denomination model.
ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.
The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.
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.
Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.
Same-workflow: catalog display, checkout presentment, and server-side charge creation.
Deep-dive: Token Desk quotes, credit accounting, and native-token balances.
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.
| Denomination | Meaning | Configured identity |
|---|---|---|
credit_balance | Project-owned ledger unit | credit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency |
native_token | Clone-native token | tokens.nativeToken.symbol |
main_currency | Project settlement fiat | store.mainCurrency |
ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.
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.
Wallet, checkout, membership, and community funding resolve project value through the same denomination model.
ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.
The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.
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.
Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.
Same-workflow: catalog display, checkout presentment, and server-side charge creation.
Deep-dive: Token Desk quotes, credit accounting, and native-token balances.
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.
| Denomination | Meaning | Configured identity |
|---|---|---|
credit_balance | Project-owned ledger unit | credit.creditBalanceUnitLabel and credit.creditBalanceUnitToMainCurrency |
native_token | Clone-native token | tokens.nativeToken.symbol |
main_currency | Project settlement fiat | store.mainCurrency |
ValueDenomination contains exactly those three values. Currency symbols such as RING, USD, or UAH are display/config values, not denomination IDs.
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.
Wallet, checkout, membership, and community funding resolve project value through the same denomination model.
ProcessConductor refreshes fiat presentment rates while manual overrides remain available in clone config.
The store separates what a buyer sees from the fiat currency a card or PayPal gateway charges.
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.
Depends-on: PaymentConductor consumes Oracle rates when a rail crosses denominations.
Same-workflow: catalog display, checkout presentment, and server-side charge creation.
Deep-dive: Token Desk quotes, credit accounting, and native-token balances.
RING/USDring-config.fx resolves providers in this order:
fx.byMainCurrency[store.mainCurrency]UAHfx.default for other main currenciesThe shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.
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.
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.
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 pipeline | lib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.ts | ProcessConductor handler, ID, and cron path |
| Conversion API | app/api/prices/conversion/route.ts | Public native ↔ main rate and conversion contract |
| SSR hydrate | app/layout.tsx | AuthenticatedAppShell warms and reads rates |
| Client provider | components/providers/app-client-shell.tsx | Passes initialExchangeRates to store currency context |
| Store currency context | features/store/currency-context.tsx | Display mode, conversion, formatting, preferences |
| Checkout presentment | features/store/components/checkout/prebilling-page.tsx | Fiat/crypto droplist and fiat paymentCurrency |
| Checkout charge | app/_actions/store-checkout-payment.ts | Server-side fiat recomputation for card/PayPal |
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.
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.
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.
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.
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.
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.
{ "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.
AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.
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.
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.
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/USDring-config.fx resolves providers in this order:
fx.byMainCurrency[store.mainCurrency]UAHfx.default for other main currenciesThe shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.
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.
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.
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 pipeline | lib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.ts | ProcessConductor handler, ID, and cron path |
| Conversion API | app/api/prices/conversion/route.ts | Public native ↔ main rate and conversion contract |
| SSR hydrate | app/layout.tsx | AuthenticatedAppShell warms and reads rates |
| Client provider | components/providers/app-client-shell.tsx | Passes initialExchangeRates to store currency context |
| Store currency context | features/store/currency-context.tsx | Display mode, conversion, formatting, preferences |
| Checkout presentment | features/store/components/checkout/prebilling-page.tsx | Fiat/crypto droplist and fiat paymentCurrency |
| Checkout charge | app/_actions/store-checkout-payment.ts | Server-side fiat recomputation for card/PayPal |
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.
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.
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.
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.
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.
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.
{ "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.
AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.
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.
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.
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/USDring-config.fx resolves providers in this order:
fx.byMainCurrency[store.mainCurrency]UAHfx.default for other main currenciesThe shipped default uses NBU for UAH and open_er_api otherwise. fx.manualOverrides wins over both static rates and the live overlay.
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.
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.
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 pipeline | lib/processes/fx/fx-feed-refresh.ts, lib/processes/registry.ts | ProcessConductor handler, ID, and cron path |
| Conversion API | app/api/prices/conversion/route.ts | Public native ↔ main rate and conversion contract |
| SSR hydrate | app/layout.tsx | AuthenticatedAppShell warms and reads rates |
| Client provider | components/providers/app-client-shell.tsx | Passes initialExchangeRates to store currency context |
| Store currency context | features/store/currency-context.tsx | Display mode, conversion, formatting, preferences |
| Checkout presentment | features/store/components/checkout/prebilling-page.tsx | Fiat/crypto droplist and fiat paymentCurrency |
| Checkout charge | app/_actions/store-checkout-payment.ts | Server-side fiat recomputation for card/PayPal |
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.
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.
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.
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.
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.
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.
{ "from": "RING", "to": "USD" } is invalid even when those are the clone’s configured symbols. Send denomination IDs, not symbols.
AuthenticatedAppShell calls ensureFxFeedFresh(), then getExchangeRates(). If refresh fails, the shell leaves initialExchangeRates null and client code falls back to static ring-config rates.
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.
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.
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.