@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31
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/README.md +13 -13
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +22 -11
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/pda.d.ts +10 -4
- package/lib/addresses/pda.js +51 -14
- package/lib/admin.d.ts +42 -26
- package/lib/admin.js +228 -81
- package/lib/clearingHouse.d.ts +130 -49
- package/lib/clearingHouse.js +1256 -367
- package/lib/clearingHouseConfig.d.ts +4 -4
- package/lib/clearingHouseUser.d.ts +51 -39
- package/lib/clearingHouseUser.js +408 -191
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.d.ts +7 -9
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +25 -12
- package/lib/constants/numericConstants.js +35 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +74 -0
- package/lib/dlob/DLOB.js +595 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +85 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +139 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +8 -2
- package/lib/events/types.js +6 -0
- package/lib/examples/makeTradeExample.js +20 -8
- package/lib/factory/bigNum.d.ts +2 -0
- package/lib/factory/bigNum.js +48 -10
- package/lib/idl/clearing_house.json +4889 -1529
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +21 -6
- package/lib/index.js +25 -6
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -66
- package/lib/math/auction.js +4 -1
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +11 -10
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +77 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +72 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +78 -3
- package/lib/math/position.d.ts +21 -13
- package/lib/math/position.js +76 -36
- package/lib/math/repeg.js +14 -5
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +192 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/trade.d.ts +10 -10
- package/lib/math/trade.js +32 -39
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +12 -92
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +566 -138
- package/lib/types.js +129 -5
- package/lib/userMap/userMap.d.ts +25 -0
- package/lib/userMap/userMap.js +73 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -6
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +31 -11
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +1 -2
- package/src/addresses/pda.ts +88 -14
- package/src/admin.ts +452 -147
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +2066 -467
- package/src/clearingHouseConfig.ts +4 -3
- package/src/clearingHouseUser.ts +747 -294
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +30 -31
- package/src/constants/numericConstants.ts +48 -25
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +73 -0
- package/src/dlob/DLOB.ts +953 -0
- package/src/dlob/DLOBNode.ts +167 -0
- package/src/dlob/NodeList.ts +189 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +19 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +32 -14
- package/src/factory/bigNum.ts +65 -13
- package/src/idl/clearing_house.json +4889 -1529
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +21 -6
- package/src/math/amm.ts +171 -88
- package/src/math/auction.ts +5 -1
- package/src/math/conversion.ts +2 -2
- package/src/math/funding.ts +20 -18
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +127 -0
- package/src/math/market.ts +145 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +138 -4
- package/src/math/position.ts +119 -58
- package/src/math/repeg.ts +16 -6
- package/src/math/spotBalance.ts +319 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +53 -59
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +24 -137
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +533 -140
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +24 -10
- package/tests/dlob/helpers.ts +397 -0
- package/tests/dlob/test.ts +3688 -0
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/constants/banks.ts +0 -43
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js.map +0 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SpotMarketAccount,
|
|
3
|
+
SpotBalanceType,
|
|
4
|
+
isVariant,
|
|
5
|
+
MarginCategory,
|
|
6
|
+
} from '../types';
|
|
7
|
+
import { BN } from '@project-serum/anchor';
|
|
8
|
+
import {
|
|
9
|
+
SPOT_MARKET_UTILIZATION_PRECISION,
|
|
10
|
+
ONE,
|
|
11
|
+
TEN,
|
|
12
|
+
ZERO,
|
|
13
|
+
SPOT_MARKET_RATE_PRECISION,
|
|
14
|
+
SPOT_MARKET_WEIGHT_PRECISION,
|
|
15
|
+
ONE_YEAR,
|
|
16
|
+
AMM_RESERVE_PRECISION,
|
|
17
|
+
} from '../constants/numericConstants';
|
|
18
|
+
import {
|
|
19
|
+
calculateSizeDiscountAssetWeight,
|
|
20
|
+
calculateSizePremiumLiabilityWeight,
|
|
21
|
+
} from './margin';
|
|
22
|
+
import { OraclePriceData } from '../oracles/types';
|
|
23
|
+
|
|
24
|
+
export function getBalance(
|
|
25
|
+
tokenAmount: BN,
|
|
26
|
+
spotMarket: SpotMarketAccount,
|
|
27
|
+
balanceType: SpotBalanceType
|
|
28
|
+
): BN {
|
|
29
|
+
const precisionIncrease = TEN.pow(new BN(19 - spotMarket.decimals));
|
|
30
|
+
|
|
31
|
+
const cumulativeInterest = isVariant(balanceType, 'deposit')
|
|
32
|
+
? spotMarket.cumulativeDepositInterest
|
|
33
|
+
: spotMarket.cumulativeBorrowInterest;
|
|
34
|
+
|
|
35
|
+
let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
|
|
36
|
+
|
|
37
|
+
if (!balance.eq(ZERO) && isVariant(balanceType, 'borrow')) {
|
|
38
|
+
balance = balance.add(ONE);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return balance;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getTokenAmount(
|
|
45
|
+
balanceAmount: BN,
|
|
46
|
+
spotMarket: SpotMarketAccount,
|
|
47
|
+
balanceType: SpotBalanceType
|
|
48
|
+
): BN {
|
|
49
|
+
const precisionDecrease = TEN.pow(new BN(19 - spotMarket.decimals));
|
|
50
|
+
|
|
51
|
+
const cumulativeInterest = isVariant(balanceType, 'deposit')
|
|
52
|
+
? spotMarket.cumulativeDepositInterest
|
|
53
|
+
: spotMarket.cumulativeBorrowInterest;
|
|
54
|
+
|
|
55
|
+
return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getSignedTokenAmount(
|
|
59
|
+
tokenAmount: BN,
|
|
60
|
+
balanceType: SpotBalanceType
|
|
61
|
+
): BN {
|
|
62
|
+
if (isVariant(balanceType, 'deposit')) {
|
|
63
|
+
return tokenAmount;
|
|
64
|
+
} else {
|
|
65
|
+
return tokenAmount.abs().neg();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function getTokenValue(
|
|
70
|
+
tokenAmount: BN,
|
|
71
|
+
spotDecimals: number,
|
|
72
|
+
oraclePriceData: OraclePriceData
|
|
73
|
+
): BN {
|
|
74
|
+
if (tokenAmount.eq(ZERO)) {
|
|
75
|
+
return ZERO;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const precisionDecrease = TEN.pow(new BN(spotDecimals));
|
|
79
|
+
|
|
80
|
+
return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function calculateAssetWeight(
|
|
84
|
+
balanceAmount: BN,
|
|
85
|
+
spotMarket: SpotMarketAccount,
|
|
86
|
+
marginCategory: MarginCategory
|
|
87
|
+
): BN {
|
|
88
|
+
const sizePrecision = TEN.pow(new BN(spotMarket.decimals));
|
|
89
|
+
let sizeInAmmReservePrecision;
|
|
90
|
+
if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
|
|
91
|
+
sizeInAmmReservePrecision = balanceAmount.div(
|
|
92
|
+
sizePrecision.div(AMM_RESERVE_PRECISION)
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
sizeInAmmReservePrecision = balanceAmount
|
|
96
|
+
.mul(AMM_RESERVE_PRECISION)
|
|
97
|
+
.div(sizePrecision);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let assetWeight;
|
|
101
|
+
|
|
102
|
+
switch (marginCategory) {
|
|
103
|
+
case 'Initial':
|
|
104
|
+
assetWeight = calculateSizeDiscountAssetWeight(
|
|
105
|
+
sizeInAmmReservePrecision,
|
|
106
|
+
spotMarket.imfFactor,
|
|
107
|
+
spotMarket.initialAssetWeight
|
|
108
|
+
);
|
|
109
|
+
break;
|
|
110
|
+
case 'Maintenance':
|
|
111
|
+
assetWeight = calculateSizeDiscountAssetWeight(
|
|
112
|
+
sizeInAmmReservePrecision,
|
|
113
|
+
spotMarket.imfFactor,
|
|
114
|
+
spotMarket.maintenanceAssetWeight
|
|
115
|
+
);
|
|
116
|
+
break;
|
|
117
|
+
default:
|
|
118
|
+
assetWeight = spotMarket.initialAssetWeight;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return assetWeight;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function calculateLiabilityWeight(
|
|
126
|
+
balanceAmount: BN,
|
|
127
|
+
spotMarket: SpotMarketAccount,
|
|
128
|
+
marginCategory: MarginCategory
|
|
129
|
+
): BN {
|
|
130
|
+
const sizePrecision = TEN.pow(new BN(spotMarket.decimals));
|
|
131
|
+
let sizeInAmmReservePrecision;
|
|
132
|
+
if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
|
|
133
|
+
sizeInAmmReservePrecision = balanceAmount.div(
|
|
134
|
+
sizePrecision.div(AMM_RESERVE_PRECISION)
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
sizeInAmmReservePrecision = balanceAmount
|
|
138
|
+
.mul(AMM_RESERVE_PRECISION)
|
|
139
|
+
.div(sizePrecision);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let assetWeight;
|
|
143
|
+
|
|
144
|
+
switch (marginCategory) {
|
|
145
|
+
case 'Initial':
|
|
146
|
+
assetWeight = calculateSizePremiumLiabilityWeight(
|
|
147
|
+
sizeInAmmReservePrecision,
|
|
148
|
+
spotMarket.imfFactor,
|
|
149
|
+
spotMarket.initialLiabilityWeight,
|
|
150
|
+
SPOT_MARKET_WEIGHT_PRECISION
|
|
151
|
+
);
|
|
152
|
+
break;
|
|
153
|
+
case 'Maintenance':
|
|
154
|
+
assetWeight = calculateSizePremiumLiabilityWeight(
|
|
155
|
+
sizeInAmmReservePrecision,
|
|
156
|
+
spotMarket.imfFactor,
|
|
157
|
+
spotMarket.maintenanceLiabilityWeight,
|
|
158
|
+
SPOT_MARKET_WEIGHT_PRECISION
|
|
159
|
+
);
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
assetWeight = spotMarket.initialLiabilityWeight;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return assetWeight;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function calculateUtilization(bank: SpotMarketAccount): BN {
|
|
170
|
+
const tokenDepositAmount = getTokenAmount(
|
|
171
|
+
bank.depositBalance,
|
|
172
|
+
bank,
|
|
173
|
+
SpotBalanceType.DEPOSIT
|
|
174
|
+
);
|
|
175
|
+
const tokenBorrowAmount = getTokenAmount(
|
|
176
|
+
bank.borrowBalance,
|
|
177
|
+
bank,
|
|
178
|
+
SpotBalanceType.BORROW
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
let utilization: BN;
|
|
182
|
+
if (tokenBorrowAmount.eq(ZERO) && tokenDepositAmount.eq(ZERO)) {
|
|
183
|
+
utilization = ZERO;
|
|
184
|
+
} else if (tokenDepositAmount.eq(ZERO)) {
|
|
185
|
+
utilization = SPOT_MARKET_UTILIZATION_PRECISION;
|
|
186
|
+
} else {
|
|
187
|
+
utilization = tokenBorrowAmount
|
|
188
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
189
|
+
.div(tokenDepositAmount);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return utilization;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function calculateInterestRate(bank: SpotMarketAccount): BN {
|
|
196
|
+
const utilization = calculateUtilization(bank);
|
|
197
|
+
|
|
198
|
+
let interestRate: BN;
|
|
199
|
+
if (utilization.gt(new BN(bank.optimalUtilization))) {
|
|
200
|
+
const surplusUtilization = utilization.sub(new BN(bank.optimalUtilization));
|
|
201
|
+
const borrowRateSlope = new BN(bank.maxBorrowRate - bank.optimalBorrowRate)
|
|
202
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
203
|
+
.div(
|
|
204
|
+
SPOT_MARKET_UTILIZATION_PRECISION.sub(new BN(bank.optimalUtilization))
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
interestRate = new BN(bank.optimalBorrowRate).add(
|
|
208
|
+
surplusUtilization
|
|
209
|
+
.mul(borrowRateSlope)
|
|
210
|
+
.div(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
const borrowRateSlope = new BN(bank.optimalBorrowRate)
|
|
214
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
215
|
+
.div(
|
|
216
|
+
SPOT_MARKET_UTILIZATION_PRECISION.sub(new BN(bank.optimalUtilization))
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
interestRate = utilization
|
|
220
|
+
.mul(borrowRateSlope)
|
|
221
|
+
.div(SPOT_MARKET_UTILIZATION_PRECISION);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return interestRate;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function calculateDepositRate(bank: SpotMarketAccount): BN {
|
|
228
|
+
const utilization = calculateUtilization(bank);
|
|
229
|
+
const borrowRate = calculateBorrowRate(bank);
|
|
230
|
+
const depositRate = borrowRate
|
|
231
|
+
.mul(utilization)
|
|
232
|
+
.div(SPOT_MARKET_UTILIZATION_PRECISION);
|
|
233
|
+
return depositRate;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function calculateBorrowRate(bank: SpotMarketAccount): BN {
|
|
237
|
+
return calculateInterestRate(bank);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function calculateInterestAccumulated(
|
|
241
|
+
bank: SpotMarketAccount,
|
|
242
|
+
now: BN
|
|
243
|
+
): { borrowInterest: BN; depositInterest: BN } {
|
|
244
|
+
const interestRate = calculateInterestRate(bank);
|
|
245
|
+
|
|
246
|
+
const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
|
|
247
|
+
|
|
248
|
+
const modifiedBorrowRate = interestRate.mul(timeSinceLastUpdate);
|
|
249
|
+
|
|
250
|
+
const utilization = calculateUtilization(bank);
|
|
251
|
+
|
|
252
|
+
const modifiedDepositRate = modifiedBorrowRate
|
|
253
|
+
.mul(utilization)
|
|
254
|
+
.div(SPOT_MARKET_UTILIZATION_PRECISION);
|
|
255
|
+
|
|
256
|
+
const borrowInterest = bank.cumulativeBorrowInterest
|
|
257
|
+
.mul(modifiedBorrowRate)
|
|
258
|
+
.div(ONE_YEAR)
|
|
259
|
+
.div(SPOT_MARKET_RATE_PRECISION)
|
|
260
|
+
.add(ONE);
|
|
261
|
+
const depositInterest = bank.cumulativeDepositInterest
|
|
262
|
+
.mul(modifiedDepositRate)
|
|
263
|
+
.div(ONE_YEAR)
|
|
264
|
+
.div(SPOT_MARKET_RATE_PRECISION);
|
|
265
|
+
|
|
266
|
+
return { borrowInterest, depositInterest };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function calculateWithdrawLimit(
|
|
270
|
+
spotMarket: SpotMarketAccount,
|
|
271
|
+
now: BN
|
|
272
|
+
): { borrowLimit: BN; withdrawLimit: BN } {
|
|
273
|
+
const marketDepositTokenAmount = getTokenAmount(
|
|
274
|
+
spotMarket.depositBalance,
|
|
275
|
+
spotMarket,
|
|
276
|
+
SpotBalanceType.DEPOSIT
|
|
277
|
+
);
|
|
278
|
+
const marketBorrowTokenAmount = getTokenAmount(
|
|
279
|
+
spotMarket.borrowBalance,
|
|
280
|
+
spotMarket,
|
|
281
|
+
SpotBalanceType.BORROW
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const twentyFourHours = new BN(60 * 60 * 24);
|
|
285
|
+
const sinceLast = now.sub(spotMarket.lastTwapTs);
|
|
286
|
+
const sinceStart = BN.max(ZERO, twentyFourHours.sub(sinceLast));
|
|
287
|
+
const borrowTokenTwapLive = spotMarket.borrowTokenTwap
|
|
288
|
+
.mul(sinceStart)
|
|
289
|
+
.add(marketBorrowTokenAmount.mul(sinceLast))
|
|
290
|
+
.div(sinceLast.add(sinceLast));
|
|
291
|
+
|
|
292
|
+
const depositTokenTwapLive = spotMarket.depositTokenTwap
|
|
293
|
+
.mul(sinceStart)
|
|
294
|
+
.add(marketDepositTokenAmount.mul(sinceLast))
|
|
295
|
+
.div(sinceLast.add(sinceLast));
|
|
296
|
+
|
|
297
|
+
const maxBorrowTokens = BN.min(
|
|
298
|
+
BN.max(
|
|
299
|
+
marketDepositTokenAmount.div(new BN(6)),
|
|
300
|
+
borrowTokenTwapLive.add(borrowTokenTwapLive.div(new BN(5)))
|
|
301
|
+
),
|
|
302
|
+
marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new BN(10)))
|
|
303
|
+
); // between ~15-90% utilization with friction on twap
|
|
304
|
+
|
|
305
|
+
const minDepositTokens = depositTokenTwapLive.sub(
|
|
306
|
+
BN.min(
|
|
307
|
+
BN.max(
|
|
308
|
+
depositTokenTwapLive.div(new BN(5)),
|
|
309
|
+
spotMarket.withdrawGuardThreshold
|
|
310
|
+
),
|
|
311
|
+
depositTokenTwapLive
|
|
312
|
+
)
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
|
|
317
|
+
withdrawLimit: marketDepositTokenAmount.sub(minDepositTokens),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SpotMarketAccount, SpotPosition } from '../types';
|
|
2
|
+
import { ZERO } from '../constants/numericConstants';
|
|
3
|
+
import { BN } from '@project-serum/anchor';
|
|
4
|
+
import {
|
|
5
|
+
getSignedTokenAmount,
|
|
6
|
+
getTokenAmount,
|
|
7
|
+
getTokenValue,
|
|
8
|
+
} from './spotBalance';
|
|
9
|
+
import { OraclePriceData } from '../oracles/types';
|
|
10
|
+
|
|
11
|
+
export function isSpotPositionAvailable(position: SpotPosition): boolean {
|
|
12
|
+
return position.balance.eq(ZERO) && position.openOrders === 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getWorstCaseTokenAmounts(
|
|
16
|
+
spotPosition: SpotPosition,
|
|
17
|
+
spotMarketAccount: SpotMarketAccount,
|
|
18
|
+
oraclePriceData: OraclePriceData
|
|
19
|
+
): [BN, BN] {
|
|
20
|
+
const tokenAmount = getSignedTokenAmount(
|
|
21
|
+
getTokenAmount(
|
|
22
|
+
spotPosition.balance,
|
|
23
|
+
spotMarketAccount,
|
|
24
|
+
spotPosition.balanceType
|
|
25
|
+
),
|
|
26
|
+
spotPosition.balanceType
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
|
|
30
|
+
const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
|
|
31
|
+
|
|
32
|
+
if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
|
|
33
|
+
const worstCaseQuoteTokenAmount = getTokenValue(
|
|
34
|
+
spotPosition.openAsks.neg(),
|
|
35
|
+
spotMarketAccount.decimals,
|
|
36
|
+
oraclePriceData
|
|
37
|
+
);
|
|
38
|
+
return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
|
|
39
|
+
} else {
|
|
40
|
+
const worstCaseQuoteTokenAmount = getTokenValue(
|
|
41
|
+
spotPosition.openBids.neg(),
|
|
42
|
+
spotMarketAccount.decimals,
|
|
43
|
+
oraclePriceData
|
|
44
|
+
);
|
|
45
|
+
return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/math/trade.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PerpMarketAccount, PositionDirection } from '../types';
|
|
2
2
|
import { BN } from '@project-serum/anchor';
|
|
3
3
|
import { assert } from '../assert/assert';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
PRICE_PRECISION,
|
|
6
6
|
PEG_PRECISION,
|
|
7
7
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
8
|
ZERO,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
calculateBidPrice,
|
|
12
12
|
calculateAskPrice,
|
|
13
|
-
|
|
13
|
+
calculateReservePrice,
|
|
14
14
|
} from './market';
|
|
15
15
|
import {
|
|
16
16
|
calculateAmmReservesAfterSwap,
|
|
@@ -48,18 +48,18 @@ export type PriceImpactUnit =
|
|
|
48
48
|
* @param useSpread whether to consider spread with calculating slippage
|
|
49
49
|
* @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
|
|
50
50
|
*
|
|
51
|
-
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision
|
|
51
|
+
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision PRICE_PRECISION
|
|
52
52
|
*
|
|
53
|
-
* 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision
|
|
53
|
+
* 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision PRICE_PRECISION
|
|
54
54
|
*
|
|
55
|
-
* 'entryPrice' => the average price of the trade : Precision
|
|
55
|
+
* 'entryPrice' => the average price of the trade : Precision PRICE_PRECISION
|
|
56
56
|
*
|
|
57
|
-
* 'newPrice' => the price of the asset after the trade : Precision
|
|
57
|
+
* 'newPrice' => the price of the asset after the trade : Precision PRICE_PRECISION
|
|
58
58
|
*/
|
|
59
59
|
export function calculateTradeSlippage(
|
|
60
60
|
direction: PositionDirection,
|
|
61
61
|
amount: BN,
|
|
62
|
-
market:
|
|
62
|
+
market: PerpMarketAccount,
|
|
63
63
|
inputAssetType: AssetType = 'quote',
|
|
64
64
|
oraclePriceData?: OraclePriceData,
|
|
65
65
|
useSpread = true
|
|
@@ -73,33 +73,25 @@ export function calculateTradeSlippage(
|
|
|
73
73
|
oldPrice = calculateBidPrice(market, oraclePriceData);
|
|
74
74
|
}
|
|
75
75
|
} else {
|
|
76
|
-
oldPrice =
|
|
76
|
+
oldPrice = calculateReservePrice(market, oraclePriceData);
|
|
77
77
|
}
|
|
78
78
|
if (amount.eq(ZERO)) {
|
|
79
79
|
return [ZERO, ZERO, oldPrice, oldPrice];
|
|
80
80
|
}
|
|
81
|
-
const [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const swapDirection = isVariant(direction, 'long')
|
|
91
|
-
? SwapDirection.REMOVE
|
|
92
|
-
: SwapDirection.ADD;
|
|
93
|
-
const quoteAssetAmountAcquired = calculateQuoteAssetAmountSwapped(
|
|
94
|
-
acquiredQuote.abs(),
|
|
95
|
-
market.amm.pegMultiplier,
|
|
96
|
-
swapDirection
|
|
97
|
-
);
|
|
81
|
+
const [acquiredBaseReserve, acquiredQuoteReserve, acquiredQuoteAssetAmount] =
|
|
82
|
+
calculateTradeAcquiredAmounts(
|
|
83
|
+
direction,
|
|
84
|
+
amount,
|
|
85
|
+
market,
|
|
86
|
+
inputAssetType,
|
|
87
|
+
oraclePriceData,
|
|
88
|
+
useSpread
|
|
89
|
+
);
|
|
98
90
|
|
|
99
|
-
const entryPrice =
|
|
91
|
+
const entryPrice = acquiredQuoteAssetAmount
|
|
100
92
|
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
101
|
-
.mul(
|
|
102
|
-
.div(
|
|
93
|
+
.mul(PRICE_PRECISION)
|
|
94
|
+
.div(acquiredBaseReserve.abs());
|
|
103
95
|
|
|
104
96
|
let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
105
97
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
@@ -116,8 +108,8 @@ export function calculateTradeSlippage(
|
|
|
116
108
|
}
|
|
117
109
|
|
|
118
110
|
const newPrice = calculatePrice(
|
|
119
|
-
amm.baseAssetReserve.sub(
|
|
120
|
-
amm.quoteAssetReserve.sub(
|
|
111
|
+
amm.baseAssetReserve.sub(acquiredBaseReserve),
|
|
112
|
+
amm.quoteAssetReserve.sub(acquiredQuoteReserve),
|
|
121
113
|
amm.pegMultiplier
|
|
122
114
|
);
|
|
123
115
|
|
|
@@ -129,12 +121,12 @@ export function calculateTradeSlippage(
|
|
|
129
121
|
|
|
130
122
|
const pctMaxSlippage = newPrice
|
|
131
123
|
.sub(oldPrice)
|
|
132
|
-
.mul(
|
|
124
|
+
.mul(PRICE_PRECISION)
|
|
133
125
|
.div(oldPrice)
|
|
134
126
|
.abs();
|
|
135
127
|
const pctAvgSlippage = entryPrice
|
|
136
128
|
.sub(oldPrice)
|
|
137
|
-
.mul(
|
|
129
|
+
.mul(PRICE_PRECISION)
|
|
138
130
|
.div(oldPrice)
|
|
139
131
|
.abs();
|
|
140
132
|
|
|
@@ -155,13 +147,13 @@ export function calculateTradeSlippage(
|
|
|
155
147
|
export function calculateTradeAcquiredAmounts(
|
|
156
148
|
direction: PositionDirection,
|
|
157
149
|
amount: BN,
|
|
158
|
-
market:
|
|
150
|
+
market: PerpMarketAccount,
|
|
159
151
|
inputAssetType: AssetType = 'quote',
|
|
160
152
|
oraclePriceData: OraclePriceData,
|
|
161
153
|
useSpread = true
|
|
162
|
-
): [BN, BN] {
|
|
154
|
+
): [BN, BN, BN] {
|
|
163
155
|
if (amount.eq(ZERO)) {
|
|
164
|
-
return [ZERO, ZERO];
|
|
156
|
+
return [ZERO, ZERO, ZERO];
|
|
165
157
|
}
|
|
166
158
|
|
|
167
159
|
const swapDirection = getSwapDirection(inputAssetType, direction);
|
|
@@ -185,7 +177,13 @@ export function calculateTradeAcquiredAmounts(
|
|
|
185
177
|
|
|
186
178
|
const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
187
179
|
const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
|
|
188
|
-
|
|
180
|
+
const acquiredQuoteAssetAmount = calculateQuoteAssetAmountSwapped(
|
|
181
|
+
acquiredQuote.abs(),
|
|
182
|
+
amm.pegMultiplier,
|
|
183
|
+
swapDirection
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
|
|
189
187
|
}
|
|
190
188
|
|
|
191
189
|
/**
|
|
@@ -201,12 +199,12 @@ export function calculateTradeAcquiredAmounts(
|
|
|
201
199
|
* [
|
|
202
200
|
* direction => direction of trade required, PositionDirection
|
|
203
201
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
204
|
-
* entryPrice => the entry price for the trade,
|
|
205
|
-
* targetPrice => the target price
|
|
202
|
+
* entryPrice => the entry price for the trade, PRICE_PRECISION
|
|
203
|
+
* targetPrice => the target price PRICE_PRECISION
|
|
206
204
|
* ]
|
|
207
205
|
*/
|
|
208
206
|
export function calculateTargetPriceTrade(
|
|
209
|
-
market:
|
|
207
|
+
market: PerpMarketAccount,
|
|
210
208
|
targetPrice: BN,
|
|
211
209
|
pct: BN = MAXPCT,
|
|
212
210
|
outputAssetType: AssetType = 'quote',
|
|
@@ -217,20 +215,20 @@ export function calculateTargetPriceTrade(
|
|
|
217
215
|
assert(targetPrice.gt(ZERO));
|
|
218
216
|
assert(pct.lte(MAXPCT) && pct.gt(ZERO));
|
|
219
217
|
|
|
220
|
-
const
|
|
218
|
+
const reservePriceBefore = calculateReservePrice(market, oraclePriceData);
|
|
221
219
|
const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
|
|
222
220
|
const askPriceBefore = calculateAskPrice(market, oraclePriceData);
|
|
223
221
|
|
|
224
222
|
let direction;
|
|
225
|
-
if (targetPrice.gt(
|
|
226
|
-
const priceGap = targetPrice.sub(
|
|
223
|
+
if (targetPrice.gt(reservePriceBefore)) {
|
|
224
|
+
const priceGap = targetPrice.sub(reservePriceBefore);
|
|
227
225
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
228
|
-
targetPrice =
|
|
226
|
+
targetPrice = reservePriceBefore.add(priceGapScaled);
|
|
229
227
|
direction = PositionDirection.LONG;
|
|
230
228
|
} else {
|
|
231
|
-
const priceGap =
|
|
229
|
+
const priceGap = reservePriceBefore.sub(targetPrice);
|
|
232
230
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
233
|
-
targetPrice =
|
|
231
|
+
targetPrice = reservePriceBefore.sub(priceGapScaled);
|
|
234
232
|
direction = PositionDirection.SHORT;
|
|
235
233
|
}
|
|
236
234
|
|
|
@@ -254,7 +252,7 @@ export function calculateTargetPriceTrade(
|
|
|
254
252
|
}
|
|
255
253
|
|
|
256
254
|
const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
257
|
-
const k = invariant.mul(
|
|
255
|
+
const k = invariant.mul(PRICE_PRECISION);
|
|
258
256
|
|
|
259
257
|
let baseAssetReserveAfter;
|
|
260
258
|
let quoteAssetReserveAfter;
|
|
@@ -267,21 +265,19 @@ export function calculateTargetPriceTrade(
|
|
|
267
265
|
targetPrice.gt(bidPriceBefore)
|
|
268
266
|
) {
|
|
269
267
|
// no trade, market is at target
|
|
270
|
-
if (
|
|
268
|
+
if (reservePriceBefore.gt(targetPrice)) {
|
|
271
269
|
direction = PositionDirection.SHORT;
|
|
272
270
|
} else {
|
|
273
271
|
direction = PositionDirection.LONG;
|
|
274
272
|
}
|
|
275
273
|
tradeSize = ZERO;
|
|
276
274
|
return [direction, tradeSize, targetPrice, targetPrice];
|
|
277
|
-
} else if (
|
|
275
|
+
} else if (reservePriceBefore.gt(targetPrice)) {
|
|
278
276
|
// overestimate y2
|
|
279
277
|
baseAssetReserveAfter = squareRootBN(
|
|
280
278
|
k.div(targetPrice).mul(peg).div(PEG_PRECISION).sub(biasModifier)
|
|
281
279
|
).sub(new BN(1));
|
|
282
|
-
quoteAssetReserveAfter = k
|
|
283
|
-
.div(MARK_PRICE_PRECISION)
|
|
284
|
-
.div(baseAssetReserveAfter);
|
|
280
|
+
quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
|
|
285
281
|
|
|
286
282
|
markPriceAfter = calculatePrice(
|
|
287
283
|
baseAssetReserveAfter,
|
|
@@ -295,14 +291,12 @@ export function calculateTargetPriceTrade(
|
|
|
295
291
|
.div(PEG_PRECISION)
|
|
296
292
|
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
297
293
|
baseSize = baseAssetReserveAfter.sub(baseAssetReserveBefore);
|
|
298
|
-
} else if (
|
|
294
|
+
} else if (reservePriceBefore.lt(targetPrice)) {
|
|
299
295
|
// underestimate y2
|
|
300
296
|
baseAssetReserveAfter = squareRootBN(
|
|
301
297
|
k.div(targetPrice).mul(peg).div(PEG_PRECISION).add(biasModifier)
|
|
302
298
|
).add(new BN(1));
|
|
303
|
-
quoteAssetReserveAfter = k
|
|
304
|
-
.div(MARK_PRICE_PRECISION)
|
|
305
|
-
.div(baseAssetReserveAfter);
|
|
299
|
+
quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
|
|
306
300
|
|
|
307
301
|
markPriceAfter = calculatePrice(
|
|
308
302
|
baseAssetReserveAfter,
|
|
@@ -326,17 +320,17 @@ export function calculateTargetPriceTrade(
|
|
|
326
320
|
|
|
327
321
|
let tp1 = targetPrice;
|
|
328
322
|
let tp2 = markPriceAfter;
|
|
329
|
-
let originalDiff = targetPrice.sub(
|
|
323
|
+
let originalDiff = targetPrice.sub(reservePriceBefore);
|
|
330
324
|
|
|
331
325
|
if (direction == PositionDirection.SHORT) {
|
|
332
326
|
tp1 = markPriceAfter;
|
|
333
327
|
tp2 = targetPrice;
|
|
334
|
-
originalDiff =
|
|
328
|
+
originalDiff = reservePriceBefore.sub(targetPrice);
|
|
335
329
|
}
|
|
336
330
|
|
|
337
331
|
const entryPrice = tradeSize
|
|
338
332
|
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
339
|
-
.mul(
|
|
333
|
+
.mul(PRICE_PRECISION)
|
|
340
334
|
.div(baseSize.abs());
|
|
341
335
|
|
|
342
336
|
assert(tp1.sub(tp2).lte(originalDiff), 'Target Price Calculation incorrect');
|
|
@@ -2,7 +2,7 @@ import { parsePriceData } from '@pythnetwork/client';
|
|
|
2
2
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { OracleClient, OraclePriceData } from './types';
|
|
4
4
|
import { BN } from '@project-serum/anchor';
|
|
5
|
-
import {
|
|
5
|
+
import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
6
6
|
|
|
7
7
|
export class PythClient implements OracleClient {
|
|
8
8
|
private connection: Connection;
|
|
@@ -38,6 +38,6 @@ export function convertPythPrice(price: number, exponent: number): BN {
|
|
|
38
38
|
exponent = Math.abs(exponent);
|
|
39
39
|
const pythPrecision = TEN.pow(new BN(exponent).abs());
|
|
40
40
|
return new BN(price * Math.pow(10, exponent))
|
|
41
|
-
.mul(
|
|
41
|
+
.mul(PRICE_PRECISION)
|
|
42
42
|
.div(pythPrecision);
|
|
43
43
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { OracleClient, OraclePriceData } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
-
import {
|
|
4
|
+
import { PRICE_PRECISION } from '../constants/numericConstants';
|
|
5
5
|
|
|
6
6
|
export const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
|
|
7
|
-
price:
|
|
7
|
+
price: PRICE_PRECISION,
|
|
8
8
|
slot: new BN(0),
|
|
9
9
|
confidence: new BN(1),
|
|
10
10
|
hasSufficientNumberOfDataPoints: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SwitchboardDecimal } from '@switchboard-xyz/switchboard-v2';
|
|
2
2
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { BN, Program, Idl, AnchorProvider } from '@project-serum/anchor';
|
|
4
|
-
import {
|
|
4
|
+
import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
5
5
|
import { OracleClient, OraclePriceData } from './types';
|
|
6
6
|
import { Wallet } from '../wallet';
|
|
7
7
|
import switchboardV2Idl from '../idl/switchboard_v2.json';
|
|
@@ -74,6 +74,6 @@ function getSwitchboardProgram(connection: Connection): Program {
|
|
|
74
74
|
function convertSwitchboardDecimal(switchboardDecimal: SwitchboardDecimal): BN {
|
|
75
75
|
const switchboardPrecision = TEN.pow(new BN(switchboardDecimal.scale));
|
|
76
76
|
return switchboardDecimal.mantissa
|
|
77
|
-
.mul(
|
|
77
|
+
.mul(PRICE_PRECISION)
|
|
78
78
|
.div(switchboardPrecision);
|
|
79
79
|
}
|