Skip to content

Commit 10eebc5

Browse files
committed
fix: patch user est net apy calc
1 parent 185553f commit 10eebc5

File tree

4 files changed

+171
-12
lines changed

4 files changed

+171
-12
lines changed

package-lock.json

Lines changed: 11 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@blend-capital/blend-sdk",
3-
"version": "3.2.0-beta",
3+
"version": "3.2.0-beta.2",
44
"description": "Javascript SDK for the Blend Protocol",
55
"type": "module",
66
"scripts": {

src/pool/user_positions_est.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ export class PositionsEstimate {
120120
const borrowLimit =
121121
totalEffectiveCollateral == 0 ? 0 : totalEffectiveLiabilities / totalEffectiveCollateral;
122122
const netApy =
123-
totalBorrowed + totalSupplied == 0
124-
? 0
125-
: (supplyApy - borrowApy) / (totalBorrowed + totalSupplied);
123+
totalSupplied == 0
124+
? // if user has no supplied funds and has borrowed funds (e.g. a bad debt position), the debt will
125+
// be forgiven as bad debt so the net APY is still 0
126+
0
127+
: (supplyApy - borrowApy) / totalSupplied;
126128
supplyApy = totalSupplied == 0 ? 0 : supplyApy / totalSupplied;
127129
borrowApy = totalBorrowed == 0 ? 0 : borrowApy / totalBorrowed;
128130

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { PoolOracle, PoolV2, Positions, PositionsEstimate } from '../../src/index.js';
2+
import { toFixed } from '../../src/math.js';
3+
import { ReserveV2 } from '../../src/pool/reserve.js';
4+
5+
describe('user position estimation', () => {
6+
const timestamp = Math.floor(Date.now() / 1000);
7+
const reserve_0 = new ReserveV2(
8+
'pool_id',
9+
'asset_0',
10+
{
11+
index: 0,
12+
c_factor: 9500000,
13+
l_factor: 9000000,
14+
decimals: 7,
15+
} as any,
16+
{
17+
dRate: BigInt(1_400_000_000_000), // d_rate
18+
bRate: BigInt(1_250_000_000_000), // b_rate
19+
lastTime: timestamp,
20+
} as any,
21+
undefined, // borrow emissions
22+
undefined, // supply emissions
23+
0.08, // borrow APR
24+
0.09, // estBorrowApy
25+
0.05, // supply APR
26+
0.06, // estSupplyApy
27+
0 // latestLedger
28+
);
29+
30+
const reserve_1 = new ReserveV2(
31+
'pool_id',
32+
'asset_1',
33+
{
34+
index: 1,
35+
c_factor: 0,
36+
l_factor: 5000000,
37+
decimals: 7,
38+
} as any,
39+
{
40+
dRate: BigInt(1_200_000_000_000), // d_rate
41+
bRate: BigInt(1_100_000_000_000), // b_rate
42+
lastTime: timestamp,
43+
} as any,
44+
undefined, // borrow emissions
45+
undefined, // supply emissions
46+
0.02, // borrow APR
47+
0.03, // estBorrowApy
48+
0.01, // supply APR
49+
0.02, // estSupplyApy
50+
0 // latestLedger
51+
);
52+
53+
const reserve_2 = new ReserveV2(
54+
'pool_id',
55+
'asset_2',
56+
{
57+
index: 2,
58+
c_factor: 9000000,
59+
l_factor: 8500000,
60+
decimals: 7,
61+
} as any,
62+
{
63+
dRate: BigInt(1_150_000_000_000), // d_rate
64+
bRate: BigInt(1_050_000_000_000), // b_rate
65+
lastTime: timestamp,
66+
} as any,
67+
undefined, // borrow emissions
68+
undefined, // supply emissions
69+
0.12, // borrow APR
70+
0.15, // estBorrowApy
71+
0.09, // supply APR
72+
0.11, // estSupplyApy
73+
0 // latestLedger
74+
);
75+
76+
const pool_oracle = new PoolOracle(
77+
'oracle_id',
78+
new Map([
79+
['asset_0', { price: toFixed(1, 7), timestamp }],
80+
['asset_1', { price: toFixed(0.3, 7), timestamp }],
81+
['asset_2', { price: toFixed(200, 7), timestamp }],
82+
]),
83+
7,
84+
0
85+
);
86+
87+
const pool = new PoolV2(
88+
{} as any,
89+
'pool_id',
90+
{} as any,
91+
new Map([
92+
['asset_0', reserve_0],
93+
['asset_1', reserve_1],
94+
['asset_2', reserve_2],
95+
]),
96+
timestamp
97+
);
98+
99+
it('calculates positions estimate correctly', () => {
100+
const user_positions = new Positions(
101+
// liabilities
102+
new Map([[2, toFixed(10, 7)]]),
103+
// collateral
104+
new Map([[0, toFixed(4_000, 7)]]),
105+
// supply
106+
new Map([[1, toFixed(10_000, 7)]])
107+
);
108+
109+
const estimate = PositionsEstimate.build(pool, pool_oracle, user_positions);
110+
111+
expect(estimate.totalBorrowed).toBeCloseTo(10 * 200 * 1.15);
112+
expect(estimate.totalSupplied).toBeCloseTo(4000 * 1 * 1.25 + 10_000 * 0.3 * 1.1);
113+
expect(estimate.totalEffectiveLiabilities).toBeCloseTo((10 * 200 * 1.15) / 0.85);
114+
expect(estimate.totalEffectiveCollateral).toBeCloseTo(4000 * 1 * 1.25 * 0.95);
115+
expect(estimate.borrowCap).toBeCloseTo(
116+
estimate.totalEffectiveCollateral - estimate.totalEffectiveLiabilities
117+
);
118+
expect(estimate.borrowLimit).toBeCloseTo(
119+
estimate.totalEffectiveLiabilities / estimate.totalEffectiveCollateral
120+
);
121+
expect(estimate.netApy).toBeCloseTo(
122+
(estimate.supplyApy - estimate.borrowApy) / estimate.totalSupplied
123+
);
124+
expect(estimate.supplyApy).toBeCloseTo(
125+
(4000 * 1 * 1.25 * 0.06 + 10_000 * 0.3 * 1.1 * 0.02) / estimate.totalSupplied
126+
);
127+
expect(estimate.borrowApy).toBeCloseTo((10 * 200 * 1.15 * 0.15) / estimate.totalBorrowed);
128+
});
129+
130+
it('calculates positions estimate correctly for bad debt user', () => {
131+
const user_positions = new Positions(
132+
// liabilities
133+
new Map([[2, toFixed(10, 7)]]),
134+
// collateral
135+
new Map(),
136+
// supply
137+
new Map()
138+
);
139+
140+
const estimate = PositionsEstimate.build(pool, pool_oracle, user_positions);
141+
142+
expect(estimate.totalBorrowed).toBeCloseTo(10 * 200 * 1.15);
143+
expect(estimate.totalSupplied).toBeCloseTo(0);
144+
expect(estimate.totalEffectiveLiabilities).toBeCloseTo((10 * 200 * 1.15) / 0.85);
145+
expect(estimate.totalEffectiveCollateral).toBeCloseTo(0);
146+
expect(estimate.borrowCap).toBeCloseTo(
147+
estimate.totalEffectiveCollateral - estimate.totalEffectiveLiabilities
148+
);
149+
expect(estimate.borrowLimit).toBeCloseTo(0);
150+
expect(estimate.netApy).toBeCloseTo(0);
151+
expect(estimate.supplyApy).toBeCloseTo(0);
152+
expect(estimate.borrowApy).toBeCloseTo((10 * 200 * 1.15 * 0.15) / estimate.totalBorrowed);
153+
});
154+
});

0 commit comments

Comments
 (0)