@moonwell-fi/moonwell-sdk 0.21.0 → 0.23.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 +51 -0
- package/README.md +9 -3
- package/_cjs/actions/beam/common.js +1 -2
- package/_cjs/actions/beam/common.js.map +1 -1
- package/_cjs/actions/core/getUserBalances.js +11 -24
- package/_cjs/actions/core/getUserBalances.js.map +1 -1
- package/_cjs/actions/core/markets/common.js +146 -96
- package/_cjs/actions/core/markets/common.js.map +1 -1
- package/_cjs/actions/governance/getDelegates.js +2 -7
- package/_cjs/actions/governance/getDelegates.js.map +1 -1
- package/_cjs/actions/governance/getGovernanceTokenInfo.js +7 -12
- package/_cjs/actions/governance/getGovernanceTokenInfo.js.map +1 -1
- package/_cjs/actions/governance/getUserVoteReceipt.js +5 -4
- package/_cjs/actions/governance/getUserVoteReceipt.js.map +1 -1
- package/_cjs/actions/governance/governor-api-client.js.map +1 -1
- package/_cjs/actions/governance/proposals/common.js +73 -6
- package/_cjs/actions/governance/proposals/common.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposal.js +6 -73
- package/_cjs/actions/governance/proposals/getProposal.js.map +1 -1
- package/_cjs/actions/governance/proposals/getProposals.js +12 -92
- package/_cjs/actions/governance/proposals/getProposals.js.map +1 -1
- package/_cjs/client/createMoonwellClient.js +17 -15
- package/_cjs/client/createMoonwellClient.js.map +1 -1
- package/_cjs/common/index.js +4 -4
- package/_cjs/common/index.js.map +1 -1
- package/_cjs/environments/definitions/governance.js +1 -8
- package/_cjs/environments/definitions/governance.js.map +1 -1
- package/_cjs/environments/index.js +28 -42
- package/_cjs/environments/index.js.map +1 -1
- package/_cjs/environments/types/config.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_esm/actions/beam/common.js +3 -2
- package/_esm/actions/beam/common.js.map +1 -1
- package/_esm/actions/core/getUserBalances.js +23 -24
- package/_esm/actions/core/getUserBalances.js.map +1 -1
- package/_esm/actions/core/markets/common.js +192 -104
- package/_esm/actions/core/markets/common.js.map +1 -1
- package/_esm/actions/governance/getDelegates.js +8 -8
- package/_esm/actions/governance/getDelegates.js.map +1 -1
- package/_esm/actions/governance/getGovernanceTokenInfo.js +20 -13
- package/_esm/actions/governance/getGovernanceTokenInfo.js.map +1 -1
- package/_esm/actions/governance/getUserVoteReceipt.js +16 -5
- package/_esm/actions/governance/getUserVoteReceipt.js.map +1 -1
- package/_esm/actions/governance/governor-api-client.js +14 -5
- package/_esm/actions/governance/governor-api-client.js.map +1 -1
- package/_esm/actions/governance/proposals/common.js +122 -10
- package/_esm/actions/governance/proposals/common.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposal.js +16 -93
- package/_esm/actions/governance/proposals/getProposal.js.map +1 -1
- package/_esm/actions/governance/proposals/getProposals.js +37 -132
- package/_esm/actions/governance/proposals/getProposals.js.map +1 -1
- package/_esm/client/createMoonwellClient.js +24 -16
- package/_esm/client/createMoonwellClient.js.map +1 -1
- package/_esm/common/index.js +15 -4
- package/_esm/common/index.js.map +1 -1
- package/_esm/environments/definitions/governance.js +5 -9
- package/_esm/environments/definitions/governance.js.map +1 -1
- package/_esm/environments/index.js +2 -14
- package/_esm/environments/index.js.map +1 -1
- package/_esm/environments/types/config.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_types/actions/beam/common.d.ts +1 -1
- package/_types/actions/beam/common.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/governance/getGovernanceTokenInfo.d.ts.map +1 -1
- package/_types/actions/governance/getUserVoteReceipt.d.ts.map +1 -1
- package/_types/actions/governance/governor-api-client.d.ts +14 -5
- package/_types/actions/governance/governor-api-client.d.ts.map +1 -1
- package/_types/actions/governance/proposals/common.d.ts +41 -6
- package/_types/actions/governance/proposals/common.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposal.d.ts +1 -1
- package/_types/actions/governance/proposals/getProposal.d.ts.map +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts +1 -1
- package/_types/actions/governance/proposals/getProposals.d.ts.map +1 -1
- package/_types/client/createMoonwellClient.d.ts +10 -843
- package/_types/client/createMoonwellClient.d.ts.map +1 -1
- package/_types/common/index.d.ts +11 -0
- package/_types/common/index.d.ts.map +1 -1
- package/_types/environments/definitions/governance.d.ts +0 -7
- package/_types/environments/definitions/governance.d.ts.map +1 -1
- package/_types/environments/index.d.ts +7 -518
- package/_types/environments/index.d.ts.map +1 -1
- package/_types/environments/types/config.d.ts +22 -8
- package/_types/environments/types/config.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/actions/beam/common.ts +4 -9
- package/actions/core/getUserBalances.ts +25 -31
- package/actions/core/markets/common.ts +307 -166
- package/actions/governance/getDelegates.ts +8 -8
- package/actions/governance/getGovernanceTokenInfo.ts +23 -15
- package/actions/governance/getUserVoteReceipt.ts +19 -5
- package/actions/governance/governor-api-client.ts +14 -5
- package/actions/governance/proposals/common.ts +143 -10
- package/actions/governance/proposals/getProposal.ts +29 -112
- package/actions/governance/proposals/getProposals.ts +52 -153
- package/client/createMoonwellClient.ts +34 -44
- package/common/index.ts +17 -6
- package/environments/definitions/governance.ts +5 -9
- package/environments/index.ts +34 -71
- package/environments/types/config.ts +24 -8
- package/errors/version.ts +1 -1
- package/package.json +1 -1
- package/_cjs/environments/definitions/moonbeam/contracts.js +0 -22
- package/_cjs/environments/definitions/moonbeam/contracts.js.map +0 -1
- package/_cjs/environments/definitions/moonbeam/core-markets.js +0 -65
- package/_cjs/environments/definitions/moonbeam/core-markets.js.map +0 -1
- package/_cjs/environments/definitions/moonbeam/custom.js +0 -24
- package/_cjs/environments/definitions/moonbeam/custom.js.map +0 -1
- package/_cjs/environments/definitions/moonbeam/environment.js +0 -38
- package/_cjs/environments/definitions/moonbeam/environment.js.map +0 -1
- package/_cjs/environments/definitions/moonbeam/tokens.js +0 -176
- package/_cjs/environments/definitions/moonbeam/tokens.js.map +0 -1
- package/_cjs/environments/definitions/moonriver/contracts.js +0 -19
- package/_cjs/environments/definitions/moonriver/contracts.js.map +0 -1
- package/_cjs/environments/definitions/moonriver/core-markets.js +0 -46
- package/_cjs/environments/definitions/moonriver/core-markets.js.map +0 -1
- package/_cjs/environments/definitions/moonriver/custom.js +0 -12
- package/_cjs/environments/definitions/moonriver/custom.js.map +0 -1
- package/_cjs/environments/definitions/moonriver/environment.js +0 -36
- package/_cjs/environments/definitions/moonriver/environment.js.map +0 -1
- package/_cjs/environments/definitions/moonriver/tokens.js +0 -110
- package/_cjs/environments/definitions/moonriver/tokens.js.map +0 -1
- package/_esm/environments/definitions/moonbeam/contracts.js +0 -19
- package/_esm/environments/definitions/moonbeam/contracts.js.map +0 -1
- package/_esm/environments/definitions/moonbeam/core-markets.js +0 -62
- package/_esm/environments/definitions/moonbeam/core-markets.js.map +0 -1
- package/_esm/environments/definitions/moonbeam/custom.js +0 -21
- package/_esm/environments/definitions/moonbeam/custom.js.map +0 -1
- package/_esm/environments/definitions/moonbeam/environment.js +0 -32
- package/_esm/environments/definitions/moonbeam/environment.js.map +0 -1
- package/_esm/environments/definitions/moonbeam/tokens.js +0 -173
- package/_esm/environments/definitions/moonbeam/tokens.js.map +0 -1
- package/_esm/environments/definitions/moonriver/contracts.js +0 -16
- package/_esm/environments/definitions/moonriver/contracts.js.map +0 -1
- package/_esm/environments/definitions/moonriver/core-markets.js +0 -43
- package/_esm/environments/definitions/moonriver/core-markets.js.map +0 -1
- package/_esm/environments/definitions/moonriver/custom.js +0 -9
- package/_esm/environments/definitions/moonriver/custom.js.map +0 -1
- package/_esm/environments/definitions/moonriver/environment.js +0 -31
- package/_esm/environments/definitions/moonriver/environment.js.map +0 -1
- package/_esm/environments/definitions/moonriver/tokens.js +0 -107
- package/_esm/environments/definitions/moonriver/tokens.js.map +0 -1
- package/_types/environments/definitions/moonbeam/contracts.d.ts +0 -14
- package/_types/environments/definitions/moonbeam/contracts.d.ts.map +0 -1
- package/_types/environments/definitions/moonbeam/core-markets.d.ts +0 -57
- package/_types/environments/definitions/moonbeam/core-markets.d.ts.map +0 -1
- package/_types/environments/definitions/moonbeam/custom.d.ts +0 -25
- package/_types/environments/definitions/moonbeam/custom.d.ts.map +0 -1
- package/_types/environments/definitions/moonbeam/environment.d.ts +0 -265
- package/_types/environments/definitions/moonbeam/environment.d.ts.map +0 -1
- package/_types/environments/definitions/moonbeam/tokens.d.ts +0 -171
- package/_types/environments/definitions/moonbeam/tokens.d.ts.map +0 -1
- package/_types/environments/definitions/moonriver/contracts.d.ts +0 -11
- package/_types/environments/definitions/moonriver/contracts.d.ts.map +0 -1
- package/_types/environments/definitions/moonriver/core-markets.d.ts +0 -38
- package/_types/environments/definitions/moonriver/core-markets.d.ts.map +0 -1
- package/_types/environments/definitions/moonriver/custom.d.ts +0 -8
- package/_types/environments/definitions/moonriver/custom.d.ts.map +0 -1
- package/_types/environments/definitions/moonriver/environment.d.ts +0 -159
- package/_types/environments/definitions/moonriver/environment.d.ts.map +0 -1
- package/_types/environments/definitions/moonriver/tokens.d.ts +0 -105
- package/_types/environments/definitions/moonriver/tokens.d.ts.map +0 -1
- package/environments/definitions/moonbeam/contracts.ts +0 -19
- package/environments/definitions/moonbeam/core-markets.ts +0 -62
- package/environments/definitions/moonbeam/custom.ts +0 -21
- package/environments/definitions/moonbeam/environment.ts +0 -39
- package/environments/definitions/moonbeam/tokens.ts +0 -173
- package/environments/definitions/moonriver/contracts.ts +0 -16
- package/environments/definitions/moonriver/core-markets.ts +0 -43
- package/environments/definitions/moonriver/custom.ts +0 -9
- package/environments/definitions/moonriver/environment.ts +0 -38
- package/environments/definitions/moonriver/tokens.ts +0 -107
|
@@ -459,6 +459,29 @@ async function getMarketsFromMTokenFallback(
|
|
|
459
459
|
return markets;
|
|
460
460
|
}
|
|
461
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Parse a numeric field from a Lunar record, rejecting `NaN`.
|
|
464
|
+
*
|
|
465
|
+
* `Number()` wrapping is defensive — Lunar may return numeric fields as strings
|
|
466
|
+
* — but a missing or non-numeric field yields `NaN`, and only the fields that go
|
|
467
|
+
* on to reach `BigInt()` fail loudly. The rest (USD totals, prices, caps, APYs)
|
|
468
|
+
* flowed into `Market` as `NaN` and silently poisoned every downstream
|
|
469
|
+
* aggregate: a single bad `totalSupplyUsd` turns a chain's summed TVL into
|
|
470
|
+
* `NaN`. Throwing puts both field classes on the same record-level guard, so a
|
|
471
|
+
* dropped field costs its record and is reported, instead of returning a market
|
|
472
|
+
* with holes in it. Names the field, which `BigInt()`'s bare "NaN cannot be
|
|
473
|
+
* converted to a BigInt" never did.
|
|
474
|
+
*/
|
|
475
|
+
const toLunarNumber = (value: unknown, field: string): number => {
|
|
476
|
+
const parsed = Number(value);
|
|
477
|
+
if (Number.isNaN(parsed)) {
|
|
478
|
+
throw new Error(
|
|
479
|
+
`Lunar field "${field}" is not a number (received ${JSON.stringify(value)})`,
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
return parsed;
|
|
483
|
+
};
|
|
484
|
+
|
|
462
485
|
/**
|
|
463
486
|
* Fetch markets data from Lunar Indexer (hybrid approach)
|
|
464
487
|
*
|
|
@@ -525,6 +548,8 @@ async function fetchMarketsFromLunar(
|
|
|
525
548
|
}
|
|
526
549
|
|
|
527
550
|
const markets: Market[] = [];
|
|
551
|
+
let malformedCount = 0;
|
|
552
|
+
let malformedIncentiveCount = 0;
|
|
528
553
|
|
|
529
554
|
for (const lunarMarket of lunarMarkets) {
|
|
530
555
|
const marketFound = findMarketByAddress(
|
|
@@ -539,196 +564,312 @@ async function fetchMarketsFromLunar(
|
|
|
539
564
|
const { marketConfig, marketToken, underlyingToken, marketKey } =
|
|
540
565
|
marketFound;
|
|
541
566
|
|
|
542
|
-
//
|
|
543
|
-
//
|
|
544
|
-
//
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
567
|
+
// A malformed record must not reject the whole chain's market list:
|
|
568
|
+
// `BigInt()` throws a RangeError on NaN (a missing numeric field), and one
|
|
569
|
+
// bad record previously took down every market on the chain — observed
|
|
570
|
+
// chain-wide on the sunset Moonbeam deployment after the indexer stopped
|
|
571
|
+
// backfilling it (MOONWELL-FRONTEND-12J). Skip the record instead; the
|
|
572
|
+
// all-malformed case still throws below so `getMarketsData` keeps its
|
|
573
|
+
// on-chain fallback. `toLunarNumber` routes the fields that never reach
|
|
574
|
+
// `BigInt()` into this same guard, so a dropped field can't leave `NaN` in a
|
|
575
|
+
// returned market either.
|
|
576
|
+
try {
|
|
577
|
+
// Transform Lunar decimal numbers to SDK Amount types. `toLunarNumber`
|
|
578
|
+
// absorbs the string-encoded numbers Lunar may return, and rejects the
|
|
579
|
+
// `NaN` a dropped field produces — see its docblock for why the fields
|
|
580
|
+
// that never reach `BigInt()` need the same guard.
|
|
581
|
+
const totalSupply = new Amount(
|
|
582
|
+
BigInt(
|
|
583
|
+
Math.floor(
|
|
584
|
+
toLunarNumber(lunarMarket.totalSupply, "totalSupply") *
|
|
585
|
+
10 ** underlyingToken.decimals,
|
|
586
|
+
),
|
|
549
587
|
),
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
);
|
|
588
|
+
underlyingToken.decimals,
|
|
589
|
+
);
|
|
553
590
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
591
|
+
const totalBorrows = new Amount(
|
|
592
|
+
BigInt(
|
|
593
|
+
Math.floor(
|
|
594
|
+
toLunarNumber(lunarMarket.totalBorrows, "totalBorrows") *
|
|
595
|
+
10 ** underlyingToken.decimals,
|
|
596
|
+
),
|
|
558
597
|
),
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
);
|
|
598
|
+
underlyingToken.decimals,
|
|
599
|
+
);
|
|
562
600
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
601
|
+
const totalReserves = new Amount(
|
|
602
|
+
BigInt(
|
|
603
|
+
Math.floor(
|
|
604
|
+
toLunarNumber(lunarMarket.totalReserves, "totalReserves") *
|
|
605
|
+
10 ** underlyingToken.decimals,
|
|
606
|
+
),
|
|
567
607
|
),
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
);
|
|
608
|
+
underlyingToken.decimals,
|
|
609
|
+
);
|
|
571
610
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
611
|
+
const cash = new Amount(
|
|
612
|
+
BigInt(
|
|
613
|
+
Math.floor(
|
|
614
|
+
toLunarNumber(lunarMarket.cash, "cash") *
|
|
615
|
+
10 ** underlyingToken.decimals,
|
|
616
|
+
),
|
|
617
|
+
),
|
|
618
|
+
underlyingToken.decimals,
|
|
619
|
+
);
|
|
578
620
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
621
|
+
const badDebt = new Amount(
|
|
622
|
+
BigInt(
|
|
623
|
+
Math.floor(
|
|
624
|
+
toLunarNumber(lunarMarket.badDebt, "badDebt") *
|
|
625
|
+
10 ** underlyingToken.decimals,
|
|
626
|
+
),
|
|
583
627
|
),
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
);
|
|
628
|
+
underlyingToken.decimals,
|
|
629
|
+
);
|
|
587
630
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
631
|
+
const supplyCaps = new Amount(
|
|
632
|
+
BigInt(
|
|
633
|
+
Math.floor(
|
|
634
|
+
toLunarNumber(lunarMarket.supplyCap, "supplyCap") *
|
|
635
|
+
10 ** underlyingToken.decimals,
|
|
636
|
+
),
|
|
592
637
|
),
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
);
|
|
638
|
+
underlyingToken.decimals,
|
|
639
|
+
);
|
|
596
640
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
641
|
+
const borrowCaps = new Amount(
|
|
642
|
+
BigInt(
|
|
643
|
+
Math.floor(
|
|
644
|
+
toLunarNumber(lunarMarket.borrowCap, "borrowCap") *
|
|
645
|
+
10 ** underlyingToken.decimals,
|
|
646
|
+
),
|
|
601
647
|
),
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
);
|
|
648
|
+
underlyingToken.decimals,
|
|
649
|
+
);
|
|
605
650
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
651
|
+
// Lunar provides reserveFactor as wei string, convert to decimal
|
|
652
|
+
const reserveFactor = new Amount(BigInt(lunarMarket.reserveFactor), 18)
|
|
653
|
+
.value;
|
|
609
654
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
655
|
+
const market: Market = {
|
|
656
|
+
marketKey,
|
|
657
|
+
chainId: environment.chainId,
|
|
658
|
+
seizePaused: lunarMarket.seizePaused,
|
|
659
|
+
transferPaused: lunarMarket.transferPaused,
|
|
660
|
+
mintPaused: lunarMarket.mintPaused,
|
|
661
|
+
borrowPaused: lunarMarket.borrowPaused,
|
|
662
|
+
deprecated: marketConfig.deprecated === true,
|
|
663
|
+
borrowCaps,
|
|
664
|
+
borrowCapsUsd:
|
|
665
|
+
toLunarNumber(lunarMarket.borrowCap, "borrowCap") *
|
|
666
|
+
toLunarNumber(lunarMarket.priceUsd, "priceUsd"),
|
|
667
|
+
cash,
|
|
668
|
+
collateralFactor: toLunarNumber(
|
|
669
|
+
lunarMarket.collateralFactor,
|
|
670
|
+
"collateralFactor",
|
|
671
|
+
),
|
|
672
|
+
exchangeRate: toLunarNumber(lunarMarket.exchangeRate, "exchangeRate"),
|
|
673
|
+
marketToken,
|
|
674
|
+
reserveFactor,
|
|
675
|
+
supplyCaps,
|
|
676
|
+
supplyCapsUsd:
|
|
677
|
+
toLunarNumber(lunarMarket.supplyCap, "supplyCap") *
|
|
678
|
+
toLunarNumber(lunarMarket.priceUsd, "priceUsd"),
|
|
679
|
+
badDebt,
|
|
680
|
+
badDebtUsd: toLunarNumber(lunarMarket.badDebtUsd, "badDebtUsd"),
|
|
681
|
+
totalBorrows,
|
|
682
|
+
totalBorrowsUsd: toLunarNumber(
|
|
683
|
+
lunarMarket.totalBorrowsUsd,
|
|
684
|
+
"totalBorrowsUsd",
|
|
685
|
+
),
|
|
686
|
+
totalReserves,
|
|
687
|
+
totalReservesUsd: toLunarNumber(
|
|
688
|
+
lunarMarket.totalReservesUsd,
|
|
689
|
+
"totalReservesUsd",
|
|
690
|
+
),
|
|
691
|
+
totalSupply,
|
|
692
|
+
totalSupplyUsd: toLunarNumber(
|
|
693
|
+
lunarMarket.totalSupplyUsd,
|
|
694
|
+
"totalSupplyUsd",
|
|
695
|
+
),
|
|
696
|
+
underlyingPrice: toLunarNumber(lunarMarket.priceUsd, "priceUsd"),
|
|
697
|
+
underlyingToken,
|
|
698
|
+
baseBorrowApy: toLunarNumber(
|
|
699
|
+
lunarMarket.baseBorrowApy,
|
|
700
|
+
"baseBorrowApy",
|
|
701
|
+
),
|
|
702
|
+
baseSupplyApy: toLunarNumber(
|
|
703
|
+
lunarMarket.baseSupplyApy,
|
|
704
|
+
"baseSupplyApy",
|
|
705
|
+
),
|
|
706
|
+
totalBorrowApr: 0,
|
|
707
|
+
totalSupplyApr: 0,
|
|
708
|
+
rewards: [],
|
|
709
|
+
};
|
|
645
710
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
continue
|
|
653
|
-
|
|
711
|
+
for (const incentive of lunarMarket.incentives) {
|
|
712
|
+
// A malformed incentive costs its own reward entry, not the market.
|
|
713
|
+
// `BigInt()` runs on three reward fields below, so a rewards-only
|
|
714
|
+
// indexer incident would otherwise throw out to the record-level catch
|
|
715
|
+
// and drop an otherwise-valid market — the same blast radius this fix
|
|
716
|
+
// set out to shrink, one level down. Matches the loop's existing
|
|
717
|
+
// skip-the-unusable-entry idiom (`if (!token) continue`).
|
|
718
|
+
try {
|
|
719
|
+
const token = findTokenByAddress(
|
|
720
|
+
environment,
|
|
721
|
+
incentive.token as `0x${string}`,
|
|
722
|
+
);
|
|
723
|
+
if (!token) {
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
654
726
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
727
|
+
let supplyApr: number;
|
|
728
|
+
let borrowApr: number;
|
|
729
|
+
|
|
730
|
+
// On-chain contracts use borrowIncentivesPerSec=1 (1 wei) as a
|
|
731
|
+
// placeholder when there are no active borrow incentives, because
|
|
732
|
+
// setting it to 0 triggers a known smart contract bug. Treat as zero.
|
|
733
|
+
const isBorrowPlaceholder =
|
|
734
|
+
BigInt(incentive.borrowIncentivesPerSec) === 1n;
|
|
735
|
+
|
|
736
|
+
if (
|
|
737
|
+
incentive.priceUsd !== null &&
|
|
738
|
+
incentive.supplyApr !== null &&
|
|
739
|
+
incentive.borrowApr !== null
|
|
740
|
+
) {
|
|
741
|
+
supplyApr = toLunarNumber(
|
|
742
|
+
incentive.supplyApr,
|
|
743
|
+
"incentive.supplyApr",
|
|
744
|
+
);
|
|
745
|
+
borrowApr = isBorrowPlaceholder
|
|
746
|
+
? 0
|
|
747
|
+
: -toLunarNumber(incentive.borrowApr, "incentive.borrowApr");
|
|
748
|
+
} else {
|
|
749
|
+
const isGovernanceToken =
|
|
750
|
+
token.symbol === environment.custom?.governance?.token;
|
|
751
|
+
const isNativeToken = token.address === zeroAddress;
|
|
752
|
+
|
|
753
|
+
const price = isNativeToken
|
|
754
|
+
? nativeTokenPrice?.value
|
|
755
|
+
: isGovernanceToken
|
|
756
|
+
? governanceTokenPrice?.value
|
|
757
|
+
: undefined;
|
|
758
|
+
|
|
759
|
+
if (!price) {
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const borrowIncentivesPerSec = isBorrowPlaceholder
|
|
764
|
+
? 0n
|
|
765
|
+
: BigInt(incentive.borrowIncentivesPerSec);
|
|
766
|
+
const supplyIncentivesPerSec = BigInt(
|
|
767
|
+
incentive.supplyIncentivesPerSec,
|
|
768
|
+
);
|
|
685
769
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
770
|
+
const supplyRewardsPerDayUsd =
|
|
771
|
+
perDay(new Amount(supplyIncentivesPerSec, token.decimals).value) *
|
|
772
|
+
price;
|
|
773
|
+
const borrowRewardsPerDayUsd =
|
|
774
|
+
perDay(new Amount(borrowIncentivesPerSec, token.decimals).value) *
|
|
775
|
+
price;
|
|
776
|
+
|
|
777
|
+
supplyApr =
|
|
778
|
+
toLunarNumber(lunarMarket.totalSupplyUsd, "totalSupplyUsd") === 0
|
|
779
|
+
? 0
|
|
780
|
+
: (supplyRewardsPerDayUsd /
|
|
781
|
+
toLunarNumber(
|
|
782
|
+
lunarMarket.totalSupplyUsd,
|
|
783
|
+
"totalSupplyUsd",
|
|
784
|
+
)) *
|
|
785
|
+
DAYS_PER_YEAR *
|
|
786
|
+
100;
|
|
787
|
+
// Negative: borrow reward APR reduces the effective borrowing cost
|
|
788
|
+
borrowApr =
|
|
789
|
+
toLunarNumber(lunarMarket.totalBorrowsUsd, "totalBorrowsUsd") ===
|
|
790
|
+
0
|
|
791
|
+
? 0
|
|
792
|
+
: (borrowRewardsPerDayUsd /
|
|
793
|
+
toLunarNumber(
|
|
794
|
+
lunarMarket.totalBorrowsUsd,
|
|
795
|
+
"totalBorrowsUsd",
|
|
796
|
+
)) *
|
|
797
|
+
DAYS_PER_YEAR *
|
|
798
|
+
100 *
|
|
799
|
+
-1;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
market.rewards.push({
|
|
803
|
+
liquidStakingApr: 0,
|
|
804
|
+
borrowApr,
|
|
805
|
+
supplyApr,
|
|
806
|
+
token,
|
|
807
|
+
});
|
|
808
|
+
} catch (error) {
|
|
809
|
+
malformedIncentiveCount++;
|
|
810
|
+
console.warn(
|
|
811
|
+
`[fetchMarketsFromLunar] Skipping malformed incentive ${incentive.token} on market ${lunarMarket.address} (chain ${environment.chainId}):`,
|
|
812
|
+
error,
|
|
813
|
+
);
|
|
814
|
+
}
|
|
712
815
|
}
|
|
713
816
|
|
|
714
|
-
market.rewards.
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
817
|
+
market.totalSupplyApr = market.rewards.reduce(
|
|
818
|
+
(prev, curr) => prev + curr.supplyApr,
|
|
819
|
+
market.baseSupplyApy,
|
|
820
|
+
);
|
|
821
|
+
market.totalBorrowApr = market.rewards.reduce(
|
|
822
|
+
(prev, curr) => prev + curr.borrowApr,
|
|
823
|
+
market.baseBorrowApy,
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
markets.push(market);
|
|
827
|
+
} catch (error) {
|
|
828
|
+
malformedCount++;
|
|
829
|
+
console.warn(
|
|
830
|
+
`[fetchMarketsFromLunar] Skipping malformed market ${lunarMarket.address} on chain ${environment.chainId}:`,
|
|
831
|
+
error,
|
|
832
|
+
);
|
|
720
833
|
}
|
|
834
|
+
}
|
|
721
835
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
836
|
+
// Every matched record was malformed — the indexer's data for this chain is
|
|
837
|
+
// unusable, so surface it to the caller's catch (one meaningful onError +
|
|
838
|
+
// on-chain fallback) instead of silently returning an empty market list.
|
|
839
|
+
if (malformedCount > 0 && markets.length === 0) {
|
|
840
|
+
throw new Error(
|
|
841
|
+
`Lunar Indexer returned only malformed market records for chain ${environment.chainId} (${malformedCount} skipped)`,
|
|
725
842
|
);
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// A partial incident is the likeliest shape, and it is the one that returns
|
|
846
|
+
// successfully — without this, markets vanishing from the response would
|
|
847
|
+
// leave nothing behind but a console line, making the incident class this fix
|
|
848
|
+
// exists for (MOONWELL-FRONTEND-12J) invisible rather than visible. Distinct
|
|
849
|
+
// `source` values so a degraded result is attributable separately from the
|
|
850
|
+
// total failure that routes through `getMarketsData`'s own "markets" source.
|
|
851
|
+
if (malformedCount > 0) {
|
|
852
|
+
environment.onError?.(
|
|
853
|
+
new Error(
|
|
854
|
+
`Lunar Indexer returned ${malformedCount} malformed market record(s) for chain ${environment.chainId}; those markets were skipped (${markets.length} returned)`,
|
|
855
|
+
),
|
|
856
|
+
{
|
|
857
|
+
source: "markets-malformed-records",
|
|
858
|
+
chainId: environment.chainId,
|
|
859
|
+
},
|
|
729
860
|
);
|
|
861
|
+
}
|
|
730
862
|
|
|
731
|
-
|
|
863
|
+
if (malformedIncentiveCount > 0) {
|
|
864
|
+
environment.onError?.(
|
|
865
|
+
new Error(
|
|
866
|
+
`Lunar Indexer returned ${malformedIncentiveCount} malformed incentive record(s) for chain ${environment.chainId}; those rewards were skipped`,
|
|
867
|
+
),
|
|
868
|
+
{
|
|
869
|
+
source: "markets-malformed-incentives",
|
|
870
|
+
chainId: environment.chainId,
|
|
871
|
+
},
|
|
872
|
+
);
|
|
732
873
|
}
|
|
733
874
|
|
|
734
875
|
return markets;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isAddress } from "viem";
|
|
2
|
-
import { base, mainnet,
|
|
2
|
+
import { base, mainnet, optimism } from "viem/chains";
|
|
3
3
|
import type { MoonwellClient } from "../../client/createMoonwellClient.js";
|
|
4
4
|
import {
|
|
5
5
|
type Environment,
|
|
@@ -23,17 +23,17 @@ export async function getDelegates(
|
|
|
23
23
|
): GetDelegatesReturnType {
|
|
24
24
|
const logId = logger.start("getDelegates", "Starting to get delegates...");
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// Any environment resolves the same `governanceIndexerUrl`; the Ethereum hub
|
|
27
|
+
// replaces Moonbeam here now that the sunset chain is gone (MOO-551).
|
|
28
|
+
const governanceEnvironment = publicEnvironments.ethereum;
|
|
27
29
|
|
|
28
30
|
const apiVoters = await fetchAllVoters(governanceEnvironment);
|
|
29
31
|
const forumProfiles = await getForumProfiles();
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
mainnet.id,
|
|
36
|
-
] as const;
|
|
33
|
+
// Moonbeam dropped with the sunset: the chain is halted, so it can no longer
|
|
34
|
+
// serve `getUserVotingPower`. Delegate totals therefore no longer include any
|
|
35
|
+
// WELL that remained on Moonbeam.
|
|
36
|
+
const targetChainIds = [base.id, optimism.id, mainnet.id] as const;
|
|
37
37
|
const envs = Object.values(client.environments as Environment[]).filter(
|
|
38
38
|
(env) =>
|
|
39
39
|
env.contracts.views !== undefined &&
|
|
@@ -19,6 +19,8 @@ export type GetGovernanceTokenInfoReturnType = Promise<
|
|
|
19
19
|
|
|
20
20
|
export async function getGovernanceTokenInfo(
|
|
21
21
|
_client: MoonwellClient,
|
|
22
|
+
// Retained for API compatibility, but WELL is the only governance token left
|
|
23
|
+
// now that MFAM went with Moonriver (MOO-551), so there is nothing to branch on.
|
|
22
24
|
args: GetGovernanceTokenInfoParameters,
|
|
23
25
|
): GetGovernanceTokenInfoReturnType {
|
|
24
26
|
const logId = logger.start(
|
|
@@ -26,22 +28,28 @@ export async function getGovernanceTokenInfo(
|
|
|
26
28
|
"Starting to get governance token info...",
|
|
27
29
|
);
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
// TypeScript already narrows `GovernanceToken` to "WELL", but a JS consumer
|
|
32
|
+
// still passing "MFAM" would otherwise receive WELL's supply as a normal
|
|
33
|
+
// success — silently wrong data where TS consumers get a compile error.
|
|
34
|
+
// Reject it rather than let the removed token look like it still resolves.
|
|
35
|
+
if (args.governanceToken !== undefined && args.governanceToken !== "WELL") {
|
|
33
36
|
logger.end(logId);
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Unsupported governance token "${args.governanceToken}". MFAM was removed with the Moonriver sunset (MOO-551); WELL is the only governance token.`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// WELL supply used to be read from Moonbeam, the original mint. That chain is
|
|
43
|
+
// halted (MOO-551), so the read now targets the Ethereum multigov hub — the
|
|
44
|
+
// home of live governance. Note this reports the hub's xWELL supply rather
|
|
45
|
+
// than Moonbeam's historical total, so the number can differ from pre-sunset
|
|
46
|
+
// releases. MFAM is gone entirely: Apollo governance ended with Moonriver.
|
|
47
|
+
const totalSupply =
|
|
48
|
+
await publicEnvironments.ethereum.contracts.governanceToken.read.totalSupply();
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
50
|
+
logger.end(logId);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
totalSupply: new Amount(totalSupply || 0n, 18),
|
|
54
|
+
};
|
|
47
55
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Address, Chain } from "viem";
|
|
2
2
|
import type { MoonwellClient } from "../../client/createMoonwellClient.js";
|
|
3
|
-
import { Amount
|
|
3
|
+
import { Amount } from "../../common/index.js";
|
|
4
4
|
import type { NetworkParameterType } from "../../common/types.js";
|
|
5
|
+
import type { Environment } from "../../environments/index.js";
|
|
5
6
|
import type { VoteReceipt } from "../../types/voteReceipt.js";
|
|
6
7
|
import {
|
|
7
8
|
type ApiVoteReceipt,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
fetchUserVoteReceipt,
|
|
11
12
|
isNotFoundError,
|
|
12
13
|
} from "./governor-api-client.js";
|
|
14
|
+
import { resolveGovernanceEnvironment } from "./proposals/common.js";
|
|
13
15
|
|
|
14
16
|
export type GetUserVoteReceiptParameters<
|
|
15
17
|
environments,
|
|
@@ -50,8 +52,17 @@ export async function getUserVoteReceipt<
|
|
|
50
52
|
): GetUserVoteReceiptReturnType {
|
|
51
53
|
const { proposalId, userAddress, chainId } = args;
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
// `args.chainId` identifies the chain the PROPOSAL lives on, not the
|
|
56
|
+
// environment we read through — the same distinction `getProposal` draws
|
|
57
|
+
// (MOO-551). Resolving the environment from it meant an archive lookup
|
|
58
|
+
// (1284/1285) matched no registered environment post-sunset and returned `[]`,
|
|
59
|
+
// a third shape callers don't handle: every historical vote read as "didn't
|
|
60
|
+
// vote". Resolve the indexer source independently and pass `chainId` through
|
|
61
|
+
// untouched.
|
|
62
|
+
const governanceEnvironment = resolveGovernanceEnvironment(
|
|
63
|
+
Object.values(client.environments as Record<string, Environment>),
|
|
64
|
+
);
|
|
65
|
+
if (!governanceEnvironment) {
|
|
55
66
|
return [];
|
|
56
67
|
}
|
|
57
68
|
|
|
@@ -64,7 +75,7 @@ export async function getUserVoteReceipt<
|
|
|
64
75
|
for (const cid of tryChains) {
|
|
65
76
|
try {
|
|
66
77
|
const apiVoteReceipts = await fetchUserVoteReceipt(
|
|
67
|
-
|
|
78
|
+
governanceEnvironment,
|
|
68
79
|
cid,
|
|
69
80
|
proposalId,
|
|
70
81
|
userAddress,
|
|
@@ -87,7 +98,10 @@ export async function getUserVoteReceipt<
|
|
|
87
98
|
if (collected.length === 0) {
|
|
88
99
|
return [
|
|
89
100
|
{
|
|
90
|
-
|
|
101
|
+
// An explicit request names the chain the stub is about; a bare lookup
|
|
102
|
+
// queried every supported chain, so the source we read through is the
|
|
103
|
+
// only chain it can honestly claim.
|
|
104
|
+
chainId: chainId ?? governanceEnvironment.chainId,
|
|
91
105
|
proposalId,
|
|
92
106
|
account: userAddress,
|
|
93
107
|
voted: false,
|