@drift-labs/sdk 2.26.0-beta.0 → 2.26.0-beta.2
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/examples/phoenix.ts +40 -0
- package/lib/addresses/pda.d.ts +0 -1
- package/lib/adminClient.d.ts +0 -1
- package/lib/constants/numericConstants.d.ts +59 -61
- package/lib/constants/spotMarkets.d.ts +0 -1
- package/lib/dlob/DLOB.d.ts +38 -3
- package/lib/dlob/DLOB.js +69 -0
- package/lib/dlob/DLOBApiClient.js +1 -1
- package/lib/dlob/DLOBNode.d.ts +0 -1
- package/lib/dlob/DLOBSubscriber.d.ts +34 -0
- package/lib/dlob/DLOBSubscriber.js +100 -0
- package/lib/dlob/NodeList.d.ts +0 -1
- package/lib/dlob/orderBookLevels.d.ts +44 -0
- package/lib/dlob/orderBookLevels.js +137 -0
- package/lib/dlob/types.d.ts +2 -0
- package/lib/driftClient.d.ts +28 -11
- package/lib/driftClient.js +158 -55
- package/lib/driftClientConfig.d.ts +3 -0
- package/lib/factory/bigNum.d.ts +7 -8
- package/lib/idl/drift.json +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/math/amm.d.ts +1 -2
- package/lib/math/auction.d.ts +0 -1
- package/lib/math/conversion.d.ts +1 -2
- package/lib/math/funding.d.ts +0 -1
- package/lib/math/insurance.d.ts +0 -1
- package/lib/math/margin.d.ts +0 -1
- package/lib/math/market.d.ts +0 -1
- package/lib/math/oracles.d.ts +0 -1
- package/lib/math/orders.d.ts +0 -1
- package/lib/math/position.d.ts +0 -1
- package/lib/math/repeg.d.ts +0 -1
- package/lib/math/spotBalance.d.ts +0 -1
- package/lib/math/spotMarket.d.ts +0 -1
- package/lib/math/spotPosition.d.ts +0 -1
- package/lib/math/trade.d.ts +0 -1
- package/lib/math/utils.d.ts +0 -1
- package/lib/oracles/pythClient.d.ts +1 -2
- package/lib/oracles/types.d.ts +0 -1
- package/lib/orderParams.d.ts +0 -1
- package/lib/phoenix/phoenixFulfillmentConfigMap.d.ts +10 -0
- package/lib/phoenix/phoenixFulfillmentConfigMap.js +17 -0
- package/lib/phoenix/phoenixSubscriber.d.ts +34 -0
- package/lib/phoenix/phoenixSubscriber.js +79 -0
- package/lib/serum/serumSubscriber.d.ts +5 -2
- package/lib/serum/serumSubscriber.js +22 -0
- package/lib/tokenFaucet.d.ts +0 -1
- package/lib/types.d.ts +1 -1
- package/lib/user.d.ts +0 -1
- package/package.json +1 -1
- package/src/assert/assert.js +9 -0
- package/src/dlob/DLOB.ts +177 -17
- package/src/dlob/DLOBApiClient.ts +3 -1
- package/src/dlob/DLOBSubscriber.ts +141 -0
- package/src/dlob/orderBookLevels.ts +243 -0
- package/src/dlob/types.ts +2 -0
- package/src/driftClient.ts +231 -66
- package/src/driftClientConfig.ts +3 -0
- package/src/idl/drift.json +1 -1
- package/src/index.ts +3 -0
- package/src/phoenix/phoenixFulfillmentConfigMap.ts +26 -0
- package/src/phoenix/phoenixSubscriber.ts +156 -0
- package/src/serum/serumSubscriber.ts +27 -1
- package/src/token/index.js +38 -0
- package/src/types.ts +1 -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/tests/dlob/helpers.ts +3 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getVammL2Generator = exports.createL2Levels = exports.mergeL2LevelGenerators = exports.getL2GeneratorFromDLOBNodes = void 0;
|
|
4
|
+
const __1 = require("..");
|
|
5
|
+
/**
|
|
6
|
+
* Get an {@link Generator<L2Level>} generator from a {@link Generator<DLOBNode>}
|
|
7
|
+
* @param dlobNodes e.g. {@link DLOB#getMakerLimitAsks} or {@link DLOB#getMakerLimitBids}
|
|
8
|
+
* @param oraclePriceData
|
|
9
|
+
* @param slot
|
|
10
|
+
*/
|
|
11
|
+
function* getL2GeneratorFromDLOBNodes(dlobNodes, oraclePriceData, slot) {
|
|
12
|
+
for (const dlobNode of dlobNodes) {
|
|
13
|
+
const size = dlobNode.order.baseAssetAmount.sub(dlobNode.order.baseAssetAmountFilled);
|
|
14
|
+
yield {
|
|
15
|
+
size,
|
|
16
|
+
price: dlobNode.getPrice(oraclePriceData, slot),
|
|
17
|
+
sources: {
|
|
18
|
+
dlob: size,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.getL2GeneratorFromDLOBNodes = getL2GeneratorFromDLOBNodes;
|
|
24
|
+
function* mergeL2LevelGenerators(l2LevelGenerators, compare) {
|
|
25
|
+
const generators = l2LevelGenerators.map((generator) => {
|
|
26
|
+
return {
|
|
27
|
+
generator,
|
|
28
|
+
next: generator.next(),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
let next;
|
|
32
|
+
do {
|
|
33
|
+
next = generators.reduce((best, next) => {
|
|
34
|
+
if (next.next.done) {
|
|
35
|
+
return best;
|
|
36
|
+
}
|
|
37
|
+
if (!best) {
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
40
|
+
if (compare(next.next.value, best.next.value)) {
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return best;
|
|
45
|
+
}
|
|
46
|
+
}, undefined);
|
|
47
|
+
if (next) {
|
|
48
|
+
yield next.next.value;
|
|
49
|
+
next.next = next.generator.next();
|
|
50
|
+
}
|
|
51
|
+
} while (next !== undefined);
|
|
52
|
+
}
|
|
53
|
+
exports.mergeL2LevelGenerators = mergeL2LevelGenerators;
|
|
54
|
+
function createL2Levels(generator, depth) {
|
|
55
|
+
const levels = [];
|
|
56
|
+
for (const level of generator) {
|
|
57
|
+
const price = level.price;
|
|
58
|
+
const size = level.size;
|
|
59
|
+
if (levels.length > 0 && levels[levels.length - 1].price.eq(price)) {
|
|
60
|
+
const currentLevel = levels[levels.length - 1];
|
|
61
|
+
currentLevel.size.add(size);
|
|
62
|
+
for (const [source, size] of Object.entries(level.sources)) {
|
|
63
|
+
if (currentLevel.sources[source]) {
|
|
64
|
+
currentLevel.sources[source] = currentLevel.sources[source].add(size);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
currentLevel.sources[source] = size;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (levels.length === depth) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
levels.push(level);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return levels;
|
|
79
|
+
}
|
|
80
|
+
exports.createL2Levels = createL2Levels;
|
|
81
|
+
function getVammL2Generator({ marketAccount, oraclePriceData, numOrders, now, }) {
|
|
82
|
+
const updatedAmm = (0, __1.calculateUpdatedAMM)(marketAccount.amm, oraclePriceData);
|
|
83
|
+
const [openBids, openAsks] = (0, __1.calculateMarketOpenBidAsk)(updatedAmm.baseAssetReserve, updatedAmm.minBaseAssetReserve, updatedAmm.maxBaseAssetReserve, updatedAmm.orderStepSize);
|
|
84
|
+
now = now !== null && now !== void 0 ? now : new __1.BN(Date.now() / 1000);
|
|
85
|
+
const [bidReserves, askReserves] = (0, __1.calculateSpreadReserves)(updatedAmm, oraclePriceData, now);
|
|
86
|
+
let numBids = 0;
|
|
87
|
+
const baseSize = openBids.div(new __1.BN(numOrders));
|
|
88
|
+
const bidAmm = {
|
|
89
|
+
baseAssetReserve: bidReserves.baseAssetReserve,
|
|
90
|
+
quoteAssetReserve: bidReserves.quoteAssetReserve,
|
|
91
|
+
sqrtK: updatedAmm.sqrtK,
|
|
92
|
+
pegMultiplier: updatedAmm.pegMultiplier,
|
|
93
|
+
};
|
|
94
|
+
const getL2Bids = function* () {
|
|
95
|
+
while (numBids < numOrders) {
|
|
96
|
+
const [afterSwapQuoteReserves, afterSwapBaseReserves] = (0, __1.calculateAmmReservesAfterSwap)(bidAmm, 'base', baseSize, __1.SwapDirection.ADD);
|
|
97
|
+
const quoteSwapped = (0, __1.calculateQuoteAssetAmountSwapped)(bidAmm.quoteAssetReserve.sub(afterSwapQuoteReserves).abs(), bidAmm.pegMultiplier, __1.SwapDirection.ADD);
|
|
98
|
+
const price = quoteSwapped.mul(__1.BASE_PRECISION).div(baseSize);
|
|
99
|
+
bidAmm.baseAssetReserve = afterSwapBaseReserves;
|
|
100
|
+
bidAmm.quoteAssetReserve = afterSwapQuoteReserves;
|
|
101
|
+
yield {
|
|
102
|
+
price,
|
|
103
|
+
size: baseSize,
|
|
104
|
+
sources: { vamm: baseSize },
|
|
105
|
+
};
|
|
106
|
+
numBids++;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
let numAsks = 0;
|
|
110
|
+
const askSize = openAsks.abs().div(new __1.BN(numOrders));
|
|
111
|
+
const askAmm = {
|
|
112
|
+
baseAssetReserve: askReserves.baseAssetReserve,
|
|
113
|
+
quoteAssetReserve: askReserves.quoteAssetReserve,
|
|
114
|
+
sqrtK: updatedAmm.sqrtK,
|
|
115
|
+
pegMultiplier: updatedAmm.pegMultiplier,
|
|
116
|
+
};
|
|
117
|
+
const getL2Asks = function* () {
|
|
118
|
+
while (numAsks < numOrders) {
|
|
119
|
+
const [afterSwapQuoteReserves, afterSwapBaseReserves] = (0, __1.calculateAmmReservesAfterSwap)(askAmm, 'base', askSize, __1.SwapDirection.REMOVE);
|
|
120
|
+
const quoteSwapped = (0, __1.calculateQuoteAssetAmountSwapped)(askAmm.quoteAssetReserve.sub(afterSwapQuoteReserves).abs(), askAmm.pegMultiplier, __1.SwapDirection.REMOVE);
|
|
121
|
+
const price = quoteSwapped.mul(__1.BASE_PRECISION).div(askSize);
|
|
122
|
+
askAmm.baseAssetReserve = afterSwapBaseReserves;
|
|
123
|
+
askAmm.quoteAssetReserve = afterSwapQuoteReserves;
|
|
124
|
+
yield {
|
|
125
|
+
price,
|
|
126
|
+
size: askSize,
|
|
127
|
+
sources: { vamm: baseSize },
|
|
128
|
+
};
|
|
129
|
+
numAsks++;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
getL2Bids,
|
|
134
|
+
getL2Asks,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
exports.getVammL2Generator = getVammL2Generator;
|
package/lib/dlob/types.d.ts
CHANGED
package/lib/driftClient.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
/// <reference types="bn.js" />
|
|
3
2
|
import { AnchorProvider, BN, Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
4
3
|
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, ModifyOrderParams, PhoenixV1FulfillmentConfigAccount } from './types';
|
|
5
4
|
import * as anchor from '@coral-xyz/anchor';
|
|
@@ -32,9 +31,10 @@ export declare class DriftClient {
|
|
|
32
31
|
program: Program;
|
|
33
32
|
provider: AnchorProvider;
|
|
34
33
|
opts?: ConfirmOptions;
|
|
35
|
-
users: Map<
|
|
34
|
+
users: Map<string, User>;
|
|
36
35
|
userStats?: UserStats;
|
|
37
36
|
activeSubAccountId: number;
|
|
37
|
+
activeAuthority: PublicKey;
|
|
38
38
|
userAccountSubscriptionConfig: UserSubscriptionConfig;
|
|
39
39
|
accountSubscriber: DriftClientAccountSubscriber;
|
|
40
40
|
eventEmitter: StrictEventEmitter<EventEmitter, DriftClientAccountEvents>;
|
|
@@ -45,11 +45,14 @@ export declare class DriftClient {
|
|
|
45
45
|
authority: PublicKey;
|
|
46
46
|
marketLookupTable: PublicKey;
|
|
47
47
|
lookupTableAccount: AddressLookupTableAccount;
|
|
48
|
+
includeDelegates?: boolean;
|
|
49
|
+
authoritySubaccountMap?: Map<string, number[]>;
|
|
50
|
+
skipLoadUsers?: boolean;
|
|
48
51
|
get isSubscribed(): boolean;
|
|
49
52
|
set isSubscribed(val: boolean);
|
|
50
53
|
constructor(config: DriftClientConfig);
|
|
51
|
-
|
|
52
|
-
createUser(subAccountId: number, accountSubscriptionConfig: UserSubscriptionConfig): User;
|
|
54
|
+
getUserMapKey(subAccountId: number, authority: PublicKey): string;
|
|
55
|
+
createUser(subAccountId: number, accountSubscriptionConfig: UserSubscriptionConfig, authority?: PublicKey): User;
|
|
53
56
|
subscribe(): Promise<boolean>;
|
|
54
57
|
subscribeUsers(): Promise<boolean>[];
|
|
55
58
|
/**
|
|
@@ -91,11 +94,15 @@ export declare class DriftClient {
|
|
|
91
94
|
* @param newWallet
|
|
92
95
|
* @param subAccountIds
|
|
93
96
|
* @param activeSubAccountId
|
|
97
|
+
* @param includeDelegates
|
|
94
98
|
*/
|
|
95
|
-
updateWallet(newWallet: IWallet, subAccountIds?: number[], activeSubAccountId?: number): Promise<
|
|
96
|
-
switchActiveUser(subAccountId: number): void;
|
|
97
|
-
addUser(subAccountId: number): Promise<
|
|
98
|
-
|
|
99
|
+
updateWallet(newWallet: IWallet, subAccountIds?: number[], activeSubAccountId?: number, includeDelegates?: boolean, authoritySubaccountMap?: Map<string, number[]>): Promise<boolean>;
|
|
100
|
+
switchActiveUser(subAccountId: number, authority?: PublicKey): void;
|
|
101
|
+
addUser(subAccountId: number, authority?: PublicKey): Promise<boolean>;
|
|
102
|
+
/**
|
|
103
|
+
* Adds and subscribes to users based on params set by the constructor or by updateWallet.
|
|
104
|
+
*/
|
|
105
|
+
addAndSubscribeToUsers(): Promise<boolean>;
|
|
99
106
|
initializeUserAccount(subAccountId?: number, name?: string, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
|
|
100
107
|
getInitializeUserInstructions(subAccountId?: number, name?: string, referrerInfo?: ReferrerInfo): Promise<[PublicKey, TransactionInstruction]>;
|
|
101
108
|
getInitializeUserStatsIx(): Promise<TransactionInstruction>;
|
|
@@ -111,14 +118,14 @@ export declare class DriftClient {
|
|
|
111
118
|
getReferredUserStatsAccountsByReferrer(referrer: PublicKey): Promise<UserStatsAccount[]>;
|
|
112
119
|
getReferrerNameAccountsForAuthority(authority: PublicKey): Promise<ReferrerNameAccount[]>;
|
|
113
120
|
deleteUser(subAccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
114
|
-
getUser(subAccountId?: number): User;
|
|
121
|
+
getUser(subAccountId?: number, authority?: PublicKey): User;
|
|
115
122
|
getUsers(): User[];
|
|
116
123
|
getUserStats(): UserStats;
|
|
117
124
|
fetchReferrerNameAccount(name: string): Promise<ReferrerNameAccount | undefined>;
|
|
118
125
|
userStatsAccountPublicKey: PublicKey;
|
|
119
126
|
getUserStatsAccountPublicKey(): PublicKey;
|
|
120
|
-
getUserAccountPublicKey(): Promise<PublicKey>;
|
|
121
|
-
getUserAccount(subAccountId?: number): UserAccount | undefined;
|
|
127
|
+
getUserAccountPublicKey(subAccountId?: number, authority?: PublicKey): Promise<PublicKey>;
|
|
128
|
+
getUserAccount(subAccountId?: number, authority?: PublicKey): UserAccount | undefined;
|
|
122
129
|
/**
|
|
123
130
|
* Forces a fetch to rpc before returning accounts. Useful for anchor tests.
|
|
124
131
|
* @param subAccountId
|
|
@@ -374,6 +381,16 @@ export declare class DriftClient {
|
|
|
374
381
|
resolvePerpPnlDeficit(spotMarketIndex: number, perpMarketIndex: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
375
382
|
getResolvePerpPnlDeficitIx(spotMarketIndex: number, perpMarketIndex: number): Promise<TransactionInstruction>;
|
|
376
383
|
getPerpMarketExtendedInfo(marketIndex: number): PerpMarketExtendedInfo;
|
|
384
|
+
/**
|
|
385
|
+
* Returns the market index and type for a given market name
|
|
386
|
+
* E.g. "SOL-PERP" -> { marketIndex: 0, marketType: MarketType.PERP }
|
|
387
|
+
*
|
|
388
|
+
* @param name
|
|
389
|
+
*/
|
|
390
|
+
getMarketIndexAndType(name: string): {
|
|
391
|
+
marketIndex: number;
|
|
392
|
+
marketType: MarketType;
|
|
393
|
+
} | undefined;
|
|
377
394
|
sendTransaction(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
|
|
378
395
|
}
|
|
379
396
|
export {};
|
package/lib/driftClient.js
CHANGED
|
@@ -61,7 +61,7 @@ class DriftClient {
|
|
|
61
61
|
this._isSubscribed = val;
|
|
62
62
|
}
|
|
63
63
|
constructor(config) {
|
|
64
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
64
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
65
65
|
this.users = new Map();
|
|
66
66
|
this._isSubscribed = false;
|
|
67
67
|
this.perpMarketLastSlotCache = new Map();
|
|
@@ -72,10 +72,26 @@ class DriftClient {
|
|
|
72
72
|
this.provider = new anchor_1.AnchorProvider(config.connection, config.wallet, this.opts);
|
|
73
73
|
this.program = new anchor_1.Program(drift_json_1.default, config.programID, this.provider);
|
|
74
74
|
this.authority = (_a = config.authority) !== null && _a !== void 0 ? _a : this.wallet.publicKey;
|
|
75
|
-
|
|
76
|
-
this.
|
|
75
|
+
this.activeSubAccountId = (_b = config.activeSubAccountId) !== null && _b !== void 0 ? _b : 0;
|
|
76
|
+
this.skipLoadUsers = (_c = config.skipLoadUsers) !== null && _c !== void 0 ? _c : false;
|
|
77
|
+
if (config.includeDelegates && config.subAccountIds) {
|
|
78
|
+
throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
|
|
79
|
+
}
|
|
80
|
+
if (config.authoritySubaccountMap && config.subAccountIds) {
|
|
81
|
+
throw new Error('Can only pass one of authoritySubaccountMap or subAccountIds');
|
|
82
|
+
}
|
|
83
|
+
if (config.authoritySubaccountMap && config.includeDelegates) {
|
|
84
|
+
throw new Error('Can only pass one of authoritySubaccountMap or includeDelegates');
|
|
85
|
+
}
|
|
86
|
+
this.authoritySubaccountMap = config.authoritySubaccountMap
|
|
87
|
+
? config.authoritySubaccountMap
|
|
88
|
+
: config.subAccountIds
|
|
89
|
+
? new Map([[this.authority.toString(), config.subAccountIds]])
|
|
90
|
+
: new Map();
|
|
91
|
+
this.includeDelegates = (_d = config.includeDelegates) !== null && _d !== void 0 ? _d : false;
|
|
92
|
+
this.activeAuthority = this.authority;
|
|
77
93
|
this.userAccountSubscriptionConfig =
|
|
78
|
-
((
|
|
94
|
+
((_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.type) === 'polling'
|
|
79
95
|
? {
|
|
80
96
|
type: 'polling',
|
|
81
97
|
accountLoader: config.accountSubscription.accountLoader,
|
|
@@ -83,7 +99,6 @@ class DriftClient {
|
|
|
83
99
|
: {
|
|
84
100
|
type: 'websocket',
|
|
85
101
|
};
|
|
86
|
-
this.createUsers(subAccountIds, this.userAccountSubscriptionConfig);
|
|
87
102
|
if (config.userStats) {
|
|
88
103
|
this.userStats = new userStats_1.UserStats({
|
|
89
104
|
driftClient: this,
|
|
@@ -108,23 +123,20 @@ class DriftClient {
|
|
|
108
123
|
if (config.env && !this.marketLookupTable) {
|
|
109
124
|
this.marketLookupTable = new web3_js_1.PublicKey(config_1.configs[config.env].MARKET_LOOKUP_TABLE);
|
|
110
125
|
}
|
|
111
|
-
if (((
|
|
126
|
+
if (((_f = config.accountSubscription) === null || _f === void 0 ? void 0 : _f.type) === 'polling') {
|
|
112
127
|
this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, perpMarketIndexes !== null && perpMarketIndexes !== void 0 ? perpMarketIndexes : [], spotMarketIndexes !== null && spotMarketIndexes !== void 0 ? spotMarketIndexes : [], oracleInfos !== null && oracleInfos !== void 0 ? oracleInfos : []);
|
|
113
128
|
}
|
|
114
129
|
else {
|
|
115
130
|
this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, perpMarketIndexes !== null && perpMarketIndexes !== void 0 ? perpMarketIndexes : [], spotMarketIndexes !== null && spotMarketIndexes !== void 0 ? spotMarketIndexes : [], oracleInfos !== null && oracleInfos !== void 0 ? oracleInfos : []);
|
|
116
131
|
}
|
|
117
132
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
118
|
-
this.txSender = new retryTxSender_1.RetryTxSender(this.provider, (
|
|
133
|
+
this.txSender = new retryTxSender_1.RetryTxSender(this.provider, (_g = config.txSenderConfig) === null || _g === void 0 ? void 0 : _g.timeout, (_h = config.txSenderConfig) === null || _h === void 0 ? void 0 : _h.retrySleep, (_j = config.txSenderConfig) === null || _j === void 0 ? void 0 : _j.additionalConnections);
|
|
119
134
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const user = this.createUser(subAccountId, accountSubscriptionConfig);
|
|
123
|
-
this.users.set(subAccountId, user);
|
|
124
|
-
}
|
|
135
|
+
getUserMapKey(subAccountId, authority) {
|
|
136
|
+
return `${subAccountId}_${authority.toString()}`;
|
|
125
137
|
}
|
|
126
|
-
createUser(subAccountId, accountSubscriptionConfig) {
|
|
127
|
-
const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.authority, subAccountId);
|
|
138
|
+
createUser(subAccountId, accountSubscriptionConfig, authority) {
|
|
139
|
+
const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, authority !== null && authority !== void 0 ? authority : this.authority, subAccountId);
|
|
128
140
|
return new user_1.User({
|
|
129
141
|
driftClient: this,
|
|
130
142
|
userAccountPublicKey,
|
|
@@ -132,7 +144,7 @@ class DriftClient {
|
|
|
132
144
|
});
|
|
133
145
|
}
|
|
134
146
|
async subscribe() {
|
|
135
|
-
let subscribePromises = this.
|
|
147
|
+
let subscribePromises = [this.addAndSubscribeToUsers()].concat(this.accountSubscriber.subscribe());
|
|
136
148
|
if (this.userStats !== undefined) {
|
|
137
149
|
subscribePromises = subscribePromises.concat(this.userStats.subscribe());
|
|
138
150
|
}
|
|
@@ -262,54 +274,109 @@ class DriftClient {
|
|
|
262
274
|
* @param newWallet
|
|
263
275
|
* @param subAccountIds
|
|
264
276
|
* @param activeSubAccountId
|
|
277
|
+
* @param includeDelegates
|
|
265
278
|
*/
|
|
266
|
-
async updateWallet(newWallet, subAccountIds
|
|
279
|
+
async updateWallet(newWallet, subAccountIds, activeSubAccountId, includeDelegates, authoritySubaccountMap) {
|
|
267
280
|
const newProvider = new anchor_1.AnchorProvider(this.connection, newWallet, this.opts);
|
|
268
281
|
const newProgram = new anchor_1.Program(drift_json_1.default, this.program.programId, newProvider);
|
|
282
|
+
this.skipLoadUsers = false;
|
|
269
283
|
// Update provider for txSender with new wallet details
|
|
270
284
|
this.txSender.provider = newProvider;
|
|
271
285
|
this.wallet = newWallet;
|
|
272
286
|
this.provider = newProvider;
|
|
273
287
|
this.program = newProgram;
|
|
274
288
|
this.authority = newWallet.publicKey;
|
|
289
|
+
this.activeSubAccountId = activeSubAccountId;
|
|
290
|
+
this.userStatsAccountPublicKey = undefined;
|
|
291
|
+
this.includeDelegates = includeDelegates !== null && includeDelegates !== void 0 ? includeDelegates : false;
|
|
292
|
+
if (includeDelegates && subAccountIds) {
|
|
293
|
+
throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
|
|
294
|
+
}
|
|
295
|
+
if (authoritySubaccountMap && subAccountIds) {
|
|
296
|
+
throw new Error('Can only pass one of authoritySubaccountMap or subAccountIds');
|
|
297
|
+
}
|
|
298
|
+
if (authoritySubaccountMap && includeDelegates) {
|
|
299
|
+
throw new Error('Can only pass one of authoritySubaccountMap or includeDelegates');
|
|
300
|
+
}
|
|
301
|
+
this.authoritySubaccountMap = authoritySubaccountMap
|
|
302
|
+
? authoritySubaccountMap
|
|
303
|
+
: subAccountIds
|
|
304
|
+
? new Map([[this.authority.toString(), subAccountIds]])
|
|
305
|
+
: new Map();
|
|
306
|
+
let success = true;
|
|
275
307
|
if (this.isSubscribed) {
|
|
276
308
|
await Promise.all(this.unsubscribeUsers());
|
|
277
309
|
if (this.userStats) {
|
|
278
310
|
await this.userStats.unsubscribe();
|
|
279
311
|
this.userStats = new userStats_1.UserStats({
|
|
280
312
|
driftClient: this,
|
|
281
|
-
userStatsAccountPublicKey:
|
|
313
|
+
userStatsAccountPublicKey: this.getUserStatsAccountPublicKey(),
|
|
282
314
|
accountSubscription: this.userAccountSubscriptionConfig,
|
|
283
315
|
});
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
this.users.clear();
|
|
287
|
-
this.createUsers(subAccountIds, this.userAccountSubscriptionConfig);
|
|
288
|
-
if (this.isSubscribed) {
|
|
289
|
-
await Promise.all(this.subscribeUsers());
|
|
290
|
-
if (this.userStats) {
|
|
291
316
|
await this.userStats.subscribe();
|
|
292
317
|
}
|
|
318
|
+
this.users.clear();
|
|
319
|
+
success = await this.addAndSubscribeToUsers();
|
|
293
320
|
}
|
|
294
|
-
|
|
295
|
-
this.userStatsAccountPublicKey = undefined;
|
|
321
|
+
return success;
|
|
296
322
|
}
|
|
297
|
-
switchActiveUser(subAccountId) {
|
|
323
|
+
switchActiveUser(subAccountId, authority) {
|
|
298
324
|
this.activeSubAccountId = subAccountId;
|
|
325
|
+
this.activeAuthority = authority !== null && authority !== void 0 ? authority : this.authority;
|
|
299
326
|
}
|
|
300
|
-
async addUser(subAccountId) {
|
|
301
|
-
|
|
302
|
-
|
|
327
|
+
async addUser(subAccountId, authority) {
|
|
328
|
+
authority = authority !== null && authority !== void 0 ? authority : this.authority;
|
|
329
|
+
const userKey = this.getUserMapKey(subAccountId, authority);
|
|
330
|
+
if (this.users.has(userKey) && this.users.get(userKey).isSubscribed) {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
const user = this.createUser(subAccountId, this.userAccountSubscriptionConfig, authority);
|
|
334
|
+
const result = await user.subscribe();
|
|
335
|
+
if (result) {
|
|
336
|
+
this.users.set(userKey, user);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
return false;
|
|
303
341
|
}
|
|
304
|
-
const user = this.createUser(subAccountId, this.userAccountSubscriptionConfig);
|
|
305
|
-
await user.subscribe();
|
|
306
|
-
this.users.set(subAccountId, user);
|
|
307
342
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
343
|
+
/**
|
|
344
|
+
* Adds and subscribes to users based on params set by the constructor or by updateWallet.
|
|
345
|
+
*/
|
|
346
|
+
async addAndSubscribeToUsers() {
|
|
347
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
348
|
+
// save the rpc calls if driftclient is initialized without a real wallet
|
|
349
|
+
if (this.skipLoadUsers)
|
|
350
|
+
return true;
|
|
351
|
+
let result = true;
|
|
352
|
+
if (this.authoritySubaccountMap && this.authoritySubaccountMap.size > 0) {
|
|
353
|
+
this.authoritySubaccountMap.forEach(async (value, key) => {
|
|
354
|
+
for (const subAccountId of value) {
|
|
355
|
+
result =
|
|
356
|
+
result && (await this.addUser(subAccountId, new web3_js_1.PublicKey(key)));
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
if (this.activeSubAccountId == undefined) {
|
|
360
|
+
this.switchActiveUser((_a = [...this.authoritySubaccountMap.values()][0][0]) !== null && _a !== void 0 ? _a : 0, new web3_js_1.PublicKey((_b = [...this.authoritySubaccountMap.keys()][0]) !== null && _b !== void 0 ? _b : this.authority.toString()));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
const userAccounts = (_c = (await this.getUserAccountsForAuthority(this.authority))) !== null && _c !== void 0 ? _c : [];
|
|
365
|
+
let delegatedAccounts = [];
|
|
366
|
+
if (this.includeDelegates) {
|
|
367
|
+
delegatedAccounts =
|
|
368
|
+
(_d = (await this.getUserAccountsForDelegate(this.authority))) !== null && _d !== void 0 ? _d : [];
|
|
369
|
+
}
|
|
370
|
+
for (const account of userAccounts.concat(delegatedAccounts)) {
|
|
371
|
+
result =
|
|
372
|
+
result &&
|
|
373
|
+
(await this.addUser(account.subAccountId, account.authority));
|
|
374
|
+
}
|
|
375
|
+
if (this.activeSubAccountId == undefined) {
|
|
376
|
+
this.switchActiveUser((_f = (_e = userAccounts.concat(delegatedAccounts)[0]) === null || _e === void 0 ? void 0 : _e.subAccountId) !== null && _f !== void 0 ? _f : 0, (_h = (_g = userAccounts.concat(delegatedAccounts)[0]) === null || _g === void 0 ? void 0 : _g.authority) !== null && _h !== void 0 ? _h : this.authority);
|
|
377
|
+
}
|
|
312
378
|
}
|
|
379
|
+
return result;
|
|
313
380
|
}
|
|
314
381
|
async initializeUserAccount(subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
|
|
315
382
|
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
|
|
@@ -416,7 +483,7 @@ class DriftClient {
|
|
|
416
483
|
}
|
|
417
484
|
async updateUserMarginTradingEnabled(marginTradingEnabled, subAccountId = 0) {
|
|
418
485
|
const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
|
|
419
|
-
await this.addUser(subAccountId);
|
|
486
|
+
await this.addUser(subAccountId, this.wallet.publicKey);
|
|
420
487
|
const remainingAccounts = this.getRemainingAccounts({
|
|
421
488
|
userAccounts: [this.getUserAccount(subAccountId)],
|
|
422
489
|
});
|
|
@@ -464,7 +531,9 @@ class DriftClient {
|
|
|
464
531
|
},
|
|
465
532
|
},
|
|
466
533
|
]);
|
|
467
|
-
return programAccounts
|
|
534
|
+
return programAccounts
|
|
535
|
+
.map((programAccount) => programAccount.account)
|
|
536
|
+
.sort((a, b) => a.subAccountId - b.subAccountId);
|
|
468
537
|
}
|
|
469
538
|
async getUserAccountsAndAddressesForAuthority(authority) {
|
|
470
539
|
const programAccounts = await this.program.account.user.all([
|
|
@@ -488,7 +557,9 @@ class DriftClient {
|
|
|
488
557
|
},
|
|
489
558
|
},
|
|
490
559
|
]);
|
|
491
|
-
return programAccounts
|
|
560
|
+
return programAccounts
|
|
561
|
+
.map((programAccount) => programAccount.account)
|
|
562
|
+
.sort((a, b) => a.subAccountId - b.subAccountId);
|
|
492
563
|
}
|
|
493
564
|
async getReferredUserStatsAccountsByReferrer(referrer) {
|
|
494
565
|
const programAccounts = await this.program.account.userStats.all([
|
|
@@ -526,19 +597,25 @@ class DriftClient {
|
|
|
526
597
|
},
|
|
527
598
|
});
|
|
528
599
|
const { txSig } = await this.sendTransaction((0, utils_1.wrapInTx)(ix, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
529
|
-
|
|
530
|
-
this.users.
|
|
600
|
+
const userMapKey = this.getUserMapKey(subAccountId, this.wallet.publicKey);
|
|
601
|
+
await ((_a = this.users.get(userMapKey)) === null || _a === void 0 ? void 0 : _a.unsubscribe());
|
|
602
|
+
this.users.delete(userMapKey);
|
|
531
603
|
return txSig;
|
|
532
604
|
}
|
|
533
|
-
getUser(subAccountId) {
|
|
605
|
+
getUser(subAccountId, authority) {
|
|
534
606
|
subAccountId = subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId;
|
|
535
|
-
|
|
607
|
+
authority = authority !== null && authority !== void 0 ? authority : this.activeAuthority;
|
|
608
|
+
const userMapKey = this.getUserMapKey(subAccountId, authority);
|
|
609
|
+
if (!this.users.has(userMapKey)) {
|
|
536
610
|
throw new Error(`Clearing House has no user for user id ${subAccountId}`);
|
|
537
611
|
}
|
|
538
|
-
return this.users.get(
|
|
612
|
+
return this.users.get(userMapKey);
|
|
539
613
|
}
|
|
540
614
|
getUsers() {
|
|
541
|
-
|
|
615
|
+
// delegate users get added to the end
|
|
616
|
+
return [...this.users.values()]
|
|
617
|
+
.filter((acct) => acct.getUserAccount().authority.equals(this.authority))
|
|
618
|
+
.concat([...this.users.values()].filter((acct) => !acct.getUserAccount().authority.equals(this.authority)));
|
|
542
619
|
}
|
|
543
620
|
getUserStats() {
|
|
544
621
|
return this.userStats;
|
|
@@ -552,14 +629,14 @@ class DriftClient {
|
|
|
552
629
|
if (this.userStatsAccountPublicKey) {
|
|
553
630
|
return this.userStatsAccountPublicKey;
|
|
554
631
|
}
|
|
555
|
-
this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.
|
|
632
|
+
this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.activeAuthority);
|
|
556
633
|
return this.userStatsAccountPublicKey;
|
|
557
634
|
}
|
|
558
|
-
async getUserAccountPublicKey() {
|
|
559
|
-
return this.getUser().userAccountPublicKey;
|
|
635
|
+
async getUserAccountPublicKey(subAccountId, authority) {
|
|
636
|
+
return this.getUser(subAccountId, authority).userAccountPublicKey;
|
|
560
637
|
}
|
|
561
|
-
getUserAccount(subAccountId) {
|
|
562
|
-
return this.getUser(subAccountId).getUserAccount();
|
|
638
|
+
getUserAccount(subAccountId, authority) {
|
|
639
|
+
return this.getUser(subAccountId, authority).getUserAccount();
|
|
563
640
|
}
|
|
564
641
|
/**
|
|
565
642
|
* Forces a fetch to rpc before returning accounts. Useful for anchor tests.
|
|
@@ -1059,9 +1136,10 @@ class DriftClient {
|
|
|
1059
1136
|
const fromUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, fromSubAccountId);
|
|
1060
1137
|
const toUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, toSubAccountId);
|
|
1061
1138
|
let remainingAccounts;
|
|
1062
|
-
|
|
1139
|
+
const userMapKey = this.getUserMapKey(fromSubAccountId, this.wallet.publicKey);
|
|
1140
|
+
if (this.users.has(userMapKey)) {
|
|
1063
1141
|
remainingAccounts = this.getRemainingAccounts({
|
|
1064
|
-
userAccounts: [this.users.get(
|
|
1142
|
+
userAccounts: [this.users.get(userMapKey).getUserAccount()],
|
|
1065
1143
|
useMarketLastSlotCache: true,
|
|
1066
1144
|
writableSpotMarketIndexes: [marketIndex],
|
|
1067
1145
|
});
|
|
@@ -1799,7 +1877,7 @@ class DriftClient {
|
|
|
1799
1877
|
});
|
|
1800
1878
|
}
|
|
1801
1879
|
async forceCancelOrders(userAccountPublicKey, user, txParams) {
|
|
1802
|
-
const { txSig } = await this.
|
|
1880
|
+
const { txSig } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getForceCancelOrdersIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1803
1881
|
return txSig;
|
|
1804
1882
|
}
|
|
1805
1883
|
async getForceCancelOrdersIx(userAccountPublicKey, userAccount) {
|
|
@@ -1819,7 +1897,7 @@ class DriftClient {
|
|
|
1819
1897
|
});
|
|
1820
1898
|
}
|
|
1821
1899
|
async updateUserIdle(userAccountPublicKey, user, txParams) {
|
|
1822
|
-
const { txSig } = await this.
|
|
1900
|
+
const { txSig } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getUpdateUserIdleIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1823
1901
|
return txSig;
|
|
1824
1902
|
}
|
|
1825
1903
|
async getUpdateUserIdleIx(userAccountPublicKey, userAccount) {
|
|
@@ -2679,6 +2757,31 @@ class DriftClient {
|
|
|
2679
2757
|
};
|
|
2680
2758
|
return extendedInfo;
|
|
2681
2759
|
}
|
|
2760
|
+
/**
|
|
2761
|
+
* Returns the market index and type for a given market name
|
|
2762
|
+
* E.g. "SOL-PERP" -> { marketIndex: 0, marketType: MarketType.PERP }
|
|
2763
|
+
*
|
|
2764
|
+
* @param name
|
|
2765
|
+
*/
|
|
2766
|
+
getMarketIndexAndType(name) {
|
|
2767
|
+
for (const perpMarketAccount of this.getPerpMarketAccounts()) {
|
|
2768
|
+
if ((0, userName_1.decodeName)(perpMarketAccount.name) === name) {
|
|
2769
|
+
return {
|
|
2770
|
+
marketIndex: perpMarketAccount.marketIndex,
|
|
2771
|
+
marketType: types_1.MarketType.PERP,
|
|
2772
|
+
};
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
for (const spotMarketAccount of this.getSpotMarketAccounts()) {
|
|
2776
|
+
if ((0, userName_1.decodeName)(spotMarketAccount.name) === name) {
|
|
2777
|
+
return {
|
|
2778
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
2779
|
+
marketType: types_1.MarketType.SPOT,
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
return undefined;
|
|
2784
|
+
}
|
|
2682
2785
|
sendTransaction(tx, additionalSigners, opts, preSigned) {
|
|
2683
2786
|
return this.txSender.send(tx, additionalSigners, opts, preSigned);
|
|
2684
2787
|
}
|
|
@@ -19,6 +19,9 @@ export type DriftClientConfig = {
|
|
|
19
19
|
env?: DriftEnv;
|
|
20
20
|
userStats?: boolean;
|
|
21
21
|
authority?: PublicKey;
|
|
22
|
+
includeDelegates?: boolean;
|
|
23
|
+
authoritySubaccountMap?: Map<string, number[]>;
|
|
24
|
+
skipLoadUsers?: boolean;
|
|
22
25
|
};
|
|
23
26
|
export type DriftClientSubscriptionConfig = {
|
|
24
27
|
type: 'websocket';
|
package/lib/factory/bigNum.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
import { BN } from '@coral-xyz/anchor';
|
|
3
2
|
export declare class BigNum {
|
|
4
3
|
val: BN;
|
|
@@ -44,11 +43,11 @@ export declare class BigNum {
|
|
|
44
43
|
gte(bn: BigNum | BN, ignorePrecision?: boolean): boolean;
|
|
45
44
|
lte(bn: BigNum | BN, ignorePrecision?: boolean): boolean;
|
|
46
45
|
eq(bn: BigNum | BN, ignorePrecision?: boolean): boolean;
|
|
47
|
-
eqZero():
|
|
48
|
-
gtZero():
|
|
49
|
-
ltZero():
|
|
50
|
-
gteZero():
|
|
51
|
-
lteZero():
|
|
46
|
+
eqZero(): any;
|
|
47
|
+
gtZero(): any;
|
|
48
|
+
ltZero(): any;
|
|
49
|
+
gteZero(): any;
|
|
50
|
+
lteZero(): any;
|
|
52
51
|
abs(): BigNum;
|
|
53
52
|
neg(): BigNum;
|
|
54
53
|
toString: (base?: number | 'hex', length?: number) => string;
|
|
@@ -88,8 +87,8 @@ export declare class BigNum {
|
|
|
88
87
|
toNotional(useTradePrecision?: boolean, precisionOverride?: number): string;
|
|
89
88
|
toMillified(precision?: number, rounded?: boolean): string;
|
|
90
89
|
toJSON(): {
|
|
91
|
-
val:
|
|
92
|
-
precision:
|
|
90
|
+
val: any;
|
|
91
|
+
precision: any;
|
|
93
92
|
};
|
|
94
93
|
isNeg(): boolean;
|
|
95
94
|
isPos(): boolean;
|
package/lib/idl/drift.json
CHANGED