@moonwell-fi/moonwell-sdk 0.23.0 → 0.25.0
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/CHANGELOG.md +36 -0
- package/_cjs/actions/axiosWithRetry.js +10 -11
- package/_cjs/actions/axiosWithRetry.js.map +1 -1
- package/_cjs/actions/core/getUserBalances.js +63 -32
- package/_cjs/actions/core/getUserBalances.js.map +1 -1
- package/_cjs/actions/core/markets/common.js +31 -42
- package/_cjs/actions/core/markets/common.js.map +1 -1
- package/_cjs/actions/core/markets/getMarkets.js +7 -3
- package/_cjs/actions/core/markets/getMarkets.js.map +1 -1
- package/_cjs/actions/core/user-positions/common.js +56 -60
- package/_cjs/actions/core/user-positions/common.js.map +1 -1
- package/_cjs/actions/core/user-positions/getUserPositions.js +9 -6
- package/_cjs/actions/core/user-positions/getUserPositions.js.map +1 -1
- package/_cjs/actions/governance/getStakingInfo.js +1 -7
- package/_cjs/actions/governance/getStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getUserStakingInfo.js +1 -7
- package/_cjs/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_cjs/actions/governance/getWellPrice.js +51 -1
- package/_cjs/actions/governance/getWellPrice.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +34 -15
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js +5 -4
- package/_cjs/actions/governance/proposals/getProposals.js.map +1 -1
- package/_cjs/actions/index.js +3 -1
- package/_cjs/actions/index.js.map +1 -1
- package/_cjs/actions/morpho/markets/common.js +155 -26
- package/_cjs/actions/morpho/markets/common.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarket.js +1 -0
- package/_cjs/actions/morpho/markets/getMorphoMarket.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarkets.js +1 -0
- package/_cjs/actions/morpho/markets/getMorphoMarkets.js.map +1 -1
- package/_cjs/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js +46 -0
- package/_cjs/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js.map +1 -0
- package/_cjs/actions/morpho/user-positions/common.js +26 -24
- package/_cjs/actions/morpho/user-positions/common.js.map +1 -1
- package/_cjs/actions/morpho/user-positions/getMorphoMarketUserPositions.js +7 -8
- package/_cjs/actions/morpho/user-positions/getMorphoMarketUserPositions.js.map +1 -1
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositions.js +7 -8
- package/_cjs/actions/morpho/user-positions/getMorphoVaultUserPositions.js.map +1 -1
- package/_cjs/actions/morpho/user-rewards/common.js +1 -7
- package/_cjs/actions/morpho/user-rewards/common.js.map +1 -1
- package/_cjs/actions/morpho/vaults/common.js +104 -87
- package/_cjs/actions/morpho/vaults/common.js.map +1 -1
- package/_cjs/actions/morpho/vaults/lunarIndexerTransform.js +31 -3
- package/_cjs/actions/morpho/vaults/lunarIndexerTransform.js.map +1 -1
- package/_cjs/actions/retry.js +43 -13
- package/_cjs/actions/retry.js.map +1 -1
- package/_cjs/client/createActions.js +2 -0
- package/_cjs/client/createActions.js.map +1 -1
- package/_cjs/common/error.js +37 -1
- package/_cjs/common/error.js.map +1 -1
- package/_cjs/common/index.js +2 -1
- package/_cjs/common/index.js.map +1 -1
- package/_cjs/common/readAcrossEnvironments.js +17 -0
- package/_cjs/common/readAcrossEnvironments.js.map +1 -0
- package/_cjs/environments/types/config.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +3 -1
- package/_cjs/index.js.map +1 -1
- package/_esm/actions/axiosWithRetry.js +11 -13
- package/_esm/actions/axiosWithRetry.js.map +1 -1
- package/_esm/actions/core/getUserBalances.js +72 -35
- package/_esm/actions/core/getUserBalances.js.map +1 -1
- package/_esm/actions/core/markets/common.js +36 -43
- package/_esm/actions/core/markets/common.js.map +1 -1
- package/_esm/actions/core/markets/getMarkets.js +7 -3
- package/_esm/actions/core/markets/getMarkets.js.map +1 -1
- package/_esm/actions/core/user-positions/common.js +65 -63
- package/_esm/actions/core/user-positions/common.js.map +1 -1
- package/_esm/actions/core/user-positions/getUserPositions.js +14 -6
- package/_esm/actions/core/user-positions/getUserPositions.js.map +1 -1
- package/_esm/actions/governance/getStakingInfo.js +2 -8
- package/_esm/actions/governance/getStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getUserStakingInfo.js +2 -8
- package/_esm/actions/governance/getUserStakingInfo.js.map +1 -1
- package/_esm/actions/governance/getWellPrice.js +67 -7
- package/_esm/actions/governance/getWellPrice.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +37 -12
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposals.js +7 -5
- package/_esm/actions/governance/proposals/getProposals.js.map +1 -1
- package/_esm/actions/index.js +1 -0
- package/_esm/actions/index.js.map +1 -1
- package/_esm/actions/morpho/markets/common.js +168 -27
- package/_esm/actions/morpho/markets/common.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarket.js +1 -0
- package/_esm/actions/morpho/markets/getMorphoMarket.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarkets.js +1 -0
- package/_esm/actions/morpho/markets/getMorphoMarkets.js.map +1 -1
- package/_esm/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js +48 -0
- package/_esm/actions/morpho/markets/getMorphoMarketsSharedLiquidity.js.map +1 -0
- package/_esm/actions/morpho/user-positions/common.js +31 -24
- package/_esm/actions/morpho/user-positions/common.js.map +1 -1
- package/_esm/actions/morpho/user-positions/getMorphoMarketUserPositions.js +12 -8
- package/_esm/actions/morpho/user-positions/getMorphoMarketUserPositions.js.map +1 -1
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositions.js +12 -8
- package/_esm/actions/morpho/user-positions/getMorphoVaultUserPositions.js.map +1 -1
- package/_esm/actions/morpho/user-rewards/common.js +2 -8
- package/_esm/actions/morpho/user-rewards/common.js.map +1 -1
- package/_esm/actions/morpho/vaults/common.js +110 -91
- package/_esm/actions/morpho/vaults/common.js.map +1 -1
- package/_esm/actions/morpho/vaults/lunarIndexerTransform.js +36 -4
- package/_esm/actions/morpho/vaults/lunarIndexerTransform.js.map +1 -1
- package/_esm/actions/retry.js +45 -15
- package/_esm/actions/retry.js.map +1 -1
- package/_esm/client/createActions.js +2 -0
- package/_esm/client/createActions.js.map +1 -1
- package/_esm/common/error.js +49 -0
- package/_esm/common/error.js.map +1 -1
- package/_esm/common/index.js +1 -1
- package/_esm/common/index.js.map +1 -1
- package/_esm/common/readAcrossEnvironments.js +30 -0
- package/_esm/common/readAcrossEnvironments.js.map +1 -0
- package/_esm/environments/types/config.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +1 -0
- package/_esm/index.js.map +1 -1
- package/_types/actions/axiosWithRetry.d.ts +1 -0
- package/_types/actions/axiosWithRetry.d.ts.map +1 -1
- package/_types/actions/core/getUserBalances.d.ts.map +1 -1
- package/_types/actions/core/markets/common.d.ts.map +1 -1
- package/_types/actions/core/markets/getMarkets.d.ts.map +1 -1
- package/_types/actions/core/user-positions/common.d.ts.map +1 -1
- package/_types/actions/core/user-positions/getUserPositions.d.ts +5 -0
- package/_types/actions/core/user-positions/getUserPositions.d.ts.map +1 -1
- package/_types/actions/governance/getStakingInfo.d.ts.map +1 -1
- package/_types/actions/governance/getUserStakingInfo.d.ts.map +1 -1
- package/_types/actions/governance/getWellPrice.d.ts +9 -1
- package/_types/actions/governance/getWellPrice.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts +10 -1
- package/_types/actions/governance/proposals/getProposals.d.ts.map +1 -1
- package/_types/actions/index.d.ts +1 -0
- package/_types/actions/index.d.ts.map +1 -1
- package/_types/actions/morpho/markets/common.d.ts +7 -10
- package/_types/actions/morpho/markets/common.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarket.d.ts +2 -0
- package/_types/actions/morpho/markets/getMorphoMarket.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarkets.d.ts +2 -0
- package/_types/actions/morpho/markets/getMorphoMarkets.d.ts.map +1 -1
- package/_types/actions/morpho/markets/getMorphoMarketsSharedLiquidity.d.ts +17 -0
- package/_types/actions/morpho/markets/getMorphoMarketsSharedLiquidity.d.ts.map +1 -0
- package/_types/actions/morpho/user-positions/common.d.ts.map +1 -1
- package/_types/actions/morpho/user-positions/getMorphoMarketUserPositions.d.ts +5 -0
- package/_types/actions/morpho/user-positions/getMorphoMarketUserPositions.d.ts.map +1 -1
- package/_types/actions/morpho/user-positions/getMorphoVaultUserPositions.d.ts +5 -0
- package/_types/actions/morpho/user-positions/getMorphoVaultUserPositions.d.ts.map +1 -1
- package/_types/actions/morpho/user-rewards/common.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/lunarIndexerTransform.d.ts.map +1 -1
- package/_types/actions/retry.d.ts +5 -4
- package/_types/actions/retry.d.ts.map +1 -1
- package/_types/client/createActions.d.ts +2 -0
- package/_types/client/createActions.d.ts.map +1 -1
- package/_types/common/error.d.ts +31 -0
- package/_types/common/error.d.ts.map +1 -1
- package/_types/common/index.d.ts +2 -2
- package/_types/common/index.d.ts.map +1 -1
- package/_types/common/readAcrossEnvironments.d.ts +23 -0
- package/_types/common/readAcrossEnvironments.d.ts.map +1 -0
- package/_types/environments/types/config.d.ts +11 -1
- package/_types/environments/types/config.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +3 -1
- package/_types/index.d.ts.map +1 -1
- package/_types/types/morphoMarket.d.ts +9 -0
- package/_types/types/morphoMarket.d.ts.map +1 -1
- package/actions/axiosWithRetry.ts +19 -13
- package/actions/core/getUserBalances.ts +98 -51
- package/actions/core/markets/common.ts +49 -51
- package/actions/core/markets/getMarkets.ts +9 -5
- package/actions/core/user-positions/common.ts +107 -111
- package/actions/core/user-positions/getUserPositions.ts +11 -10
- package/actions/governance/getStakingInfo.ts +2 -9
- package/actions/governance/getUserStakingInfo.ts +2 -8
- package/actions/governance/getWellPrice.ts +99 -7
- package/actions/governance/proposals/common.ts +44 -19
- package/actions/governance/proposals/getProposals.ts +22 -5
- package/actions/index.ts +5 -0
- package/actions/morpho/markets/common.ts +324 -125
- package/actions/morpho/markets/getMorphoMarket.ts +3 -0
- package/actions/morpho/markets/getMorphoMarkets.ts +3 -0
- package/actions/morpho/markets/getMorphoMarketsSharedLiquidity.ts +93 -0
- package/actions/morpho/user-positions/common.ts +48 -42
- package/actions/morpho/user-positions/getMorphoMarketUserPositions.ts +14 -15
- package/actions/morpho/user-positions/getMorphoVaultUserPositions.ts +14 -15
- package/actions/morpho/user-rewards/common.ts +2 -8
- package/actions/morpho/vaults/common.ts +161 -127
- package/actions/morpho/vaults/lunarIndexerTransform.ts +41 -6
- package/actions/retry.ts +53 -18
- package/client/createActions.ts +13 -0
- package/common/error.ts +45 -0
- package/common/index.ts +2 -2
- package/common/readAcrossEnvironments.ts +45 -0
- package/environments/types/config.ts +11 -1
- package/errors/version.ts +1 -1
- package/index.ts +3 -0
- package/package.json +1 -1
- package/types/morphoMarket.ts +10 -0
|
@@ -4,6 +4,7 @@ import type { MultichainReturnType } from "../../../common/types.js";
|
|
|
4
4
|
import type { Environment } from "../../../environments/index.js";
|
|
5
5
|
import type {
|
|
6
6
|
MorphoMarket,
|
|
7
|
+
MorphoMarketSharedLiquidity,
|
|
7
8
|
PublicAllocatorSharedLiquidityType,
|
|
8
9
|
} from "../../../types/morphoMarket.js";
|
|
9
10
|
import type { MorphoReward } from "../../../types/morphoReward.js";
|
|
@@ -45,14 +46,164 @@ export interface LunarSharedLiquidityResponse {
|
|
|
45
46
|
markets: Record<string, LunarMarketLiveData>;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
function parseLiquidityQuantity(
|
|
50
|
+
value: unknown,
|
|
51
|
+
field: string,
|
|
52
|
+
raw = false,
|
|
53
|
+
): number {
|
|
54
|
+
// Raw uint quantities routinely exceed Number.MAX_SAFE_INTEGER. Validate the
|
|
55
|
+
// integer string, not its safe-integer range; keep the existing numeric units.
|
|
56
|
+
const pattern = raw ? /^\d+$/ : /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
57
|
+
if (typeof value !== "string" || !pattern.test(value)) {
|
|
58
|
+
throw new TypeError(`Invalid shared-liquidity quantity: ${field}`);
|
|
59
|
+
}
|
|
60
|
+
const quantity = Number(value);
|
|
61
|
+
if (!Number.isFinite(quantity)) {
|
|
62
|
+
throw new TypeError(`Invalid shared-liquidity quantity: ${field}`);
|
|
63
|
+
}
|
|
64
|
+
return quantity;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function validateLoanDecimals(value: unknown): number {
|
|
68
|
+
if (
|
|
69
|
+
typeof value !== "number" ||
|
|
70
|
+
!Number.isInteger(value) ||
|
|
71
|
+
value < 0 ||
|
|
72
|
+
value > 255
|
|
73
|
+
) {
|
|
74
|
+
throw new TypeError("Invalid shared-liquidity loan token decimals");
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Summarizes an unexpected top-level body so the error says what arrived. */
|
|
80
|
+
function describeSharedLiquidityBody(data: unknown): string {
|
|
81
|
+
if (data === null || data === undefined) return `received ${data}`;
|
|
82
|
+
if (typeof data === "string") {
|
|
83
|
+
return `received string of ${data.length} chars: ${JSON.stringify(data.slice(0, 100))}`;
|
|
84
|
+
}
|
|
85
|
+
if (typeof data !== "object") return `received ${typeof data}`;
|
|
86
|
+
if (Array.isArray(data)) return `received array of ${data.length}`;
|
|
87
|
+
const body = data as Record<string, unknown>;
|
|
88
|
+
const kind = (value: unknown): string =>
|
|
89
|
+
Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
90
|
+
const keys = Object.keys(body).slice(0, 10).join(", ");
|
|
91
|
+
return `received object with keys [${keys}]; vaults: ${kind(body.vaults)}, markets: ${kind(body.markets)}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function validatedMarketLiquidity(
|
|
95
|
+
data: LunarSharedLiquidityResponse,
|
|
96
|
+
): Map<string, number> {
|
|
97
|
+
if (
|
|
98
|
+
!data ||
|
|
99
|
+
!Array.isArray(data.vaults) ||
|
|
100
|
+
!data.markets ||
|
|
101
|
+
typeof data.markets !== "object" ||
|
|
102
|
+
Array.isArray(data.markets)
|
|
103
|
+
) {
|
|
104
|
+
throw new TypeError(
|
|
105
|
+
`Invalid shared-liquidity response (${describeSharedLiquidityBody(data)})`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
for (const vault of data.vaults) {
|
|
109
|
+
parseLiquidityQuantity(vault.fee, "vault.fee", true);
|
|
110
|
+
for (const market of vault.markets) {
|
|
111
|
+
for (const field of [
|
|
112
|
+
"flowCapIn",
|
|
113
|
+
"flowCapOut",
|
|
114
|
+
"supplyCap",
|
|
115
|
+
"vaultSupplyShares",
|
|
116
|
+
"vaultSupplyAssets",
|
|
117
|
+
] as const) {
|
|
118
|
+
parseLiquidityQuantity(
|
|
119
|
+
market[field],
|
|
120
|
+
`${market.marketId}.${field}`,
|
|
121
|
+
true,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (typeof market.supplyCapEnabled !== "boolean") {
|
|
125
|
+
throw new TypeError("Invalid shared-liquidity supplyCapEnabled");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return new Map(
|
|
130
|
+
Object.entries(data.markets).map(([marketId, market]) => {
|
|
131
|
+
if (market.loanToken !== undefined) {
|
|
132
|
+
validateLoanDecimals(market.loanToken.decimals);
|
|
133
|
+
}
|
|
134
|
+
for (const field of ["totalSupplyAssets", "totalBorrowAssets"] as const) {
|
|
135
|
+
if (market[field] !== undefined) {
|
|
136
|
+
parseLiquidityQuantity(market[field], `${marketId}.${field}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const liquidity =
|
|
140
|
+
market.totalLiquidity !== undefined
|
|
141
|
+
? parseLiquidityQuantity(
|
|
142
|
+
market.totalLiquidity,
|
|
143
|
+
`${marketId}.totalLiquidity`,
|
|
144
|
+
)
|
|
145
|
+
: parseLiquidityQuantity(
|
|
146
|
+
market.totalSupplyAssets,
|
|
147
|
+
`${marketId}.totalSupplyAssets`,
|
|
148
|
+
) -
|
|
149
|
+
parseLiquidityQuantity(
|
|
150
|
+
market.totalBorrowAssets,
|
|
151
|
+
`${marketId}.totalBorrowAssets`,
|
|
152
|
+
);
|
|
153
|
+
if (liquidity < 0) {
|
|
154
|
+
throw new TypeError(`Negative shared liquidity for ${marketId}`);
|
|
155
|
+
}
|
|
156
|
+
return [marketId, liquidity];
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function fetchSharedLiquidityFromLunar(
|
|
49
162
|
lunarIndexerUrl: string,
|
|
50
163
|
chainId: number,
|
|
164
|
+
options: { signal?: AbortSignal; timeoutMs?: number } = {},
|
|
51
165
|
): Promise<LunarSharedLiquidityResponse> {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
166
|
+
// One budget for the request AND its retries. The endpoint often takes more
|
|
167
|
+
// than five seconds, so let it finish instead of restarting the same work.
|
|
168
|
+
const timeoutMs = options.timeoutMs ?? 15_000;
|
|
169
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
170
|
+
throw new RangeError(
|
|
171
|
+
"Shared-liquidity timeoutMs must be positive and finite",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
const abort = (): void => controller.abort();
|
|
176
|
+
if (options.signal?.aborted) abort();
|
|
177
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
178
|
+
let timedOut = false;
|
|
179
|
+
const timer = setTimeout(() => {
|
|
180
|
+
timedOut = true;
|
|
181
|
+
abort();
|
|
182
|
+
}, timeoutMs);
|
|
183
|
+
try {
|
|
184
|
+
const response = await getWithRetry<LunarSharedLiquidityResponse>(
|
|
185
|
+
`${lunarIndexerUrl}/api/v1/isolated/shared-liquidity/${chainId}`,
|
|
186
|
+
{ timeout: timeoutMs, signal: controller.signal },
|
|
187
|
+
);
|
|
188
|
+
return response.data;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// Our own deadline aborts the request, which axios reports as a bare
|
|
191
|
+
// `CanceledError: canceled` (Sentry MOONWELL-FRONTEND-1C7 & co). That is a
|
|
192
|
+
// timeout, not a cancellation: surface it as one. A caller's own abort
|
|
193
|
+
// still propagates as the CanceledError it is.
|
|
194
|
+
if (timedOut && !options.signal?.aborted) {
|
|
195
|
+
const timeoutError = new Error(
|
|
196
|
+
`Shared-liquidity request timed out after ${timeoutMs}ms (chainId=${chainId})`,
|
|
197
|
+
{ cause: error },
|
|
198
|
+
);
|
|
199
|
+
timeoutError.name = "TimeoutError";
|
|
200
|
+
throw timeoutError;
|
|
201
|
+
}
|
|
202
|
+
throw error;
|
|
203
|
+
} finally {
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
options.signal?.removeEventListener("abort", abort);
|
|
206
|
+
}
|
|
56
207
|
}
|
|
57
208
|
|
|
58
209
|
export function computeSharedLiquidityFromLunar(
|
|
@@ -69,7 +220,9 @@ export function computeSharedLiquidityFromLunar(
|
|
|
69
220
|
}
|
|
70
221
|
>,
|
|
71
222
|
chainId: number,
|
|
72
|
-
):
|
|
223
|
+
): MorphoMarketSharedLiquidity[] {
|
|
224
|
+
// Validate the complete response before building any successful allocations.
|
|
225
|
+
const liquidityByMarket = validatedMarketLiquidity(data);
|
|
73
226
|
return targetMarkets.map((targetMarket) => {
|
|
74
227
|
const targetId = targetMarket.toLowerCase();
|
|
75
228
|
const r: PublicAllocatorSharedLiquidityType[] = [];
|
|
@@ -83,10 +236,11 @@ export function computeSharedLiquidityFromLunar(
|
|
|
83
236
|
// (wei-like). Markets data (totalSupplyAssets, totalBorrowAssets, totalLiquidity)
|
|
84
237
|
// is already in token units (divided by decimals). We convert vault raw values
|
|
85
238
|
// to token units using the loan token decimals before comparing.
|
|
86
|
-
const targetLoanDecimals =
|
|
239
|
+
const targetLoanDecimals = validateLoanDecimals(
|
|
87
240
|
targetLiveData?.loanToken?.decimals ??
|
|
88
|
-
|
|
89
|
-
|
|
241
|
+
targetParams?.loanToken.decimals ??
|
|
242
|
+
18,
|
|
243
|
+
);
|
|
90
244
|
const targetScale = 10 ** targetLoanDecimals;
|
|
91
245
|
|
|
92
246
|
for (const vault of data.vaults) {
|
|
@@ -135,25 +289,25 @@ export function computeSharedLiquidityFromLunar(
|
|
|
135
289
|
|
|
136
290
|
const sourceLiveData =
|
|
137
291
|
data.markets[sourceMarket.marketId.toLowerCase()];
|
|
138
|
-
|
|
292
|
+
const liquidity = liquidityByMarket.get(
|
|
293
|
+
sourceMarket.marketId.toLowerCase(),
|
|
294
|
+
);
|
|
295
|
+
// The indexer can omit an entire source record. Preserve that existing
|
|
296
|
+
// skip behavior; quantities in every returned record were validated above.
|
|
297
|
+
if (!sourceLiveData || liquidity === undefined) continue;
|
|
139
298
|
|
|
140
|
-
const sourceLoanDecimals =
|
|
299
|
+
const sourceLoanDecimals = validateLoanDecimals(
|
|
141
300
|
sourceLiveData.loanToken?.decimals ??
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
301
|
+
marketParamsMap.get(sourceMarket.marketId.toLowerCase())?.loanToken
|
|
302
|
+
.decimals ??
|
|
303
|
+
18,
|
|
304
|
+
);
|
|
145
305
|
const sourceScale = 10 ** sourceLoanDecimals;
|
|
146
306
|
|
|
147
307
|
const vaultSupplyInSource =
|
|
148
308
|
Number(sourceMarket.vaultSupplyAssets) / sourceScale;
|
|
149
309
|
const maxOut = Number(sourceMarket.flowCapOut) / sourceScale;
|
|
150
310
|
|
|
151
|
-
// Use pre-computed totalLiquidity if available, else derive from supply/borrow
|
|
152
|
-
const liquidity = sourceLiveData.totalLiquidity
|
|
153
|
-
? Number(sourceLiveData.totalLiquidity)
|
|
154
|
-
: Number(sourceLiveData.totalSupplyAssets ?? 0) -
|
|
155
|
-
Number(sourceLiveData.totalBorrowAssets ?? 0);
|
|
156
|
-
|
|
157
311
|
if (vaultSupplyInSource > 0 && maxOut > 0 && liquidity > 0) {
|
|
158
312
|
const sourceParams = marketParamsMap.get(
|
|
159
313
|
sourceMarket.marketId.toLowerCase(),
|
|
@@ -219,6 +373,7 @@ export async function getMorphoMarketsData(params: {
|
|
|
219
373
|
environments: Environment[];
|
|
220
374
|
markets?: string[] | undefined;
|
|
221
375
|
includeRewards?: boolean | undefined;
|
|
376
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
222
377
|
}): Promise<MorphoMarket[]> {
|
|
223
378
|
const { environments } = params;
|
|
224
379
|
|
|
@@ -240,6 +395,7 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
240
395
|
environments: Environment[];
|
|
241
396
|
markets?: string[] | undefined;
|
|
242
397
|
includeRewards?: boolean | undefined;
|
|
398
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
243
399
|
}): Promise<MorphoMarket[]> {
|
|
244
400
|
const { environments } = params;
|
|
245
401
|
|
|
@@ -281,7 +437,11 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
281
437
|
: [],
|
|
282
438
|
);
|
|
283
439
|
|
|
284
|
-
const initialMarkets:
|
|
440
|
+
const initialMarkets: {
|
|
441
|
+
chainId: number;
|
|
442
|
+
marketId: string;
|
|
443
|
+
marketKey: string;
|
|
444
|
+
}[] = [];
|
|
285
445
|
fulfilledMarketsInfo.forEach(({ environment, marketsInfo }) => {
|
|
286
446
|
marketsInfo.forEach((marketInfo) => {
|
|
287
447
|
const marketKey = Object.keys(environment.config.morphoMarkets).find(
|
|
@@ -298,7 +458,7 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
298
458
|
chainId: environment.chainId,
|
|
299
459
|
marketId: marketInfo.marketId,
|
|
300
460
|
marketKey,
|
|
301
|
-
}
|
|
461
|
+
});
|
|
302
462
|
});
|
|
303
463
|
});
|
|
304
464
|
|
|
@@ -308,6 +468,7 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
308
468
|
const rewardsData = await getMorphoMarketRewards(
|
|
309
469
|
rewardEnvironment,
|
|
310
470
|
initialMarkets,
|
|
471
|
+
params,
|
|
311
472
|
);
|
|
312
473
|
const rewardsDataByChainAndMarket = new Map<
|
|
313
474
|
string,
|
|
@@ -493,6 +654,10 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
493
654
|
rewards: [],
|
|
494
655
|
publicAllocatorSharedLiquidity:
|
|
495
656
|
marketRewardData?.publicAllocatorSharedLiquidity ?? [],
|
|
657
|
+
sharedLiquidityStatus:
|
|
658
|
+
params.includeSharedLiquidity === false
|
|
659
|
+
? "not-requested"
|
|
660
|
+
: (marketRewardData?.sharedLiquidityStatus ?? "unavailable"),
|
|
496
661
|
};
|
|
497
662
|
|
|
498
663
|
return [mapping];
|
|
@@ -516,17 +681,11 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
516
681
|
return environment?.custom.morpho?.minimalDeployment === false;
|
|
517
682
|
});
|
|
518
683
|
|
|
519
|
-
const rewards = await getMorphoMarketRewards(
|
|
520
|
-
params.environments.find((env) => env.custom?.morpho?.apiUrl) ??
|
|
521
|
-
params.environments[0],
|
|
522
|
-
markets,
|
|
523
|
-
);
|
|
524
|
-
|
|
525
684
|
markets.forEach((market) => {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
685
|
+
// Collateral, rewards and optional liquidity came from the same GraphQL
|
|
686
|
+
// response above. Do not repeat that expensive enrichment request.
|
|
687
|
+
const marketReward = rewardsDataByChainAndMarket.get(
|
|
688
|
+
`${market.chainId}-${market.marketId.toLowerCase()}`,
|
|
530
689
|
);
|
|
531
690
|
if (marketReward) {
|
|
532
691
|
market.rewards = marketReward.rewards;
|
|
@@ -556,13 +715,6 @@ async function getMorphoMarketsDataFromOnChain(params: {
|
|
|
556
715
|
});
|
|
557
716
|
}
|
|
558
717
|
|
|
559
|
-
type GetMorphoMarketsPublicAllocatorSharedLiquidityReturnType = {
|
|
560
|
-
chainId: number;
|
|
561
|
-
marketId: string;
|
|
562
|
-
reallocatableLiquidityAssets: Amount;
|
|
563
|
-
publicAllocatorSharedLiquidity: PublicAllocatorSharedLiquidityType[];
|
|
564
|
-
};
|
|
565
|
-
|
|
566
718
|
type GetMorphoMarketsRewardsReturnType = {
|
|
567
719
|
chainId: number;
|
|
568
720
|
marketId: string;
|
|
@@ -571,11 +723,16 @@ type GetMorphoMarketsRewardsReturnType = {
|
|
|
571
723
|
reallocatableLiquidityAssets: Amount;
|
|
572
724
|
publicAllocatorSharedLiquidity: PublicAllocatorSharedLiquidityType[];
|
|
573
725
|
rewards: Required<MorphoReward>[];
|
|
726
|
+
sharedLiquidityStatus: "available" | "unavailable" | "not-requested";
|
|
574
727
|
};
|
|
575
728
|
|
|
576
729
|
async function getMorphoMarketRewards(
|
|
577
730
|
environment: Environment,
|
|
578
731
|
markets: { marketId: string; chainId: number }[],
|
|
732
|
+
options: {
|
|
733
|
+
includeRewards?: boolean | undefined;
|
|
734
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
735
|
+
},
|
|
579
736
|
): Promise<GetMorphoMarketsRewardsReturnType[]> {
|
|
580
737
|
if (markets.length === 0) {
|
|
581
738
|
return [];
|
|
@@ -591,7 +748,10 @@ async function getMorphoMarketRewards(
|
|
|
591
748
|
id
|
|
592
749
|
}
|
|
593
750
|
}
|
|
594
|
-
|
|
751
|
+
${
|
|
752
|
+
options.includeSharedLiquidity === false
|
|
753
|
+
? ""
|
|
754
|
+
: `reallocatableLiquidityAssets
|
|
595
755
|
publicAllocatorSharedLiquidity {
|
|
596
756
|
assets
|
|
597
757
|
vault {
|
|
@@ -621,6 +781,8 @@ async function getMorphoMarketRewards(
|
|
|
621
781
|
lltv
|
|
622
782
|
}
|
|
623
783
|
}
|
|
784
|
+
`
|
|
785
|
+
}
|
|
624
786
|
collateralAsset {
|
|
625
787
|
decimals
|
|
626
788
|
}
|
|
@@ -631,7 +793,9 @@ async function getMorphoMarketRewards(
|
|
|
631
793
|
state {
|
|
632
794
|
collateralAssets
|
|
633
795
|
collateralAssetsUsd
|
|
634
|
-
|
|
796
|
+
${
|
|
797
|
+
options.includeRewards
|
|
798
|
+
? `rewards {
|
|
635
799
|
asset {
|
|
636
800
|
address
|
|
637
801
|
symbol
|
|
@@ -640,6 +804,8 @@ async function getMorphoMarketRewards(
|
|
|
640
804
|
}
|
|
641
805
|
supplyApr
|
|
642
806
|
borrowApr
|
|
807
|
+
}`
|
|
808
|
+
: ""
|
|
643
809
|
}
|
|
644
810
|
}
|
|
645
811
|
marketId
|
|
@@ -718,7 +884,7 @@ async function getMorphoMarketRewards(
|
|
|
718
884
|
chainId: item.morphoBlue.chain.id,
|
|
719
885
|
marketId: item.marketId,
|
|
720
886
|
reallocatableLiquidityAssets: new Amount(
|
|
721
|
-
BigInt(item.reallocatableLiquidityAssets),
|
|
887
|
+
BigInt(item.reallocatableLiquidityAssets ?? "0"),
|
|
722
888
|
loanAssetDecimals,
|
|
723
889
|
),
|
|
724
890
|
// Note: The Morpho GraphQL API may return null for collateralAssets and
|
|
@@ -732,38 +898,49 @@ async function getMorphoMarketRewards(
|
|
|
732
898
|
)
|
|
733
899
|
: null,
|
|
734
900
|
collateralAssetsUsd: item.state.collateralAssetsUsd ?? null,
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
irmAddress: item.allocationMarket.irmAddress,
|
|
762
|
-
lltv: item.allocationMarket.lltv,
|
|
901
|
+
sharedLiquidityStatus:
|
|
902
|
+
options.includeSharedLiquidity === false
|
|
903
|
+
? "not-requested"
|
|
904
|
+
: item.publicAllocatorSharedLiquidity
|
|
905
|
+
? "available"
|
|
906
|
+
: "unavailable",
|
|
907
|
+
publicAllocatorSharedLiquidity: (options.includeSharedLiquidity ===
|
|
908
|
+
false
|
|
909
|
+
? []
|
|
910
|
+
: (item.publicAllocatorSharedLiquidity ?? [])
|
|
911
|
+
).map((item) => ({
|
|
912
|
+
assets: Number(item.assets) / 10 ** loanAssetDecimals,
|
|
913
|
+
vault: {
|
|
914
|
+
address: item.vault.address,
|
|
915
|
+
name: item.vault.name,
|
|
916
|
+
// The Morpho API renamed Market.uniqueKey to marketId; map it
|
|
917
|
+
// back to keep the SDK's public types unchanged.
|
|
918
|
+
publicAllocatorConfig: {
|
|
919
|
+
fee: item.vault.publicAllocatorConfig.fee,
|
|
920
|
+
flowCaps: item.vault.publicAllocatorConfig.flowCaps.map(
|
|
921
|
+
(flowCap) => ({
|
|
922
|
+
market: { uniqueKey: flowCap.market.marketId },
|
|
923
|
+
maxIn: flowCap.maxIn,
|
|
924
|
+
maxOut: flowCap.maxOut,
|
|
925
|
+
}),
|
|
926
|
+
),
|
|
763
927
|
},
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
|
|
928
|
+
},
|
|
929
|
+
allocationMarket: {
|
|
930
|
+
uniqueKey: item.allocationMarket.marketId,
|
|
931
|
+
loanAsset: item.allocationMarket.loanAsset,
|
|
932
|
+
...(item.allocationMarket.collateralAsset
|
|
933
|
+
? { collateralAsset: item.allocationMarket.collateralAsset }
|
|
934
|
+
: {}),
|
|
935
|
+
oracleAddress: item.allocationMarket.oracleAddress,
|
|
936
|
+
irmAddress: item.allocationMarket.irmAddress,
|
|
937
|
+
lltv: item.allocationMarket.lltv,
|
|
938
|
+
},
|
|
939
|
+
})),
|
|
940
|
+
rewards: (options.includeRewards
|
|
941
|
+
? (item.state?.rewards ?? [])
|
|
942
|
+
: []
|
|
943
|
+
).map((reward) => {
|
|
767
944
|
//Supply APR is used only for vaults, zeroing it for now to avoid confusion
|
|
768
945
|
// Morpho removed the per-token amount fields from the API
|
|
769
946
|
// (MarketStateReward.amountPerBorrowedToken et al.), so reward
|
|
@@ -795,6 +972,7 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
795
972
|
environments: Environment[];
|
|
796
973
|
markets?: string[] | undefined;
|
|
797
974
|
includeRewards?: boolean | undefined;
|
|
975
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
798
976
|
}): Promise<MorphoMarket[]> {
|
|
799
977
|
const { environments } = params;
|
|
800
978
|
|
|
@@ -866,6 +1044,7 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
866
1044
|
environments: failedEnvironments,
|
|
867
1045
|
markets: params.markets,
|
|
868
1046
|
includeRewards: params.includeRewards,
|
|
1047
|
+
includeSharedLiquidity: params.includeSharedLiquidity,
|
|
869
1048
|
});
|
|
870
1049
|
} catch (rpcError) {
|
|
871
1050
|
console.warn(
|
|
@@ -883,61 +1062,69 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
883
1062
|
|
|
884
1063
|
// Fetch shared liquidity from lunar-indexer.
|
|
885
1064
|
const sharedLiquiditySettlements = await Promise.allSettled(
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1065
|
+
(params.includeSharedLiquidity === false ? [] : fulfilledMarkets).map(
|
|
1066
|
+
async ({
|
|
1067
|
+
environment,
|
|
1068
|
+
markets,
|
|
1069
|
+
}): Promise<{
|
|
1070
|
+
environment: Environment;
|
|
1071
|
+
data: MorphoMarketSharedLiquidity[];
|
|
1072
|
+
}> => {
|
|
1073
|
+
const lunarIndexerUrl = environment.lunarIndexerUrl;
|
|
1074
|
+
if (!lunarIndexerUrl)
|
|
1075
|
+
return {
|
|
1076
|
+
environment,
|
|
1077
|
+
data: [],
|
|
1078
|
+
};
|
|
893
1079
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1080
|
+
const marketParamsMap = new Map(
|
|
1081
|
+
markets.map((m) => [
|
|
1082
|
+
m.marketId.toLowerCase(),
|
|
1083
|
+
{
|
|
1084
|
+
oracle: m.oracle,
|
|
1085
|
+
irm: m.irm,
|
|
1086
|
+
lltv: m.lltv,
|
|
1087
|
+
loanToken: {
|
|
1088
|
+
address: m.loanToken.address,
|
|
1089
|
+
decimals: m.loanToken.decimals,
|
|
1090
|
+
},
|
|
1091
|
+
collateralToken: {
|
|
1092
|
+
address: m.collateralToken.address,
|
|
1093
|
+
decimals: m.collateralToken.decimals,
|
|
1094
|
+
},
|
|
908
1095
|
},
|
|
909
|
-
|
|
910
|
-
]),
|
|
911
|
-
);
|
|
912
|
-
|
|
913
|
-
try {
|
|
914
|
-
const rawData = await fetchSharedLiquidityFromLunar(
|
|
915
|
-
lunarIndexerUrl,
|
|
916
|
-
environment.chainId,
|
|
917
|
-
);
|
|
918
|
-
const marketIds = markets.map((m) => m.marketId);
|
|
919
|
-
const data = computeSharedLiquidityFromLunar(
|
|
920
|
-
rawData,
|
|
921
|
-
marketIds,
|
|
922
|
-
marketParamsMap,
|
|
923
|
-
environment.chainId,
|
|
924
|
-
);
|
|
925
|
-
return { environment, data };
|
|
926
|
-
} catch (error) {
|
|
927
|
-
console.warn(
|
|
928
|
-
`[getMorphoMarketsData] Lunar shared liquidity failed for chain ${environment.chainId}:`,
|
|
929
|
-
error,
|
|
1096
|
+
]),
|
|
930
1097
|
);
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1098
|
+
|
|
1099
|
+
try {
|
|
1100
|
+
const rawData = await fetchSharedLiquidityFromLunar(
|
|
1101
|
+
lunarIndexerUrl,
|
|
1102
|
+
environment.chainId,
|
|
1103
|
+
);
|
|
1104
|
+
const marketIds = markets.map((m) => m.marketId);
|
|
1105
|
+
const data = computeSharedLiquidityFromLunar(
|
|
1106
|
+
rawData,
|
|
1107
|
+
marketIds,
|
|
1108
|
+
marketParamsMap,
|
|
1109
|
+
environment.chainId,
|
|
1110
|
+
);
|
|
1111
|
+
return { environment, data };
|
|
1112
|
+
} catch (error) {
|
|
1113
|
+
console.warn(
|
|
1114
|
+
`[getMorphoMarketsData] Lunar shared liquidity failed for chain ${environment.chainId}:`,
|
|
1115
|
+
error,
|
|
1116
|
+
);
|
|
1117
|
+
environment.onError?.(error, {
|
|
1118
|
+
source: "morpho-shared-liquidity",
|
|
1119
|
+
chainId: environment.chainId,
|
|
1120
|
+
});
|
|
1121
|
+
return {
|
|
1122
|
+
environment,
|
|
1123
|
+
data: [],
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
},
|
|
1127
|
+
),
|
|
941
1128
|
);
|
|
942
1129
|
|
|
943
1130
|
const fulfilledSharedLiquidity = sharedLiquiditySettlements.flatMap((s) =>
|
|
@@ -1027,6 +1214,18 @@ async function getMorphoMarketsDataFromIndexer(params: {
|
|
|
1027
1214
|
environment,
|
|
1028
1215
|
rewardsDataMap,
|
|
1029
1216
|
sharedLiquidityMap,
|
|
1217
|
+
).map(
|
|
1218
|
+
(market): MorphoMarket => ({
|
|
1219
|
+
...market,
|
|
1220
|
+
sharedLiquidityStatus:
|
|
1221
|
+
params.includeSharedLiquidity === false
|
|
1222
|
+
? "not-requested"
|
|
1223
|
+
: sharedLiquidityMap.has(
|
|
1224
|
+
`${market.chainId}-${market.marketId.toLowerCase()}`,
|
|
1225
|
+
)
|
|
1226
|
+
? "available"
|
|
1227
|
+
: "unavailable",
|
|
1228
|
+
}),
|
|
1030
1229
|
);
|
|
1031
1230
|
},
|
|
1032
1231
|
);
|
|
@@ -17,6 +17,8 @@ export type GetMorphoMarketParameters<
|
|
|
17
17
|
> = NetworkParameterType<environments, network> &
|
|
18
18
|
MorphoMarketParameterType<network> & {
|
|
19
19
|
includeRewards?: boolean | undefined;
|
|
20
|
+
/** Defaults to true. Disable to load base market data independently. */
|
|
21
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export type GetMorphoMarketReturnType = Promise<MorphoMarket | undefined>;
|
|
@@ -47,6 +49,7 @@ export async function getMorphoMarket<
|
|
|
47
49
|
environments: [environment],
|
|
48
50
|
markets: [marketId],
|
|
49
51
|
includeRewards: args.includeRewards,
|
|
52
|
+
includeSharedLiquidity: args.includeSharedLiquidity,
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
return first(markets);
|
|
@@ -11,6 +11,8 @@ export type GetMorphoMarketsParameters<
|
|
|
11
11
|
network extends Chain | undefined,
|
|
12
12
|
> = OptionalNetworkParameterType<environments, network> & {
|
|
13
13
|
includeRewards?: boolean | undefined;
|
|
14
|
+
/** Defaults to true. Disable to load base market data independently. */
|
|
15
|
+
includeSharedLiquidity?: boolean | undefined;
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
export type GetMorphoMarketsReturnType = Promise<MorphoMarket[]>;
|
|
@@ -32,6 +34,7 @@ export async function getMorphoMarkets<
|
|
|
32
34
|
const result = await getMorphoMarketsData({
|
|
33
35
|
environments: environments,
|
|
34
36
|
includeRewards: args?.includeRewards,
|
|
37
|
+
includeSharedLiquidity: args?.includeSharedLiquidity,
|
|
35
38
|
});
|
|
36
39
|
|
|
37
40
|
logger.end(logId);
|