Skip to main content

Pool Metrics

The useForexPoolData hook provides detailed metrics for individual forex pools, including daily snapshots that track TVL, APY, and utilization over time.

Core Types

ForexPoolDailySnapshot

import type { ForexPoolDailySnapshot } from '@one_deploy/sdk';

interface ForexPoolDailySnapshot {
/** The date of this snapshot (ISO-8601 date string, e.g. "2025-04-15"). */
date: string;

/** Pool identifier. */
poolId: string;

/** Pool type at time of snapshot. */
poolType: 'clearing' | 'hedging' | 'insurance';

/** Total value locked at end of day (in USDC). */
tvl: number;

/** Annualized percentage yield for this day. */
apy: number;

/** Pool utilization as a decimal (0.0 to 1.0). */
utilization: number;

/** Total volume processed through the pool on this day. */
volume: number;

/** Number of transactions processed on this day. */
transactionCount: number;

/** Net inflow (deposits - withdrawals) on this day. */
netInflow: number;

/** Fees collected on this day (in USDC). */
feesCollected: number;
}

useForexPoolData Hook

Hook Signature

import { useForexPoolData } from '@one_deploy/sdk';

function useForexPoolData(poolId: string): UseForexPoolDataResult;

UseForexPoolDataResult

interface UseForexPoolDataResult {
/** Current pool state. */
pool: ForexPool | null;

/** Daily snapshots for the pool, ordered by date descending. */
snapshots: ForexPoolDailySnapshot[];

/** Whether data is being fetched. */
isLoading: boolean;

/** Error object if the fetch failed. */
error: Error | null;

/** Re-fetch pool data and snapshots. */
refetch: () => Promise<void>;

/** Fetch snapshots for a specific date range. */
fetchSnapshots: (params: {
startDate: string;
endDate: string;
}) => Promise<ForexPoolDailySnapshot[]>;
}

Fetching Pool Metrics

Basic Usage

import React from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import { useForexPoolData } from '@one_deploy/sdk';

function PoolMetricsView({ poolId }: { poolId: string }) {
const { pool, snapshots, isLoading, error } = useForexPoolData(poolId);

if (isLoading) return <ActivityIndicator size="large" />;
if (error) return <Text style={styles.error}>Error: {error.message}</Text>;
if (!pool) return <Text>Pool not found</Text>;

const latestSnapshot = snapshots[0];

return (
<View style={styles.container}>
<Text style={styles.header}>
{pool.type.charAt(0).toUpperCase() + pool.type.slice(1)} Pool
</Text>

<View style={styles.metricsRow}>
<MetricCard
label="TVL"
value={`$${pool.totalValueLocked.toLocaleString()}`}
/>
<MetricCard
label="APY"
value={`${(pool.apy * 100).toFixed(2)}%`}
/>
<MetricCard
label="Utilization"
value={`${(pool.utilization * 100).toFixed(1)}%`}
/>
</View>

{latestSnapshot && (
<View style={styles.snapshot}>
<Text style={styles.snapshotHeader}>
Latest Snapshot ({latestSnapshot.date})
</Text>
<Text style={styles.snapshotText}>
Volume: ${latestSnapshot.volume.toLocaleString()}
</Text>
<Text style={styles.snapshotText}>
Transactions: {latestSnapshot.transactionCount}
</Text>
<Text style={styles.snapshotText}>
Net Inflow: ${latestSnapshot.netInflow.toLocaleString()}
</Text>
<Text style={styles.snapshotText}>
Fees: ${latestSnapshot.feesCollected.toFixed(2)}
</Text>
</View>
)}
</View>
);
}

function MetricCard({ label, value }: { label: string; value: string }) {
return (
<View style={styles.metricCard}>
<Text style={styles.metricLabel}>{label}</Text>
<Text style={styles.metricValue}>{value}</Text>
</View>
);
}

const styles = StyleSheet.create({
container: { padding: 16 },
header: { fontSize: 20, fontWeight: '700', color: '#fff', marginBottom: 16 },
error: { color: '#cc4444', padding: 16 },
metricsRow: { flexDirection: 'row', gap: 12, marginBottom: 20 },
metricCard: {
flex: 1,
backgroundColor: '#1a1a2e',
padding: 14,
borderRadius: 10,
alignItems: 'center',
},
metricLabel: { fontSize: 12, color: '#8888aa', marginBottom: 4 },
metricValue: { fontSize: 18, fontWeight: '700', color: '#ffffff' },
snapshot: {
backgroundColor: '#1a1a2e',
padding: 16,
borderRadius: 12,
},
snapshotHeader: { fontSize: 14, fontWeight: '600', color: '#ccc', marginBottom: 10 },
snapshotText: { fontSize: 13, color: '#aaa', marginBottom: 4 },
});

Fetching Date-Range Snapshots

import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import { useForexPoolData } from '@one_deploy/sdk';
import type { ForexPoolDailySnapshot } from '@one_deploy/sdk';

function PoolHistory({ poolId }: { poolId: string }) {
const { fetchSnapshots } = useForexPoolData(poolId);
const [history, setHistory] = useState<ForexPoolDailySnapshot[]>([]);

useEffect(() => {
// Fetch last 30 days
const endDate = new Date().toISOString().split('T')[0];
const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
.toISOString()
.split('T')[0];

fetchSnapshots({ startDate, endDate }).then(setHistory);
}, [poolId, fetchSnapshots]);

return (
<FlatList
data={history}
keyExtractor={(item) => item.date}
renderItem={({ item }) => (
<View style={styles.row}>
<Text style={styles.date}>{item.date}</Text>
<Text style={styles.cell}>
TVL: ${(item.tvl / 1000).toFixed(0)}k
</Text>
<Text style={styles.cell}>
APY: {(item.apy * 100).toFixed(2)}%
</Text>
<Text style={styles.cell}>
Util: {(item.utilization * 100).toFixed(0)}%
</Text>
</View>
)}
/>
);
}

const styles = StyleSheet.create({
row: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 10,
borderBottomWidth: 1,
borderColor: '#222',
},
date: { color: '#888', fontSize: 12, width: 90 },
cell: { color: '#ccc', fontSize: 12, flex: 1 },
});

Aggregating Metrics Across All Pools

import { useForexPools, useForexPoolData } from '@one_deploy/sdk';

function useAggregatedMetrics() {
const { pools } = useForexPools();

const totalTvl = pools.reduce((sum, pool) => sum + pool.totalValueLocked, 0);

const weightedApy = pools.reduce(
(sum, pool) => sum + pool.apy * pool.totalValueLocked,
0
) / (totalTvl || 1);

const avgUtilization = pools.reduce(
(sum, pool) => sum + pool.utilization,
0
) / (pools.length || 1);

return { totalTvl, weightedApy, avgUtilization, poolCount: pools.length };
}

// Usage in a component
function AggregatedMetrics() {
const { totalTvl, weightedApy, avgUtilization } = useAggregatedMetrics();

return (
<View style={{ padding: 16 }}>
<Text style={{ color: '#fff', fontSize: 16, fontWeight: '700' }}>
StableFX Overview
</Text>
<Text style={{ color: '#aaa', marginTop: 8 }}>
Total TVL: ${totalTvl.toLocaleString()}
</Text>
<Text style={{ color: '#aaa' }}>
Weighted APY: {(weightedApy * 100).toFixed(2)}%
</Text>
<Text style={{ color: '#aaa' }}>
Avg Utilization: {(avgUtilization * 100).toFixed(1)}%
</Text>
</View>
);
}

Snapshot Data Model

Each daily snapshot captures the state of a pool at the end of a UTC day:

FieldDescriptionExample
dateUTC date string"2025-04-15"
tvlTotal value locked in USDC2500000
apyAnnualized yield (decimal)0.0825
utilizationCapital utilization (decimal)0.72
volumeTotal volume in USDC1200000
transactionCountNumber of pool transactions347
netInflowDeposits minus withdrawals85000
feesCollectedFees collected in USDC3200.50

Next Steps