@openexchangeapi/sdk
Version:
Minimal JavaScript client for OpenExchangeAPI using native fetch.
149 lines (138 loc) • 5.3 kB
JavaScript
/**
* @typedef {import('./types.js').GetLatestRatesResponse} GetLatestRatesResponse
* @typedef {import('./types.js').GetLatestPreciseRatesResponse} GetLatestPreciseRatesResponse
* @typedef {import('./types.js').GetHistoricalRatesResponse} GetHistoricalRatesResponse
* @typedef {import('./types.js').GetHistoricalPreciseRatesResponse} GetHistoricalPreciseRatesResponse
* @typedef {import('./types.js').ConvertCurrencyResponse} ConvertCurrencyResponse
* @typedef {import('./types.js').ConvertCurrencyPreciseResponse} ConvertCurrencyPreciseResponse
* @typedef {import('./types.js').Currency} Currency
* @typedef {import('./types.js').GetCurrencyResponse} GetCurrencyResponse
*/
/**
* Minimal OpenExchangeApiClient client using fetch.
* @example
* const api = new OpenExchangeApiClient('YOUR_API_KEY');
* const rates = await api.getLatest({ base: 'EUR' });
*/
export class OpenExchangeApiClient
{
/**
* @param {string} [apiKey] - Your OpenExchangeAPI key (optional)
* @param {string} [baseUrl] - API base URL (default: 'https://api.openexchangeapi.com')
*/
constructor(apiKey = undefined, baseUrl = 'https://api.openexchangeapi.com')
{
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
/**
* Internal fetch helper
* @private
* @param {string} path - API path
* @param {Object} params - Query parameters
* @returns {Promise<any>} API response JSON
*/
async _fetch(path, params = {})
{
const url = new URL(this.baseUrl + path);
if (this.apiKey) params.app_id = this.apiKey;
Object.entries(params).forEach(([k, v]) =>
{
if (v !== undefined && v !== null) url.searchParams.append(k, v);
});
const res = await fetch(url.toString());
if (!res.ok) throw await res.json();
return res.json();
}
/**
* Get latest exchange rates
* @param {Object} [opts]
* @param {string} [opts.base] - Base currency code (ISO 4217)
* @returns {Promise<GetLatestRatesResponse>} Latest rates response
*/
getLatest({ base } = {})
{
return this._fetch('/v1/latest', { base });
}
/**
* Get latest exchange rates (high precision)
* @param {Object} [opts]
* @param {string} [opts.base] - Base currency code (ISO 4217)
* @returns {Promise<GetLatestPreciseRatesResponse>} Latest precise rates response
*/
getLatestPrecise({ base } = {})
{
return this._fetch('/v1/latest-precise', { base });
}
/**
* Get historical exchange rates
* @param {Object} opts
* @param {string} opts.date - Date in YYYY-MM-DD format
* @param {string} [opts.base] - Base currency code (ISO 4217)
* @returns {Promise<GetHistoricalRatesResponse>} Historical rates response
*/
getHistorical({ date, base })
{
if (!date) throw new Error('date is required');
return this._fetch(`/v1/historical/${date}`, { base });
}
/**
* Get historical exchange rates (high precision)
* @param {Object} opts
* @param {string} opts.date - Date in YYYY-MM-DD format
* @param {string} [opts.base] - Base currency code (ISO 4217)
* @returns {Promise<GetHistoricalPreciseRatesResponse>} Historical precise rates response
*/
getHistoricalPrecise({ date, base })
{
if (!date) throw new Error('date is required');
return this._fetch(`/v1/historical-precise/${date}`, { base });
}
/**
* Convert currency
* @param {Object} opts
* @param {string} opts.from - Source currency code (ISO 4217)
* @param {string} opts.to - Target currency code (ISO 4217)
* @param {number} opts.amount - Amount to convert
* @returns {Promise<ConvertCurrencyResponse>} Conversion result
*/
convert({ from, to, amount })
{
if (!from || !to || amount == null) throw new Error('from, to, and amount are required');
return this._fetch('/v1/convert', { from, to, amount });
}
/**
* Convert currency (high precision)
* @param {Object} opts
* @param {string} opts.from - Source currency code (ISO 4217)
* @param {string} opts.to - Target currency code (ISO 4217)
* @param {number|string} opts.amount - Amount to convert
* @returns {Promise<ConvertCurrencyPreciseResponse>} Conversion result (high precision)
*/
convertPrecise({ from, to, amount })
{
if (!from || !to || amount == null) throw new Error('from, to, and amount are required');
return this._fetch('/v1/convert-precise', { from, to, amount });
}
/**
* List all supported currencies
* @param {Object} [opts]
* @param {string} [opts.type] - Filter by currency type ('fiat' or 'crypto')
* @returns {Promise<Currency[]>} List of currencies
*/
listCurrencies({ type } = {})
{
return this._fetch('/v1/currencies', { type });
}
/**
* Get currency by code
* @param {Object} opts
* @param {string} opts.code - ISO 4217 currency code
* @returns {Promise<GetCurrencyResponse>} Currency details
*/
getCurrency({ code })
{
if (!code) throw new Error('code is required');
return this._fetch(`/v1/currencies/${code}`);
}
}