@drift-labs/sdk 0.1.29-master.0 → 0.1.30-master.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accounts/bulkAccountLoader.d.ts +1 -0
- package/lib/accounts/bulkAccountLoader.js +33 -13
- package/lib/clearingHouse.d.ts +4 -1
- package/lib/clearingHouse.js +49 -0
- package/lib/constants/markets.js +11 -0
- package/lib/idl/clearing_house.json +63 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/amm.d.ts +0 -20
- package/lib/math/amm.js +1 -151
- package/lib/math/repeg.d.ts +32 -0
- package/lib/math/repeg.js +178 -0
- package/lib/oracles/pythClient.js +1 -1
- package/lib/orderParams.d.ts +1 -1
- package/lib/orderParams.js +2 -2
- package/lib/tx/retryTxSender.d.ts +5 -2
- package/lib/tx/retryTxSender.js +14 -1
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.ts +40 -15
- package/src/clearingHouse.ts +71 -0
- package/src/constants/markets.ts +11 -0
- package/src/idl/clearing_house.json +63 -2
- package/src/index.ts +1 -0
- package/src/math/amm.ts +1 -212
- package/src/math/repeg.ts +253 -0
- package/src/oracles/pythClient.ts +1 -1
- package/src/orderParams.ts +3 -2
- package/src/tx/retryTxSender.ts +19 -1
- package/src/accounts/bulkUserSubscription.js +0 -56
- package/src/accounts/bulkUserSubscription.js.map +0 -1
- package/src/accounts/pollingUserAccountSubscriber.js +0 -139
- package/src/accounts/pollingUserAccountSubscriber.js.map +0 -1
- package/src/accounts/types.js +0 -11
- package/src/accounts/types.js.map +0 -1
- package/src/accounts/webSocketUserAccountSubscriber.js +0 -78
- package/src/accounts/webSocketUserAccountSubscriber.js.map +0 -1
- package/src/addresses.js +0 -59
- package/src/addresses.js.map +0 -1
- package/src/admin.js +0 -443
- package/src/admin.js.map +0 -1
- package/src/clearingHouseUser.js +0 -581
- package/src/clearingHouseUser.js.map +0 -1
- package/src/config.js +0 -37
- package/src/config.js.map +0 -1
- package/src/factory/clearingHouse.js +0 -65
- package/src/factory/clearingHouse.js.map +0 -1
- package/src/factory/clearingHouseUser.js +0 -35
- package/src/factory/clearingHouseUser.js.map +0 -1
- package/src/factory/oracleClient.js +0 -17
- package/src/factory/oracleClient.js.map +0 -1
- package/src/index.js +0 -56
- package/src/index.js.map +0 -1
- package/src/math/amm.js +0 -285
- package/src/math/amm.js.map +0 -1
- package/src/mockUSDCFaucet.js +0 -143
- package/src/mockUSDCFaucet.js.map +0 -1
- package/src/oracles/pythClient.js +0 -39
- package/src/oracles/pythClient.js.map +0 -1
- package/src/orderParams.js +0 -109
- package/src/orderParams.js.map +0 -1
- package/src/orders.js +0 -172
- package/src/orders.js.map +0 -1
- package/src/tx/retryTxSender.js +0 -137
- package/src/tx/retryTxSender.js.map +0 -1
- package/src/types.js +0 -61
- package/src/types.js.map +0 -1
- package/src/wallet.js +0 -23
- package/src/wallet.js.map +0 -1
package/src/math/amm.ts
CHANGED
|
@@ -4,11 +4,7 @@ import {
|
|
|
4
4
|
MARK_PRICE_PRECISION,
|
|
5
5
|
PEG_PRECISION,
|
|
6
6
|
ZERO,
|
|
7
|
-
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
|
-
QUOTE_PRECISION,
|
|
9
|
-
AMM_RESERVE_PRECISION,
|
|
10
7
|
} from '../constants/numericConstants';
|
|
11
|
-
import { calculateBaseAssetValue } from './position';
|
|
12
8
|
import {
|
|
13
9
|
AMM,
|
|
14
10
|
PositionDirection,
|
|
@@ -17,12 +13,7 @@ import {
|
|
|
17
13
|
isVariant,
|
|
18
14
|
} from '../types';
|
|
19
15
|
import { assert } from '../assert/assert';
|
|
20
|
-
import {
|
|
21
|
-
calculatePositionPNL,
|
|
22
|
-
calculateMarkPrice,
|
|
23
|
-
convertToNumber,
|
|
24
|
-
squareRootBN,
|
|
25
|
-
} from '..';
|
|
16
|
+
import { squareRootBN } from '..';
|
|
26
17
|
|
|
27
18
|
/**
|
|
28
19
|
* Calculates a price given an arbitrary base and quote amount (they must have the same precision)
|
|
@@ -139,125 +130,6 @@ export function getSwapDirection(
|
|
|
139
130
|
return SwapDirection.ADD;
|
|
140
131
|
}
|
|
141
132
|
|
|
142
|
-
/**
|
|
143
|
-
* Helper function calculating adjust k cost
|
|
144
|
-
* @param market
|
|
145
|
-
* @param marketIndex
|
|
146
|
-
* @param numerator
|
|
147
|
-
* @param denomenator
|
|
148
|
-
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
149
|
-
*/
|
|
150
|
-
export function calculateAdjustKCost(
|
|
151
|
-
market: Market,
|
|
152
|
-
marketIndex: BN,
|
|
153
|
-
numerator: BN,
|
|
154
|
-
denomenator: BN
|
|
155
|
-
): BN {
|
|
156
|
-
const netUserPosition = {
|
|
157
|
-
baseAssetAmount: market.baseAssetAmount,
|
|
158
|
-
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
159
|
-
marketIndex: new BN(marketIndex),
|
|
160
|
-
quoteAssetAmount: new BN(0),
|
|
161
|
-
openOrders: new BN(0),
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
165
|
-
|
|
166
|
-
const marketNewK = Object.assign({}, market);
|
|
167
|
-
marketNewK.amm = Object.assign({}, market.amm);
|
|
168
|
-
|
|
169
|
-
marketNewK.amm.baseAssetReserve = market.amm.baseAssetReserve
|
|
170
|
-
.mul(numerator)
|
|
171
|
-
.div(denomenator);
|
|
172
|
-
marketNewK.amm.quoteAssetReserve = market.amm.quoteAssetReserve
|
|
173
|
-
.mul(numerator)
|
|
174
|
-
.div(denomenator);
|
|
175
|
-
marketNewK.amm.sqrtK = market.amm.sqrtK.mul(numerator).div(denomenator);
|
|
176
|
-
|
|
177
|
-
netUserPosition.quoteAssetAmount = currentValue;
|
|
178
|
-
|
|
179
|
-
const cost = calculatePositionPNL(marketNewK, netUserPosition);
|
|
180
|
-
|
|
181
|
-
const p = PEG_PRECISION.mul(numerator).div(denomenator);
|
|
182
|
-
const x = market.amm.baseAssetReserve;
|
|
183
|
-
const y = market.amm.quoteAssetReserve;
|
|
184
|
-
const delta = market.baseAssetAmount;
|
|
185
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
186
|
-
|
|
187
|
-
const numer1 = PEG_PRECISION.sub(p).mul(y).div(PEG_PRECISION);
|
|
188
|
-
const numer20 = k
|
|
189
|
-
.mul(p)
|
|
190
|
-
.mul(p)
|
|
191
|
-
.div(PEG_PRECISION)
|
|
192
|
-
.div(PEG_PRECISION)
|
|
193
|
-
.div(x.mul(p).div(PEG_PRECISION).add(delta));
|
|
194
|
-
const numer21 = k.div(x.add(delta));
|
|
195
|
-
|
|
196
|
-
const formulaCost = numer21
|
|
197
|
-
.sub(numer20)
|
|
198
|
-
.sub(numer1)
|
|
199
|
-
.mul(market.amm.pegMultiplier)
|
|
200
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
201
|
-
console.log(convertToNumber(formulaCost, QUOTE_PRECISION));
|
|
202
|
-
|
|
203
|
-
// p.div(p.mul(x).add(delta)).sub()
|
|
204
|
-
|
|
205
|
-
return cost;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
210
|
-
*
|
|
211
|
-
* @param market
|
|
212
|
-
* @param marketIndex
|
|
213
|
-
* @param newPeg
|
|
214
|
-
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
215
|
-
*/
|
|
216
|
-
export function calculateRepegCost(
|
|
217
|
-
market: Market,
|
|
218
|
-
marketIndex: BN,
|
|
219
|
-
newPeg: BN
|
|
220
|
-
): BN {
|
|
221
|
-
const netUserPosition = {
|
|
222
|
-
baseAssetAmount: market.baseAssetAmount,
|
|
223
|
-
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
224
|
-
marketIndex: new BN(marketIndex),
|
|
225
|
-
quoteAssetAmount: new BN(0),
|
|
226
|
-
openOrders: new BN(0),
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
230
|
-
netUserPosition.quoteAssetAmount = currentValue;
|
|
231
|
-
const prevMarketPrice = calculateMarkPrice(market);
|
|
232
|
-
const marketNewPeg = Object.assign({}, market);
|
|
233
|
-
marketNewPeg.amm = Object.assign({}, market.amm);
|
|
234
|
-
|
|
235
|
-
// const marketNewPeg = JSON.parse(JSON.stringify(market));
|
|
236
|
-
marketNewPeg.amm.pegMultiplier = newPeg;
|
|
237
|
-
|
|
238
|
-
console.log(
|
|
239
|
-
'Price moves from',
|
|
240
|
-
convertToNumber(prevMarketPrice),
|
|
241
|
-
'to',
|
|
242
|
-
convertToNumber(calculateMarkPrice(marketNewPeg))
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
|
|
246
|
-
|
|
247
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
248
|
-
const newQuoteAssetReserve = k.div(
|
|
249
|
-
market.amm.baseAssetReserve.add(netUserPosition.baseAssetAmount)
|
|
250
|
-
);
|
|
251
|
-
const deltaQuoteAssetReserves = newQuoteAssetReserve.sub(
|
|
252
|
-
market.amm.quoteAssetReserve
|
|
253
|
-
);
|
|
254
|
-
const cost2 = deltaQuoteAssetReserves
|
|
255
|
-
.mul(market.amm.pegMultiplier.sub(newPeg))
|
|
256
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
257
|
-
console.log(convertToNumber(cost2, QUOTE_PRECISION));
|
|
258
|
-
return cost;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
133
|
/**
|
|
262
134
|
* Helper function calculating terminal price of amm
|
|
263
135
|
*
|
|
@@ -315,86 +187,3 @@ export function calculateMaxBaseAssetAmountToTrade(
|
|
|
315
187
|
return [new BN(0), PositionDirection.LONG];
|
|
316
188
|
}
|
|
317
189
|
}
|
|
318
|
-
|
|
319
|
-
export function calculateBudgetedK(market: Market, cost: BN): [BN, BN] {
|
|
320
|
-
// wolframalpha.com
|
|
321
|
-
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
322
|
-
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
323
|
-
|
|
324
|
-
// todo: assumes k = x * y
|
|
325
|
-
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
326
|
-
|
|
327
|
-
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
328
|
-
const x = market.amm.baseAssetReserve;
|
|
329
|
-
const y = market.amm.quoteAssetReserve;
|
|
330
|
-
|
|
331
|
-
const d = market.baseAssetAmount;
|
|
332
|
-
const Q = market.amm.pegMultiplier;
|
|
333
|
-
|
|
334
|
-
const C = cost.mul(new BN(-1));
|
|
335
|
-
|
|
336
|
-
const numer1 = y.mul(d).mul(Q).div(AMM_RESERVE_PRECISION).div(PEG_PRECISION);
|
|
337
|
-
const numer2 = C.mul(x.add(d)).div(QUOTE_PRECISION);
|
|
338
|
-
const denom1 = C.mul(x)
|
|
339
|
-
.mul(x.add(d))
|
|
340
|
-
.div(AMM_RESERVE_PRECISION)
|
|
341
|
-
.div(QUOTE_PRECISION);
|
|
342
|
-
const denom2 = y
|
|
343
|
-
.mul(d)
|
|
344
|
-
.mul(d)
|
|
345
|
-
.mul(Q)
|
|
346
|
-
.div(AMM_RESERVE_PRECISION)
|
|
347
|
-
.div(AMM_RESERVE_PRECISION)
|
|
348
|
-
.div(PEG_PRECISION);
|
|
349
|
-
|
|
350
|
-
const numerator = d
|
|
351
|
-
.mul(numer1.add(numer2))
|
|
352
|
-
.div(AMM_RESERVE_PRECISION)
|
|
353
|
-
.div(AMM_RESERVE_PRECISION)
|
|
354
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
355
|
-
const denominator = denom1
|
|
356
|
-
.add(denom2)
|
|
357
|
-
.div(AMM_RESERVE_PRECISION)
|
|
358
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
359
|
-
console.log(numerator, denominator);
|
|
360
|
-
// const p = (numerator).div(denominator);
|
|
361
|
-
|
|
362
|
-
// const formulaCost = (numer21.sub(numer20).sub(numer1)).mul(market.amm.pegMultiplier).div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
363
|
-
// console.log(convertToNumber(formulaCost, QUOTE_PRECISION))
|
|
364
|
-
|
|
365
|
-
return [numerator, denominator];
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export function calculateBudgetedPeg(market: Market, cost: BN): BN {
|
|
369
|
-
// wolframalpha.com
|
|
370
|
-
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
371
|
-
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
372
|
-
|
|
373
|
-
// todo: assumes k = x * y
|
|
374
|
-
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
375
|
-
|
|
376
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
377
|
-
const x = market.amm.baseAssetReserve;
|
|
378
|
-
const y = market.amm.quoteAssetReserve;
|
|
379
|
-
|
|
380
|
-
const d = market.baseAssetAmount;
|
|
381
|
-
const Q = market.amm.pegMultiplier;
|
|
382
|
-
|
|
383
|
-
const C = cost.mul(new BN(-1));
|
|
384
|
-
|
|
385
|
-
const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
386
|
-
const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION)
|
|
387
|
-
.div(deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO))
|
|
388
|
-
.mul(PEG_PRECISION)
|
|
389
|
-
.div(QUOTE_PRECISION);
|
|
390
|
-
console.log(
|
|
391
|
-
Q.toNumber(),
|
|
392
|
-
'change by',
|
|
393
|
-
deltaPegMultiplier.toNumber() / MARK_PRICE_PRECISION.toNumber()
|
|
394
|
-
);
|
|
395
|
-
const newPeg = Q.sub(
|
|
396
|
-
deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
return newPeg;
|
|
400
|
-
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { BN } from '@project-serum/anchor';
|
|
2
|
+
import {
|
|
3
|
+
MARK_PRICE_PRECISION,
|
|
4
|
+
AMM_RESERVE_PRECISION,
|
|
5
|
+
PEG_PRECISION,
|
|
6
|
+
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
7
|
+
QUOTE_PRECISION,
|
|
8
|
+
ZERO,
|
|
9
|
+
} from '../constants/numericConstants';
|
|
10
|
+
import { calculateBaseAssetValue } from './position';
|
|
11
|
+
import { calculateTerminalPrice } from './amm';
|
|
12
|
+
|
|
13
|
+
import { Market } from '../types';
|
|
14
|
+
import { calculatePositionPNL, calculateMarkPrice, convertToNumber } from '..';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Helper function calculating adjust k cost
|
|
18
|
+
* @param market
|
|
19
|
+
* @param marketIndex
|
|
20
|
+
* @param numerator
|
|
21
|
+
* @param denomenator
|
|
22
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
23
|
+
*/
|
|
24
|
+
export function calculateAdjustKCost(
|
|
25
|
+
market: Market,
|
|
26
|
+
marketIndex: BN,
|
|
27
|
+
numerator: BN,
|
|
28
|
+
denomenator: BN
|
|
29
|
+
): BN {
|
|
30
|
+
const netUserPosition = {
|
|
31
|
+
baseAssetAmount: market.baseAssetAmount,
|
|
32
|
+
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
33
|
+
marketIndex: new BN(marketIndex),
|
|
34
|
+
quoteAssetAmount: ZERO,
|
|
35
|
+
openOrders: ZERO,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
39
|
+
|
|
40
|
+
const marketNewK = Object.assign({}, market);
|
|
41
|
+
marketNewK.amm = Object.assign({}, market.amm);
|
|
42
|
+
|
|
43
|
+
marketNewK.amm.baseAssetReserve = market.amm.baseAssetReserve
|
|
44
|
+
.mul(numerator)
|
|
45
|
+
.div(denomenator);
|
|
46
|
+
marketNewK.amm.quoteAssetReserve = market.amm.quoteAssetReserve
|
|
47
|
+
.mul(numerator)
|
|
48
|
+
.div(denomenator);
|
|
49
|
+
marketNewK.amm.sqrtK = market.amm.sqrtK.mul(numerator).div(denomenator);
|
|
50
|
+
|
|
51
|
+
netUserPosition.quoteAssetAmount = currentValue;
|
|
52
|
+
|
|
53
|
+
const cost = calculatePositionPNL(marketNewK, netUserPosition);
|
|
54
|
+
|
|
55
|
+
return cost;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
60
|
+
*
|
|
61
|
+
* @param market
|
|
62
|
+
* @param marketIndex
|
|
63
|
+
* @param newPeg
|
|
64
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
65
|
+
*/
|
|
66
|
+
export function calculateRepegCost(
|
|
67
|
+
market: Market,
|
|
68
|
+
marketIndex: BN,
|
|
69
|
+
newPeg: BN
|
|
70
|
+
): BN {
|
|
71
|
+
const netUserPosition = {
|
|
72
|
+
baseAssetAmount: market.baseAssetAmount,
|
|
73
|
+
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
74
|
+
marketIndex: new BN(marketIndex),
|
|
75
|
+
quoteAssetAmount: new BN(0),
|
|
76
|
+
openOrders: ZERO,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
80
|
+
netUserPosition.quoteAssetAmount = currentValue;
|
|
81
|
+
const prevMarketPrice = calculateMarkPrice(market);
|
|
82
|
+
const marketNewPeg = Object.assign({}, market);
|
|
83
|
+
marketNewPeg.amm = Object.assign({}, market.amm);
|
|
84
|
+
|
|
85
|
+
// const marketNewPeg = JSON.parse(JSON.stringify(market));
|
|
86
|
+
marketNewPeg.amm.pegMultiplier = newPeg;
|
|
87
|
+
|
|
88
|
+
console.log(
|
|
89
|
+
'Price moves from',
|
|
90
|
+
convertToNumber(prevMarketPrice),
|
|
91
|
+
'to',
|
|
92
|
+
convertToNumber(calculateMarkPrice(marketNewPeg))
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
|
|
96
|
+
|
|
97
|
+
return cost;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
102
|
+
*
|
|
103
|
+
* @param market
|
|
104
|
+
* @param marketIndex
|
|
105
|
+
* @param newPeg
|
|
106
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
107
|
+
*/
|
|
108
|
+
export function calculateReserveRebalanceCost(
|
|
109
|
+
market: Market,
|
|
110
|
+
marketIndex: BN
|
|
111
|
+
): BN {
|
|
112
|
+
const netUserPosition = {
|
|
113
|
+
baseAssetAmount: market.baseAssetAmount,
|
|
114
|
+
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
115
|
+
marketIndex: new BN(marketIndex),
|
|
116
|
+
quoteAssetAmount: new BN(0),
|
|
117
|
+
openOrders: ZERO,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
121
|
+
netUserPosition.quoteAssetAmount = currentValue;
|
|
122
|
+
const prevMarketPrice = calculateMarkPrice(market);
|
|
123
|
+
const marketNewPeg = Object.assign({}, market);
|
|
124
|
+
marketNewPeg.amm = Object.assign({}, market.amm);
|
|
125
|
+
|
|
126
|
+
// const marketNewPeg = JSON.parse(JSON.stringify(market));
|
|
127
|
+
const newPeg = calculateTerminalPrice(market)
|
|
128
|
+
.mul(PEG_PRECISION)
|
|
129
|
+
.div(MARK_PRICE_PRECISION);
|
|
130
|
+
// const newPeg = prevMarketPrice.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION);
|
|
131
|
+
|
|
132
|
+
const newBaseReserve = market.amm.baseAssetReserve.add(
|
|
133
|
+
market.baseAssetAmount
|
|
134
|
+
);
|
|
135
|
+
const newQuoteReserve = market.amm.sqrtK
|
|
136
|
+
.mul(market.amm.sqrtK)
|
|
137
|
+
.div(newBaseReserve);
|
|
138
|
+
console.log(
|
|
139
|
+
'current reserves on close, quote:',
|
|
140
|
+
convertToNumber(newQuoteReserve, AMM_RESERVE_PRECISION),
|
|
141
|
+
'base:',
|
|
142
|
+
convertToNumber(newBaseReserve, AMM_RESERVE_PRECISION)
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
let newSqrtK;
|
|
146
|
+
if (newPeg.lt(market.amm.pegMultiplier)) {
|
|
147
|
+
newSqrtK = newBaseReserve;
|
|
148
|
+
} else {
|
|
149
|
+
newSqrtK = newQuoteReserve;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
marketNewPeg.amm.baseAssetReserve = newSqrtK.sub(market.baseAssetAmount); // newSqrtK.sub(market.baseAssetAmount);
|
|
153
|
+
marketNewPeg.amm.quoteAssetReserve = newSqrtK
|
|
154
|
+
.mul(newSqrtK)
|
|
155
|
+
.div(marketNewPeg.amm.baseAssetReserve);
|
|
156
|
+
marketNewPeg.amm.sqrtK = newSqrtK;
|
|
157
|
+
marketNewPeg.amm.pegMultiplier = newPeg;
|
|
158
|
+
|
|
159
|
+
console.log(
|
|
160
|
+
'Price moves from',
|
|
161
|
+
convertToNumber(prevMarketPrice),
|
|
162
|
+
'to',
|
|
163
|
+
convertToNumber(calculateMarkPrice(marketNewPeg))
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
|
|
167
|
+
|
|
168
|
+
return cost;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function calculateBudgetedK(market: Market, cost: BN): [BN, BN] {
|
|
172
|
+
// wolframalpha.com
|
|
173
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
174
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
175
|
+
|
|
176
|
+
// todo: assumes k = x * y
|
|
177
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
178
|
+
|
|
179
|
+
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
180
|
+
const x = market.amm.baseAssetReserve;
|
|
181
|
+
const y = market.amm.quoteAssetReserve;
|
|
182
|
+
|
|
183
|
+
const d = market.baseAssetAmount;
|
|
184
|
+
const Q = market.amm.pegMultiplier;
|
|
185
|
+
|
|
186
|
+
const C = cost.mul(new BN(-1));
|
|
187
|
+
|
|
188
|
+
const numer1 = y.mul(d).mul(Q).div(AMM_RESERVE_PRECISION).div(PEG_PRECISION);
|
|
189
|
+
const numer2 = C.mul(x.add(d)).div(QUOTE_PRECISION);
|
|
190
|
+
const denom1 = C.mul(x)
|
|
191
|
+
.mul(x.add(d))
|
|
192
|
+
.div(AMM_RESERVE_PRECISION)
|
|
193
|
+
.div(QUOTE_PRECISION);
|
|
194
|
+
const denom2 = y
|
|
195
|
+
.mul(d)
|
|
196
|
+
.mul(d)
|
|
197
|
+
.mul(Q)
|
|
198
|
+
.div(AMM_RESERVE_PRECISION)
|
|
199
|
+
.div(AMM_RESERVE_PRECISION)
|
|
200
|
+
.div(PEG_PRECISION);
|
|
201
|
+
|
|
202
|
+
const numerator = d
|
|
203
|
+
.mul(numer1.add(numer2))
|
|
204
|
+
.div(AMM_RESERVE_PRECISION)
|
|
205
|
+
.div(AMM_RESERVE_PRECISION)
|
|
206
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
207
|
+
const denominator = denom1
|
|
208
|
+
.add(denom2)
|
|
209
|
+
.div(AMM_RESERVE_PRECISION)
|
|
210
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
211
|
+
console.log(numerator, denominator);
|
|
212
|
+
// const p = (numerator).div(denominator);
|
|
213
|
+
|
|
214
|
+
// const formulaCost = (numer21.sub(numer20).sub(numer1)).mul(market.amm.pegMultiplier).div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
215
|
+
// console.log(convertToNumber(formulaCost, QUOTE_PRECISION))
|
|
216
|
+
|
|
217
|
+
return [numerator, denominator];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function calculateBudgetedPeg(market: Market, cost: BN): BN {
|
|
221
|
+
// wolframalpha.com
|
|
222
|
+
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
223
|
+
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
224
|
+
|
|
225
|
+
// todo: assumes k = x * y
|
|
226
|
+
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
227
|
+
|
|
228
|
+
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
229
|
+
const x = market.amm.baseAssetReserve;
|
|
230
|
+
const y = market.amm.quoteAssetReserve;
|
|
231
|
+
|
|
232
|
+
const d = market.baseAssetAmount;
|
|
233
|
+
const Q = market.amm.pegMultiplier;
|
|
234
|
+
|
|
235
|
+
const C = cost.mul(new BN(-1));
|
|
236
|
+
|
|
237
|
+
const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
238
|
+
const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION).div(
|
|
239
|
+
deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
240
|
+
);
|
|
241
|
+
// .mul(PEG_PRECISION)
|
|
242
|
+
// .div(QUOTE_PRECISION);
|
|
243
|
+
console.log(
|
|
244
|
+
Q.toNumber(),
|
|
245
|
+
'change by',
|
|
246
|
+
deltaPegMultiplier.toNumber() / MARK_PRICE_PRECISION.toNumber()
|
|
247
|
+
);
|
|
248
|
+
const newPeg = Q.sub(
|
|
249
|
+
deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
return newPeg;
|
|
253
|
+
}
|
|
@@ -28,7 +28,7 @@ export class PythClient {
|
|
|
28
28
|
): Promise<OraclePriceData> {
|
|
29
29
|
const priceData = parsePriceData(buffer);
|
|
30
30
|
return {
|
|
31
|
-
price: convertPythPrice(priceData.price, priceData.exponent),
|
|
31
|
+
price: convertPythPrice(priceData.aggregate.price, priceData.exponent),
|
|
32
32
|
slot: new BN(priceData.lastSlot.toString()),
|
|
33
33
|
confidence: convertPythPrice(priceData.confidence, priceData.exponent),
|
|
34
34
|
twap: convertPythPrice(priceData.twap.value, priceData.exponent),
|
package/src/orderParams.ts
CHANGED
|
@@ -17,7 +17,8 @@ export function getLimitOrderParams(
|
|
|
17
17
|
referrer = false,
|
|
18
18
|
userOrderId = 0,
|
|
19
19
|
postOnly = false,
|
|
20
|
-
oraclePriceOffset = ZERO
|
|
20
|
+
oraclePriceOffset = ZERO,
|
|
21
|
+
immediateOrCancel = false
|
|
21
22
|
): OrderParams {
|
|
22
23
|
return {
|
|
23
24
|
orderType: OrderType.LIMIT,
|
|
@@ -29,7 +30,7 @@ export function getLimitOrderParams(
|
|
|
29
30
|
price,
|
|
30
31
|
reduceOnly,
|
|
31
32
|
postOnly,
|
|
32
|
-
immediateOrCancel
|
|
33
|
+
immediateOrCancel,
|
|
33
34
|
positionLimit: ZERO,
|
|
34
35
|
padding0: true,
|
|
35
36
|
padding1: ZERO,
|
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
SignatureResult,
|
|
9
9
|
Transaction,
|
|
10
10
|
TransactionSignature,
|
|
11
|
+
Connection,
|
|
11
12
|
} from '@solana/web3.js';
|
|
12
13
|
import { Provider } from '@project-serum/anchor';
|
|
13
14
|
import assert from 'assert';
|
|
@@ -24,15 +25,18 @@ export class RetryTxSender implements TxSender {
|
|
|
24
25
|
provider: Provider;
|
|
25
26
|
timeout: number;
|
|
26
27
|
retrySleep: number;
|
|
28
|
+
additionalConnections: Connection[];
|
|
27
29
|
|
|
28
30
|
public constructor(
|
|
29
31
|
provider: Provider,
|
|
30
32
|
timeout?: number,
|
|
31
|
-
retrySleep?: number
|
|
33
|
+
retrySleep?: number,
|
|
34
|
+
additionalConnections = new Array<Connection>()
|
|
32
35
|
) {
|
|
33
36
|
this.provider = provider;
|
|
34
37
|
this.timeout = timeout ?? DEFAULT_TIMEOUT;
|
|
35
38
|
this.retrySleep = retrySleep ?? DEFAULT_RETRY;
|
|
39
|
+
this.additionalConnections = additionalConnections;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
async send(
|
|
@@ -54,6 +58,7 @@ export class RetryTxSender implements TxSender {
|
|
|
54
58
|
|
|
55
59
|
const txid: TransactionSignature =
|
|
56
60
|
await this.provider.connection.sendRawTransaction(rawTransaction, opts);
|
|
61
|
+
this.sendToAdditionalConnections(rawTransaction, opts);
|
|
57
62
|
|
|
58
63
|
let done = false;
|
|
59
64
|
const resolveReference: ResolveReference = {
|
|
@@ -76,6 +81,7 @@ export class RetryTxSender implements TxSender {
|
|
|
76
81
|
console.error(e);
|
|
77
82
|
stopWaiting();
|
|
78
83
|
});
|
|
84
|
+
this.sendToAdditionalConnections(rawTransaction, opts);
|
|
79
85
|
}
|
|
80
86
|
}
|
|
81
87
|
})();
|
|
@@ -193,4 +199,16 @@ export class RetryTxSender implements TxSender {
|
|
|
193
199
|
return result;
|
|
194
200
|
});
|
|
195
201
|
}
|
|
202
|
+
|
|
203
|
+
sendToAdditionalConnections(rawTx: Buffer, opts: ConfirmOptions): void {
|
|
204
|
+
this.additionalConnections.map((connection) => {
|
|
205
|
+
connection.sendRawTransaction(rawTx, opts).catch((e) => {
|
|
206
|
+
console.error(
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
`error sending tx to additional connection ${connection._rpcEndpoint}`
|
|
209
|
+
);
|
|
210
|
+
console.error(e);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
196
214
|
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bulkPollingUserSubscribe = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* @param users
|
|
6
|
-
* @param accountLoader
|
|
7
|
-
*/
|
|
8
|
-
async function bulkPollingUserSubscribe(users, accountLoader) {
|
|
9
|
-
if (users.length === 0) {
|
|
10
|
-
await accountLoader.load();
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
// Fetch all the accounts first
|
|
14
|
-
const program = users[0].clearingHouse.program;
|
|
15
|
-
let userProgramAccounts;
|
|
16
|
-
let orderProgramAccounts;
|
|
17
|
-
await Promise.all([
|
|
18
|
-
(async () => {
|
|
19
|
-
userProgramAccounts = await program.account.user.all();
|
|
20
|
-
})(),
|
|
21
|
-
(async () => {
|
|
22
|
-
orderProgramAccounts = await program.account.userOrders.all();
|
|
23
|
-
})(),
|
|
24
|
-
]);
|
|
25
|
-
// Create a map of the authority to keys
|
|
26
|
-
const authorityToKeys = new Map();
|
|
27
|
-
const userToAuthority = new Map();
|
|
28
|
-
for (const userProgramAccount of userProgramAccounts) {
|
|
29
|
-
const userAccountPublicKey = userProgramAccount.publicKey;
|
|
30
|
-
const userAccount = userProgramAccount.account;
|
|
31
|
-
authorityToKeys.set(userAccount.authority.toString(), {
|
|
32
|
-
user: userAccountPublicKey,
|
|
33
|
-
userPositions: userAccount.positions,
|
|
34
|
-
userOrders: undefined,
|
|
35
|
-
});
|
|
36
|
-
userToAuthority.set(userAccountPublicKey.toString(), userAccount.authority.toString());
|
|
37
|
-
}
|
|
38
|
-
for (const orderProgramAccount of orderProgramAccounts) {
|
|
39
|
-
const userOrderAccountPublicKey = orderProgramAccount.publicKey;
|
|
40
|
-
const userOrderAccount = orderProgramAccount.account;
|
|
41
|
-
const authority = userToAuthority.get(userOrderAccount.user.toString());
|
|
42
|
-
const userPublicKeys = authorityToKeys.get(authority);
|
|
43
|
-
userPublicKeys.userOrders = userOrderAccountPublicKey;
|
|
44
|
-
}
|
|
45
|
-
await Promise.all(users.map((user) => {
|
|
46
|
-
// Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
|
|
47
|
-
const userPublicKeys = authorityToKeys.get(user.authority.toString());
|
|
48
|
-
return user.accountSubscriber.addToAccountLoader(userPublicKeys);
|
|
49
|
-
}));
|
|
50
|
-
await accountLoader.load();
|
|
51
|
-
await Promise.all(users.map(async (user) => {
|
|
52
|
-
return user.subscribe();
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
exports.bulkPollingUserSubscribe = bulkPollingUserSubscribe;
|
|
56
|
-
//# sourceMappingURL=bulkUserSubscription.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bulkUserSubscription.js","sourceRoot":"","sources":["bulkUserSubscription.ts"],"names":[],"mappings":";;;AAOA;;;GAGG;AACI,KAAK,UAAU,wBAAwB,CAC7C,KAA0B,EAC1B,aAAgC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO;KACP;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC;IAC/C,IAAI,mBAAqC,CAAC;IAC1C,IAAI,oBAAsC,CAAC;IAC3C,MAAM,OAAO,CAAC,GAAG,CAAC;QACjB,CAAC,KAAK,IAAI,EAAE;YACX,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACxD,CAAC,CAAC,EAAE;QACJ,CAAC,KAAK,IAAI,EAAE;YACX,oBAAoB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAC/D,CAAC,CAAC,EAAE;KACJ,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1D,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,kBAAkB,IAAI,mBAAmB,EAAE;QACrD,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,SAAS,CAAC;QAC1D,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAsB,CAAC;QAE9D,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE;YACrD,IAAI,EAAE,oBAAoB;YAC1B,aAAa,EAAE,WAAW,CAAC,SAAS;YACpC,UAAU,EAAE,SAAS;SACrB,CAAC,CAAC;QAEH,eAAe,CAAC,GAAG,CAClB,oBAAoB,CAAC,QAAQ,EAAE,EAC/B,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,CAChC,CAAC;KACF;IACD,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE;QACvD,MAAM,yBAAyB,GAAG,mBAAmB,CAAC,SAAS,CAAC;QAChE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAA4B,CAAC;QAE1E,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtD,cAAc,CAAC,UAAU,GAAG,yBAAyB,CAAC;KACtD;IAED,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClB,0FAA0F;QAC1F,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtE,OACC,IAAI,CAAC,iBACL,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC,CAAC,CACF,CAAC;IAEF,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAE3B,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACxB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC,CAAC,CACF,CAAC;AACH,CAAC;AAlED,4DAkEC"}
|