Converting & rates
use Fomvasss\Currency\Facades\Currency;The facade resolves the currency binding (Fomvasss\Currency\Currency), so you can also inject Fomvasss\Currency\Currency or call app('currency').
How rates are expressed
Section titled “How rates are expressed”A rate is the amount of the base currency for one unit of the currency. With the default base UAH and Monobank:
Currency::getRate('USD'); // ~41.5 — UAH per 1 USDEvery provider returns rates as ['USD' => ['buy' => float, 'sell' => float], ...] against its own base currency; Currency reduces that pair to one number by the rate type and, when your base currency differs from the provider’s, recalculates it — see Base currency.
Rate types
Section titled “Rate types”| Type | Value |
|---|---|
buy | Bank buying rate — you sell the currency |
sell | Bank selling rate — you buy the currency |
average | (buy + sell) / 2 |
all | Only for getRates() / getRatesAt(): the raw ['buy' => ..., 'sell' => ...] pair |
Passing null (the default everywhere) uses default_rate_type from config. Anything else throws InvalidArgumentException: Invalid rate type: ....
Providers without a buy/sell split (NBU, ExchangeRatesAPI, CurrencyAPI, Fixer) return the same value for both, so all three types give the same number. jsDelivr returns a synthetic ±0.5% spread around the mid rate.
convert()
Section titled “convert()”Currency::convert(float $amount, string $from, string $to, ?string $rateType = null): floatCurrency::convert(100, 'USD', 'UAH'); // 100 × rate(USD)Currency::convert(4150, 'UAH', 'USD'); // 4150 ÷ rate(USD)Currency::convert(100, 'usd', 'eur', 'buy'); // codes are case-insensitiveConversion goes through the base currency: $amount × rate($from) ÷ rate($to), where the rate of the base currency itself is 1. The same rate type is used on both legs, so convert(100, 'USD', 'EUR', 'buy') uses the buying rate of USD and the buying rate of EUR — it is not a “sell USD, buy EUR” cross rate.
The result is rounded to the target currency’s precision, or default_precision if the currency isn’t in currencies config. convert(100, 'USD', 'USD') skips the provider entirely and just rounds.
If the provider has no rate for $from or $to, convert() throws InvalidArgumentException: Currency rate not found for: XXX. This includes the case where the API is unreachable and nothing is cached — see Caching & failures.
getRate()
Section titled “getRate()”Currency::getRate(string $currency, ?string $rateType = null): ?floatCurrency::getRate('USD'); // config default typeCurrency::getRate('USD', 'sell');Currency::getRate('UAH'); // 1.0 — the base currencyCurrency::getRate('XYZ'); // null — unknown to the providerUnlike convert(), getRate() returns null instead of throwing when there is no rate.
getRates()
Section titled “getRates()”Currency::getRates(?string $rateType = null): arrayCurrency::getRates(); // ['USD' => 41.5, 'EUR' => 47.1, ...]Currency::getRates('all'); // ['USD' => ['buy' => 41.3, 'sell' => 41.7], ...]All currencies the provider returned — not filtered by the currencies config. The base currency itself is not in the array.
Checking support
Section titled “Checking support”Currency::isSupported('JPY'); // the provider has a rate for JPYCurrency::getSupportedCurrencies(); // ['USD', 'EUR', ...]Currency::getSupportedCurrenciesCount(); // e.g. ~200 for jsdelivrErrors at a glance
Section titled “Errors at a glance”| Situation | convert() / convertAt() | getRate() / getRateAt() | getRates() / getRatesAt() |
|---|---|---|---|
| Unknown rate type | InvalidArgumentException | InvalidArgumentException | InvalidArgumentException |
| No rate for the currency | InvalidArgumentException | null | currency absent |
| Custom base currency unknown to the provider | InvalidArgumentException | null | InvalidArgumentException |
| API down, nothing cached | InvalidArgumentException | null | [] (or the exception above with a custom base) |
Provider without historical rates (*At methods) | LogicException | LogicException | LogicException |