Skip to content

Commit fbb9e3c

Browse files
committed
feat: add router adapter
1 parent c5c28bc commit fbb9e3c

File tree

7 files changed

+399
-351
lines changed

7 files changed

+399
-351
lines changed

README.md

Lines changed: 167 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -948,34 +948,93 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
948948
```
949949

950950
### Leverage (createLoan, borrowMore, repay) for lendMarket
951+
952+
LendMarket leverage operations support different routers and require quote information from external routing services.
953+
954+
#### Breaking Changes
955+
956+
**1. New metrics methods - get all metrics in one call**
957+
- Instead of `createLoanBands`, `createLoanPrices`, `createLoanHealth`, `createLoanPriceImpact`: `createLoanExpectedMetrics()` - returns priceImpact, bands, prices, health
958+
- Instead of `borrowMoreBands`, `borrowMorePrices`, `borrowMoreHealth`, `borrowMorePriceImpact`:
959+
`borrowMoreExpectedMetrics()`returns priceImpact, bands, prices, health
960+
- Instead of `repayBands`, `repayPrices`, `repayHealth`, `repayPriceImpact`:
961+
`repayExpectedMetrics()`returns priceImpact, bands, prices, health
962+
963+
964+
**ILeverageMetrics** - metrics object returned by new methods:
965+
966+
```ts
967+
interface ILeverageMetrics {
968+
priceImpact: number;
969+
bands: [number, number];
970+
prices: string[];
971+
health: string;
972+
}
973+
```
974+
975+
**2. Final methods now require `router` and `calldata` parameters**
976+
- **Before**: `createLoan(userCollateral, userBorrowed, debt, range)`
977+
- **Now**: `createLoan(userCollateral, userBorrowed, debt, range, router, calldata)`
978+
- **Before**: `borrowMore(userCollateral, userBorrowed, debt, slippage)`
979+
- **Now**: `borrowMore(userCollateral, userBorrowed, debt, router, calldata)`
980+
- **Before**: `repay(stateCollateral, userCollateral, userBorrowed, slippage)`
981+
- **Now**: `repay(stateCollateral, userCollateral, userBorrowed, router, calldata)`
982+
983+
where `router` - address of router, `calldata` - calldata byte code
984+
985+
#### Understanding Callback Functions and Quotes
986+
987+
**GetExpectedFn** - callback function for fetching quotes from router (e.g., Odos, Curve):
988+
989+
```ts
990+
type GetExpectedFn = (
991+
fromToken: string, // Address of token to swap from
992+
toToken: string, // Address of token to swap to
993+
amountIn: bigint, // Amount of tokens to swap (in wei)
994+
blacklist: string | string[], // Contract/pool addresses to exclude
995+
) => Promise<IQuote>;
996+
```
997+
998+
**IQuote** - quote object with swap information:
999+
1000+
```ts
1001+
interface IQuote {
1002+
outAmount: string; // Amount of tokens to receive
1003+
priceImpact: number; // Price impac
1004+
}
1005+
```
1006+
1007+
#### Which quotes are needed for different operations
1008+
1009+
| Action type | Quote inputAmount |
1010+
|--------------|------------------|
1011+
| createLoan | debt + userBorrowed |
1012+
| borrowMore | debt + userBorrowed |
1013+
| repay | stateCollateral + userCollateral |
1014+
1015+
**For createLoan and borrowMore:**
1016+
- Get quote for swapping `(debt + userBorrowed)` borrowed tokenscollateral tokens
1017+
- Example: For debt=2000 and userBorrowed=1000, get quote for swapping 3000 borrowed tokens to collateral
1018+
1019+
!!! Be careful: here debt means the amount of debt added during the operation, not the new total debt the user will have after it.
1020+
1021+
**For repay:**
1022+
- Get quote for swapping `(stateCollateral + userCollateral)` collateral tokensborrowed tokens
1023+
- Example: For stateCollateral=2 and userCollateral=1, get quote for swapping 3 collateral tokens to borrowed tokens
1024+
1025+
1026+
#### Leverage operations with routers
1027+
9511028
```ts
9521029
(async () => {
953-
await llamalend.init('JsonRpc', {}, {}, API_KEY_1INCH);
1030+
await llamalend.init('JsonRpc', {});
9541031
await llamalend.lendMarkets.fetchMarkets();
9551032
9561033
const lendMarket = llamalend.getLendMarket('one-way-market-0');
957-
console.log(lendMarket.collateral_token, lendMarket.borrowed_token);
958-
// {
959-
// address: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1',
960-
// decimals: 18,
961-
// name: 'Wrapped Ether',
962-
// symbol: 'WETH'
963-
// }
964-
//
965-
// {
966-
// address: '0x498bf2b1e120fed3ad3d42ea2165e9b73f99c1e5',
967-
// decimals: 18,
968-
// name: 'curve.finance USD Stablecoin',
969-
// symbol: 'crvUSD'
970-
// }
971-
console.log(await lendMarket.wallet.balances());
972-
// {
973-
// collateral: '100.0',
974-
// borrowed: '2000000.0',
975-
// vaultShares: '0.0',
976-
// gauge: '0'
977-
// }
978-
1034+
1035+
const router = '0x.....'; // router name
1036+
const calldata = '0x...'; // calldata from router for executing swap
1037+
const quote = // quote from your router (debt + userBorrowed)
9791038
9801039
// - Create Loan -
9811040
@@ -994,10 +1053,11 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
9941053
let userBorrowed = 1000;
9951054
let debt = 2000;
9961055
const range = 10;
997-
const slippage = 0.5; // %
9981056
await lendMarket.leverage.maxLeverage(range);
9991057
// 7.4728229145282742179
1000-
await lendMarket.leverage.createLoanMaxRecv(userCollateral, userBorrowed, range);
1058+
1059+
// Get maximum possible debt for given parameters
1060+
await lendMarket.leverage.createLoanMaxRecv(userCollateral, userBorrowed, range, getExpected);
10011061
// {
10021062
// maxDebt: '26089.494406081862861214',
10031063
// maxTotalCollateral: '9.539182089833411347',
@@ -1007,7 +1067,11 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
10071067
// maxLeverage: '7.25291100528992828612',
10081068
// avgPrice: '3172.3757757003568790858'
10091069
// }
1010-
await lendMarket.leverage.createLoanExpectedCollateral(userCollateral, userBorrowed, debt, slippage);
1070+
1071+
// Get quote for swapping (debt + userBorrowed)!!!
1072+
1073+
// Get expected collateral amount
1074+
await lendMarket.leverage.createLoanExpectedCollateral(userCollateral, userBorrowed, debt, quote);
10111075
// {
10121076
// totalCollateral: '1.946422996710829',
10131077
// userCollateral: '1.0',
@@ -1016,31 +1080,34 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
10161080
// leverage: '1.4796358613861877'
10171081
// avgPrice: '3169.8299919022623523421'
10181082
// }
1019-
await lendMarket.leverage.createLoanPriceImpact(userBorrowed, debt);
1020-
// 0.08944411854377342 %
1021-
await lendMarket.leverage.createLoanMaxRange(userCollateral, userBorrowed, debt);
1022-
// 50
1023-
await lendMarket.leverage.createLoanBands(userCollateral, userBorrowed, debt, range);
1024-
// [ 76, 67 ]
1025-
await lendMarket.leverage.createLoanPrices(userCollateral, userBorrowed, debt, range);
1026-
// [ '1027.977701011670136614', '1187.061409925215211173' ]
1027-
await lendMarket.leverage.createLoanHealth(userCollateral, userBorrowed, debt, range);
1028-
// 195.8994783042570637
1029-
await lendMarket.leverage.createLoanHealth(userCollateral, userBorrowed, debt, range, false);
1030-
// 3.2780908310686365
1083+
1084+
// NEW: Get all metrics in one call
1085+
const metrics = await lendMarket.leverage.createLoanExpectedMetrics(
1086+
userCollateral,
1087+
userBorrowed,
1088+
debt,
1089+
range,
1090+
quote,
1091+
true // healthIsFull - true for full health, false for not full
1092+
);
1093+
// {
1094+
// priceImpact: 0.08944411854377342, // %
1095+
// bands: [76, 67],
1096+
// prices: ['1027.977701011670136614', '1187.061409925215211173'],
1097+
// health: '195.8994783042570637' // %
1098+
//
1099+
10311100
await lendMarket.leverage.createLoanIsApproved(userCollateral, userBorrowed);
10321101
// false
10331102
await lendMarket.leverage.createLoanApprove(userCollateral, userBorrowed);
10341103
// [
10351104
// '0xd5491d9f1e9d8ac84b03867494e35b25efad151c597d2fa4211d7bf5d540c98e',
10361105
// '0x93565f37ec5be902a824714a30bddc25cf9cd9ed39b4c0e8de61fab44af5bc8c'
10371106
// ]
1038-
await lendMarket.leverage.createLoanRouteImage(userBorrowed, debt);
1039-
// 'data:image/svg+xml;base64,PHN2ZyBpZD0ic2Fua2V5UGFyZW50U3ZnIiB4bWxucz...'
10401107
10411108
1042-
// You must call lendMarket.leverage.createLoanExpectedCollateral() with the same args before
1043-
await lendMarket.leverage.createLoan(userCollateral, userBorrowed, debt, range);
1109+
// Create loan, passing router address and calldata from router
1110+
await lendMarket.leverage.createLoan(userCollateral, userBorrowed, debt, range, router, calldata);
10441111
// 0xeb1b7a92bcb02598f00dc8bbfe8fa3a554e7a2b1ca764e0ee45e2bf583edf731
10451112
10461113
await lendMarket.wallet.balances();
@@ -1083,7 +1150,9 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
10831150
userCollateral = 2;
10841151
userBorrowed = 2000;
10851152
debt = 10000;
1086-
await lendMarket.leverage.borrowMoreMaxRecv(userCollateral, userBorrowed);
1153+
1154+
// Get maximum possible debt for given parameters
1155+
await lendMarket.leverage.borrowMoreMaxRecv(userCollateral, userBorrowed, getExpected);
10871156
// {
10881157
// maxDebt: '76182.8497941193262889',
10891158
// maxTotalCollateral: '26.639775583730298462',
@@ -1092,33 +1161,40 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
10921161
// collateralFromMaxDebt: '22.962457277119938834',
10931162
// avgPrice: '3172.55402418338331369083'
10941163
// }
1095-
await lendMarket.leverage.borrowMoreExpectedCollateral(userCollateral, userBorrowed, debt, slippage);
1164+
1165+
// Get quote for swapping (debt + userBorrowed)
1166+
1167+
await lendMarket.leverage.borrowMoreExpectedCollateral(userCollateral, userBorrowed, debt, quote);
10961168
// {
10971169
// totalCollateral: '5.783452104143246413',
10981170
// userCollateral: '2.0',
10991171
// collateralFromUserBorrowed: '0.630575350690541071',
11001172
// collateralFromDebt: '3.152876753452705342'
11011173
// avgPrice: '3171.70659749038129067231'
11021174
// }
1103-
await lendMarket.leverage.borrowMorePriceImpact(userBorrowed, debt);
1104-
// 0.010784277354269765 %
1105-
await lendMarket.leverage.borrowMoreBands(userCollateral, userBorrowed, debt);
1106-
// [ 47, 38 ]
1107-
await lendMarket.leverage.borrowMorePrices(userCollateral, userBorrowed, debt);
1108-
// [ '1560.282474721398939216', '1801.742501325928269008' ]
1109-
await lendMarket.leverage.borrowMoreHealth(userCollateral, userBorrowed, debt, true);
1110-
// 91.6798951784708552
1111-
await lendMarket.leverage.borrowMoreHealth(userCollateral, userBorrowed, debt, false);
1112-
// 3.7614279042995641
1175+
1176+
// NEW: Get all metrics in one call
1177+
const metricsBM = await lendMarket.leverage.borrowMoreExpectedMetrics(
1178+
userCollateral,
1179+
userBorrowed,
1180+
debt,
1181+
quote,
1182+
true // healthIsFull - true for full health, false for not full
1183+
);
1184+
// {
1185+
// priceImpact: 0.010784277354269765, // %
1186+
// bands: [47, 38],
1187+
// prices: ['1560.282474721398939216', '1801.742501325928269008'],
1188+
// health: '91.6798951784708552' // %
1189+
// }
1190+
11131191
await lendMarket.leverage.borrowMoreIsApproved(userCollateral, userBorrowed);
11141192
// true
11151193
await lendMarket.leverage.borrowMoreApprove(userCollateral, userBorrowed);
11161194
// []
1117-
await lendMarket.leverage.borrowMoreRouteImage(userBorrowed, debt);
1118-
// 'data:image/svg+xml;base64,PHN2ZyBpZD0ic2Fua2V5UGFyZW50U3ZnIiB4bWxucz...'
11191195
1120-
// You must call lendMarket.leverage.borrowMoreExpectedCollateral() with the same args before
1121-
await lendMarket.leverage.borrowMore(userCollateral, userBorrowed, debt, slippage);
1196+
// Execute borrowMore, passing router address and calldata from router
1197+
await lendMarket.leverage.borrowMore(userCollateral, userBorrowed, debt, router, calldata);
11221198
// 0x6357dd6ea7250d7adb2344cd9295f8255fd8fbbe85f00120fbcd1ebf139e057c
11231199
11241200
await lendMarket.wallet.balances();
@@ -1164,7 +1240,10 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
11641240
const stateCollateral = 2;
11651241
userCollateral = 1;
11661242
userBorrowed = 1500;
1167-
await lendMarket.leverage.repayExpectedBorrowed(stateCollateral, userCollateral, userBorrowed, slippage);
1243+
1244+
// Get quote for swapping (stateCollateral + userCollateral)
1245+
1246+
await lendMarket.leverage.repayExpectedBorrowed(stateCollateral, userCollateral, userBorrowed, quote);
11681247
// {
11691248
// totalBorrowed: '10998.882838599741571472',
11701249
// borrowedFromStateCollateral: '6332.588559066494374648',
@@ -1173,29 +1252,33 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
11731252
// avgPrice: '3166.29427953324743125312'
11741253
// }
11751254
1176-
await lendMarket.leverage.repayPriceImpact(stateCollateral, userCollateral);
1177-
// 0.013150142802201724 %
1178-
await lendMarket.leverage.repayIsFull(stateCollateral, userCollateral, userBorrowed);
1255+
await lendMarket.leverage.repayIsFull(stateCollateral, userCollateral, userBorrowed, quote);
11791256
// false
1180-
await lendMarket.leverage.repayIsAvailable(stateCollateral, userCollateral, userBorrowed);
1257+
await lendMarket.leverage.repayIsAvailable(stateCollateral, userCollateral, userBorrowed, quote);
11811258
// true
1182-
await lendMarket.leverage.repayBands(stateCollateral, userCollateral, userBorrowed);
1183-
// [ 199, 190 ]
1184-
await lendMarket.leverage.repayPrices(stateCollateral, userCollateral, userBorrowed);
1185-
// [ '175.130965754280721633', '202.233191367561902757' ]
1186-
await lendMarket.leverage.repayHealth(stateCollateral, userCollateral, userBorrowed, true);
1187-
// 1699.6097751079226865
1188-
await lendMarket.leverage.repayHealth(stateCollateral, userCollateral, userBorrowed, false);
1189-
// 3.4560086962806991
1259+
1260+
// NEW: Get all metrics in one call
1261+
const metricsRepay = await lendMarket.leverage.repayExpectedMetrics(
1262+
stateCollateral,
1263+
userCollateral,
1264+
userBorrowed,
1265+
true, // healthIsFull - true for full health, false for not full
1266+
quote
1267+
);
1268+
// {
1269+
// priceImpact: 0.013150142802201724, // %
1270+
// bands: [199, 190],
1271+
// prices: ['175.130965754280721633', '202.233191367561902757'],
1272+
// health: '1699.6097751079226865' // %
1273+
// }
1274+
11901275
await lendMarket.leverage.repayIsApproved(userCollateral, userBorrowed);
11911276
// false
11921277
await lendMarket.leverage.repayApprove(userCollateral, userBorrowed);
11931278
// ['0xd8a8d3b3f67395e1a4f4d4f95b041edcaf1c9f7bab5eb8a8a767467678295498']
1194-
await lendMarket.leverage.repayRouteImage(stateCollateral, userCollateral);
1195-
// 'data:image/svg+xml;base64,PHN2ZyBpZD0ic2Fua2V5UGFyZW50U3ZnIiB4bWxucz...'
11961279
1197-
// You must call lendMarket.leverage.repayExpectedBorrowed() with the same args before
1198-
await lendMarket.leverage.repay(stateCollateral, userCollateral, userBorrowed, slippage);
1280+
// Execute repay, passing router address and calldata from router
1281+
await lendMarket.leverage.repay(stateCollateral, userCollateral, userBorrowed, router, calldata);
11991282
// 0xe48a97fef1c54180a2c7d104d210a95ac1a516fdd22109682179f1582da23a82
12001283
12011284
await lendMarket.wallet.balances();
@@ -1225,15 +1308,17 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
12251308

12261309
### Leverage createLoan all ranges methods for lendMarket
12271310
```ts
1228-
await llamalend.init('JsonRpc', {}, {}, API_KEY_1INCH);
1311+
await llamalend.init('JsonRpc', {});
12291312
await llamalend.lendMarkets.fetchMarkets();
12301313
12311314
const lendMarket = llamalend.getLendMarket('one-way-market-0');
12321315
12331316
const userCollateral = 1;
12341317
const userBorrowed = 1000;
12351318
const debt = 2000;
1236-
await lendMarket.leverage.createLoanMaxRecvAllRanges(userCollateral, userBorrowed);
1319+
1320+
// Get maximum values for all possible ranges
1321+
await lendMarket.leverage.createLoanMaxRecvAllRanges(userCollateral, userBorrowed, getExpected);
12371322
// {
12381323
// '4': {
12391324
// maxDebt: '37916.338071504823875251',
@@ -1283,8 +1368,10 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
12831368
// maxLeverage: '2.94916151440614435181',
12841369
// avgPrice: '3167.28167656266072703689'
12851370
// }
1286-
1287-
await lendMarket.leverage.createLoanBandsAllRanges(userCollateral, userBorrowed, debt);
1371+
1372+
// Get quote for specific debt + userBorrowed
1373+
// and provide getExpected callback
1374+
await lendMarket.leverage.createLoanBandsAllRanges(userCollateral, userBorrowed, debt, getExpected, quote);
12881375
// {
12891376
// '4': [ 73, 70 ],
12901377
// '5': [ 73, 69 ],
@@ -1296,7 +1383,7 @@ await lendMarket.forceUpdateUserState(txHash, "0x123...");
12961383
// '50': [ 97, 48 ]
12971384
// }
12981385
1299-
await lendMarket.leverage.createLoanPricesAllRanges(userCollateral, userBorrowed, debt);
1386+
await lendMarket.leverage.createLoanPricesAllRanges(userCollateral, userBorrowed, debt, getExpected, quote);
13001387
// {
13011388
// '4': [ '1073.323292757532604807', '1136.910693647788699808' ],
13021389
// '5': [ '1073.323292757532604807', '1153.387660222394333133' ],

0 commit comments

Comments
 (0)