import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:hash_wallet/entities/fiat_currency.dart'; import 'dart:convert'; // Hash Bags price endpoint. Backed by the Cloudflare Worker in // github.com/Such-Software/hash-wallet-prices: Kraken for majors, Nonlogs + // volume-weighted CexSwap for WOW, KV-cached every 60s. // // Non-USD fiats are converted server-side through ECB daily reference rates // (since 2026-08-16). An unknown quote currency returns price=0 and the UI // shows the existing "price unavailable" fallback. // // TODO: add a .onion mirror once we deploy a Tor hidden service and update // _fiatApiOnionAuthority — Tor users currently fall back to clearnet. const _fiatApiClearNetAuthority = 'prices.neroswap.com'; const _fiatApiOnionAuthority = ''; const _fiatApiPath = '/v2/rates'; Future _fetchPrice(String crypto, String fiat, bool torOnly) async { final Map queryParams = { 'base': crypto.split(".").first, 'quote': fiat, }; num price = 0.0; try { final clearnetUri = Uri.https(_fiatApiClearNetAuthority, _fiatApiPath, queryParams); final onionUri = _fiatApiOnionAuthority.isEmpty ? clearnetUri : Uri.http(_fiatApiOnionAuthority, _fiatApiPath, queryParams); final response = await ProxyWrapper().get( onionUri: onionUri, clearnetUri: torOnly ? onionUri : clearnetUri, ); if (response.statusCode != 200) { return 0.0; } final responseJSON = json.decode(response.body) as Map; final results = responseJSON['results'] as Map; if (results.isNotEmpty) { price = results.values.first as num; } return price.toDouble(); } catch (e) { return price.toDouble(); } } /// Override specific [CryptoCurrency] to fix its price to the price of another /// e.g. nDEPS should have the same price as DEPS, but only DEPS is tracked CryptoCurrency _overrideCryptoCurrency(CryptoCurrency crypto) { if (crypto.title == CryptoCurrency.ndeps.title) return CryptoCurrency.deps; return crypto; } class FiatConversionService { static Future fetchPrice({ required CryptoCurrency crypto, required FiatCurrency fiat, required bool torOnly, }) async => await _fetchPrice(_overrideCryptoCurrency(crypto).toString(), fiat.toString(), torOnly); }