π°Lend / Borrow (Money Market)
Money Market part of SDK provides abstractions to assist you with interacting with the cross-chain Money Market Smart Contracts.
Using SDK Config and Constants
SDK includes predefined configurations of supported chains, tokens and other relevant information for the client to consume.
import { supportedSpokeChains, getSupportedSolverTokens, SpokeChainId, Token } from "@sodax/sdk"
// all supported spoke chains
export const spokeChains: SpokeChainId[] = supportedSpokeChains;
// using spoke chain id to retrieve supported tokens address (on spoke chain = original address) for money market
const supportedMoneyMarketTokens: readonly Token[] = getSupportedMoneyMarketTokens(spokeChainId)
// check if token address for given spoke chain id is supported
const isMoneyMarketSupportedToken: boolean = isMoneyMarketSupportedToken(spokeChainId, token)
// Get all supported reserves (hub chain token addresses, i.e. money market on Sonic chain)
const supportedReserves = sodax.moneyMarket.getSupportedReserves();
Please refer to SDK constants.ts for more.
Initialising Spoke Provider
Refer to Initialising Spoke Provider section to see how BSC spoke provider used as bscSpokeProvider
can be created.
Allowance and Approval
Before making a money market action (supply, repay, withdraw, borrow), you need to ensure the money market contract has sufficient allowance to spend your tokens. The SDK provides methods to check and set allowances for different types of spoke providers:
Checking Allowance
import { MoneyMarketSupplyParams, MoneyMarketRepayParams } from "@sodax/sdk";
// Check if allowance is sufficient for supply
const supplyParams: MoneyMarketSupplyParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to supply (in token decimals)
action: 'supply',
};
const isAllowanceValid = await sodax.moneyMarket.isAllowanceValid(supplyParams, spokeProvider);
if (!isAllowanceValid.ok) {
// Handle error
return;
}
if (!isAllowanceValid.value) {
// Need to approve - allowance is insufficient
}
Setting Allowance
The approve
method sets the allowance for the specified action. The spender address varies depending on the spoke provider type:
EVM Spoke Chains: The spender is the asset manager contract
Sonic Spoke (Hub) Chain: The spender is the user router contract (for supply/repay) or specific approval contracts (for withdraw/borrow)
import { MoneyMarketSupplyParams, MoneyMarketRepayParams } from "@sodax/sdk";
// Parameters for supply operation
const supplyParams: MoneyMarketSupplyParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to supply (in token decimals)
action: 'supply',
};
// First check if allowance is sufficient
const isAllowanceValid = await sodax.moneyMarket.isAllowanceValid(supplyParams, spokeProvider);
if (!isAllowanceValid.ok) {
// Handle error
return;
}
if (!isAllowanceValid.value) {
// Approve the money market contract to spend tokens
const approveResult = await sodax.moneyMarket.approve(
supplyParams,
spokeProvider,
false // Optional: true = return raw transaction data, false = execute and return transaction hash (default: false)
);
if (!approveResult.ok) {
// Handle approval error
return;
}
// Transaction hash or raw transaction data
const txResult = approveResult.value;
}
Supported Actions by Provider Type
The allowance and approval system supports different actions depending on the spoke provider type:
EVM Spoke Providers:
supply
- Approves the asset manager contract to spend tokensrepay
- Approves the asset manager contract to spend tokens
Sonic Spoke Provider (Hub Chain):
supply
- Approves the user router contract to spend tokensrepay
- Approves the user router contract to spend tokenswithdraw
- Approves the withdraw operation using SonicSpokeServiceborrow
- Approves the borrow operation using SonicSpokeService
Complete Example
Here's a complete example showing the allowance check and approval flow:
import { MoneyMarketSupplyParams } from "@sodax/sdk";
const supplyParams: MoneyMarketSupplyParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to supply (in token decimals)
action: 'supply',
};
// Step 1: Check if allowance is sufficient
const allowanceCheck = await sodax.moneyMarket.isAllowanceValid(supplyParams, spokeProvider);
if (!allowanceCheck.ok) {
console.error('Allowance check failed:', allowanceCheck.error);
return;
}
// Step 2: Approve if allowance is insufficient
if (!allowanceCheck.value) {
console.log('Insufficient allowance, approving...');
const approveResult = await sodax.moneyMarket.approve(supplyParams, spokeProvider);
if (!approveResult.ok) {
console.error('Approval failed:', approveResult.error);
return;
}
console.log('Approval successful:', approveResult.value);
}
// Step 3: Now you can proceed with supply
const supplyResult = await sodax.moneyMarket.supply(supplyParams, spokeProvider);
if (supplyResult.ok) {
const [spokeTxHash, hubTxHash] = supplyResult.value;
console.log('Supply successful:', { spokeTxHash, hubTxHash });
} else {
console.error('Supply failed:', supplyResult.error);
}
Estimate Gas for Raw Transactions
The estimateGas
function allows you to estimate the gas cost for raw transactions before executing them. This is particularly useful for money market operations (supply, borrow, withdraw, repay) and approval transactions to provide users with accurate gas estimates.
import { MoneyMarketService, MoneyMarketSupplyParams } from "@sodax/sdk";
// Example: Estimate gas for a supply transaction
const supplyResult = await sodax.moneyMarket.createSupplyIntent(
supplyParams,
spokeProvider,
true, // true = get raw transaction
);
if (supplyResult.ok) {
const rawTx = supplyResult.value;
// Estimate gas for the raw transaction
const gasEstimate = await MoneyMarketService.estimateGas(rawTx, spokeProvider);
if (gasEstimate.ok) {
console.log('Estimated gas for supply:', gasEstimate.value);
} else {
console.error('Failed to estimate gas for supply:', gasEstimate.error);
}
}
// Example: Estimate gas for an approval transaction
const approveResult = await sodax.moneyMarket.approve(
supplyParams,
spokeProvider,
true // true = get raw transaction
);
if (approveResult.ok) {
const rawTx = approveResult.value;
// Estimate gas for the approval transaction
const gasEstimate = await MoneyMarketService.estimateGas(rawTx, spokeProvider);
if (gasEstimate.ok) {
console.log('Estimated gas for approval:', gasEstimate.value);
} else {
console.error('Failed to estimate gas for approval:', gasEstimate.error);
}
}
// Example: Estimate gas for a borrow transaction
const borrowResult = await sodax.moneyMarket.createBorrowIntent(
borrowParams,
spokeProvider,
true // true = get raw transaction
);
if (borrowResult.ok) {
const rawTx = borrowResult.value;
// Estimate gas for the borrow transaction
const gasEstimate = await MoneyMarketService.estimateGas(rawTx, spokeProvider);
if (gasEstimate.ok) {
console.log('Estimated gas for borrow:', gasEstimate.value);
} else {
console.error('Failed to estimate gas for borrow:', gasEstimate.error);
}
}
// Example: Estimate gas for a withdraw transaction
const withdrawResult = await sodax.moneyMarket.createWithdrawIntent(
withdrawParams,
spokeProvider,
true // true = get raw transaction
);
if (withdrawResult.ok) {
const rawTx = withdrawResult.value;
// Estimate gas for the withdraw transaction
const gasEstimate = await MoneyMarketService.estimateGas(rawTx, spokeProvider);
if (gasEstimate.ok) {
console.log('Estimated gas for withdraw:', gasEstimate.value);
} else {
console.error('Failed to estimate gas for withdraw:', gasEstimate.error);
}
}
// Example: Estimate gas for a repay transaction
const repayResult = await sodax.moneyMarket.createRepayIntent(
repayParams,
spokeProvider,
true // true = get raw transaction
);
if (repayResult.ok) {
const rawTx = repayResult.value;
// Estimate gas for the repay transaction
const gasEstimate = await MoneyMarketService.estimateGas(rawTx, spokeProvider);
if (gasEstimate.ok) {
console.log('Estimated gas for repay:', gasEstimate.value);
} else {
console.error('Failed to estimate gas for repay:', gasEstimate.error);
}
}
Supply Tokens
Supply tokens to the money market pool. There are two methods available:
supply
: Supply tokens to the money market pool, relay the transaction to the hub and submit the intent to the Solver APIcreateSupplyIntent
: Create supply intent only (without relay and submit to Solver API)
import { MoneyMarketSupplyParams, DEFAULT_RELAY_TX_TIMEOUT } from "@sodax/sdk";
// Parameters for supply operation
const supplyParams: MoneyMarketSupplyParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to supply (in token decimals)
};
// First check and set allowance if needed
const isAllowanceValid = await sodax.moneyMarket.isAllowanceValid(supplyParams, spokeProvider);
if (!isAllowanceValid.ok || !isAllowanceValid.value) {
const approveResult = await sodax.moneyMarket.approve(
supplyParams.token as Address,
supplyParams.amount,
spokeProvider.chainConfig.addresses.assetManager,
spokeProvider
);
if (!approveResult.ok) {
// Handle approval error
return;
}
}
// Supply and submit to Solver API
const supplyAndSubmitResult = await sodax.moneyMarket.supply(
supplyParams,
spokeProvider,
DEFAULT_RELAY_TX_TIMEOUT // Optional: timeout in milliseconds (default: 1 minute)
);
if (supplyAndSubmitResult.ok) {
const [spokeTxHash, hubTxHash] = supplyAndSubmitResult.value;
// Handle success
} else {
// Handle error
}
// Create supply intent only (without submitting to Solver API)
const supplyResult = await sodax.moneyMarket.createSupplyIntent(
supplyParams,
spokeProvider,
false // Optional: whether to return raw transaction (default: false)
);
if (supplyResult.ok) {
const txHash = supplyResult.value;
// Handle success
} else {
// Handle error
}
Borrow Tokens
Borrow tokens from the money market pool. There are two methods available:
borrow
: Borrow tokens from the money market pool, relay the transaction to the hub and submit the intent to the Solver APIcreateBorrowIntent
: Create borrow intent only (without relay and submit to Solver API)
import { MoneyMarketBorrowParams, DEFAULT_RELAY_TX_TIMEOUT } from "@sodax/sdk";
// Parameters for borrow operation
const borrowParams: MoneyMarketBorrowParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to borrow (in token decimals)
};
// Borrow and submit to Solver API
const borrowAndSubmitResult = await sodax.moneyMarket.borrowAndSubmit(
borrowParams,
spokeProvider,
DEFAULT_RELAY_TX_TIMEOUT // Optional: timeout in milliseconds (default: 1 minute)
);
if (borrowAndSubmitResult.ok) {
const [spokeTxHash, hubTxHash] = borrowAndSubmitResult.value;
// Handle success
} else {
// Handle error
}
// Borrow only (without submitting to Solver API)
const borrowResult = await sodax.moneyMarket.borrow(
borrowParams,
spokeProvider,
false // Optional: whether to return raw transaction (default: false)
);
if (borrowResult.ok) {
const txHash = borrowResult.value;
// Handle success
} else {
// Handle error
}
Withdraw Tokens
Withdraw tokens from the money market pool. There are two methods available:
withdraw
: Withdraw tokens from the money market pool, relay the transaction to the hub and submit the intent to the Solver APIcreateWithdrawIntent
: Create withdraw intent only (without relay and submit to Solver API)
import { MoneyMarketWithdrawParams, DEFAULT_RELAY_TX_TIMEOUT } from "@sodax/sdk";
// Parameters for withdraw operation
const withdrawParams: MoneyMarketWithdrawParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to withdraw (in token decimals)
};
// Withdraw and submit to Solver API
const withdrawAndSubmitResult = await sodax.moneyMarket.withdrawAndSubmit(
withdrawParams,
spokeProvider,
DEFAULT_RELAY_TX_TIMEOUT // Optional: timeout in milliseconds (default: 1 minute)
);
if (withdrawAndSubmitResult.ok) {
const [spokeTxHash, hubTxHash] = withdrawAndSubmitResult.value;
// Handle success
} else {
// Handle error
}
// Withdraw only (without submitting to Solver API)
const withdrawResult = await sodax.moneyMarket.withdraw(
withdrawParams,
spokeProvider,
false // Optional: whether to return raw transaction (default: false)
);
if (withdrawResult.ok) {
const txHash = withdrawResult.value;
// Handle success
} else {
// Handle error
}
Repay Tokens
Repay tokens to the money market pool. There are two methods available:
repay
: Repay tokens to the money market pool, relay the transaction to the hub and submit the intent to the Solver APIcreateRepayIntent
: Create repay intent only (without relay and submit to Solver API)
import { MoneyMarketRepayParams, DEFAULT_RELAY_TX_TIMEOUT } from "@sodax/sdk";
// Parameters for repay operation
const repayParams: MoneyMarketRepayParams = {
token: '0x...', // Address of the token (spoke chain) to supply
amount: 1000n, // Amount to repay (in token decimals)
};
// First check and set allowance if needed
const isAllowanceValid = await sodax.moneyMarket.isAllowanceValid(repayParams, spokeProvider);
if (!isAllowanceValid.ok || !isAllowanceValid.value) {
const approveResult = await sodax.moneyMarket.approve(
repayParams.token as Address,
repayParams.amount,
spokeProvider.chainConfig.addresses.assetManager,
spokeProvider
);
if (!approveResult.ok) {
// Handle approval error
return;
}
}
// Repay and submit to Solver API
const repayAndSubmitResult = await sodax.moneyMarket.repayAndSubmit(
repayParams,
spokeProvider,
DEFAULT_RELAY_TX_TIMEOUT // Optional: timeout in milliseconds (default: 1 minute)
);
if (repayAndSubmitResult.ok) {
const [spokeTxHash, hubTxHash] = repayAndSubmitResult.value;
// Handle success
} else {
// Handle error
}
// Repay only (without submitting to Solver API)
const repayResult = await sodax.moneyMarket.repay(
repayParams,
spokeProvider,
false // Optional: whether to return raw transaction (default: false)
);
if (repayResult.ok) {
const txHash = repayResult.value;
// Handle success
} else {
// Handle error
}
Error Handling
Error handling for Money Market operations is complex due to the multi-step nature of cross-chain transactions. The SDK provides specific error types and type guards to help you handle different failure scenarios appropriately.
Error Types
All Money Market methods return a Result
type that can be either successful or contain an error:
type MoneyMarketError<T extends MoneyMarketErrorCode> = {
code: T;
data: GetMoneyMarketError<T>;
};
type MoneyMarketErrorCode =
| RelayErrorCode
| 'CREATE_SUPPLY_INTENT_FAILED'
| 'CREATE_BORROW_INTENT_FAILED'
| 'CREATE_WITHDRAW_INTENT_FAILED'
| 'CREATE_REPAY_INTENT_FAILED'
| 'SUPPLY_UNKNOWN_ERROR'
| 'BORROW_UNKNOWN_ERROR'
| 'WITHDRAW_UNKNOWN_ERROR'
| 'REPAY_UNKNOWN_ERROR';
Where RelayErrorCode
includes:
'SUBMIT_TX_FAILED'
- Failed to submit the spoke chain transaction to the relay API'RELAY_TIMEOUT'
- Timeout waiting for transaction execution on the hub chain
Using Error Type Guards
The SDK provides type guards to help you narrow down error types safely:
import {
isMoneyMarketSubmitTxFailedError,
isMoneyMarketRelayTimeoutError,
isMoneyMarketCreateSupplyIntentFailedError,
isMoneyMarketCreateBorrowIntentFailedError,
isMoneyMarketCreateWithdrawIntentFailedError,
isMoneyMarketCreateRepayIntentFailedError,
isMoneyMarketSupplyUnknownError,
isMoneyMarketBorrowUnknownError,
isMoneyMarketWithdrawUnknownError,
isMoneyMarketRepayUnknownError,
} from '@sodax/sdk';
Handling Money Market Operation Errors
Money Market operations (supply, borrow, withdraw, repay) perform multiple operations in sequence, and each step can fail. Use the type guards to handle errors safely:
const result = await sodax.moneyMarket.supply(params, spokeProvider);
if (!result.ok) {
const error = result.error;
if (isMoneyMarketSubmitTxFailedError(error)) {
// Failed to submit the spoke chain transaction to the relay API
// IMPORTANT: This is a critical event and you should retry submit
// and store relevant payload information in localStorage or
// similar local permanent memory. If client leaves the session
// in this critical moment their funds might get stuck until
// successful re-submission is made.
//
// This could be due to:
// - Relay API being down
// - Invalid transaction hash
// - Network connectivity issues
console.error('Submit transaction failed:', error.data.error);
console.log('Transaction hash that failed to submit:', error.data.payload);
// You may want to retry the submission or check relay API status
} else if (isMoneyMarketRelayTimeoutError(error)) {
// The transaction was submitted but failed to execute on the hub chain
// This could be due to:
// - Timeout waiting for execution
// - Hub chain congestion
// - Transaction execution failure on hub chain
console.error('Transaction execution timeout:', error.data.error);
console.log('Transaction hash that timed out:', error.data.payload);
// You may want to check the transaction status or retry with longer timeout
} else if (isMoneyMarketSupplyUnknownError(error)) {
// Handle supply-specific unknown errors
console.error('Supply operation failed:', error.data.error);
console.log('Supply parameters:', error.data.payload);
} else if (isMoneyMarketBorrowUnknownError(error)) {
// Handle borrow-specific unknown errors
console.error('Borrow operation failed:', error.data.error);
console.log('Borrow parameters:', error.data.payload);
} else if (isMoneyMarketWithdrawUnknownError(error)) {
// Handle withdraw-specific unknown errors
console.error('Withdraw operation failed:', error.data.error);
console.log('Withdraw parameters:', error.data.payload);
} else if (isMoneyMarketRepayUnknownError(error)) {
// Handle repay-specific unknown errors
console.error('Repay operation failed:', error.data.error);
console.log('Repay parameters:', error.data.payload);
} else {
// Handle other error cases
console.error('Unexpected error:', error);
}
}
Handling Create Intent Errors
The create*Intent
methods (createSupplyIntent, createBorrowIntent, etc.) have a simpler error structure since they only handle transaction creation on the spoke chain:
const createIntentResult = await sodax.moneyMarket.createSupplyIntent(
supplyParams,
spokeProvider,
false
);
if (!createIntentResult.ok) {
const error = createIntentResult.error;
if (isMoneyMarketCreateSupplyIntentFailedError(error)) {
console.error('Supply intent creation failed:', error.data.error);
console.log('Supply parameters:', error.data.payload);
// Common causes:
// - Insufficient token balance (including fee)
// - Invalid token addresses or chain IDs
// - Network issues on the spoke chain
// - Invalid wallet address or permissions
// - Contract interaction failures
// You may want to:
// - Check user's token balance
// - Verify token addresses and chain configurations
// - Retry with different parameters
} else if (isMoneyMarketCreateBorrowIntentFailedError(error)) {
console.error('Borrow intent creation failed:', error.data.error);
console.log('Borrow parameters:', error.data.payload);
} else if (isMoneyMarketCreateWithdrawIntentFailedError(error)) {
console.error('Withdraw intent creation failed:', error.data.error);
console.log('Withdraw parameters:', error.data.payload);
} else if (isMoneyMarketCreateRepayIntentFailedError(error)) {
console.error('Repay intent creation failed:', error.data.error);
console.log('Repay parameters:', error.data.payload);
} else {
console.error('Unexpected error:', error);
}
}
Handling Allowance and Approval Errors
Allowance and approval operations have simpler error handling:
const allowanceCheck = await sodax.moneyMarket.isAllowanceValid(params, spokeProvider);
if (!allowanceCheck.ok) {
console.error('Allowance check failed:', allowanceCheck.error);
// Handle error - could be network issues, invalid parameters, etc.
}
if (!allowanceCheck.value) {
const approveResult = await sodax.moneyMarket.approve(params, spokeProvider);
if (!approveResult.ok) {
console.error('Approval failed:', approveResult.error);
// Handle approval error - could be insufficient balance, network issues, etc.
}
}
Best Practices for Error Handling
Always check for
SUBMIT_TX_FAILED
errors: These are critical and require immediate attention to prevent funds from getting stuck.Store transaction data locally: When a
SUBMIT_TX_FAILED
error occurs, store the transaction hash and parameters locally so you can retry submission even if the user leaves the session.Use type guards: Leverage the provided type guards to safely handle different error types without type casting.
Access error payloads: Use the error payload data to provide better user feedback and debugging information.
Implement retry logic: For network-related errors, implement exponential backoff retry logic.
Provide user feedback: Give users clear, actionable error messages based on the error type.
Monitor timeouts: Use appropriate timeout values and inform users when operations take longer than expected.
Check transaction status: After timeouts, check the actual transaction status on the blockchain to determine if the operation succeeded despite the timeout.
Data Retrieval and Formatting
The Money Market SDK provides comprehensive data retrieval and formatting capabilities through the MoneyMarketDataService
. This service allows you to fetch reserve data, user data, and format them into human-readable values with USD conversions.
Available Data Methods
The SDK provides several methods to retrieve different types of data:
Reserve Data
getReservesList()
- Get list of all reserve addressesgetReservesData()
- Get raw aggregated reserve datagetReservesHumanized()
- Get humanized reserve data with normalized decimalsgetReserveData(asset)
- Get specific reserve data for an assetgetReserveNormalizedIncome(asset)
- Get normalized income for a specific asset
User Data
getUserReservesData(spokeProvider)
- Get raw user reserve datagetUserReservesHumanized(spokeProvider)
- Get humanized user reserve data
E-Mode Data
getEModes()
- Get raw E-Mode datagetEModesHumanized()
- Get humanized E-Mode data
Data Formatting
The SDK provides powerful formatting capabilities to convert raw blockchain data into human-readable values with USD conversions:
Formatting Reserve Data
formatReservesUSD()
- Format reserves with USD conversionsformatReserveUSD()
- Format a single reserve with USD conversion
Formatting User Data
formatUserSummary()
- Format user portfolio summary with USD conversions
NOTE if you need more customized formatting checkout math-utils.
Complete Example: Fetching and Formatting Data
Here's a complete example showing how to retrieve and format money market data:
// Fetch reserves data
const reserves = await sodax.moneyMarket.data.getReservesHumanized();
// Format reserves with USD conversions
const formattedReserves = sodax.moneyMarket.data.formatReservesUSD(
sodax.moneyMarket.data.buildReserveDataWithPrice(reserves),
);
// Fetch user reserves data
const userReserves = await sodax.moneyMarket.data.getUserReservesHumanized(spokeProvider);
// Format user summary with USD conversions
const userSummary = sodax.moneyMarket.data.formatUserSummary(
sodax.moneyMarket.data.buildUserSummaryRequest(reserves, formattedReserves, userReserves),
);
// Display formatted data
console.log('formattedReserves:', formattedReserves);
console.log('userSummary:', userSummary);
Step-by-Step Data Retrieval Process
1. Fetch Raw Data
First, retrieve the raw data from the blockchain:
// Get humanized reserves data (normalized decimals)
const reserves = await sodax.moneyMarket.data.getReservesHumanized();
// Get user reserves data for a specific spoke provider
const userReserves = await sodax.moneyMarket.data.getUserReservesHumanized(spokeProvider);
2. Build Formatting Requests
Use the helper methods to build the formatting requests:
// Build request for reserve formatting
const reserveFormatRequest = sodax.moneyMarket.data.buildReserveDataWithPrice(reserves);
// Build request for user summary formatting
const userSummaryRequest = sodax.moneyMarket.data.buildUserSummaryRequest(
reserves,
formattedReserves,
userReserves,
);
3. Format Data
Apply the formatting to get human-readable values with USD conversions:
// Format reserves with USD values
const formattedReserves = sodax.moneyMarket.data.formatReservesUSD(reserveFormatRequest);
// Format user summary with USD values
const userSummary = sodax.moneyMarket.data.formatUserSummary(userSummaryRequest);
Data Structure Examples
Formatted Reserve Data
The formattedReserves
array contains objects with the following structure:
type FormattedReserve = {
// Basic reserve information
symbol: string;
name: string;
decimals: number;
address: string;
// Supply information
totalScaledVariableDebt: string;
availableLiquidity: string;
totalPrincipalStableDebt: string;
averageStableRate: string;
liquidityIndex: string;
variableBorrowIndex: string;
lastUpdateTimestamp: number;
// USD values
totalLiquidityUSD: string;
totalVariableDebtUSD: string;
totalStableDebtUSD: string;
availableLiquidityUSD: string;
// Rates and factors
liquidityRate: string;
variableBorrowRate: string;
stableBorrowRate: string;
averageStableRate: string;
liquidityIndex: string;
variableBorrowIndex: string;
// Configuration
usageAsCollateralEnabledOnUser: boolean;
borrowingEnabled: boolean;
stableBorrowRateEnabled: boolean;
isActive: boolean;
isFrozen: boolean;
// E-Mode
eModeCategoryId: number;
// Price information
priceInMarketReferenceCurrency: string;
priceInUsd: string;
};
Formatted User Summary
The userSummary
object contains the user's portfolio information:
type FormattedUserSummary = {
// Total portfolio values
totalCollateralUSD: string;
totalBorrowsUSD: string;
totalLiquidityUSD: string;
totalFeesUSD: string;
totalRewardsUSD: string;
// Health factor and borrowing power
healthFactor: string;
availableBorrowsUSD: string;
availableBorrowsMarketReferenceCurrency: string;
// Liquidation information
totalCollateralMarketReferenceCurrency: string;
totalBorrowsMarketReferenceCurrency: string;
totalFeesMarketReferenceCurrency: string;
totalRewardsMarketReferenceCurrency: string;
// Current timestamp
currentTimestamp: number;
// Market reference currency info
marketReferenceCurrencyDecimals: number;
marketReferenceCurrencyPriceInUsd: string;
// E-Mode information
userEmodeCategoryId: number;
};
Utility Functions
The SDK also provides utility functions for formatting specific values:
import { formatPercentage, formatBasisPoints } from '@sodax/sdk';
// Format percentage values (e.g., interest rates)
// rateValue is a bigint representing the rate with 27 decimals
const rateValue = 52500000000000000000000000n; // 5.25% with 27 decimals
const formattedRate = formatPercentage(rateValue, 27); // Returns "5.25%"
// Format basis points
// basisPointsValue is a bigint representing basis points (1 basis point = 0.01%)
const basisPointsValue = 250n; // 250 basis points = 2.50%
const formattedBasisPoints = formatBasisPoints(basisPointsValue); // Returns "2.50%"
// Example with different values
const highRate = 150000000000000000000000000n; // 15% with 27 decimals
const highRateFormatted = formatPercentage(highRate, 27); // Returns "15.00%"
const lowBasisPoints = 50n; // 50 basis points = 0.50%
const lowBasisPointsFormatted = formatBasisPoints(lowBasisPoints); // Returns "0.50%"
Last updated