@drift-labs/sdk 2.20.0-beta.3 → 2.21.0-beta.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/driftClient.d.ts +6 -3
- package/lib/driftClient.js +60 -20
- package/lib/idl/drift.json +12 -3
- package/lib/types.d.ts +2 -1
- package/lib/user.d.ts +1 -0
- package/lib/user.js +32 -0
- package/lib/userMap/userMap.d.ts +1 -1
- package/lib/userMap/userMap.js +2 -2
- package/package.json +1 -1
- package/src/driftClient.ts +96 -23
- package/src/idl/drift.json +12 -3
- package/src/types.ts +2 -1
- package/src/user.ts +41 -1
- package/src/userMap/userMap.ts +4 -4
- package/src/assert/assert.js +0 -9
- package/src/token/index.js +0 -38
- package/src/util/computeUnits.js +0 -27
- package/src/util/getTokenAddress.js +0 -9
- package/src/util/promiseTimeout.js +0 -14
- package/src/util/tps.js +0 -27
package/lib/driftClient.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="bn.js" />
|
|
3
|
-
import { AnchorProvider, BN, Program } from '@project-serum/anchor';
|
|
3
|
+
import { AnchorProvider, BN, Program, ProgramAccount } from '@project-serum/anchor';
|
|
4
4
|
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, OrderType, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo } from './types';
|
|
5
5
|
import * as anchor from '@project-serum/anchor';
|
|
6
6
|
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer, AddressLookupTableAccount } from '@solana/web3.js';
|
|
@@ -101,6 +101,7 @@ export declare class DriftClient {
|
|
|
101
101
|
updateUserCustomMarginRatio(marginRatio: number, subAccountId?: number): Promise<TransactionSignature>;
|
|
102
102
|
updateUserMarginTradingEnabled(marginTradingEnabled: boolean, subAccountId?: number): Promise<TransactionSignature>;
|
|
103
103
|
updateUserDelegate(delegate: PublicKey, subAccountId?: number): Promise<TransactionSignature>;
|
|
104
|
+
fetchAllUserAccounts(includeIdle?: boolean): Promise<ProgramAccount<UserAccount>[]>;
|
|
104
105
|
getUserAccountsForDelegate(delegate: PublicKey): Promise<UserAccount[]>;
|
|
105
106
|
getUserAccountsForAuthority(authority: PublicKey): Promise<UserAccount[]>;
|
|
106
107
|
deleteUser(subAccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
@@ -200,8 +201,10 @@ export declare class DriftClient {
|
|
|
200
201
|
getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
|
|
201
202
|
forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
202
203
|
getForceCancelOrdersIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
updateUserInactive(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
205
|
+
getUpdateUserInactiveIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
206
|
+
placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
207
|
+
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
205
208
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
206
209
|
getPlaceAndMakePerpOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
207
210
|
placeAndTakeSpotOrder(orderParams: OptionalOrderParams, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
package/lib/driftClient.js
CHANGED
|
@@ -424,6 +424,20 @@ class DriftClient {
|
|
|
424
424
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
425
425
|
return txSig;
|
|
426
426
|
}
|
|
427
|
+
async fetchAllUserAccounts(includeIdle = true) {
|
|
428
|
+
let filters = undefined;
|
|
429
|
+
if (!includeIdle) {
|
|
430
|
+
filters = [
|
|
431
|
+
{
|
|
432
|
+
memcmp: {
|
|
433
|
+
offset: 4350,
|
|
434
|
+
bytes: bs58_1.default.encode(Uint8Array.from([0])),
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
];
|
|
438
|
+
}
|
|
439
|
+
return (await this.program.account.user.all(filters));
|
|
440
|
+
}
|
|
427
441
|
async getUserAccountsForDelegate(delegate) {
|
|
428
442
|
const programAccounts = await this.program.account.user.all([
|
|
429
443
|
{
|
|
@@ -1578,6 +1592,25 @@ class DriftClient {
|
|
|
1578
1592
|
remainingAccounts,
|
|
1579
1593
|
});
|
|
1580
1594
|
}
|
|
1595
|
+
async updateUserInactive(userAccountPublicKey, user, txParams) {
|
|
1596
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateUserInactiveIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1597
|
+
return txSig;
|
|
1598
|
+
}
|
|
1599
|
+
async getUpdateUserInactiveIx(userAccountPublicKey, userAccount) {
|
|
1600
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1601
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1602
|
+
userAccounts: [userAccount],
|
|
1603
|
+
});
|
|
1604
|
+
return await this.program.instruction.updateUserInactive({
|
|
1605
|
+
accounts: {
|
|
1606
|
+
state: await this.getStatePublicKey(),
|
|
1607
|
+
filler: fillerPublicKey,
|
|
1608
|
+
user: userAccountPublicKey,
|
|
1609
|
+
authority: this.wallet.publicKey,
|
|
1610
|
+
},
|
|
1611
|
+
remainingAccounts,
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1581
1614
|
async placeAndTakePerpOrder(orderParams, makerInfo, referrerInfo, txParams) {
|
|
1582
1615
|
const { txSig, slot } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1583
1616
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
@@ -1587,42 +1620,49 @@ class DriftClient {
|
|
|
1587
1620
|
orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
|
|
1588
1621
|
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
1589
1622
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1623
|
+
makerInfo = Array.isArray(makerInfo)
|
|
1624
|
+
? makerInfo
|
|
1625
|
+
: makerInfo
|
|
1626
|
+
? [makerInfo]
|
|
1627
|
+
: [];
|
|
1590
1628
|
const userAccounts = [this.getUserAccount()];
|
|
1591
|
-
|
|
1592
|
-
userAccounts.push(
|
|
1629
|
+
for (const maker of makerInfo) {
|
|
1630
|
+
userAccounts.push(maker.makerUserAccount);
|
|
1593
1631
|
}
|
|
1594
1632
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1595
1633
|
userAccounts,
|
|
1596
1634
|
useMarketLastSlotCache: true,
|
|
1597
1635
|
writablePerpMarketIndexes: [orderParams.marketIndex],
|
|
1598
1636
|
});
|
|
1599
|
-
|
|
1600
|
-
if (makerInfo) {
|
|
1601
|
-
makerOrderId = makerInfo.order.orderId;
|
|
1602
|
-
remainingAccounts.push({
|
|
1603
|
-
pubkey: makerInfo.maker,
|
|
1604
|
-
isSigner: false,
|
|
1605
|
-
isWritable: true,
|
|
1606
|
-
});
|
|
1607
|
-
remainingAccounts.push({
|
|
1608
|
-
pubkey: makerInfo.makerStats,
|
|
1609
|
-
isSigner: false,
|
|
1610
|
-
isWritable: true,
|
|
1611
|
-
});
|
|
1612
|
-
}
|
|
1613
|
-
if (referrerInfo) {
|
|
1637
|
+
for (const maker of makerInfo) {
|
|
1614
1638
|
remainingAccounts.push({
|
|
1615
|
-
pubkey:
|
|
1639
|
+
pubkey: maker.maker,
|
|
1616
1640
|
isWritable: true,
|
|
1617
1641
|
isSigner: false,
|
|
1618
1642
|
});
|
|
1619
1643
|
remainingAccounts.push({
|
|
1620
|
-
pubkey:
|
|
1644
|
+
pubkey: maker.makerStats,
|
|
1621
1645
|
isWritable: true,
|
|
1622
1646
|
isSigner: false,
|
|
1623
1647
|
});
|
|
1624
1648
|
}
|
|
1625
|
-
|
|
1649
|
+
if (referrerInfo) {
|
|
1650
|
+
const referrerIsMaker = makerInfo.find((maker) => maker.maker.equals(referrerInfo.referrer)) !==
|
|
1651
|
+
undefined;
|
|
1652
|
+
if (!referrerIsMaker) {
|
|
1653
|
+
remainingAccounts.push({
|
|
1654
|
+
pubkey: referrerInfo.referrer,
|
|
1655
|
+
isWritable: true,
|
|
1656
|
+
isSigner: false,
|
|
1657
|
+
});
|
|
1658
|
+
remainingAccounts.push({
|
|
1659
|
+
pubkey: referrerInfo.referrerStats,
|
|
1660
|
+
isWritable: true,
|
|
1661
|
+
isSigner: false,
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return await this.program.instruction.placeAndTakePerpOrder(orderParams, null, {
|
|
1626
1666
|
accounts: {
|
|
1627
1667
|
state: await this.getStatePublicKey(),
|
|
1628
1668
|
user: userAccountPublicKey,
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.21.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -4543,7 +4543,7 @@
|
|
|
4543
4543
|
"type": "u64"
|
|
4544
4544
|
},
|
|
4545
4545
|
{
|
|
4546
|
-
"name": "
|
|
4546
|
+
"name": "lastActiveSlot",
|
|
4547
4547
|
"type": "u64"
|
|
4548
4548
|
},
|
|
4549
4549
|
{
|
|
@@ -4572,12 +4572,16 @@
|
|
|
4572
4572
|
"name": "isMarginTradingEnabled",
|
|
4573
4573
|
"type": "bool"
|
|
4574
4574
|
},
|
|
4575
|
+
{
|
|
4576
|
+
"name": "idle",
|
|
4577
|
+
"type": "bool"
|
|
4578
|
+
},
|
|
4575
4579
|
{
|
|
4576
4580
|
"name": "padding",
|
|
4577
4581
|
"type": {
|
|
4578
4582
|
"array": [
|
|
4579
4583
|
"u8",
|
|
4580
|
-
|
|
4584
|
+
25
|
|
4581
4585
|
]
|
|
4582
4586
|
}
|
|
4583
4587
|
}
|
|
@@ -8733,6 +8737,11 @@
|
|
|
8733
8737
|
"code": 6237,
|
|
8734
8738
|
"name": "UnableToLoadUserStatsAccount",
|
|
8735
8739
|
"msg": "UnableToLoadUserStatsAccount"
|
|
8740
|
+
},
|
|
8741
|
+
{
|
|
8742
|
+
"code": 6238,
|
|
8743
|
+
"name": "UserNotInactive",
|
|
8744
|
+
"msg": "User Not Inactive"
|
|
8736
8745
|
}
|
|
8737
8746
|
]
|
|
8738
8747
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -845,8 +845,9 @@ export type UserAccount = {
|
|
|
845
845
|
totalSocialLoss: BN;
|
|
846
846
|
cumulativePerpFunding: BN;
|
|
847
847
|
liquidationMarginFreed: BN;
|
|
848
|
-
|
|
848
|
+
lastActiveSlot: BN;
|
|
849
849
|
isMarginTradingEnabled: boolean;
|
|
850
|
+
inactive: boolean;
|
|
850
851
|
};
|
|
851
852
|
export type SpotPosition = {
|
|
852
853
|
marketIndex: number;
|
package/lib/user.d.ts
CHANGED
|
@@ -269,6 +269,7 @@ export declare class User {
|
|
|
269
269
|
depositAmount: BN;
|
|
270
270
|
maxDepositAmount: BN;
|
|
271
271
|
};
|
|
272
|
+
canMakeIdle(slot: BN, slotsBeforeIdle: BN): boolean;
|
|
272
273
|
/**
|
|
273
274
|
* Get the total position value, excluding any position coming from the given target market
|
|
274
275
|
* @param marketToIgnore
|
package/lib/user.js
CHANGED
|
@@ -1212,6 +1212,38 @@ class User {
|
|
|
1212
1212
|
depositAmount,
|
|
1213
1213
|
};
|
|
1214
1214
|
}
|
|
1215
|
+
canMakeIdle(slot, slotsBeforeIdle) {
|
|
1216
|
+
const userAccount = this.getUserAccount();
|
|
1217
|
+
if (userAccount.inactive) {
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
const userLastActiveSlot = userAccount.lastActiveSlot;
|
|
1221
|
+
if (userLastActiveSlot.lt(slotsBeforeIdle)) {
|
|
1222
|
+
return false;
|
|
1223
|
+
}
|
|
1224
|
+
if (this.isBeingLiquidated()) {
|
|
1225
|
+
return false;
|
|
1226
|
+
}
|
|
1227
|
+
for (const perpPosition of userAccount.perpPositions) {
|
|
1228
|
+
if (!(0, position_1.positionIsAvailable)(perpPosition)) {
|
|
1229
|
+
return false;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1233
|
+
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
|
|
1234
|
+
return false;
|
|
1235
|
+
}
|
|
1236
|
+
if (spotPosition.openOrders !== 0) {
|
|
1237
|
+
return false;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
for (const order of userAccount.orders) {
|
|
1241
|
+
if (!(0, types_1.isVariant)(order.status, 'init')) {
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1215
1247
|
/**
|
|
1216
1248
|
* Get the total position value, excluding any position coming from the given target market
|
|
1217
1249
|
* @param marketToIgnore
|
package/lib/userMap/userMap.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class UserMap implements UserMapInterface {
|
|
|
15
15
|
private driftClient;
|
|
16
16
|
private accountSubscription;
|
|
17
17
|
constructor(driftClient: DriftClient, accountSubscription: UserSubscriptionConfig);
|
|
18
|
-
fetchAllUsers(): Promise<void>;
|
|
18
|
+
fetchAllUsers(includeIdle?: boolean): Promise<void>;
|
|
19
19
|
addPubkey(userAccountPublicKey: PublicKey): Promise<void>;
|
|
20
20
|
has(key: string): boolean;
|
|
21
21
|
/**
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -9,10 +9,10 @@ class UserMap {
|
|
|
9
9
|
this.driftClient = driftClient;
|
|
10
10
|
this.accountSubscription = accountSubscription;
|
|
11
11
|
}
|
|
12
|
-
async fetchAllUsers() {
|
|
12
|
+
async fetchAllUsers(includeIdle = true) {
|
|
13
13
|
const userArray = [];
|
|
14
14
|
const userAccountArray = [];
|
|
15
|
-
const programUserAccounts =
|
|
15
|
+
const programUserAccounts = await this.driftClient.fetchAllUserAccounts(includeIdle);
|
|
16
16
|
for (const programUserAccount of programUserAccounts) {
|
|
17
17
|
if (this.userMap.has(programUserAccount.publicKey.toString())) {
|
|
18
18
|
continue;
|
package/package.json
CHANGED
package/src/driftClient.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AnchorProvider,
|
|
3
|
+
BN,
|
|
4
|
+
Idl,
|
|
5
|
+
Program,
|
|
6
|
+
ProgramAccount,
|
|
7
|
+
} from '@project-serum/anchor';
|
|
2
8
|
import bs58 from 'bs58';
|
|
3
9
|
import {
|
|
4
10
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
@@ -713,6 +719,25 @@ export class DriftClient {
|
|
|
713
719
|
return txSig;
|
|
714
720
|
}
|
|
715
721
|
|
|
722
|
+
public async fetchAllUserAccounts(
|
|
723
|
+
includeIdle = true
|
|
724
|
+
): Promise<ProgramAccount<UserAccount>[]> {
|
|
725
|
+
let filters = undefined;
|
|
726
|
+
if (!includeIdle) {
|
|
727
|
+
filters = [
|
|
728
|
+
{
|
|
729
|
+
memcmp: {
|
|
730
|
+
offset: 4350,
|
|
731
|
+
bytes: bs58.encode(Uint8Array.from([0])),
|
|
732
|
+
},
|
|
733
|
+
},
|
|
734
|
+
];
|
|
735
|
+
}
|
|
736
|
+
return (await this.program.account.user.all(
|
|
737
|
+
filters
|
|
738
|
+
)) as ProgramAccount<UserAccount>[];
|
|
739
|
+
}
|
|
740
|
+
|
|
716
741
|
public async getUserAccountsForDelegate(
|
|
717
742
|
delegate: PublicKey
|
|
718
743
|
): Promise<UserAccount[]> {
|
|
@@ -2734,9 +2759,47 @@ export class DriftClient {
|
|
|
2734
2759
|
});
|
|
2735
2760
|
}
|
|
2736
2761
|
|
|
2762
|
+
public async updateUserInactive(
|
|
2763
|
+
userAccountPublicKey: PublicKey,
|
|
2764
|
+
user: UserAccount,
|
|
2765
|
+
txParams?: TxParams
|
|
2766
|
+
): Promise<TransactionSignature> {
|
|
2767
|
+
const { txSig } = await this.txSender.send(
|
|
2768
|
+
wrapInTx(
|
|
2769
|
+
await this.getUpdateUserInactiveIx(userAccountPublicKey, user),
|
|
2770
|
+
txParams?.computeUnits,
|
|
2771
|
+
txParams?.computeUnitsPrice
|
|
2772
|
+
),
|
|
2773
|
+
[],
|
|
2774
|
+
this.opts
|
|
2775
|
+
);
|
|
2776
|
+
return txSig;
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
public async getUpdateUserInactiveIx(
|
|
2780
|
+
userAccountPublicKey: PublicKey,
|
|
2781
|
+
userAccount: UserAccount
|
|
2782
|
+
): Promise<TransactionInstruction> {
|
|
2783
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2784
|
+
|
|
2785
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2786
|
+
userAccounts: [userAccount],
|
|
2787
|
+
});
|
|
2788
|
+
|
|
2789
|
+
return await this.program.instruction.updateUserInactive({
|
|
2790
|
+
accounts: {
|
|
2791
|
+
state: await this.getStatePublicKey(),
|
|
2792
|
+
filler: fillerPublicKey,
|
|
2793
|
+
user: userAccountPublicKey,
|
|
2794
|
+
authority: this.wallet.publicKey,
|
|
2795
|
+
},
|
|
2796
|
+
remainingAccounts,
|
|
2797
|
+
});
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2737
2800
|
public async placeAndTakePerpOrder(
|
|
2738
2801
|
orderParams: OptionalOrderParams,
|
|
2739
|
-
makerInfo?: MakerInfo,
|
|
2802
|
+
makerInfo?: MakerInfo | MakerInfo[],
|
|
2740
2803
|
referrerInfo?: ReferrerInfo,
|
|
2741
2804
|
txParams?: TxParams
|
|
2742
2805
|
): Promise<TransactionSignature> {
|
|
@@ -2759,54 +2822,64 @@ export class DriftClient {
|
|
|
2759
2822
|
|
|
2760
2823
|
public async getPlaceAndTakePerpOrderIx(
|
|
2761
2824
|
orderParams: OptionalOrderParams,
|
|
2762
|
-
makerInfo?: MakerInfo,
|
|
2825
|
+
makerInfo?: MakerInfo | MakerInfo[],
|
|
2763
2826
|
referrerInfo?: ReferrerInfo
|
|
2764
2827
|
): Promise<TransactionInstruction> {
|
|
2765
2828
|
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
2766
2829
|
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2767
2830
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
2768
2831
|
|
|
2832
|
+
makerInfo = Array.isArray(makerInfo)
|
|
2833
|
+
? makerInfo
|
|
2834
|
+
: makerInfo
|
|
2835
|
+
? [makerInfo]
|
|
2836
|
+
: [];
|
|
2837
|
+
|
|
2769
2838
|
const userAccounts = [this.getUserAccount()];
|
|
2770
|
-
|
|
2771
|
-
userAccounts.push(
|
|
2839
|
+
for (const maker of makerInfo) {
|
|
2840
|
+
userAccounts.push(maker.makerUserAccount);
|
|
2772
2841
|
}
|
|
2842
|
+
|
|
2773
2843
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2774
2844
|
userAccounts,
|
|
2775
2845
|
useMarketLastSlotCache: true,
|
|
2776
2846
|
writablePerpMarketIndexes: [orderParams.marketIndex],
|
|
2777
2847
|
});
|
|
2778
2848
|
|
|
2779
|
-
|
|
2780
|
-
if (makerInfo) {
|
|
2781
|
-
makerOrderId = makerInfo.order.orderId;
|
|
2849
|
+
for (const maker of makerInfo) {
|
|
2782
2850
|
remainingAccounts.push({
|
|
2783
|
-
pubkey:
|
|
2784
|
-
isSigner: false,
|
|
2851
|
+
pubkey: maker.maker,
|
|
2785
2852
|
isWritable: true,
|
|
2853
|
+
isSigner: false,
|
|
2786
2854
|
});
|
|
2787
2855
|
remainingAccounts.push({
|
|
2788
|
-
pubkey:
|
|
2789
|
-
isSigner: false,
|
|
2856
|
+
pubkey: maker.makerStats,
|
|
2790
2857
|
isWritable: true,
|
|
2858
|
+
isSigner: false,
|
|
2791
2859
|
});
|
|
2792
2860
|
}
|
|
2793
2861
|
|
|
2794
2862
|
if (referrerInfo) {
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2863
|
+
const referrerIsMaker =
|
|
2864
|
+
makerInfo.find((maker) => maker.maker.equals(referrerInfo.referrer)) !==
|
|
2865
|
+
undefined;
|
|
2866
|
+
if (!referrerIsMaker) {
|
|
2867
|
+
remainingAccounts.push({
|
|
2868
|
+
pubkey: referrerInfo.referrer,
|
|
2869
|
+
isWritable: true,
|
|
2870
|
+
isSigner: false,
|
|
2871
|
+
});
|
|
2872
|
+
remainingAccounts.push({
|
|
2873
|
+
pubkey: referrerInfo.referrerStats,
|
|
2874
|
+
isWritable: true,
|
|
2875
|
+
isSigner: false,
|
|
2876
|
+
});
|
|
2877
|
+
}
|
|
2805
2878
|
}
|
|
2806
2879
|
|
|
2807
2880
|
return await this.program.instruction.placeAndTakePerpOrder(
|
|
2808
2881
|
orderParams,
|
|
2809
|
-
|
|
2882
|
+
null,
|
|
2810
2883
|
{
|
|
2811
2884
|
accounts: {
|
|
2812
2885
|
state: await this.getStatePublicKey(),
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.21.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -4543,7 +4543,7 @@
|
|
|
4543
4543
|
"type": "u64"
|
|
4544
4544
|
},
|
|
4545
4545
|
{
|
|
4546
|
-
"name": "
|
|
4546
|
+
"name": "lastActiveSlot",
|
|
4547
4547
|
"type": "u64"
|
|
4548
4548
|
},
|
|
4549
4549
|
{
|
|
@@ -4572,12 +4572,16 @@
|
|
|
4572
4572
|
"name": "isMarginTradingEnabled",
|
|
4573
4573
|
"type": "bool"
|
|
4574
4574
|
},
|
|
4575
|
+
{
|
|
4576
|
+
"name": "idle",
|
|
4577
|
+
"type": "bool"
|
|
4578
|
+
},
|
|
4575
4579
|
{
|
|
4576
4580
|
"name": "padding",
|
|
4577
4581
|
"type": {
|
|
4578
4582
|
"array": [
|
|
4579
4583
|
"u8",
|
|
4580
|
-
|
|
4584
|
+
25
|
|
4581
4585
|
]
|
|
4582
4586
|
}
|
|
4583
4587
|
}
|
|
@@ -8733,6 +8737,11 @@
|
|
|
8733
8737
|
"code": 6237,
|
|
8734
8738
|
"name": "UnableToLoadUserStatsAccount",
|
|
8735
8739
|
"msg": "UnableToLoadUserStatsAccount"
|
|
8740
|
+
},
|
|
8741
|
+
{
|
|
8742
|
+
"code": 6238,
|
|
8743
|
+
"name": "UserNotInactive",
|
|
8744
|
+
"msg": "User Not Inactive"
|
|
8736
8745
|
}
|
|
8737
8746
|
]
|
|
8738
8747
|
}
|
package/src/types.ts
CHANGED
|
@@ -798,8 +798,9 @@ export type UserAccount = {
|
|
|
798
798
|
totalSocialLoss: BN;
|
|
799
799
|
cumulativePerpFunding: BN;
|
|
800
800
|
liquidationMarginFreed: BN;
|
|
801
|
-
|
|
801
|
+
lastActiveSlot: BN;
|
|
802
802
|
isMarginTradingEnabled: boolean;
|
|
803
|
+
inactive: boolean;
|
|
803
804
|
};
|
|
804
805
|
|
|
805
806
|
export type SpotPosition = {
|
package/src/user.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
isOneOfVariant,
|
|
13
13
|
PerpMarketAccount,
|
|
14
14
|
} from './types';
|
|
15
|
-
import { calculateEntryPrice } from './math/position';
|
|
15
|
+
import { calculateEntryPrice, positionIsAvailable } from './math/position';
|
|
16
16
|
import {
|
|
17
17
|
PRICE_PRECISION,
|
|
18
18
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
@@ -2171,6 +2171,46 @@ export class User {
|
|
|
2171
2171
|
};
|
|
2172
2172
|
}
|
|
2173
2173
|
|
|
2174
|
+
public canMakeIdle(slot: BN, slotsBeforeIdle: BN): boolean {
|
|
2175
|
+
const userAccount = this.getUserAccount();
|
|
2176
|
+
if (userAccount.inactive) {
|
|
2177
|
+
return false;
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
const userLastActiveSlot = userAccount.lastActiveSlot;
|
|
2181
|
+
if (userLastActiveSlot.lt(slotsBeforeIdle)) {
|
|
2182
|
+
return false;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
if (this.isBeingLiquidated()) {
|
|
2186
|
+
return false;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
for (const perpPosition of userAccount.perpPositions) {
|
|
2190
|
+
if (!positionIsAvailable(perpPosition)) {
|
|
2191
|
+
return false;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
2196
|
+
if (isVariant(spotPosition.balanceType, 'borrow')) {
|
|
2197
|
+
return false;
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
if (spotPosition.openOrders !== 0) {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
for (const order of userAccount.orders) {
|
|
2206
|
+
if (!isVariant(order.status, 'init')) {
|
|
2207
|
+
return false;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
return true;
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2174
2214
|
/**
|
|
2175
2215
|
* Get the total position value, excluding any position coming from the given target market
|
|
2176
2216
|
* @param marketToIgnore
|
package/src/userMap/userMap.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
NewUserRecord,
|
|
15
15
|
LPRecord,
|
|
16
16
|
} from '..';
|
|
17
|
-
import { ProgramAccount } from '@project-serum/anchor';
|
|
18
17
|
|
|
19
18
|
import { PublicKey } from '@solana/web3.js';
|
|
20
19
|
|
|
@@ -42,12 +41,13 @@ export class UserMap implements UserMapInterface {
|
|
|
42
41
|
this.accountSubscription = accountSubscription;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
public async fetchAllUsers() {
|
|
44
|
+
public async fetchAllUsers(includeIdle = true) {
|
|
46
45
|
const userArray: User[] = [];
|
|
47
46
|
const userAccountArray: UserAccount[] = [];
|
|
48
47
|
|
|
49
|
-
const programUserAccounts =
|
|
50
|
-
|
|
48
|
+
const programUserAccounts = await this.driftClient.fetchAllUserAccounts(
|
|
49
|
+
includeIdle
|
|
50
|
+
);
|
|
51
51
|
for (const programUserAccount of programUserAccounts) {
|
|
52
52
|
if (this.userMap.has(programUserAccount.publicKey.toString())) {
|
|
53
53
|
continue;
|
package/src/assert/assert.js
DELETED
package/src/token/index.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseTokenAccount = void 0;
|
|
4
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
function parseTokenAccount(data) {
|
|
7
|
-
const accountInfo = spl_token_1.AccountLayout.decode(data);
|
|
8
|
-
accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
|
|
9
|
-
accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
|
|
10
|
-
accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
|
|
11
|
-
if (accountInfo.delegateOption === 0) {
|
|
12
|
-
accountInfo.delegate = null;
|
|
13
|
-
// eslint-disable-next-line new-cap
|
|
14
|
-
accountInfo.delegatedAmount = new spl_token_1.u64(0);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
|
|
18
|
-
accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
|
|
19
|
-
}
|
|
20
|
-
accountInfo.isInitialized = accountInfo.state !== 0;
|
|
21
|
-
accountInfo.isFrozen = accountInfo.state === 2;
|
|
22
|
-
if (accountInfo.isNativeOption === 1) {
|
|
23
|
-
accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
|
|
24
|
-
accountInfo.isNative = true;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
accountInfo.rentExemptReserve = null;
|
|
28
|
-
accountInfo.isNative = false;
|
|
29
|
-
}
|
|
30
|
-
if (accountInfo.closeAuthorityOption === 0) {
|
|
31
|
-
accountInfo.closeAuthority = null;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
|
|
35
|
-
}
|
|
36
|
-
return accountInfo;
|
|
37
|
-
}
|
|
38
|
-
exports.parseTokenAccount = parseTokenAccount;
|
package/src/util/computeUnits.js
DELETED
|
@@ -1,27 +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.findComputeUnitConsumption = void 0;
|
|
13
|
-
function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
|
|
14
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const tx = yield connection.getTransaction(txSignature, { commitment });
|
|
16
|
-
const computeUnits = [];
|
|
17
|
-
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
|
|
18
|
-
tx.meta.logMessages.forEach((logMessage) => {
|
|
19
|
-
const match = logMessage.match(regex);
|
|
20
|
-
if (match && match[1]) {
|
|
21
|
-
computeUnits.push(match[1]);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return computeUnits;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
exports.findComputeUnitConsumption = findComputeUnitConsumption;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTokenAddress = void 0;
|
|
4
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
7
|
-
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
8
|
-
};
|
|
9
|
-
exports.getTokenAddress = getTokenAddress;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promiseTimeout = void 0;
|
|
4
|
-
function promiseTimeout(promise, timeoutMs) {
|
|
5
|
-
let timeoutId;
|
|
6
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
7
|
-
timeoutId = setTimeout(() => resolve(null), timeoutMs);
|
|
8
|
-
});
|
|
9
|
-
return Promise.race([promise, timeoutPromise]).then((result) => {
|
|
10
|
-
clearTimeout(timeoutId);
|
|
11
|
-
return result;
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
exports.promiseTimeout = promiseTimeout;
|
package/src/util/tps.js
DELETED
|
@@ -1,27 +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.estimateTps = void 0;
|
|
13
|
-
function estimateTps(programId, connection, failed) {
|
|
14
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
let signatures = yield connection.getSignaturesForAddress(programId, undefined, 'finalized');
|
|
16
|
-
if (failed) {
|
|
17
|
-
signatures = signatures.filter((signature) => signature.err);
|
|
18
|
-
}
|
|
19
|
-
const numberOfSignatures = signatures.length;
|
|
20
|
-
if (numberOfSignatures === 0) {
|
|
21
|
-
return 0;
|
|
22
|
-
}
|
|
23
|
-
return (numberOfSignatures /
|
|
24
|
-
(signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
exports.estimateTps = estimateTps;
|