Skip to content

Commit 63cc85b

Browse files
committed
Enhance Moolah SDK with new method to retrieve market user data with broker information. Introduce getMarketUserDataWithBroker for fixed-term markets, allowing integration of broker positions into user data. Update README to reflect new API method and improve documentation on USDT handling in approval steps. Add tests to validate new functionality and ensure correct behavior across Ethereum and BSC networks.
1 parent d0fe046 commit 63cc85b

11 files changed

Lines changed: 140 additions & 37 deletions

File tree

packages/moolah-lending-sdk/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# @lista-dao/moolah-lending-sdk
22

3+
## 1.0.6
4+
5+
### Patch Changes
6+
7+
- Enhance Moolah SDK with new method to retrieve market user data with broker information. Introduce `getMarketUserDataWithBroker` for fixed-term markets, allowing integration of broker positions into user data. Update README to reflect new API method and improve documentation on USDT handling in approval steps. Add tests to validate new functionality and ensure correct behavior across Ethereum and BSC networks.
8+
- Updated dependencies
9+
- @lista-dao/moolah-sdk-core@1.0.7
10+
311
## 1.0.5
412

513
### Patch Changes

packages/moolah-lending-sdk/README.md

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,23 @@ const brokerPositions = await sdk.getBrokerUserPositions(
112112
brokerAddress,
113113
userAddress,
114114
);
115+
116+
// Fixed-term market: get user data with broker merged (borrowed/borrowRate from broker)
117+
// Broker address is typically from API (holdings or market list).
118+
const userDataWithBroker = await sdk.getMarketUserDataWithBroker(
119+
chainId,
120+
marketId,
121+
userAddress,
122+
brokerAddress,
123+
);
124+
// Or manually: pass fixedTermData into getMarketUserData
125+
const fixedTermData = brokerPositionsToUserFixedTermData(brokerPositions);
126+
const userData = await sdk.getMarketUserData(
127+
chainId,
128+
marketId,
129+
userAddress,
130+
fixedTermData,
131+
);
115132
```
116133

117134
### API Data (with Filtering & Sorting)
@@ -316,22 +333,23 @@ const brokerRepaySteps = await sdk.buildBrokerRepayParams({
316333

317334
### Read Methods
318335

319-
| Method | Source | Description |
320-
| ------------------------------------------------- | ------ | -------------------------- |
321-
| `getMarketExtraInfo(chainId, marketId)` | Chain | Market on-chain data |
322-
| `getMarketUserData(chainId, marketId, user)` | Chain | User market position |
323-
| `getWriteConfig(chainId, marketId)` | Chain | Config for write ops |
324-
| `getVaultInfo(chainId, vaultAddress)` | Chain | Vault on-chain data |
325-
| `getVaultUserData(chainId, vaultAddress, user)` | Chain | User vault position |
326-
| `getSmartMarketExtraInfo(chainId, marketId)` | Chain | Smart market on-chain data |
327-
| `getSmartMarketUserData(chainId, marketId, user)` | Chain | Smart market user position |
328-
| `getBrokerFixedTerms(chainId, broker)` | Chain | Broker fixed-term rates |
329-
| `getBrokerUserPositions(chainId, broker, user)` | Chain | Broker user positions |
330-
| `getMarketInfo(chainId, marketId)` | API | Market metadata |
331-
| `getMarketList(params)` | API | Market list with filters |
332-
| `getVaultMetadata(address)` | API | Vault metadata |
333-
| `getVaultList(params)` | API | Vault list with filters |
334-
| `getMarketVaultDetails(marketId, params)` | API | Vaults for a market |
336+
| Method | Source | Description |
337+
| -------------------------------------------------------------- | ------ | ----------------------------------------------------- |
338+
| `getMarketExtraInfo(chainId, marketId)` | Chain | Market on-chain data |
339+
| `getMarketUserData(chainId, marketId, user)` | Chain | User market position |
340+
| `getMarketUserDataWithBroker(chainId, marketId, user, broker)` | Chain | User market position (fixed-term: merged broker data) |
341+
| `getWriteConfig(chainId, marketId)` | Chain | Config for write ops |
342+
| `getVaultInfo(chainId, vaultAddress)` | Chain | Vault on-chain data |
343+
| `getVaultUserData(chainId, vaultAddress, user)` | Chain | User vault position |
344+
| `getSmartMarketExtraInfo(chainId, marketId)` | Chain | Smart market on-chain data |
345+
| `getSmartMarketUserData(chainId, marketId, user)` | Chain | Smart market user position |
346+
| `getBrokerFixedTerms(chainId, broker)` | Chain | Broker fixed-term rates |
347+
| `getBrokerUserPositions(chainId, broker, user)` | Chain | Broker user positions |
348+
| `getMarketInfo(chainId, marketId)` | API | Market metadata |
349+
| `getMarketList(params)` | API | Market list with filters |
350+
| `getVaultMetadata(address)` | API | Vault metadata |
351+
| `getVaultList(params)` | API | Vault list with filters |
352+
| `getMarketVaultDetails(marketId, params)` | API | Vaults for a market |
335353

336354
### Build Methods
337355

packages/moolah-lending-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@lista-dao/moolah-lending-sdk",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"type": "module",
55
"main": "./dist/index.js",
66
"module": "./dist/index.js",

packages/moolah-lending-sdk/src/MoolahSDK.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
simulateMarketBorrow,
1111
simulateMarketRepay,
1212
toWriteConfig,
13+
brokerPositionsToUserFixedTermData,
1314
} from "@lista-dao/moolah-sdk-core";
1415
import type {
1516
MarketExtraInfo,
@@ -114,7 +115,9 @@ const CHAIN_BY_NETWORK: Record<NetworkName, Chain> = {
114115

115116
const EMPTY_TRANSPORT_CONFIG: SdkTransportConfig = {};
116117

117-
function toMarketSimulationState(extraInfo: MarketExtraInfo): SimulateMarketState {
118+
function toMarketSimulationState(
119+
extraInfo: MarketExtraInfo,
120+
): SimulateMarketState {
118121
return {
119122
totalSupply: extraInfo.totalSupply,
120123
totalBorrow: extraInfo.totalBorrow,
@@ -137,7 +140,9 @@ export class MoolahSDK {
137140
const apiBaseUrl = config.apiBaseUrl ?? LISTA_API_URLS.prod;
138141
this.apiClient = new MoolahApiClient({ baseUrl: apiBaseUrl });
139142

140-
for (const [chainId, client] of Object.entries(config.publicClients ?? {})) {
143+
for (const [chainId, client] of Object.entries(
144+
config.publicClients ?? {},
145+
)) {
141146
this.publicClients.set(chainId, client);
142147
}
143148
}
@@ -265,6 +270,32 @@ export class MoolahSDK {
265270
);
266271
}
267272

273+
async getMarketUserDataWithBroker(
274+
chainId: ChainId,
275+
marketId: Address,
276+
userAddress: Address,
277+
brokerAddress: Address,
278+
options?: { loanDecimals?: number; marketExtraInfo?: MarketExtraInfo },
279+
): Promise<MarketUserData> {
280+
const [brokerPositions, extraInfo] = await Promise.all([
281+
this.getBrokerUserPositions(
282+
chainId,
283+
brokerAddress,
284+
userAddress,
285+
options?.loanDecimals,
286+
),
287+
options?.marketExtraInfo ?? this.getMarketExtraInfo(chainId, marketId),
288+
]);
289+
const fixedTermData = brokerPositionsToUserFixedTermData(brokerPositions);
290+
return this.getMarketUserData(
291+
chainId,
292+
marketId,
293+
userAddress,
294+
fixedTermData,
295+
extraInfo,
296+
);
297+
}
298+
268299
async getWriteConfig(
269300
chainId: ChainId,
270301
marketId: Address,

packages/moolah-lending-sdk/src/__tests__/builders/approve.test.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,21 @@ describe("buildApproveSteps", () => {
8282
expect(steps[0].meta?.token).toBe(TEST_TOKEN);
8383
});
8484

85-
it("should reset USDT-like tokens before approving", async () => {
86-
// USDT on BSC
87-
const USDT_ADDRESS =
88-
"0x55d398326f99059fF775485246999027B3197955" as Address;
85+
it("should reset USDT-like tokens before approving (ethereum mainnet only)", async () => {
86+
const ETH_USDT =
87+
"0xdAC17F958D2ee523a2206206994597C13D831ec7" as Address;
8988
mockReadContract.mockResolvedValue(100n); // Has some existing allowance
9089

9190
const steps = await buildApproveSteps(
9291
{
93-
chainId: 56,
92+
chainId: 1,
9493
owner: TEST_OWNER,
95-
token: USDT_ADDRESS,
94+
token: ETH_USDT,
9695
spender: TEST_SPENDER,
9796
amount: 1000n,
9897
},
9998
mockPublicClient,
100-
"bsc",
99+
"ethereum",
101100
);
102101

103102
// Should have 2 steps: reset to 0, then approve
@@ -114,23 +113,45 @@ describe("buildApproveSteps", () => {
114113
expect(steps[1].meta?.reset).toBeUndefined();
115114
});
116115

117-
it("should not reset USDT if allowance is zero", async () => {
118-
const USDT_ADDRESS =
116+
it("should not reset BSC USDT (only ethereum USDT uses reset)", async () => {
117+
const BSC_USDT =
119118
"0x55d398326f99059fF775485246999027B3197955" as Address;
120-
mockReadContract.mockResolvedValue(0n);
119+
mockReadContract.mockResolvedValue(100n);
121120

122121
const steps = await buildApproveSteps(
123122
{
124123
chainId: 56,
125124
owner: TEST_OWNER,
126-
token: USDT_ADDRESS,
125+
token: BSC_USDT,
127126
spender: TEST_SPENDER,
128127
amount: 1000n,
129128
},
130129
mockPublicClient,
131130
"bsc",
132131
);
133132

133+
expect(steps).toHaveLength(1);
134+
expect(steps[0].meta?.reset).toBeUndefined();
135+
expect(steps[0].meta?.amount).toBe(1000n);
136+
});
137+
138+
it("should not reset USDT if allowance is zero", async () => {
139+
const ETH_USDT =
140+
"0xdAC17F958D2ee523a2206206994597C13D831ec7" as Address;
141+
mockReadContract.mockResolvedValue(0n);
142+
143+
const steps = await buildApproveSteps(
144+
{
145+
chainId: 1,
146+
owner: TEST_OWNER,
147+
token: ETH_USDT,
148+
spender: TEST_SPENDER,
149+
amount: 1000n,
150+
},
151+
mockPublicClient,
152+
"ethereum",
153+
);
154+
134155
expect(steps).toHaveLength(1);
135156
expect(steps[0].meta?.reset).toBeUndefined();
136157
});

packages/moolah-lending-sdk/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export {
6464
isUsdtLikeToken,
6565
getApiChain,
6666
LISTA_API_URLS,
67+
brokerPositionsToUserFixedTermData,
6768
} from "@lista-dao/moolah-sdk-core";
6869

6970
export const initMoolahSDK = (config: import("./types").MoolahSDKConfig) =>

packages/moolah-sdk-core/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @lista-dao/moolah-sdk-core
22

3+
## 1.0.7
4+
5+
### Patch Changes
6+
7+
- Enhance Moolah SDK with new method to retrieve market user data with broker information. Introduce `getMarketUserDataWithBroker` for fixed-term markets, allowing integration of broker positions into user data. Update README to reflect new API method and improve documentation on USDT handling in approval steps. Add tests to validate new functionality and ensure correct behavior across Ethereum and BSC networks.
8+
39
## 1.0.6
410

511
### Patch Changes

packages/moolah-sdk-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@lista-dao/moolah-sdk-core",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"type": "module",
55
"main": "./dist/index.js",
66
"module": "./dist/index.js",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Decimal } from "./utils/decimal.js";
2+
import type { BrokerUserPositionsData } from "./types/broker.js";
3+
import type { UserFixedTermData } from "./types/market.js";
4+
5+
/**
6+
* Convert broker user positions to UserFixedTermData for use with getMarketUserData.
7+
* Use this when the market is fixed-term and you have broker positions from getBrokerUserPositions.
8+
* Pass the result as the 4th argument to getMarketUserData so borrowed/borrowRate come from broker.
9+
*/
10+
export function brokerPositionsToUserFixedTermData(
11+
data: BrokerUserPositionsData,
12+
): UserFixedTermData {
13+
return {
14+
dynamicOutstanding: data.dynamicOutstanding ?? Decimal.ZERO,
15+
fixedOutstanding: data.fixedOutstanding,
16+
totalBorrowed: data.totalOutstanding,
17+
weightedBorrowRate: data.weightedBorrowRate,
18+
};
19+
}

packages/moolah-sdk-core/src/contracts/config.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ import type { Address } from "viem";
22
import type { NetworkName, NetworkContracts } from "./types.js";
33

44
/**
5-
* USDT addresses that require special approve handling (reset to 0 first)
5+
* USDT addresses that require special approve handling (reset to 0 first).
6+
* Only Ethereum mainnet USDT uses the non-standard approve behavior.
67
*/
78
export const USDT_ADDRESSES: Record<string, Address> = {
89
ethereum: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
9-
bsc: "0x55d398326f99059fF775485246999027B3197955",
1010
};
1111

1212
/**
13-
* Check if a token requires USDT-style approve (reset to 0 first)
14-
* @param network - Network name
15-
* @param tokenAddress - Token address to check
16-
* @returns true if token requires reset-then-approve pattern
13+
* Check if a token requires USDT-style approve (reset to 0 first).
14+
* Only Ethereum mainnet USDT needs this; BSC USDT does not.
1715
*/
1816
export function isUsdtLikeToken(
1917
network: NetworkName,

0 commit comments

Comments
 (0)