assets[].userMetrics now exposes three new fields alongside the existing totalRepayable*:
type LendAssetUserMetrics = {
// existing — unchanged
totalRepayable: number; // session-aware: min(wallet, debt) − relayer-fee headroom
totalRepayableRaw: string;
totalRepayableUsd: number;
// new — wallet-only, no fee carve-out
totalRepayableMax: number; // = min(wallet, debt), exact
totalRepayableMaxRaw: string;
totalRepayableMaxUsd: number;
// ...other fields
};totalRepayableMax is always ≥ totalRepayable. The two converge to the same value when the relayer fee is zero (e.g. on Sonic) or when min(wallet, debt) == debt and the user has plenty of headroom.
const repayMax = sessionsEnabled
? asset.userMetrics.totalRepayable // legacy field — already deducts session fee
: asset.userMetrics.totalRepayableMax; // new field — full wallet-side capOr, since you already do your own conditional session-fee deduction in useLendDrawers.tsx (lines 519–545), you can simplify to always read totalRepayableMax and let your existing FE-side logic do the deduction in session mode:
// Always pull the wallet-only cap from the API.
maxInputValueRaw = asset.userMetrics.totalRepayableMaxRaw;
maxInputValue = asset.userMetrics.totalRepayableMax;
// Then your existing session-fee deduction kicks in unchanged:
if (sessionsEnabled && sessionFeeTokenRaw && maxInputValueRaw) {
const feeWei = BigInt(sessionFeeTokenRaw);
const walletWei = BigInt(asset.userMetrics.walletBalanceRaw ?? '0');
const sessionMaxWei = walletWei > feeWei ? walletWei - feeWei : 0n;
const repayWei = BigInt(maxInputValueRaw);
const effectiveWei = sessionMaxWei < repayWei ? sessionMaxWei : repayWei;
if (effectiveWei !== repayWei) {
maxInputValueRaw = effectiveWei.toString();
maxInputValue = Number(formatUnits(effectiveWei, decimals));
}
}This second form is the cleaner end-state — the API stops being session-aware and the FE owns that policy.
walletBalance: 0.001
totalBorrowed: 0.001000275778364331
totalRepayable: 0.000615… ← old field, deducts session relayer fee
totalRepayableMax: 0.001 ← new field, raw min(wallet, debt)
Direct repay (no sessions): user can submit 0.001 and clear the entire debt. Pre-fix the FE was capping at 0.000615 and leaving them stuck.
Session repay: tx submits userInput + relayerFee on-chain. The FE-side deduction caps userInput so total stays under wallet — same outcome as before.
- Now (v0.3.52): both fields available.
totalRepayable*semantics unchanged. Switch the repay-drawer's MAX source tototalRepayableMaxwhenever you're ready. - Future: once everyone's on
totalRepayableMax, the legacytotalRepayable*fields can be deprecated and eventually removed.
Same URL, same auth: GET https://api.flyingtulip.com/mm/lend?chainId=<id>&user=<addr>
origin-api-aws.flyingtulip.com/mm/lend?... works the same — both go through CloudFront to the same origin.