impermax-sdk 2.1.30 → 2.1.32

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.
@@ -5,6 +5,8 @@ import OffchainLendingPool from './offchainLendingPool';
5
5
  export default class OffchainBorrowable extends OffchainPoolToken {
6
6
  private readonly lendingPool;
7
7
  private readonly poolTokenType;
8
+ private _accrueInterest;
9
+ private _calculateBorrowRate;
8
10
  constructor(lendingPool: OffchainLendingPool, poolTokenType: PoolTokenType);
9
11
  getOffchain: () => import("..").default;
10
12
  getLendingPool: () => OffchainLendingPool;
@@ -18,14 +20,12 @@ export default class OffchainBorrowable extends OffchainPoolToken {
18
20
  getBorrowIndex(): Promise<number>;
19
21
  getAccrualTimestamp(): Promise<number>;
20
22
  getTotalBorrows(): Promise<number>;
21
- getCurrentTotalBorrows(): Promise<number>;
22
23
  getTotalBorrowsUSD(): Promise<number>;
23
24
  getBorrowRate(): Promise<number>;
24
25
  getBorrowAPR(): Promise<number>;
25
26
  getNextBorrowRate(borrowAmount: number): Promise<number>;
26
27
  getNextBorrowAPR(borrowAmount: number): Promise<number>;
27
28
  getSupply(): Promise<number>;
28
- getCurrentSupply(): Promise<number>;
29
29
  getSupplyUSD(): Promise<number>;
30
30
  getUtilizationRate(): Promise<number>;
31
31
  getSupplyRate(): Promise<number>;
@@ -16,6 +16,82 @@ const utils_1 = require("../../utils");
16
16
  const imxes_1 = require("../../config/contracts/imxes");
17
17
  const offchainPoolToken_1 = __importDefault(require("../offchainPoolToken"));
18
18
  class OffchainBorrowable extends offchainPoolToken_1.default {
19
+ // Simulates `accrueInterest` from `BInterestRateModel.sol`
20
+ _accrueInterest() {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const [totalBalance, borrows, index, accrualTimestamp, borrowRate] = yield Promise.all([
23
+ this.getPoolTokenParamFloat("totalBalance"),
24
+ this.getPoolTokenParamFloat("totalBorrows"),
25
+ this.getPoolTokenParamFloat("borrowIndex"),
26
+ this.getPoolTokenParamFloat("accrualTimestamp"),
27
+ this.getPoolTokenParamFloat("borrowRate"),
28
+ ]);
29
+ const timeElapsed = Date.now() / 1000 - accrualTimestamp;
30
+ if (timeElapsed === 0)
31
+ return {
32
+ totalBalance,
33
+ totalBorrows: borrows,
34
+ borrowIndex: index,
35
+ timeElapsed,
36
+ interest: 0,
37
+ };
38
+ const interestFactor = borrowRate * timeElapsed;
39
+ const interest = interestFactor * borrows;
40
+ const totalBorrows = borrows + interest;
41
+ const borrowIndex = index + interestFactor * index;
42
+ return { totalBalance, totalBorrows, borrowIndex, timeElapsed, interest };
43
+ });
44
+ }
45
+ // Simulates `_calculateBorrowRate` from `BInterestRateModel.sol`, uses `accruedInterestIndices`
46
+ // to simulate interest accrual first since this function is always called after `accrueInterest`.
47
+ _calculateBorrowRate() {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ let borrowRate = 0;
50
+ const KINK_MULTIPLIER = this.lendingPool.getKinkMultiplier();
51
+ const KINK_BORROW_RATE_MAX = 792.7448 / 1e9; // 2500% per year
52
+ const KINK_BORROW_RATE_MIN = 0.31709792 / 1e9; // 1% per year
53
+ const [_kinkUtilizationRate, _adjustSpeed, _borrowRate, _kinkBorrowRate, _rateUpdateTimestamp,] = yield Promise.all([
54
+ this.getPoolTokenParamFloat("kinkUtilizationRate"),
55
+ this.getPoolTokenParamFloat("adjustSpeed"),
56
+ this.getPoolTokenParamFloat("borrowRate"),
57
+ this.getPoolTokenParamFloat("kinkBorrowRate"),
58
+ // This should be same most of time, cant get it from subgraph since no event
59
+ this.getPoolTokenParamFloat("accrualTimestamp"),
60
+ ]);
61
+ // Calculate new kink borrow rate
62
+ const timeElapsed = Date.now() / 1000 - _rateUpdateTimestamp;
63
+ let kinkBorrowRate = 0;
64
+ if (timeElapsed > 0) {
65
+ let adjustFactor = 0;
66
+ if (_borrowRate < _kinkBorrowRate) {
67
+ const tmp = (_kinkBorrowRate - _borrowRate) / _kinkBorrowRate * _adjustSpeed * timeElapsed;
68
+ adjustFactor = tmp > 1 ? 0 : 1 - tmp;
69
+ }
70
+ else {
71
+ const tmp = (_borrowRate - _kinkBorrowRate) / _kinkBorrowRate * _adjustSpeed * timeElapsed;
72
+ adjustFactor = 1 + tmp;
73
+ }
74
+ kinkBorrowRate = _kinkBorrowRate * adjustFactor;
75
+ if (kinkBorrowRate > KINK_BORROW_RATE_MAX)
76
+ kinkBorrowRate = KINK_BORROW_RATE_MAX;
77
+ if (kinkBorrowRate < KINK_BORROW_RATE_MIN)
78
+ kinkBorrowRate = KINK_BORROW_RATE_MIN;
79
+ }
80
+ // Simulate accrual
81
+ const { totalBalance, totalBorrows } = yield this._accrueInterest();
82
+ ;
83
+ const _actualBalance = totalBalance + totalBorrows;
84
+ const _utilizationRate = _actualBalance === 0 ? 0 : totalBorrows / _actualBalance;
85
+ if (_utilizationRate <= _kinkUtilizationRate) {
86
+ borrowRate = kinkBorrowRate * _utilizationRate / _kinkUtilizationRate;
87
+ }
88
+ else {
89
+ const overUtil = (_utilizationRate - _kinkUtilizationRate) / (1 - _kinkUtilizationRate);
90
+ borrowRate = ((KINK_MULTIPLIER - 1) * overUtil + 1) * kinkBorrowRate;
91
+ }
92
+ return { borrowRate, kinkBorrowRate };
93
+ });
94
+ }
19
95
  constructor(lendingPool, poolTokenType) {
20
96
  super();
21
97
  this.getOffchain = () => this.lendingPool.getOffchain();
@@ -39,7 +115,8 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
39
115
  // Kink Borrow Rate
40
116
  getKinkBorrowRate() {
41
117
  return __awaiter(this, void 0, void 0, function* () {
42
- return this.getPoolTokenParamFloat("kinkBorrowRate");
118
+ const { kinkBorrowRate } = yield this._calculateBorrowRate();
119
+ return kinkBorrowRate;
43
120
  });
44
121
  }
45
122
  // Kink Utilization Rate
@@ -64,7 +141,8 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
64
141
  // Borrow Index
65
142
  getBorrowIndex() {
66
143
  return __awaiter(this, void 0, void 0, function* () {
67
- return this.getPoolTokenParamFloat("borrowIndex");
144
+ const { borrowIndex } = yield this._accrueInterest();
145
+ return borrowIndex;
68
146
  });
69
147
  }
70
148
  // Accrue Timestamp
@@ -76,20 +154,13 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
76
154
  // Total borrows
77
155
  getTotalBorrows() {
78
156
  return __awaiter(this, void 0, void 0, function* () {
79
- return this.getPoolTokenParamFloat("totalBorrows");
80
- });
81
- }
82
- getCurrentTotalBorrows() {
83
- return __awaiter(this, void 0, void 0, function* () {
84
- const storedAmount = yield this.getTotalBorrows();
85
- const accrualTimestamp = yield this.getAccrualTimestamp();
86
- const borrowRate = yield this.getBorrowRate();
87
- return storedAmount * (1 + (Date.now() / 1000 - accrualTimestamp) * borrowRate);
157
+ const { totalBorrows } = yield this._accrueInterest();
158
+ return totalBorrows;
88
159
  });
89
160
  }
90
161
  getTotalBorrowsUSD() {
91
162
  return __awaiter(this, void 0, void 0, function* () {
92
- const totalBorrows = yield this.getCurrentTotalBorrows();
163
+ const totalBorrows = yield this.getTotalBorrows();
93
164
  const tokenPrice = yield this.getTokenPriceFast();
94
165
  return totalBorrows * tokenPrice;
95
166
  });
@@ -97,7 +168,8 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
97
168
  // Borrow rate
98
169
  getBorrowRate() {
99
170
  return __awaiter(this, void 0, void 0, function* () {
100
- return this.getPoolTokenParamFloat("borrowRate");
171
+ const { borrowRate } = yield this._calculateBorrowRate();
172
+ return borrowRate;
101
173
  });
102
174
  }
103
175
  getBorrowAPR() {
@@ -108,10 +180,10 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
108
180
  }
109
181
  getNextBorrowRate(borrowAmount) {
110
182
  return __awaiter(this, void 0, void 0, function* () {
111
- const totalBorrows = yield this.getTotalBorrows();
112
- const supply = yield this.getSupply();
183
+ const { totalBalance, totalBorrows } = yield this._accrueInterest();
184
+ const supply = totalBalance + totalBorrows;
113
185
  const UR = (borrowAmount + totalBorrows) / supply;
114
- const kinkBR = yield this.getKinkBorrowRate();
186
+ const { kinkBorrowRate: kinkBR } = yield this._calculateBorrowRate();
115
187
  const kinkUR = yield this.getKinkUtilizationRate();
116
188
  if (UR < kinkUR)
117
189
  return UR / kinkUR * kinkBR;
@@ -128,22 +200,13 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
128
200
  // Supply
129
201
  getSupply() {
130
202
  return __awaiter(this, void 0, void 0, function* () {
131
- const totalBalance = yield this.getTotalBalance();
132
- const totalBorrows = yield this.getTotalBorrows();
203
+ const { totalBalance, totalBorrows } = yield this._accrueInterest();
133
204
  return totalBalance + totalBorrows;
134
205
  });
135
206
  }
136
- getCurrentSupply() {
137
- return __awaiter(this, void 0, void 0, function* () {
138
- const storedAmount = yield this.getSupply();
139
- const accrualTimestamp = yield this.getAccrualTimestamp();
140
- const supplyRate = yield this.getSupplyRate();
141
- return storedAmount * (1 + (Date.now() / 1000 - accrualTimestamp) * supplyRate);
142
- });
143
- }
144
207
  getSupplyUSD() {
145
208
  return __awaiter(this, void 0, void 0, function* () {
146
- const supply = yield this.getCurrentSupply();
209
+ const supply = yield this.getSupply();
147
210
  const tokenPrice = yield this.getTokenPriceFast();
148
211
  return supply * tokenPrice;
149
212
  });
@@ -151,11 +214,10 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
151
214
  // Utilization Rate
152
215
  getUtilizationRate() {
153
216
  return __awaiter(this, void 0, void 0, function* () {
154
- const supply = yield this.getSupply();
155
- if (supply == 0)
217
+ const { totalBalance, totalBorrows } = yield this._accrueInterest();
218
+ if (totalBorrows == 0)
156
219
  return 0;
157
- const totalBalance = yield this.getTotalBorrows();
158
- return totalBalance / supply;
220
+ return totalBorrows / (totalBalance + totalBorrows);
159
221
  });
160
222
  }
161
223
  // Supply Rate
@@ -175,10 +237,10 @@ class OffchainBorrowable extends offchainPoolToken_1.default {
175
237
  }
176
238
  getNextSupplyRate(supplyAmount) {
177
239
  return __awaiter(this, void 0, void 0, function* () {
178
- const totalBorrows = yield this.getTotalBorrows();
179
- const supply = yield this.getSupply();
240
+ const { totalBalance, totalBorrows } = yield this._accrueInterest();
241
+ const supply = totalBalance + totalBorrows;
180
242
  const UR = totalBorrows / (supply + supplyAmount);
181
- const kinkBR = yield this.getKinkBorrowRate();
243
+ const { kinkBorrowRate: kinkBR } = yield this._calculateBorrowRate();
182
244
  const kinkUR = yield this.getKinkUtilizationRate();
183
245
  const reserveFactor = yield this.getReserveFactor();
184
246
  if (UR < kinkUR)
@@ -21,7 +21,7 @@ export default abstract class OnchainInteractionsPoolToken {
21
21
  getPoolTokenAllowance(): Promise<ethers.BigNumber>;
22
22
  getUnderlyingAllowance(): Promise<ethers.BigNumber>;
23
23
  approvePoolToken(amount: BigNumber, onTransactionHash: Function): Promise<any>;
24
- permitPoolToken(amount: BigNumber, callBack: (permit: Permit | null) => void): Promise<void>;
24
+ permitPoolToken(amount: BigNumber): Promise<Permit>;
25
25
  approveUnderlying(amount: BigNumber, onTransactionHash: Function): Promise<any>;
26
26
  protected getSendData(permits: Permits): Promise<{
27
27
  router: any;
@@ -79,11 +79,11 @@ class OnchainInteractionsPoolToken {
79
79
  return this.send(poolToken.methods.approve(spender, amount), onTransactionHash);
80
80
  });
81
81
  }
82
- permitPoolToken(amount, callBack) {
82
+ permitPoolToken(amount) {
83
83
  return __awaiter(this, void 0, void 0, function* () {
84
84
  const { owner, spender } = this.getOwnerSpender();
85
85
  const poolToken = yield this.poolToken.getPoolToken();
86
- this.getPermitHelper().getTokenPermit(poolToken, owner, spender, amount, callBack);
86
+ return this.getPermitHelper().getTokenPermit(poolToken, owner, spender, amount);
87
87
  });
88
88
  }
89
89
  approveUnderlying(amount, onTransactionHash) {
@@ -15,7 +15,7 @@ export default class OnchainPermitHelper {
15
15
  private getNftPermitJSONData;
16
16
  private getPermit2SingleJSONData;
17
17
  private getSignature;
18
- getTokenPermit(token: Contract, owner: Address, spender: Address, value: BigNumber, callBack: (permit: Permit | null) => void): Promise<void>;
19
- getNftPermit(token: Contract, owner: Address, spender: Address, tokenId: BigNumber, callBack: (permit: Permit | null) => void): Promise<void>;
20
- getPermit2Single(token: Contract, owner: Address, spender: Address, value: BigNumber, callBack: (permit: Permit | null) => void): Promise<void>;
18
+ getTokenPermit(token: Contract, owner: Address, spender: Address, value: BigNumber): Promise<Permit>;
19
+ getNftPermit(token: Contract, owner: Address, spender: Address, tokenId: BigNumber): Promise<Permit>;
20
+ getPermit2Single(token: Contract, owner: Address, spender: Address, value: BigNumber): Promise<Permit>;
21
21
  }
@@ -48,12 +48,20 @@ const PERMIT2_SINGLE = [
48
48
  { name: "spender", type: "address" },
49
49
  { name: "sigDeadline", type: "uint256" },
50
50
  ];
51
- const TYPES = {
51
+ const TOKEN_PERMIT_TYPES = {
52
52
  EIP712Domain: EIP712_DOMAIN,
53
- Permit2Domain: PERMIT2_DOMAIN,
54
53
  Permit: PERMIT,
54
+ };
55
+ const BORROW_PERMIT_TYPES = {
56
+ EIP712Domain: EIP712_DOMAIN,
55
57
  BorrowPermit: PERMIT,
56
- NftPermit: NFT_PERMIT,
58
+ };
59
+ const NFT_PERMIT_TYPES = {
60
+ EIP712Domain: EIP712_DOMAIN,
61
+ Permit: NFT_PERMIT,
62
+ };
63
+ const PERMIT2_TYPES = {
64
+ Permit2Domain: PERMIT2_DOMAIN,
57
65
  PermitDetails: PERMIT2_DETAILS,
58
66
  PermitSingle: PERMIT2_SINGLE,
59
67
  };
@@ -86,47 +94,49 @@ class OnchainPermitHelper {
86
94
  return __awaiter(this, void 0, void 0, function* () {
87
95
  const domain = yield this.getDomainPermit1(contract);
88
96
  const primaryType = "Permit";
89
- return JSON.stringify({ types: TYPES, domain, primaryType, message });
97
+ return JSON.stringify({ types: TOKEN_PERMIT_TYPES, domain, primaryType, message });
90
98
  });
91
99
  }
92
100
  getBorrowPermitJSONData(contract, message) {
93
101
  return __awaiter(this, void 0, void 0, function* () {
94
102
  const domain = yield this.getDomainPermit1(contract);
95
103
  const primaryType = "BorrowPermit";
96
- return JSON.stringify({ types: TYPES, domain, primaryType, message });
104
+ return JSON.stringify({ types: BORROW_PERMIT_TYPES, domain, primaryType, message });
97
105
  });
98
106
  }
99
107
  getNftPermitJSONData(contract, message) {
100
108
  return __awaiter(this, void 0, void 0, function* () {
101
109
  const domain = yield this.getDomainPermit1(contract);
102
- const primaryType = "NftPermit";
103
- return JSON.stringify({ types: TYPES, domain, primaryType, message });
110
+ const primaryType = "Permit";
111
+ return JSON.stringify({ types: NFT_PERMIT_TYPES, domain, primaryType, message });
104
112
  });
105
113
  }
106
114
  getPermit2SingleJSONData(message) {
107
115
  return __awaiter(this, void 0, void 0, function* () {
108
116
  const domain = this.getDomainPermit2();
109
117
  const primaryType = "PermitSingle";
110
- return JSON.stringify({ types: TYPES, domain, primaryType, message });
118
+ return JSON.stringify({ types: PERMIT2_TYPES, domain, primaryType, message });
111
119
  });
112
120
  }
113
- getSignature(owner, jsonData, callBack) {
121
+ getSignature(owner, jsonData) {
114
122
  return __awaiter(this, void 0, void 0, function* () {
115
- this.onchain.web3.currentProvider.send({
116
- method: "eth_signTypedData_v4",
117
- params: [owner, jsonData],
118
- from: owner
119
- }, (err, data) => {
120
- if (err) {
121
- console.error(err);
122
- return callBack(null);
123
- }
124
- console.log("signature", data.result);
125
- callBack(data.result);
123
+ return new Promise((resolve, reject) => {
124
+ this.onchain.web3.currentProvider.send({
125
+ method: "eth_signTypedData_v4",
126
+ params: [owner, jsonData],
127
+ from: owner
128
+ }, (err, data) => {
129
+ if (err) {
130
+ reject(err);
131
+ }
132
+ else {
133
+ resolve(data.result);
134
+ }
135
+ });
126
136
  });
127
137
  });
128
138
  }
129
- getTokenPermit(token, owner, spender, value, callBack) {
139
+ getTokenPermit(token, owner, spender, value) {
130
140
  return __awaiter(this, void 0, void 0, function* () {
131
141
  const nonce = yield token.methods.nonces(owner).call();
132
142
  const jsonData = yield this.getTokenPermitJSONData(token, {
@@ -136,19 +146,14 @@ class OnchainPermitHelper {
136
146
  nonce: ethers_1.BigNumber.from(nonce).toHexString(),
137
147
  deadline: this.deadline,
138
148
  });
139
- console.log("jsonData", jsonData);
140
- this.getSignature(owner, jsonData, (signature) => {
141
- if (!signature)
142
- return callBack(null);
143
- callBack({
144
- permitType: onchainTypes_1.PermitType.PERMIT1,
145
- permitData: ethers_1.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'uint256'], [token._address, value.toString(), this.deadline]),
146
- signature
147
- });
148
- });
149
+ return {
150
+ permitType: onchainTypes_1.PermitType.PERMIT1,
151
+ permitData: ethers_1.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'uint256'], [token._address, value.toString(), this.deadline]),
152
+ signature: yield this.getSignature(owner, jsonData)
153
+ };
149
154
  });
150
155
  }
151
- getNftPermit(token, owner, spender, tokenId, callBack) {
156
+ getNftPermit(token, owner, spender, tokenId) {
152
157
  return __awaiter(this, void 0, void 0, function* () {
153
158
  const nonce = yield token.methods.nonces(tokenId).call();
154
159
  const jsonData = yield this.getNftPermitJSONData(token, {
@@ -157,22 +162,18 @@ class OnchainPermitHelper {
157
162
  nonce: ethers_1.BigNumber.from(nonce).toHexString(),
158
163
  deadline: this.deadline,
159
164
  });
160
- this.getSignature(owner, jsonData, (signature) => {
161
- if (!signature)
162
- return callBack(null);
163
- callBack({
164
- permitType: onchainTypes_1.PermitType.PERMIT_NFT,
165
- permitData: ethers_1.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'uint256'], [token.address, tokenId.toString(), this.deadline]),
166
- signature
167
- });
168
- });
165
+ return {
166
+ permitType: onchainTypes_1.PermitType.PERMIT_NFT,
167
+ permitData: ethers_1.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'uint256'], [token.address, tokenId.toString(), this.deadline]),
168
+ signature: yield this.getSignature(owner, jsonData)
169
+ };
169
170
  });
170
171
  }
171
- getPermit2Single(token, owner, spender, value, callBack) {
172
+ getPermit2Single(token, owner, spender, value) {
172
173
  return __awaiter(this, void 0, void 0, function* () {
173
174
  const allowanceData = yield this.permit2.methods.allowance(owner, token.address, spender);
174
175
  if (!allowanceData)
175
- return callBack(null);
176
+ throw new Error("Invalid permit2 allowance data");
176
177
  const nonce = allowanceData.nonce;
177
178
  const permitDetailsType = 'tuple(address tokenAddress, uint160 amount, uint48 expiration, uint48 nonce)';
178
179
  const details = {
@@ -186,15 +187,11 @@ class OnchainPermitHelper {
186
187
  spender,
187
188
  sigDeadline: this.deadline,
188
189
  });
189
- this.getSignature(owner, jsonData, (signature) => {
190
- if (!signature)
191
- return callBack(null);
192
- callBack({
193
- permitType: onchainTypes_1.PermitType.PERMIT2_SINGLE,
194
- permitData: ethers_1.ethers.utils.defaultAbiCoder.encode([permitDetailsType, 'address', 'uint256'], [token, spender, this.deadline]),
195
- signature
196
- });
197
- });
190
+ return {
191
+ permitType: onchainTypes_1.PermitType.PERMIT2_SINGLE,
192
+ permitData: ethers_1.ethers.utils.defaultAbiCoder.encode([permitDetailsType, 'address', 'uint256'], [token, spender, this.deadline]),
193
+ signature: yield this.getSignature(owner, jsonData)
194
+ };
198
195
  });
199
196
  }
200
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impermax-sdk",
3
- "version": "2.1.30",
3
+ "version": "2.1.32",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib/index.js",