@drift-labs/sdk 0.2.0-master.28 → 0.2.0-master.29
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/types.d.ts +0 -1
- package/lib/admin.d.ts +3 -3
- package/lib/admin.js +5 -5
- package/lib/clearingHouse.d.ts +5 -0
- package/lib/clearingHouse.js +46 -13
- package/lib/clearingHouseConfig.d.ts +1 -0
- package/lib/clearingHouseUser.js +3 -3
- package/lib/config.js +1 -1
- package/lib/idl/clearing_house.json +122 -94
- package/lib/math/insurance.js +1 -1
- package/lib/types.d.ts +21 -38
- package/package.json +1 -1
- package/src/addresses/marketAddresses.js +26 -0
- package/src/admin.ts +14 -20
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +74 -8
- package/src/clearingHouseConfig.ts +1 -0
- package/src/clearingHouseUser.ts +4 -4
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/markets.js +42 -0
- package/src/events/eventList.js +77 -0
- package/src/events/txEventCache.js +71 -0
- package/src/examples/makeTradeExample.js +157 -0
- package/src/factory/bigNum.js +390 -0
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +122 -94
- package/src/math/auction.js +42 -0
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/insurance.ts +2 -2
- package/src/math/repeg.js +128 -0
- package/src/math/trade.js +253 -0
- package/src/math/utils.js +26 -0
- package/src/math/utils.js.map +1 -0
- package/src/oracles/oracleClientCache.js +19 -0
- package/src/oracles/pythClient.js +46 -0
- package/src/oracles/quoteAssetOracleClient.js +32 -0
- package/src/oracles/switchboardClient.js +69 -0
- package/src/oracles/types.js +2 -0
- package/src/token/index.js +38 -0
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/types.ts +23 -39
- package/src/userName.js +20 -0
- package/src/util/computeUnits.js +27 -0
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.js +35 -0
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/src/math/state.ts +0 -14
|
@@ -1809,6 +1809,31 @@
|
|
|
1809
1809
|
}
|
|
1810
1810
|
]
|
|
1811
1811
|
},
|
|
1812
|
+
{
|
|
1813
|
+
"name": "updateUserDelegate",
|
|
1814
|
+
"accounts": [
|
|
1815
|
+
{
|
|
1816
|
+
"name": "user",
|
|
1817
|
+
"isMut": true,
|
|
1818
|
+
"isSigner": false
|
|
1819
|
+
},
|
|
1820
|
+
{
|
|
1821
|
+
"name": "authority",
|
|
1822
|
+
"isMut": false,
|
|
1823
|
+
"isSigner": true
|
|
1824
|
+
}
|
|
1825
|
+
],
|
|
1826
|
+
"args": [
|
|
1827
|
+
{
|
|
1828
|
+
"name": "userId",
|
|
1829
|
+
"type": "u8"
|
|
1830
|
+
},
|
|
1831
|
+
{
|
|
1832
|
+
"name": "delegate",
|
|
1833
|
+
"type": "publicKey"
|
|
1834
|
+
}
|
|
1835
|
+
]
|
|
1836
|
+
},
|
|
1812
1837
|
{
|
|
1813
1838
|
"name": "settleFundingPayment",
|
|
1814
1839
|
"accounts": [
|
|
@@ -2253,7 +2278,7 @@
|
|
|
2253
2278
|
]
|
|
2254
2279
|
},
|
|
2255
2280
|
{
|
|
2256
|
-
"name": "
|
|
2281
|
+
"name": "updatePerpFeeStructure",
|
|
2257
2282
|
"accounts": [
|
|
2258
2283
|
{
|
|
2259
2284
|
"name": "admin",
|
|
@@ -2268,7 +2293,7 @@
|
|
|
2268
2293
|
],
|
|
2269
2294
|
"args": [
|
|
2270
2295
|
{
|
|
2271
|
-
"name": "
|
|
2296
|
+
"name": "feeStructure",
|
|
2272
2297
|
"type": {
|
|
2273
2298
|
"defined": "FeeStructure"
|
|
2274
2299
|
}
|
|
@@ -2276,7 +2301,7 @@
|
|
|
2276
2301
|
]
|
|
2277
2302
|
},
|
|
2278
2303
|
{
|
|
2279
|
-
"name": "
|
|
2304
|
+
"name": "updateSpotFeeStructure",
|
|
2280
2305
|
"accounts": [
|
|
2281
2306
|
{
|
|
2282
2307
|
"name": "admin",
|
|
@@ -2291,9 +2316,9 @@
|
|
|
2291
2316
|
],
|
|
2292
2317
|
"args": [
|
|
2293
2318
|
{
|
|
2294
|
-
"name": "
|
|
2319
|
+
"name": "feeStructure",
|
|
2295
2320
|
"type": {
|
|
2296
|
-
"defined": "
|
|
2321
|
+
"defined": "FeeStructure"
|
|
2297
2322
|
}
|
|
2298
2323
|
}
|
|
2299
2324
|
]
|
|
@@ -2971,6 +2996,42 @@
|
|
|
2971
2996
|
"type": "u64"
|
|
2972
2997
|
}
|
|
2973
2998
|
]
|
|
2999
|
+
},
|
|
3000
|
+
{
|
|
3001
|
+
"name": "updateUserQuoteAssetInsuranceStake",
|
|
3002
|
+
"accounts": [
|
|
3003
|
+
{
|
|
3004
|
+
"name": "state",
|
|
3005
|
+
"isMut": false,
|
|
3006
|
+
"isSigner": false
|
|
3007
|
+
},
|
|
3008
|
+
{
|
|
3009
|
+
"name": "spotMarket",
|
|
3010
|
+
"isMut": false,
|
|
3011
|
+
"isSigner": false
|
|
3012
|
+
},
|
|
3013
|
+
{
|
|
3014
|
+
"name": "insuranceFundStake",
|
|
3015
|
+
"isMut": true,
|
|
3016
|
+
"isSigner": false
|
|
3017
|
+
},
|
|
3018
|
+
{
|
|
3019
|
+
"name": "userStats",
|
|
3020
|
+
"isMut": true,
|
|
3021
|
+
"isSigner": false
|
|
3022
|
+
},
|
|
3023
|
+
{
|
|
3024
|
+
"name": "authority",
|
|
3025
|
+
"isMut": false,
|
|
3026
|
+
"isSigner": true
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
"name": "insuranceFundVault",
|
|
3030
|
+
"isMut": true,
|
|
3031
|
+
"isSigner": false
|
|
3032
|
+
}
|
|
3033
|
+
],
|
|
3034
|
+
"args": []
|
|
2974
3035
|
}
|
|
2975
3036
|
],
|
|
2976
3037
|
"accounts": [
|
|
@@ -3447,18 +3508,6 @@
|
|
|
3447
3508
|
"name": "insuranceVault",
|
|
3448
3509
|
"type": "publicKey"
|
|
3449
3510
|
},
|
|
3450
|
-
{
|
|
3451
|
-
"name": "perpFeeStructure",
|
|
3452
|
-
"type": {
|
|
3453
|
-
"defined": "FeeStructure"
|
|
3454
|
-
}
|
|
3455
|
-
},
|
|
3456
|
-
{
|
|
3457
|
-
"name": "spotFeeStructure",
|
|
3458
|
-
"type": {
|
|
3459
|
-
"defined": "FeeStructure"
|
|
3460
|
-
}
|
|
3461
|
-
},
|
|
3462
3511
|
{
|
|
3463
3512
|
"name": "whitelistMint",
|
|
3464
3513
|
"type": "publicKey"
|
|
@@ -3512,6 +3561,18 @@
|
|
|
3512
3561
|
{
|
|
3513
3562
|
"name": "signerNonce",
|
|
3514
3563
|
"type": "u8"
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
"name": "perpFeeStructure",
|
|
3567
|
+
"type": {
|
|
3568
|
+
"defined": "FeeStructure"
|
|
3569
|
+
}
|
|
3570
|
+
},
|
|
3571
|
+
{
|
|
3572
|
+
"name": "spotFeeStructure",
|
|
3573
|
+
"type": {
|
|
3574
|
+
"defined": "FeeStructure"
|
|
3575
|
+
}
|
|
3515
3576
|
}
|
|
3516
3577
|
]
|
|
3517
3578
|
}
|
|
@@ -3525,6 +3586,10 @@
|
|
|
3525
3586
|
"name": "authority",
|
|
3526
3587
|
"type": "publicKey"
|
|
3527
3588
|
},
|
|
3589
|
+
{
|
|
3590
|
+
"name": "delegate",
|
|
3591
|
+
"type": "publicKey"
|
|
3592
|
+
},
|
|
3528
3593
|
{
|
|
3529
3594
|
"name": "userId",
|
|
3530
3595
|
"type": "u8"
|
|
@@ -3619,6 +3684,14 @@
|
|
|
3619
3684
|
"name": "totalReferrerReward",
|
|
3620
3685
|
"type": "u64"
|
|
3621
3686
|
},
|
|
3687
|
+
{
|
|
3688
|
+
"name": "currentEpochReferrerReward",
|
|
3689
|
+
"type": "u64"
|
|
3690
|
+
},
|
|
3691
|
+
{
|
|
3692
|
+
"name": "nextEpochTs",
|
|
3693
|
+
"type": "i64"
|
|
3694
|
+
},
|
|
3622
3695
|
{
|
|
3623
3696
|
"name": "fees",
|
|
3624
3697
|
"type": {
|
|
@@ -3650,8 +3723,8 @@
|
|
|
3650
3723
|
"type": "i64"
|
|
3651
3724
|
},
|
|
3652
3725
|
{
|
|
3653
|
-
"name": "
|
|
3654
|
-
"type": "
|
|
3726
|
+
"name": "stakedQuoteAssetAmount",
|
|
3727
|
+
"type": "u64"
|
|
3655
3728
|
}
|
|
3656
3729
|
]
|
|
3657
3730
|
}
|
|
@@ -4342,39 +4415,26 @@
|
|
|
4342
4415
|
"kind": "struct",
|
|
4343
4416
|
"fields": [
|
|
4344
4417
|
{
|
|
4345
|
-
"name": "
|
|
4346
|
-
"type": "u128"
|
|
4347
|
-
},
|
|
4348
|
-
{
|
|
4349
|
-
"name": "feeDenominator",
|
|
4350
|
-
"type": "u128"
|
|
4351
|
-
},
|
|
4352
|
-
{
|
|
4353
|
-
"name": "discountTokenTiers",
|
|
4418
|
+
"name": "feeTiers",
|
|
4354
4419
|
"type": {
|
|
4355
|
-
"
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
"defined": "ReferralDiscount"
|
|
4420
|
+
"array": [
|
|
4421
|
+
{
|
|
4422
|
+
"defined": "FeeTier"
|
|
4423
|
+
},
|
|
4424
|
+
10
|
|
4425
|
+
]
|
|
4362
4426
|
}
|
|
4363
4427
|
},
|
|
4364
|
-
{
|
|
4365
|
-
"name": "makerRebateNumerator",
|
|
4366
|
-
"type": "u128"
|
|
4367
|
-
},
|
|
4368
|
-
{
|
|
4369
|
-
"name": "makerRebateDenominator",
|
|
4370
|
-
"type": "u128"
|
|
4371
|
-
},
|
|
4372
4428
|
{
|
|
4373
4429
|
"name": "fillerRewardStructure",
|
|
4374
4430
|
"type": {
|
|
4375
4431
|
"defined": "OrderFillerRewardStructure"
|
|
4376
4432
|
}
|
|
4377
4433
|
},
|
|
4434
|
+
{
|
|
4435
|
+
"name": "referrerRewardEpochUpperBound",
|
|
4436
|
+
"type": "u64"
|
|
4437
|
+
},
|
|
4378
4438
|
{
|
|
4379
4439
|
"name": "flatFillerFee",
|
|
4380
4440
|
"type": "u128"
|
|
@@ -4383,77 +4443,41 @@
|
|
|
4383
4443
|
}
|
|
4384
4444
|
},
|
|
4385
4445
|
{
|
|
4386
|
-
"name": "
|
|
4446
|
+
"name": "FeeTier",
|
|
4387
4447
|
"type": {
|
|
4388
4448
|
"kind": "struct",
|
|
4389
4449
|
"fields": [
|
|
4390
4450
|
{
|
|
4391
|
-
"name": "
|
|
4392
|
-
"type":
|
|
4393
|
-
"defined": "DiscountTokenTier"
|
|
4394
|
-
}
|
|
4395
|
-
},
|
|
4396
|
-
{
|
|
4397
|
-
"name": "secondTier",
|
|
4398
|
-
"type": {
|
|
4399
|
-
"defined": "DiscountTokenTier"
|
|
4400
|
-
}
|
|
4451
|
+
"name": "feeNumerator",
|
|
4452
|
+
"type": "u32"
|
|
4401
4453
|
},
|
|
4402
4454
|
{
|
|
4403
|
-
"name": "
|
|
4404
|
-
"type":
|
|
4405
|
-
"defined": "DiscountTokenTier"
|
|
4406
|
-
}
|
|
4455
|
+
"name": "feeDenominator",
|
|
4456
|
+
"type": "u32"
|
|
4407
4457
|
},
|
|
4408
4458
|
{
|
|
4409
|
-
"name": "
|
|
4410
|
-
"type":
|
|
4411
|
-
"defined": "DiscountTokenTier"
|
|
4412
|
-
}
|
|
4413
|
-
}
|
|
4414
|
-
]
|
|
4415
|
-
}
|
|
4416
|
-
},
|
|
4417
|
-
{
|
|
4418
|
-
"name": "DiscountTokenTier",
|
|
4419
|
-
"type": {
|
|
4420
|
-
"kind": "struct",
|
|
4421
|
-
"fields": [
|
|
4422
|
-
{
|
|
4423
|
-
"name": "minimumBalance",
|
|
4424
|
-
"type": "u64"
|
|
4459
|
+
"name": "makerRebateNumerator",
|
|
4460
|
+
"type": "u32"
|
|
4425
4461
|
},
|
|
4426
4462
|
{
|
|
4427
|
-
"name": "
|
|
4428
|
-
"type": "
|
|
4463
|
+
"name": "makerRebateDenominator",
|
|
4464
|
+
"type": "u32"
|
|
4429
4465
|
},
|
|
4430
|
-
{
|
|
4431
|
-
"name": "discountDenominator",
|
|
4432
|
-
"type": "u128"
|
|
4433
|
-
}
|
|
4434
|
-
]
|
|
4435
|
-
}
|
|
4436
|
-
},
|
|
4437
|
-
{
|
|
4438
|
-
"name": "ReferralDiscount",
|
|
4439
|
-
"type": {
|
|
4440
|
-
"kind": "struct",
|
|
4441
|
-
"fields": [
|
|
4442
4466
|
{
|
|
4443
4467
|
"name": "referrerRewardNumerator",
|
|
4444
|
-
"type": "
|
|
4468
|
+
"type": "u32"
|
|
4445
4469
|
},
|
|
4446
4470
|
{
|
|
4447
4471
|
"name": "referrerRewardDenominator",
|
|
4448
|
-
"type": "
|
|
4472
|
+
"type": "u32"
|
|
4449
4473
|
},
|
|
4450
4474
|
{
|
|
4451
|
-
"name": "
|
|
4452
|
-
"type": "
|
|
4475
|
+
"name": "refereeFeeNumerator",
|
|
4476
|
+
"type": "u32"
|
|
4453
4477
|
},
|
|
4454
4478
|
{
|
|
4455
|
-
"name": "
|
|
4456
|
-
"type": "
|
|
4479
|
+
"name": "refereeFeeDenominator",
|
|
4480
|
+
"type": "u32"
|
|
4457
4481
|
}
|
|
4458
4482
|
]
|
|
4459
4483
|
}
|
|
@@ -4536,6 +4560,10 @@
|
|
|
4536
4560
|
{
|
|
4537
4561
|
"name": "openAsks",
|
|
4538
4562
|
"type": "i128"
|
|
4563
|
+
},
|
|
4564
|
+
{
|
|
4565
|
+
"name": "cumulativeDeposits",
|
|
4566
|
+
"type": "i64"
|
|
4539
4567
|
}
|
|
4540
4568
|
]
|
|
4541
4569
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAuctionPrice = exports.isAuctionComplete = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const _1 = require("../.");
|
|
6
|
+
function isAuctionComplete(order, slot) {
|
|
7
|
+
if (order.auctionDuration === 0) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return new _1.BN(slot).sub(order.slot).gt(new _1.BN(order.auctionDuration));
|
|
11
|
+
}
|
|
12
|
+
exports.isAuctionComplete = isAuctionComplete;
|
|
13
|
+
function getAuctionPrice(order, slot) {
|
|
14
|
+
const slotsElapsed = new _1.BN(slot).sub(order.slot);
|
|
15
|
+
const deltaDenominator = new _1.BN(order.auctionDuration);
|
|
16
|
+
const deltaNumerator = _1.BN.min(slotsElapsed, deltaDenominator);
|
|
17
|
+
if (deltaDenominator.eq(_1.ZERO)) {
|
|
18
|
+
return order.auctionEndPrice;
|
|
19
|
+
}
|
|
20
|
+
let priceDelta;
|
|
21
|
+
if (types_1.isVariant(order.direction, 'long')) {
|
|
22
|
+
priceDelta = order.auctionEndPrice
|
|
23
|
+
.sub(order.auctionStartPrice)
|
|
24
|
+
.mul(deltaNumerator)
|
|
25
|
+
.div(deltaDenominator);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
priceDelta = order.auctionStartPrice
|
|
29
|
+
.sub(order.auctionEndPrice)
|
|
30
|
+
.mul(deltaNumerator)
|
|
31
|
+
.div(deltaDenominator);
|
|
32
|
+
}
|
|
33
|
+
let price;
|
|
34
|
+
if (types_1.isVariant(order.direction, 'long')) {
|
|
35
|
+
price = order.auctionStartPrice.add(priceDelta);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
price = order.auctionStartPrice.sub(priceDelta);
|
|
39
|
+
}
|
|
40
|
+
return price;
|
|
41
|
+
}
|
|
42
|
+
exports.getAuctionPrice = getAuctionPrice;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToNumber = void 0;
|
|
4
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
|
+
const convertToNumber = (bigNumber, precision = numericConstants_1.MARK_PRICE_PRECISION) => {
|
|
6
|
+
if (!bigNumber)
|
|
7
|
+
return 0;
|
|
8
|
+
return (bigNumber.div(precision).toNumber() +
|
|
9
|
+
bigNumber.mod(precision).toNumber() / precision.toNumber());
|
|
10
|
+
};
|
|
11
|
+
exports.convertToNumber = convertToNumber;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateEstimatedFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
|
|
13
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
14
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
15
|
+
const market_1 = require("./market");
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param market
|
|
19
|
+
* @param oraclePriceData
|
|
20
|
+
* @param periodAdjustment
|
|
21
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
22
|
+
*/
|
|
23
|
+
function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
// periodAdjustment
|
|
26
|
+
// 1: hourly
|
|
27
|
+
// 24: daily
|
|
28
|
+
// 24 * 365.25: annualized
|
|
29
|
+
const secondsInHour = new anchor_1.BN(3600);
|
|
30
|
+
const hoursInDay = new anchor_1.BN(24);
|
|
31
|
+
const ONE = new anchor_1.BN(1);
|
|
32
|
+
if (!market.initialized) {
|
|
33
|
+
return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
34
|
+
}
|
|
35
|
+
const payFreq = new anchor_1.BN(market.amm.fundingPeriod);
|
|
36
|
+
// todo: sufficiently differs from blockchain timestamp?
|
|
37
|
+
const now = new anchor_1.BN((Date.now() / 1000).toFixed(0));
|
|
38
|
+
const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
|
|
39
|
+
// calculate real-time mark twap
|
|
40
|
+
const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
|
|
41
|
+
const lastMarkPriceTwapTs = market.amm.lastMarkPriceTwapTs;
|
|
42
|
+
const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
|
|
43
|
+
const markTwapTimeSinceLastUpdate = anchor_1.BN.max(secondsInHour, anchor_1.BN.max(numericConstants_1.ZERO, secondsInHour.sub(timeSinceLastMarkChange)));
|
|
44
|
+
const baseAssetPriceWithMantissa = market_1.calculateMarkPrice(market, oraclePriceData);
|
|
45
|
+
const markTwapWithMantissa = markTwapTimeSinceLastUpdate
|
|
46
|
+
.mul(lastMarkTwapWithMantissa)
|
|
47
|
+
.add(timeSinceLastMarkChange.mul(baseAssetPriceWithMantissa))
|
|
48
|
+
.div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
|
|
49
|
+
// calculate real-time (predicted) oracle twap
|
|
50
|
+
// note: oracle twap depends on `when the chord is struck` (market is trade)
|
|
51
|
+
const lastOracleTwapWithMantissa = market.amm.lastOraclePriceTwap;
|
|
52
|
+
const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
|
|
53
|
+
const oracleInvalidDuration = anchor_1.BN.max(numericConstants_1.ZERO, lastMarkPriceTwapTs.sub(lastOraclePriceTwapTs));
|
|
54
|
+
const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
|
|
55
|
+
const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(ONE, anchor_1.BN.min(secondsInHour, anchor_1.BN.max(ONE, secondsInHour.sub(timeSinceLastOracleTwapUpdate))));
|
|
56
|
+
let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
|
|
57
|
+
// if passing live oracle data, improve predicted calc estimate
|
|
58
|
+
if (oraclePriceData) {
|
|
59
|
+
const oraclePrice = oraclePriceData.price;
|
|
60
|
+
const oracleLiveVsTwap = oraclePrice
|
|
61
|
+
.sub(lastOracleTwapWithMantissa)
|
|
62
|
+
.abs()
|
|
63
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
64
|
+
.mul(new anchor_1.BN(100))
|
|
65
|
+
.div(lastOracleTwapWithMantissa);
|
|
66
|
+
// verify pyth live input is within 10% of last twap for live update
|
|
67
|
+
if (oracleLiveVsTwap.lte(numericConstants_1.MARK_PRICE_PRECISION.mul(new anchor_1.BN(10)))) {
|
|
68
|
+
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
69
|
+
.mul(lastOracleTwapWithMantissa)
|
|
70
|
+
.add(timeSinceLastMarkChange.mul(oraclePrice))
|
|
71
|
+
.div(timeSinceLastMarkChange.add(oracleTwapTimeSinceLastUpdate));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const shrunkLastOracleTwapwithMantissa = oracleTwapTimeSinceLastUpdate
|
|
75
|
+
.mul(lastOracleTwapWithMantissa)
|
|
76
|
+
.add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
|
|
77
|
+
.div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
|
|
78
|
+
const twapSpread = lastMarkTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
|
|
79
|
+
const twapSpreadPct = twapSpread
|
|
80
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
81
|
+
.mul(new anchor_1.BN(100))
|
|
82
|
+
.div(shrunkLastOracleTwapwithMantissa);
|
|
83
|
+
const lowerboundEst = twapSpreadPct
|
|
84
|
+
.mul(payFreq)
|
|
85
|
+
.mul(anchor_1.BN.min(secondsInHour, timeSinceLastUpdate))
|
|
86
|
+
.mul(periodAdjustment)
|
|
87
|
+
.div(secondsInHour)
|
|
88
|
+
.div(secondsInHour)
|
|
89
|
+
.div(hoursInDay);
|
|
90
|
+
const interpEst = twapSpreadPct.mul(periodAdjustment).div(hoursInDay);
|
|
91
|
+
const interpRateQuote = twapSpreadPct
|
|
92
|
+
.mul(periodAdjustment)
|
|
93
|
+
.div(hoursInDay)
|
|
94
|
+
.div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION));
|
|
95
|
+
let feePoolSize = calculateFundingPool(market);
|
|
96
|
+
if (interpRateQuote.lt(new anchor_1.BN(0))) {
|
|
97
|
+
feePoolSize = feePoolSize.mul(new anchor_1.BN(-1));
|
|
98
|
+
}
|
|
99
|
+
let cappedAltEst;
|
|
100
|
+
let largerSide;
|
|
101
|
+
let smallerSide;
|
|
102
|
+
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
|
|
103
|
+
largerSide = market.baseAssetAmountLong.abs();
|
|
104
|
+
smallerSide = market.baseAssetAmountShort.abs();
|
|
105
|
+
if (twapSpread.gt(new anchor_1.BN(0))) {
|
|
106
|
+
return [
|
|
107
|
+
markTwapWithMantissa,
|
|
108
|
+
oracleTwapWithMantissa,
|
|
109
|
+
lowerboundEst,
|
|
110
|
+
interpEst,
|
|
111
|
+
interpEst,
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
|
|
116
|
+
largerSide = market.baseAssetAmountShort.abs();
|
|
117
|
+
smallerSide = market.baseAssetAmountLong.abs();
|
|
118
|
+
if (twapSpread.lt(new anchor_1.BN(0))) {
|
|
119
|
+
return [
|
|
120
|
+
markTwapWithMantissa,
|
|
121
|
+
oracleTwapWithMantissa,
|
|
122
|
+
lowerboundEst,
|
|
123
|
+
interpEst,
|
|
124
|
+
interpEst,
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return [
|
|
130
|
+
markTwapWithMantissa,
|
|
131
|
+
oracleTwapWithMantissa,
|
|
132
|
+
lowerboundEst,
|
|
133
|
+
interpEst,
|
|
134
|
+
interpEst,
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
if (largerSide.gt(numericConstants_1.ZERO)) {
|
|
138
|
+
// funding smaller flow
|
|
139
|
+
cappedAltEst = smallerSide.mul(twapSpread).div(hoursInDay);
|
|
140
|
+
const feePoolTopOff = feePoolSize
|
|
141
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION))
|
|
142
|
+
.mul(numericConstants_1.AMM_RESERVE_PRECISION);
|
|
143
|
+
cappedAltEst = cappedAltEst.add(feePoolTopOff).div(largerSide);
|
|
144
|
+
cappedAltEst = cappedAltEst
|
|
145
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
146
|
+
.mul(new anchor_1.BN(100))
|
|
147
|
+
.div(oracleTwapWithMantissa)
|
|
148
|
+
.mul(periodAdjustment);
|
|
149
|
+
if (cappedAltEst.abs().gte(interpEst.abs())) {
|
|
150
|
+
cappedAltEst = interpEst;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
cappedAltEst = interpEst;
|
|
155
|
+
}
|
|
156
|
+
return [
|
|
157
|
+
markTwapWithMantissa,
|
|
158
|
+
oracleTwapWithMantissa,
|
|
159
|
+
lowerboundEst,
|
|
160
|
+
cappedAltEst,
|
|
161
|
+
interpEst,
|
|
162
|
+
];
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
exports.calculateAllEstimatedFundingRate = calculateAllEstimatedFundingRate;
|
|
166
|
+
/**
|
|
167
|
+
*
|
|
168
|
+
* @param market
|
|
169
|
+
* @param oraclePriceData
|
|
170
|
+
* @param periodAdjustment
|
|
171
|
+
* @param estimationMethod
|
|
172
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
173
|
+
*/
|
|
174
|
+
function calculateEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1), estimationMethod) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
const [_1, _2, lowerboundEst, cappedAltEst, interpEst] = yield calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
|
|
177
|
+
if (estimationMethod == 'lowerbound') {
|
|
178
|
+
//assuming remaining funding period has no gap
|
|
179
|
+
return lowerboundEst;
|
|
180
|
+
}
|
|
181
|
+
else if (estimationMethod == 'capped') {
|
|
182
|
+
return cappedAltEst;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return interpEst;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
|
|
190
|
+
/**
|
|
191
|
+
*
|
|
192
|
+
* @param market
|
|
193
|
+
* @param oraclePriceData
|
|
194
|
+
* @param periodAdjustment
|
|
195
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
196
|
+
*/
|
|
197
|
+
function calculateLongShortFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const [_1, _2, _, cappedAltEst, interpEst] = yield calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
|
|
200
|
+
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
|
|
201
|
+
return [cappedAltEst, interpEst];
|
|
202
|
+
}
|
|
203
|
+
else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
|
|
204
|
+
return [interpEst, cappedAltEst];
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
return [interpEst, interpEst];
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
exports.calculateLongShortFundingRate = calculateLongShortFundingRate;
|
|
212
|
+
/**
|
|
213
|
+
*
|
|
214
|
+
* @param market
|
|
215
|
+
* @param oraclePriceData
|
|
216
|
+
* @param periodAdjustment
|
|
217
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
218
|
+
*/
|
|
219
|
+
function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
|
|
220
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = yield calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
|
|
222
|
+
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
|
|
223
|
+
return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
|
|
224
|
+
}
|
|
225
|
+
else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
|
|
226
|
+
return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
return [markTwapLive, oracleTwapLive, interpEst, interpEst];
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
exports.calculateLongShortFundingRateAndLiveTwaps = calculateLongShortFundingRateAndLiveTwaps;
|
|
234
|
+
/**
|
|
235
|
+
*
|
|
236
|
+
* @param market
|
|
237
|
+
* @returns Estimated fee pool size
|
|
238
|
+
*/
|
|
239
|
+
function calculateFundingPool(market) {
|
|
240
|
+
// todo
|
|
241
|
+
const totalFeeLB = market.amm.totalExchangeFee.div(new anchor_1.BN(2));
|
|
242
|
+
const feePool = anchor_1.BN.max(numericConstants_1.ZERO, market.amm.totalFeeMinusDistributions
|
|
243
|
+
.sub(totalFeeLB)
|
|
244
|
+
.mul(new anchor_1.BN(1))
|
|
245
|
+
.div(new anchor_1.BN(3)));
|
|
246
|
+
return feePool;
|
|
247
|
+
}
|
|
248
|
+
exports.calculateFundingPool = calculateFundingPool;
|
package/src/math/insurance.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZERO } from '../constants/numericConstants';
|
|
2
2
|
import { BN } from '../index';
|
|
3
3
|
|
|
4
4
|
export function stakeAmountToShares(
|
|
@@ -25,7 +25,7 @@ export function unstakeSharesToAmount(
|
|
|
25
25
|
if (totalIfShares.gt(ZERO)) {
|
|
26
26
|
amount = BN.max(
|
|
27
27
|
ZERO,
|
|
28
|
-
nShares.mul(insuranceFundVaultBalance).div(totalIfShares)
|
|
28
|
+
nShares.mul(insuranceFundVaultBalance).div(totalIfShares)
|
|
29
29
|
);
|
|
30
30
|
} else {
|
|
31
31
|
amount = ZERO;
|