π°Lend / Borrow (Money Market)
Money Market part of SDK provides abstractions to assist you with interacting with the cross-chain Money Market Smart Contracts.
All money market operations are accessed through the moneyMarket property of a Sodax instance:
import { Sodax, type SpokeChainId, type Token } from "@sodax/sdk";
const sodax = new Sodax();
// All money market methods are available through sodax.moneyMarket
const supplyResult = await sodax.moneyMarket.supply(supplyParams, spokeProvider);Using SDK Config and Constants
SDK includes predefined configurations of supported chains, tokens and other relevant information for the client to consume. All configurations are accessible through the config property of the Sodax instance (sodax.config), or through service-specific properties for convenience.
IMPORTANT: If you want dynamic (backend API based - contains latest tokens) configuration, make sure to initialize the instance before usage:
await sodax.initialize();By default, configuration from the specific SDK version you are using is used.
import { Sodax, type SpokeChainId, type Token, type Address } from "@sodax/sdk";
const sodax = new Sodax();
await sodax.initialize(); // Initialize for dynamic config (optional)
// All supported spoke chains (general config)
const spokeChains: SpokeChainId[] = sodax.config.getSupportedSpokeChains();
// Get supported money market tokens for a specific chain
const supportedMoneyMarketTokens: readonly Token[] = sodax.moneyMarket.getSupportedTokensByChainId(chainId);
// Get all supported money market tokens per chain
const allMoneyMarketTokens = sodax.moneyMarket.getSupportedTokens();
// Get all supported reserves (hub chain token addresses, i.e. money market on Sonic chain)
const supportedReserves: readonly Address[] = sodax.moneyMarket.getSupportedReserves();
// Check if token address for given spoke chain id is supported (through config service)
const isMoneyMarketSupportedToken: boolean = sodax.config.isMoneyMarketSupportedToken(chainId, token);
// Alternative: Access through config service
const moneyMarketTokensFromConfig: readonly Token[] = sodax.config.getSupportedMoneyMarketTokensByChainId(chainId);
const allMoneyMarketTokensFromConfig = sodax.config.getSupportedMoneyMarketTokens();Please refer to SDK constants.ts for additional static constants and configurations.
Available Methods
All money market methods are accessible through sodax.moneyMarket:
Token & Reserve Configuration
getSupportedTokensByChainId(chainId)- Get supported money market tokens for a specific chaingetSupportedTokens()- Get all supported money market tokens per chaingetSupportedReserves()- Get all supported money market reserves (hub chain addresses)
Allowance & Approval
isAllowanceValid(params, spokeProvider)- Check if token approval is neededapprove(params, spokeProvider, raw?)- Approve tokens or request trustline (Stellar)
Money Market Operations
supply(params, spokeProvider, timeout?)- Supply tokens (complete operation with relay)createSupplyIntent(params, spokeProvider, raw?)- Create supply intent onlyborrow(params, spokeProvider, timeout?)- Borrow tokens (complete operation with relay)createBorrowIntent(params, spokeProvider, raw?)- Create borrow intent onlywithdraw(params, spokeProvider, timeout?)- Withdraw tokens (complete operation with relay)createWithdrawIntent(params, spokeProvider, raw?)- Create withdraw intent onlyrepay(params, spokeProvider, timeout?)- Repay tokens (complete operation with relay)createRepayIntent(params, spokeProvider, raw?)- Create repay intent only
Data Retrieval & Formatting
data.getReservesList()- Get list of all reserve addressesdata.getReservesData()- Get raw aggregated reserve datadata.getReservesHumanized()- Get humanized reserve datadata.getReserveData(asset)- Get specific reserve datadata.getUserReservesData(spokeProvider)- Get raw user reserve datadata.getUserReservesHumanized(spokeProvider)- Get humanized user reserve datadata.formatReservesUSD(request)- Format reserves with USD conversionsdata.formatUserSummary(request)- Format user portfolio summary with USD conversions
Utility Methods
MoneyMarketService.estimateGas(rawTx, spokeProvider)- Estimate gas for raw transactions (static method)
Initialising Spoke Provider
Refer to Initialising Spoke Provider section to see how BSC spoke provider used as bscSpokeProvider can be created.
Function Parameters Structure
All money market functions use object parameters for better readability and extensibility. The common parameter structure includes:
params: The money market operation parameters (MoneyMarketSupplyParams,MoneyMarketBorrowParams,MoneyMarketWithdrawParams, orMoneyMarketRepayParams) containing token address, amount, and action typespokeProvider: The spoke provider instance for the source chainraw: (Optional) Whether to return raw transaction data instead of executing the transaction. Used increate*Intentandapprovemethods. Default:falsetimeout: (Optional) Timeout in milliseconds for relay operations (default: 60 seconds). Used insupply,borrow,withdraw, andrepaymethods
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.
Note: For Stellar-based operations, the allowance and approval system works differently:
Source Chain (Stellar): The standard
isAllowanceValidandapprovemethods work as expected for EVM chains, but for Stellar as the source chain, these methods check and establish trustlines automatically.Destination Chain (Stellar): When Stellar is specified as the destination chain, frontends/clients need to manually establish trustlines before executing money market actions using
StellarSpokeService.hasSufficientTrustlineandStellarSpokeService.requestTrustlinefunctions.
Checking Allowance
The isAllowanceValid method checks if the current allowance is sufficient for the specified action:
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)
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
Stellar Trustline Requirements
For Stellar-based money market operations, you need to handle trustlines differently depending on whether Stellar is the source or destination chain. See Stellar Trustline Requirements for detailed information and code examples.
Complete Example
Here's a complete example showing the allowance check and approval flow:
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.
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)
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)
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)
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)
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:
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:
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:
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:
Handling Allowance and Approval Errors
Allowance and approval operations have simpler error handling:
Error Data Structure
Each error type contains specific data that can help with debugging and error handling:
Best Practices for Error Handling
Always check for
SUBMIT_TX_FAILEDerrors: These are critical and require immediate attention to prevent funds from getting stuck.Store transaction data locally: When a
SUBMIT_TX_FAILEDerror 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:
Step-by-Step Data Retrieval Process
1. Fetch Raw Data
First, retrieve the raw data from the blockchain:
2. Build Formatting Requests
Use the helper methods to build the formatting requests:
3. Format Data
Apply the formatting to get human-readable values with USD conversions:
Data Structure Examples
Formatted Reserve Data
The formattedReserves array contains objects with the following structure:
Formatted User Summary
The userSummary object contains the user's portfolio information:
Utility Functions
The SDK also provides utility functions for formatting specific values:
Last updated