@defisaver/positions-sdk 2.1.144-dev → 2.1.145
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/cjs/config/contracts.d.ts +249 -0
- package/cjs/config/contracts.js +11 -1
- package/cjs/constants/index.d.ts +1 -0
- package/cjs/constants/index.js +2 -1
- package/cjs/contracts.d.ts +1510 -0
- package/cjs/contracts.js +3 -2
- package/cjs/fluid/index.js +6 -2
- package/cjs/helpers/fluidHelpers/index.js +5 -4
- package/cjs/helpers/index.d.ts +1 -0
- package/cjs/helpers/index.js +2 -1
- package/cjs/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
- package/cjs/helpers/morphoMidnightHelpers/headroom.js +52 -0
- package/cjs/helpers/morphoMidnightHelpers/index.d.ts +113 -0
- package/cjs/helpers/morphoMidnightHelpers/index.js +298 -0
- package/cjs/helpers/morphoMidnightHelpers/rate.d.ts +15 -0
- package/cjs/helpers/morphoMidnightHelpers/rate.js +62 -0
- package/cjs/helpers/morphoMidnightHelpers/tenor.d.ts +129 -0
- package/cjs/helpers/morphoMidnightHelpers/tenor.js +254 -0
- package/cjs/index.d.ts +2 -1
- package/cjs/index.js +3 -1
- package/cjs/markets/index.d.ts +1 -0
- package/cjs/markets/index.js +6 -1
- package/cjs/markets/morphoMidnight/index.d.ts +60 -0
- package/cjs/markets/morphoMidnight/index.js +659 -0
- package/cjs/morphoMidnight/index.d.ts +14 -0
- package/cjs/morphoMidnight/index.js +261 -0
- package/cjs/portfolio/discovery.js +4 -0
- package/cjs/portfolio/index.js +44 -0
- package/cjs/services/viem.d.ts +11 -11
- package/cjs/staking/eligibility.d.ts +15 -1
- package/cjs/staking/eligibility.js +12 -1
- package/cjs/staking/staking.js +18 -22
- package/cjs/types/index.d.ts +1 -0
- package/cjs/types/index.js +1 -0
- package/cjs/types/morphoMidnight.d.ts +141 -0
- package/cjs/types/morphoMidnight.js +47 -0
- package/cjs/types/portfolio.d.ts +4 -0
- package/esm/config/contracts.d.ts +249 -0
- package/esm/config/contracts.js +9 -0
- package/esm/constants/index.d.ts +1 -0
- package/esm/constants/index.js +1 -0
- package/esm/contracts.d.ts +1510 -0
- package/esm/contracts.js +1 -0
- package/esm/fluid/index.js +6 -2
- package/esm/helpers/fluidHelpers/index.js +6 -5
- package/esm/helpers/index.d.ts +1 -0
- package/esm/helpers/index.js +1 -0
- package/esm/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
- package/esm/helpers/morphoMidnightHelpers/headroom.js +45 -0
- package/esm/helpers/morphoMidnightHelpers/index.d.ts +113 -0
- package/esm/helpers/morphoMidnightHelpers/index.js +271 -0
- package/esm/helpers/morphoMidnightHelpers/rate.d.ts +15 -0
- package/esm/helpers/morphoMidnightHelpers/rate.js +50 -0
- package/esm/helpers/morphoMidnightHelpers/tenor.d.ts +129 -0
- package/esm/helpers/morphoMidnightHelpers/tenor.js +238 -0
- package/esm/index.d.ts +2 -1
- package/esm/index.js +2 -1
- package/esm/markets/index.d.ts +1 -0
- package/esm/markets/index.js +1 -0
- package/esm/markets/morphoMidnight/index.d.ts +60 -0
- package/esm/markets/morphoMidnight/index.js +631 -0
- package/esm/morphoMidnight/index.d.ts +14 -0
- package/esm/morphoMidnight/index.js +248 -0
- package/esm/portfolio/discovery.js +5 -1
- package/esm/portfolio/index.js +45 -1
- package/esm/services/viem.d.ts +11 -11
- package/esm/staking/eligibility.d.ts +15 -1
- package/esm/staking/eligibility.js +10 -0
- package/esm/staking/staking.js +19 -23
- package/esm/types/index.d.ts +1 -0
- package/esm/types/index.js +1 -0
- package/esm/types/morphoMidnight.d.ts +141 -0
- package/esm/types/morphoMidnight.js +44 -0
- package/esm/types/portfolio.d.ts +4 -0
- package/package.json +1 -1
- package/src/config/contracts.ts +9 -0
- package/src/constants/index.ts +1 -0
- package/src/contracts.ts +1 -0
- package/src/fluid/index.ts +6 -2
- package/src/helpers/fluidHelpers/index.ts +6 -5
- package/src/helpers/index.ts +1 -0
- package/src/helpers/morphoMidnightHelpers/headroom.ts +82 -0
- package/src/helpers/morphoMidnightHelpers/index.ts +485 -0
- package/src/helpers/morphoMidnightHelpers/rate.ts +71 -0
- package/src/helpers/morphoMidnightHelpers/tenor.ts +407 -0
- package/src/index.ts +2 -0
- package/src/markets/index.ts +3 -0
- package/src/markets/morphoMidnight/index.ts +675 -0
- package/src/morphoMidnight/index.ts +276 -0
- package/src/portfolio/discovery.ts +6 -0
- package/src/portfolio/index.ts +44 -0
- package/src/staking/eligibility.ts +29 -2
- package/src/staking/staking.ts +20 -22
- package/src/types/index.ts +1 -0
- package/src/types/morphoMidnight.ts +163 -0
- package/src/types/portfolio.ts +4 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
2
|
+
import { MorphoMidnightBookSide, MorphoMidnightMarketData, MorphoMidnightParsedBook, NetworkNumber } from '../../types';
|
|
3
|
+
import type { MorphoMidnightBorrowQuote, MorphoMidnightPaybackQuote, MorphoMidnightPaybackUnitsQuote } from './index';
|
|
4
|
+
type TenorBookKey = 'asks' | 'bids';
|
|
5
|
+
export declare const tenorBookKeyFor: (side: MorphoMidnightBookSide) => TenorBookKey;
|
|
6
|
+
export declare const tenorBookRateToApyPercent: (rate: Dec.Value) => string;
|
|
7
|
+
interface TenorOfferCollateral {
|
|
8
|
+
token: string;
|
|
9
|
+
lltv: string | number;
|
|
10
|
+
liquidation_cursor: string | number;
|
|
11
|
+
oracle: string;
|
|
12
|
+
}
|
|
13
|
+
interface TenorOffer {
|
|
14
|
+
start: string | number;
|
|
15
|
+
group?: string;
|
|
16
|
+
callback?: string;
|
|
17
|
+
tick: string | number;
|
|
18
|
+
chain_id: string | number;
|
|
19
|
+
maturity: string | number;
|
|
20
|
+
buy: boolean;
|
|
21
|
+
maker: string;
|
|
22
|
+
loan_token_address: string;
|
|
23
|
+
callback_data?: string;
|
|
24
|
+
expiry: string | number;
|
|
25
|
+
ratifier?: string;
|
|
26
|
+
collaterals: TenorOfferCollateral[];
|
|
27
|
+
continuous_fee_cap: string | number;
|
|
28
|
+
enter_gate: string;
|
|
29
|
+
liquidator_gate: string;
|
|
30
|
+
max_assets: string | number;
|
|
31
|
+
max_units: string | number;
|
|
32
|
+
ratifier_data?: string;
|
|
33
|
+
rcf_threshold: string | number;
|
|
34
|
+
receiver_if_maker_is_seller?: string;
|
|
35
|
+
reduce_only: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface TenorOfferFill {
|
|
38
|
+
units: string | number;
|
|
39
|
+
offer: TenorOffer;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Tenor's offer JSON is flat (market fields live on the offer). Morpho's is nested, and that nested
|
|
43
|
+
* shape is what the app encodes for `Midnight.take`. Map Tenor into that shape so recipes stay on one encoder.
|
|
44
|
+
*/
|
|
45
|
+
export declare const tenorOfferToApiOffer: (offer: TenorOffer) => {
|
|
46
|
+
market: {
|
|
47
|
+
chain_id: string | number;
|
|
48
|
+
midnight: "0xAdedD8ab6dE832766Fedf0FaC4992E5C4D3EA18A";
|
|
49
|
+
loan_token: string;
|
|
50
|
+
collaterals: TenorOfferCollateral[];
|
|
51
|
+
maturity: string | number;
|
|
52
|
+
rcf_threshold: string | number;
|
|
53
|
+
enter_gate: string;
|
|
54
|
+
liquidator_gate: string;
|
|
55
|
+
};
|
|
56
|
+
buy: boolean;
|
|
57
|
+
maker: string;
|
|
58
|
+
start: string | number;
|
|
59
|
+
expiry: string | number;
|
|
60
|
+
tick: string | number;
|
|
61
|
+
group: string;
|
|
62
|
+
callback: string;
|
|
63
|
+
callback_data: string;
|
|
64
|
+
receiver_if_maker_is_seller: string;
|
|
65
|
+
ratifier: string;
|
|
66
|
+
reduce_only: boolean;
|
|
67
|
+
max_units: string | number;
|
|
68
|
+
max_assets: string | number;
|
|
69
|
+
continuous_fee_cap: string | number;
|
|
70
|
+
};
|
|
71
|
+
export declare const tenorOfferFillToApiFill: (fill: TenorOfferFill) => {
|
|
72
|
+
units: string | number;
|
|
73
|
+
offer: {
|
|
74
|
+
market: {
|
|
75
|
+
chain_id: string | number;
|
|
76
|
+
midnight: "0xAdedD8ab6dE832766Fedf0FaC4992E5C4D3EA18A";
|
|
77
|
+
loan_token: string;
|
|
78
|
+
collaterals: TenorOfferCollateral[];
|
|
79
|
+
maturity: string | number;
|
|
80
|
+
rcf_threshold: string | number;
|
|
81
|
+
enter_gate: string;
|
|
82
|
+
liquidator_gate: string;
|
|
83
|
+
};
|
|
84
|
+
buy: boolean;
|
|
85
|
+
maker: string;
|
|
86
|
+
start: string | number;
|
|
87
|
+
expiry: string | number;
|
|
88
|
+
tick: string | number;
|
|
89
|
+
group: string;
|
|
90
|
+
callback: string;
|
|
91
|
+
callback_data: string;
|
|
92
|
+
receiver_if_maker_is_seller: string;
|
|
93
|
+
ratifier: string;
|
|
94
|
+
reduce_only: boolean;
|
|
95
|
+
max_units: string | number;
|
|
96
|
+
max_assets: string | number;
|
|
97
|
+
continuous_fee_cap: string | number;
|
|
98
|
+
};
|
|
99
|
+
ratifier_data: string;
|
|
100
|
+
market_id: string;
|
|
101
|
+
};
|
|
102
|
+
interface TenorBookBucket {
|
|
103
|
+
rate: number | string;
|
|
104
|
+
liquidity: number | string;
|
|
105
|
+
cumulative_liquidity?: number | string;
|
|
106
|
+
}
|
|
107
|
+
interface TenorBookSidePayload {
|
|
108
|
+
buckets?: TenorBookBucket[];
|
|
109
|
+
}
|
|
110
|
+
interface TenorBookResponse {
|
|
111
|
+
asks?: TenorBookSidePayload | TenorBookBucket[];
|
|
112
|
+
bids?: TenorBookSidePayload | TenorBookBucket[];
|
|
113
|
+
}
|
|
114
|
+
/** The levels resting on the Tenor side a taker of `side` fills, in raw loan-token base units. */
|
|
115
|
+
export declare const parseTenorBookSide: (json: TenorBookResponse, side: MorphoMidnightBookSide) => {
|
|
116
|
+
rate: string;
|
|
117
|
+
liquidityRaw: string;
|
|
118
|
+
}[];
|
|
119
|
+
export declare const parseTenorOrderBook: (json: TenorBookResponse, side: MorphoMidnightBookSide, loanSymbol: string) => MorphoMidnightParsedBook | null;
|
|
120
|
+
export declare const getTenorMarketBook: (market: MorphoMidnightMarketData, network: NetworkNumber, side?: MorphoMidnightBookSide) => Promise<MorphoMidnightParsedBook | null>;
|
|
121
|
+
/**
|
|
122
|
+
* Tenor's router takes no slippage of its own — it prices the fill and hands back the offers. `slippagePercent`
|
|
123
|
+
* is therefore accepted only to keep the signature aligned with the Morpho-hosted quote that `index.ts`
|
|
124
|
+
* forwards to positionally; the guard comes from `rateSlippagePercent` via `midnightBoundPrice`.
|
|
125
|
+
*/
|
|
126
|
+
export declare const getTenorBorrowQuote: (marketId: string, assetsRaw: string, slippagePercent: Dec.Value, maturity: number, maxBorrowRate?: Dec.Value, taker?: string, rateSlippagePercent?: Dec.Value, network?: NetworkNumber) => Promise<MorphoMidnightBorrowQuote>;
|
|
127
|
+
export declare const getTenorPaybackQuote: (marketId: string, assetsRaw: string, slippagePercent: Dec.Value, maturity: number, minPaybackRate?: Dec.Value, taker?: string, rateSlippagePercent?: Dec.Value, network?: NetworkNumber) => Promise<MorphoMidnightPaybackQuote>;
|
|
128
|
+
export declare const getTenorPaybackUnitsQuote: (marketId: string, unitsRaw: string, slippagePercent: Dec.Value, maturity: number, minPaybackRate?: Dec.Value, taker?: string, rateSlippagePercent?: Dec.Value, network?: NetworkNumber) => Promise<MorphoMidnightPaybackUnitsQuote>;
|
|
129
|
+
export {};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import Dec from 'decimal.js';
|
|
11
|
+
import { assetAmountInEth, getAssetInfoByAddress } from '@defisaver/tokens';
|
|
12
|
+
import { ZERO_ADDRESS, ZERO_BYTES32 } from '../../constants';
|
|
13
|
+
import { NetworkNumber, } from '../../types';
|
|
14
|
+
import { isTenorMidnightMarket, MIDNIGHT_BASE } from '../../markets/morphoMidnight';
|
|
15
|
+
import { buildMidnightParsedBook, midnightApyFromPrice, midnightBoundPrice, midnightTimeToMaturityDays, } from './rate';
|
|
16
|
+
// Notion doc by Rajko: https://app.notion.com/p/defisaver/Tenor-API-3ba0be682adc80dfad35c81a9a4cb442
|
|
17
|
+
const TENOR_QUOTES_URL = 'https://router.tenor.finance/v1/quotes';
|
|
18
|
+
const TENOR_ORDERBOOK_URL = 'https://router.tenor.finance/v1/orderbook';
|
|
19
|
+
const TENOR_TIMEOUT_MS = 15000;
|
|
20
|
+
const TENOR_ALGORITHM = 'branch_and_bound';
|
|
21
|
+
const tenorQuoteError = (reason) => (reason ? `Morpho Midnight quote unavailable: ${reason}` : 'Morpho Midnight quote unavailable');
|
|
22
|
+
export const tenorBookKeyFor = (side) => (side === 'bids' ? 'asks' : 'bids');
|
|
23
|
+
// Tenor order-book levels are annualized APR in basis points: 25 → 0.25%, 700 → 7%.
|
|
24
|
+
export const tenorBookRateToApyPercent = (rate) => new Dec(rate || 0).div(100).toString();
|
|
25
|
+
const tenorFillPrice = (assets, units) => (new Dec(units).lte(0) ? '0' : new Dec(assets).div(units).toString());
|
|
26
|
+
/**
|
|
27
|
+
* Tenor's offer JSON is flat (market fields live on the offer). Morpho's is nested, and that nested
|
|
28
|
+
* shape is what the app encodes for `Midnight.take`. Map Tenor into that shape so recipes stay on one encoder.
|
|
29
|
+
*/
|
|
30
|
+
export const tenorOfferToApiOffer = (offer) => ({
|
|
31
|
+
market: {
|
|
32
|
+
chain_id: offer.chain_id,
|
|
33
|
+
midnight: MIDNIGHT_BASE,
|
|
34
|
+
loan_token: offer.loan_token_address,
|
|
35
|
+
collaterals: offer.collaterals || [],
|
|
36
|
+
maturity: offer.maturity,
|
|
37
|
+
rcf_threshold: offer.rcf_threshold,
|
|
38
|
+
enter_gate: offer.enter_gate,
|
|
39
|
+
liquidator_gate: offer.liquidator_gate,
|
|
40
|
+
},
|
|
41
|
+
buy: offer.buy,
|
|
42
|
+
maker: offer.maker,
|
|
43
|
+
start: offer.start,
|
|
44
|
+
expiry: offer.expiry,
|
|
45
|
+
tick: offer.tick,
|
|
46
|
+
group: offer.group || ZERO_BYTES32,
|
|
47
|
+
callback: offer.callback || ZERO_ADDRESS,
|
|
48
|
+
callback_data: offer.callback_data || '0x',
|
|
49
|
+
receiver_if_maker_is_seller: offer.receiver_if_maker_is_seller || ZERO_ADDRESS,
|
|
50
|
+
ratifier: offer.ratifier || ZERO_ADDRESS,
|
|
51
|
+
reduce_only: offer.reduce_only,
|
|
52
|
+
max_units: offer.max_units,
|
|
53
|
+
max_assets: offer.max_assets,
|
|
54
|
+
continuous_fee_cap: offer.continuous_fee_cap,
|
|
55
|
+
});
|
|
56
|
+
export const tenorOfferFillToApiFill = (fill) => ({
|
|
57
|
+
units: fill.units,
|
|
58
|
+
offer: tenorOfferToApiOffer(fill.offer),
|
|
59
|
+
ratifier_data: fill.offer.ratifier_data || '0x',
|
|
60
|
+
market_id: '',
|
|
61
|
+
});
|
|
62
|
+
const tenorBookBuckets = (side) => {
|
|
63
|
+
if (!side)
|
|
64
|
+
return [];
|
|
65
|
+
if (Array.isArray(side))
|
|
66
|
+
return side;
|
|
67
|
+
return side.buckets || [];
|
|
68
|
+
};
|
|
69
|
+
/** The levels resting on the Tenor side a taker of `side` fills, in raw loan-token base units. */
|
|
70
|
+
export const parseTenorBookSide = (json, side) => tenorBookBuckets(json[tenorBookKeyFor(side)])
|
|
71
|
+
.map((bucket) => ({
|
|
72
|
+
rate: tenorBookRateToApyPercent(bucket.rate),
|
|
73
|
+
liquidityRaw: new Dec(bucket.liquidity || 0).toFixed(0),
|
|
74
|
+
}))
|
|
75
|
+
.filter((offer) => new Dec(offer.liquidityRaw).gt(0));
|
|
76
|
+
export const parseTenorOrderBook = (json, side, loanSymbol) => {
|
|
77
|
+
const offers = parseTenorBookSide(json, side).map((offer) => ({
|
|
78
|
+
rate: offer.rate,
|
|
79
|
+
liquidity: assetAmountInEth(offer.liquidityRaw, loanSymbol),
|
|
80
|
+
}));
|
|
81
|
+
return buildMidnightParsedBook(offers, side);
|
|
82
|
+
};
|
|
83
|
+
const fetchTenorBook = (marketId, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
84
|
+
const res = yield fetch(`${TENOR_ORDERBOOK_URL}/${marketId}?chain_id=${network}`, { signal: AbortSignal.timeout(TENOR_TIMEOUT_MS) });
|
|
85
|
+
if (!res.ok)
|
|
86
|
+
throw new Error(`Midnight book request failed for ${marketId} (${res.status})`);
|
|
87
|
+
return res.json();
|
|
88
|
+
});
|
|
89
|
+
export const getTenorMarketBook = (market_1, network_1, ...args_1) => __awaiter(void 0, [market_1, network_1, ...args_1], void 0, function* (market, network, side = 'bids') {
|
|
90
|
+
const loanSymbol = getAssetInfoByAddress(market.loanToken, network).symbol;
|
|
91
|
+
return parseTenorOrderBook(yield fetchTenorBook(market.marketId, network), side, loanSymbol);
|
|
92
|
+
});
|
|
93
|
+
const tenorBookAvailableAssetsRaw = (marketId, network, side) => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
|
+
try {
|
|
95
|
+
const json = yield fetchTenorBook(marketId, network);
|
|
96
|
+
return parseTenorBookSide(json, side).reduce((sum, offer) => sum.add(offer.liquidityRaw), new Dec(0)).toFixed(0);
|
|
97
|
+
}
|
|
98
|
+
catch (_a) {
|
|
99
|
+
return '0';
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const fetchTenorQuote = (_a) => __awaiter(void 0, [_a], void 0, function* ({ marketId, side, assets, units, taker, network = NetworkNumber.Base, }) {
|
|
103
|
+
var _b;
|
|
104
|
+
const hasAssets = assets !== undefined && assets !== null;
|
|
105
|
+
const hasUnits = units !== undefined && units !== null;
|
|
106
|
+
if (hasAssets === hasUnits) {
|
|
107
|
+
throw new Error(tenorQuoteError('Either assets or units must be provided'));
|
|
108
|
+
}
|
|
109
|
+
if (side !== 'asks' && side !== 'bids') {
|
|
110
|
+
throw new Error(tenorQuoteError(`Unsupported Tenor quote side: ${side}`));
|
|
111
|
+
}
|
|
112
|
+
const isBuy = side === 'asks';
|
|
113
|
+
const amount = (hasAssets ? assets : units);
|
|
114
|
+
const res = yield fetch(TENOR_QUOTES_URL, {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
117
|
+
body: JSON.stringify({
|
|
118
|
+
market_hashes: [marketId],
|
|
119
|
+
amount,
|
|
120
|
+
chain_id: network,
|
|
121
|
+
is_buy: isBuy,
|
|
122
|
+
is_exact_in: hasAssets ? isBuy : !isBuy,
|
|
123
|
+
limit_rate: null,
|
|
124
|
+
valid_for: null,
|
|
125
|
+
algorithm: TENOR_ALGORITHM,
|
|
126
|
+
allow_partial: false,
|
|
127
|
+
taker: taker || ZERO_ADDRESS,
|
|
128
|
+
}),
|
|
129
|
+
signal: AbortSignal.timeout(TENOR_TIMEOUT_MS),
|
|
130
|
+
});
|
|
131
|
+
const result = yield res.json().catch(() => ({}));
|
|
132
|
+
if (!res.ok) {
|
|
133
|
+
throw new Error(tenorQuoteError(result.error || result.message || `Tenor quote request failed with status ${res.status}`));
|
|
134
|
+
}
|
|
135
|
+
const payload = ((_b = result.quotes) === null || _b === void 0 ? void 0 : _b[0]) || result;
|
|
136
|
+
const quotedUnits = new Dec(payload.units || result.units || 0);
|
|
137
|
+
const offers = payload.offers || result.offers || [];
|
|
138
|
+
// A book that can't fill the size comes back 200 with everything zeroed rather than as an error.
|
|
139
|
+
if (quotedUnits.lte(0) || offers.length === 0) {
|
|
140
|
+
throw new Error(tenorQuoteError('INSUFFICIENT_LIQUIDITY'));
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
units: quotedUnits.toFixed(0),
|
|
144
|
+
buyerAssets: (payload.buyer_assets || result.buyer_assets || '0').toString(),
|
|
145
|
+
offerFills: offers.map(tenorOfferFillToApiFill),
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
const TENOR_NO_AVAILABLE_UNITS = '0';
|
|
149
|
+
/**
|
|
150
|
+
* Tenor's router takes no slippage of its own — it prices the fill and hands back the offers. `slippagePercent`
|
|
151
|
+
* is therefore accepted only to keep the signature aligned with the Morpho-hosted quote that `index.ts`
|
|
152
|
+
* forwards to positionally; the guard comes from `rateSlippagePercent` via `midnightBoundPrice`.
|
|
153
|
+
*/
|
|
154
|
+
export const getTenorBorrowQuote = (marketId_1, assetsRaw_1, slippagePercent_1, maturity_1, maxBorrowRate_1, taker_1, rateSlippagePercent_1, ...args_1) => __awaiter(void 0, [marketId_1, assetsRaw_1, slippagePercent_1, maturity_1, maxBorrowRate_1, taker_1, rateSlippagePercent_1, ...args_1], void 0, function* (marketId, assetsRaw, slippagePercent, maturity, maxBorrowRate, taker, rateSlippagePercent, network = NetworkNumber.Base) {
|
|
155
|
+
if (!isTenorMidnightMarket(marketId)) {
|
|
156
|
+
throw new Error(tenorQuoteError(`Not a Tenor Midnight market: ${marketId}`));
|
|
157
|
+
}
|
|
158
|
+
const [quote, availableAssets] = yield Promise.all([
|
|
159
|
+
fetchTenorQuote({
|
|
160
|
+
marketId, side: 'bids', assets: assetsRaw, taker, network,
|
|
161
|
+
}),
|
|
162
|
+
tenorBookAvailableAssetsRaw(marketId, network, 'bids'),
|
|
163
|
+
]);
|
|
164
|
+
const ttmDays = midnightTimeToMaturityDays(maturity);
|
|
165
|
+
const bestPrice = tenorFillPrice(assetsRaw, quote.units);
|
|
166
|
+
const estBorrowRate = midnightApyFromPrice(bestPrice, ttmDays);
|
|
167
|
+
const capPrice = midnightBoundPrice(estBorrowRate, ttmDays, 'ceiling', maxBorrowRate, rateSlippagePercent);
|
|
168
|
+
const maxRate = midnightApyFromPrice(capPrice, ttmDays);
|
|
169
|
+
const maxUnits = new Dec(capPrice).lte(0) ? '0' : new Dec(assetsRaw).div(capPrice).toFixed(0);
|
|
170
|
+
return {
|
|
171
|
+
bestPrice,
|
|
172
|
+
worstPrice: capPrice,
|
|
173
|
+
estBorrowRate,
|
|
174
|
+
maxRate,
|
|
175
|
+
newUnits: quote.units,
|
|
176
|
+
maxUnits,
|
|
177
|
+
availableAssets,
|
|
178
|
+
availableUnits: TENOR_NO_AVAILABLE_UNITS,
|
|
179
|
+
takeableOffers: quote.offerFills,
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
export const getTenorPaybackQuote = (marketId_1, assetsRaw_1, slippagePercent_1, maturity_1, minPaybackRate_1, taker_1, rateSlippagePercent_1, ...args_1) => __awaiter(void 0, [marketId_1, assetsRaw_1, slippagePercent_1, maturity_1, minPaybackRate_1, taker_1, rateSlippagePercent_1, ...args_1], void 0, function* (marketId, assetsRaw, slippagePercent, maturity, minPaybackRate, taker, rateSlippagePercent, network = NetworkNumber.Base) {
|
|
183
|
+
if (!isTenorMidnightMarket(marketId)) {
|
|
184
|
+
throw new Error(tenorQuoteError(`Not a Tenor Midnight market: ${marketId}`));
|
|
185
|
+
}
|
|
186
|
+
const [quote, availableAssets] = yield Promise.all([
|
|
187
|
+
fetchTenorQuote({
|
|
188
|
+
marketId, side: 'asks', assets: assetsRaw, taker, network,
|
|
189
|
+
}),
|
|
190
|
+
tenorBookAvailableAssetsRaw(marketId, network, 'asks'),
|
|
191
|
+
]);
|
|
192
|
+
const ttmDays = midnightTimeToMaturityDays(maturity);
|
|
193
|
+
const bestPrice = tenorFillPrice(assetsRaw, quote.units);
|
|
194
|
+
const estPaybackRate = midnightApyFromPrice(bestPrice, ttmDays);
|
|
195
|
+
const capPrice = midnightBoundPrice(estPaybackRate, ttmDays, 'floor', minPaybackRate, rateSlippagePercent);
|
|
196
|
+
const minRate = midnightApyFromPrice(capPrice, ttmDays);
|
|
197
|
+
const minUnits = new Dec(capPrice).lte(0) ? '0' : new Dec(assetsRaw).div(capPrice).toFixed(0, Dec.ROUND_DOWN);
|
|
198
|
+
return {
|
|
199
|
+
bestPrice,
|
|
200
|
+
worstPrice: capPrice,
|
|
201
|
+
estPaybackRate,
|
|
202
|
+
minRate,
|
|
203
|
+
newUnits: quote.units,
|
|
204
|
+
minUnits,
|
|
205
|
+
availableAssets,
|
|
206
|
+
availableUnits: TENOR_NO_AVAILABLE_UNITS,
|
|
207
|
+
takeableOffers: quote.offerFills,
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
export const getTenorPaybackUnitsQuote = (marketId_1, unitsRaw_1, slippagePercent_1, maturity_1, minPaybackRate_1, taker_1, rateSlippagePercent_1, ...args_1) => __awaiter(void 0, [marketId_1, unitsRaw_1, slippagePercent_1, maturity_1, minPaybackRate_1, taker_1, rateSlippagePercent_1, ...args_1], void 0, function* (marketId, unitsRaw, slippagePercent, maturity, minPaybackRate, taker, rateSlippagePercent, network = NetworkNumber.Base) {
|
|
211
|
+
if (!isTenorMidnightMarket(marketId)) {
|
|
212
|
+
throw new Error(tenorQuoteError(`Not a Tenor Midnight market: ${marketId}`));
|
|
213
|
+
}
|
|
214
|
+
const [quote, availableAssets] = yield Promise.all([
|
|
215
|
+
fetchTenorQuote({
|
|
216
|
+
marketId, side: 'asks', units: unitsRaw, taker, network,
|
|
217
|
+
}),
|
|
218
|
+
tenorBookAvailableAssetsRaw(marketId, network, 'asks'),
|
|
219
|
+
]);
|
|
220
|
+
const ttmDays = midnightTimeToMaturityDays(maturity);
|
|
221
|
+
const newAssets = quote.buyerAssets;
|
|
222
|
+
const bestPrice = tenorFillPrice(newAssets, unitsRaw);
|
|
223
|
+
const estPaybackRate = midnightApyFromPrice(bestPrice, ttmDays);
|
|
224
|
+
const capPrice = midnightBoundPrice(estPaybackRate, ttmDays, 'floor', minPaybackRate, rateSlippagePercent);
|
|
225
|
+
const minRate = midnightApyFromPrice(capPrice, ttmDays);
|
|
226
|
+
const maxAssets = new Dec(unitsRaw).mul(capPrice).toFixed(0, Dec.ROUND_UP);
|
|
227
|
+
return {
|
|
228
|
+
bestPrice,
|
|
229
|
+
worstPrice: capPrice,
|
|
230
|
+
estPaybackRate,
|
|
231
|
+
minRate,
|
|
232
|
+
newAssets,
|
|
233
|
+
maxAssets,
|
|
234
|
+
availableAssets,
|
|
235
|
+
availableUnits: TENOR_NO_AVAILABLE_UNITS,
|
|
236
|
+
takeableOffers: quote.offerFills,
|
|
237
|
+
};
|
|
238
|
+
});
|
package/esm/index.d.ts
CHANGED
|
@@ -16,9 +16,10 @@ import * as markets from './markets';
|
|
|
16
16
|
import * as helpers from './helpers';
|
|
17
17
|
import * as exchange from './exchange';
|
|
18
18
|
import * as morphoBlue from './morphoBlue';
|
|
19
|
+
import * as morphoMidnight from './morphoMidnight';
|
|
19
20
|
import * as llamaLend from './llamaLend';
|
|
20
21
|
import * as portfolio from './portfolio';
|
|
21
22
|
import * as claiming from './claiming';
|
|
22
23
|
import * as savings from './savings';
|
|
23
24
|
export * from './types';
|
|
24
|
-
export { aaveV2, aaveV3, aaveV4, compoundV2, compoundV3, spark, curveUsd, liquity, liquityV2, maker, exchange, staking, moneymarket, markets, helpers, morphoBlue, llamaLend, fluid, portfolio, claiming, savings, };
|
|
25
|
+
export { aaveV2, aaveV3, aaveV4, compoundV2, compoundV3, spark, curveUsd, liquity, liquityV2, maker, exchange, staking, moneymarket, markets, helpers, morphoBlue, morphoMidnight, llamaLend, fluid, portfolio, claiming, savings, };
|
package/esm/index.js
CHANGED
|
@@ -16,9 +16,10 @@ import * as markets from './markets';
|
|
|
16
16
|
import * as helpers from './helpers';
|
|
17
17
|
import * as exchange from './exchange';
|
|
18
18
|
import * as morphoBlue from './morphoBlue';
|
|
19
|
+
import * as morphoMidnight from './morphoMidnight';
|
|
19
20
|
import * as llamaLend from './llamaLend';
|
|
20
21
|
import * as portfolio from './portfolio';
|
|
21
22
|
import * as claiming from './claiming';
|
|
22
23
|
import * as savings from './savings';
|
|
23
24
|
export * from './types';
|
|
24
|
-
export { aaveV2, aaveV3, aaveV4, compoundV2, compoundV3, spark, curveUsd, liquity, liquityV2, maker, exchange, staking, moneymarket, markets, helpers, morphoBlue, llamaLend, fluid, portfolio, claiming, savings, };
|
|
25
|
+
export { aaveV2, aaveV3, aaveV4, compoundV2, compoundV3, spark, curveUsd, liquity, liquityV2, maker, exchange, staking, moneymarket, markets, helpers, morphoBlue, morphoMidnight, llamaLend, fluid, portfolio, claiming, savings, };
|
package/esm/markets/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { CompoundMarkets, compoundV2CollateralAssets, v3ETHCollAssets, v3USDbCCo
|
|
|
3
3
|
export { SparkMarkets } from './spark';
|
|
4
4
|
export { CrvUsdMarkets } from './curveUsd';
|
|
5
5
|
export { MorphoBlueMarkets, findMorphoBlueMarket } from './morphoBlue';
|
|
6
|
+
export { MorphoMidnightMarkets, findMorphoMidnightMarket, isTenorMidnightMarket, morphoMidnightMarketCollateralParams, } from './morphoMidnight';
|
|
6
7
|
export { LlamaLendMarkets } from './llamaLend';
|
|
7
8
|
export { LiquityV2Markets, findLiquityV2MarketByAddress } from './liquityV2';
|
|
8
9
|
export { FluidMarkets, getFluidVersionsDataForNetwork, getFluidMarketInfoById, getFTokenAddress, getFluidMarketInfoByAddress, } from './fluid';
|
package/esm/markets/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { CompoundMarkets, compoundV2CollateralAssets, v3ETHCollAssets, v3USDbCCo
|
|
|
3
3
|
export { SparkMarkets } from './spark';
|
|
4
4
|
export { CrvUsdMarkets } from './curveUsd';
|
|
5
5
|
export { MorphoBlueMarkets, findMorphoBlueMarket } from './morphoBlue';
|
|
6
|
+
export { MorphoMidnightMarkets, findMorphoMidnightMarket, isTenorMidnightMarket, morphoMidnightMarketCollateralParams, } from './morphoMidnight';
|
|
6
7
|
export { LlamaLendMarkets } from './llamaLend';
|
|
7
8
|
export { LiquityV2Markets, findLiquityV2MarketByAddress } from './liquityV2';
|
|
8
9
|
export { FluidMarkets, getFluidVersionsDataForNetwork, getFluidMarketInfoById, getFTokenAddress, getFluidMarketInfoByAddress, } from './fluid';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { MorphoMidnightCollateralParams, MorphoMidnightMarketData, NetworkNumber } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Morpho Midnight core contract on Base. Every Midnight market trades against this one, whoever curates
|
|
4
|
+
* its order book — it is part of the market struct the id is hashed from, and it is what offer tuples
|
|
5
|
+
* encode for `Midnight.take`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MIDNIGHT_BASE: "0xAdedD8ab6dE832766Fedf0FaC4992E5C4D3EA18A";
|
|
8
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20260731: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
9
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20260828: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
10
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20260925: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
11
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20261030: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
12
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20261127: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
13
|
+
export declare const MORPHO_MIDNIGHT_CBBTC_USDC_860_20261225: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
14
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBBTC_USDC_860_20260827: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
15
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBBTC_USDC_860_20260924: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
16
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBBTC_USDC_860_20261022: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
17
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBBTC_USDC_860_20261119: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
18
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBBTC_USDC_860_20261217: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
19
|
+
export declare const MORPHO_MIDNIGHT_TENOR_WETH_USDC_860_20260827: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
20
|
+
export declare const MORPHO_MIDNIGHT_TENOR_WETH_USDC_860_20260924: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
21
|
+
export declare const MORPHO_MIDNIGHT_TENOR_WETH_USDC_860_20261022: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
22
|
+
export declare const MORPHO_MIDNIGHT_TENOR_WETH_USDC_860_20261119: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
23
|
+
export declare const MORPHO_MIDNIGHT_TENOR_WETH_USDC_860_20261217: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
24
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBETH_WETH_945_20260827: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
25
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBETH_WETH_945_20260924: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
26
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBETH_WETH_945_20261022: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
27
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBETH_WETH_945_20261119: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
28
|
+
export declare const MORPHO_MIDNIGHT_TENOR_CBETH_WETH_945_20261217: (networkId?: NetworkNumber) => MorphoMidnightMarketData;
|
|
29
|
+
export declare const MorphoMidnightMarkets: (networkId: NetworkNumber) => {
|
|
30
|
+
readonly morphomidnightcbbtcusdc_860_20260731_base: MorphoMidnightMarketData;
|
|
31
|
+
readonly morphomidnightcbbtcusdc_860_20260828_base: MorphoMidnightMarketData;
|
|
32
|
+
readonly morphomidnightcbbtcusdc_860_20260925_base: MorphoMidnightMarketData;
|
|
33
|
+
readonly morphomidnightcbbtcusdc_860_20261030_base: MorphoMidnightMarketData;
|
|
34
|
+
readonly morphomidnightcbbtcusdc_860_20261127_base: MorphoMidnightMarketData;
|
|
35
|
+
readonly morphomidnightcbbtcusdc_860_20261225_base: MorphoMidnightMarketData;
|
|
36
|
+
readonly morphomidnighttenorcbbtcusdc_20260827_base: MorphoMidnightMarketData;
|
|
37
|
+
readonly morphomidnighttenorcbbtcusdc_20260924_base: MorphoMidnightMarketData;
|
|
38
|
+
readonly morphomidnighttenorcbbtcusdc_20261022_base: MorphoMidnightMarketData;
|
|
39
|
+
readonly morphomidnighttenorcbbtcusdc_20261119_base: MorphoMidnightMarketData;
|
|
40
|
+
readonly morphomidnighttenorcbbtcusdc_20261217_base: MorphoMidnightMarketData;
|
|
41
|
+
readonly morphomidnighttenorwethusdc_20260827_base: MorphoMidnightMarketData;
|
|
42
|
+
readonly morphomidnighttenorwethusdc_20260924_base: MorphoMidnightMarketData;
|
|
43
|
+
readonly morphomidnighttenorwethusdc_20261022_base: MorphoMidnightMarketData;
|
|
44
|
+
readonly morphomidnighttenorwethusdc_20261119_base: MorphoMidnightMarketData;
|
|
45
|
+
readonly morphomidnighttenorwethusdc_20261217_base: MorphoMidnightMarketData;
|
|
46
|
+
readonly morphomidnighttenorcbethweth_20260827_base: MorphoMidnightMarketData;
|
|
47
|
+
readonly morphomidnighttenorcbethweth_20260924_base: MorphoMidnightMarketData;
|
|
48
|
+
readonly morphomidnighttenorcbethweth_20261022_base: MorphoMidnightMarketData;
|
|
49
|
+
readonly morphomidnighttenorcbethweth_20261119_base: MorphoMidnightMarketData;
|
|
50
|
+
readonly morphomidnighttenorcbethweth_20261217_base: MorphoMidnightMarketData;
|
|
51
|
+
};
|
|
52
|
+
export declare const isTenorMidnightMarket: (market: Pick<MorphoMidnightMarketData, "curator"> | string) => boolean;
|
|
53
|
+
export declare const findMorphoMidnightMarket: (marketId: string, network?: NetworkNumber) => MorphoMidnightMarketData | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* The market's collateral set as the chain knows it: the listed collaterals followed by the curator's
|
|
56
|
+
* hidden ones. This — not `collaterals` — is what a `Market` struct takes, since the market id is the hash
|
|
57
|
+
* of that struct. Anything assembling one for a contract call goes through here so it can't quietly build
|
|
58
|
+
* a market of its own instead.
|
|
59
|
+
*/
|
|
60
|
+
export declare const morphoMidnightMarketCollateralParams: (market: Pick<MorphoMidnightMarketData, "collaterals" | "hiddenCollaterals">) => MorphoMidnightCollateralParams[];
|