@drift-labs/sdk 2.85.0-beta.1 → 2.85.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/bun.lockb +0 -0
- package/lib/accounts/bulkAccountLoader.d.ts +3 -3
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +10 -2
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +4 -3
- package/lib/accounts/pollingUserAccountSubscriber.js +7 -6
- package/lib/accounts/testBulkAccountLoader.d.ts +4 -0
- package/lib/accounts/testBulkAccountLoader.js +45 -0
- package/lib/bankrun/bankrunConnection.d.ts +71 -0
- package/lib/bankrun/bankrunConnection.js +285 -0
- package/lib/blockhashSubscriber/BlockhashSubscriber.js +22 -15
- package/lib/constants/perpMarkets.js +10 -0
- package/lib/constants/spotMarkets.js +10 -0
- package/lib/driftClient.d.ts +3 -1
- package/lib/driftClient.js +45 -32
- package/lib/driftClientConfig.d.ts +2 -1
- package/lib/events/eventSubscriber.js +12 -4
- package/lib/idl/drift.json +28 -8
- package/lib/testClient.js +1 -2
- package/lib/tokenFaucet.d.ts +3 -1
- package/lib/tokenFaucet.js +41 -8
- package/lib/tx/blockhashFetcher/baseBlockhashFetcher.d.ts +8 -0
- package/lib/tx/blockhashFetcher/baseBlockhashFetcher.js +13 -0
- package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.d.ts +28 -0
- package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.js +73 -0
- package/lib/tx/blockhashFetcher/types.d.ts +4 -0
- package/lib/tx/blockhashFetcher/types.js +2 -0
- package/lib/tx/txHandler.d.ts +10 -0
- package/lib/tx/txHandler.js +16 -7
- package/lib/tx/txParamProcessor.d.ts +2 -1
- package/lib/tx/txParamProcessor.js +7 -3
- package/lib/tx/utils.d.ts +2 -0
- package/lib/tx/utils.js +10 -0
- package/lib/types.d.ts +1 -0
- package/lib/user.js +1 -1
- package/package.json +4 -1
- package/src/accounts/bulkAccountLoader.ts +3 -2
- package/src/accounts/pollingDriftClientAccountSubscriber.ts +16 -3
- package/src/accounts/pollingUserAccountSubscriber.ts +13 -12
- package/src/accounts/testBulkAccountLoader.ts +53 -0
- package/src/bankrun/bankrunConnection.ts +466 -0
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +24 -19
- package/src/constants/perpMarkets.ts +10 -0
- package/src/constants/spotMarkets.ts +10 -0
- package/src/driftClient.ts +91 -42
- package/src/driftClientConfig.ts +2 -1
- package/src/events/eventSubscriber.ts +5 -0
- package/src/idl/drift.json +28 -8
- package/src/testClient.ts +1 -2
- package/src/tokenFaucet.ts +49 -12
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +19 -0
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +90 -0
- package/src/tx/blockhashFetcher/types.ts +5 -0
- package/src/tx/txHandler.ts +38 -4
- package/src/tx/txParamProcessor.ts +11 -2
- package/src/tx/utils.ts +11 -0
- package/src/types.ts +1 -0
- package/src/user.ts +5 -2
- package/tests/tx/cachedBlockhashFetcher.test.ts +96 -0
|
@@ -8,7 +8,8 @@ type TransactionBuildingProps = {
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class TransactionParamProcessor {
|
|
10
10
|
private static getComputeUnitsFromSim;
|
|
11
|
-
static getTxSimComputeUnits(tx: VersionedTransaction, connection: Connection, bufferMultiplier: number
|
|
11
|
+
static getTxSimComputeUnits(tx: VersionedTransaction, connection: Connection, bufferMultiplier: number, // Making this a mandatory param to force the user to remember that simulated CU's can be inaccurate and a buffer should be applied
|
|
12
|
+
lowerBoundCu?: number): Promise<{
|
|
12
13
|
success: boolean;
|
|
13
14
|
computeUnits: number;
|
|
14
15
|
}>;
|
|
@@ -15,8 +15,8 @@ class TransactionParamProcessor {
|
|
|
15
15
|
}
|
|
16
16
|
return undefined;
|
|
17
17
|
}
|
|
18
|
-
static async getTxSimComputeUnits(tx, connection, bufferMultiplier // Making this a mandatory param to force the user to remember that simulated CU's can be inaccurate and a buffer should be applied
|
|
19
|
-
) {
|
|
18
|
+
static async getTxSimComputeUnits(tx, connection, bufferMultiplier, // Making this a mandatory param to force the user to remember that simulated CU's can be inaccurate and a buffer should be applied
|
|
19
|
+
lowerBoundCu) {
|
|
20
20
|
var _a, _b, _c;
|
|
21
21
|
try {
|
|
22
22
|
if (TEST_SIMS_ALWAYS_FAIL)
|
|
@@ -29,7 +29,11 @@ class TransactionParamProcessor {
|
|
|
29
29
|
}
|
|
30
30
|
const computeUnits = await this.getComputeUnitsFromSim(simTxResult);
|
|
31
31
|
// Apply the buffer, but round down to the MAX_COMPUTE_UNITS, and round up to the nearest whole number
|
|
32
|
-
|
|
32
|
+
let bufferedComputeUnits = Math.ceil(Math.min(computeUnits * bufferMultiplier, MAX_COMPUTE_UNITS));
|
|
33
|
+
// If a lower bound CU is passed then enforce it
|
|
34
|
+
if (lowerBoundCu) {
|
|
35
|
+
bufferedComputeUnits = Math.max(bufferedComputeUnits, Math.min(lowerBoundCu, MAX_COMPUTE_UNITS));
|
|
36
|
+
}
|
|
33
37
|
return {
|
|
34
38
|
success: true,
|
|
35
39
|
computeUnits: bufferedComputeUnits,
|
package/lib/tx/utils.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isVersionedTransaction = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const isVersionedTransaction = (tx) => {
|
|
6
|
+
const version = tx === null || tx === void 0 ? void 0 : tx.version;
|
|
7
|
+
const isVersionedTx = tx instanceof web3_js_1.VersionedTransaction || version !== undefined;
|
|
8
|
+
return isVersionedTx;
|
|
9
|
+
};
|
|
10
|
+
exports.isVersionedTransaction = isVersionedTransaction;
|
package/lib/types.d.ts
CHANGED
|
@@ -1085,6 +1085,7 @@ export type ProcessingTxParams = {
|
|
|
1085
1085
|
computeUnitsBufferMultiplier?: number;
|
|
1086
1086
|
useSimulatedComputeUnitsForCUPriceCalculation?: boolean;
|
|
1087
1087
|
getCUPriceFromComputeUnits?: (computeUnits: number) => number;
|
|
1088
|
+
lowerBoundCu?: number;
|
|
1088
1089
|
};
|
|
1089
1090
|
export type TxParams = BaseTxParams & ProcessingTxParams;
|
|
1090
1091
|
export declare class SwapReduceOnly {
|
package/lib/user.js
CHANGED
|
@@ -27,7 +27,7 @@ class User {
|
|
|
27
27
|
this.driftClient = config.driftClient;
|
|
28
28
|
this.userAccountPublicKey = config.userAccountPublicKey;
|
|
29
29
|
if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) === 'polling') {
|
|
30
|
-
this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.
|
|
30
|
+
this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.connection, config.userAccountPublicKey, config.accountSubscription.accountLoader, this.driftClient.program.account.user.coder.accounts.decodeUnchecked.bind(this.driftClient.program.account.user.coder.accounts));
|
|
31
31
|
}
|
|
32
32
|
else if (((_b = config.accountSubscription) === null || _b === void 0 ? void 0 : _b.type) === 'custom') {
|
|
33
33
|
this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.85.0-beta.
|
|
3
|
+
"version": "2.85.0-beta.11",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"@pythnetwork/pyth-solana-receiver": "^0.7.0",
|
|
42
42
|
"@solana/spl-token": "0.3.7",
|
|
43
43
|
"@solana/web3.js": "1.92.3",
|
|
44
|
+
"anchor-bankrun": "^0.3.0",
|
|
44
45
|
"rpc-websockets": "7.5.1",
|
|
46
|
+
"solana-bankrun": "^0.3.0",
|
|
45
47
|
"strict-event-emitter-types": "^2.0.0",
|
|
46
48
|
"uuid": "^8.3.2",
|
|
47
49
|
"zstddec": "^0.1.0"
|
|
@@ -63,6 +65,7 @@
|
|
|
63
65
|
"mocha": "^10.0.0",
|
|
64
66
|
"object-sizeof": "^2.6.3",
|
|
65
67
|
"prettier": "3.0.1",
|
|
68
|
+
"sinon": "^18.0.0",
|
|
66
69
|
"ts-node": "^10.8.0",
|
|
67
70
|
"typescript": "^4.9.5"
|
|
68
71
|
},
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Commitment,
|
|
1
|
+
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
3
|
import { BufferAndSlot } from './types';
|
|
4
4
|
import { promiseTimeout } from '../util/promiseTimeout';
|
|
5
|
+
import { Connection } from '../bankrun/bankrunConnection';
|
|
5
6
|
|
|
6
|
-
type AccountToLoad = {
|
|
7
|
+
export type AccountToLoad = {
|
|
7
8
|
publicKey: PublicKey;
|
|
8
9
|
callbacks: Map<string, (buffer: Buffer, slot: number) => void>;
|
|
9
10
|
};
|
|
@@ -288,14 +288,20 @@ export class PollingDriftClientAccountSubscriber
|
|
|
288
288
|
public async fetch(): Promise<void> {
|
|
289
289
|
await this.accountLoader.load();
|
|
290
290
|
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
291
|
-
const
|
|
291
|
+
const bufferAndSlot = this.accountLoader.getBufferAndSlot(
|
|
292
292
|
accountToPoll.publicKey
|
|
293
293
|
);
|
|
294
|
+
|
|
295
|
+
if (!bufferAndSlot) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const { buffer, slot } = bufferAndSlot;
|
|
300
|
+
|
|
294
301
|
if (buffer) {
|
|
295
302
|
const account = this.program.account[
|
|
296
303
|
accountToPoll.key
|
|
297
304
|
].coder.accounts.decodeUnchecked(capitalize(accountToPoll.key), buffer);
|
|
298
|
-
|
|
299
305
|
if (accountToPoll.mapKey != undefined) {
|
|
300
306
|
this[accountToPoll.key].set(accountToPoll.mapKey, {
|
|
301
307
|
data: account,
|
|
@@ -311,9 +317,16 @@ export class PollingDriftClientAccountSubscriber
|
|
|
311
317
|
}
|
|
312
318
|
|
|
313
319
|
for (const [_, oracleToPoll] of this.oraclesToPoll) {
|
|
314
|
-
const
|
|
320
|
+
const bufferAndSlot = this.accountLoader.getBufferAndSlot(
|
|
315
321
|
oracleToPoll.publicKey
|
|
316
322
|
);
|
|
323
|
+
|
|
324
|
+
if (!bufferAndSlot) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const { buffer, slot } = bufferAndSlot;
|
|
329
|
+
|
|
317
330
|
if (buffer) {
|
|
318
331
|
const oracleClient = this.oracleClientCache.get(
|
|
319
332
|
oracleToPoll.source,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
UserAccountEvents,
|
|
5
5
|
UserAccountSubscriber,
|
|
6
6
|
} from './types';
|
|
7
|
-
import {
|
|
7
|
+
import { Connection } from '../bankrun/bankrunConnection';
|
|
8
8
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
9
9
|
import { EventEmitter } from 'events';
|
|
10
10
|
import { PublicKey } from '@solana/web3.js';
|
|
@@ -13,7 +13,7 @@ import { BulkAccountLoader } from './bulkAccountLoader';
|
|
|
13
13
|
|
|
14
14
|
export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
15
15
|
isSubscribed: boolean;
|
|
16
|
-
|
|
16
|
+
connection: Connection;
|
|
17
17
|
eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
|
|
18
18
|
userAccountPublicKey: PublicKey;
|
|
19
19
|
|
|
@@ -21,18 +21,22 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
21
21
|
callbackId?: string;
|
|
22
22
|
errorCallbackId?: string;
|
|
23
23
|
|
|
24
|
+
decode: (name, buffer) => UserAccount;
|
|
25
|
+
|
|
24
26
|
user?: DataAndSlot<UserAccount>;
|
|
25
27
|
|
|
26
28
|
public constructor(
|
|
27
|
-
|
|
29
|
+
connection: Connection,
|
|
28
30
|
userAccountPublicKey: PublicKey,
|
|
29
|
-
accountLoader: BulkAccountLoader
|
|
31
|
+
accountLoader: BulkAccountLoader,
|
|
32
|
+
decode: (name, buffer) => UserAccount
|
|
30
33
|
) {
|
|
31
34
|
this.isSubscribed = false;
|
|
32
|
-
this.
|
|
35
|
+
this.connection = connection;
|
|
33
36
|
this.accountLoader = accountLoader;
|
|
34
37
|
this.eventEmitter = new EventEmitter();
|
|
35
38
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
39
|
+
this.decode = decode;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
async subscribe(userAccount?: UserAccount): Promise<boolean> {
|
|
@@ -71,10 +75,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
71
75
|
return;
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
const account = this.
|
|
75
|
-
'User',
|
|
76
|
-
buffer
|
|
77
|
-
);
|
|
78
|
+
const account = this.decode('User', buffer);
|
|
78
79
|
this.user = { data: account, slot };
|
|
79
80
|
this.eventEmitter.emit('userAccountUpdate', account);
|
|
80
81
|
this.eventEmitter.emit('update');
|
|
@@ -94,19 +95,19 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
94
95
|
|
|
95
96
|
async fetch(): Promise<void> {
|
|
96
97
|
try {
|
|
97
|
-
const dataAndContext = await this.
|
|
98
|
+
const dataAndContext = await this.connection.getAccountInfoAndContext(
|
|
98
99
|
this.userAccountPublicKey,
|
|
99
100
|
this.accountLoader.commitment
|
|
100
101
|
);
|
|
101
102
|
if (dataAndContext.context.slot > (this.user?.slot ?? 0)) {
|
|
102
103
|
this.user = {
|
|
103
|
-
data: dataAndContext.data
|
|
104
|
+
data: this.decode('User', dataAndContext.value.data),
|
|
104
105
|
slot: dataAndContext.context.slot,
|
|
105
106
|
};
|
|
106
107
|
}
|
|
107
108
|
} catch (e) {
|
|
108
109
|
console.log(
|
|
109
|
-
`PollingUserAccountSubscriber.fetch() UserAccount does not exist: ${e.message}`
|
|
110
|
+
`PollingUserAccountSubscriber.fetch() UserAccount does not exist: ${e.message}-${e.stack}`
|
|
110
111
|
);
|
|
111
112
|
}
|
|
112
113
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AccountToLoad, BulkAccountLoader } from './bulkAccountLoader';
|
|
2
|
+
|
|
3
|
+
export class TestBulkAccountLoader extends BulkAccountLoader {
|
|
4
|
+
async loadChunk(accountsToLoadChunks: AccountToLoad[][]): Promise<void> {
|
|
5
|
+
if (accountsToLoadChunks.length === 0) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const accounts = [];
|
|
10
|
+
for (const accountsToLoadChunk of accountsToLoadChunks) {
|
|
11
|
+
for (const accountToLoad of accountsToLoadChunk) {
|
|
12
|
+
const account = await this.connection.getAccountInfoAndContext(
|
|
13
|
+
accountToLoad.publicKey,
|
|
14
|
+
this.commitment
|
|
15
|
+
);
|
|
16
|
+
accounts.push(account);
|
|
17
|
+
const newSlot = account.context.slot;
|
|
18
|
+
if (newSlot > this.mostRecentSlot) {
|
|
19
|
+
this.mostRecentSlot = newSlot;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (accountToLoad.callbacks.size === 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const key = accountToLoad.publicKey.toBase58();
|
|
27
|
+
const prev = this.bufferAndSlotMap.get(key);
|
|
28
|
+
|
|
29
|
+
if (prev && newSlot < prev.slot) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let newBuffer: Buffer | undefined = undefined;
|
|
34
|
+
|
|
35
|
+
if (account.value) {
|
|
36
|
+
newBuffer = account.value.data;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!prev) {
|
|
40
|
+
this.bufferAndSlotMap.set(key, { slot: newSlot, buffer: newBuffer });
|
|
41
|
+
this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const oldBuffer = prev.buffer;
|
|
46
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
47
|
+
this.bufferAndSlotMap.set(key, { slot: newSlot, buffer: newBuffer });
|
|
48
|
+
this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|