@moonwell-fi/moonwell-sdk 0.19.1 → 0.20.1
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 +24 -0
- package/_cjs/actions/governance/getUserVotingPowers.js +15 -6
- package/_cjs/actions/governance/getUserVotingPowers.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +15 -5
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposal.js +1 -1
- package/_cjs/actions/governance/proposals/getProposal.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js.map +1 -1
- package/_cjs/actions/morpho/markets/common.js +25 -16
- package/_cjs/actions/morpho/markets/common.js.map +1 -1
- package/_cjs/actions/morpho/utils/graphql.js +4 -12
- package/_cjs/actions/morpho/utils/graphql.js.map +1 -1
- package/_cjs/actions/morpho/vaults/common.js +6 -24
- package/_cjs/actions/morpho/vaults/common.js.map +1 -1
- package/_cjs/common/getBlockNumberAtTimestamp.js +12 -2
- package/_cjs/common/getBlockNumberAtTimestamp.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_esm/actions/governance/getUserVotingPowers.js +22 -6
- package/_esm/actions/governance/getUserVotingPowers.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +59 -19
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposal.js +6 -2
- package/_esm/actions/governance/proposals/getProposal.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposals.js +5 -2
- package/_esm/actions/governance/proposals/getProposals.js.map +1 -1
- package/_esm/actions/morpho/markets/common.js +31 -19
- package/_esm/actions/morpho/markets/common.js.map +1 -1
- package/_esm/actions/morpho/utils/graphql.js +4 -12
- package/_esm/actions/morpho/utils/graphql.js.map +1 -1
- package/_esm/actions/morpho/vaults/common.js +9 -24
- package/_esm/actions/morpho/vaults/common.js.map +1 -1
- package/_esm/common/getBlockNumberAtTimestamp.js +36 -8
- package/_esm/common/getBlockNumberAtTimestamp.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_types/actions/governance/getUserVotingPowers.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts +48 -12
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposal.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts.map +1 -1
- package/_types/actions/morpho/utils/graphql.d.ts.map +1 -1
- package/_types/actions/morpho/vaults/common.d.ts.map +1 -1
- package/_types/common/getBlockNumberAtTimestamp.d.ts +18 -3
- package/_types/common/getBlockNumberAtTimestamp.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/actions/governance/getUserVotingPowers.ts +30 -15
- package/actions/governance/proposals/common.ts +77 -21
- package/actions/governance/proposals/getProposal.ts +5 -2
- package/actions/governance/proposals/getProposals.ts +4 -2
- package/actions/morpho/markets/common.ts +36 -28
- package/actions/morpho/utils/graphql.ts +10 -18
- package/actions/morpho/vaults/common.ts +11 -38
- package/common/getBlockNumberAtTimestamp.ts +36 -8
- package/errors/version.ts +1 -1
- package/package.json +1 -1
|
@@ -603,13 +603,13 @@ async function getMorphoMarketRewards(
|
|
|
603
603
|
maxIn
|
|
604
604
|
maxOut
|
|
605
605
|
market {
|
|
606
|
-
|
|
606
|
+
marketId
|
|
607
607
|
}
|
|
608
608
|
}
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
|
-
allocationMarket {
|
|
612
|
-
|
|
611
|
+
allocationMarket: withdrawMarket {
|
|
612
|
+
marketId
|
|
613
613
|
loanAsset {
|
|
614
614
|
address
|
|
615
615
|
}
|
|
@@ -640,11 +640,9 @@ async function getMorphoMarketRewards(
|
|
|
640
640
|
}
|
|
641
641
|
supplyApr
|
|
642
642
|
borrowApr
|
|
643
|
-
amountPerBorrowedToken
|
|
644
|
-
amountPerSuppliedToken
|
|
645
643
|
}
|
|
646
644
|
}
|
|
647
|
-
|
|
645
|
+
marketId
|
|
648
646
|
}
|
|
649
647
|
}
|
|
650
648
|
} `;
|
|
@@ -657,7 +655,7 @@ async function getMorphoMarketRewards(
|
|
|
657
655
|
id: number;
|
|
658
656
|
};
|
|
659
657
|
};
|
|
660
|
-
|
|
658
|
+
marketId: string;
|
|
661
659
|
reallocatableLiquidityAssets: string;
|
|
662
660
|
publicAllocatorSharedLiquidity: {
|
|
663
661
|
assets: string;
|
|
@@ -668,7 +666,7 @@ async function getMorphoMarketRewards(
|
|
|
668
666
|
fee: number;
|
|
669
667
|
flowCaps: {
|
|
670
668
|
market: {
|
|
671
|
-
|
|
669
|
+
marketId: string;
|
|
672
670
|
};
|
|
673
671
|
maxIn: number;
|
|
674
672
|
maxOut: number;
|
|
@@ -676,7 +674,7 @@ async function getMorphoMarketRewards(
|
|
|
676
674
|
};
|
|
677
675
|
};
|
|
678
676
|
allocationMarket: {
|
|
679
|
-
|
|
677
|
+
marketId: string;
|
|
680
678
|
loanAsset: {
|
|
681
679
|
address: string;
|
|
682
680
|
};
|
|
@@ -706,9 +704,7 @@ async function getMorphoMarketRewards(
|
|
|
706
704
|
name: string;
|
|
707
705
|
};
|
|
708
706
|
supplyApr: number;
|
|
709
|
-
amountPerSuppliedToken: string;
|
|
710
707
|
borrowApr: number;
|
|
711
|
-
amountPerBorrowedToken: string;
|
|
712
708
|
}[];
|
|
713
709
|
};
|
|
714
710
|
}[];
|
|
@@ -720,7 +716,7 @@ async function getMorphoMarketRewards(
|
|
|
720
716
|
const loanAssetDecimals = item.loanAsset.decimals;
|
|
721
717
|
const mapping: GetMorphoMarketsRewardsReturnType = {
|
|
722
718
|
chainId: item.morphoBlue.chain.id,
|
|
723
|
-
marketId: item.
|
|
719
|
+
marketId: item.marketId,
|
|
724
720
|
reallocatableLiquidityAssets: new Amount(
|
|
725
721
|
BigInt(item.reallocatableLiquidityAssets),
|
|
726
722
|
loanAssetDecimals,
|
|
@@ -742,31 +738,43 @@ async function getMorphoMarketRewards(
|
|
|
742
738
|
vault: {
|
|
743
739
|
address: item.vault.address,
|
|
744
740
|
name: item.vault.name,
|
|
745
|
-
|
|
741
|
+
// The Morpho API renamed Market.uniqueKey to marketId; map it
|
|
742
|
+
// back to keep the SDK's public types unchanged.
|
|
743
|
+
publicAllocatorConfig: {
|
|
744
|
+
fee: item.vault.publicAllocatorConfig.fee,
|
|
745
|
+
flowCaps: item.vault.publicAllocatorConfig.flowCaps.map(
|
|
746
|
+
(flowCap) => ({
|
|
747
|
+
market: { uniqueKey: flowCap.market.marketId },
|
|
748
|
+
maxIn: flowCap.maxIn,
|
|
749
|
+
maxOut: flowCap.maxOut,
|
|
750
|
+
}),
|
|
751
|
+
),
|
|
752
|
+
},
|
|
753
|
+
},
|
|
754
|
+
allocationMarket: {
|
|
755
|
+
uniqueKey: item.allocationMarket.marketId,
|
|
756
|
+
loanAsset: item.allocationMarket.loanAsset,
|
|
757
|
+
...(item.allocationMarket.collateralAsset
|
|
758
|
+
? { collateralAsset: item.allocationMarket.collateralAsset }
|
|
759
|
+
: {}),
|
|
760
|
+
oracleAddress: item.allocationMarket.oracleAddress,
|
|
761
|
+
irmAddress: item.allocationMarket.irmAddress,
|
|
762
|
+
lltv: item.allocationMarket.lltv,
|
|
746
763
|
},
|
|
747
|
-
allocationMarket: item.allocationMarket,
|
|
748
764
|
}),
|
|
749
765
|
),
|
|
750
766
|
rewards: item.state?.rewards.map((reward) => {
|
|
751
|
-
const tokenDecimals = 10 ** reward.asset.decimals;
|
|
752
|
-
|
|
753
767
|
//Supply APR is used only for vaults, zeroing it for now to avoid confusion
|
|
754
|
-
//
|
|
755
|
-
//
|
|
756
|
-
|
|
757
|
-
const borrowTokenAmountPer1000 =
|
|
758
|
-
(Number.parseFloat(reward.amountPerBorrowedToken) /
|
|
759
|
-
item.loanAsset.priceUsd) *
|
|
760
|
-
1000;
|
|
761
|
-
|
|
762
|
-
const borrowAmount = borrowTokenAmountPer1000 / tokenDecimals;
|
|
768
|
+
// Morpho removed the per-token amount fields from the API
|
|
769
|
+
// (MarketStateReward.amountPerBorrowedToken et al.), so reward
|
|
770
|
+
// amounts can no longer be computed and are reported as 0.
|
|
763
771
|
return {
|
|
764
|
-
marketId: item.
|
|
772
|
+
marketId: item.marketId,
|
|
765
773
|
asset: reward.asset,
|
|
766
774
|
supplyApr: 0, //(reward.supplyApr || 0) * 100,
|
|
767
|
-
supplyAmount: 0,
|
|
775
|
+
supplyAmount: 0,
|
|
768
776
|
borrowApr: (reward.borrowApr || 0) * 100 * -1,
|
|
769
|
-
borrowAmount:
|
|
777
|
+
borrowAmount: 0,
|
|
770
778
|
};
|
|
771
779
|
}),
|
|
772
780
|
};
|
|
@@ -20,20 +20,16 @@ export async function getGraphQL<T>(
|
|
|
20
20
|
|
|
21
21
|
const json = await response.json();
|
|
22
22
|
if (response.status !== 200 || json.errors) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
}
|
|
23
|
+
console.error(
|
|
24
|
+
`[Morpho GraphQL] Non-200 (${response.statusText}) or errors:`,
|
|
25
|
+
JSON.stringify(json.errors),
|
|
26
|
+
);
|
|
29
27
|
return undefined;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
return json.data as T;
|
|
33
31
|
} catch (error) {
|
|
34
|
-
|
|
35
|
-
console.debug("[Morpho GraphQL] Error fetching data:", error);
|
|
36
|
-
}
|
|
32
|
+
console.error("[Morpho GraphQL] Error fetching data:", error);
|
|
37
33
|
return undefined;
|
|
38
34
|
}
|
|
39
35
|
}
|
|
@@ -94,20 +90,16 @@ export async function getVaultV2Apy(
|
|
|
94
90
|
|
|
95
91
|
const json = await response.json();
|
|
96
92
|
if (response.status !== 200 || json.errors) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
102
|
-
}
|
|
93
|
+
console.error(
|
|
94
|
+
`[Morpho V2 APY] Non-200 (${response.statusText}) or errors:`,
|
|
95
|
+
JSON.stringify(json.errors),
|
|
96
|
+
);
|
|
103
97
|
return undefined;
|
|
104
98
|
}
|
|
105
99
|
|
|
106
100
|
return json.data?.vaultV2ByAddress as MorphoVaultV2ApyResponse | undefined;
|
|
107
101
|
} catch (error) {
|
|
108
|
-
|
|
109
|
-
console.debug("[Morpho V2 APY] Error fetching data:", error);
|
|
110
|
-
}
|
|
102
|
+
console.error("[Morpho V2 APY] Error fetching data:", error);
|
|
111
103
|
return undefined;
|
|
112
104
|
}
|
|
113
105
|
}
|
|
@@ -1372,11 +1372,8 @@ export async function getMorphoVaultsRewards(
|
|
|
1372
1372
|
}
|
|
1373
1373
|
id
|
|
1374
1374
|
address
|
|
1375
|
-
asset {
|
|
1376
|
-
priceUsd
|
|
1377
|
-
}
|
|
1378
1375
|
state {
|
|
1379
|
-
|
|
1376
|
+
allRewards {
|
|
1380
1377
|
asset {
|
|
1381
1378
|
address
|
|
1382
1379
|
symbol
|
|
@@ -1387,7 +1384,6 @@ export async function getMorphoVaultsRewards(
|
|
|
1387
1384
|
}
|
|
1388
1385
|
}
|
|
1389
1386
|
supplyApr
|
|
1390
|
-
amountPerSuppliedToken
|
|
1391
1387
|
}
|
|
1392
1388
|
}
|
|
1393
1389
|
}
|
|
@@ -1405,10 +1401,7 @@ export async function getMorphoVaultsRewards(
|
|
|
1405
1401
|
id
|
|
1406
1402
|
}
|
|
1407
1403
|
}
|
|
1408
|
-
|
|
1409
|
-
loanAsset {
|
|
1410
|
-
priceUsd
|
|
1411
|
-
}
|
|
1404
|
+
marketId
|
|
1412
1405
|
state {
|
|
1413
1406
|
rewards {
|
|
1414
1407
|
asset {
|
|
@@ -1421,7 +1414,6 @@ export async function getMorphoVaultsRewards(
|
|
|
1421
1414
|
}
|
|
1422
1415
|
}
|
|
1423
1416
|
supplyApr
|
|
1424
|
-
amountPerSuppliedToken
|
|
1425
1417
|
}
|
|
1426
1418
|
}
|
|
1427
1419
|
}
|
|
@@ -1437,11 +1429,8 @@ export async function getMorphoVaultsRewards(
|
|
|
1437
1429
|
};
|
|
1438
1430
|
id: string;
|
|
1439
1431
|
address: Address;
|
|
1440
|
-
asset: {
|
|
1441
|
-
priceUsd: number;
|
|
1442
|
-
};
|
|
1443
1432
|
state: {
|
|
1444
|
-
|
|
1433
|
+
allRewards: {
|
|
1445
1434
|
asset: {
|
|
1446
1435
|
address: Address;
|
|
1447
1436
|
symbol: string;
|
|
@@ -1452,7 +1441,6 @@ export async function getMorphoVaultsRewards(
|
|
|
1452
1441
|
};
|
|
1453
1442
|
};
|
|
1454
1443
|
supplyApr: number;
|
|
1455
|
-
amountPerSuppliedToken: string;
|
|
1456
1444
|
}[];
|
|
1457
1445
|
};
|
|
1458
1446
|
}[];
|
|
@@ -1468,10 +1456,7 @@ export async function getMorphoVaultsRewards(
|
|
|
1468
1456
|
id: number;
|
|
1469
1457
|
};
|
|
1470
1458
|
};
|
|
1471
|
-
|
|
1472
|
-
loanAsset: {
|
|
1473
|
-
priceUsd: number;
|
|
1474
|
-
};
|
|
1459
|
+
marketId: string;
|
|
1475
1460
|
state: {
|
|
1476
1461
|
rewards: {
|
|
1477
1462
|
asset: {
|
|
@@ -1484,7 +1469,6 @@ export async function getMorphoVaultsRewards(
|
|
|
1484
1469
|
};
|
|
1485
1470
|
};
|
|
1486
1471
|
supplyApr: number;
|
|
1487
|
-
amountPerSuppliedToken: string;
|
|
1488
1472
|
}[];
|
|
1489
1473
|
};
|
|
1490
1474
|
};
|
|
@@ -1494,22 +1478,18 @@ export async function getMorphoVaultsRewards(
|
|
|
1494
1478
|
|
|
1495
1479
|
if (result) {
|
|
1496
1480
|
try {
|
|
1481
|
+
// Morpho removed the per-supplied-token amount fields from the API
|
|
1482
|
+
// (VaultStateReward.amountPerSuppliedToken et al.), so reward amounts
|
|
1483
|
+
// can no longer be computed and are reported as 0.
|
|
1497
1484
|
const marketsRewards = result.marketPositions.items.flatMap((item) => {
|
|
1498
1485
|
const rewards = (item.market.state?.rewards || []).map((reward) => {
|
|
1499
|
-
const tokenAmountPer1000 =
|
|
1500
|
-
(Number.parseFloat(reward.amountPerSuppliedToken) /
|
|
1501
|
-
item.market.loanAsset.priceUsd) *
|
|
1502
|
-
1000;
|
|
1503
|
-
const tokenDecimals = 10 ** reward.asset.decimals;
|
|
1504
|
-
const amount = Number(tokenAmountPer1000) / tokenDecimals;
|
|
1505
|
-
|
|
1506
1486
|
return {
|
|
1507
1487
|
chainId: reward.asset.chain.id,
|
|
1508
1488
|
vaultId: item.user.address,
|
|
1509
|
-
marketId: item.market.
|
|
1489
|
+
marketId: item.market.marketId,
|
|
1510
1490
|
asset: reward.asset,
|
|
1511
1491
|
supplyApr: (reward.supplyApr || 0) * 100,
|
|
1512
|
-
supplyAmount:
|
|
1492
|
+
supplyAmount: 0,
|
|
1513
1493
|
borrowApr: 0,
|
|
1514
1494
|
borrowAmount: 0,
|
|
1515
1495
|
};
|
|
@@ -1518,21 +1498,14 @@ export async function getMorphoVaultsRewards(
|
|
|
1518
1498
|
});
|
|
1519
1499
|
|
|
1520
1500
|
const vaultsRewards = result.vaults.items.flatMap((item) => {
|
|
1521
|
-
return (item.state?.
|
|
1522
|
-
const tokenAmountPer1000 =
|
|
1523
|
-
(Number.parseFloat(reward.amountPerSuppliedToken) /
|
|
1524
|
-
item.asset.priceUsd) *
|
|
1525
|
-
1000;
|
|
1526
|
-
const tokenDecimals = 10 ** reward.asset.decimals;
|
|
1527
|
-
const amount = Number(tokenAmountPer1000) / tokenDecimals;
|
|
1528
|
-
|
|
1501
|
+
return (item.state?.allRewards || []).map((reward) => {
|
|
1529
1502
|
return {
|
|
1530
1503
|
chainId: reward.asset.chain.id,
|
|
1531
1504
|
vaultId: item.address,
|
|
1532
1505
|
marketId: undefined,
|
|
1533
1506
|
asset: reward.asset,
|
|
1534
1507
|
supplyApr: (reward.supplyApr || 0) * 100,
|
|
1535
|
-
supplyAmount:
|
|
1508
|
+
supplyAmount: 0,
|
|
1536
1509
|
borrowApr: 0,
|
|
1537
1510
|
borrowAmount: 0,
|
|
1538
1511
|
};
|
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import type { PublicClient } from "viem";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* converges in ~3–5 reads
|
|
6
|
-
*
|
|
4
|
+
* Cap on interpolation iterations before falling back to binary search. With
|
|
5
|
+
* near-linear `ts(block)` the interpolation phase converges in ~3–5 reads.
|
|
6
|
+
* On chains whose block time changed over their history the projection can
|
|
7
|
+
* fail to converge at all — see the binary completion phase below.
|
|
7
8
|
*/
|
|
8
|
-
const
|
|
9
|
+
const MAX_INTERPOLATION_ITERATIONS = 8;
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Find the block number on a chain whose timestamp is the latest one ≤ the target unix timestamp.
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Two phases:
|
|
15
|
+
*
|
|
16
|
+
* 1. Interpolation search anchored on the latest block and block 1: each iteration
|
|
17
|
+
* narrows the range by reading one block and projecting the target via the slope
|
|
18
|
+
* of the remaining range. Converges in ~3–5 RPC calls on chains with a roughly
|
|
19
|
+
* constant block time.
|
|
20
|
+
* 2. Binary-search completion: if interpolation hasn't converged after
|
|
21
|
+
* `MAX_INTERPOLATION_ITERATIONS`, finish with plain bisection — guaranteed
|
|
22
|
+
* convergence in ~log2(remaining range) reads.
|
|
23
|
+
*
|
|
24
|
+
* The completion phase is load-bearing, not defensive: on Moonbeam the block time
|
|
25
|
+
* changed ~12s → ~6s (async backing), so the interpolated projection — whose slope
|
|
26
|
+
* is the all-history average — lands after the target on every probe. Only the
|
|
27
|
+
* upper bound moves, the lower bound never leaves block 1, and the previous
|
|
28
|
+
* implementation silently returned that unconverged bound. Voting-power reads then
|
|
29
|
+
* executed against a block years before the views contract existed and reverted
|
|
30
|
+
* (governance proposal 171 incident, June 2026). An unconverged bound must never
|
|
31
|
+
* be returned.
|
|
16
32
|
*
|
|
17
33
|
* Assumes block 1 exists on the chain — true for every EVM chain Moonwell supports.
|
|
18
34
|
*
|
|
@@ -30,12 +46,13 @@ export async function getBlockNumberAtTimestamp(
|
|
|
30
46
|
const first = await publicClient.getBlock({ blockNumber: 1n });
|
|
31
47
|
if (targetTimestamp <= first.timestamp) return first.number;
|
|
32
48
|
|
|
49
|
+
// Invariant throughout: ts(lo) <= targetTimestamp < ts(hi).
|
|
33
50
|
let lo = first.number;
|
|
34
51
|
let loTs = first.timestamp;
|
|
35
52
|
let hi = latest.number;
|
|
36
53
|
let hiTs = latest.timestamp;
|
|
37
54
|
|
|
38
|
-
for (let i = 0; i <
|
|
55
|
+
for (let i = 0; i < MAX_INTERPOLATION_ITERATIONS; i += 1) {
|
|
39
56
|
if (hi - lo <= 1n) break;
|
|
40
57
|
const tsRange = hiTs - loTs;
|
|
41
58
|
if (tsRange <= 0n) break;
|
|
@@ -55,5 +72,16 @@ export async function getBlockNumberAtTimestamp(
|
|
|
55
72
|
}
|
|
56
73
|
}
|
|
57
74
|
|
|
75
|
+
// Binary completion: never return an unconverged bound.
|
|
76
|
+
while (hi - lo > 1n) {
|
|
77
|
+
const mid = (lo + hi) / 2n;
|
|
78
|
+
const block = await publicClient.getBlock({ blockNumber: mid });
|
|
79
|
+
if (block.timestamp <= targetTimestamp) {
|
|
80
|
+
lo = mid;
|
|
81
|
+
} else {
|
|
82
|
+
hi = mid;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
58
86
|
return lo;
|
|
59
87
|
}
|
package/errors/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.20.1'
|