origin-morpho-utils 0.1.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/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ import {
2
+ MORPHO_BLUE_ADDRESSES,
3
+ computeDepositImpact,
4
+ computeDepositImpactRpc,
5
+ computeWithdrawalImpact,
6
+ computeWithdrawalImpactRpc,
7
+ erc20Abi,
8
+ fetchVaultApy,
9
+ fetchVaultApyViem,
10
+ fetchVaultMarkets,
11
+ fetchVaultMarketsViem,
12
+ findMaxDeposit,
13
+ findMaxDepositAmount,
14
+ findMaxDepositRpc,
15
+ findMaxWithdrawal,
16
+ findMaxWithdrawalAmount,
17
+ findMaxWithdrawalRpc,
18
+ getMorphoBlueAddress,
19
+ irmAdaptiveCurveAbi,
20
+ metaMorphoAbi,
21
+ morphoAbi
22
+ } from "./chunk-M43IOBUD.js";
23
+ import {
24
+ estimateMarketApy,
25
+ mergeMarketDetails,
26
+ simulateDeposit,
27
+ simulateWithdrawal,
28
+ weightedVaultApy,
29
+ weightedVaultApyDetailed
30
+ } from "./chunk-K2ZKPGSF.js";
31
+ export {
32
+ MORPHO_BLUE_ADDRESSES,
33
+ computeDepositImpact,
34
+ computeDepositImpactRpc,
35
+ computeWithdrawalImpact,
36
+ computeWithdrawalImpactRpc,
37
+ erc20Abi,
38
+ estimateMarketApy,
39
+ fetchVaultApy,
40
+ fetchVaultApyViem,
41
+ fetchVaultMarkets,
42
+ fetchVaultMarketsViem,
43
+ findMaxDeposit,
44
+ findMaxDepositAmount,
45
+ findMaxDepositRpc,
46
+ findMaxWithdrawal,
47
+ findMaxWithdrawalAmount,
48
+ findMaxWithdrawalRpc,
49
+ getMorphoBlueAddress,
50
+ irmAdaptiveCurveAbi,
51
+ mergeMarketDetails,
52
+ metaMorphoAbi,
53
+ morphoAbi,
54
+ simulateDeposit,
55
+ simulateWithdrawal,
56
+ weightedVaultApy,
57
+ weightedVaultApyDetailed
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,164 @@
1
+ interface MarketForApy {
2
+ marketId: string;
3
+ name?: string;
4
+ loanToken?: string;
5
+ collateralToken?: string;
6
+ totalSupplyAssets: bigint;
7
+ totalBorrowAssets: bigint;
8
+ fee: bigint;
9
+ vaultSupplyAssets: bigint;
10
+ rateAtTarget: bigint;
11
+ decimals: number;
12
+ inSupplyQueue: boolean;
13
+ inWithdrawQueue: boolean;
14
+ withdrawQueueIndex: number;
15
+ cap: bigint;
16
+ }
17
+ interface VaultFetchResult {
18
+ markets: MarketForApy[];
19
+ idleAssets: bigint;
20
+ }
21
+ interface VaultApyResult {
22
+ apy: number;
23
+ markets: MarketForApy[];
24
+ idleAssets: bigint;
25
+ marketDetails: MarketApyDetail[];
26
+ }
27
+ interface MarketApyDetail {
28
+ marketId: string;
29
+ name?: string;
30
+ supplyApy: number;
31
+ borrowApy: number;
32
+ utilization: number;
33
+ allocationPct: number;
34
+ vaultSupplyAssets: bigint;
35
+ }
36
+ interface VaultApyDetailed {
37
+ apy: number;
38
+ markets: MarketApyDetail[];
39
+ }
40
+ interface MarketApySnapshot {
41
+ supplyApy: number;
42
+ borrowApy: number;
43
+ utilization: number;
44
+ allocationPct: number;
45
+ vaultSupplyAssets: bigint;
46
+ }
47
+ interface MarketImpactDetail {
48
+ marketId: string;
49
+ name?: string;
50
+ current: MarketApySnapshot;
51
+ simulated: MarketApySnapshot;
52
+ }
53
+ interface DepositImpactResult {
54
+ currentApy: number;
55
+ newApy: number;
56
+ impact: number;
57
+ impactBps: number;
58
+ markets: MarketImpactDetail[];
59
+ }
60
+ interface WithdrawalImpactResult {
61
+ currentApy: number;
62
+ newApy: number;
63
+ impact: number;
64
+ impactBps: number;
65
+ isPartial: boolean;
66
+ withdrawableAmount: string;
67
+ markets: MarketImpactDetail[];
68
+ }
69
+ interface FindMaxDepositResult {
70
+ amount: bigint;
71
+ maxPossibleAmount: bigint;
72
+ isMaxAmount: boolean;
73
+ isCapped: boolean;
74
+ impact: DepositImpactResult;
75
+ }
76
+ interface FindMaxWithdrawalResult {
77
+ amount: bigint;
78
+ maxPossibleAmount: bigint;
79
+ isMaxAmount: boolean;
80
+ isCapped: boolean;
81
+ impact: WithdrawalImpactResult;
82
+ }
83
+ /** State passed to custom constraint callback during find-max binary search. */
84
+ interface FindMaxConstraintState {
85
+ amount: bigint;
86
+ currentApy: number;
87
+ simulatedApy: number;
88
+ impactBps: number;
89
+ markets: MarketImpactDetail[];
90
+ /** true if withdrawal was liquidity-constrained (withdrawal only) */
91
+ isPartial?: boolean;
92
+ /** Actual removable amount (withdrawal only) */
93
+ withdrawableAmount?: bigint;
94
+ }
95
+ /**
96
+ * Custom constraint for find-max binary search. Must be monotonic in amount:
97
+ * if amount X fails, all amounts > X must also fail.
98
+ *
99
+ * Returns true if the amount is acceptable, false if it exceeds the constraint.
100
+ * Can be async (e.g. to fetch external data).
101
+ */
102
+ type FindMaxConstraint = (state: FindMaxConstraintState) => boolean | Promise<boolean>;
103
+
104
+ /**
105
+ * Pure APY math for Morpho Blue / MetaMorpho vaults.
106
+ * No external dependencies — fully unit-testable.
107
+ */
108
+
109
+ /**
110
+ * Compute supply and borrow APY for a single Morpho Blue market.
111
+ *
112
+ * @param depositAmt - Extra supply to simulate (0 for current rate). In token units (float).
113
+ * @param totalSupply - Current total supply assets. In token units (float).
114
+ * @param totalBorrows - Current total borrow assets. In token units (float).
115
+ * @param fee - Protocol fee, WAD-scaled (raw bigint converted to number before passing).
116
+ * @param rateAtTarget - Per-second borrow rate at 90% utilisation, WAD-scaled (raw int256 as number).
117
+ */
118
+ declare function estimateMarketApy(depositAmt: number, totalSupply: number, totalBorrows: number, fee: number, rateAtTarget: number): {
119
+ supplyApy: number;
120
+ borrowApy: number;
121
+ };
122
+ /**
123
+ * Compute the position-weighted vault APY across all markets,
124
+ * returning per-market details (supplyApy, borrowApy, utilization, allocation).
125
+ *
126
+ * @param markets - All markets (both supply + withdraw queues).
127
+ * @param depositSim - Optional map of { marketId -> extra bigint supply } for deposit simulation.
128
+ * @param withdrawalSim - Optional map of { marketId -> bigint withdrawn } for withdrawal simulation.
129
+ */
130
+ declare function weightedVaultApyDetailed(markets: MarketForApy[], depositSim?: Record<string, bigint>, withdrawalSim?: Record<string, bigint>): VaultApyDetailed;
131
+ /**
132
+ * Compute the position-weighted vault APY across all markets.
133
+ *
134
+ * @param markets - All markets (both supply + withdraw queues).
135
+ * @param depositSim - Optional map of { marketId -> extra bigint supply } for deposit simulation.
136
+ * @param withdrawalSim - Optional map of { marketId -> bigint withdrawn } for withdrawal simulation.
137
+ */
138
+ declare function weightedVaultApy(markets: MarketForApy[], depositSim?: Record<string, bigint>, withdrawalSim?: Record<string, bigint>): number;
139
+ /**
140
+ * Simulate how a deposit flows through the supply queue and build a depositSim map.
141
+ *
142
+ * Deposits fill each supply-queue market up to its cap, then spill to the next.
143
+ * Returns a Record<marketId, bigint> representing extra supply per market.
144
+ */
145
+ declare function simulateDeposit(markets: MarketForApy[], depositAmount: bigint): Record<string, bigint>;
146
+ /**
147
+ * Simulate how a withdrawal flows through the withdraw queue.
148
+ *
149
+ * Idle assets are consumed first (no market APY impact), then each withdraw-queue
150
+ * market is drained up to min(vaultSupplyAssets, available liquidity).
151
+ * Returns positive values representing amounts removed per market.
152
+ */
153
+ declare function simulateWithdrawal(markets: MarketForApy[], withdrawAmount: bigint, idleAssets: bigint): {
154
+ sim: Record<string, bigint>;
155
+ withdrawable: bigint;
156
+ remaining: bigint;
157
+ };
158
+ /**
159
+ * Merge two MarketApyDetail arrays (current vs simulated) into a single
160
+ * array of MarketImpactDetail with nested `current` and `simulated` snapshots.
161
+ */
162
+ declare function mergeMarketDetails(current: MarketApyDetail[], simulated: MarketApyDetail[]): MarketImpactDetail[];
163
+
164
+ export { type DepositImpactResult as D, type FindMaxConstraint as F, type MarketForApy as M, type VaultApyResult as V, type WithdrawalImpactResult as W, type VaultFetchResult as a, type FindMaxDepositResult as b, type FindMaxWithdrawalResult as c, type FindMaxConstraintState as d, type MarketApyDetail as e, type MarketApySnapshot as f, type MarketImpactDetail as g, type VaultApyDetailed as h, estimateMarketApy as i, simulateWithdrawal as j, weightedVaultApyDetailed as k, mergeMarketDetails as m, simulateDeposit as s, weightedVaultApy as w };
@@ -0,0 +1,164 @@
1
+ interface MarketForApy {
2
+ marketId: string;
3
+ name?: string;
4
+ loanToken?: string;
5
+ collateralToken?: string;
6
+ totalSupplyAssets: bigint;
7
+ totalBorrowAssets: bigint;
8
+ fee: bigint;
9
+ vaultSupplyAssets: bigint;
10
+ rateAtTarget: bigint;
11
+ decimals: number;
12
+ inSupplyQueue: boolean;
13
+ inWithdrawQueue: boolean;
14
+ withdrawQueueIndex: number;
15
+ cap: bigint;
16
+ }
17
+ interface VaultFetchResult {
18
+ markets: MarketForApy[];
19
+ idleAssets: bigint;
20
+ }
21
+ interface VaultApyResult {
22
+ apy: number;
23
+ markets: MarketForApy[];
24
+ idleAssets: bigint;
25
+ marketDetails: MarketApyDetail[];
26
+ }
27
+ interface MarketApyDetail {
28
+ marketId: string;
29
+ name?: string;
30
+ supplyApy: number;
31
+ borrowApy: number;
32
+ utilization: number;
33
+ allocationPct: number;
34
+ vaultSupplyAssets: bigint;
35
+ }
36
+ interface VaultApyDetailed {
37
+ apy: number;
38
+ markets: MarketApyDetail[];
39
+ }
40
+ interface MarketApySnapshot {
41
+ supplyApy: number;
42
+ borrowApy: number;
43
+ utilization: number;
44
+ allocationPct: number;
45
+ vaultSupplyAssets: bigint;
46
+ }
47
+ interface MarketImpactDetail {
48
+ marketId: string;
49
+ name?: string;
50
+ current: MarketApySnapshot;
51
+ simulated: MarketApySnapshot;
52
+ }
53
+ interface DepositImpactResult {
54
+ currentApy: number;
55
+ newApy: number;
56
+ impact: number;
57
+ impactBps: number;
58
+ markets: MarketImpactDetail[];
59
+ }
60
+ interface WithdrawalImpactResult {
61
+ currentApy: number;
62
+ newApy: number;
63
+ impact: number;
64
+ impactBps: number;
65
+ isPartial: boolean;
66
+ withdrawableAmount: string;
67
+ markets: MarketImpactDetail[];
68
+ }
69
+ interface FindMaxDepositResult {
70
+ amount: bigint;
71
+ maxPossibleAmount: bigint;
72
+ isMaxAmount: boolean;
73
+ isCapped: boolean;
74
+ impact: DepositImpactResult;
75
+ }
76
+ interface FindMaxWithdrawalResult {
77
+ amount: bigint;
78
+ maxPossibleAmount: bigint;
79
+ isMaxAmount: boolean;
80
+ isCapped: boolean;
81
+ impact: WithdrawalImpactResult;
82
+ }
83
+ /** State passed to custom constraint callback during find-max binary search. */
84
+ interface FindMaxConstraintState {
85
+ amount: bigint;
86
+ currentApy: number;
87
+ simulatedApy: number;
88
+ impactBps: number;
89
+ markets: MarketImpactDetail[];
90
+ /** true if withdrawal was liquidity-constrained (withdrawal only) */
91
+ isPartial?: boolean;
92
+ /** Actual removable amount (withdrawal only) */
93
+ withdrawableAmount?: bigint;
94
+ }
95
+ /**
96
+ * Custom constraint for find-max binary search. Must be monotonic in amount:
97
+ * if amount X fails, all amounts > X must also fail.
98
+ *
99
+ * Returns true if the amount is acceptable, false if it exceeds the constraint.
100
+ * Can be async (e.g. to fetch external data).
101
+ */
102
+ type FindMaxConstraint = (state: FindMaxConstraintState) => boolean | Promise<boolean>;
103
+
104
+ /**
105
+ * Pure APY math for Morpho Blue / MetaMorpho vaults.
106
+ * No external dependencies — fully unit-testable.
107
+ */
108
+
109
+ /**
110
+ * Compute supply and borrow APY for a single Morpho Blue market.
111
+ *
112
+ * @param depositAmt - Extra supply to simulate (0 for current rate). In token units (float).
113
+ * @param totalSupply - Current total supply assets. In token units (float).
114
+ * @param totalBorrows - Current total borrow assets. In token units (float).
115
+ * @param fee - Protocol fee, WAD-scaled (raw bigint converted to number before passing).
116
+ * @param rateAtTarget - Per-second borrow rate at 90% utilisation, WAD-scaled (raw int256 as number).
117
+ */
118
+ declare function estimateMarketApy(depositAmt: number, totalSupply: number, totalBorrows: number, fee: number, rateAtTarget: number): {
119
+ supplyApy: number;
120
+ borrowApy: number;
121
+ };
122
+ /**
123
+ * Compute the position-weighted vault APY across all markets,
124
+ * returning per-market details (supplyApy, borrowApy, utilization, allocation).
125
+ *
126
+ * @param markets - All markets (both supply + withdraw queues).
127
+ * @param depositSim - Optional map of { marketId -> extra bigint supply } for deposit simulation.
128
+ * @param withdrawalSim - Optional map of { marketId -> bigint withdrawn } for withdrawal simulation.
129
+ */
130
+ declare function weightedVaultApyDetailed(markets: MarketForApy[], depositSim?: Record<string, bigint>, withdrawalSim?: Record<string, bigint>): VaultApyDetailed;
131
+ /**
132
+ * Compute the position-weighted vault APY across all markets.
133
+ *
134
+ * @param markets - All markets (both supply + withdraw queues).
135
+ * @param depositSim - Optional map of { marketId -> extra bigint supply } for deposit simulation.
136
+ * @param withdrawalSim - Optional map of { marketId -> bigint withdrawn } for withdrawal simulation.
137
+ */
138
+ declare function weightedVaultApy(markets: MarketForApy[], depositSim?: Record<string, bigint>, withdrawalSim?: Record<string, bigint>): number;
139
+ /**
140
+ * Simulate how a deposit flows through the supply queue and build a depositSim map.
141
+ *
142
+ * Deposits fill each supply-queue market up to its cap, then spill to the next.
143
+ * Returns a Record<marketId, bigint> representing extra supply per market.
144
+ */
145
+ declare function simulateDeposit(markets: MarketForApy[], depositAmount: bigint): Record<string, bigint>;
146
+ /**
147
+ * Simulate how a withdrawal flows through the withdraw queue.
148
+ *
149
+ * Idle assets are consumed first (no market APY impact), then each withdraw-queue
150
+ * market is drained up to min(vaultSupplyAssets, available liquidity).
151
+ * Returns positive values representing amounts removed per market.
152
+ */
153
+ declare function simulateWithdrawal(markets: MarketForApy[], withdrawAmount: bigint, idleAssets: bigint): {
154
+ sim: Record<string, bigint>;
155
+ withdrawable: bigint;
156
+ remaining: bigint;
157
+ };
158
+ /**
159
+ * Merge two MarketApyDetail arrays (current vs simulated) into a single
160
+ * array of MarketImpactDetail with nested `current` and `simulated` snapshots.
161
+ */
162
+ declare function mergeMarketDetails(current: MarketApyDetail[], simulated: MarketApyDetail[]): MarketImpactDetail[];
163
+
164
+ export { type DepositImpactResult as D, type FindMaxConstraint as F, type MarketForApy as M, type VaultApyResult as V, type WithdrawalImpactResult as W, type VaultFetchResult as a, type FindMaxDepositResult as b, type FindMaxWithdrawalResult as c, type FindMaxConstraintState as d, type MarketApyDetail as e, type MarketApySnapshot as f, type MarketImpactDetail as g, type VaultApyDetailed as h, estimateMarketApy as i, simulateWithdrawal as j, weightedVaultApyDetailed as k, mergeMarketDetails as m, simulateDeposit as s, weightedVaultApy as w };
package/dist/math.cjs ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+ var _chunk37KGZP4Ocjs = require('./chunk-37KGZP4O.cjs');
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+ exports.estimateMarketApy = _chunk37KGZP4Ocjs.estimateMarketApy; exports.mergeMarketDetails = _chunk37KGZP4Ocjs.mergeMarketDetails; exports.simulateDeposit = _chunk37KGZP4Ocjs.simulateDeposit; exports.simulateWithdrawal = _chunk37KGZP4Ocjs.simulateWithdrawal; exports.weightedVaultApy = _chunk37KGZP4Ocjs.weightedVaultApy; exports.weightedVaultApyDetailed = _chunk37KGZP4Ocjs.weightedVaultApyDetailed;
17
+ //# sourceMappingURL=math.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Volumes/origin/morpho-utils/dist/math.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,iZAAC","file":"/Volumes/origin/morpho-utils/dist/math.cjs"}
@@ -0,0 +1 @@
1
+ export { e as MarketApyDetail, M as MarketForApy, g as MarketImpactDetail, h as VaultApyDetailed, i as estimateMarketApy, m as mergeMarketDetails, s as simulateDeposit, j as simulateWithdrawal, w as weightedVaultApy, k as weightedVaultApyDetailed } from './math-ClwpjVti.cjs';
package/dist/math.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { e as MarketApyDetail, M as MarketForApy, g as MarketImpactDetail, h as VaultApyDetailed, i as estimateMarketApy, m as mergeMarketDetails, s as simulateDeposit, j as simulateWithdrawal, w as weightedVaultApy, k as weightedVaultApyDetailed } from './math-ClwpjVti.js';
package/dist/math.js ADDED
@@ -0,0 +1,17 @@
1
+ import {
2
+ estimateMarketApy,
3
+ mergeMarketDetails,
4
+ simulateDeposit,
5
+ simulateWithdrawal,
6
+ weightedVaultApy,
7
+ weightedVaultApyDetailed
8
+ } from "./chunk-K2ZKPGSF.js";
9
+ export {
10
+ estimateMarketApy,
11
+ mergeMarketDetails,
12
+ simulateDeposit,
13
+ simulateWithdrawal,
14
+ weightedVaultApy,
15
+ weightedVaultApyDetailed
16
+ };
17
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "origin-morpho-utils",
3
+ "version": "0.1.0",
4
+ "description": "Morpho Blue / MetaMorpho vault APY computation and deposit/withdrawal impact simulation",
5
+ "license": "BUSL-1.1",
6
+ "author": "Origin Protocol",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/OriginProtocol/morpho-utils.git"
10
+ },
11
+ "keywords": ["morpho", "defi", "apy", "metamorpho", "viem"],
12
+ "type": "module",
13
+ "main": "./dist/index.cjs",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "bin": {
17
+ "morpho-utils": "./dist/cli.js"
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "import": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/index.d.cts",
27
+ "default": "./dist/index.cjs"
28
+ }
29
+ },
30
+ "./math": {
31
+ "import": {
32
+ "types": "./dist/math.d.ts",
33
+ "default": "./dist/math.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/math.d.cts",
37
+ "default": "./dist/math.cjs"
38
+ }
39
+ }
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsx src/cli.ts",
47
+ "start": "node dist/cli.js",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "lint": "eslint src/ test/",
51
+ "lint:fix": "eslint src/ test/ --fix",
52
+ "prettier-check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'",
53
+ "prettier-fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
54
+ "typecheck": "tsc --noEmit",
55
+ "prepublishOnly": "pnpm build"
56
+ },
57
+ "peerDependencies": {
58
+ "viem": ">=2.0.0"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "viem": {
62
+ "optional": true
63
+ }
64
+ },
65
+ "devDependencies": {
66
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
67
+ "@types/node": "^25.6.0",
68
+ "eslint": "^9.39.4",
69
+ "prettier": "^3.8.2",
70
+ "tsup": "^8.0.0",
71
+ "tsx": "^4.21.0",
72
+ "typescript": "~5.8.0",
73
+ "typescript-eslint": "^8.58.1",
74
+ "viem": "^2.40.0",
75
+ "vitest": "^3.0.0"
76
+ }
77
+ }