@drift-labs/sdk 0.1.23-master.4 → 0.1.26
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 +2 -0
- package/lib/accounts/bulkAccountLoader.js +24 -0
- package/lib/addresses.js +5 -1
- package/lib/admin.d.ts +2 -2
- package/lib/admin.js +11 -5
- package/lib/clearingHouse.js +7 -1
- package/lib/clearingHouseUser.d.ts +12 -17
- package/lib/clearingHouseUser.js +114 -217
- package/lib/constants/markets.d.ts +6 -4
- package/lib/constants/markets.js +48 -0
- package/lib/constants/numericConstants.d.ts +2 -2
- package/lib/constants/numericConstants.js +3 -3
- package/lib/factory/oracleClient.d.ts +5 -0
- package/lib/factory/oracleClient.js +16 -0
- package/lib/idl/clearing_house.json +58 -5
- package/lib/idl/switchboard_v2.json +4663 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.js +9 -2
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +4 -16
- package/lib/math/orders.d.ts +1 -0
- package/lib/math/orders.js +19 -1
- package/lib/mockUSDCFaucet.js +5 -1
- package/lib/oracles/pythClient.d.ts +14 -0
- package/lib/oracles/pythClient.js +53 -0
- package/lib/oracles/switchboardClient.d.ts +13 -0
- package/lib/oracles/switchboardClient.js +76 -0
- package/lib/oracles/types.d.ts +15 -0
- package/lib/oracles/types.js +2 -0
- package/lib/orderParams.d.ts +1 -1
- package/lib/orderParams.js +2 -2
- package/lib/orders.js +1 -1
- package/lib/types.d.ts +5 -1
- package/package.json +2 -1
- package/src/accounts/bulkAccountLoader.ts +32 -0
- package/src/accounts/types.js +10 -0
- package/src/accounts/utils.js +7 -0
- package/src/accounts/webSocketAccountSubscriber.js +76 -0
- package/src/addresses.js +83 -0
- package/src/admin.ts +15 -4
- package/src/clearingHouse.ts +2 -0
- package/src/clearingHouseUser.ts +161 -330
- package/src/constants/markets.ts +54 -3
- package/src/constants/numericConstants.ts +2 -2
- package/src/factory/oracleClient.ts +22 -0
- package/src/idl/clearing_house.json +58 -5
- package/src/idl/switchboard_v2.json +4663 -0
- package/src/index.ts +4 -1
- package/src/math/funding.ts +9 -25
- package/src/math/orders.ts +28 -0
- package/src/mockUSDCFaucet.js +171 -0
- package/src/oracles/pythClient.ts +49 -0
- package/src/oracles/switchboardClient.ts +87 -0
- package/src/oracles/types.ts +15 -0
- package/src/orderParams.ts +3 -2
- package/src/orders.ts +1 -1
- package/src/types.js +60 -0
- package/src/types.ts +6 -1
- package/lib/pythClient.d.ts +0 -7
- package/lib/pythClient.js +0 -25
- package/src/pythClient.ts +0 -15
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import { PublicKey } from '@solana/web3.js';
|
|
3
3
|
export * from './mockUSDCFaucet';
|
|
4
|
-
export * from './
|
|
4
|
+
export * from './oracles/types';
|
|
5
|
+
export * from './oracles/pythClient';
|
|
6
|
+
export * from './oracles/switchboardClient';
|
|
5
7
|
export * from './types';
|
|
6
8
|
export * from './constants/markets';
|
|
7
9
|
export * from './accounts/webSocketClearingHouseAccountSubscriber';
|
|
@@ -16,6 +18,7 @@ export * from './clearingHouseUser';
|
|
|
16
18
|
export * from './clearingHouse';
|
|
17
19
|
export * from './factory/clearingHouse';
|
|
18
20
|
export * from './factory/clearingHouseUser';
|
|
21
|
+
export * from './factory/oracleClient';
|
|
19
22
|
export * from './math/conversion';
|
|
20
23
|
export * from './math/funding';
|
|
21
24
|
export * from './math/insuranceFund';
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -16,7 +20,9 @@ Object.defineProperty(exports, "BN", { enumerable: true, get: function () { retu
|
|
|
16
20
|
const web3_js_1 = require("@solana/web3.js");
|
|
17
21
|
Object.defineProperty(exports, "PublicKey", { enumerable: true, get: function () { return web3_js_1.PublicKey; } });
|
|
18
22
|
__exportStar(require("./mockUSDCFaucet"), exports);
|
|
19
|
-
__exportStar(require("./
|
|
23
|
+
__exportStar(require("./oracles/types"), exports);
|
|
24
|
+
__exportStar(require("./oracles/pythClient"), exports);
|
|
25
|
+
__exportStar(require("./oracles/switchboardClient"), exports);
|
|
20
26
|
__exportStar(require("./types"), exports);
|
|
21
27
|
__exportStar(require("./constants/markets"), exports);
|
|
22
28
|
__exportStar(require("./accounts/webSocketClearingHouseAccountSubscriber"), exports);
|
|
@@ -31,6 +37,7 @@ __exportStar(require("./clearingHouseUser"), exports);
|
|
|
31
37
|
__exportStar(require("./clearingHouse"), exports);
|
|
32
38
|
__exportStar(require("./factory/clearingHouse"), exports);
|
|
33
39
|
__exportStar(require("./factory/clearingHouseUser"), exports);
|
|
40
|
+
__exportStar(require("./factory/oracleClient"), exports);
|
|
34
41
|
__exportStar(require("./math/conversion"), exports);
|
|
35
42
|
__exportStar(require("./math/funding"), exports);
|
|
36
43
|
__exportStar(require("./math/insuranceFund"), exports);
|
package/lib/math/funding.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { BN } from '@project-serum/anchor';
|
|
3
|
-
import { PriceData } from '@pythnetwork/client';
|
|
4
3
|
import { Market } from '../types';
|
|
4
|
+
import { OraclePriceData } from '../oracles/types';
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
7
7
|
* @param market
|
|
8
|
-
* @param
|
|
8
|
+
* @param oraclePriceData
|
|
9
9
|
* @param periodAdjustment
|
|
10
10
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
11
11
|
*/
|
|
12
|
-
export declare function calculateAllEstimatedFundingRate(market: Market, oraclePriceData:
|
|
12
|
+
export declare function calculateAllEstimatedFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN, BN]>;
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
15
|
* @param market
|
|
@@ -18,7 +18,7 @@ export declare function calculateAllEstimatedFundingRate(market: Market, oracleP
|
|
|
18
18
|
* @param estimationMethod
|
|
19
19
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
20
20
|
*/
|
|
21
|
-
export declare function calculateEstimatedFundingRate(market: Market, oraclePriceData:
|
|
21
|
+
export declare function calculateEstimatedFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment: BN, estimationMethod: 'interpolated' | 'lowerbound' | 'capped'): Promise<BN>;
|
|
22
22
|
/**
|
|
23
23
|
*
|
|
24
24
|
* @param market
|
|
@@ -26,7 +26,7 @@ export declare function calculateEstimatedFundingRate(market: Market, oraclePric
|
|
|
26
26
|
* @param periodAdjustment
|
|
27
27
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
28
28
|
*/
|
|
29
|
-
export declare function calculateLongShortFundingRate(market: Market, oraclePriceData:
|
|
29
|
+
export declare function calculateLongShortFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN]>;
|
|
30
30
|
/**
|
|
31
31
|
*
|
|
32
32
|
* @param market
|
|
@@ -34,7 +34,7 @@ export declare function calculateLongShortFundingRate(market: Market, oraclePric
|
|
|
34
34
|
* @param periodAdjustment
|
|
35
35
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
36
36
|
*/
|
|
37
|
-
export declare function calculateLongShortFundingRateAndLiveTwaps(market: Market, oraclePriceData:
|
|
37
|
+
export declare function calculateLongShortFundingRateAndLiveTwaps(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN]>;
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
40
40
|
* @param market
|
package/lib/math/funding.js
CHANGED
|
@@ -16,7 +16,7 @@ const market_1 = require("./market");
|
|
|
16
16
|
/**
|
|
17
17
|
*
|
|
18
18
|
* @param market
|
|
19
|
-
* @param
|
|
19
|
+
* @param oraclePriceData
|
|
20
20
|
* @param periodAdjustment
|
|
21
21
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
22
22
|
*/
|
|
@@ -51,21 +51,9 @@ function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustm
|
|
|
51
51
|
const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
|
|
52
52
|
const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
|
|
53
53
|
const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(secondsInHour, secondsInHour.sub(timeSinceLastOracleTwapUpdate));
|
|
54
|
-
|
|
55
|
-
let oracleStablePriceNum = 0;
|
|
56
|
-
let oracleInputCount = 0;
|
|
57
|
-
if (oraclePriceData.price >= 0) {
|
|
58
|
-
oracleStablePriceNum += oraclePriceData.price;
|
|
59
|
-
oracleInputCount += 1;
|
|
60
|
-
}
|
|
61
|
-
if (oraclePriceData.previousPrice >= 0) {
|
|
62
|
-
oracleStablePriceNum += oraclePriceData.previousPrice;
|
|
63
|
-
oracleInputCount += 1;
|
|
64
|
-
}
|
|
65
|
-
oracleStablePriceNum = oracleStablePriceNum / oracleInputCount;
|
|
66
|
-
const oraclePriceStableWithMantissa = new anchor_1.BN(oracleStablePriceNum * numericConstants_1.MARK_PRICE_PRECISION.toNumber());
|
|
54
|
+
const oraclePrice = oraclePriceData.price;
|
|
67
55
|
let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
|
|
68
|
-
const oracleLiveVsTwap =
|
|
56
|
+
const oracleLiveVsTwap = oraclePrice
|
|
69
57
|
.sub(lastOracleTwapWithMantissa)
|
|
70
58
|
.abs()
|
|
71
59
|
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
@@ -75,7 +63,7 @@ function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustm
|
|
|
75
63
|
if (oracleLiveVsTwap.lte(numericConstants_1.MARK_PRICE_PRECISION.mul(new anchor_1.BN(10)))) {
|
|
76
64
|
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
77
65
|
.mul(lastOracleTwapWithMantissa)
|
|
78
|
-
.add(timeSinceLastMarkChange.mul(
|
|
66
|
+
.add(timeSinceLastMarkChange.mul(oraclePrice))
|
|
79
67
|
.div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
|
|
80
68
|
}
|
|
81
69
|
const twapSpread = lastMarkTwapWithMantissa.sub(lastOracleTwapWithMantissa);
|
package/lib/math/orders.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ import { ClearingHouseUser } from '../clearingHouseUser';
|
|
|
2
2
|
import { Order } from '../types';
|
|
3
3
|
export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
|
|
4
4
|
export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
|
|
5
|
+
export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
|
package/lib/math/orders.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
3
|
+
exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
function isOrderRiskIncreasing(user, order) {
|
|
@@ -52,3 +52,21 @@ function isOrderRiskIncreasingInSameDirection(user, order) {
|
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
54
54
|
exports.isOrderRiskIncreasingInSameDirection = isOrderRiskIncreasingInSameDirection;
|
|
55
|
+
function isOrderReduceOnly(user, order) {
|
|
56
|
+
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const position = user.getUserPosition(order.marketIndex) ||
|
|
60
|
+
user.getEmptyPosition(order.marketIndex);
|
|
61
|
+
// if position is long and order is long
|
|
62
|
+
if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(order.direction, 'long')) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
// if position is short and order is short
|
|
66
|
+
if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
|
|
67
|
+
(0, types_1.isVariant)(order.direction, 'short')) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return order.baseAssetAmount.abs().lte(position.baseAssetAmount.abs());
|
|
71
|
+
}
|
|
72
|
+
exports.isOrderReduceOnly = isOrderReduceOnly;
|
package/lib/mockUSDCFaucet.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="bn.js" />
|
|
3
|
+
import { PriceData } from '@pythnetwork/client';
|
|
4
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
5
|
+
import { OraclePriceData } from './types';
|
|
6
|
+
import { BN } from '@project-serum/anchor';
|
|
7
|
+
export declare class PythClient {
|
|
8
|
+
private connection;
|
|
9
|
+
constructor(connection: Connection);
|
|
10
|
+
getPriceData(pricePublicKey: PublicKey): Promise<PriceData>;
|
|
11
|
+
getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
|
|
12
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
|
|
13
|
+
}
|
|
14
|
+
export declare function convertPythPrice(price: number, exponent: number): BN;
|
|
@@ -0,0 +1,53 @@
|
|
|
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.convertPythPrice = exports.PythClient = void 0;
|
|
13
|
+
const client_1 = require("@pythnetwork/client");
|
|
14
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
15
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
16
|
+
class PythClient {
|
|
17
|
+
constructor(connection) {
|
|
18
|
+
this.connection = connection;
|
|
19
|
+
}
|
|
20
|
+
getPriceData(pricePublicKey) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
const account = yield this.connection.getAccountInfo(pricePublicKey);
|
|
23
|
+
return (0, client_1.parsePriceData)(account.data);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getOraclePriceData(pricePublicKey) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const accountInfo = yield this.connection.getAccountInfo(pricePublicKey);
|
|
29
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
getOraclePriceDataFromBuffer(buffer) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const priceData = (0, client_1.parsePriceData)(buffer);
|
|
35
|
+
return {
|
|
36
|
+
price: convertPythPrice(priceData.price, priceData.exponent),
|
|
37
|
+
slot: new anchor_1.BN(priceData.lastSlot.toString()),
|
|
38
|
+
confidence: convertPythPrice(priceData.confidence, priceData.exponent),
|
|
39
|
+
twap: convertPythPrice(priceData.twap.value, priceData.exponent),
|
|
40
|
+
twapConfidence: convertPythPrice(priceData.twac.value, priceData.exponent),
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.PythClient = PythClient;
|
|
46
|
+
function convertPythPrice(price, exponent) {
|
|
47
|
+
exponent = Math.abs(exponent);
|
|
48
|
+
const pythPrecision = numericConstants_1.TEN.pow(new anchor_1.BN(exponent).abs());
|
|
49
|
+
return new anchor_1.BN(price * Math.pow(10, exponent))
|
|
50
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
51
|
+
.div(pythPrecision);
|
|
52
|
+
}
|
|
53
|
+
exports.convertPythPrice = convertPythPrice;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { DriftEnv } from '../config';
|
|
4
|
+
import { Program } from '@project-serum/anchor';
|
|
5
|
+
import { OracleClient, OraclePriceData } from './types';
|
|
6
|
+
export declare class SwitchboardClient implements OracleClient {
|
|
7
|
+
connection: Connection;
|
|
8
|
+
env: DriftEnv;
|
|
9
|
+
constructor(connection: Connection, env: DriftEnv);
|
|
10
|
+
getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
|
|
11
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
|
|
12
|
+
getProgram(): Promise<Program>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SwitchboardClient = void 0;
|
|
16
|
+
const switchboard_v2_1 = require("@switchboard-xyz/switchboard-v2");
|
|
17
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
18
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
19
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
20
|
+
const wallet_1 = require("../wallet");
|
|
21
|
+
const switchboard_v2_json_1 = __importDefault(require("../idl/switchboard_v2.json"));
|
|
22
|
+
// cache switchboard program for every client object since itll always be the same
|
|
23
|
+
const programMap = new Map();
|
|
24
|
+
class SwitchboardClient {
|
|
25
|
+
constructor(connection, env) {
|
|
26
|
+
this.connection = connection;
|
|
27
|
+
this.env = env;
|
|
28
|
+
}
|
|
29
|
+
getOraclePriceData(pricePublicKey) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const accountInfo = yield this.connection.getAccountInfo(pricePublicKey);
|
|
32
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
getOraclePriceDataFromBuffer(buffer) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const program = yield this.getProgram();
|
|
38
|
+
const aggregatorAccountData = program.account.aggregatorAccountData.coder.accounts.decode('AggregatorAccountData', buffer);
|
|
39
|
+
const price = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound.result);
|
|
40
|
+
const confidence = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound
|
|
41
|
+
.stdDeviation);
|
|
42
|
+
const slot = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
|
|
43
|
+
return {
|
|
44
|
+
price,
|
|
45
|
+
slot,
|
|
46
|
+
confidence,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
getProgram() {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
if (programMap.has(this.env)) {
|
|
53
|
+
return programMap.get(this.env);
|
|
54
|
+
}
|
|
55
|
+
const program = yield getSwitchboardProgram(this.env, this.connection);
|
|
56
|
+
programMap.set(this.env, program);
|
|
57
|
+
return program;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.SwitchboardClient = SwitchboardClient;
|
|
62
|
+
function getSwitchboardProgram(env, connection) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const DEFAULT_KEYPAIR = web3_js_1.Keypair.fromSeed(new Uint8Array(32).fill(1));
|
|
65
|
+
const programId = (0, switchboard_v2_1.getSwitchboardPid)(env);
|
|
66
|
+
const wallet = new wallet_1.Wallet(DEFAULT_KEYPAIR);
|
|
67
|
+
const provider = new anchor_1.Provider(connection, wallet, {});
|
|
68
|
+
return new anchor_1.Program(switchboard_v2_json_1.default, programId, provider);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function convertSwitchboardDecimal(switchboardDecimal) {
|
|
72
|
+
const switchboardPrecision = numericConstants_1.TEN.pow(new anchor_1.BN(switchboardDecimal.scale));
|
|
73
|
+
return switchboardDecimal.mantissa
|
|
74
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
75
|
+
.div(switchboardPrecision);
|
|
76
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { BN } from '@project-serum/anchor';
|
|
4
|
+
import { PublicKey } from '@solana/web3.js';
|
|
5
|
+
export declare type OraclePriceData = {
|
|
6
|
+
price: BN;
|
|
7
|
+
slot: BN;
|
|
8
|
+
confidence: BN;
|
|
9
|
+
twap?: BN;
|
|
10
|
+
twapConfidence?: BN;
|
|
11
|
+
};
|
|
12
|
+
export interface OracleClient {
|
|
13
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
|
|
14
|
+
getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
|
|
15
|
+
}
|
package/lib/orderParams.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { OrderParams, OrderTriggerCondition, PositionDirection } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
-
export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
4
|
+
export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number, postOnly?: boolean): OrderParams;
|
|
5
5
|
export declare function getTriggerMarketOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
6
6
|
export declare function getTriggerLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
7
7
|
export declare function getMarketOrderParams(marketIndex: BN, direction: PositionDirection, quoteAssetAmount: BN, baseAssetAmount: BN, reduceOnly: boolean, price?: BN, discountToken?: boolean, referrer?: boolean): OrderParams;
|
package/lib/orderParams.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
5
|
const numericConstants_1 = require("./constants/numericConstants");
|
|
6
|
-
function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
|
|
6
|
+
function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0, postOnly = false) {
|
|
7
7
|
return {
|
|
8
8
|
orderType: types_1.OrderType.LIMIT,
|
|
9
9
|
userOrderId,
|
|
@@ -13,7 +13,7 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
|
|
|
13
13
|
baseAssetAmount,
|
|
14
14
|
price,
|
|
15
15
|
reduceOnly,
|
|
16
|
-
postOnly
|
|
16
|
+
postOnly,
|
|
17
17
|
immediateOrCancel: false,
|
|
18
18
|
positionLimit: numericConstants_1.ZERO,
|
|
19
19
|
padding0: true,
|
package/lib/orders.js
CHANGED
|
@@ -137,7 +137,7 @@ function isTriggerConditionSatisfied(market, order) {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
function calculateBaseAssetAmountUserCanExecute(market, order, user) {
|
|
140
|
-
const maxLeverage = user.getMaxLeverage('Initial');
|
|
140
|
+
const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
|
|
141
141
|
const freeCollateral = user.getFreeCollateral();
|
|
142
142
|
let quoteAssetAmount;
|
|
143
143
|
if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
|
package/lib/types.d.ts
CHANGED
|
@@ -225,6 +225,7 @@ export declare type OrderRecord = {
|
|
|
225
225
|
fee: BN;
|
|
226
226
|
fillerReward: BN;
|
|
227
227
|
tradeRecordId: BN;
|
|
228
|
+
quoteAssetAmountSurplus: BN;
|
|
228
229
|
};
|
|
229
230
|
export declare type StateAccount = {
|
|
230
231
|
admin: PublicKey;
|
|
@@ -272,7 +273,6 @@ export declare type OrderStateAccount = {
|
|
|
272
273
|
minOrderQuoteAssetAmount: BN;
|
|
273
274
|
};
|
|
274
275
|
export declare type MarketsAccount = {
|
|
275
|
-
accountIndex: BN;
|
|
276
276
|
markets: Market[];
|
|
277
277
|
};
|
|
278
278
|
export declare type Market = {
|
|
@@ -282,6 +282,9 @@ export declare type Market = {
|
|
|
282
282
|
baseAssetAmountShort: BN;
|
|
283
283
|
initialized: boolean;
|
|
284
284
|
openInterest: BN;
|
|
285
|
+
marginRatioInitial: number;
|
|
286
|
+
marginRatioMaintenance: number;
|
|
287
|
+
marginRatioPartial: number;
|
|
285
288
|
};
|
|
286
289
|
export declare type AMM = {
|
|
287
290
|
baseAssetReserve: BN;
|
|
@@ -434,3 +437,4 @@ export declare type OrderFillerRewardStructure = {
|
|
|
434
437
|
rewardDenominator: BN;
|
|
435
438
|
timeBasedRewardLowerBound: BN;
|
|
436
439
|
};
|
|
440
|
+
export declare type MarginCategory = 'Initial' | 'Partial' | 'Maintenance';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"@pythnetwork/client": "^2.5.1",
|
|
33
33
|
"@solana/spl-token": "^0.1.6",
|
|
34
34
|
"@solana/web3.js": "^1.22.0",
|
|
35
|
+
"@switchboard-xyz/switchboard-v2": "^0.0.67",
|
|
35
36
|
"strict-event-emitter-types": "^2.0.0",
|
|
36
37
|
"uuid": "^8.3.2"
|
|
37
38
|
},
|
|
@@ -9,6 +9,8 @@ type AccountToLoad = {
|
|
|
9
9
|
|
|
10
10
|
const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
|
|
11
11
|
|
|
12
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
13
|
+
|
|
12
14
|
export class BulkAccountLoader {
|
|
13
15
|
connection: Connection;
|
|
14
16
|
commitment: Commitment;
|
|
@@ -20,6 +22,8 @@ export class BulkAccountLoader {
|
|
|
20
22
|
// to handle clients spamming load
|
|
21
23
|
loadPromise?: Promise<void>;
|
|
22
24
|
loadPromiseResolver: () => void;
|
|
25
|
+
loggingEnabled = false;
|
|
26
|
+
lastUpdate = Date.now();
|
|
23
27
|
|
|
24
28
|
public constructor(
|
|
25
29
|
connection: Connection,
|
|
@@ -100,6 +104,10 @@ export class BulkAccountLoader {
|
|
|
100
104
|
this.loadPromiseResolver = resolver;
|
|
101
105
|
});
|
|
102
106
|
|
|
107
|
+
if (this.loggingEnabled) {
|
|
108
|
+
console.log('Loading accounts');
|
|
109
|
+
}
|
|
110
|
+
|
|
103
111
|
try {
|
|
104
112
|
const chunks = this.chunks(
|
|
105
113
|
Array.from(this.accountsToLoad.values()),
|
|
@@ -120,6 +128,20 @@ export class BulkAccountLoader {
|
|
|
120
128
|
} finally {
|
|
121
129
|
this.loadPromiseResolver();
|
|
122
130
|
this.loadPromise = undefined;
|
|
131
|
+
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
if (now - this.lastUpdate > fiveMinutes) {
|
|
134
|
+
if (this.loggingEnabled) {
|
|
135
|
+
console.log(
|
|
136
|
+
"Haven't seen updated account in five minutes. Bulk account loader creating new Connection Object"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
this.connection = new Connection(
|
|
140
|
+
// @ts-ignore
|
|
141
|
+
this.connection._rpcEndpoint,
|
|
142
|
+
this.connection.commitment
|
|
143
|
+
);
|
|
144
|
+
}
|
|
123
145
|
}
|
|
124
146
|
}
|
|
125
147
|
|
|
@@ -161,6 +183,7 @@ export class BulkAccountLoader {
|
|
|
161
183
|
buffer: newBuffer,
|
|
162
184
|
});
|
|
163
185
|
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
186
|
+
this.lastUpdate = Date.now();
|
|
164
187
|
continue;
|
|
165
188
|
}
|
|
166
189
|
|
|
@@ -175,6 +198,7 @@ export class BulkAccountLoader {
|
|
|
175
198
|
buffer: newBuffer,
|
|
176
199
|
});
|
|
177
200
|
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
201
|
+
this.lastUpdate = Date.now();
|
|
178
202
|
}
|
|
179
203
|
}
|
|
180
204
|
}
|
|
@@ -195,6 +219,10 @@ export class BulkAccountLoader {
|
|
|
195
219
|
return;
|
|
196
220
|
}
|
|
197
221
|
|
|
222
|
+
if (this.loggingEnabled) {
|
|
223
|
+
console.log(`startPolling`);
|
|
224
|
+
}
|
|
225
|
+
|
|
198
226
|
this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
|
|
199
227
|
}
|
|
200
228
|
|
|
@@ -202,6 +230,10 @@ export class BulkAccountLoader {
|
|
|
202
230
|
if (this.intervalId) {
|
|
203
231
|
clearInterval(this.intervalId);
|
|
204
232
|
this.intervalId = undefined;
|
|
233
|
+
|
|
234
|
+
if (this.loggingEnabled) {
|
|
235
|
+
console.log(`stopPolling`);
|
|
236
|
+
}
|
|
205
237
|
}
|
|
206
238
|
}
|
|
207
239
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotSubscribedError = void 0;
|
|
4
|
+
class NotSubscribedError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.name = 'NotSubscribedError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.NotSubscribedError = NotSubscribedError;
|
|
@@ -0,0 +1,76 @@
|
|
|
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.WebSocketAccountSubscriber = void 0;
|
|
13
|
+
const utils_1 = require("./utils");
|
|
14
|
+
class WebSocketAccountSubscriber {
|
|
15
|
+
constructor(accountName, program, accountPublicKey) {
|
|
16
|
+
this.accountName = accountName;
|
|
17
|
+
this.program = program;
|
|
18
|
+
this.accountPublicKey = accountPublicKey;
|
|
19
|
+
}
|
|
20
|
+
subscribe(onChange) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
if (this.listenerId) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.onChange = onChange;
|
|
26
|
+
yield this.fetch();
|
|
27
|
+
this.listenerId = this.program.provider.connection.onAccountChange(this.accountPublicKey, (accountInfo, context) => {
|
|
28
|
+
this.handleRpcResponse(context, accountInfo);
|
|
29
|
+
}, this.program.provider.opts.commitment);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
fetch() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const rpcResponse = yield this.program.provider.connection.getAccountInfoAndContext(this.accountPublicKey, this.program.provider.opts.commitment);
|
|
35
|
+
this.handleRpcResponse(rpcResponse.context, rpcResponse === null || rpcResponse === void 0 ? void 0 : rpcResponse.value);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
handleRpcResponse(context, accountInfo) {
|
|
39
|
+
const newSlot = context.slot;
|
|
40
|
+
let newBuffer = undefined;
|
|
41
|
+
if (accountInfo) {
|
|
42
|
+
newBuffer = accountInfo.data;
|
|
43
|
+
}
|
|
44
|
+
if (!this.accountData) {
|
|
45
|
+
this.accountData = {
|
|
46
|
+
buffer: newBuffer,
|
|
47
|
+
slot: newSlot,
|
|
48
|
+
};
|
|
49
|
+
if (newBuffer) {
|
|
50
|
+
this.data = this.program.account[this.accountName].coder.accounts.decode(utils_1.capitalize(this.accountName), newBuffer);
|
|
51
|
+
this.onChange(this.data);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (newSlot <= this.accountData.slot) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const oldBuffer = this.accountData.buffer;
|
|
59
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
60
|
+
this.accountData = {
|
|
61
|
+
buffer: newBuffer,
|
|
62
|
+
slot: newSlot,
|
|
63
|
+
};
|
|
64
|
+
this.data = this.program.account[this.accountName].coder.accounts.decode(utils_1.capitalize(this.accountName), newBuffer);
|
|
65
|
+
this.onChange(this.data);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
unsubscribe() {
|
|
69
|
+
if (this.listenerId) {
|
|
70
|
+
const promise = this.program.provider.connection.removeAccountChangeListener(this.listenerId);
|
|
71
|
+
this.listenerId = undefined;
|
|
72
|
+
return promise;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.WebSocketAccountSubscriber = WebSocketAccountSubscriber;
|