@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.2
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/lib/accounts/bulkAccountLoader.d.ts +6 -6
- package/lib/accounts/bulkAccountLoader.js +81 -95
- package/lib/accounts/bulkUserSubscription.js +13 -57
- package/lib/accounts/fetch.d.ts +4 -0
- package/lib/accounts/fetch.js +18 -0
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
- package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
- package/lib/accounts/pollingOracleSubscriber.js +37 -49
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
- package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
- package/lib/accounts/types.d.ts +34 -41
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
- package/lib/accounts/webSocketAccountSubscriber.js +39 -35
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
- package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
- package/lib/addresses/marketAddresses.d.ts +4 -0
- package/lib/addresses/marketAddresses.js +15 -0
- package/lib/addresses/pda.d.ts +12 -0
- package/lib/addresses/pda.js +83 -0
- package/lib/admin.d.ts +9 -17
- package/lib/admin.js +375 -558
- package/lib/clearingHouse.d.ts +86 -109
- package/lib/clearingHouse.js +828 -895
- package/lib/clearingHouseConfig.d.ts +34 -0
- package/lib/clearingHouseConfig.js +2 -0
- package/lib/clearingHouseUser.d.ts +19 -22
- package/lib/clearingHouseUser.js +155 -141
- package/lib/clearingHouseUserConfig.d.ts +14 -0
- package/lib/clearingHouseUserConfig.js +2 -0
- package/lib/config.d.ts +12 -0
- package/lib/config.js +35 -4
- package/lib/constants/banks.d.ts +16 -0
- package/lib/constants/banks.js +34 -0
- package/lib/constants/markets.d.ts +8 -3
- package/lib/constants/markets.js +13 -206
- package/lib/constants/numericConstants.d.ts +17 -0
- package/lib/constants/numericConstants.js +23 -6
- package/lib/events/eventList.d.ts +22 -0
- package/lib/events/eventList.js +77 -0
- package/lib/events/eventSubscriber.d.ts +34 -0
- package/lib/events/eventSubscriber.js +126 -0
- package/lib/events/fetchLogs.d.ts +13 -0
- package/lib/events/fetchLogs.js +39 -0
- package/lib/events/pollingLogProvider.d.ts +15 -0
- package/lib/events/pollingLogProvider.js +53 -0
- package/lib/events/sort.d.ts +2 -0
- package/lib/events/sort.js +44 -0
- package/lib/events/txEventCache.d.ts +24 -0
- package/lib/events/txEventCache.js +71 -0
- package/lib/events/types.d.ts +49 -0
- package/lib/events/types.js +20 -0
- package/lib/events/webSocketLogProvider.d.ts +12 -0
- package/lib/events/webSocketLogProvider.js +30 -0
- package/lib/examples/makeTradeExample.js +26 -27
- package/lib/factory/bigNum.d.ts +118 -0
- package/lib/factory/bigNum.js +364 -0
- package/lib/factory/oracleClient.d.ts +1 -2
- package/lib/factory/oracleClient.js +6 -2
- package/lib/idl/clearing_house.json +2287 -2938
- package/lib/index.d.ts +12 -4
- package/lib/index.js +12 -4
- package/lib/math/amm.d.ts +24 -29
- package/lib/math/amm.js +239 -178
- package/lib/math/auction.d.ts +5 -0
- package/lib/math/auction.js +39 -0
- package/lib/math/bankBalance.d.ts +9 -0
- package/lib/math/bankBalance.js +75 -0
- package/lib/math/conversion.d.ts +0 -1
- package/lib/math/conversion.js +1 -5
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +158 -175
- package/lib/math/market.d.ts +6 -6
- package/lib/math/market.js +10 -9
- package/lib/math/orders.d.ts +5 -0
- package/lib/math/orders.js +31 -1
- package/lib/math/position.d.ts +7 -5
- package/lib/math/position.js +27 -27
- package/lib/math/repeg.d.ts +22 -0
- package/lib/math/repeg.js +128 -0
- package/lib/math/trade.d.ts +5 -4
- package/lib/math/trade.js +29 -21
- package/lib/mockUSDCFaucet.js +87 -116
- package/lib/oracles/oracleClientCache.d.ts +8 -0
- package/lib/oracles/oracleClientCache.js +19 -0
- package/lib/oracles/pythClient.d.ts +3 -5
- package/lib/oracles/pythClient.js +12 -31
- package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
- package/lib/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/oracles/switchboardClient.d.ts +3 -5
- package/lib/oracles/switchboardClient.js +29 -50
- package/lib/oracles/types.d.ts +6 -1
- package/lib/orders.d.ts +6 -7
- package/lib/orders.js +10 -80
- package/lib/slot/SlotSubscriber.d.ts +12 -0
- package/lib/slot/SlotSubscriber.js +23 -0
- package/lib/tx/retryTxSender.d.ts +2 -2
- package/lib/tx/retryTxSender.js +108 -123
- package/lib/tx/types.d.ts +5 -1
- package/lib/tx/utils.d.ts +1 -1
- package/lib/tx/utils.js +11 -2
- package/lib/types.d.ts +110 -109
- package/lib/types.js +14 -1
- package/lib/userName.d.ts +4 -0
- package/lib/userName.js +20 -0
- package/lib/util/computeUnits.js +10 -21
- package/lib/util/tps.js +11 -22
- package/lib/wallet.js +7 -20
- package/package.json +11 -4
- package/src/accounts/bulkAccountLoader.ts +21 -15
- package/src/accounts/bulkUserSubscription.ts +1 -45
- package/src/accounts/fetch.ts +33 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
- package/src/accounts/pollingOracleSubscriber.ts +16 -8
- package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
- package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
- package/src/accounts/types.ts +41 -70
- package/src/accounts/webSocketAccountSubscriber.ts +33 -16
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
- package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
- package/src/addresses/marketAddresses.ts +18 -0
- package/src/addresses/pda.ts +118 -0
- package/src/admin.ts +218 -346
- package/src/clearingHouse.ts +983 -952
- package/src/clearingHouseConfig.ts +37 -0
- package/src/clearingHouseUser.ts +275 -185
- package/src/clearingHouseUserConfig.ts +18 -0
- package/src/config.ts +54 -1
- package/src/constants/banks.ts +43 -0
- package/src/constants/markets.ts +16 -207
- package/src/constants/numericConstants.ts +34 -5
- package/src/events/eventList.ts +94 -0
- package/src/events/eventSubscriber.ts +194 -0
- package/src/events/fetchLogs.ts +80 -0
- package/src/events/pollingLogProvider.ts +79 -0
- package/src/events/sort.ts +65 -0
- package/src/events/txEventCache.ts +74 -0
- package/src/events/types.ts +98 -0
- package/src/events/webSocketLogProvider.ts +38 -0
- package/src/examples/makeTradeExample.ts +20 -11
- package/src/factory/bigNum.ts +524 -0
- package/src/factory/oracleClient.ts +7 -4
- package/src/idl/clearing_house.json +2287 -2938
- package/src/index.ts +12 -4
- package/src/math/amm.ts +414 -245
- package/src/math/auction.ts +39 -0
- package/src/math/bankBalance.ts +112 -0
- package/src/math/conversion.ts +1 -11
- package/src/math/funding.ts +12 -9
- package/src/math/market.ts +37 -30
- package/src/math/orders.ts +38 -0
- package/src/math/position.ts +48 -35
- package/src/math/repeg.ts +176 -0
- package/src/math/trade.ts +45 -35
- package/src/math/utils.js +27 -0
- package/src/math/utils.js.map +1 -0
- package/src/oracles/oracleClientCache.ts +20 -0
- package/src/oracles/pythClient.ts +4 -11
- package/src/oracles/quoteAssetOracleClient.ts +25 -0
- package/src/oracles/switchboardClient.ts +11 -24
- package/src/oracles/types.ts +7 -1
- package/src/orders.ts +24 -126
- package/src/slot/SlotSubscriber.ts +32 -0
- package/src/tx/retryTxSender.ts +6 -4
- package/src/tx/types.ts +6 -1
- package/src/tx/utils.ts +22 -3
- package/src/types.ts +111 -122
- package/src/userName.ts +20 -0
- package/src/util/computeUnits.js +17 -0
- package/src/util/computeUnits.js.map +1 -0
- package/tests/bn/test.ts +255 -0
- package/tsconfig.json +12 -12
- package/lib/addresses.d.ts +0 -10
- package/lib/addresses.js +0 -93
- package/lib/constants/accounts.d.ts +0 -15
- package/lib/constants/accounts.js +0 -18
- package/lib/factory/clearingHouse.d.ts +0 -35
- package/lib/factory/clearingHouse.js +0 -81
- package/lib/factory/clearingHouseUser.d.ts +0 -19
- package/lib/factory/clearingHouseUser.js +0 -34
- package/lib/math/insuranceFund.d.ts +0 -15
- package/lib/math/insuranceFund.js +0 -33
- package/lib/settlement.d.ts +0 -4
- package/lib/settlement.js +0 -10
- package/lib/tx/defaultTxSender.d.ts +0 -8
- package/lib/tx/defaultTxSender.js +0 -12
- package/src/addresses.ts +0 -82
- package/src/constants/accounts.ts +0 -26
- package/src/factory/clearingHouse.ts +0 -173
- package/src/factory/clearingHouseUser.ts +0 -73
- package/src/math/insuranceFund.ts +0 -29
- package/src/settlement.ts +0 -9
- package/src/tx/defaultTxSender.ts +0 -24
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { BN } from '@project-serum/anchor';
|
|
2
|
+
import { assert } from '../assert/assert';
|
|
3
|
+
import {
|
|
4
|
+
MARK_PRICE_PRECISION,
|
|
5
|
+
AMM_RESERVE_PRECISION,
|
|
6
|
+
PEG_PRECISION,
|
|
7
|
+
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
|
+
PRICE_DIV_PEG,
|
|
9
|
+
QUOTE_PRECISION,
|
|
10
|
+
ZERO,
|
|
11
|
+
} from '../constants/numericConstants';
|
|
12
|
+
import { AMM } from '../types';
|
|
13
|
+
/**
|
|
14
|
+
* Helper function calculating adjust k cost
|
|
15
|
+
* @param amm
|
|
16
|
+
* @param numerator
|
|
17
|
+
* @param denomenator
|
|
18
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
19
|
+
*/
|
|
20
|
+
export function calculateAdjustKCost(
|
|
21
|
+
amm: AMM,
|
|
22
|
+
numerator: BN,
|
|
23
|
+
denomenator: BN
|
|
24
|
+
): BN {
|
|
25
|
+
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
26
|
+
const x = amm.baseAssetReserve;
|
|
27
|
+
const y = amm.quoteAssetReserve;
|
|
28
|
+
|
|
29
|
+
const d = amm.netBaseAssetAmount;
|
|
30
|
+
const Q = amm.pegMultiplier;
|
|
31
|
+
|
|
32
|
+
const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
|
|
33
|
+
|
|
34
|
+
const p = numerator.mul(MARK_PRICE_PRECISION).div(denomenator);
|
|
35
|
+
|
|
36
|
+
const cost = quoteScale
|
|
37
|
+
.div(x.add(d))
|
|
38
|
+
.sub(
|
|
39
|
+
quoteScale
|
|
40
|
+
.mul(p)
|
|
41
|
+
.div(MARK_PRICE_PRECISION)
|
|
42
|
+
.div(x.mul(p).div(MARK_PRICE_PRECISION).add(d))
|
|
43
|
+
)
|
|
44
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
45
|
+
.div(PEG_PRECISION);
|
|
46
|
+
|
|
47
|
+
return cost.mul(new BN(-1));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
52
|
+
*
|
|
53
|
+
* @param amm
|
|
54
|
+
* @param newPeg
|
|
55
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
56
|
+
*/
|
|
57
|
+
export function calculateRepegCost(amm: AMM, newPeg: BN): BN {
|
|
58
|
+
const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
|
|
59
|
+
const cost = dqar
|
|
60
|
+
.mul(newPeg.sub(amm.pegMultiplier))
|
|
61
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
62
|
+
.div(PEG_PRECISION);
|
|
63
|
+
return cost;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function calculateBudgetedKBN(
|
|
67
|
+
x: BN,
|
|
68
|
+
y: BN,
|
|
69
|
+
budget: BN,
|
|
70
|
+
Q: BN,
|
|
71
|
+
d: BN
|
|
72
|
+
): [BN, BN] {
|
|
73
|
+
assert(Q.gt(new BN(0)));
|
|
74
|
+
const C = budget.mul(new BN(-1));
|
|
75
|
+
|
|
76
|
+
let dSign = new BN(1);
|
|
77
|
+
if (d.lt(new BN(0))) {
|
|
78
|
+
dSign = new BN(-1);
|
|
79
|
+
}
|
|
80
|
+
const pegged_y_d_d = y
|
|
81
|
+
.mul(d)
|
|
82
|
+
.mul(d)
|
|
83
|
+
.mul(Q)
|
|
84
|
+
.div(AMM_RESERVE_PRECISION)
|
|
85
|
+
.div(AMM_RESERVE_PRECISION)
|
|
86
|
+
.div(PEG_PRECISION);
|
|
87
|
+
|
|
88
|
+
const numer1 = pegged_y_d_d;
|
|
89
|
+
const numer2 = C.mul(d)
|
|
90
|
+
.div(QUOTE_PRECISION)
|
|
91
|
+
.mul(x.add(d))
|
|
92
|
+
.div(AMM_RESERVE_PRECISION)
|
|
93
|
+
.mul(dSign);
|
|
94
|
+
|
|
95
|
+
const denom1 = C.mul(x)
|
|
96
|
+
.mul(x.add(d))
|
|
97
|
+
.div(AMM_RESERVE_PRECISION)
|
|
98
|
+
.div(QUOTE_PRECISION);
|
|
99
|
+
const denom2 = pegged_y_d_d;
|
|
100
|
+
|
|
101
|
+
const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
102
|
+
const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
103
|
+
|
|
104
|
+
return [numerator, denominator];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN] {
|
|
108
|
+
// wolframalpha.com
|
|
109
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
110
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*d*d*Q)
|
|
111
|
+
|
|
112
|
+
// numer
|
|
113
|
+
// = y*d*d*Q - Cxd - Cdd
|
|
114
|
+
// = y/x*Q*d*d - Cd - Cd/x
|
|
115
|
+
// = mark - C/d - C/(x)
|
|
116
|
+
// = mark/C - 1/d - 1/x
|
|
117
|
+
|
|
118
|
+
// denom
|
|
119
|
+
// = C*x*x + C*x*d + y*d*d*Q
|
|
120
|
+
// = x/d**2 + 1 / d + mark/C
|
|
121
|
+
|
|
122
|
+
// todo: assumes k = x * y
|
|
123
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
124
|
+
|
|
125
|
+
const x = amm.baseAssetReserve;
|
|
126
|
+
const y = amm.quoteAssetReserve;
|
|
127
|
+
|
|
128
|
+
const d = amm.netBaseAssetAmount;
|
|
129
|
+
const Q = amm.pegMultiplier;
|
|
130
|
+
|
|
131
|
+
const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
|
|
132
|
+
|
|
133
|
+
return [numerator, denominator];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
|
|
137
|
+
// wolframalpha.com
|
|
138
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
139
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
140
|
+
|
|
141
|
+
// todo: assumes k = x * y
|
|
142
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
143
|
+
const targetPeg = targetPrice
|
|
144
|
+
.mul(amm.baseAssetReserve)
|
|
145
|
+
.div(amm.quoteAssetReserve)
|
|
146
|
+
.div(PRICE_DIV_PEG);
|
|
147
|
+
|
|
148
|
+
const k = amm.sqrtK.mul(amm.sqrtK);
|
|
149
|
+
const x = amm.baseAssetReserve;
|
|
150
|
+
const y = amm.quoteAssetReserve;
|
|
151
|
+
|
|
152
|
+
const d = amm.netBaseAssetAmount;
|
|
153
|
+
const Q = amm.pegMultiplier;
|
|
154
|
+
|
|
155
|
+
const C = cost.mul(new BN(-1));
|
|
156
|
+
|
|
157
|
+
const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
158
|
+
const pegChangeDirection = targetPeg.sub(Q);
|
|
159
|
+
|
|
160
|
+
const useTargetPeg =
|
|
161
|
+
(deltaQuoteAssetReserves.lt(ZERO) && pegChangeDirection.gt(ZERO)) ||
|
|
162
|
+
(deltaQuoteAssetReserves.gt(ZERO) && pegChangeDirection.lt(ZERO));
|
|
163
|
+
|
|
164
|
+
if (deltaQuoteAssetReserves.eq(ZERO) || useTargetPeg) {
|
|
165
|
+
return targetPeg;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION).div(
|
|
169
|
+
deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
170
|
+
);
|
|
171
|
+
const newPeg = Q.sub(
|
|
172
|
+
deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
return newPeg;
|
|
176
|
+
}
|
package/src/math/trade.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MarketAccount, PositionDirection, SwapDirection } from '../types';
|
|
2
2
|
import { BN } from '@project-serum/anchor';
|
|
3
3
|
import { assert } from '../assert/assert';
|
|
4
4
|
import {
|
|
@@ -17,10 +17,12 @@ import {
|
|
|
17
17
|
calculatePrice,
|
|
18
18
|
getSwapDirection,
|
|
19
19
|
AssetType,
|
|
20
|
-
|
|
20
|
+
calculateUpdatedAMMSpreadReserves,
|
|
21
|
+
calculateQuoteAssetAmountSwapped,
|
|
21
22
|
} from './amm';
|
|
22
23
|
import { squareRootBN } from './utils';
|
|
23
24
|
import { isVariant } from '../types';
|
|
25
|
+
import { OraclePriceData } from '../oracles/types';
|
|
24
26
|
|
|
25
27
|
const MAXPCT = new BN(1000); //percentage units are [0,1000] => [0,1]
|
|
26
28
|
|
|
@@ -57,20 +59,21 @@ export type PriceImpactUnit =
|
|
|
57
59
|
export function calculateTradeSlippage(
|
|
58
60
|
direction: PositionDirection,
|
|
59
61
|
amount: BN,
|
|
60
|
-
market:
|
|
62
|
+
market: MarketAccount,
|
|
61
63
|
inputAssetType: AssetType = 'quote',
|
|
64
|
+
oraclePriceData?: OraclePriceData,
|
|
62
65
|
useSpread = true
|
|
63
66
|
): [BN, BN, BN, BN] {
|
|
64
67
|
let oldPrice: BN;
|
|
65
68
|
|
|
66
69
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
67
70
|
if (isVariant(direction, 'long')) {
|
|
68
|
-
oldPrice = calculateAskPrice(market);
|
|
71
|
+
oldPrice = calculateAskPrice(market, oraclePriceData);
|
|
69
72
|
} else {
|
|
70
|
-
oldPrice = calculateBidPrice(market);
|
|
73
|
+
oldPrice = calculateBidPrice(market, oraclePriceData);
|
|
71
74
|
}
|
|
72
75
|
} else {
|
|
73
|
-
oldPrice = calculateMarkPrice(market);
|
|
76
|
+
oldPrice = calculateMarkPrice(market, oraclePriceData);
|
|
74
77
|
}
|
|
75
78
|
if (amount.eq(ZERO)) {
|
|
76
79
|
return [ZERO, ZERO, oldPrice, oldPrice];
|
|
@@ -80,26 +83,33 @@ export function calculateTradeSlippage(
|
|
|
80
83
|
amount,
|
|
81
84
|
market,
|
|
82
85
|
inputAssetType,
|
|
86
|
+
oraclePriceData,
|
|
83
87
|
useSpread
|
|
84
88
|
);
|
|
85
89
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
+
);
|
|
98
|
+
|
|
99
|
+
const entryPrice = quoteAssetAmountAcquired
|
|
100
|
+
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
101
|
+
.mul(MARK_PRICE_PRECISION)
|
|
102
|
+
.div(acquiredBase.abs());
|
|
91
103
|
|
|
92
104
|
let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
93
105
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
94
|
-
const { baseAssetReserve, quoteAssetReserve } =
|
|
95
|
-
market.amm,
|
|
96
|
-
direction
|
|
97
|
-
);
|
|
106
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
107
|
+
calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
98
108
|
amm = {
|
|
99
109
|
baseAssetReserve,
|
|
100
110
|
quoteAssetReserve,
|
|
101
|
-
sqrtK:
|
|
102
|
-
pegMultiplier:
|
|
111
|
+
sqrtK: sqrtK,
|
|
112
|
+
pegMultiplier: newPeg,
|
|
103
113
|
};
|
|
104
114
|
} else {
|
|
105
115
|
amm = market.amm;
|
|
@@ -112,9 +122,9 @@ export function calculateTradeSlippage(
|
|
|
112
122
|
);
|
|
113
123
|
|
|
114
124
|
if (direction == PositionDirection.SHORT) {
|
|
115
|
-
assert(newPrice.
|
|
125
|
+
assert(newPrice.lte(oldPrice));
|
|
116
126
|
} else {
|
|
117
|
-
assert(oldPrice.
|
|
127
|
+
assert(oldPrice.lte(newPrice));
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
const pctMaxSlippage = newPrice
|
|
@@ -145,8 +155,9 @@ export function calculateTradeSlippage(
|
|
|
145
155
|
export function calculateTradeAcquiredAmounts(
|
|
146
156
|
direction: PositionDirection,
|
|
147
157
|
amount: BN,
|
|
148
|
-
market:
|
|
158
|
+
market: MarketAccount,
|
|
149
159
|
inputAssetType: AssetType = 'quote',
|
|
160
|
+
oraclePriceData: OraclePriceData,
|
|
150
161
|
useSpread = true
|
|
151
162
|
): [BN, BN] {
|
|
152
163
|
if (amount.eq(ZERO)) {
|
|
@@ -157,15 +168,13 @@ export function calculateTradeAcquiredAmounts(
|
|
|
157
168
|
|
|
158
169
|
let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
159
170
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
160
|
-
const { baseAssetReserve, quoteAssetReserve } =
|
|
161
|
-
market.amm,
|
|
162
|
-
direction
|
|
163
|
-
);
|
|
171
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
172
|
+
calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
164
173
|
amm = {
|
|
165
174
|
baseAssetReserve,
|
|
166
175
|
quoteAssetReserve,
|
|
167
|
-
sqrtK:
|
|
168
|
-
pegMultiplier:
|
|
176
|
+
sqrtK: sqrtK,
|
|
177
|
+
pegMultiplier: newPeg,
|
|
169
178
|
};
|
|
170
179
|
} else {
|
|
171
180
|
amm = market.amm;
|
|
@@ -197,19 +206,20 @@ export function calculateTradeAcquiredAmounts(
|
|
|
197
206
|
* ]
|
|
198
207
|
*/
|
|
199
208
|
export function calculateTargetPriceTrade(
|
|
200
|
-
market:
|
|
209
|
+
market: MarketAccount,
|
|
201
210
|
targetPrice: BN,
|
|
202
211
|
pct: BN = MAXPCT,
|
|
203
212
|
outputAssetType: AssetType = 'quote',
|
|
213
|
+
oraclePriceData?: OraclePriceData,
|
|
204
214
|
useSpread = true
|
|
205
215
|
): [PositionDirection, BN, BN, BN] {
|
|
206
216
|
assert(market.amm.baseAssetReserve.gt(ZERO));
|
|
207
217
|
assert(targetPrice.gt(ZERO));
|
|
208
218
|
assert(pct.lte(MAXPCT) && pct.gt(ZERO));
|
|
209
219
|
|
|
210
|
-
const markPriceBefore = calculateMarkPrice(market);
|
|
211
|
-
const bidPriceBefore = calculateBidPrice(market);
|
|
212
|
-
const askPriceBefore = calculateAskPrice(market);
|
|
220
|
+
const markPriceBefore = calculateMarkPrice(market, oraclePriceData);
|
|
221
|
+
const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
|
|
222
|
+
const askPriceBefore = calculateAskPrice(market, oraclePriceData);
|
|
213
223
|
|
|
214
224
|
let direction;
|
|
215
225
|
if (targetPrice.gt(markPriceBefore)) {
|
|
@@ -230,19 +240,19 @@ export function calculateTargetPriceTrade(
|
|
|
230
240
|
let baseAssetReserveBefore: BN;
|
|
231
241
|
let quoteAssetReserveBefore: BN;
|
|
232
242
|
|
|
243
|
+
let peg = market.amm.pegMultiplier;
|
|
244
|
+
|
|
233
245
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
234
|
-
const { baseAssetReserve, quoteAssetReserve } =
|
|
235
|
-
market.amm,
|
|
236
|
-
direction
|
|
237
|
-
);
|
|
246
|
+
const { baseAssetReserve, quoteAssetReserve, newPeg } =
|
|
247
|
+
calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
238
248
|
baseAssetReserveBefore = baseAssetReserve;
|
|
239
249
|
quoteAssetReserveBefore = quoteAssetReserve;
|
|
250
|
+
peg = newPeg;
|
|
240
251
|
} else {
|
|
241
252
|
baseAssetReserveBefore = market.amm.baseAssetReserve;
|
|
242
253
|
quoteAssetReserveBefore = market.amm.quoteAssetReserve;
|
|
243
254
|
}
|
|
244
255
|
|
|
245
|
-
const peg = market.amm.pegMultiplier;
|
|
246
256
|
const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
247
257
|
const k = invariant.mul(MARK_PRICE_PRECISION);
|
|
248
258
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.squareRootBN = void 0;
|
|
4
|
+
const __1 = require("../");
|
|
5
|
+
const squareRootBN = (n, closeness = new __1.BN(1)) => {
|
|
6
|
+
// Assuming the sqrt of n as n only
|
|
7
|
+
let x = n;
|
|
8
|
+
// The closed guess will be stored in the root
|
|
9
|
+
let root;
|
|
10
|
+
// To count the number of iterations
|
|
11
|
+
let count = 0;
|
|
12
|
+
const TWO = new __1.BN(2);
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
14
|
+
while (count < Number.MAX_SAFE_INTEGER) {
|
|
15
|
+
count++;
|
|
16
|
+
// Calculate more closed x
|
|
17
|
+
root = x.add(n.div(x)).div(TWO);
|
|
18
|
+
// Check for closeness
|
|
19
|
+
if (x.sub(root).abs().lte(closeness))
|
|
20
|
+
break;
|
|
21
|
+
// Update root
|
|
22
|
+
x = root;
|
|
23
|
+
}
|
|
24
|
+
return root;
|
|
25
|
+
};
|
|
26
|
+
exports.squareRootBN = squareRootBN;
|
|
27
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":";;;AAAA,2BAAyB;AAElB,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,MAAE,CAAC,CAAC,CAAC,EAAE,EAAE;IACxD,mCAAmC;IACnC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,8CAA8C;IAC9C,IAAI,IAAI,CAAC;IAET,oCAAoC;IACpC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,GAAG,GAAG,IAAI,MAAE,CAAC,CAAC,CAAC,CAAC;IAEtB,6DAA6D;IAC7D,OAAO,KAAK,GAAG,MAAM,CAAC,gBAAgB,EAAE;QACvC,KAAK,EAAE,CAAC;QAER,0BAA0B;QAC1B,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhC,sBAAsB;QACtB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,MAAM;QAE5C,cAAc;QACd,CAAC,GAAG,IAAI,CAAC;KACT;IAED,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AA1BW,QAAA,YAAY,gBA0BvB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OracleClient } from './types';
|
|
2
|
+
import { OracleSource } from '../types';
|
|
3
|
+
import { getOracleClient } from '../factory/oracleClient';
|
|
4
|
+
import { Connection } from '@solana/web3.js';
|
|
5
|
+
|
|
6
|
+
export class OracleClientCache {
|
|
7
|
+
cache = new Map<string, OracleClient>();
|
|
8
|
+
public constructor() {}
|
|
9
|
+
|
|
10
|
+
public get(oracleSource: OracleSource, connection: Connection) {
|
|
11
|
+
const key = Object.keys(oracleSource)[0];
|
|
12
|
+
if (this.cache.has(key)) {
|
|
13
|
+
return this.cache.get(key);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const client = getOracleClient(oracleSource, connection);
|
|
17
|
+
this.cache.set(key, client);
|
|
18
|
+
return client;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
import { parsePriceData
|
|
1
|
+
import { parsePriceData } from '@pythnetwork/client';
|
|
2
2
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
-
import { OraclePriceData } from './types';
|
|
3
|
+
import { OracleClient, OraclePriceData } from './types';
|
|
4
4
|
import { BN } from '@project-serum/anchor';
|
|
5
5
|
import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
6
6
|
|
|
7
|
-
export class PythClient {
|
|
7
|
+
export class PythClient implements OracleClient {
|
|
8
8
|
private connection: Connection;
|
|
9
9
|
|
|
10
10
|
public constructor(connection: Connection) {
|
|
11
11
|
this.connection = connection;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
|
|
15
|
-
const account = await this.connection.getAccountInfo(pricePublicKey);
|
|
16
|
-
return parsePriceData(account.data);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
14
|
public async getOraclePriceData(
|
|
20
15
|
pricePublicKey: PublicKey
|
|
21
16
|
): Promise<OraclePriceData> {
|
|
@@ -23,9 +18,7 @@ export class PythClient {
|
|
|
23
18
|
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
24
19
|
}
|
|
25
20
|
|
|
26
|
-
public
|
|
27
|
-
buffer: Buffer
|
|
28
|
-
): Promise<OraclePriceData> {
|
|
21
|
+
public getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData {
|
|
29
22
|
const priceData = parsePriceData(buffer);
|
|
30
23
|
return {
|
|
31
24
|
price: convertPythPrice(priceData.aggregate.price, priceData.exponent),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { OracleClient, OraclePriceData } from './types';
|
|
3
|
+
import { BN } from '@project-serum/anchor';
|
|
4
|
+
import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
|
|
5
|
+
|
|
6
|
+
export const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
|
|
7
|
+
price: MARK_PRICE_PRECISION,
|
|
8
|
+
slot: new BN(0),
|
|
9
|
+
confidence: new BN(1),
|
|
10
|
+
hasSufficientNumberOfDataPoints: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class QuoteAssetOracleClient implements OracleClient {
|
|
14
|
+
public constructor() {}
|
|
15
|
+
|
|
16
|
+
public async getOraclePriceData(
|
|
17
|
+
_pricePublicKey: PublicKey
|
|
18
|
+
): Promise<OraclePriceData> {
|
|
19
|
+
return Promise.resolve(QUOTE_ORACLE_PRICE_DATA);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public getOraclePriceDataFromBuffer(_buffer: Buffer): OraclePriceData {
|
|
23
|
+
return QUOTE_ORACLE_PRICE_DATA;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSwitchboardPid,
|
|
3
|
-
SwitchboardDecimal,
|
|
4
|
-
} from '@switchboard-xyz/switchboard-v2';
|
|
1
|
+
import { SwitchboardDecimal } from '@switchboard-xyz/switchboard-v2';
|
|
5
2
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
6
|
-
import { DriftEnv } from '../config';
|
|
7
3
|
import { BN, Program, Idl, AnchorProvider } from '@project-serum/anchor';
|
|
8
4
|
import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
9
5
|
import { OracleClient, OraclePriceData } from './types';
|
|
10
6
|
import { Wallet } from '../wallet';
|
|
11
7
|
import switchboardV2Idl from '../idl/switchboard_v2.json';
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
const programMap = new Map<string, Program>();
|
|
9
|
+
let program: Program | undefined;
|
|
15
10
|
|
|
16
11
|
export class SwitchboardClient implements OracleClient {
|
|
17
12
|
connection: Connection;
|
|
18
|
-
env: DriftEnv;
|
|
19
13
|
|
|
20
|
-
public constructor(connection: Connection
|
|
14
|
+
public constructor(connection: Connection) {
|
|
21
15
|
this.connection = connection;
|
|
22
|
-
this.env = env;
|
|
23
16
|
}
|
|
24
17
|
|
|
25
18
|
public async getOraclePriceData(
|
|
@@ -29,10 +22,8 @@ export class SwitchboardClient implements OracleClient {
|
|
|
29
22
|
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
30
23
|
}
|
|
31
24
|
|
|
32
|
-
public
|
|
33
|
-
|
|
34
|
-
): Promise<OraclePriceData> {
|
|
35
|
-
const program = await this.getProgram();
|
|
25
|
+
public getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData {
|
|
26
|
+
const program = this.getProgram();
|
|
36
27
|
|
|
37
28
|
const aggregatorAccountData =
|
|
38
29
|
program.account.aggregatorAccountData.coder.accounts.decode(
|
|
@@ -61,23 +52,19 @@ export class SwitchboardClient implements OracleClient {
|
|
|
61
52
|
};
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
public
|
|
65
|
-
if (
|
|
66
|
-
return
|
|
55
|
+
public getProgram(): Program {
|
|
56
|
+
if (program) {
|
|
57
|
+
return program;
|
|
67
58
|
}
|
|
68
59
|
|
|
69
|
-
|
|
70
|
-
programMap.set(this.env, program);
|
|
60
|
+
program = getSwitchboardProgram(this.connection);
|
|
71
61
|
return program;
|
|
72
62
|
}
|
|
73
63
|
}
|
|
74
64
|
|
|
75
|
-
|
|
76
|
-
env: DriftEnv,
|
|
77
|
-
connection: Connection
|
|
78
|
-
): Promise<Program> {
|
|
65
|
+
function getSwitchboardProgram(connection: Connection): Program {
|
|
79
66
|
const DEFAULT_KEYPAIR = Keypair.fromSeed(new Uint8Array(32).fill(1));
|
|
80
|
-
const programId =
|
|
67
|
+
const programId = PublicKey.default;
|
|
81
68
|
const wallet = new Wallet(DEFAULT_KEYPAIR);
|
|
82
69
|
const provider = new AnchorProvider(connection, wallet, {});
|
|
83
70
|
|
package/src/oracles/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { OracleSource } from '../types';
|
|
3
4
|
|
|
4
5
|
export type OraclePriceData = {
|
|
5
6
|
price: BN;
|
|
@@ -10,7 +11,12 @@ export type OraclePriceData = {
|
|
|
10
11
|
twapConfidence?: BN;
|
|
11
12
|
};
|
|
12
13
|
|
|
14
|
+
export type OracleInfo = {
|
|
15
|
+
publicKey: PublicKey;
|
|
16
|
+
source: OracleSource;
|
|
17
|
+
};
|
|
18
|
+
|
|
13
19
|
export interface OracleClient {
|
|
14
|
-
getOraclePriceDataFromBuffer(buffer: Buffer):
|
|
20
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData;
|
|
15
21
|
getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
|
|
16
22
|
}
|