@drift-labs/sdk 2.87.0-beta.0 → 2.87.0-beta.10
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/VERSION +1 -1
- package/lib/addresses/pda.d.ts +2 -0
- package/lib/addresses/pda.js +9 -1
- package/lib/adminClient.d.ts +2 -0
- package/lib/adminClient.js +27 -4
- package/lib/bankrun/bankrunConnection.js +1 -1
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -0
- package/lib/constants/perpMarkets.js +12 -12
- package/lib/constants/spotMarkets.d.ts +1 -0
- package/lib/constants/spotMarkets.js +13 -3
- package/lib/dlob/orderBookLevels.d.ts +1 -1
- package/lib/driftClient.d.ts +15 -5
- package/lib/driftClient.js +155 -41
- package/lib/events/types.d.ts +3 -2
- package/lib/events/types.js +1 -0
- package/lib/factory/oracleClient.js +4 -0
- package/lib/idl/drift.json +147 -5
- package/lib/idl/openbook.json +3854 -0
- package/lib/idl/switchboard_on_demand_30.json +4383 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/math/spotMarket.d.ts +6 -0
- package/lib/math/spotMarket.js +16 -1
- package/lib/math/superStake.d.ts +3 -2
- package/lib/openbook/openbookV2FulfillmentConfigMap.d.ts +10 -0
- package/lib/openbook/openbookV2FulfillmentConfigMap.js +17 -0
- package/lib/openbook/openbookV2Subscriber.d.ts +36 -0
- package/lib/openbook/openbookV2Subscriber.js +102 -0
- package/lib/oracles/switchboardOnDemandClient.d.ts +11 -0
- package/lib/oracles/switchboardOnDemandClient.js +32 -0
- package/lib/types.d.ts +13 -0
- package/lib/types.js +1 -0
- package/package.json +6 -2
- package/src/addresses/pda.ts +10 -0
- package/src/adminClient.ts +47 -4
- package/src/bankrun/bankrunConnection.ts +2 -2
- package/src/config.ts +3 -0
- package/src/constants/perpMarkets.ts +12 -12
- package/src/constants/spotMarkets.ts +15 -3
- package/src/dlob/orderBookLevels.ts +1 -1
- package/src/driftClient.ts +229 -52
- package/src/events/types.ts +5 -1
- package/src/factory/oracleClient.ts +5 -0
- package/src/idl/drift.json +147 -5
- package/src/idl/switchboard_on_demand_30.json +4383 -0
- package/src/index.ts +2 -0
- package/src/math/spotMarket.ts +28 -2
- package/src/openbook/openbookV2FulfillmentConfigMap.ts +29 -0
- package/src/openbook/openbookV2Subscriber.ts +165 -0
- package/src/oracles/switchboardOnDemandClient.ts +56 -0
- package/src/types.ts +13 -0
- package/tests/ci/verifyConstants.ts +3 -6
- package/tests/subscriber/openbook.ts +58 -0
package/lib/index.d.ts
CHANGED
|
@@ -72,6 +72,8 @@ export * from './serum/serumFulfillmentConfigMap';
|
|
|
72
72
|
export * from './phoenix/phoenixSubscriber';
|
|
73
73
|
export * from './priorityFee';
|
|
74
74
|
export * from './phoenix/phoenixFulfillmentConfigMap';
|
|
75
|
+
export * from './openbook/openbookV2Subscriber';
|
|
76
|
+
export * from './openbook/openbookV2FulfillmentConfigMap';
|
|
75
77
|
export * from './tx/fastSingleTxSender';
|
|
76
78
|
export * from './tx/retryTxSender';
|
|
77
79
|
export * from './tx/whileValidTxSender';
|
package/lib/index.js
CHANGED
|
@@ -95,6 +95,8 @@ __exportStar(require("./serum/serumFulfillmentConfigMap"), exports);
|
|
|
95
95
|
__exportStar(require("./phoenix/phoenixSubscriber"), exports);
|
|
96
96
|
__exportStar(require("./priorityFee"), exports);
|
|
97
97
|
__exportStar(require("./phoenix/phoenixFulfillmentConfigMap"), exports);
|
|
98
|
+
__exportStar(require("./openbook/openbookV2Subscriber"), exports);
|
|
99
|
+
__exportStar(require("./openbook/openbookV2FulfillmentConfigMap"), exports);
|
|
98
100
|
__exportStar(require("./tx/fastSingleTxSender"), exports);
|
|
99
101
|
__exportStar(require("./tx/retryTxSender"), exports);
|
|
100
102
|
__exportStar(require("./tx/whileValidTxSender"), exports);
|
package/lib/math/spotMarket.d.ts
CHANGED
|
@@ -3,3 +3,9 @@ import { BN } from '@coral-xyz/anchor';
|
|
|
3
3
|
import { MarginCategory, SpotBalanceType, SpotMarketAccount } from '../types';
|
|
4
4
|
export declare function castNumberToSpotPrecision(value: number | BN, spotMarket: SpotMarketAccount): BN;
|
|
5
5
|
export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, oraclePrice: BN, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType, customMarginRatio?: number): number;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the maximum remaining deposit that can be made to the spot market. If the maxTokenDeposits on the market is zero then there is no limit and this function will also return zero. (so that needs to be checked)
|
|
8
|
+
* @param market
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateMaxRemainingDeposit(market: SpotMarketAccount): BN;
|
package/lib/math/spotMarket.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateSpotMarketMarginRatio = exports.castNumberToSpotPrecision = void 0;
|
|
3
|
+
exports.calculateMaxRemainingDeposit = exports.calculateSpotMarketMarginRatio = exports.castNumberToSpotPrecision = void 0;
|
|
4
4
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const spotBalance_1 = require("./spotBalance");
|
|
@@ -32,3 +32,18 @@ function calculateSpotMarketMarginRatio(market, oraclePrice, marginCategory, siz
|
|
|
32
32
|
return marginRatio;
|
|
33
33
|
}
|
|
34
34
|
exports.calculateSpotMarketMarginRatio = calculateSpotMarketMarginRatio;
|
|
35
|
+
/**
|
|
36
|
+
* Returns the maximum remaining deposit that can be made to the spot market. If the maxTokenDeposits on the market is zero then there is no limit and this function will also return zero. (so that needs to be checked)
|
|
37
|
+
* @param market
|
|
38
|
+
* @returns
|
|
39
|
+
*/
|
|
40
|
+
function calculateMaxRemainingDeposit(market) {
|
|
41
|
+
const marketMaxTokenDeposits = market.maxTokenDeposits;
|
|
42
|
+
if (marketMaxTokenDeposits.eq(numericConstants_1.ZERO)) {
|
|
43
|
+
// If the maxTokenDeposits is set to zero then that means there is no limit. Return the largest number we can to represent infinite available deposit.
|
|
44
|
+
return numericConstants_1.ZERO;
|
|
45
|
+
}
|
|
46
|
+
const totalDepositsTokenAmount = (0, spotBalance_1.getTokenAmount)(market.depositBalance, market, types_1.SpotBalanceType.DEPOSIT);
|
|
47
|
+
return marketMaxTokenDeposits.sub(totalDepositsTokenAmount);
|
|
48
|
+
}
|
|
49
|
+
exports.calculateMaxRemainingDeposit = calculateMaxRemainingDeposit;
|
package/lib/math/superStake.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { DriftClient } from '../driftClient';
|
|
|
5
5
|
import { BN } from '@coral-xyz/anchor';
|
|
6
6
|
import { User } from '../user';
|
|
7
7
|
import { DepositRecord } from '../types';
|
|
8
|
+
import fetch from 'node-fetch';
|
|
8
9
|
export type BSOL_STATS_API_RESPONSE = {
|
|
9
10
|
success: boolean;
|
|
10
11
|
stats?: {
|
|
@@ -27,8 +28,8 @@ export type BSOL_EMISSIONS_API_RESPONSE = {
|
|
|
27
28
|
lend: number;
|
|
28
29
|
};
|
|
29
30
|
};
|
|
30
|
-
export declare function fetchBSolMetrics(): Promise<
|
|
31
|
-
export declare function fetchBSolDriftEmissions(): Promise<
|
|
31
|
+
export declare function fetchBSolMetrics(): Promise<fetch.Response>;
|
|
32
|
+
export declare function fetchBSolDriftEmissions(): Promise<fetch.Response>;
|
|
32
33
|
export declare function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, jupiterQuote, }: {
|
|
33
34
|
marketIndex: number;
|
|
34
35
|
amount: BN;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { OpenbookV2FulfillmentConfigAccount } from '../types';
|
|
3
|
+
import { DriftClient } from '../driftClient';
|
|
4
|
+
export declare class OpenbookV2FulfillmentConfigMap {
|
|
5
|
+
driftClient: DriftClient;
|
|
6
|
+
map: Map<number, OpenbookV2FulfillmentConfigAccount>;
|
|
7
|
+
constructor(driftClient: DriftClient);
|
|
8
|
+
add(marketIndex: number, openbookV2MarketAddress: PublicKey): Promise<void>;
|
|
9
|
+
get(marketIndex: number): OpenbookV2FulfillmentConfigAccount | undefined;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenbookV2FulfillmentConfigMap = void 0;
|
|
4
|
+
class OpenbookV2FulfillmentConfigMap {
|
|
5
|
+
constructor(driftClient) {
|
|
6
|
+
this.map = new Map();
|
|
7
|
+
this.driftClient = driftClient;
|
|
8
|
+
}
|
|
9
|
+
async add(marketIndex, openbookV2MarketAddress) {
|
|
10
|
+
const account = await this.driftClient.getOpenbookV2FulfillmentConfig(openbookV2MarketAddress);
|
|
11
|
+
this.map.set(marketIndex, account);
|
|
12
|
+
}
|
|
13
|
+
get(marketIndex) {
|
|
14
|
+
return this.map.get(marketIndex);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.OpenbookV2FulfillmentConfigMap = OpenbookV2FulfillmentConfigMap;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
2
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
|
|
4
|
+
import { BN } from '@coral-xyz/anchor';
|
|
5
|
+
import { L2Level, L2OrderBookGenerator } from '../dlob/orderBookLevels';
|
|
6
|
+
import { Market, OpenBookV2Client } from '@openbook-dex/openbook-v2';
|
|
7
|
+
export type OpenbookV2SubscriberConfig = {
|
|
8
|
+
connection: Connection;
|
|
9
|
+
programId: PublicKey;
|
|
10
|
+
marketAddress: PublicKey;
|
|
11
|
+
accountSubscription: {
|
|
12
|
+
type: 'polling';
|
|
13
|
+
accountLoader: BulkAccountLoader;
|
|
14
|
+
} | {
|
|
15
|
+
type: 'websocket';
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare class OpenbookV2Subscriber implements L2OrderBookGenerator {
|
|
19
|
+
connection: Connection;
|
|
20
|
+
programId: PublicKey;
|
|
21
|
+
marketAddress: PublicKey;
|
|
22
|
+
subscriptionType: 'polling' | 'websocket';
|
|
23
|
+
accountLoader: BulkAccountLoader | undefined;
|
|
24
|
+
subscribed: boolean;
|
|
25
|
+
market: Market;
|
|
26
|
+
marketCallbackId: string | number;
|
|
27
|
+
client: OpenBookV2Client;
|
|
28
|
+
constructor(config: OpenbookV2SubscriberConfig);
|
|
29
|
+
subscribe(): Promise<void>;
|
|
30
|
+
getBestBid(): BN | undefined;
|
|
31
|
+
getBestAsk(): BN | undefined;
|
|
32
|
+
getL2Bids(): Generator<L2Level>;
|
|
33
|
+
getL2Asks(): Generator<L2Level>;
|
|
34
|
+
getL2Levels(side: 'bids' | 'asks'): Generator<L2Level>;
|
|
35
|
+
unsubscribe(): Promise<void>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OpenbookV2Subscriber = void 0;
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
8
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
9
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
10
|
+
const openbook_v2_1 = require("@openbook-dex/openbook-v2");
|
|
11
|
+
const openbook_json_1 = __importDefault(require("../idl/openbook.json"));
|
|
12
|
+
class OpenbookV2Subscriber {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.connection = config.connection;
|
|
15
|
+
this.programId = config.programId;
|
|
16
|
+
this.marketAddress = config.marketAddress;
|
|
17
|
+
this.subscribed = false;
|
|
18
|
+
if (config.accountSubscription.type === 'polling') {
|
|
19
|
+
this.subscriptionType = 'polling';
|
|
20
|
+
this.accountLoader = config.accountSubscription.accountLoader;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.subscriptionType = 'websocket';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async subscribe() {
|
|
27
|
+
if (this.subscribed === true) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const anchorProvider = new anchor_1.AnchorProvider(this.connection, new anchor_1.Wallet(web3_js_1.Keypair.generate()), {});
|
|
31
|
+
const openbookV2Program = new anchor_1.Program(openbook_json_1.default, this.programId, anchorProvider);
|
|
32
|
+
this.client = new openbook_v2_1.OpenBookV2Client(anchorProvider);
|
|
33
|
+
const market = await openbook_v2_1.Market.load(this.client, this.marketAddress);
|
|
34
|
+
this.market = await market.loadOrderBook();
|
|
35
|
+
if (this.subscriptionType === 'websocket') {
|
|
36
|
+
this.marketCallbackId = this.connection.onAccountChange(this.marketAddress, async (accountInfo, _) => {
|
|
37
|
+
const marketRaw = openbookV2Program.coder.accounts.decode('Market', accountInfo.data);
|
|
38
|
+
this.market = new openbook_v2_1.Market(this.client, this.marketAddress, marketRaw);
|
|
39
|
+
await this.market.loadOrderBook();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.marketCallbackId = await this.accountLoader.addAccount(this.marketAddress, (buffer, _) => {
|
|
44
|
+
const marketRaw = openbookV2Program.coder.accounts.decode('Market', buffer);
|
|
45
|
+
this.market = new openbook_v2_1.Market(this.client, this.marketAddress, marketRaw);
|
|
46
|
+
(async () => {
|
|
47
|
+
await this.market.loadOrderBook();
|
|
48
|
+
})();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
this.subscribed = true;
|
|
52
|
+
}
|
|
53
|
+
getBestBid() {
|
|
54
|
+
const bestBid = this.market.bids.best();
|
|
55
|
+
if (bestBid === undefined) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
return new anchor_1.BN(Math.floor(bestBid.price * numericConstants_1.PRICE_PRECISION.toNumber()));
|
|
59
|
+
}
|
|
60
|
+
getBestAsk() {
|
|
61
|
+
const bestAsk = this.market.asks.best();
|
|
62
|
+
if (bestAsk === undefined) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
return new anchor_1.BN(Math.floor(bestAsk.price * numericConstants_1.PRICE_PRECISION.toNumber()));
|
|
66
|
+
}
|
|
67
|
+
getL2Bids() {
|
|
68
|
+
return this.getL2Levels('bids');
|
|
69
|
+
}
|
|
70
|
+
getL2Asks() {
|
|
71
|
+
return this.getL2Levels('asks');
|
|
72
|
+
}
|
|
73
|
+
*getL2Levels(side) {
|
|
74
|
+
const basePrecision = Math.ceil(1 / this.market.baseNativeFactor.toNumber());
|
|
75
|
+
const pricePrecision = numericConstants_1.PRICE_PRECISION.toNumber();
|
|
76
|
+
const levels = side === 'bids' ? this.market.bids : this.market.asks;
|
|
77
|
+
for (const order of levels.items()) {
|
|
78
|
+
const size = new anchor_1.BN(order.size * basePrecision);
|
|
79
|
+
const price = new anchor_1.BN(order.price * pricePrecision);
|
|
80
|
+
yield {
|
|
81
|
+
price,
|
|
82
|
+
size,
|
|
83
|
+
sources: {
|
|
84
|
+
openbook: size,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async unsubscribe() {
|
|
90
|
+
if (!this.subscribed) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (this.subscriptionType === 'websocket') {
|
|
94
|
+
await this.connection.removeAccountChangeListener(this.marketCallbackId);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.accountLoader.removeAccount(this.marketAddress, this.marketCallbackId);
|
|
98
|
+
}
|
|
99
|
+
this.subscribed = false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.OpenbookV2Subscriber = OpenbookV2Subscriber;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { OracleClient, OraclePriceData } from './types';
|
|
4
|
+
import { BorshAccountsCoder as BorshAccountsCoder30 } from '@coral-xyz/anchor-30';
|
|
5
|
+
export declare class SwitchboardOnDemandClient implements OracleClient {
|
|
6
|
+
connection: Connection;
|
|
7
|
+
coder: BorshAccountsCoder30;
|
|
8
|
+
constructor(connection: Connection);
|
|
9
|
+
getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
|
|
10
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData;
|
|
11
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SwitchboardOnDemandClient = void 0;
|
|
7
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
|
+
const switchboard_on_demand_30_json_1 = __importDefault(require("../idl/switchboard_on_demand_30.json"));
|
|
9
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
10
|
+
const anchor_30_1 = require("@coral-xyz/anchor-30");
|
|
11
|
+
const SB_PRECISION_EXP = new anchor_1.BN(18);
|
|
12
|
+
const SB_PRECISION = new anchor_1.BN(10).pow(SB_PRECISION_EXP.sub(numericConstants_1.PRICE_PRECISION_EXP));
|
|
13
|
+
class SwitchboardOnDemandClient {
|
|
14
|
+
constructor(connection) {
|
|
15
|
+
this.connection = connection;
|
|
16
|
+
this.coder = new anchor_30_1.BorshAccountsCoder(switchboard_on_demand_30_json_1.default);
|
|
17
|
+
}
|
|
18
|
+
async getOraclePriceData(pricePublicKey) {
|
|
19
|
+
const accountInfo = await this.connection.getAccountInfo(pricePublicKey);
|
|
20
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
21
|
+
}
|
|
22
|
+
getOraclePriceDataFromBuffer(buffer) {
|
|
23
|
+
const pullFeedAccountData = this.coder.decodeUnchecked('PullFeedAccountData', buffer);
|
|
24
|
+
return {
|
|
25
|
+
price: pullFeedAccountData.result.value.div(SB_PRECISION),
|
|
26
|
+
slot: pullFeedAccountData.result.slot,
|
|
27
|
+
confidence: pullFeedAccountData.result.range.div(SB_PRECISION),
|
|
28
|
+
hasSufficientNumberOfDataPoints: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.SwitchboardOnDemandClient = SwitchboardOnDemandClient;
|
package/lib/types.d.ts
CHANGED
|
@@ -182,6 +182,9 @@ export declare class OracleSource {
|
|
|
182
182
|
static readonly Prelaunch: {
|
|
183
183
|
prelaunch: {};
|
|
184
184
|
};
|
|
185
|
+
static readonly SWITCHBOARD_ON_DEMAND: {
|
|
186
|
+
switchboardOnDemand: {};
|
|
187
|
+
};
|
|
185
188
|
}
|
|
186
189
|
export declare class OrderType {
|
|
187
190
|
static readonly LIMIT: {
|
|
@@ -671,6 +674,15 @@ export type SwapRecord = {
|
|
|
671
674
|
inOraclePrice: BN;
|
|
672
675
|
fee: BN;
|
|
673
676
|
};
|
|
677
|
+
export type SpotMarketVaultDepositRecord = {
|
|
678
|
+
ts: BN;
|
|
679
|
+
marketIndex: number;
|
|
680
|
+
depositBalance: BN;
|
|
681
|
+
cumulativeDepositInterestBefore: BN;
|
|
682
|
+
cumulativeDepositInterestAfter: BN;
|
|
683
|
+
depositTokenAmountBefore: BN;
|
|
684
|
+
amount: BN;
|
|
685
|
+
};
|
|
674
686
|
export type StateAccount = {
|
|
675
687
|
admin: PublicKey;
|
|
676
688
|
exchangeStatus: number;
|
|
@@ -821,6 +833,7 @@ export type SpotMarketAccount = {
|
|
|
821
833
|
fuelBoostTaker: number;
|
|
822
834
|
fuelBoostMaker: number;
|
|
823
835
|
fuelBoostInsurance: number;
|
|
836
|
+
tokenProgram: number;
|
|
824
837
|
};
|
|
825
838
|
export type PoolBalance = {
|
|
826
839
|
scaledBalance: BN;
|
package/lib/types.js
CHANGED
|
@@ -114,6 +114,7 @@ OracleSource.QUOTE_ASSET = { quoteAsset: {} };
|
|
|
114
114
|
OracleSource.PYTH_STABLE_COIN = { pythStableCoin: {} };
|
|
115
115
|
OracleSource.PYTH_STABLE_COIN_PULL = { pythStableCoinPull: {} };
|
|
116
116
|
OracleSource.Prelaunch = { prelaunch: {} };
|
|
117
|
+
OracleSource.SWITCHBOARD_ON_DEMAND = { switchboardOnDemand: {} };
|
|
117
118
|
class OrderType {
|
|
118
119
|
}
|
|
119
120
|
exports.OrderType = OrderType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.87.0-beta.
|
|
3
|
+
"version": "2.87.0-beta.10",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -35,13 +35,16 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@coral-xyz/anchor": "0.28.0",
|
|
38
|
+
"@coral-xyz/anchor-30": "npm:@coral-xyz/anchor@0.30.1",
|
|
38
39
|
"@ellipsis-labs/phoenix-sdk": "^1.4.2",
|
|
40
|
+
"@openbook-dex/openbook-v2": "^0.2.10",
|
|
39
41
|
"@project-serum/serum": "^0.13.38",
|
|
40
42
|
"@pythnetwork/client": "2.5.3",
|
|
41
43
|
"@pythnetwork/price-service-sdk": "^1.7.1",
|
|
42
44
|
"@pythnetwork/pyth-solana-receiver": "^0.7.0",
|
|
43
45
|
"@solana/spl-token": "0.3.7",
|
|
44
46
|
"@solana/web3.js": "1.92.3",
|
|
47
|
+
"@switchboard-xyz/on-demand": "^1.2.1",
|
|
45
48
|
"anchor-bankrun": "^0.3.0",
|
|
46
49
|
"rpc-websockets": "7.5.1",
|
|
47
50
|
"solana-bankrun": "^0.3.0",
|
|
@@ -75,6 +78,7 @@
|
|
|
75
78
|
"node": ">=18"
|
|
76
79
|
},
|
|
77
80
|
"resolutions": {
|
|
78
|
-
"@solana/errors": "2.0.0-preview.4"
|
|
81
|
+
"@solana/errors": "2.0.0-preview.4",
|
|
82
|
+
"@solana/codecs-data-structures": "2.0.0-preview.4"
|
|
79
83
|
}
|
|
80
84
|
}
|
package/src/addresses/pda.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { PublicKey } from '@solana/web3.js';
|
|
2
2
|
import * as anchor from '@coral-xyz/anchor';
|
|
3
3
|
import { BN } from '@coral-xyz/anchor';
|
|
4
|
+
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
5
|
+
import { SpotMarketAccount } from '..';
|
|
4
6
|
|
|
5
7
|
export async function getDriftStateAccountPublicKeyAndNonce(
|
|
6
8
|
programId: PublicKey
|
|
@@ -264,3 +266,11 @@ export function getPythPullOraclePublicKey(
|
|
|
264
266
|
progarmId
|
|
265
267
|
)[0];
|
|
266
268
|
}
|
|
269
|
+
export function getTokenProgramForSpotMarket(
|
|
270
|
+
spotMarketAccount: SpotMarketAccount
|
|
271
|
+
): PublicKey {
|
|
272
|
+
if (spotMarketAccount.tokenProgram === 1) {
|
|
273
|
+
return TOKEN_2022_PROGRAM_ID;
|
|
274
|
+
}
|
|
275
|
+
return TOKEN_PROGRAM_ID;
|
|
276
|
+
}
|
package/src/adminClient.ts
CHANGED
|
@@ -198,6 +198,8 @@ export class AdminClient extends DriftClient {
|
|
|
198
198
|
spotMarketIndex
|
|
199
199
|
);
|
|
200
200
|
|
|
201
|
+
const tokenProgram = (await this.connection.getAccountInfo(mint)).owner;
|
|
202
|
+
|
|
201
203
|
const nameBuffer = encodeName(name);
|
|
202
204
|
const initializeIx = await this.program.instruction.initializeSpotMarket(
|
|
203
205
|
optimalUtilization,
|
|
@@ -233,7 +235,7 @@ export class AdminClient extends DriftClient {
|
|
|
233
235
|
oracle,
|
|
234
236
|
rent: SYSVAR_RENT_PUBKEY,
|
|
235
237
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
236
|
-
tokenProgram
|
|
238
|
+
tokenProgram,
|
|
237
239
|
},
|
|
238
240
|
}
|
|
239
241
|
);
|
|
@@ -997,6 +999,49 @@ export class AdminClient extends DriftClient {
|
|
|
997
999
|
});
|
|
998
1000
|
}
|
|
999
1001
|
|
|
1002
|
+
public async depositIntoSpotMarketVault(
|
|
1003
|
+
spotMarketIndex: number,
|
|
1004
|
+
amount: BN,
|
|
1005
|
+
sourceVault: PublicKey
|
|
1006
|
+
): Promise<TransactionSignature> {
|
|
1007
|
+
const depositIntoPerpMarketFeePoolIx =
|
|
1008
|
+
await this.getDepositIntoSpotMarketVaultIx(
|
|
1009
|
+
spotMarketIndex,
|
|
1010
|
+
amount,
|
|
1011
|
+
sourceVault
|
|
1012
|
+
);
|
|
1013
|
+
|
|
1014
|
+
const tx = await this.buildTransaction(depositIntoPerpMarketFeePoolIx);
|
|
1015
|
+
|
|
1016
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1017
|
+
|
|
1018
|
+
return txSig;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
public async getDepositIntoSpotMarketVaultIx(
|
|
1022
|
+
spotMarketIndex: number,
|
|
1023
|
+
amount: BN,
|
|
1024
|
+
sourceVault: PublicKey
|
|
1025
|
+
): Promise<TransactionInstruction> {
|
|
1026
|
+
const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
|
|
1027
|
+
|
|
1028
|
+
const remainingAccounts = [];
|
|
1029
|
+
this.addTokenMintToRemainingAccounts(spotMarket, remainingAccounts);
|
|
1030
|
+
const tokenProgram = this.getTokenProgramForSpotMarket(spotMarket);
|
|
1031
|
+
return await this.program.instruction.depositIntoSpotMarketVault(amount, {
|
|
1032
|
+
accounts: {
|
|
1033
|
+
admin: this.isSubscribed
|
|
1034
|
+
? this.getStateAccount().admin
|
|
1035
|
+
: this.wallet.publicKey,
|
|
1036
|
+
state: await this.getStatePublicKey(),
|
|
1037
|
+
sourceVault,
|
|
1038
|
+
spotMarket: spotMarket.pubkey,
|
|
1039
|
+
spotMarketVault: spotMarket.vault,
|
|
1040
|
+
tokenProgram,
|
|
1041
|
+
},
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1000
1045
|
public async updateAdmin(admin: PublicKey): Promise<TransactionSignature> {
|
|
1001
1046
|
const updateAdminIx = await this.getUpdateAdminIx(admin);
|
|
1002
1047
|
|
|
@@ -1115,9 +1160,7 @@ export class AdminClient extends DriftClient {
|
|
|
1115
1160
|
},
|
|
1116
1161
|
{
|
|
1117
1162
|
accounts: {
|
|
1118
|
-
admin: this.
|
|
1119
|
-
? this.getStateAccount().admin
|
|
1120
|
-
: this.wallet.publicKey,
|
|
1163
|
+
admin: this.wallet.publicKey,
|
|
1121
1164
|
state: await this.getStatePublicKey(),
|
|
1122
1165
|
perpMarket: await getPerpMarketPublicKey(
|
|
1123
1166
|
this.program.programId,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
import { BankrunProvider } from 'anchor-bankrun';
|
|
36
36
|
import bs58 from 'bs58';
|
|
37
37
|
import { BN, Wallet } from '@coral-xyz/anchor';
|
|
38
|
-
import { Account,
|
|
38
|
+
import { Account, unpackAccount } from '@solana/spl-token';
|
|
39
39
|
|
|
40
40
|
export type Connection = SolanaConnection | BankrunConnection;
|
|
41
41
|
|
|
@@ -164,7 +164,7 @@ export class BankrunConnection {
|
|
|
164
164
|
|
|
165
165
|
async getTokenAccount(publicKey: PublicKey): Promise<Account> {
|
|
166
166
|
const info = await this.getAccountInfo(publicKey);
|
|
167
|
-
return unpackAccount(publicKey, info,
|
|
167
|
+
return unpackAccount(publicKey, info, info.owner);
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
async getMultipleAccountsInfo(
|
package/src/config.ts
CHANGED
|
@@ -23,6 +23,7 @@ type DriftConfig = {
|
|
|
23
23
|
USDC_MINT_ADDRESS: string;
|
|
24
24
|
SERUM_V3: string;
|
|
25
25
|
PHOENIX: string;
|
|
26
|
+
OPENBOOK: string;
|
|
26
27
|
V2_ALPHA_TICKET_MINT_ADDRESS: string;
|
|
27
28
|
PERP_MARKETS: PerpMarketConfig[];
|
|
28
29
|
SPOT_MARKETS: SpotMarketConfig[];
|
|
@@ -46,6 +47,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
46
47
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
47
48
|
SERUM_V3: 'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
|
48
49
|
PHOENIX: 'PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY',
|
|
50
|
+
OPENBOOK: 'opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb',
|
|
49
51
|
V2_ALPHA_TICKET_MINT_ADDRESS:
|
|
50
52
|
'DeEiGWfCMP9psnLGkxGrBBMEAW5Jv8bBGMN8DCtFRCyB',
|
|
51
53
|
PERP_MARKETS: DevnetPerpMarkets,
|
|
@@ -61,6 +63,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
61
63
|
USDC_MINT_ADDRESS: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
62
64
|
SERUM_V3: 'srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX',
|
|
63
65
|
PHOENIX: 'PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY',
|
|
66
|
+
OPENBOOK: 'opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb',
|
|
64
67
|
V2_ALPHA_TICKET_MINT_ADDRESS:
|
|
65
68
|
'Cmvhycb6LQvvzaShGw4iDHRLzeSSryioAsU98DSSkMNa',
|
|
66
69
|
PERP_MARKETS: MainnetPerpMarkets,
|
|
@@ -160,16 +160,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
160
160
|
'0x385f64d993f7b77d8182ed5003d97c60aa3361f3cecfe711544d2d59165e9bdf',
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
|
-
fullName: '
|
|
163
|
+
fullName: 'RENDER',
|
|
164
164
|
category: ['Infra'],
|
|
165
|
-
symbol: '
|
|
166
|
-
baseAssetSymbol: '
|
|
165
|
+
symbol: 'RENDER-PERP',
|
|
166
|
+
baseAssetSymbol: 'RENDER',
|
|
167
167
|
marketIndex: 12,
|
|
168
|
-
oracle: new PublicKey('
|
|
168
|
+
oracle: new PublicKey('8TQztfGcNjHGRusX4ejQQtPZs3Ypczt9jWF6pkgQMqUX'),
|
|
169
169
|
launchTs: 1687201081000,
|
|
170
170
|
oracleSource: OracleSource.PYTH_PULL,
|
|
171
171
|
pythFeedId:
|
|
172
|
-
'
|
|
172
|
+
'0x3d4a2bd9535be6ce8059d75eadeba507b043257321aa544717c56fa19b49e35d',
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
fullName: 'XRP',
|
|
@@ -297,9 +297,9 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
297
297
|
symbol: 'W-PERP',
|
|
298
298
|
baseAssetSymbol: 'W',
|
|
299
299
|
marketIndex: 23,
|
|
300
|
-
oracle: new PublicKey('
|
|
300
|
+
oracle: new PublicKey('4iCi4DvXrubHQne8jzbMaWL3pd7v1Fip8iTe4H9vHNXB'),
|
|
301
301
|
launchTs: 1709852537000,
|
|
302
|
-
oracleSource: OracleSource.
|
|
302
|
+
oracleSource: OracleSource.SWITCHBOARD_ON_DEMAND,
|
|
303
303
|
pythFeedId:
|
|
304
304
|
'0xeff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389',
|
|
305
305
|
},
|
|
@@ -475,16 +475,16 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
475
475
|
'0x385f64d993f7b77d8182ed5003d97c60aa3361f3cecfe711544d2d59165e9bdf',
|
|
476
476
|
},
|
|
477
477
|
{
|
|
478
|
-
fullName: '
|
|
478
|
+
fullName: 'RENDER',
|
|
479
479
|
category: ['Infra', 'Solana'],
|
|
480
|
-
symbol: '
|
|
481
|
-
baseAssetSymbol: '
|
|
480
|
+
symbol: 'RENDER-PERP',
|
|
481
|
+
baseAssetSymbol: 'RENDER',
|
|
482
482
|
marketIndex: 12,
|
|
483
|
-
oracle: new PublicKey('
|
|
483
|
+
oracle: new PublicKey('8TQztfGcNjHGRusX4ejQQtPZs3Ypczt9jWF6pkgQMqUX'),
|
|
484
484
|
launchTs: 1687201081000,
|
|
485
485
|
oracleSource: OracleSource.PYTH_PULL,
|
|
486
486
|
pythFeedId:
|
|
487
|
-
'
|
|
487
|
+
'0x3d4a2bd9535be6ce8059d75eadeba507b043257321aa544717c56fa19b49e35d',
|
|
488
488
|
},
|
|
489
489
|
{
|
|
490
490
|
fullName: 'XRP',
|
|
@@ -20,6 +20,7 @@ export type SpotMarketConfig = {
|
|
|
20
20
|
precisionExp: BN;
|
|
21
21
|
serumMarket?: PublicKey;
|
|
22
22
|
phoenixMarket?: PublicKey;
|
|
23
|
+
openbookMarket?: PublicKey;
|
|
23
24
|
launchTs?: number;
|
|
24
25
|
pythFeedId?: string;
|
|
25
26
|
};
|
|
@@ -67,6 +68,17 @@ export const DevnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
67
68
|
pythFeedId:
|
|
68
69
|
'0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
|
|
69
70
|
},
|
|
71
|
+
{
|
|
72
|
+
symbol: 'PYUSD',
|
|
73
|
+
marketIndex: 3,
|
|
74
|
+
oracle: new PublicKey('HpMoKp3TCd3QT4MWYUKk2zCBwmhr5Df45fB6wdxYqEeh'),
|
|
75
|
+
oracleSource: OracleSource.PYTH_PULL,
|
|
76
|
+
mint: new PublicKey('GLfF72ZCUnS6N9iDJw8kedHzd6WFVf3VbpwdKKy76FRk'),
|
|
77
|
+
precision: new BN(10).pow(SIX),
|
|
78
|
+
precisionExp: SIX,
|
|
79
|
+
pythFeedId:
|
|
80
|
+
'0xc1da1b73d7f01e7ddd54b3766cf7fcd644395ad14f70aa706ec5384c59e76692',
|
|
81
|
+
},
|
|
70
82
|
];
|
|
71
83
|
|
|
72
84
|
export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
@@ -235,9 +247,9 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
235
247
|
'0x0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996',
|
|
236
248
|
},
|
|
237
249
|
{
|
|
238
|
-
symbol: '
|
|
250
|
+
symbol: 'RENDER',
|
|
239
251
|
marketIndex: 12,
|
|
240
|
-
oracle: new PublicKey('
|
|
252
|
+
oracle: new PublicKey('8TQztfGcNjHGRusX4ejQQtPZs3Ypczt9jWF6pkgQMqUX'),
|
|
241
253
|
oracleSource: OracleSource.PYTH_PULL,
|
|
242
254
|
mint: new PublicKey('rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof'),
|
|
243
255
|
precision: new BN(10).pow(EIGHT),
|
|
@@ -245,7 +257,7 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
245
257
|
serumMarket: new PublicKey('2m7ZLEKtxWF29727DSb5D91erpXPUY1bqhRWRC3wQX7u'),
|
|
246
258
|
launchTs: 1708964021000,
|
|
247
259
|
pythFeedId:
|
|
248
|
-
'
|
|
260
|
+
'0x3d4a2bd9535be6ce8059d75eadeba507b043257321aa544717c56fa19b49e35d',
|
|
249
261
|
},
|
|
250
262
|
{
|
|
251
263
|
symbol: 'W',
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import { PublicKey } from '@solana/web3.js';
|
|
22
22
|
import { assert } from '../assert/assert';
|
|
23
23
|
|
|
24
|
-
type liquiditySource = 'serum' | 'vamm' | 'dlob' | 'phoenix';
|
|
24
|
+
type liquiditySource = 'serum' | 'vamm' | 'dlob' | 'phoenix' | 'openbook';
|
|
25
25
|
|
|
26
26
|
export type L2Level = {
|
|
27
27
|
price: BN;
|