@drift-labs/sdk 2.21.0-beta.0 → 2.21.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +2 -1
- package/lib/accounts/pollingUserAccountSubscriber.js +21 -6
- package/lib/driftClient.d.ts +3 -2
- package/lib/driftClient.js +17 -4
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/idl/drift.json +58 -1
- package/lib/tx/retryTxSender.js +2 -2
- package/lib/types.d.ts +1 -1
- package/lib/user.js +2 -2
- package/lib/userConfig.d.ts +1 -0
- package/package.json +1 -1
- package/src/accounts/pollingUserAccountSubscriber.ts +35 -6
- package/src/assert/assert.js +9 -0
- package/src/driftClient.ts +19 -4
- package/src/driftClientConfig.ts +1 -0
- package/src/idl/drift.json +58 -1
- package/src/token/index.js +38 -0
- package/src/tx/retryTxSender.ts +3 -2
- package/src/types.ts +1 -1
- package/src/user.ts +3 -2
- package/src/userConfig.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
|
@@ -14,8 +14,9 @@ export declare class PollingUserAccountSubscriber implements UserAccountSubscrib
|
|
|
14
14
|
accountLoader: BulkAccountLoader;
|
|
15
15
|
accountsToPoll: Map<string, AccountToPoll>;
|
|
16
16
|
errorCallbackId?: string;
|
|
17
|
+
lazyDecode: boolean;
|
|
17
18
|
user?: DataAndSlot<UserAccount>;
|
|
18
|
-
constructor(program: Program, userAccountPublicKey: PublicKey, accountLoader: BulkAccountLoader);
|
|
19
|
+
constructor(program: Program, userAccountPublicKey: PublicKey, accountLoader: BulkAccountLoader, lazyDecode?: boolean);
|
|
19
20
|
subscribe(): Promise<boolean>;
|
|
20
21
|
addToAccountLoader(): Promise<void>;
|
|
21
22
|
fetchIfUnloaded(): Promise<void>;
|
|
@@ -5,13 +5,14 @@ const types_1 = require("./types");
|
|
|
5
5
|
const events_1 = require("events");
|
|
6
6
|
const utils_1 = require("./utils");
|
|
7
7
|
class PollingUserAccountSubscriber {
|
|
8
|
-
constructor(program, userAccountPublicKey, accountLoader) {
|
|
8
|
+
constructor(program, userAccountPublicKey, accountLoader, lazyDecode = false) {
|
|
9
9
|
this.accountsToPoll = new Map();
|
|
10
10
|
this.isSubscribed = false;
|
|
11
11
|
this.program = program;
|
|
12
12
|
this.accountLoader = accountLoader;
|
|
13
13
|
this.eventEmitter = new events_1.EventEmitter();
|
|
14
14
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
15
|
+
this.lazyDecode = lazyDecode;
|
|
15
16
|
}
|
|
16
17
|
async subscribe() {
|
|
17
18
|
if (this.isSubscribed) {
|
|
@@ -40,7 +41,9 @@ class PollingUserAccountSubscriber {
|
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
|
|
43
|
-
this
|
|
44
|
+
if (!this.lazyDecode) {
|
|
45
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
46
|
+
}
|
|
44
47
|
// @ts-ignore
|
|
45
48
|
this.eventEmitter.emit(accountToPoll.eventType, account);
|
|
46
49
|
this.eventEmitter.emit('update');
|
|
@@ -53,7 +56,12 @@ class PollingUserAccountSubscriber {
|
|
|
53
56
|
async fetchIfUnloaded() {
|
|
54
57
|
let shouldFetch = false;
|
|
55
58
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
56
|
-
if (this[accountToPoll.key] === undefined) {
|
|
59
|
+
if (!this.lazyDecode && this[accountToPoll.key] === undefined) {
|
|
60
|
+
shouldFetch = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
else if (this.lazyDecode &&
|
|
64
|
+
this.accountLoader.bufferAndSlotMap.has(accountToPoll.publicKey.toString())) {
|
|
57
65
|
shouldFetch = true;
|
|
58
66
|
break;
|
|
59
67
|
}
|
|
@@ -66,7 +74,7 @@ class PollingUserAccountSubscriber {
|
|
|
66
74
|
await this.accountLoader.load();
|
|
67
75
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
68
76
|
const { buffer, slot } = this.accountLoader.getBufferAndSlot(accountToPoll.publicKey);
|
|
69
|
-
if (buffer) {
|
|
77
|
+
if (buffer && !this.lazyDecode) {
|
|
70
78
|
const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
|
|
71
79
|
this[accountToPoll.key] = { data: account, slot };
|
|
72
80
|
}
|
|
@@ -75,7 +83,7 @@ class PollingUserAccountSubscriber {
|
|
|
75
83
|
doAccountsExist() {
|
|
76
84
|
let success = true;
|
|
77
85
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
78
|
-
if (!this
|
|
86
|
+
if (!this.accountLoader.bufferAndSlotMap.has(accountToPoll.publicKey.toString())) {
|
|
79
87
|
success = false;
|
|
80
88
|
break;
|
|
81
89
|
}
|
|
@@ -101,7 +109,14 @@ class PollingUserAccountSubscriber {
|
|
|
101
109
|
}
|
|
102
110
|
getUserAccountAndSlot() {
|
|
103
111
|
this.assertIsSubscribed();
|
|
104
|
-
|
|
112
|
+
if (!this.lazyDecode) {
|
|
113
|
+
return this.user;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const { buffer, slot } = this.accountLoader.getBufferAndSlot(this.userAccountPublicKey);
|
|
117
|
+
const account = this.program.account.user.coder.accounts.decode('User', buffer);
|
|
118
|
+
return { data: account, slot };
|
|
119
|
+
}
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
exports.PollingUserAccountSubscriber = PollingUserAccountSubscriber;
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -191,6 +191,7 @@ export declare class DriftClient {
|
|
|
191
191
|
getCancelOrdersIx(marketType: MarketType | null, marketIndex: number | null, direction: PositionDirection | null): Promise<TransactionInstruction>;
|
|
192
192
|
fillPerpOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
193
193
|
getFillPerpOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
194
|
+
getRevertFillIx(): Promise<TransactionInstruction>;
|
|
194
195
|
placeSpotOrder(orderParams: OptionalOrderParams, txParams?: TxParams): Promise<TransactionSignature>;
|
|
195
196
|
getPlaceSpotOrderIx(orderParams: OptionalOrderParams): Promise<TransactionInstruction>;
|
|
196
197
|
fillSpotOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
@@ -201,8 +202,8 @@ export declare class DriftClient {
|
|
|
201
202
|
getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
|
|
202
203
|
forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
203
204
|
getForceCancelOrdersIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
updateUserIdle(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
206
|
+
getUpdateUserIdleIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
206
207
|
placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
207
208
|
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
208
209
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
package/lib/driftClient.js
CHANGED
|
@@ -79,6 +79,7 @@ class DriftClient {
|
|
|
79
79
|
? {
|
|
80
80
|
type: 'polling',
|
|
81
81
|
accountLoader: config.accountSubscription.accountLoader,
|
|
82
|
+
lazyDecode: config.accountSubscription.lazyDecode,
|
|
82
83
|
}
|
|
83
84
|
: {
|
|
84
85
|
type: 'websocket',
|
|
@@ -1357,6 +1358,18 @@ class DriftClient {
|
|
|
1357
1358
|
remainingAccounts,
|
|
1358
1359
|
});
|
|
1359
1360
|
}
|
|
1361
|
+
async getRevertFillIx() {
|
|
1362
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1363
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1364
|
+
return this.program.instruction.revertFill({
|
|
1365
|
+
accounts: {
|
|
1366
|
+
state: await this.getStatePublicKey(),
|
|
1367
|
+
filler: fillerPublicKey,
|
|
1368
|
+
fillerStats: fillerStatsPublicKey,
|
|
1369
|
+
authority: this.wallet.publicKey,
|
|
1370
|
+
},
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1360
1373
|
async placeSpotOrder(orderParams, txParams) {
|
|
1361
1374
|
const { txSig, slot } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1362
1375
|
this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
@@ -1592,16 +1605,16 @@ class DriftClient {
|
|
|
1592
1605
|
remainingAccounts,
|
|
1593
1606
|
});
|
|
1594
1607
|
}
|
|
1595
|
-
async
|
|
1596
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
1608
|
+
async updateUserIdle(userAccountPublicKey, user, txParams) {
|
|
1609
|
+
const { txSig } = await this.txSender.send((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);
|
|
1597
1610
|
return txSig;
|
|
1598
1611
|
}
|
|
1599
|
-
async
|
|
1612
|
+
async getUpdateUserIdleIx(userAccountPublicKey, userAccount) {
|
|
1600
1613
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1601
1614
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1602
1615
|
userAccounts: [userAccount],
|
|
1603
1616
|
});
|
|
1604
|
-
return await this.program.instruction.
|
|
1617
|
+
return await this.program.instruction.updateUserIdle({
|
|
1605
1618
|
accounts: {
|
|
1606
1619
|
state: await this.getStatePublicKey(),
|
|
1607
1620
|
filler: fillerPublicKey,
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.21.0-beta.
|
|
2
|
+
"version": "2.21.0-beta.1",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -909,6 +909,32 @@
|
|
|
909
909
|
}
|
|
910
910
|
]
|
|
911
911
|
},
|
|
912
|
+
{
|
|
913
|
+
"name": "revertFill",
|
|
914
|
+
"accounts": [
|
|
915
|
+
{
|
|
916
|
+
"name": "state",
|
|
917
|
+
"isMut": false,
|
|
918
|
+
"isSigner": false
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"name": "authority",
|
|
922
|
+
"isMut": false,
|
|
923
|
+
"isSigner": true
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"name": "filler",
|
|
927
|
+
"isMut": true,
|
|
928
|
+
"isSigner": false
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "fillerStats",
|
|
932
|
+
"isMut": true,
|
|
933
|
+
"isSigner": false
|
|
934
|
+
}
|
|
935
|
+
],
|
|
936
|
+
"args": []
|
|
937
|
+
},
|
|
912
938
|
{
|
|
913
939
|
"name": "fillSpotOrder",
|
|
914
940
|
"accounts": [
|
|
@@ -1023,6 +1049,32 @@
|
|
|
1023
1049
|
],
|
|
1024
1050
|
"args": []
|
|
1025
1051
|
},
|
|
1052
|
+
{
|
|
1053
|
+
"name": "updateUserIdle",
|
|
1054
|
+
"accounts": [
|
|
1055
|
+
{
|
|
1056
|
+
"name": "state",
|
|
1057
|
+
"isMut": false,
|
|
1058
|
+
"isSigner": false
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"name": "authority",
|
|
1062
|
+
"isMut": false,
|
|
1063
|
+
"isSigner": true
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"name": "filler",
|
|
1067
|
+
"isMut": true,
|
|
1068
|
+
"isSigner": false
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"name": "user",
|
|
1072
|
+
"isMut": true,
|
|
1073
|
+
"isSigner": false
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"args": []
|
|
1077
|
+
},
|
|
1026
1078
|
{
|
|
1027
1079
|
"name": "settlePnl",
|
|
1028
1080
|
"accounts": [
|
|
@@ -8742,6 +8794,11 @@
|
|
|
8742
8794
|
"code": 6238,
|
|
8743
8795
|
"name": "UserNotInactive",
|
|
8744
8796
|
"msg": "User Not Inactive"
|
|
8797
|
+
},
|
|
8798
|
+
{
|
|
8799
|
+
"code": 6239,
|
|
8800
|
+
"name": "RevertFill",
|
|
8801
|
+
"msg": "RevertFill"
|
|
8745
8802
|
}
|
|
8746
8803
|
]
|
|
8747
8804
|
}
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -31,12 +31,12 @@ class RetryTxSender {
|
|
|
31
31
|
async prepareTx(tx, additionalSigners, opts) {
|
|
32
32
|
tx.feePayer = this.provider.wallet.publicKey;
|
|
33
33
|
tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
|
|
34
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
35
34
|
additionalSigners
|
|
36
35
|
.filter((s) => s !== undefined)
|
|
37
36
|
.forEach((kp) => {
|
|
38
|
-
|
|
37
|
+
tx.partialSign(kp);
|
|
39
38
|
});
|
|
39
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
40
40
|
return signedTx;
|
|
41
41
|
}
|
|
42
42
|
async sendVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
|
package/lib/types.d.ts
CHANGED
package/lib/user.js
CHANGED
|
@@ -25,7 +25,7 @@ class User {
|
|
|
25
25
|
this.driftClient = config.driftClient;
|
|
26
26
|
this.userAccountPublicKey = config.userAccountPublicKey;
|
|
27
27
|
if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) === 'polling') {
|
|
28
|
-
this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, config.accountSubscription.accountLoader);
|
|
28
|
+
this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, config.accountSubscription.accountLoader, config.accountSubscription.lazyDecode);
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
31
|
this.accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey);
|
|
@@ -1214,7 +1214,7 @@ class User {
|
|
|
1214
1214
|
}
|
|
1215
1215
|
canMakeIdle(slot, slotsBeforeIdle) {
|
|
1216
1216
|
const userAccount = this.getUserAccount();
|
|
1217
|
-
if (userAccount.
|
|
1217
|
+
if (userAccount.idle) {
|
|
1218
1218
|
return false;
|
|
1219
1219
|
}
|
|
1220
1220
|
const userLastActiveSlot = userAccount.lastActiveSlot;
|
package/lib/userConfig.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -23,18 +23,22 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
23
23
|
accountsToPoll = new Map<string, AccountToPoll>();
|
|
24
24
|
errorCallbackId?: string;
|
|
25
25
|
|
|
26
|
+
lazyDecode: boolean;
|
|
27
|
+
|
|
26
28
|
user?: DataAndSlot<UserAccount>;
|
|
27
29
|
|
|
28
30
|
public constructor(
|
|
29
31
|
program: Program,
|
|
30
32
|
userAccountPublicKey: PublicKey,
|
|
31
|
-
accountLoader: BulkAccountLoader
|
|
33
|
+
accountLoader: BulkAccountLoader,
|
|
34
|
+
lazyDecode = false
|
|
32
35
|
) {
|
|
33
36
|
this.isSubscribed = false;
|
|
34
37
|
this.program = program;
|
|
35
38
|
this.accountLoader = accountLoader;
|
|
36
39
|
this.eventEmitter = new EventEmitter();
|
|
37
40
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
41
|
+
this.lazyDecode = lazyDecode;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
async subscribe(): Promise<boolean> {
|
|
@@ -75,7 +79,9 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
75
79
|
const account = this.program.account[
|
|
76
80
|
accountToPoll.key
|
|
77
81
|
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
78
|
-
this
|
|
82
|
+
if (!this.lazyDecode) {
|
|
83
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
84
|
+
}
|
|
79
85
|
// @ts-ignore
|
|
80
86
|
this.eventEmitter.emit(accountToPoll.eventType, account);
|
|
81
87
|
this.eventEmitter.emit('update');
|
|
@@ -91,7 +97,15 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
91
97
|
async fetchIfUnloaded(): Promise<void> {
|
|
92
98
|
let shouldFetch = false;
|
|
93
99
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
94
|
-
if (this[accountToPoll.key] === undefined) {
|
|
100
|
+
if (!this.lazyDecode && this[accountToPoll.key] === undefined) {
|
|
101
|
+
shouldFetch = true;
|
|
102
|
+
break;
|
|
103
|
+
} else if (
|
|
104
|
+
this.lazyDecode &&
|
|
105
|
+
this.accountLoader.bufferAndSlotMap.has(
|
|
106
|
+
accountToPoll.publicKey.toString()
|
|
107
|
+
)
|
|
108
|
+
) {
|
|
95
109
|
shouldFetch = true;
|
|
96
110
|
break;
|
|
97
111
|
}
|
|
@@ -108,7 +122,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
108
122
|
const { buffer, slot } = this.accountLoader.getBufferAndSlot(
|
|
109
123
|
accountToPoll.publicKey
|
|
110
124
|
);
|
|
111
|
-
if (buffer) {
|
|
125
|
+
if (buffer && !this.lazyDecode) {
|
|
112
126
|
const account = this.program.account[
|
|
113
127
|
accountToPoll.key
|
|
114
128
|
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
@@ -120,7 +134,11 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
120
134
|
doAccountsExist(): boolean {
|
|
121
135
|
let success = true;
|
|
122
136
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
123
|
-
if (
|
|
137
|
+
if (
|
|
138
|
+
!this.accountLoader.bufferAndSlotMap.has(
|
|
139
|
+
accountToPoll.publicKey.toString()
|
|
140
|
+
)
|
|
141
|
+
) {
|
|
124
142
|
success = false;
|
|
125
143
|
break;
|
|
126
144
|
}
|
|
@@ -158,6 +176,17 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
158
176
|
|
|
159
177
|
public getUserAccountAndSlot(): DataAndSlot<UserAccount> {
|
|
160
178
|
this.assertIsSubscribed();
|
|
161
|
-
|
|
179
|
+
if (!this.lazyDecode) {
|
|
180
|
+
return this.user;
|
|
181
|
+
} else {
|
|
182
|
+
const { buffer, slot } = this.accountLoader.getBufferAndSlot(
|
|
183
|
+
this.userAccountPublicKey
|
|
184
|
+
);
|
|
185
|
+
const account = this.program.account.user.coder.accounts.decode(
|
|
186
|
+
'User',
|
|
187
|
+
buffer
|
|
188
|
+
);
|
|
189
|
+
return { data: account, slot };
|
|
190
|
+
}
|
|
162
191
|
}
|
|
163
192
|
}
|
package/src/driftClient.ts
CHANGED
|
@@ -160,6 +160,7 @@ export class DriftClient {
|
|
|
160
160
|
? {
|
|
161
161
|
type: 'polling',
|
|
162
162
|
accountLoader: config.accountSubscription.accountLoader,
|
|
163
|
+
lazyDecode: config.accountSubscription.lazyDecode,
|
|
163
164
|
}
|
|
164
165
|
: {
|
|
165
166
|
type: 'websocket',
|
|
@@ -2394,6 +2395,20 @@ export class DriftClient {
|
|
|
2394
2395
|
});
|
|
2395
2396
|
}
|
|
2396
2397
|
|
|
2398
|
+
public async getRevertFillIx(): Promise<TransactionInstruction> {
|
|
2399
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2400
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2401
|
+
|
|
2402
|
+
return this.program.instruction.revertFill({
|
|
2403
|
+
accounts: {
|
|
2404
|
+
state: await this.getStatePublicKey(),
|
|
2405
|
+
filler: fillerPublicKey,
|
|
2406
|
+
fillerStats: fillerStatsPublicKey,
|
|
2407
|
+
authority: this.wallet.publicKey,
|
|
2408
|
+
},
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2397
2412
|
public async placeSpotOrder(
|
|
2398
2413
|
orderParams: OptionalOrderParams,
|
|
2399
2414
|
txParams?: TxParams
|
|
@@ -2759,14 +2774,14 @@ export class DriftClient {
|
|
|
2759
2774
|
});
|
|
2760
2775
|
}
|
|
2761
2776
|
|
|
2762
|
-
public async
|
|
2777
|
+
public async updateUserIdle(
|
|
2763
2778
|
userAccountPublicKey: PublicKey,
|
|
2764
2779
|
user: UserAccount,
|
|
2765
2780
|
txParams?: TxParams
|
|
2766
2781
|
): Promise<TransactionSignature> {
|
|
2767
2782
|
const { txSig } = await this.txSender.send(
|
|
2768
2783
|
wrapInTx(
|
|
2769
|
-
await this.
|
|
2784
|
+
await this.getUpdateUserIdleIx(userAccountPublicKey, user),
|
|
2770
2785
|
txParams?.computeUnits,
|
|
2771
2786
|
txParams?.computeUnitsPrice
|
|
2772
2787
|
),
|
|
@@ -2776,7 +2791,7 @@ export class DriftClient {
|
|
|
2776
2791
|
return txSig;
|
|
2777
2792
|
}
|
|
2778
2793
|
|
|
2779
|
-
public async
|
|
2794
|
+
public async getUpdateUserIdleIx(
|
|
2780
2795
|
userAccountPublicKey: PublicKey,
|
|
2781
2796
|
userAccount: UserAccount
|
|
2782
2797
|
): Promise<TransactionInstruction> {
|
|
@@ -2786,7 +2801,7 @@ export class DriftClient {
|
|
|
2786
2801
|
userAccounts: [userAccount],
|
|
2787
2802
|
});
|
|
2788
2803
|
|
|
2789
|
-
return await this.program.instruction.
|
|
2804
|
+
return await this.program.instruction.updateUserIdle({
|
|
2790
2805
|
accounts: {
|
|
2791
2806
|
state: await this.getStatePublicKey(),
|
|
2792
2807
|
filler: fillerPublicKey,
|
package/src/driftClientConfig.ts
CHANGED
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.21.0-beta.
|
|
2
|
+
"version": "2.21.0-beta.1",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -909,6 +909,32 @@
|
|
|
909
909
|
}
|
|
910
910
|
]
|
|
911
911
|
},
|
|
912
|
+
{
|
|
913
|
+
"name": "revertFill",
|
|
914
|
+
"accounts": [
|
|
915
|
+
{
|
|
916
|
+
"name": "state",
|
|
917
|
+
"isMut": false,
|
|
918
|
+
"isSigner": false
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"name": "authority",
|
|
922
|
+
"isMut": false,
|
|
923
|
+
"isSigner": true
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"name": "filler",
|
|
927
|
+
"isMut": true,
|
|
928
|
+
"isSigner": false
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "fillerStats",
|
|
932
|
+
"isMut": true,
|
|
933
|
+
"isSigner": false
|
|
934
|
+
}
|
|
935
|
+
],
|
|
936
|
+
"args": []
|
|
937
|
+
},
|
|
912
938
|
{
|
|
913
939
|
"name": "fillSpotOrder",
|
|
914
940
|
"accounts": [
|
|
@@ -1023,6 +1049,32 @@
|
|
|
1023
1049
|
],
|
|
1024
1050
|
"args": []
|
|
1025
1051
|
},
|
|
1052
|
+
{
|
|
1053
|
+
"name": "updateUserIdle",
|
|
1054
|
+
"accounts": [
|
|
1055
|
+
{
|
|
1056
|
+
"name": "state",
|
|
1057
|
+
"isMut": false,
|
|
1058
|
+
"isSigner": false
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"name": "authority",
|
|
1062
|
+
"isMut": false,
|
|
1063
|
+
"isSigner": true
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"name": "filler",
|
|
1067
|
+
"isMut": true,
|
|
1068
|
+
"isSigner": false
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"name": "user",
|
|
1072
|
+
"isMut": true,
|
|
1073
|
+
"isSigner": false
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"args": []
|
|
1077
|
+
},
|
|
1026
1078
|
{
|
|
1027
1079
|
"name": "settlePnl",
|
|
1028
1080
|
"accounts": [
|
|
@@ -8742,6 +8794,11 @@
|
|
|
8742
8794
|
"code": 6238,
|
|
8743
8795
|
"name": "UserNotInactive",
|
|
8744
8796
|
"msg": "User Not Inactive"
|
|
8797
|
+
},
|
|
8798
|
+
{
|
|
8799
|
+
"code": 6239,
|
|
8800
|
+
"name": "RevertFill",
|
|
8801
|
+
"msg": "RevertFill"
|
|
8745
8802
|
}
|
|
8746
8803
|
]
|
|
8747
8804
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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/tx/retryTxSender.ts
CHANGED
|
@@ -75,13 +75,14 @@ export class RetryTxSender implements TxSender {
|
|
|
75
75
|
)
|
|
76
76
|
).blockhash;
|
|
77
77
|
|
|
78
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
79
78
|
additionalSigners
|
|
80
79
|
.filter((s): s is Signer => s !== undefined)
|
|
81
80
|
.forEach((kp) => {
|
|
82
|
-
|
|
81
|
+
tx.partialSign(kp);
|
|
83
82
|
});
|
|
84
83
|
|
|
84
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
85
|
+
|
|
85
86
|
return signedTx;
|
|
86
87
|
}
|
|
87
88
|
|
package/src/types.ts
CHANGED
package/src/user.ts
CHANGED
|
@@ -95,7 +95,8 @@ export class User {
|
|
|
95
95
|
this.accountSubscriber = new PollingUserAccountSubscriber(
|
|
96
96
|
config.driftClient.program,
|
|
97
97
|
config.userAccountPublicKey,
|
|
98
|
-
config.accountSubscription.accountLoader
|
|
98
|
+
config.accountSubscription.accountLoader,
|
|
99
|
+
config.accountSubscription.lazyDecode
|
|
99
100
|
);
|
|
100
101
|
} else {
|
|
101
102
|
this.accountSubscriber = new WebSocketUserAccountSubscriber(
|
|
@@ -2173,7 +2174,7 @@ export class User {
|
|
|
2173
2174
|
|
|
2174
2175
|
public canMakeIdle(slot: BN, slotsBeforeIdle: BN): boolean {
|
|
2175
2176
|
const userAccount = this.getUserAccount();
|
|
2176
|
-
if (userAccount.
|
|
2177
|
+
if (userAccount.idle) {
|
|
2177
2178
|
return false;
|
|
2178
2179
|
}
|
|
2179
2180
|
|
package/src/userConfig.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
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;
|
|
@@ -0,0 +1,9 @@
|
|
|
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;
|
|
@@ -0,0 +1,14 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
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;
|