FX Module
The fx module handles foreign exchange and currency conversion operations via USDC bridge.
Import
const fx = await brdzSDK.fx;
Methods Overview (7 methods)
| Method | Description | Auth Required | HTTP Endpoint |
|---|---|---|---|
getFiatRoutesConversion | FIAT to FIAT via USDC | ❌ | GET /fx/convert |
getUsdcConversion | USDC to FIAT direct | ❌ | GET /fx/usdc |
getUsdcTicker | Get ticker with changes | ❌ | GET /fx/usdc-ticker |
updateUsdcTicker | Manual ticker update | ❌ | POST /fx/usdc-ticker/update |
convertAll | Convert with route details | ❌ | GET /fx/convertall |
getRate | Get exchange rate (deprecated) | ❌ | GET /fx/rate/:from/:to |
simulateFx | Simulate FX transaction (deprecated) | ❌ | POST /fx/simulate |
Configuration
// Configure SDK
const config = await brdzSDK.config;
config.setBaseUrl('https://api.brdz.link/api');
config.setApiKey('your_api_key'); // Only API key required, no JWT token
Methods
getFiatRoutesConversion
Convert between fiat currencies using USDC as bridge.
Syntax:
await fx.getFiatRoutesConversion(from, to, amount)
Parameters:
from(string): Source currency code (e.g., "IDR", "USD")to(string): Target currency code (e.g., "USD", "SGD")amount(number): Amount to convert
Returns:
{
route: "IDR → USDC → USD",
result: 67.45,
usdcIntermediate: 0.000064
}
Example:
try {
// Convert 1,000,000 IDR to USD
const conversion = await fx.getFiatRoutesConversion('IDR', 'USD', 1000000);
console.log('Conversion Route:', conversion.route);
console.log('Result:', conversion.result, 'USD');
console.log('USDC Intermediate:', conversion.usdcIntermediate);
// Multiple conversions
const conversions = [
{ from: 'IDR', to: 'USD', amount: 1000000 },
{ from: 'USD', to: 'SGD', amount: 100 },
{ from: 'SGD', to: 'IDR', amount: 50 }
];
for (const conv of conversions) {
const result = await fx.getFiatRoutesConversion(conv.from, conv.to, conv.amount);
console.log(`${conv.from} ${conv.amount} = ${result.result} ${conv.to}`);
}
} catch (error) {
console.error('Conversion failed:', error.message);
}
Use Cases:
- Currency conversion for international payments
- Multi-currency portfolio valuation
- Cross-border remittance calculations
getUsdcConversion
Direct conversion between USDC and fiat currencies.
Syntax:
await fx.getUsdcConversion(fiat, direction, amount)
Parameters:
fiat(string): Fiat currency code (e.g., "IDR", "USD")direction(string): "toFiat" (USDC → Fiat) or "fromFiat" (Fiat → USDC)amount(number): Amount to convert
Returns:
{
route: "USDC → IDR",
rate: 15750.50,
result: 157505.00
}
Example:
try {
// Convert 10 USDC to IDR
const usdcToIdr = await fx.getUsdcConversion('IDR', 'toFiat', 10);
console.log('10 USDC =', usdcToIdr.result, 'IDR');
console.log('Rate:', usdcToIdr.rate);
// Convert 157,500 IDR to USDC
const idrToUsdc = await fx.getUsdcConversion('IDR', 'fromFiat', 157500);
console.log('157,500 IDR =', idrToUsdc.result, 'USDC');
console.log('Rate:', idrToUsdc.rate);
// Helper function for USDC conversions
async function convertUsdc(fiat, direction, amount) {
const result = await fx.getUsdcConversion(fiat, direction, amount);
return result;
}
// Batch USDC conversions
const usdcConversions = await Promise.all([
convertUsdc('IDR', 'toFiat', 10), // 10 USDC → IDR
convertUsdc('USD', 'fromFiat', 100), // 100 USD → USDC
convertUsdc('SGD', 'toFiat', 5) // 5 USDC → SGD
]);
usdcConversions.forEach((conv, i) => {
console.log(`Conversion ${i + 1}: ${conv.route} = ${conv.result}`);
});
} catch (error) {
console.error('USDC conversion failed:', error.message);
}
Direction Values:
"toFiat": Convert USDC to fiat currency"fromFiat": Convert fiat currency to USDC
getUsdcTicker
Get real-time USDC ticker data with price changes.
Syntax:
await fx.getUsdcTicker()
Parameters: None
Returns:
{
success: true,
data: {
USD: {
rate: 1.0000,
change: 0.0000,
percent: 0.0000,
isUp: true
},
IDR: {
rate: 15750.50,
change: -125.25,
percent: -0.79,
isUp: false
},
SGD: {
rate: 1.3456,
change: 0.0012,
percent: 0.09,
isUp: true
}
}
}
Example:
try {
const tickerData = await fx.getUsdcTicker();
if (tickerData.success) {
console.log('USDC Ticker Data:');
Object.entries(tickerData.data).forEach(([currency, data]) => {
const arrow = data.isUp ? '↗️' : '↘️';
const sign = data.change >= 0 ? '+' : '';
console.log(`${currency}/USDC: ${data.rate}`);
console.log(` Change: ${sign}${data.change} (${sign}${data.percent}%) ${arrow}`);
});
} else {
console.error('Failed to load ticker:', tickerData.error);
}
// Create ticker monitor
class TickerMonitor {
constructor() {
this.previousRates = {};
}
async checkRates() {
const ticker = await fx.getUsdcTicker();
if (ticker.success) {
Object.entries(ticker.data).forEach(([currency, data]) => {
const currentRate = data.rate;
if (this.previousRates[currency]) {
const prevRate = this.previousRates[currency];
const changePercent = ((currentRate - prevRate) / prevRate) * 100;
if (Math.abs(changePercent) > 1) { // 1% change threshold
console.log(`🚨 ${currency} significant change: ${prevRate} → ${currentRate} (${changePercent.toFixed(2)}%)`);
}
}
this.previousRates[currency] = currentRate;
});
}
}
startMonitoring(intervalSeconds = 30) {
setInterval(() => this.checkRates(), intervalSeconds * 1000);
}
}
// Start monitoring
const monitor = new TickerMonitor();
monitor.startMonitoring(30); // Check every 30 seconds
} catch (error) {
console.error('Ticker fetch failed:', error.message);
}
Ticker Properties:
rate: Current exchange ratechange: Absolute price changepercent: Percentage changeisUp: Boolean indicating price direction
updateUsdcTicker
Manually trigger ticker update from Coinbase.
Syntax:
await fx.updateUsdcTicker()
Parameters: None
Returns:
{
success: true,
message: "Rates updated successfully"
}
Example:
try {
const updateResult = await fx.updateUsdcTicker();
if (updateResult.success) {
console.log('✅ Ticker updated:', updateResult.message);
// Get updated ticker data
const tickerData = await fx.getUsdcTicker();
console.log('Updated rates:', tickerData.data);
} else {
console.error('❌ Update failed:', updateResult.error);
}
// Auto-update ticker every hour
setInterval(async () => {
try {
const result = await fx.updateUsdcTicker();
if (result.success) {
console.log('🔄 Hourly ticker update completed');
}
} catch (error) {
console.error('❌ Scheduled update failed:', error);
}
}, 3600000); // 1 hour = 3,600,000 ms
} catch (error) {
console.error('Manual update failed:', error.message);
}
Use Cases:
- Get latest rates during high volatility
- Refresh rates before important transactions
- Scheduled rate updates for applications
convertAll
Convert currencies with detailed route information.
Syntax:
await fx.convertAll(from, to, amount)
Parameters:
from(string): Source currency codeto(string): Target currency codeamount(number): Amount to convert
Returns:
{
from: "IDR",
to: "USD",
original_amount: 1000000,
route: "IDR → USDC → USD",
usdc_intermediate: 63.456,
converted_amount: 63.45,
exchange_rate: 0.00006345
}
Example:
try {
const conversion = await fx.convertAll('IDR', 'USD', 1000000);
console.log('Conversion Details:');
console.log(`From: ${conversion.from} ${conversion.original_amount}`);
console.log(`To: ${conversion.to} ${conversion.converted_amount}`);
console.log(`Route: ${conversion.route}`);
console.log(`Exchange Rate: ${conversion.exchange_rate}`);
if (conversion.usdc_intermediate) {
console.log(`USDC Intermediate: ${conversion.usdc_intermediate}`);
}
// Conversion tracker
class ConversionTracker {
constructor() {
this.conversions = [];
}
async convert(from, to, amount) {
const conversion = await fx.convertAll(from, to, amount);
conversion.timestamp = new Date().toISOString();
this.conversions.push(conversion);
return conversion;
}
getHistory() {
return this.conversions.map(conv => ({
timestamp: conv.timestamp,
conversion: `${conv.from} ${conv.original_amount} → ${conv.to} ${conv.converted_amount}`,
rate: conv.exchange_rate,
route: conv.route
}));
}
getTotalConverted(currency) {
return this.conversions
.filter(conv => conv.to === currency)
.reduce((total, conv) => total + conv.converted_amount, 0);
}
}
// Usage
const tracker = new ConversionTracker();
await tracker.convert('IDR', 'USD', 1000000);
await tracker.convert('USD', 'SGD', 100);
console.log('Conversion History:', tracker.getHistory());
console.log('Total USD Converted:', tracker.getTotalConverted('USD'));
} catch (error) {
console.error('Detailed conversion failed:', error.message);
}
Detailed Properties:
original_amount: Input amountconverted_amount: Output amountexchange_rate: Calculated rateroute: Conversion path takenusdc_intermediate: USDC amount (if applicable)
getRate (Deprecated)
⚠️ This method is deprecated. Use getFiatRoutesConversion instead.
Syntax:
await fx.getRate(from, to)
Example:
// ❌ Deprecated - will show warning
const rate = await fx.getRate('USD', 'IDR');
// ✅ Use this instead
const conversion = await fx.getFiatRoutesConversion('USD', 'IDR', 1);
console.log('Rate:', conversion.result); // Rate for 1 USD
simulateFx (Deprecated)
⚠️ This method is deprecated. Use convertAll instead.
Syntax:
await fx.simulateFx(data)
Example:
// ❌ Deprecated - will show warning
const simulation = await fx.simulateFx({
from_currency: 'IDR',
to_currency: 'USDC',
amount: 1000000
});
// ✅ Use this instead
const conversion = await fx.convertAll('IDR', 'USDC', 1000000);
console.log('Conversion result:', conversion);
Complete Integration Example
class FXManager {
constructor() {
this.fx = null;
this.init();
}
async init() {
// Initialize SDK
const config = await brdzSDK.config;
config.setBaseUrl('https://api.brdz.link/api');
config.setApiKey('your_api_key');
this.fx = await brdzSDK.fx;
}
async getCurrentRates() {
try {
const ticker = await this.fx.getUsdcTicker();
return ticker.success ? ticker.data : null;
} catch (error) {
console.error('Failed to get rates:', error);
return null;
}
}
async convertCurrency(from, to, amount) {
try {
if (from === 'USDC' || to === 'USDC') {
// Direct USDC conversion
const direction = from === 'USDC' ? 'toFiat' : 'fromFiat';
const fiat = from === 'USDC' ? to : from;
return await this.fx.getUsdcConversion(fiat, direction, amount);
} else {
// FIAT to FIAT conversion
return await this.fx.convertAll(from, to, amount);
}
} catch (error) {
console.error('Conversion failed:', error);
throw error;
}
}
async refreshRates() {
try {
const result = await this.fx.updateUsdcTicker();
return result.success;
} catch (error) {
console.error('Rate refresh failed:', error);
return false;
}
}
async calculatePortfolioValue(holdings, targetCurrency = 'USD') {
let totalValue = 0;
const conversions = [];
for (const holding of holdings) {
if (holding.currency === targetCurrency) {
totalValue += holding.amount;
conversions.push({
...holding,
convertedAmount: holding.amount,
rate: 1
});
} else {
const conversion = await this.convertCurrency(
holding.currency,
targetCurrency,
holding.amount
);
const convertedAmount = conversion.converted_amount || conversion.result;
totalValue += convertedAmount;
conversions.push({
...holding,
convertedAmount,
rate: conversion.exchange_rate || conversion.rate
});
}
}
return {
totalValue,
targetCurrency,
conversions,
timestamp: new Date().toISOString()
};
}
}
// Usage
const fxManager = new FXManager();
await fxManager.init();
// Get current rates
const rates = await fxManager.getCurrentRates();
console.log('Current rates:', rates);
// Convert currency
const conversion = await fxManager.convertCurrency('IDR', 'USD', 1000000);
console.log('Conversion result:', conversion);
// Calculate portfolio value
const portfolio = [
{ currency: 'IDR', amount: 10000000, asset: 'Cash' },
{ currency: 'USD', amount: 500, asset: 'Savings' },
{ currency: 'USDC', amount: 1000, asset: 'Crypto' }
];
const valuation = await fxManager.calculatePortfolioValue(portfolio, 'USD');
console.log(`Total Portfolio Value: $${valuation.totalValue.toFixed(2)} USD`);
Error Handling
Common Error Patterns
try {
const result = await fx.convertAll('IDR', 'USD', 1000000);
} catch (error) {
if (error.message.includes('Missing required parameters')) {
console.error('Invalid parameters provided');
} else if (error.message.includes('Invalid amount')) {
console.error('Amount must be a positive number');
} else if (error.message.includes('Unsupported currency')) {
console.error('Currency not supported');
} else if (error.message.includes('Conversion failed')) {
console.error('Rate source unavailable, try again later');
} else {
console.error('Unexpected error:', error.message);
}
}
Rate Availability Check
async function checkRateAvailability(currencies) {
try {
const ticker = await fx.getUsdcTicker();
if (!ticker.success) {
return { available: false, reason: 'Ticker service unavailable' };
}
const unavailable = currencies.filter(curr =>
curr !== 'USDC' && !ticker.data[curr]
);
if (unavailable.length > 0) {
return {
available: false,
reason: `Unsupported currencies: ${unavailable.join(', ')}`
};
}
return { available: true };
} catch (error) {
return { available: false, reason: error.message };
}
}
// Usage
const availability = await checkRateAvailability(['IDR', 'USD', 'SGD']);
if (availability.available) {
// Proceed with conversion
} else {
console.error('Cannot convert:', availability.reason);
}
USDC Bridge Architecture
All currency conversions use USDC as an intermediate bridge:
Conversion Flow
- FIAT → USDC: Convert source fiat to USDC
- USDC → FIAT: Convert USDC to target fiat
- Rate Calculation: Combine both rates for final conversion
Advantages
- Consistent Pricing: Single source of truth for rates
- Reduced Complexity: No need for N×N currency pairs
- Real-time Updates: Direct connection to Coinbase rates
- Lower Slippage: Stable intermediate currency
Supported Currencies
Primary Fiat Currencies
- IDR: Indonesian Rupiah (~15,000-16,000 per USDC)
- USD: US Dollar (~1.0000 per USDC)
- SGD: Singapore Dollar (~1.30-1.40 per USDC)
Digital Assets
- USDC: USD Coin (bridge currency)
Rate Characteristics
- Update Frequency: Every 15 minutes (automatic)
- Manual Updates: Available via API
- Precision: Up to 6 decimal places
- Source: Coinbase Pro API
Best Practices
1. Rate Monitoring
// Monitor significant rate changes
class RateMonitor {
constructor(threshold = 1) {
this.threshold = threshold; // 1% change threshold
this.previousRates = {};
}
async checkSignificantChanges() {
const ticker = await fx.getUsdcTicker();
if (ticker.success) {
Object.entries(ticker.data).forEach(([currency, data]) => {
if (Math.abs(data.percent) > this.threshold) {
console.log(`🚨 ${currency} changed ${data.percent}% in recent period`);
}
});
}
}
}
2. Conversion Batching
// Batch multiple conversions for efficiency
async function batchConvert(conversions) {
return Promise.all(
conversions.map(conv =>
fx.convertAll(conv.from, conv.to, conv.amount)
)
);
}
3. Rate Caching
// Cache rates to reduce API calls
class RateCache {
constructor(ttl = 300000) { // 5 minutes TTL
this.cache = new Map();
this.ttl = ttl;
}
async getRates() {
const now = Date.now();
const cached = this.cache.get('rates');
if (cached && (now - cached.timestamp) < this.ttl) {
return cached.data;
}
const rates = await fx.getUsdcTicker();
this.cache.set('rates', {
data: rates,
timestamp: now
});
return rates;
}
}