@drift-labs/sdk 0.1.27 → 0.1.29-master.1
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.js +13 -3
- package/lib/clearingHouse.d.ts +2 -0
- package/lib/clearingHouse.js +24 -0
- package/lib/constants/markets.js +12 -1
- package/lib/idl/clearing_house.json +66 -2
- package/lib/math/amm.d.ts +0 -18
- package/lib/math/amm.js +1 -88
- package/lib/math/repeg.d.ts +32 -0
- package/lib/math/repeg.js +178 -0
- package/lib/types.d.ts +3 -0
- package/lib/types.js +1 -0
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.ts +14 -4
- package/src/clearingHouse.ts +40 -0
- package/src/constants/markets.ts +12 -1
- package/src/idl/clearing_house.json +66 -2
- package/src/math/amm.ts +2 -127
- package/src/math/repeg.ts +253 -0
- package/src/types.ts +1 -0
- package/src/accounts/bulkAccountLoader.js +0 -180
- package/src/accounts/bulkAccountLoader.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/clearingHouse.js +0 -769
- package/src/clearingHouse.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/index.js +0 -56
- package/src/index.js.map +0 -1
- package/src/mockUSDCFaucet.js +0 -143
- package/src/mockUSDCFaucet.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/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/clearingHouse.ts
CHANGED
|
@@ -788,6 +788,46 @@ export class ClearingHouse {
|
|
|
788
788
|
});
|
|
789
789
|
}
|
|
790
790
|
|
|
791
|
+
public async expireOrders(
|
|
792
|
+
userAccountPublicKey: PublicKey,
|
|
793
|
+
userOrdersAccountPublicKey: PublicKey
|
|
794
|
+
): Promise<TransactionSignature> {
|
|
795
|
+
return await this.txSender.send(
|
|
796
|
+
wrapInTx(
|
|
797
|
+
await this.getExpireOrdersIx(
|
|
798
|
+
userAccountPublicKey,
|
|
799
|
+
userOrdersAccountPublicKey
|
|
800
|
+
)
|
|
801
|
+
),
|
|
802
|
+
[],
|
|
803
|
+
this.opts
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
public async getExpireOrdersIx(
|
|
808
|
+
userAccountPublicKey: PublicKey,
|
|
809
|
+
userOrdersAccountPublicKey: PublicKey
|
|
810
|
+
): Promise<TransactionInstruction> {
|
|
811
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
812
|
+
const userAccount: any = await this.program.account.user.fetch(
|
|
813
|
+
userAccountPublicKey
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
const orderState = this.getOrderStateAccount();
|
|
817
|
+
return await this.program.instruction.expireOrders({
|
|
818
|
+
accounts: {
|
|
819
|
+
state: await this.getStatePublicKey(),
|
|
820
|
+
filler: fillerPublicKey,
|
|
821
|
+
user: userAccountPublicKey,
|
|
822
|
+
authority: this.wallet.publicKey,
|
|
823
|
+
userPositions: userAccount.positions,
|
|
824
|
+
userOrders: userOrdersAccountPublicKey,
|
|
825
|
+
orderState: await this.getOrderStatePublicKey(),
|
|
826
|
+
orderHistory: orderState.orderHistory,
|
|
827
|
+
},
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
|
|
791
831
|
public async cancelOrder(
|
|
792
832
|
orderId: BN,
|
|
793
833
|
oracle?: PublicKey
|
package/src/constants/markets.ts
CHANGED
|
@@ -166,7 +166,7 @@ export const Markets: MarketConfig[] = [
|
|
|
166
166
|
oracleSource: OracleSource.SWITCHBOARD,
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
|
-
fullName: '
|
|
169
|
+
fullName: 'ApeCoin',
|
|
170
170
|
category: ['NFT'],
|
|
171
171
|
symbol: 'APE-PERP',
|
|
172
172
|
baseAssetSymbol: 'APE',
|
|
@@ -176,6 +176,17 @@ export const Markets: MarketConfig[] = [
|
|
|
176
176
|
launchTs: 1648475932000,
|
|
177
177
|
oracleSource: OracleSource.SWITCHBOARD,
|
|
178
178
|
},
|
|
179
|
+
{
|
|
180
|
+
fullName: 'DogeCoin',
|
|
181
|
+
category: ['Meme', 'NFT'],
|
|
182
|
+
symbol: 'DOGE-PERP',
|
|
183
|
+
baseAssetSymbol: 'DOGE',
|
|
184
|
+
marketIndex: new BN(15),
|
|
185
|
+
devnetPublicKey: '4L6YhY8VvUgmqG5MvJkUJATtzB2rFqdrJwQCmFLv4Jzy',
|
|
186
|
+
mainnetPublicKey: 'FsSM3s38PX9K7Dn6eGzuE29S2Dsk1Sss1baytTQdCaQj',
|
|
187
|
+
launchTs: 1648607439000,
|
|
188
|
+
oracleSource: OracleSource.PYTH,
|
|
189
|
+
},
|
|
179
190
|
// {
|
|
180
191
|
// symbol: 'mSOL-PERP',
|
|
181
192
|
// baseAssetSymbol: 'mSOL',
|
|
@@ -677,6 +677,52 @@
|
|
|
677
677
|
}
|
|
678
678
|
]
|
|
679
679
|
},
|
|
680
|
+
{
|
|
681
|
+
"name": "expireOrders",
|
|
682
|
+
"accounts": [
|
|
683
|
+
{
|
|
684
|
+
"name": "state",
|
|
685
|
+
"isMut": false,
|
|
686
|
+
"isSigner": false
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
"name": "orderState",
|
|
690
|
+
"isMut": false,
|
|
691
|
+
"isSigner": false
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
"name": "authority",
|
|
695
|
+
"isMut": false,
|
|
696
|
+
"isSigner": true
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
"name": "filler",
|
|
700
|
+
"isMut": true,
|
|
701
|
+
"isSigner": false
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
"name": "user",
|
|
705
|
+
"isMut": true,
|
|
706
|
+
"isSigner": false
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
"name": "userPositions",
|
|
710
|
+
"isMut": true,
|
|
711
|
+
"isSigner": false
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
"name": "userOrders",
|
|
715
|
+
"isMut": true,
|
|
716
|
+
"isSigner": false
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
"name": "orderHistory",
|
|
720
|
+
"isMut": true,
|
|
721
|
+
"isSigner": false
|
|
722
|
+
}
|
|
723
|
+
],
|
|
724
|
+
"args": []
|
|
725
|
+
},
|
|
680
726
|
{
|
|
681
727
|
"name": "fillOrder",
|
|
682
728
|
"accounts": [
|
|
@@ -1398,6 +1444,11 @@
|
|
|
1398
1444
|
"isMut": true,
|
|
1399
1445
|
"isSigner": false
|
|
1400
1446
|
},
|
|
1447
|
+
{
|
|
1448
|
+
"name": "userOrders",
|
|
1449
|
+
"isMut": true,
|
|
1450
|
+
"isSigner": false
|
|
1451
|
+
},
|
|
1401
1452
|
{
|
|
1402
1453
|
"name": "authority",
|
|
1403
1454
|
"isMut": false,
|
|
@@ -3190,8 +3241,8 @@
|
|
|
3190
3241
|
"type": "u128"
|
|
3191
3242
|
},
|
|
3192
3243
|
{
|
|
3193
|
-
"name": "
|
|
3194
|
-
"type": "
|
|
3244
|
+
"name": "netRevenueSinceLastFunding",
|
|
3245
|
+
"type": "i64"
|
|
3195
3246
|
},
|
|
3196
3247
|
{
|
|
3197
3248
|
"name": "padding2",
|
|
@@ -3800,6 +3851,9 @@
|
|
|
3800
3851
|
},
|
|
3801
3852
|
{
|
|
3802
3853
|
"name": "Fill"
|
|
3854
|
+
},
|
|
3855
|
+
{
|
|
3856
|
+
"name": "Expire"
|
|
3803
3857
|
}
|
|
3804
3858
|
]
|
|
3805
3859
|
}
|
|
@@ -4190,6 +4244,16 @@
|
|
|
4190
4244
|
"code": 6059,
|
|
4191
4245
|
"name": "InvalidOracleOffset",
|
|
4192
4246
|
"msg": "InvalidOracleOffset"
|
|
4247
|
+
},
|
|
4248
|
+
{
|
|
4249
|
+
"code": 6060,
|
|
4250
|
+
"name": "CantExpireOrders",
|
|
4251
|
+
"msg": "CantExpireOrders"
|
|
4252
|
+
},
|
|
4253
|
+
{
|
|
4254
|
+
"code": 6061,
|
|
4255
|
+
"name": "InvalidRepegPriceImpact",
|
|
4256
|
+
"msg": "AMM repeg mark price impact vs oracle too large"
|
|
4193
4257
|
}
|
|
4194
4258
|
]
|
|
4195
4259
|
}
|
package/src/math/amm.ts
CHANGED
|
@@ -2,13 +2,12 @@ import { BN } from '@project-serum/anchor';
|
|
|
2
2
|
import {
|
|
3
3
|
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
|
|
4
4
|
MARK_PRICE_PRECISION,
|
|
5
|
+
AMM_RESERVE_PRECISION,
|
|
5
6
|
PEG_PRECISION,
|
|
6
7
|
ZERO,
|
|
7
8
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
9
|
QUOTE_PRECISION,
|
|
9
|
-
AMM_RESERVE_PRECISION,
|
|
10
10
|
} from '../constants/numericConstants';
|
|
11
|
-
import { calculateBaseAssetValue } from './position';
|
|
12
11
|
import {
|
|
13
12
|
AMM,
|
|
14
13
|
PositionDirection,
|
|
@@ -17,12 +16,7 @@ import {
|
|
|
17
16
|
isVariant,
|
|
18
17
|
} from '../types';
|
|
19
18
|
import { assert } from '../assert/assert';
|
|
20
|
-
import {
|
|
21
|
-
calculatePositionPNL,
|
|
22
|
-
calculateMarkPrice,
|
|
23
|
-
convertToNumber,
|
|
24
|
-
squareRootBN,
|
|
25
|
-
} from '..';
|
|
19
|
+
import { squareRootBN } from '..';
|
|
26
20
|
|
|
27
21
|
/**
|
|
28
22
|
* Calculates a price given an arbitrary base and quote amount (they must have the same precision)
|
|
@@ -139,125 +133,6 @@ export function getSwapDirection(
|
|
|
139
133
|
return SwapDirection.ADD;
|
|
140
134
|
}
|
|
141
135
|
|
|
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
136
|
/**
|
|
262
137
|
* Helper function calculating terminal price of amm
|
|
263
138
|
*
|
|
@@ -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
|
+
}
|
package/src/types.ts
CHANGED