Skip to content

Commit a63d9b0

Browse files
committed
fix type issues
1 parent 9e56604 commit a63d9b0

4 files changed

Lines changed: 70 additions & 57 deletions

File tree

src/server-extension/morpho.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,17 @@ export class MorphoVaultApyResolver {
164164
@Arg('depositAmount', () => String) depositAmount: string,
165165
@Info() _info: GraphQLResolveInfo,
166166
): Promise<MorphoDepositImpactResult> {
167+
let amount: bigint
168+
try {
169+
amount = BigInt(depositAmount)
170+
} catch {
171+
throw new Error(`Invalid depositAmount: "${depositAmount}". Must be a valid integer string.`)
172+
}
173+
if (amount <= 0n) {
174+
throw new Error(`depositAmount must be positive, got ${depositAmount}`)
175+
}
167176
const client = getViemClient(chainId)
168-
const result = await computeDepositImpact(client as any, chainId, vaultAddress, depositAmount)
177+
const result = await computeDepositImpact(client as any, chainId, vaultAddress, amount)
169178
return new MorphoDepositImpactResult(result)
170179
}
171180
}

src/templates/morpho/deposit-impact.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export interface DepositImpactResult {
1717
* @param client viem PublicClient for the target chain
1818
* @param chainId Chain ID (used to resolve the Morpho Blue singleton address)
1919
* @param vaultAddress MetaMorpho V1.1 vault address
20-
* @param depositAmount Deposit size as a decimal string in loan-token units
20+
* @param depositAmount Deposit size in loan-token base units (e.g. 1e18 for 1 ETH)
2121
*/
2222
export async function computeDepositImpact(
2323
client: PublicClient,
2424
chainId: number,
2525
vaultAddress: string,
26-
depositAmount: string,
26+
depositAmount: bigint,
2727
): Promise<DepositImpactResult> {
2828
const morphoAddress = ousd.morpho.blue[chainId]
2929
if (!morphoAddress) {
@@ -36,14 +36,8 @@ export async function computeDepositImpact(
3636
}
3737

3838
const { apy: currentApy, markets } = result
39-
const sim = simulateDeposit(markets, BigInt(depositAmount))
40-
41-
let newApy = currentApy
42-
try {
43-
newApy = weightedVaultApy(markets, sim)
44-
} catch {
45-
// If simulation fails, newApy stays at currentApy → impactBps = 0
46-
}
39+
const sim = simulateDeposit(markets, depositAmount)
40+
const newApy = weightedVaultApy(markets, sim)
4741

4842
return {
4943
currentApy,

src/templates/morpho/fetch.ts

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* - `fetchVaultApy` — Subsquid version, returns null if vault has no markets
1010
* - `fetchVaultApyViem` — viem version, returns { apy, markets } or null
1111
*/
12+
import { compact } from 'lodash'
1213
import type { PublicClient } from 'viem'
1314
import { getAddress } from 'viem'
1415

@@ -192,8 +193,18 @@ export async function fetchVaultMarketsViem(
192193

193194
// 2. Market IDs from both queues
194195
const queueCalls = [
195-
...Array.from({ length: supplyLenN }, (_, i) => ({ address: vault, abi: META_MORPHO_ABI_JSON, functionName: 'supplyQueue' as const, args: [BigInt(i)] })),
196-
...Array.from({ length: withdrawLenN }, (_, i) => ({ address: vault, abi: META_MORPHO_ABI_JSON, functionName: 'withdrawQueue' as const, args: [BigInt(i)] })),
196+
...Array.from({ length: supplyLenN }, (_, i) => ({
197+
address: vault,
198+
abi: META_MORPHO_ABI_JSON,
199+
functionName: 'supplyQueue' as const,
200+
args: [BigInt(i)],
201+
})),
202+
...Array.from({ length: withdrawLenN }, (_, i) => ({
203+
address: vault,
204+
abi: META_MORPHO_ABI_JSON,
205+
functionName: 'withdrawQueue' as const,
206+
args: [BigInt(i)],
207+
})),
197208
]
198209

199210
const queueResults = await client.multicall({ contracts: queueCalls, allowFailure: false })
@@ -206,53 +217,47 @@ export async function fetchVaultMarketsViem(
206217

207218
if (allIds.length === 0) return []
208219

209-
// 4. Fetch market state, position, params, config
210-
const perMarketCalls = allIds.flatMap((id) => [
211-
{ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'market' as const, args: [id] },
212-
{ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'position' as const, args: [id, vault] },
213-
{ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'idToMarketParams' as const, args: [id] },
214-
{ address: vault, abi: META_MORPHO_ABI_JSON, functionName: 'config' as const, args: [id] },
220+
// 4. Fetch market state, position, params, config (parallel multicalls)
221+
const [marketStates, positions, marketParams, configs] = await Promise.all([
222+
client.multicall({
223+
contracts: allIds.map((id) => ({ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'market' as const, args: [id] })),
224+
allowFailure: false,
225+
}),
226+
client.multicall({
227+
contracts: allIds.map((id) => ({ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'position' as const, args: [id, vault] })),
228+
allowFailure: false,
229+
}),
230+
client.multicall({
231+
contracts: allIds.map((id) => ({ address: morpho, abi: MORPHO_ABI_JSON, functionName: 'idToMarketParams' as const, args: [id] })),
232+
allowFailure: false,
233+
}),
234+
client.multicall({
235+
contracts: allIds.map((id) => ({ address: vault, abi: META_MORPHO_ABI_JSON, functionName: 'config' as const, args: [id] })),
236+
allowFailure: false,
237+
}),
215238
])
216239

217-
const perMarketResults = await client.multicall({ contracts: perMarketCalls, allowFailure: false })
218-
219-
// Parse per-market results (4 calls per market)
220-
// viem returns multi-output functions as arrays, so destructure by position.
221-
const parsed = allIds.map((_, i) => {
222-
const base = i * 4
223-
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, , , fee] = perMarketResults[base] as unknown as bigint[]
224-
const [supplyShares] = perMarketResults[base + 1] as unknown as bigint[]
225-
const [loanToken, , , irm] = perMarketResults[base + 2] as unknown as `0x${string}`[]
226-
const [cap] = perMarketResults[base + 3] as unknown as bigint[]
227-
return {
228-
state: { totalSupplyAssets, totalSupplyShares, totalBorrowAssets, fee },
229-
pos: { supplyShares },
230-
params: { loanToken, irm },
231-
cfg: { cap },
232-
}
233-
})
234-
235240
// 5. Per-market IRM + decimals (single multicall batch)
236-
const irmAndDecimalCalls = parsed.flatMap(({ params }, i) => {
237-
const hasIrm = params.irm && params.irm.toLowerCase() !== ADDRESS_ZERO
241+
const irmAndDecimalCalls = marketParams.flatMap(([loanToken, , , irm], i) => {
242+
const hasIrm = irm && irm.toLowerCase() !== ADDRESS_ZERO
238243
return [
239244
hasIrm
240-
? { address: getAddress(params.irm), abi: IRM_ABI_JSON, functionName: 'rateAtTarget' as const, args: [allIds[i]] }
245+
? { address: getAddress(irm), abi: IRM_ABI_JSON, functionName: 'rateAtTarget' as const, args: [allIds[i]] }
241246
: null,
242-
{ address: getAddress(params.loanToken), abi: ERC20_ABI_JSON, functionName: 'decimals' as const },
247+
{ address: getAddress(loanToken), abi: ERC20_ABI_JSON, functionName: 'decimals' as const },
243248
]
244249
})
245250
const irmAndDecimalResults = await client.multicall({
246-
contracts: irmAndDecimalCalls.filter((c): c is NonNullable<typeof c> => c !== null),
251+
contracts: compact(irmAndDecimalCalls),
247252
allowFailure: true,
248253
})
249254

250255
// Map results back, accounting for skipped IRM calls
251256
let resultIdx = 0
252257
const ratesAtTarget: bigint[] = []
253258
const decimals: number[] = []
254-
for (const { params } of parsed) {
255-
const hasIrm = params.irm && params.irm.toLowerCase() !== ADDRESS_ZERO
259+
for (const [, , , irm] of marketParams) {
260+
const hasIrm = irm && irm.toLowerCase() !== ADDRESS_ZERO
256261
if (hasIrm) {
257262
const r = irmAndDecimalResults[resultIdx++]
258263
const rate = r.status === 'success' ? (r.result as bigint) : 0n
@@ -266,20 +271,26 @@ export async function fetchVaultMarketsViem(
266271

267272
// 6. Assemble
268273
return allIds.map((marketId, i) => {
269-
const { state, pos, cfg } = parsed[i]
274+
// market: [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, totalBorrowShares, lastUpdate, fee]
275+
const [totalSupplyAssets, totalSupplyShares, totalBorrowAssets, , , fee] = marketStates[i]
276+
// position: [supplyShares, borrowShares, collateral]
277+
const [supplyShares] = positions[i]
278+
// config: [cap, enabled, removableAt]
279+
const [cap] = configs[i]
280+
270281
let vaultSupplyAssets = 0n
271-
if (pos.supplyShares > 0n && state.totalSupplyShares > 0n) {
272-
vaultSupplyAssets = (pos.supplyShares * state.totalSupplyAssets) / state.totalSupplyShares
282+
if (supplyShares > 0n && totalSupplyShares > 0n) {
283+
vaultSupplyAssets = (supplyShares * totalSupplyAssets) / totalSupplyShares
273284
}
274285

275286
return {
276287
marketId,
277-
totalSupplyAssets: state.totalSupplyAssets,
278-
totalBorrowAssets: state.totalBorrowAssets,
279-
fee: state.fee,
288+
totalSupplyAssets,
289+
totalBorrowAssets,
290+
fee,
280291
vaultSupplyAssets,
281292
rateAtTarget: ratesAtTarget[i],
282-
cap: cfg.cap,
293+
cap,
283294
decimals: decimals[i],
284295
inSupplyQueue: supplySet.has(marketId as `0x${string}`),
285296
} satisfies MarketForApy

src/templates/morpho/math.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,13 @@ export function weightedVaultApy(markets: MarketForApy[], depositSim: Record<str
100100
// Apply deposit simulation: increase totalSupplyAssets for target markets
101101
const simSupply = depositSim[m.marketId] ? m.totalSupplyAssets + depositSim[m.marketId] : m.totalSupplyAssets
102102

103-
// Convert BigInt → float via string to avoid Number.MAX_SAFE_INTEGER overflow
104-
const supply = Number(simSupply.toString()) / scale
105-
const borrows = Number(m.totalBorrowAssets.toString()) / scale
106-
const fee = Number(m.fee.toString()) // stays WAD-scaled; /WAD done inside estimateMarketApy
107-
const rate = Number(m.rateAtTarget.toString()) // stays WAD-scaled
103+
const supply = Number(simSupply) / scale
104+
const borrows = Number(m.totalBorrowAssets) / scale
105+
const fee = Number(m.fee) // stays WAD-scaled; /WAD done inside estimateMarketApy
106+
const rate = Number(m.rateAtTarget) // stays WAD-scaled
108107

109108
const { supplyApy } = estimateMarketApy(0, supply, borrows, fee, rate)
110-
const weight = Number(m.vaultSupplyAssets.toString()) / scale
109+
const weight = Number(m.vaultSupplyAssets) / scale
111110

112111
if (weight <= 0) continue
113112

0 commit comments

Comments
 (0)