A lightweight TypeScript currency conversion package with React support. Fetch live or historical exchange rates from a public CDN or your own self-hosted endpoint.
- Latest and historical exchange rates
- CDN provider (zero config) or self-hosted endpoint
- React hook and component
- In-memory caching with TTL
- Automatic retries on network failure
- Full TypeScript types
- ESM + CommonJS, tree-shakeable
npm install @assystant/currency-converterReact is a peer dependency — install it if you haven't already:
npm install reactThe package has two entry points:
| Entry | Contains |
|---|---|
@assystant/currency-converter |
convertCurrency, error classes, types |
@assystant/currency-converter/react |
useCurrencyConverter, CurrencyConversion |
import { convertCurrency } from "@assystant/currency-converter";
const result = await convertCurrency({
amount: 100,
sourceCurrency: "USD",
targetCurrency: "INR",
});
console.log(result.convertedAmount); // e.g. 8342.12
console.log(result.exchangeRate); // e.g. 83.4212const result = await convertCurrency({
amount: 100,
sourceCurrency: "USD",
targetCurrency: "EUR",
date: "2024-01-15",
});const result = await convertCurrency({
amount: 100,
sourceCurrency: "USD",
targetCurrency: "EUR",
selfHostedEndpoint: "https://rates.your-company.com/convert",
selfHostedToken: "Token your_secret_api_token_here"
});| Param | Type | Required | Description |
|---|---|---|---|
amount |
number |
Yes | The amount to convert |
sourceCurrency |
string |
Yes | ISO 4217 source currency code (e.g. "USD") |
targetCurrency |
string |
Yes | ISO 4217 target currency code (e.g. "EUR") |
date |
string |
No | Historical date in YYYY-MM-DD format. Omit for latest rate |
selfHostedEndpoint |
string |
No | URL of your self-hosted rate endpoint. Overrides the CDN provider |
selfHostedToken |
string |
No | Bearer token sent as Authorization header to your self-hosted endpoint |
type CurrencyConversionResult = {
amount: number;
convertedAmount: number; // rounded to 4 decimal places
exchangeRate: number; // rounded to 4 decimal places
sourceCurrency: string; // uppercased
targetCurrency: string; // uppercased
date: string; // "latest" when no date was provided
provider: string; // "cdn" or "self_hosted"
};import { useCurrencyConverter } from "@assystant/currency-converter/react";
function PriceTag() {
const { convertedAmount, exchangeRate, loading, error } =
useCurrencyConverter({
amount: 100,
sourceCurrency: "USD",
targetCurrency: "EUR",
});
if (loading) return <span>Loading...</span>;
if (error) return <span>Error: {error.message}</span>;
return <span>{convertedAmount} EUR</span>;
}| Prop | Type | Required | Description |
|---|---|---|---|
amount |
number |
Yes | Amount to convert |
sourceCurrency |
string |
Yes | Source currency code |
targetCurrency |
string |
Yes | Target currency code |
date |
string |
No | Historical date (YYYY-MM-DD) |
enabled |
boolean |
No | Set to false to skip fetching. Defaults to true |
selfHostedEndpoint |
string |
No | Self-hosted rate endpoint URL |
selfHostedToken |
string |
No | Bearer token sent as Authorization header to your self-hosted endpoint |
| Field | Type | Description |
|---|---|---|
convertedAmount |
number | null |
Converted amount, or null while loading or on error |
exchangeRate |
number | null |
Exchange rate used, or null while loading or on error |
loading |
boolean |
true while a request is in flight |
error |
Error | null |
Error from the last failed request, or null |
A new fetch is triggered any time amount, sourceCurrency, targetCurrency, date, selfHostedEndpoint, or selfHostedToken changes. In-flight requests are automatically cancelled when props change or the component unmounts.
A ready-made display component built on top of useCurrencyConverter.
import { CurrencyConversion } from "@assystant/currency-converter/react";
function App() {
return (
<CurrencyConversion
amount={250}
sourceCurrency="USD"
targetCurrency="GBP"
/>
);
}Output (default):
250 USD = 197.25 GBP
Rate: 1 USD = 0.789 GBP
Date: latest
| Prop | Type | Default | Description |
|---|---|---|---|
amount |
number |
— | Amount to convert |
sourceCurrency |
string |
— | Source currency code |
targetCurrency |
string |
— | Target currency code |
date |
string |
— | Historical date (YYYY-MM-DD) |
selfHostedEndpoint |
string |
— | Self-hosted rate endpoint URL |
selfHostedToken |
string |
— | Bearer token sent as Authorization header to your self-hosted endpoint |
showRate |
boolean |
true |
Show the exchange rate line |
showDate |
boolean |
true |
Show the date line |
loadingComponent |
ReactNode |
<span>Loading...</span> |
Rendered while fetching |
errorComponent |
ReactNode |
<span>Failed to fetch currency conversion.</span> |
Rendered on error |
Uses the public @fawazahmed0/currency-api. No API key or configuration required.
- Latest rates:
https://latest.currency-api.pages.dev/v1/currencies/{source}.json - Historical rates:
https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@{date}/v1/currencies/{source}.json
Point the package at your own endpoint by passing selfHostedEndpoint as a prop, or by setting the SELF_HOSTED_ENDPOINT environment variable. Optionally protect the endpoint with a token via selfHostedToken or SELF_HOSTED_TOKEN.
Expected request:
GET {endpoint}?source=USD&target=INR
GET {endpoint}?source=USD&target=INR&date=2024-01-15
Authorization: Bearer <token> (only when a token is provided)
Expected response:
{ "rate": 83.4212 }The package will throw UnsupportedCurrencyError if the response does not contain a numeric rate field.
selfHostedEndpointpassed as a prop/param at runtimeSELF_HOSTED_ENDPOINTenvironment variable- CDN provider (default fallback)
Token resolution follows the same priority: selfHostedToken prop/param overrides SELF_HOSTED_TOKEN environment variable.
| Variable | Description |
|---|---|
CURRENCY_PROVIDER |
Set to self_hosted to use the self-hosted provider by default. Defaults to cdn |
SELF_HOSTED_ENDPOINT |
Base URL of your self-hosted rate endpoint. Required when CURRENCY_PROVIDER=self_hosted |
SELF_HOSTED_TOKEN |
Bearer token sent as Authorization header to your self-hosted endpoint |
Example .env:
CURRENCY_PROVIDER=self_hosted
SELF_HOSTED_ENDPOINT=https://rates.your-company.com/convert
SELF_HOSTED_TOKEN=your_secret_api_token_hereRates are cached in memory to avoid redundant network requests.
| Rate type | TTL |
|---|---|
| Latest rates | 12 hours |
| Historical rates | No expiry (historical rates never change) |
Cache keys are scoped by currency pair, date, and — for self-hosted — by endpoint URL and token, so different endpoints or tokens never share cached values.
import {
convertCurrency,
UnsupportedCurrencyError,
ProviderUnavailableError,
InvalidDateError,
} from "@assystant/currency-converter";
try {
const result = await convertCurrency({
amount: 100,
sourceCurrency: "USD",
targetCurrency: "XYZ",
});
} catch (error) {
if (error instanceof UnsupportedCurrencyError) {
// currency code not recognised by the provider
}
if (error instanceof ProviderUnavailableError) {
// all retries exhausted — network or provider issue
}
if (error instanceof InvalidDateError) {
// date format is not YYYY-MM-DD, or date is in the future
}
}| Error | Thrown when |
|---|---|
UnsupportedCurrencyError |
The source or target currency is not recognised |
ProviderUnavailableError |
The provider fails after all retries |
InvalidDateError |
Date is not YYYY-MM-DD, or is a future date |
Network errors are retried up to 2 times before throwing ProviderUnavailableError.
All types are exported from the main entry point:
import type {
ConvertCurrencyParams,
CurrencyConversionResult,
} from "@assystant/currency-converter";