@mento-protocol/mento-sdk 3.1.0-beta.4 → 3.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/abis/index.d.ts +1 -0
- package/dist/core/abis/index.js +1 -0
- package/dist/core/abis/liquidityStrategy.d.ts +132 -0
- package/dist/core/abis/liquidityStrategy.js +10 -0
- package/dist/core/constants/addresses.js +1 -0
- package/dist/core/types/contractAddresses.d.ts +1 -0
- package/dist/core/types/liquidity.d.ts +43 -0
- package/dist/core/types/pool.d.ts +64 -1
- package/dist/esm/core/abis/index.js +1 -0
- package/dist/esm/core/abis/liquidityStrategy.js +6 -0
- package/dist/esm/core/constants/addresses.js +1 -0
- package/dist/esm/index.js +25 -9
- package/dist/esm/services/borrow/internal/borrowReadService.js +63 -34
- package/dist/esm/services/borrow/internal/borrowRegistryReader.js +45 -28
- package/dist/esm/services/index.js +1 -0
- package/dist/esm/services/liquidity/LiquidityService.js +26 -2
- package/dist/esm/services/liquidity/liquidityHelpers.js +36 -7
- package/dist/esm/services/liquidity/rebalance.js +59 -0
- package/dist/esm/services/liquidity/zapHelpers.js +20 -24
- package/dist/esm/services/liquidity/zapIn.js +68 -75
- package/dist/esm/services/liquidity/zapOut.js +89 -77
- package/dist/esm/services/pools/PoolService.js +126 -22
- package/dist/esm/services/pools/poolDetails.js +99 -58
- package/dist/esm/services/pools/rebalancePreview.js +181 -0
- package/dist/esm/services/quotes/QuoteService.js +22 -20
- package/dist/esm/services/routes/RouteService.js +82 -24
- package/dist/esm/services/swap/SwapService.js +81 -37
- package/dist/esm/services/tokens/tokenService.js +142 -29
- package/dist/esm/services/trading/TradingService.js +51 -12
- package/dist/esm/utils/multicall.js +29 -2
- package/dist/index.d.ts +11 -1
- package/dist/index.js +25 -9
- package/dist/services/borrow/internal/borrowReadService.d.ts +1 -0
- package/dist/services/borrow/internal/borrowReadService.js +63 -34
- package/dist/services/borrow/internal/borrowRegistryReader.js +45 -28
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/liquidity/LiquidityService.d.ts +18 -1
- package/dist/services/liquidity/LiquidityService.js +24 -0
- package/dist/services/liquidity/liquidityHelpers.d.ts +8 -2
- package/dist/services/liquidity/liquidityHelpers.js +36 -6
- package/dist/services/liquidity/rebalance.d.ts +6 -0
- package/dist/services/liquidity/rebalance.js +64 -0
- package/dist/services/liquidity/zapHelpers.js +20 -24
- package/dist/services/liquidity/zapIn.d.ts +2 -1
- package/dist/services/liquidity/zapIn.js +67 -73
- package/dist/services/liquidity/zapOut.d.ts +2 -10
- package/dist/services/liquidity/zapOut.js +90 -77
- package/dist/services/pools/PoolService.d.ts +8 -1
- package/dist/services/pools/PoolService.js +125 -21
- package/dist/services/pools/poolDetails.d.ts +2 -0
- package/dist/services/pools/poolDetails.js +100 -57
- package/dist/services/pools/rebalancePreview.d.ts +5 -0
- package/dist/services/pools/rebalancePreview.js +186 -0
- package/dist/services/quotes/QuoteService.d.ts +1 -0
- package/dist/services/quotes/QuoteService.js +24 -21
- package/dist/services/routes/RouteService.d.ts +8 -0
- package/dist/services/routes/RouteService.js +82 -24
- package/dist/services/swap/SwapService.d.ts +19 -0
- package/dist/services/swap/SwapService.js +81 -37
- package/dist/services/tokens/tokenService.d.ts +7 -0
- package/dist/services/tokens/tokenService.js +142 -29
- package/dist/services/trading/TradingService.d.ts +3 -0
- package/dist/services/trading/TradingService.js +51 -12
- package/dist/utils/multicall.d.ts +5 -1
- package/dist/utils/multicall.js +29 -2
- package/package.json +1 -1
package/dist/core/abis/index.js
CHANGED
|
@@ -34,4 +34,5 @@ __exportStar(require("./troveNFT"), exports);
|
|
|
34
34
|
__exportStar(require("./priceFeed"), exports);
|
|
35
35
|
__exportStar(require("./addressesRegistry"), exports);
|
|
36
36
|
__exportStar(require("./systemParams"), exports);
|
|
37
|
+
__exportStar(require("./liquidityStrategy"), exports);
|
|
37
38
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export declare const LIQUIDITY_STRATEGY_ABI: readonly [{
|
|
2
|
+
readonly name: "poolConfigs";
|
|
3
|
+
readonly type: "function";
|
|
4
|
+
readonly stateMutability: "view";
|
|
5
|
+
readonly inputs: readonly [{
|
|
6
|
+
readonly type: "address";
|
|
7
|
+
}];
|
|
8
|
+
readonly outputs: readonly [{
|
|
9
|
+
readonly type: "bool";
|
|
10
|
+
readonly name: "isToken0Debt";
|
|
11
|
+
}, {
|
|
12
|
+
readonly type: "uint32";
|
|
13
|
+
readonly name: "lastRebalance";
|
|
14
|
+
}, {
|
|
15
|
+
readonly type: "uint32";
|
|
16
|
+
readonly name: "rebalanceCooldown";
|
|
17
|
+
}, {
|
|
18
|
+
readonly type: "address";
|
|
19
|
+
readonly name: "protocolFeeRecipient";
|
|
20
|
+
}, {
|
|
21
|
+
readonly type: "uint64";
|
|
22
|
+
readonly name: "liquiditySourceIncentiveExpansion";
|
|
23
|
+
}, {
|
|
24
|
+
readonly type: "uint64";
|
|
25
|
+
readonly name: "protocolIncentiveExpansion";
|
|
26
|
+
}, {
|
|
27
|
+
readonly type: "uint64";
|
|
28
|
+
readonly name: "liquiditySourceIncentiveContraction";
|
|
29
|
+
}, {
|
|
30
|
+
readonly type: "uint64";
|
|
31
|
+
readonly name: "protocolIncentiveContraction";
|
|
32
|
+
}];
|
|
33
|
+
}, {
|
|
34
|
+
readonly name: "determineAction";
|
|
35
|
+
readonly type: "function";
|
|
36
|
+
readonly stateMutability: "view";
|
|
37
|
+
readonly inputs: readonly [{
|
|
38
|
+
readonly type: "address";
|
|
39
|
+
readonly name: "pool";
|
|
40
|
+
}];
|
|
41
|
+
readonly outputs: readonly [{
|
|
42
|
+
readonly type: "tuple";
|
|
43
|
+
readonly components: readonly [{
|
|
44
|
+
readonly type: "address";
|
|
45
|
+
readonly name: "pool";
|
|
46
|
+
}, {
|
|
47
|
+
readonly type: "tuple";
|
|
48
|
+
readonly components: readonly [{
|
|
49
|
+
readonly type: "uint256";
|
|
50
|
+
readonly name: "reserveNum";
|
|
51
|
+
}, {
|
|
52
|
+
readonly type: "uint256";
|
|
53
|
+
readonly name: "reserveDen";
|
|
54
|
+
}];
|
|
55
|
+
readonly name: "reserves";
|
|
56
|
+
}, {
|
|
57
|
+
readonly type: "tuple";
|
|
58
|
+
readonly components: readonly [{
|
|
59
|
+
readonly type: "uint256";
|
|
60
|
+
readonly name: "oracleNum";
|
|
61
|
+
}, {
|
|
62
|
+
readonly type: "uint256";
|
|
63
|
+
readonly name: "oracleDen";
|
|
64
|
+
}, {
|
|
65
|
+
readonly type: "bool";
|
|
66
|
+
readonly name: "poolPriceAbove";
|
|
67
|
+
}, {
|
|
68
|
+
readonly type: "uint16";
|
|
69
|
+
readonly name: "rebalanceThreshold";
|
|
70
|
+
}];
|
|
71
|
+
readonly name: "prices";
|
|
72
|
+
}, {
|
|
73
|
+
readonly type: "address";
|
|
74
|
+
readonly name: "token0";
|
|
75
|
+
}, {
|
|
76
|
+
readonly type: "address";
|
|
77
|
+
readonly name: "token1";
|
|
78
|
+
}, {
|
|
79
|
+
readonly type: "uint64";
|
|
80
|
+
readonly name: "token0Dec";
|
|
81
|
+
}, {
|
|
82
|
+
readonly type: "uint64";
|
|
83
|
+
readonly name: "token1Dec";
|
|
84
|
+
}, {
|
|
85
|
+
readonly type: "bool";
|
|
86
|
+
readonly name: "isToken0Debt";
|
|
87
|
+
}, {
|
|
88
|
+
readonly type: "tuple";
|
|
89
|
+
readonly components: readonly [{
|
|
90
|
+
readonly type: "uint64";
|
|
91
|
+
readonly name: "liquiditySourceIncentiveExpansion";
|
|
92
|
+
}, {
|
|
93
|
+
readonly type: "uint64";
|
|
94
|
+
readonly name: "protocolIncentiveExpansion";
|
|
95
|
+
}, {
|
|
96
|
+
readonly type: "uint64";
|
|
97
|
+
readonly name: "liquiditySourceIncentiveContraction";
|
|
98
|
+
}, {
|
|
99
|
+
readonly type: "uint64";
|
|
100
|
+
readonly name: "protocolIncentiveContraction";
|
|
101
|
+
}];
|
|
102
|
+
readonly name: "incentives";
|
|
103
|
+
}];
|
|
104
|
+
readonly name: "ctx";
|
|
105
|
+
}, {
|
|
106
|
+
readonly type: "tuple";
|
|
107
|
+
readonly components: readonly [{
|
|
108
|
+
readonly type: "uint8";
|
|
109
|
+
readonly name: "dir";
|
|
110
|
+
}, {
|
|
111
|
+
readonly type: "uint256";
|
|
112
|
+
readonly name: "amount0Out";
|
|
113
|
+
}, {
|
|
114
|
+
readonly type: "uint256";
|
|
115
|
+
readonly name: "amount1Out";
|
|
116
|
+
}, {
|
|
117
|
+
readonly type: "uint256";
|
|
118
|
+
readonly name: "amountOwedToPool";
|
|
119
|
+
}];
|
|
120
|
+
readonly name: "action";
|
|
121
|
+
}];
|
|
122
|
+
}, {
|
|
123
|
+
readonly name: "rebalance";
|
|
124
|
+
readonly type: "function";
|
|
125
|
+
readonly stateMutability: "nonpayable";
|
|
126
|
+
readonly inputs: readonly [{
|
|
127
|
+
readonly type: "address";
|
|
128
|
+
readonly name: "pool";
|
|
129
|
+
}];
|
|
130
|
+
readonly outputs: readonly [];
|
|
131
|
+
}];
|
|
132
|
+
//# sourceMappingURL=liquidityStrategy.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LIQUIDITY_STRATEGY_ABI = void 0;
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
exports.LIQUIDITY_STRATEGY_ABI = (0, viem_1.parseAbi)([
|
|
6
|
+
'function poolConfigs(address) view returns (bool isToken0Debt, uint32 lastRebalance, uint32 rebalanceCooldown, address protocolFeeRecipient, uint64 liquiditySourceIncentiveExpansion, uint64 protocolIncentiveExpansion, uint64 liquiditySourceIncentiveContraction, uint64 protocolIncentiveContraction)',
|
|
7
|
+
'function determineAction(address pool) view returns ((address pool, (uint256 reserveNum, uint256 reserveDen) reserves, (uint256 oracleNum, uint256 oracleDen, bool poolPriceAbove, uint16 rebalanceThreshold) prices, address token0, address token1, uint64 token0Dec, uint64 token1Dec, bool isToken0Debt, (uint64 liquiditySourceIncentiveExpansion, uint64 protocolIncentiveExpansion, uint64 liquiditySourceIncentiveContraction, uint64 protocolIncentiveContraction) incentives) ctx, (uint8 dir, uint256 amount0Out, uint256 amount1Out, uint256 amountOwedToPool) action)',
|
|
8
|
+
'function rebalance(address pool)',
|
|
9
|
+
]);
|
|
10
|
+
//# sourceMappingURL=liquidityStrategy.js.map
|
|
@@ -44,6 +44,7 @@ exports.addresses = {
|
|
|
44
44
|
FPMMFactory: '0x353ED52bF8482027C0e0b9e3c0e5d96A9F680980',
|
|
45
45
|
Router: '0xcf6cD45210b3ffE3cA28379C4683F1e60D0C2CCd',
|
|
46
46
|
ReserveLiquidityStrategy: '0x734bb3251Ec3f1A83f8f2A8609bcEF649D54EbF8',
|
|
47
|
+
OpenLiquidityStrategy: '0xCCd2aD0603a08EBc14D223a983171ef18192e8c9',
|
|
47
48
|
},
|
|
48
49
|
[chainId_1.ChainId.MONAD]: {},
|
|
49
50
|
[chainId_1.ChainId.CELO_SEPOLIA]: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CallParams } from './transaction';
|
|
2
|
+
import { LiquidityStrategyDirection } from './pool';
|
|
2
3
|
import { RouterRoute } from '../../utils/pathEncoder';
|
|
3
4
|
export interface LiquidityOptions {
|
|
4
5
|
slippageTolerance: number;
|
|
@@ -114,6 +115,39 @@ export interface ZapOutTransaction {
|
|
|
114
115
|
approval: TokenApproval | null;
|
|
115
116
|
zapOut: ZapOutDetails;
|
|
116
117
|
}
|
|
118
|
+
export interface RebalanceDetails {
|
|
119
|
+
params: CallParams;
|
|
120
|
+
poolAddress: string;
|
|
121
|
+
strategyAddress: string;
|
|
122
|
+
inputToken: string;
|
|
123
|
+
outputToken: string;
|
|
124
|
+
amountRequired: bigint;
|
|
125
|
+
expectedAmountTransferred: bigint;
|
|
126
|
+
expectedProtocolIncentive: bigint;
|
|
127
|
+
expectedLiquiditySourceIncentive: bigint;
|
|
128
|
+
approvalToken: string;
|
|
129
|
+
approvalSpender: string;
|
|
130
|
+
approvalAmount: bigint;
|
|
131
|
+
direction: LiquidityStrategyDirection;
|
|
132
|
+
}
|
|
133
|
+
export interface RebalanceTransaction {
|
|
134
|
+
approval: TokenApproval | null;
|
|
135
|
+
rebalance: RebalanceDetails;
|
|
136
|
+
}
|
|
137
|
+
export interface PreparedZapIn {
|
|
138
|
+
routesA: RouterRoute[];
|
|
139
|
+
routesB: RouterRoute[];
|
|
140
|
+
quote: ZapInQuote;
|
|
141
|
+
approval?: TokenApproval | null;
|
|
142
|
+
details: ZapInDetails;
|
|
143
|
+
}
|
|
144
|
+
export interface PreparedZapOut {
|
|
145
|
+
routesA: RouterRoute[];
|
|
146
|
+
routesB: RouterRoute[];
|
|
147
|
+
quote: ZapOutQuote;
|
|
148
|
+
approval?: TokenApproval | null;
|
|
149
|
+
details: ZapOutDetails;
|
|
150
|
+
}
|
|
117
151
|
/** Input for adding liquidity (without approval handling) */
|
|
118
152
|
export interface AddLiquidityInput {
|
|
119
153
|
poolAddress: string;
|
|
@@ -140,6 +174,9 @@ export interface ZapInInput {
|
|
|
140
174
|
recipient: string;
|
|
141
175
|
options: LiquidityOptions;
|
|
142
176
|
}
|
|
177
|
+
export interface PrepareZapInInput extends ZapInInput {
|
|
178
|
+
owner?: string;
|
|
179
|
+
}
|
|
143
180
|
/** Input for zap out (without approval handling) */
|
|
144
181
|
export interface ZapOutInput {
|
|
145
182
|
poolAddress: string;
|
|
@@ -148,4 +185,10 @@ export interface ZapOutInput {
|
|
|
148
185
|
recipient: string;
|
|
149
186
|
options: LiquidityOptions;
|
|
150
187
|
}
|
|
188
|
+
export interface PrepareZapOutInput extends ZapOutInput {
|
|
189
|
+
owner?: string;
|
|
190
|
+
}
|
|
191
|
+
export interface RebalanceInput {
|
|
192
|
+
poolAddress: string;
|
|
193
|
+
}
|
|
151
194
|
//# sourceMappingURL=liquidity.d.ts.map
|
|
@@ -92,9 +92,72 @@ export interface FPMMRebalancing {
|
|
|
92
92
|
rebalanceThresholdBelowPercent: number;
|
|
93
93
|
/** Whether the current price is within rebalancing thresholds (null when pricing unavailable) */
|
|
94
94
|
inBand: boolean | null;
|
|
95
|
-
/** The
|
|
95
|
+
/** The registered Open Liquidity Strategy address for this pool, or null if none */
|
|
96
96
|
liquidityStrategy: string | null;
|
|
97
97
|
}
|
|
98
|
+
export type LiquidityStrategyDirection = 'Expand' | 'Contract';
|
|
99
|
+
export interface LiquidityStrategyRebalanceIncentives {
|
|
100
|
+
liquiditySourceIncentiveExpansion: bigint;
|
|
101
|
+
protocolIncentiveExpansion: bigint;
|
|
102
|
+
liquiditySourceIncentiveContraction: bigint;
|
|
103
|
+
protocolIncentiveContraction: bigint;
|
|
104
|
+
}
|
|
105
|
+
export interface LiquidityStrategyPoolConfig {
|
|
106
|
+
isToken0Debt: boolean;
|
|
107
|
+
lastRebalance: number;
|
|
108
|
+
rebalanceCooldown: number;
|
|
109
|
+
protocolFeeRecipient: string;
|
|
110
|
+
liquiditySourceIncentiveExpansion: bigint;
|
|
111
|
+
protocolIncentiveExpansion: bigint;
|
|
112
|
+
liquiditySourceIncentiveContraction: bigint;
|
|
113
|
+
protocolIncentiveContraction: bigint;
|
|
114
|
+
}
|
|
115
|
+
export interface LiquidityStrategyContext {
|
|
116
|
+
pool: string;
|
|
117
|
+
reserves: {
|
|
118
|
+
reserveNum: bigint;
|
|
119
|
+
reserveDen: bigint;
|
|
120
|
+
};
|
|
121
|
+
prices: {
|
|
122
|
+
oracleNum: bigint;
|
|
123
|
+
oracleDen: bigint;
|
|
124
|
+
poolPriceAbove: boolean;
|
|
125
|
+
rebalanceThreshold: number;
|
|
126
|
+
};
|
|
127
|
+
token0: string;
|
|
128
|
+
token1: string;
|
|
129
|
+
token0Dec: bigint;
|
|
130
|
+
token1Dec: bigint;
|
|
131
|
+
isToken0Debt: boolean;
|
|
132
|
+
incentives: LiquidityStrategyRebalanceIncentives;
|
|
133
|
+
}
|
|
134
|
+
export interface LiquidityStrategyAction {
|
|
135
|
+
dir: LiquidityStrategyDirection;
|
|
136
|
+
amount0Out: bigint;
|
|
137
|
+
amount1Out: bigint;
|
|
138
|
+
amountOwedToPool: bigint;
|
|
139
|
+
}
|
|
140
|
+
export interface PoolRebalanceTokenAmount {
|
|
141
|
+
token: string;
|
|
142
|
+
amount: bigint;
|
|
143
|
+
}
|
|
144
|
+
export interface PoolRebalancePreview {
|
|
145
|
+
poolAddress: string;
|
|
146
|
+
strategyAddress: string;
|
|
147
|
+
direction: LiquidityStrategyDirection;
|
|
148
|
+
config: LiquidityStrategyPoolConfig;
|
|
149
|
+
context: LiquidityStrategyContext;
|
|
150
|
+
action: LiquidityStrategyAction;
|
|
151
|
+
inputToken: string;
|
|
152
|
+
outputToken: string;
|
|
153
|
+
amountRequired: PoolRebalanceTokenAmount;
|
|
154
|
+
amountTransferred: PoolRebalanceTokenAmount;
|
|
155
|
+
protocolIncentive: PoolRebalanceTokenAmount;
|
|
156
|
+
liquiditySourceIncentive: PoolRebalanceTokenAmount;
|
|
157
|
+
approvalToken: string;
|
|
158
|
+
approvalSpender: string;
|
|
159
|
+
approvalAmount: bigint;
|
|
160
|
+
}
|
|
98
161
|
/**
|
|
99
162
|
* Enriched details for an FPMM pool including pricing, fees, and rebalancing state
|
|
100
163
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { parseAbi } from 'viem';
|
|
2
|
+
export const LIQUIDITY_STRATEGY_ABI = parseAbi([
|
|
3
|
+
'function poolConfigs(address) view returns (bool isToken0Debt, uint32 lastRebalance, uint32 rebalanceCooldown, address protocolFeeRecipient, uint64 liquiditySourceIncentiveExpansion, uint64 protocolIncentiveExpansion, uint64 liquiditySourceIncentiveContraction, uint64 protocolIncentiveContraction)',
|
|
4
|
+
'function determineAction(address pool) view returns ((address pool, (uint256 reserveNum, uint256 reserveDen) reserves, (uint256 oracleNum, uint256 oracleDen, bool poolPriceAbove, uint16 rebalanceThreshold) prices, address token0, address token1, uint64 token0Dec, uint64 token1Dec, bool isToken0Debt, (uint64 liquiditySourceIncentiveExpansion, uint64 protocolIncentiveExpansion, uint64 liquiditySourceIncentiveContraction, uint64 protocolIncentiveContraction) incentives) ctx, (uint8 dir, uint256 amount0Out, uint256 amount1Out, uint256 amountOwedToPool) action)',
|
|
5
|
+
'function rebalance(address pool)',
|
|
6
|
+
]);
|
|
@@ -39,6 +39,7 @@ export const addresses = {
|
|
|
39
39
|
FPMMFactory: '0x353ED52bF8482027C0e0b9e3c0e5d96A9F680980',
|
|
40
40
|
Router: '0xcf6cD45210b3ffE3cA28379C4683F1e60D0C2CCd',
|
|
41
41
|
ReserveLiquidityStrategy: '0x734bb3251Ec3f1A83f8f2A8609bcEF649D54EbF8',
|
|
42
|
+
OpenLiquidityStrategy: '0xCCd2aD0603a08EBc14D223a983171ef18192e8c9',
|
|
42
43
|
},
|
|
43
44
|
[ChainId.MONAD]: {},
|
|
44
45
|
[ChainId.CELO_SEPOLIA]: {
|
package/dist/esm/index.js
CHANGED
|
@@ -10,6 +10,14 @@ import { SwapService } from './services/swap';
|
|
|
10
10
|
import { TradingService } from './services/trading';
|
|
11
11
|
import { LiquidityService } from './services/liquidity';
|
|
12
12
|
import { BorrowService } from './services/borrow';
|
|
13
|
+
const DEFAULT_HTTP_BATCH_OPTIONS = {
|
|
14
|
+
batchSize: 1000,
|
|
15
|
+
wait: 8,
|
|
16
|
+
};
|
|
17
|
+
const DEFAULT_MULTICALL_BATCH_OPTIONS = {
|
|
18
|
+
batchSize: 1024,
|
|
19
|
+
wait: 8,
|
|
20
|
+
};
|
|
13
21
|
/**
|
|
14
22
|
* @class Mento
|
|
15
23
|
* @description The main class for the Mento SDK. Initializes a viem PublicClient internally
|
|
@@ -70,14 +78,7 @@ export class Mento {
|
|
|
70
78
|
this.liquidity = liquidity;
|
|
71
79
|
this.borrow = borrow;
|
|
72
80
|
}
|
|
73
|
-
|
|
74
|
-
* Create a new Mento SDK instance
|
|
75
|
-
* @param chainId - The chain ID (e.g., ChainId.CELO, ChainId.CELO_SEPOLIA)
|
|
76
|
-
* @param rpcUrlOrClient - Optional RPC URL string or an existing viem PublicClient.
|
|
77
|
-
* If not provided, uses the default RPC URL for the chain.
|
|
78
|
-
* @returns A new Mento instance
|
|
79
|
-
*/
|
|
80
|
-
static async create(chainId, rpcUrlOrClient) {
|
|
81
|
+
static async create(chainId, rpcUrlOrClient, options) {
|
|
81
82
|
// Validate chainId is supported
|
|
82
83
|
const supportedChainIds = Object.values(ChainId).filter((v) => typeof v === 'number');
|
|
83
84
|
if (!supportedChainIds.includes(chainId)) {
|
|
@@ -89,8 +90,23 @@ export class Mento {
|
|
|
89
90
|
publicClient = rpcUrlOrClient;
|
|
90
91
|
}
|
|
91
92
|
else {
|
|
92
|
-
const transport = http(rpcUrlOrClient || getDefaultRpcUrl(chainId)
|
|
93
|
+
const transport = http(rpcUrlOrClient || getDefaultRpcUrl(chainId), {
|
|
94
|
+
batch: options?.httpBatch === false
|
|
95
|
+
? false
|
|
96
|
+
: {
|
|
97
|
+
...DEFAULT_HTTP_BATCH_OPTIONS,
|
|
98
|
+
...(options?.httpBatch ?? {}),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
93
101
|
publicClient = createPublicClient({
|
|
102
|
+
batch: {
|
|
103
|
+
multicall: options?.multicallBatch === false
|
|
104
|
+
? false
|
|
105
|
+
: {
|
|
106
|
+
...DEFAULT_MULTICALL_BATCH_OPTIONS,
|
|
107
|
+
...(options?.multicallBatch ?? {}),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
94
110
|
chain: getChainConfig(chainId),
|
|
95
111
|
transport,
|
|
96
112
|
});
|
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import { BORROWER_OPERATIONS_ABI, HINT_HELPERS_ABI, MULTI_TROVE_GETTER_ABI, PRICE_FEED_ABI, TROVE_MANAGER_ABI, TROVE_NFT_ABI, } from '../../../core/abis';
|
|
2
2
|
import { COLL_INDEX } from '../../../core/constants';
|
|
3
|
+
import { multicall } from '../../../utils/multicall';
|
|
3
4
|
import { parseBorrowPosition } from './borrowPositionParser';
|
|
4
5
|
import { formatTroveId, MAX_SAFE_INTEGER_BIGINT, parseTroveId, requireAddress, requireNonNegativeBigInt, } from './borrowValidation';
|
|
6
|
+
const TROVE_ID_BATCH_SIZE = 64;
|
|
7
|
+
const TROVE_OWNER_BATCH_SIZE = 64;
|
|
8
|
+
const TROVE_DETAIL_BATCH_SIZE = 64;
|
|
5
9
|
export class BorrowReadService {
|
|
6
10
|
constructor(publicClient) {
|
|
7
11
|
this.publicClient = publicClient;
|
|
8
12
|
}
|
|
9
13
|
async getTroveData(ctx, troveId) {
|
|
10
14
|
const parsedTroveId = parseTroveId(troveId);
|
|
11
|
-
const [latestData, trovesData] = await
|
|
12
|
-
|
|
15
|
+
const [latestData, trovesData] = await this.readContractsInChunks([
|
|
16
|
+
{
|
|
13
17
|
address: ctx.addresses.troveManager,
|
|
14
18
|
abi: TROVE_MANAGER_ABI,
|
|
15
19
|
functionName: 'getLatestTroveData',
|
|
16
20
|
args: [parsedTroveId],
|
|
17
|
-
}
|
|
18
|
-
|
|
21
|
+
},
|
|
22
|
+
{
|
|
19
23
|
address: ctx.addresses.troveManager,
|
|
20
24
|
abi: TROVE_MANAGER_ABI,
|
|
21
25
|
functionName: 'Troves',
|
|
22
26
|
args: [parsedTroveId],
|
|
23
|
-
}
|
|
24
|
-
]);
|
|
27
|
+
},
|
|
28
|
+
], 2);
|
|
25
29
|
return parseBorrowPosition(formatTroveId(parsedTroveId), latestData, trovesData);
|
|
26
30
|
}
|
|
27
31
|
async getUserTroves(ctx, owner) {
|
|
@@ -32,41 +36,49 @@ export class BorrowReadService {
|
|
|
32
36
|
functionName: 'getTroveIdsCount',
|
|
33
37
|
args: [],
|
|
34
38
|
}));
|
|
35
|
-
|
|
39
|
+
if (troveCount === 0n) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const troveIdContracts = [];
|
|
36
43
|
for (let i = 0n; i < troveCount; i++) {
|
|
37
|
-
|
|
44
|
+
troveIdContracts.push({
|
|
38
45
|
address: ctx.addresses.troveManager,
|
|
39
46
|
abi: TROVE_MANAGER_ABI,
|
|
40
47
|
functionName: 'getTroveFromTroveIdsArray',
|
|
41
48
|
args: [i],
|
|
42
|
-
})
|
|
43
|
-
const troveOwner = (await this.publicClient.readContract({
|
|
44
|
-
address: ctx.addresses.troveNFT,
|
|
45
|
-
abi: TROVE_NFT_ABI,
|
|
46
|
-
functionName: 'ownerOf',
|
|
47
|
-
args: [troveId],
|
|
48
|
-
}));
|
|
49
|
-
if (troveOwner.toLowerCase() === ownerAddress.toLowerCase()) {
|
|
50
|
-
matchedTroveIds.push(troveId);
|
|
51
|
-
}
|
|
49
|
+
});
|
|
52
50
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
args: [troveId],
|
|
60
|
-
}),
|
|
61
|
-
this.publicClient.readContract({
|
|
62
|
-
address: ctx.addresses.troveManager,
|
|
63
|
-
abi: TROVE_MANAGER_ABI,
|
|
64
|
-
functionName: 'Troves',
|
|
65
|
-
args: [troveId],
|
|
66
|
-
}),
|
|
67
|
-
]);
|
|
68
|
-
return parseBorrowPosition(formatTroveId(troveId), latestData, trovesData);
|
|
51
|
+
const troveIds = (await this.readContractsInChunks(troveIdContracts, TROVE_ID_BATCH_SIZE)).map((troveId) => troveId);
|
|
52
|
+
const ownerContracts = troveIds.map((troveId) => ({
|
|
53
|
+
address: ctx.addresses.troveNFT,
|
|
54
|
+
abi: TROVE_NFT_ABI,
|
|
55
|
+
functionName: 'ownerOf',
|
|
56
|
+
args: [troveId],
|
|
69
57
|
}));
|
|
58
|
+
const troveOwners = await this.readContractsInChunks(ownerContracts, TROVE_OWNER_BATCH_SIZE);
|
|
59
|
+
const matchedTroveIds = troveIds.filter((troveId, index) => troveOwners[index].toLowerCase() === ownerAddress.toLowerCase());
|
|
60
|
+
if (matchedTroveIds.length === 0) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const troveDetailContracts = matchedTroveIds.flatMap((troveId) => ([
|
|
64
|
+
{
|
|
65
|
+
address: ctx.addresses.troveManager,
|
|
66
|
+
abi: TROVE_MANAGER_ABI,
|
|
67
|
+
functionName: 'getLatestTroveData',
|
|
68
|
+
args: [troveId],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
address: ctx.addresses.troveManager,
|
|
72
|
+
abi: TROVE_MANAGER_ABI,
|
|
73
|
+
functionName: 'Troves',
|
|
74
|
+
args: [troveId],
|
|
75
|
+
},
|
|
76
|
+
]));
|
|
77
|
+
const detailResults = await this.readContractsInChunks(troveDetailContracts, TROVE_DETAIL_BATCH_SIZE * 2);
|
|
78
|
+
return matchedTroveIds.map((troveId, index) => {
|
|
79
|
+
const offset = index * 2;
|
|
80
|
+
return parseBorrowPosition(formatTroveId(troveId), detailResults[offset], detailResults[offset + 1]);
|
|
81
|
+
});
|
|
70
82
|
}
|
|
71
83
|
async getCollateralPrice(ctx) {
|
|
72
84
|
return (await this.publicClient.readContract({
|
|
@@ -210,4 +222,21 @@ export class BorrowReadService {
|
|
|
210
222
|
}
|
|
211
223
|
return Number(ownerTroveCount);
|
|
212
224
|
}
|
|
225
|
+
async readContractsInChunks(contracts, chunkSize) {
|
|
226
|
+
if (contracts.length === 0) {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
const results = [];
|
|
230
|
+
for (let index = 0; index < contracts.length; index += chunkSize) {
|
|
231
|
+
const chunk = contracts.slice(index, index + chunkSize);
|
|
232
|
+
const chunkResults = await multicall(this.publicClient, chunk, { allowFailure: false });
|
|
233
|
+
for (const result of chunkResults) {
|
|
234
|
+
if (result.status === 'failure') {
|
|
235
|
+
throw result.error;
|
|
236
|
+
}
|
|
237
|
+
results.push(result.result);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return results;
|
|
241
|
+
}
|
|
213
242
|
}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import { ADDRESSES_REGISTRY_ABI, BORROWER_OPERATIONS_ABI, SYSTEM_PARAMS_ABI, } from '../../../core/abis';
|
|
2
|
+
import { multicall } from '../../../utils/multicall';
|
|
2
3
|
import { validateAddress } from '../../../utils/validation';
|
|
3
4
|
function readNoArgsContract(publicClient, address, abi, functionName) {
|
|
4
5
|
const readContract = publicClient.readContract;
|
|
5
6
|
return readContract({ address, abi, functionName, args: [] });
|
|
6
7
|
}
|
|
8
|
+
async function readNoArgsContracts(publicClient, contracts) {
|
|
9
|
+
if (contracts.length === 0) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const results = await multicall(publicClient, contracts.map((contract) => ({
|
|
13
|
+
...contract,
|
|
14
|
+
abi: contract.abi,
|
|
15
|
+
args: [],
|
|
16
|
+
})), { allowFailure: false });
|
|
17
|
+
return results.map((result) => {
|
|
18
|
+
if (result.status === 'failure') {
|
|
19
|
+
throw result.error;
|
|
20
|
+
}
|
|
21
|
+
return result.result;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
7
24
|
function requireAddress(value, fieldName) {
|
|
8
25
|
if (typeof value !== 'string') {
|
|
9
26
|
throw new Error(`${fieldName} must be a string address`);
|
|
@@ -23,26 +40,26 @@ function requireBigInt(value, fieldName) {
|
|
|
23
40
|
export async function resolveAddressesFromRegistry(publicClient, registryAddress) {
|
|
24
41
|
validateAddress(registryAddress, 'registryAddress');
|
|
25
42
|
const registry = registryAddress;
|
|
26
|
-
const [borrowerOperationsRaw, troveManagerRaw, sortedTrovesRaw, activePoolRaw, defaultPoolRaw, hintHelpersRaw, multiTroveGetterRaw, collTokenRaw, debtTokenRaw, troveNFTRaw, metadataNFTRaw, stabilityPoolRaw, priceFeedRaw, collSurplusPoolRaw, interestRouterRaw, collateralRegistryRaw, gasTokenRaw, gasPoolAddressRaw, liquidityStrategyRaw,] = await
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const [borrowerOperationsRaw, troveManagerRaw, sortedTrovesRaw, activePoolRaw, defaultPoolRaw, hintHelpersRaw, multiTroveGetterRaw, collTokenRaw, debtTokenRaw, troveNFTRaw, metadataNFTRaw, stabilityPoolRaw, priceFeedRaw, collSurplusPoolRaw, interestRouterRaw, collateralRegistryRaw, gasTokenRaw, gasPoolAddressRaw, liquidityStrategyRaw,] = await readNoArgsContracts(publicClient, [
|
|
44
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'borrowerOperations' },
|
|
45
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'troveManager' },
|
|
46
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'sortedTroves' },
|
|
47
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'activePool' },
|
|
48
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'defaultPool' },
|
|
49
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'hintHelpers' },
|
|
50
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'multiTroveGetter' },
|
|
51
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'collToken' },
|
|
52
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'boldToken' },
|
|
53
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'troveNFT' },
|
|
54
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'metadataNFT' },
|
|
55
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'stabilityPool' },
|
|
56
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'priceFeed' },
|
|
57
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'collSurplusPool' },
|
|
58
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'interestRouter' },
|
|
59
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'collateralRegistry' },
|
|
60
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'gasToken' },
|
|
61
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'gasPoolAddress' },
|
|
62
|
+
{ address: registry, abi: ADDRESSES_REGISTRY_ABI, functionName: 'liquidityStrategy' },
|
|
46
63
|
]);
|
|
47
64
|
return {
|
|
48
65
|
borrowerOperations: requireAddress(borrowerOperationsRaw, 'borrowerOperations'),
|
|
@@ -70,14 +87,14 @@ export async function readSystemParams(publicClient, borrowerOperations) {
|
|
|
70
87
|
validateAddress(borrowerOperations, 'borrowerOperations');
|
|
71
88
|
const systemParamsAddressRaw = await readNoArgsContract(publicClient, borrowerOperations, BORROWER_OPERATIONS_ABI, 'systemParams');
|
|
72
89
|
const systemParamsAddress = requireAddress(systemParamsAddressRaw, 'systemParamsAddress');
|
|
73
|
-
const [ccrRaw, mcrRaw, scrRaw, bcrRaw, minDebtRaw, ethGasCompensationRaw, minAnnualInterestRateRaw,] = await
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
const [ccrRaw, mcrRaw, scrRaw, bcrRaw, minDebtRaw, ethGasCompensationRaw, minAnnualInterestRateRaw,] = await readNoArgsContracts(publicClient, [
|
|
91
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'CCR' },
|
|
92
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'MCR' },
|
|
93
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'SCR' },
|
|
94
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'BCR' },
|
|
95
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'MIN_DEBT' },
|
|
96
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'ETH_GAS_COMPENSATION' },
|
|
97
|
+
{ address: systemParamsAddress, abi: SYSTEM_PARAMS_ABI, functionName: 'MIN_ANNUAL_INTEREST_RATE' },
|
|
81
98
|
]);
|
|
82
99
|
return {
|
|
83
100
|
mcr: requireBigInt(mcrRaw, 'MCR'),
|