Bridge Developer Fees
Fee Types
typescript
type FeeType = 'percent' | 'fixed'; type FeeMode = 'source' | 'destination';
Percentage-Based Fees (Virtual Accounts)
typescript
interface FeePercentConfig {
developer_fee_percent: string; // e.g., "1.0" for 1%
}
// Validations
const validateFeePercent = (fee: string): boolean => {
const num = parseFloat(fee);
if (isNaN(num)) return false;
if (num < 0) return false;
if (num > 100) return false;
// Check precision (max 5 decimal places)
const decimalParts = fee.split('.');
if (decimalParts[1] && decimalParts[1].length > 5) return false;
return true;
};
// Calculate fee amount
const calculateFee = (amount: string, feePercent: string): string => {
const numAmount = parseFloat(amount);
const numFee = parseFloat(feePercent);
const feeAmount = numAmount * (numFee / 100);
return feeAmount.toFixed(2);
};
Create Virtual Account with Fee
typescript
async function createVirtualAccountWithFee(
customerId: string,
currency: 'usd' | 'eur' | 'mxn',
cryptoAddress: string,
feePercent: string
): Promise<VirtualAccount> {
if (!validateFeePercent(feePercent)) {
throw new Error('Invalid fee percentage');
}
return createVirtualAccount(customerId, {
source: { currency },
destination: {
payment_rail: 'ethereum',
currency: 'usdc',
address: cryptoAddress,
},
developer_fee_percent: feePercent,
});
}
// Usage
const account = await createVirtualAccountWithFee(
'cust_alice',
'usd',
'0x3f5CE5FBFe3E9af3971dD833D26BA9b5C936f0bE',
'1.0' // 1% fee
);
console.log(`Fee configured: ${account.developer_fee_percent}%`);
Fixed Fees (Transfers)
typescript
async function createTransferWithFixedFee(
request: CreateTransferRequest,
fixedFee: string
): Promise<Transfer> {
return createTransfer({
...request,
developer_fee: fixedFee,
});
}
// Calculate total with fee
const calculateTotalWithFee = (amount: string, fee: string): string => {
return (parseFloat(amount) + parseFloat(fee)).toFixed(2);
};
Flexible Amount Transfers with Fee
typescript
interface FlexibleTransferRequest {
on_behalf_of: string;
source: {
payment_rail: string;
currency: string;
};
destination: {
payment_rail: string;
currency: string;
to_address: string;
};
developer_fee_percent: string;
features: {
flexible_amount: true;
};
}
interface FlexibleTransferResponse {
amount: string;
developer_fee_percent: string;
net_amount: string;
}
async function createFlexibleTransfer(
request: FlexibleTransferRequest
): Promise<FlexibleTransferResponse> {
const response = await fetch(`${BRIDGE_API_URL}/transfers`, {
method: 'POST',
headers: {
'Api-Key': API_KEY,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (!response.ok) {
throw new Error('Transfer creation failed');
}
const transfer = await response.json();
// Return calculated amounts
return {
amount: transfer.amount,
developer_fee_percent: transfer.developer_fee_percent,
net_amount: transfer.receipt?.final_amount || transfer.amount,
};
}
// Usage
const result = await createFlexibleTransfer({
on_behalf_of: 'cust_alice',
source: { payment_rail: 'ach', currency: 'usd' },
destination: {
payment_rail: 'ethereum',
currency: 'usdc',
to_address: '0xdeadbeef',
},
developer_fee_percent: '2.0', // 2% fee
features: { flexible_amount: true },
});
console.log(`Customer pays: $${result.amount}`);
console.log(`Fee (2%): $${(parseFloat(result.amount) * 0.02).toFixed(2)}`);
console.log(`Net to crypto: ${result.net_amount} USDC`);
Default Developer Fees
typescript
interface UpdateFeesRequest {
default_liquidation_address_fee_percent: string;
}
async function updateDefaultFees(feePercent: string): Promise<{ summary: string }> {
if (!validateFeePercent(feePercent)) {
throw new Error('Invalid fee percentage');
}
const response = await fetch(`${BRIDGE_API_URL}/developer/fees`, {
method: 'POST',
headers: {
'Api-Key': API_KEY,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
default_liquidation_address_fee_percent: feePercent,
}),
});
if (!response.ok) {
throw new Error('Failed to update fees');
}
return response.json();
}
// Usage
await updateDefaultFees('0.5'); // 0.5% default fee
console.log('Default fees updated');
Fee Strategies
typescript
interface FeeTier {
name: string;
min_volume: number;
max_volume?: number;
fee_percent: string;
}
const FEE_TIERS: FeeTier[] = [
{ name: 'Standard', min_volume: 0, fee_percent: '1.0' },
{ name: 'Silver', min_volume: 10000, fee_percent: '0.75' },
{ name: 'Gold', min_volume: 50000, fee_percent: '0.50' },
{ name: 'Platinum', min_volume: 100000, fee_percent: '0.25' },
];
function getApplicableTier(volume: number): FeeTier {
return FEE_TIERS.find(
t => volume >= t.min_volume && (!t.max_volume || volume < t.max_volume)
) || FEE_TIERS[0];
}
function calculateTieredFee(amount: string, customerId: string): string {
// Get customer's monthly volume from your system
const monthlyVolume = getCustomerMonthlyVolume(customerId);
const tier = getApplicableTier(monthlyVolume);
return calculateFee(amount, tier.fee_percent);
}
Fee Dashboard
typescript
interface FeeDashboard {
total_fees_collected: string;
transaction_count: number;
average_fee: string;
by_tier: { tier: string; fees: string; count: number }[];
}
async function getFeeDashboard(developerId: string): Promise<FeeDashboard> {
// Aggregate from transfer history
const transfers = await listAllTransfers({ developer_id: developerId });
let totalFees = 0;
const byTier = new Map<string, { fees: number; count: number }>();
for (const transfer of transfers) {
totalFees += parseFloat(transfer.developer_fee || '0');
}
return {
total_fees_collected: totalFees.toFixed(2),
transaction_count: transfers.length,
average_fee: (totalFees / transfers.length).toFixed(2),
byTier: Array.from(byTier.entries()).map(([tier, data]) => ({
tier,
fees: data.fees.toFixed(2),
count: data.count,
})),
};
}
Fee Transparency
typescript
function generateFeeDisclosure(feePercent: string): string {
return `
Fee Disclosure
=============
A developer fee of ${feePercent}% will be applied to this transaction.
Example:
- Deposit: $100.00
- Fee (${feePercent}%): $${(100 * parseFloat(feePercent) / 100).toFixed(2)}
- Net credit: $${(100 * (1 - parseFloat(feePercent) / 100)).toFixed(2)}
Fees support platform maintenance and development.
`.trim();
}
Webhook Events
- •
fee.collected- Fee was collected on a transfer - •
fee.config_updated- Fee configuration changed
Best Practices
- •Fee transparency - Always disclose fees to users
- •Tiered approach - Reward high-volume customers
- •Precision - Use proper decimal handling
- •Idempotency - Prevent duplicate fee charges
- •Testing - Use sandbox to test fee calculations