@drift-labs/sdk 0.1.24 → 0.1.25-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 +16 -2
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +4 -4
- package/lib/accounts/webSocketAccountSubscriber.js +2 -2
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +2 -2
- package/lib/addresses.js +5 -1
- package/lib/admin.d.ts +1 -1
- package/lib/admin.js +15 -10
- package/lib/clearingHouse.js +26 -20
- package/lib/clearingHouseUser.js +18 -18
- package/lib/constants/markets.d.ts +4 -4
- package/lib/constants/markets.js +22 -0
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +2 -1
- package/lib/examples/makeTradeExample.js +6 -6
- package/lib/factory/oracleClient.d.ts +5 -0
- package/lib/factory/oracleClient.js +16 -0
- package/lib/idl/clearing_house.json +11 -1
- package/lib/idl/switchboard_v2.json +4663 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.js +9 -2
- package/lib/math/amm.js +12 -12
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +5 -17
- package/lib/math/market.js +2 -2
- package/lib/math/orders.js +9 -9
- package/lib/math/position.js +1 -1
- package/lib/math/trade.js +18 -18
- 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 +19 -19
- package/lib/tx/retryTxSender.js +1 -1
- package/lib/types.d.ts +1 -0
- package/package.json +2 -1
- package/src/accounts/bulkAccountLoader.ts +19 -0
- package/src/admin.ts +2 -0
- package/src/clearingHouse.ts +2 -0
- package/src/constants/markets.ts +26 -3
- package/src/constants/numericConstants.ts +1 -0
- package/src/factory/oracleClient.ts +22 -0
- package/src/idl/clearing_house.json +11 -1
- package/src/idl/switchboard_v2.json +4663 -0
- package/src/index.ts +4 -1
- package/src/math/funding.ts +9 -25
- 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/types.ts +1 -0
- package/lib/pythClient.d.ts +0 -7
- package/lib/pythClient.js +0 -25
- package/src/pythClient.ts +0 -15
package/src/index.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { BN } from '@project-serum/anchor';
|
|
|
2
2
|
import { PublicKey } from '@solana/web3.js';
|
|
3
3
|
|
|
4
4
|
export * from './mockUSDCFaucet';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './oracles/types';
|
|
6
|
+
export * from './oracles/pythClient';
|
|
7
|
+
export * from './oracles/switchboardClient';
|
|
6
8
|
export * from './types';
|
|
7
9
|
export * from './constants/markets';
|
|
8
10
|
export * from './accounts/webSocketClearingHouseAccountSubscriber';
|
|
@@ -17,6 +19,7 @@ export * from './clearingHouseUser';
|
|
|
17
19
|
export * from './clearingHouse';
|
|
18
20
|
export * from './factory/clearingHouse';
|
|
19
21
|
export * from './factory/clearingHouseUser';
|
|
22
|
+
export * from './factory/oracleClient';
|
|
20
23
|
export * from './math/conversion';
|
|
21
24
|
export * from './math/funding';
|
|
22
25
|
export * from './math/insuranceFund';
|
package/src/math/funding.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
|
-
import { PriceData } from '@pythnetwork/client';
|
|
3
2
|
import {
|
|
4
3
|
AMM_RESERVE_PRECISION,
|
|
5
4
|
MARK_PRICE_PRECISION,
|
|
@@ -8,17 +7,18 @@ import {
|
|
|
8
7
|
} from '../constants/numericConstants';
|
|
9
8
|
import { Market } from '../types';
|
|
10
9
|
import { calculateMarkPrice } from './market';
|
|
10
|
+
import { OraclePriceData } from '../oracles/types';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
*
|
|
14
14
|
* @param market
|
|
15
|
-
* @param
|
|
15
|
+
* @param oraclePriceData
|
|
16
16
|
* @param periodAdjustment
|
|
17
17
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
18
18
|
*/
|
|
19
19
|
export async function calculateAllEstimatedFundingRate(
|
|
20
20
|
market: Market,
|
|
21
|
-
oraclePriceData:
|
|
21
|
+
oraclePriceData: OraclePriceData,
|
|
22
22
|
periodAdjustment: BN = new BN(1)
|
|
23
23
|
): Promise<[BN, BN, BN, BN, BN]> {
|
|
24
24
|
// periodAdjustment
|
|
@@ -65,26 +65,10 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
65
65
|
secondsInHour.sub(timeSinceLastOracleTwapUpdate)
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
let oracleStablePriceNum = 0;
|
|
70
|
-
let oracleInputCount = 0;
|
|
71
|
-
if (oraclePriceData.price >= 0) {
|
|
72
|
-
oracleStablePriceNum += oraclePriceData.price;
|
|
73
|
-
oracleInputCount += 1;
|
|
74
|
-
}
|
|
75
|
-
if (oraclePriceData.previousPrice >= 0) {
|
|
76
|
-
oracleStablePriceNum += oraclePriceData.previousPrice;
|
|
77
|
-
oracleInputCount += 1;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
oracleStablePriceNum = oracleStablePriceNum / oracleInputCount;
|
|
81
|
-
const oraclePriceStableWithMantissa = new BN(
|
|
82
|
-
oracleStablePriceNum * MARK_PRICE_PRECISION.toNumber()
|
|
83
|
-
);
|
|
84
|
-
|
|
68
|
+
const oraclePrice = oraclePriceData.price;
|
|
85
69
|
let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
|
|
86
70
|
|
|
87
|
-
const oracleLiveVsTwap =
|
|
71
|
+
const oracleLiveVsTwap = oraclePrice
|
|
88
72
|
.sub(lastOracleTwapWithMantissa)
|
|
89
73
|
.abs()
|
|
90
74
|
.mul(MARK_PRICE_PRECISION)
|
|
@@ -95,7 +79,7 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
95
79
|
if (oracleLiveVsTwap.lte(MARK_PRICE_PRECISION.mul(new BN(10)))) {
|
|
96
80
|
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
97
81
|
.mul(lastOracleTwapWithMantissa)
|
|
98
|
-
.add(timeSinceLastMarkChange.mul(
|
|
82
|
+
.add(timeSinceLastMarkChange.mul(oraclePrice))
|
|
99
83
|
.div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
|
|
100
84
|
}
|
|
101
85
|
|
|
@@ -203,7 +187,7 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
203
187
|
*/
|
|
204
188
|
export async function calculateEstimatedFundingRate(
|
|
205
189
|
market: Market,
|
|
206
|
-
oraclePriceData:
|
|
190
|
+
oraclePriceData: OraclePriceData,
|
|
207
191
|
periodAdjustment: BN = new BN(1),
|
|
208
192
|
estimationMethod: 'interpolated' | 'lowerbound' | 'capped'
|
|
209
193
|
): Promise<BN> {
|
|
@@ -233,7 +217,7 @@ export async function calculateEstimatedFundingRate(
|
|
|
233
217
|
*/
|
|
234
218
|
export async function calculateLongShortFundingRate(
|
|
235
219
|
market: Market,
|
|
236
|
-
oraclePriceData:
|
|
220
|
+
oraclePriceData: OraclePriceData,
|
|
237
221
|
periodAdjustment: BN = new BN(1)
|
|
238
222
|
): Promise<[BN, BN]> {
|
|
239
223
|
const [_1, _2, _, cappedAltEst, interpEst] =
|
|
@@ -261,7 +245,7 @@ export async function calculateLongShortFundingRate(
|
|
|
261
245
|
*/
|
|
262
246
|
export async function calculateLongShortFundingRateAndLiveTwaps(
|
|
263
247
|
market: Market,
|
|
264
|
-
oraclePriceData:
|
|
248
|
+
oraclePriceData: OraclePriceData,
|
|
265
249
|
periodAdjustment: BN = new BN(1)
|
|
266
250
|
): Promise<[BN, BN, BN, BN]> {
|
|
267
251
|
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { parsePriceData, PriceData } from '@pythnetwork/client';
|
|
2
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { OraclePriceData } from './types';
|
|
4
|
+
import { BN } from '@project-serum/anchor';
|
|
5
|
+
import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
6
|
+
|
|
7
|
+
export class PythClient {
|
|
8
|
+
private connection: Connection;
|
|
9
|
+
|
|
10
|
+
public constructor(connection: Connection) {
|
|
11
|
+
this.connection = connection;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
|
|
15
|
+
const account = await this.connection.getAccountInfo(pricePublicKey);
|
|
16
|
+
return parsePriceData(account.data);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public async getOraclePriceData(
|
|
20
|
+
pricePublicKey: PublicKey
|
|
21
|
+
): Promise<OraclePriceData> {
|
|
22
|
+
const accountInfo = await this.connection.getAccountInfo(pricePublicKey);
|
|
23
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async getOraclePriceDataFromBuffer(
|
|
27
|
+
buffer: Buffer
|
|
28
|
+
): Promise<OraclePriceData> {
|
|
29
|
+
const priceData = parsePriceData(buffer);
|
|
30
|
+
return {
|
|
31
|
+
price: convertPythPrice(priceData.price, priceData.exponent),
|
|
32
|
+
slot: new BN(priceData.lastSlot.toString()),
|
|
33
|
+
confidence: convertPythPrice(priceData.confidence, priceData.exponent),
|
|
34
|
+
twap: convertPythPrice(priceData.twap.value, priceData.exponent),
|
|
35
|
+
twapConfidence: convertPythPrice(
|
|
36
|
+
priceData.twac.value,
|
|
37
|
+
priceData.exponent
|
|
38
|
+
),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function convertPythPrice(price: number, exponent: number): BN {
|
|
44
|
+
exponent = Math.abs(exponent);
|
|
45
|
+
const pythPrecision = TEN.pow(new BN(exponent).abs());
|
|
46
|
+
return new BN(price * Math.pow(10, exponent))
|
|
47
|
+
.mul(MARK_PRICE_PRECISION)
|
|
48
|
+
.div(pythPrecision);
|
|
49
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSwitchboardPid,
|
|
3
|
+
SwitchboardDecimal,
|
|
4
|
+
} from '@switchboard-xyz/switchboard-v2';
|
|
5
|
+
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
6
|
+
import { DriftEnv } from '../config';
|
|
7
|
+
import { BN, Provider, Program, Idl } from '@project-serum/anchor';
|
|
8
|
+
import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
9
|
+
import { OracleClient, OraclePriceData } from './types';
|
|
10
|
+
import { Wallet } from '../wallet';
|
|
11
|
+
import switchboardV2Idl from '../idl/switchboard_v2.json';
|
|
12
|
+
|
|
13
|
+
// cache switchboard program for every client object since itll always be the same
|
|
14
|
+
const programMap = new Map<string, Program>();
|
|
15
|
+
|
|
16
|
+
export class SwitchboardClient implements OracleClient {
|
|
17
|
+
connection: Connection;
|
|
18
|
+
env: DriftEnv;
|
|
19
|
+
|
|
20
|
+
public constructor(connection: Connection, env: DriftEnv) {
|
|
21
|
+
this.connection = connection;
|
|
22
|
+
this.env = env;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public async getOraclePriceData(
|
|
26
|
+
pricePublicKey: PublicKey
|
|
27
|
+
): Promise<OraclePriceData> {
|
|
28
|
+
const accountInfo = await this.connection.getAccountInfo(pricePublicKey);
|
|
29
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async getOraclePriceDataFromBuffer(
|
|
33
|
+
buffer: Buffer
|
|
34
|
+
): Promise<OraclePriceData> {
|
|
35
|
+
const program = await this.getProgram();
|
|
36
|
+
|
|
37
|
+
const aggregatorAccountData =
|
|
38
|
+
program.account.aggregatorAccountData.coder.accounts.decode(
|
|
39
|
+
'AggregatorAccountData',
|
|
40
|
+
buffer
|
|
41
|
+
);
|
|
42
|
+
const price = convertSwitchboardDecimal(
|
|
43
|
+
aggregatorAccountData.latestConfirmedRound.result as SwitchboardDecimal
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const confidence = convertSwitchboardDecimal(
|
|
47
|
+
aggregatorAccountData.latestConfirmedRound
|
|
48
|
+
.stdDeviation as SwitchboardDecimal
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const slot: BN = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
|
|
52
|
+
return {
|
|
53
|
+
price,
|
|
54
|
+
slot,
|
|
55
|
+
confidence,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public async getProgram(): Promise<Program> {
|
|
60
|
+
if (programMap.has(this.env)) {
|
|
61
|
+
return programMap.get(this.env);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const program = await getSwitchboardProgram(this.env, this.connection);
|
|
65
|
+
programMap.set(this.env, program);
|
|
66
|
+
return program;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function getSwitchboardProgram(
|
|
71
|
+
env: DriftEnv,
|
|
72
|
+
connection: Connection
|
|
73
|
+
): Promise<Program> {
|
|
74
|
+
const DEFAULT_KEYPAIR = Keypair.fromSeed(new Uint8Array(32).fill(1));
|
|
75
|
+
const programId = getSwitchboardPid(env);
|
|
76
|
+
const wallet = new Wallet(DEFAULT_KEYPAIR);
|
|
77
|
+
const provider = new Provider(connection, wallet, {});
|
|
78
|
+
|
|
79
|
+
return new Program(switchboardV2Idl as Idl, programId, provider);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function convertSwitchboardDecimal(switchboardDecimal: SwitchboardDecimal): BN {
|
|
83
|
+
const switchboardPrecision = TEN.pow(new BN(switchboardDecimal.scale));
|
|
84
|
+
return switchboardDecimal.mantissa
|
|
85
|
+
.mul(MARK_PRICE_PRECISION)
|
|
86
|
+
.div(switchboardPrecision);
|
|
87
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BN } from '@project-serum/anchor';
|
|
2
|
+
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
|
|
4
|
+
export type OraclePriceData = {
|
|
5
|
+
price: BN;
|
|
6
|
+
slot: BN;
|
|
7
|
+
confidence: BN;
|
|
8
|
+
twap?: BN;
|
|
9
|
+
twapConfidence?: BN;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface OracleClient {
|
|
13
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
|
|
14
|
+
getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
|
|
15
|
+
}
|
package/src/orderParams.ts
CHANGED
|
@@ -15,7 +15,8 @@ export function getLimitOrderParams(
|
|
|
15
15
|
reduceOnly: boolean,
|
|
16
16
|
discountToken = false,
|
|
17
17
|
referrer = false,
|
|
18
|
-
userOrderId = 0
|
|
18
|
+
userOrderId = 0,
|
|
19
|
+
postOnly = false
|
|
19
20
|
): OrderParams {
|
|
20
21
|
return {
|
|
21
22
|
orderType: OrderType.LIMIT,
|
|
@@ -26,7 +27,7 @@ export function getLimitOrderParams(
|
|
|
26
27
|
baseAssetAmount,
|
|
27
28
|
price,
|
|
28
29
|
reduceOnly,
|
|
29
|
-
postOnly
|
|
30
|
+
postOnly,
|
|
30
31
|
immediateOrCancel: false,
|
|
31
32
|
positionLimit: ZERO,
|
|
32
33
|
padding0: true,
|
package/src/types.ts
CHANGED
package/lib/pythClient.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { PriceData } from '@pythnetwork/client';
|
|
2
|
-
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
-
export declare class PythClient {
|
|
4
|
-
private connection;
|
|
5
|
-
constructor(connection: Connection);
|
|
6
|
-
getPriceData(pricePublicKey: PublicKey): Promise<PriceData>;
|
|
7
|
-
}
|
package/lib/pythClient.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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.PythClient = void 0;
|
|
13
|
-
const client_1 = require("@pythnetwork/client");
|
|
14
|
-
class PythClient {
|
|
15
|
-
constructor(connection) {
|
|
16
|
-
this.connection = connection;
|
|
17
|
-
}
|
|
18
|
-
getPriceData(pricePublicKey) {
|
|
19
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
-
const account = yield this.connection.getAccountInfo(pricePublicKey);
|
|
21
|
-
return client_1.parsePriceData(account.data);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
exports.PythClient = PythClient;
|
package/src/pythClient.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { parsePriceData, PriceData } from '@pythnetwork/client';
|
|
2
|
-
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
-
|
|
4
|
-
export class PythClient {
|
|
5
|
-
private connection: Connection;
|
|
6
|
-
|
|
7
|
-
public constructor(connection: Connection) {
|
|
8
|
-
this.connection = connection;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
|
|
12
|
-
const account = await this.connection.getAccountInfo(pricePublicKey);
|
|
13
|
-
return parsePriceData(account.data);
|
|
14
|
-
}
|
|
15
|
-
}
|