@drift-labs/sdk 0.2.0-master.4 → 0.2.0-master.40
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/README.md +27 -27
- package/lib/accounts/bulkAccountLoader.d.ts +2 -0
- package/lib/accounts/bulkAccountLoader.js +36 -29
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.d.ts +2 -2
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
- package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
- package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
- package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +26 -15
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
- package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/marketAddresses.js +1 -1
- package/lib/addresses/pda.d.ts +15 -9
- package/lib/addresses/pda.js +73 -35
- package/lib/adminClient.d.ts +65 -0
- package/lib/adminClient.js +637 -0
- package/lib/config.d.ts +9 -9
- package/lib/config.js +25 -21
- package/lib/constants/numericConstants.d.ts +30 -12
- package/lib/constants/numericConstants.js +41 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +82 -0
- package/lib/dlob/DLOB.js +696 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +77 -0
- package/lib/dlob/NodeList.d.ts +27 -0
- package/lib/dlob/NodeList.js +144 -0
- package/lib/driftClient.d.ts +233 -0
- package/lib/driftClient.js +2096 -0
- package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
- package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +5 -2
- package/lib/events/eventSubscriber.js +25 -11
- package/lib/events/fetchLogs.d.ts +13 -2
- package/lib/events/fetchLogs.js +40 -12
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +7 -3
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +9 -3
- package/lib/events/types.js +6 -0
- package/lib/events/webSocketLogProvider.js +1 -1
- package/lib/examples/makeTradeExample.js +30 -18
- package/lib/factory/bigNum.d.ts +8 -4
- package/lib/factory/bigNum.js +109 -19
- package/lib/idl/drift.json +8250 -0
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +30 -13
- package/lib/index.js +30 -13
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -38
- package/lib/math/conversion.js +1 -1
- package/lib/math/exchangeStatus.d.ts +4 -0
- package/lib/math/exchangeStatus.js +18 -0
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +23 -21
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +82 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +70 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +14 -6
- package/lib/math/orders.js +90 -17
- package/lib/math/position.d.ts +27 -13
- package/lib/math/position.js +92 -36
- package/lib/math/repeg.js +17 -8
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +192 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/trade.d.ts +10 -10
- package/lib/math/trade.js +27 -31
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +4 -4
- package/lib/orderParams.js +12 -4
- package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
- package/lib/serum/serumFulfillmentConfigMap.js +17 -0
- package/lib/serum/serumSubscriber.d.ts +27 -0
- package/lib/serum/serumSubscriber.js +56 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/{clearingHouseUserConfig.js → serum/types.js} +0 -0
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +589 -196
- package/lib/types.js +108 -17
- package/lib/user.d.ts +226 -0
- package/lib/user.js +949 -0
- package/lib/userConfig.d.ts +14 -0
- package/lib/userConfig.js +2 -0
- package/lib/userMap/userMap.d.ts +41 -0
- package/lib/userMap/userMap.js +85 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/userName.d.ts +1 -0
- package/lib/userName.js +3 -2
- package/lib/userStats.d.ts +18 -0
- package/lib/userStats.js +49 -0
- package/lib/userStatsConfig.d.ts +14 -0
- package/lib/userStatsConfig.js +2 -0
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +10 -3
- package/src/accounts/bulkAccountLoader.ts +44 -34
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +2 -3
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
- package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +35 -15
- package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +3 -4
- package/src/addresses/pda.ts +105 -33
- package/src/adminClient.ts +1207 -0
- package/src/config.ts +37 -31
- package/src/constants/numericConstants.ts +58 -24
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +73 -0
- package/src/dlob/DLOB.ts +1123 -0
- package/src/dlob/DLOBNode.ts +155 -0
- package/src/dlob/NodeList.ts +195 -0
- package/src/driftClient.ts +3564 -0
- package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +36 -14
- package/src/events/fetchLogs.ts +55 -13
- package/src/events/pollingLogProvider.ts +11 -3
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +21 -2
- package/src/events/webSocketLogProvider.ts +1 -1
- package/src/examples/makeTradeExample.ts +44 -28
- package/src/factory/bigNum.ts +150 -22
- package/src/idl/drift.json +8250 -0
- package/src/idl/pyth.json +98 -2
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +30 -13
- package/src/math/amm.ts +161 -48
- package/src/math/conversion.ts +2 -2
- package/src/math/exchangeStatus.ts +31 -0
- package/src/math/funding.ts +41 -31
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +133 -0
- package/src/math/market.ts +143 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +163 -26
- package/src/math/position.ts +136 -58
- package/src/math/repeg.ts +19 -9
- package/src/math/spotBalance.ts +319 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +33 -37
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +16 -8
- package/src/serum/serumFulfillmentConfigMap.ts +26 -0
- package/src/serum/serumSubscriber.ts +99 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +572 -178
- package/src/user.ts +1582 -0
- package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
- package/src/userMap/userMap.ts +124 -0
- package/src/userMap/userStatsMap.ts +108 -0
- package/src/userName.ts +2 -1
- package/src/userStats.ts +75 -0
- package/src/userStatsConfig.ts +18 -0
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +46 -11
- package/tests/dlob/helpers.ts +611 -0
- package/tests/dlob/test.ts +4588 -0
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
- package/lib/admin.d.ts +0 -44
- package/lib/admin.js +0 -433
- package/lib/clearingHouse.d.ts +0 -133
- package/lib/clearingHouse.js +0 -931
- package/lib/clearingHouseUser.d.ts +0 -187
- package/lib/clearingHouseUser.js +0 -643
- package/lib/clearingHouseUserConfig.d.ts +0 -14
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/idl/clearing_house.json +0 -3998
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/admin.ts +0 -722
- package/src/clearingHouse.ts +0 -1451
- package/src/clearingHouseUser.ts +0 -989
- package/src/constants/banks.ts +0 -43
- package/src/idl/clearing_house.json +0 -3998
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js +0 -17
- package/src/util/computeUnits.js.map +0 -1
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { ConfirmOptions, Connection, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { IWallet } from './types';
|
|
3
|
-
import { BN } from '@project-serum/anchor';
|
|
4
3
|
import { OracleInfo } from './oracles/types';
|
|
5
4
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
6
5
|
import { DriftEnv } from './config';
|
|
7
6
|
|
|
8
|
-
export type
|
|
7
|
+
export type DriftClientConfig = {
|
|
9
8
|
connection: Connection;
|
|
10
9
|
wallet: IWallet;
|
|
11
10
|
programID: PublicKey;
|
|
12
|
-
accountSubscription?:
|
|
11
|
+
accountSubscription?: DriftClientSubscriptionConfig;
|
|
13
12
|
opts?: ConfirmOptions;
|
|
14
13
|
txSenderConfig?: TxSenderConfig;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
subAccountIds?: number[];
|
|
15
|
+
activeSubAccountId?: number;
|
|
16
|
+
perpMarketIndexes?: number[];
|
|
17
|
+
spotMarketIndexes?: number[];
|
|
19
18
|
oracleInfos?: OracleInfo[];
|
|
20
19
|
env?: DriftEnv;
|
|
20
|
+
userStats?: boolean;
|
|
21
|
+
authority?: PublicKey; // explicitly pass an authority if signer is delegate
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
type
|
|
24
|
+
type DriftClientSubscriptionConfig =
|
|
24
25
|
| {
|
|
25
26
|
type: 'websocket';
|
|
26
27
|
}
|
package/src/events/eventList.ts
CHANGED
|
@@ -53,7 +53,10 @@ export class EventList<Type extends EventType> {
|
|
|
53
53
|
newNode.next = currentNode.next;
|
|
54
54
|
if (currentNode.next !== undefined) {
|
|
55
55
|
newNode.next.prev = newNode;
|
|
56
|
+
} else {
|
|
57
|
+
this.tail = newNode;
|
|
56
58
|
}
|
|
59
|
+
|
|
57
60
|
currentNode.next = newNode;
|
|
58
61
|
newNode.prev = currentNode;
|
|
59
62
|
}
|
|
@@ -25,6 +25,9 @@ export class EventSubscriber {
|
|
|
25
25
|
private awaitTxResolver = new Map<string, () => void>();
|
|
26
26
|
private logProvider: LogProvider;
|
|
27
27
|
public eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
|
|
28
|
+
private lastSeenSlot: number;
|
|
29
|
+
private lastSeenBlockTime: number | undefined;
|
|
30
|
+
public lastSeenTxSig: string;
|
|
28
31
|
|
|
29
32
|
public constructor(
|
|
30
33
|
private connection: Connection,
|
|
@@ -62,25 +65,29 @@ export class EventSubscriber {
|
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
public subscribe(): boolean {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
public async subscribe(): Promise<boolean> {
|
|
69
|
+
try {
|
|
70
|
+
if (this.logProvider.isSubscribed()) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
69
73
|
|
|
70
|
-
|
|
74
|
+
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
|
|
75
|
+
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
|
|
76
|
+
}, true);
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
} catch (e) {
|
|
71
80
|
console.error('Error fetching previous txs in event subscriber');
|
|
72
81
|
console.error(e);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return this.logProvider.subscribe((txSig, slot, logs) => {
|
|
76
|
-
this.handleTxLogs(txSig, slot, logs);
|
|
77
|
-
});
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
private handleTxLogs(
|
|
81
87
|
txSig: TransactionSignature,
|
|
82
88
|
slot: number,
|
|
83
|
-
logs: string[]
|
|
89
|
+
logs: string[],
|
|
90
|
+
mostRecentBlockTime: number | undefined
|
|
84
91
|
): void {
|
|
85
92
|
if (this.txEventCache.has(txSig)) {
|
|
86
93
|
return;
|
|
@@ -89,6 +96,10 @@ export class EventSubscriber {
|
|
|
89
96
|
const wrappedEvents = this.parseEventsFromLogs(txSig, slot, logs);
|
|
90
97
|
for (const wrappedEvent of wrappedEvents) {
|
|
91
98
|
this.eventListMap.get(wrappedEvent.eventType).insert(wrappedEvent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// dont emit event till we've added all the events to the eventListMap
|
|
102
|
+
for (const wrappedEvent of wrappedEvents) {
|
|
92
103
|
this.eventEmitter.emit('newEvent', wrappedEvent);
|
|
93
104
|
}
|
|
94
105
|
|
|
@@ -98,11 +109,22 @@ export class EventSubscriber {
|
|
|
98
109
|
this.awaitTxResolver.delete(txSig);
|
|
99
110
|
}
|
|
100
111
|
|
|
112
|
+
if (slot > this.lastSeenSlot) {
|
|
113
|
+
this.lastSeenTxSig = txSig;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (
|
|
117
|
+
this.lastSeenBlockTime === undefined ||
|
|
118
|
+
mostRecentBlockTime > this.lastSeenBlockTime
|
|
119
|
+
) {
|
|
120
|
+
this.lastSeenBlockTime = mostRecentBlockTime;
|
|
121
|
+
}
|
|
122
|
+
|
|
101
123
|
this.txEventCache.add(txSig, wrappedEvents);
|
|
102
124
|
}
|
|
103
125
|
|
|
104
|
-
|
|
105
|
-
if (!this.options.untilTx) {
|
|
126
|
+
public async fetchPreviousTx(fetchMax?: boolean): Promise<void> {
|
|
127
|
+
if (!this.options.untilTx && !fetchMax) {
|
|
106
128
|
return;
|
|
107
129
|
}
|
|
108
130
|
|
|
@@ -126,7 +148,7 @@ export class EventSubscriber {
|
|
|
126
148
|
beforeTx = response.earliestTx;
|
|
127
149
|
|
|
128
150
|
for (const { txSig, slot, logs } of response.transactionLogs) {
|
|
129
|
-
this.handleTxLogs(txSig, slot, logs);
|
|
151
|
+
this.handleTxLogs(txSig, slot, logs, response.mostRecentBlockTime);
|
|
130
152
|
}
|
|
131
153
|
}
|
|
132
154
|
}
|
package/src/events/fetchLogs.ts
CHANGED
|
@@ -1,35 +1,51 @@
|
|
|
1
|
+
import { Program } from '@project-serum/anchor';
|
|
1
2
|
import {
|
|
2
3
|
Connection,
|
|
3
4
|
Finality,
|
|
4
5
|
PublicKey,
|
|
6
|
+
TransactionResponse,
|
|
5
7
|
TransactionSignature,
|
|
6
8
|
} from '@solana/web3.js';
|
|
9
|
+
import { WrappedEvents } from './types';
|
|
7
10
|
|
|
8
11
|
type Log = { txSig: TransactionSignature; slot: number; logs: string[] };
|
|
9
12
|
type FetchLogsResponse = {
|
|
10
13
|
earliestTx: string;
|
|
11
14
|
mostRecentTx: string;
|
|
15
|
+
earliestSlot: number;
|
|
16
|
+
mostRecentSlot: number;
|
|
12
17
|
transactionLogs: Log[];
|
|
18
|
+
mostRecentBlockTime: number | undefined;
|
|
13
19
|
};
|
|
14
20
|
|
|
21
|
+
function mapTransactionResponseToLog(transaction: TransactionResponse): Log {
|
|
22
|
+
return {
|
|
23
|
+
txSig: transaction.transaction.signatures[0],
|
|
24
|
+
slot: transaction.slot,
|
|
25
|
+
logs: transaction.meta.logMessages,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
15
29
|
export async function fetchLogs(
|
|
16
30
|
connection: Connection,
|
|
17
31
|
programId: PublicKey,
|
|
18
32
|
finality: Finality,
|
|
19
33
|
beforeTx?: TransactionSignature,
|
|
20
|
-
untilTx?: TransactionSignature
|
|
21
|
-
|
|
34
|
+
untilTx?: TransactionSignature,
|
|
35
|
+
limit?: number
|
|
36
|
+
): Promise<FetchLogsResponse> {
|
|
22
37
|
const signatures = await connection.getSignaturesForAddress(
|
|
23
38
|
programId,
|
|
24
39
|
{
|
|
25
40
|
before: beforeTx,
|
|
26
41
|
until: untilTx,
|
|
42
|
+
limit,
|
|
27
43
|
},
|
|
28
44
|
finality
|
|
29
45
|
);
|
|
30
46
|
|
|
31
47
|
const sortedSignatures = signatures.sort((a, b) =>
|
|
32
|
-
a.slot < b.slot ? -1 : 1
|
|
48
|
+
a.slot === b.slot ? 0 : a.slot < b.slot ? -1 : 1
|
|
33
49
|
);
|
|
34
50
|
|
|
35
51
|
const filteredSignatures = sortedSignatures.filter(
|
|
@@ -51,24 +67,22 @@ export async function fetchLogs(
|
|
|
51
67
|
);
|
|
52
68
|
|
|
53
69
|
return transactions.map((transaction) => {
|
|
54
|
-
return
|
|
55
|
-
txSig: transaction.transaction.signatures[0],
|
|
56
|
-
slot: transaction.slot,
|
|
57
|
-
logs: transaction.meta.logMessages,
|
|
58
|
-
};
|
|
70
|
+
return mapTransactionResponseToLog(transaction);
|
|
59
71
|
});
|
|
60
72
|
})
|
|
61
73
|
)
|
|
62
74
|
).flat();
|
|
63
75
|
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
filteredSignatures[filteredSignatures.length - 1].signature;
|
|
76
|
+
const earliest = filteredSignatures[0];
|
|
77
|
+
const mostRecent = filteredSignatures[filteredSignatures.length - 1];
|
|
67
78
|
|
|
68
79
|
return {
|
|
69
80
|
transactionLogs: transactionLogs,
|
|
70
|
-
earliestTx:
|
|
71
|
-
mostRecentTx:
|
|
81
|
+
earliestTx: earliest.signature,
|
|
82
|
+
mostRecentTx: mostRecent.signature,
|
|
83
|
+
earliestSlot: earliest.slot,
|
|
84
|
+
mostRecentSlot: mostRecent.slot,
|
|
85
|
+
mostRecentBlockTime: mostRecent.blockTime,
|
|
72
86
|
};
|
|
73
87
|
}
|
|
74
88
|
|
|
@@ -78,3 +92,31 @@ function chunk<T>(array: readonly T[], size: number): T[][] {
|
|
|
78
92
|
.map((_, index) => index * size)
|
|
79
93
|
.map((begin) => array.slice(begin, begin + size));
|
|
80
94
|
}
|
|
95
|
+
|
|
96
|
+
export class LogParser {
|
|
97
|
+
private program: Program;
|
|
98
|
+
|
|
99
|
+
constructor(program: Program) {
|
|
100
|
+
this.program = program;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public parseEventsFromTransaction(
|
|
104
|
+
transaction: TransactionResponse
|
|
105
|
+
): WrappedEvents {
|
|
106
|
+
const transactionLogObject = mapTransactionResponseToLog(transaction);
|
|
107
|
+
|
|
108
|
+
return this.parseEventsFromLogs(transactionLogObject);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public parseEventsFromLogs(event: Log): WrappedEvents {
|
|
112
|
+
const records: WrappedEvents = [];
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
this.program._events._eventParser.parseLogs(event.logs, (eventLog) => {
|
|
115
|
+
eventLog.data.txSig = event.txSig;
|
|
116
|
+
eventLog.data.slot = event.slot;
|
|
117
|
+
eventLog.data.eventType = eventLog.name;
|
|
118
|
+
records.push(eventLog.data);
|
|
119
|
+
});
|
|
120
|
+
return records;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -13,6 +13,7 @@ export class PollingLogProvider implements LogProvider {
|
|
|
13
13
|
private intervalId: NodeJS.Timer;
|
|
14
14
|
private mostRecentSeenTx?: TransactionSignature;
|
|
15
15
|
private mutex: number;
|
|
16
|
+
private firstFetch = true;
|
|
16
17
|
|
|
17
18
|
public constructor(
|
|
18
19
|
private connection: Connection,
|
|
@@ -23,7 +24,10 @@ export class PollingLogProvider implements LogProvider {
|
|
|
23
24
|
this.finality = commitment === 'finalized' ? 'finalized' : 'confirmed';
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
public subscribe(
|
|
27
|
+
public subscribe(
|
|
28
|
+
callback: logProviderCallback,
|
|
29
|
+
skipHistory?: boolean
|
|
30
|
+
): boolean {
|
|
27
31
|
if (this.intervalId) {
|
|
28
32
|
return true;
|
|
29
33
|
}
|
|
@@ -40,9 +44,13 @@ export class PollingLogProvider implements LogProvider {
|
|
|
40
44
|
this.programId,
|
|
41
45
|
this.finality,
|
|
42
46
|
undefined,
|
|
43
|
-
this.mostRecentSeenTx
|
|
47
|
+
this.mostRecentSeenTx,
|
|
48
|
+
// If skipping history, only fetch one log back, not the maximum amount available
|
|
49
|
+
skipHistory && this.firstFetch ? 1 : undefined
|
|
44
50
|
);
|
|
45
51
|
|
|
52
|
+
this.firstFetch = false;
|
|
53
|
+
|
|
46
54
|
if (response === undefined) {
|
|
47
55
|
return;
|
|
48
56
|
}
|
|
@@ -50,7 +58,7 @@ export class PollingLogProvider implements LogProvider {
|
|
|
50
58
|
const { mostRecentTx, transactionLogs } = response;
|
|
51
59
|
|
|
52
60
|
for (const { txSig, slot, logs } of transactionLogs) {
|
|
53
|
-
callback(txSig, slot, logs);
|
|
61
|
+
callback(txSig, slot, logs, response.mostRecentBlockTime);
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
this.mostRecentSeenTx = mostRecentTx;
|
package/src/events/sort.ts
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
SortFn,
|
|
7
7
|
Event,
|
|
8
8
|
} from './types';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { OrderActionRecord } from '../types';
|
|
10
|
+
import { ZERO } from '../index';
|
|
11
11
|
|
|
12
12
|
function clientSortAscFn(): 'less than' {
|
|
13
13
|
return 'less than';
|
|
@@ -24,21 +24,17 @@ function defaultBlockchainSortFn(
|
|
|
24
24
|
return currentEvent.slot <= newEvent.slot ? 'less than' : 'greater than';
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
function
|
|
28
|
-
currentEvent: Event<
|
|
29
|
-
newEvent: Event<
|
|
27
|
+
function orderActionRecordSortFn(
|
|
28
|
+
currentEvent: Event<OrderActionRecord>,
|
|
29
|
+
newEvent: Event<OrderActionRecord>
|
|
30
30
|
): 'less than' | 'greater than' {
|
|
31
|
-
const currentEventMarketIndex =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const newEventMarketIndex = !newEvent.maker.equals(PublicKey.default)
|
|
35
|
-
? newEvent.makerOrder.marketIndex
|
|
36
|
-
: newEvent.takerOrder.marketIndex;
|
|
37
|
-
if (!currentEventMarketIndex.eq(newEventMarketIndex)) {
|
|
31
|
+
const currentEventMarketIndex = currentEvent.marketIndex;
|
|
32
|
+
const newEventMarketIndex = newEvent.marketIndex;
|
|
33
|
+
if (currentEventMarketIndex !== newEventMarketIndex) {
|
|
38
34
|
return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
if (currentEvent.fillRecordId
|
|
37
|
+
if (currentEvent.fillRecordId?.gt(ZERO) && newEvent.fillRecordId?.gt(ZERO)) {
|
|
42
38
|
return currentEvent.fillRecordId.lte(newEvent.fillRecordId)
|
|
43
39
|
? 'less than'
|
|
44
40
|
: 'greater than';
|
|
@@ -57,8 +53,8 @@ export function getSortFn(
|
|
|
57
53
|
}
|
|
58
54
|
|
|
59
55
|
switch (eventType) {
|
|
60
|
-
case '
|
|
61
|
-
return
|
|
56
|
+
case 'OrderActionRecord':
|
|
57
|
+
return orderActionRecordSortFn;
|
|
62
58
|
default:
|
|
63
59
|
return defaultBlockchainSortFn;
|
|
64
60
|
}
|
package/src/events/types.ts
CHANGED
|
@@ -4,7 +4,13 @@ import {
|
|
|
4
4
|
FundingPaymentRecord,
|
|
5
5
|
FundingRateRecord,
|
|
6
6
|
LiquidationRecord,
|
|
7
|
+
NewUserRecord,
|
|
8
|
+
OrderActionRecord,
|
|
7
9
|
OrderRecord,
|
|
10
|
+
SettlePnlRecord,
|
|
11
|
+
LPRecord,
|
|
12
|
+
InsuranceFundRecord,
|
|
13
|
+
SpotInterestRecord,
|
|
8
14
|
} from '../index';
|
|
9
15
|
|
|
10
16
|
export type EventSubscriptionOptions = {
|
|
@@ -26,7 +32,13 @@ export const DefaultEventSubscriptionOptions: EventSubscriptionOptions = {
|
|
|
26
32
|
'FundingPaymentRecord',
|
|
27
33
|
'LiquidationRecord',
|
|
28
34
|
'OrderRecord',
|
|
35
|
+
'OrderActionRecord',
|
|
29
36
|
'FundingRateRecord',
|
|
37
|
+
'NewUserRecord',
|
|
38
|
+
'SettlePnlRecord',
|
|
39
|
+
'LPRecord',
|
|
40
|
+
'InsuranceFundRecord',
|
|
41
|
+
'SpotInterestRecord',
|
|
30
42
|
],
|
|
31
43
|
maxEventsPerType: 4096,
|
|
32
44
|
orderBy: 'blockchain',
|
|
@@ -59,6 +71,12 @@ export type EventMap = {
|
|
|
59
71
|
LiquidationRecord: Event<LiquidationRecord>;
|
|
60
72
|
FundingRateRecord: Event<FundingRateRecord>;
|
|
61
73
|
OrderRecord: Event<OrderRecord>;
|
|
74
|
+
OrderActionRecord: Event<OrderActionRecord>;
|
|
75
|
+
SettlePnlRecord: Event<SettlePnlRecord>;
|
|
76
|
+
NewUserRecord: Event<NewUserRecord>;
|
|
77
|
+
LPRecord: Event<LPRecord>;
|
|
78
|
+
InsuranceFundRecord: Event<InsuranceFundRecord>;
|
|
79
|
+
SpotInterestRecord: Event<SpotInterestRecord>;
|
|
62
80
|
};
|
|
63
81
|
|
|
64
82
|
export type EventType = keyof EventMap;
|
|
@@ -75,12 +93,13 @@ export type SortFn = (
|
|
|
75
93
|
export type logProviderCallback = (
|
|
76
94
|
txSig: TransactionSignature,
|
|
77
95
|
slot: number,
|
|
78
|
-
logs: string[]
|
|
96
|
+
logs: string[],
|
|
97
|
+
mostRecentBlockTime: number | undefined
|
|
79
98
|
) => void;
|
|
80
99
|
|
|
81
100
|
export interface LogProvider {
|
|
82
101
|
isSubscribed(): boolean;
|
|
83
|
-
subscribe(callback: logProviderCallback): boolean;
|
|
102
|
+
subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
|
|
84
103
|
unsubscribe(): Promise<boolean>;
|
|
85
104
|
}
|
|
86
105
|
|
|
@@ -17,7 +17,7 @@ export class WebSocketLogProvider implements LogProvider {
|
|
|
17
17
|
this.subscriptionId = this.connection.onLogs(
|
|
18
18
|
this.programId,
|
|
19
19
|
(logs, ctx) => {
|
|
20
|
-
callback(logs.signature, ctx.slot, logs.logs);
|
|
20
|
+
callback(logs.signature, ctx.slot, logs.logs, undefined);
|
|
21
21
|
},
|
|
22
22
|
this.commitment
|
|
23
23
|
);
|
|
@@ -3,17 +3,19 @@ import { Wallet } from '..';
|
|
|
3
3
|
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
4
4
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
calculateReservePrice,
|
|
7
|
+
DriftClient,
|
|
8
|
+
User,
|
|
9
9
|
initialize,
|
|
10
10
|
PositionDirection,
|
|
11
11
|
convertToNumber,
|
|
12
12
|
calculateTradeSlippage,
|
|
13
|
-
|
|
13
|
+
BulkAccountLoader,
|
|
14
|
+
PerpMarkets,
|
|
15
|
+
PRICE_PRECISION,
|
|
14
16
|
QUOTE_PRECISION,
|
|
15
17
|
} from '..';
|
|
16
|
-
import {
|
|
18
|
+
import { SpotMarkets } from '../constants/spotMarkets';
|
|
17
19
|
|
|
18
20
|
export const getTokenAddress = (
|
|
19
21
|
mintAddress: string,
|
|
@@ -27,9 +29,11 @@ export const getTokenAddress = (
|
|
|
27
29
|
);
|
|
28
30
|
};
|
|
29
31
|
|
|
32
|
+
const cluster = 'devnet';
|
|
33
|
+
|
|
30
34
|
const main = async () => {
|
|
31
35
|
// Initialize Drift SDK
|
|
32
|
-
const sdkConfig = initialize({ env:
|
|
36
|
+
const sdkConfig = initialize({ env: cluster });
|
|
33
37
|
|
|
34
38
|
// Set up the Wallet and Provider
|
|
35
39
|
const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
|
|
@@ -60,20 +64,35 @@ const main = async () => {
|
|
|
60
64
|
);
|
|
61
65
|
|
|
62
66
|
// Set up the Drift Clearing House
|
|
63
|
-
const
|
|
64
|
-
|
|
67
|
+
const driftPublicKey = new PublicKey(sdkConfig.CLEARING_HOUSE_PROGRAM_ID);
|
|
68
|
+
const bulkAccountLoader = new BulkAccountLoader(
|
|
69
|
+
connection,
|
|
70
|
+
'confirmed',
|
|
71
|
+
1000
|
|
65
72
|
);
|
|
66
|
-
const
|
|
73
|
+
const driftClient = new DriftClient({
|
|
67
74
|
connection,
|
|
68
75
|
wallet: provider.wallet,
|
|
69
|
-
programID:
|
|
76
|
+
programID: driftPublicKey,
|
|
77
|
+
perpMarketIndexes: PerpMarkets[cluster].map((market) => market.marketIndex),
|
|
78
|
+
spotMarketIndexes: SpotMarkets[cluster].map(
|
|
79
|
+
(spotMarket) => spotMarket.marketIndex
|
|
80
|
+
),
|
|
81
|
+
accountSubscription: {
|
|
82
|
+
type: 'polling',
|
|
83
|
+
accountLoader: bulkAccountLoader,
|
|
84
|
+
},
|
|
70
85
|
});
|
|
71
|
-
await
|
|
86
|
+
await driftClient.subscribe();
|
|
72
87
|
|
|
73
88
|
// Set up Clearing House user client
|
|
74
|
-
const user = new
|
|
75
|
-
|
|
76
|
-
userAccountPublicKey: await
|
|
89
|
+
const user = new User({
|
|
90
|
+
driftClient: driftClient,
|
|
91
|
+
userAccountPublicKey: await driftClient.getUserAccountPublicKey(),
|
|
92
|
+
accountSubscription: {
|
|
93
|
+
type: 'polling',
|
|
94
|
+
accountLoader: bulkAccountLoader,
|
|
95
|
+
},
|
|
77
96
|
});
|
|
78
97
|
|
|
79
98
|
//// Check if clearing house account exists for the current wallet
|
|
@@ -82,37 +101,34 @@ const main = async () => {
|
|
|
82
101
|
if (!userAccountExists) {
|
|
83
102
|
//// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
|
|
84
103
|
const depositAmount = new BN(10000).mul(QUOTE_PRECISION);
|
|
85
|
-
await
|
|
104
|
+
await driftClient.initializeUserAccountAndDepositCollateral(
|
|
86
105
|
depositAmount,
|
|
87
106
|
await getTokenAddress(
|
|
88
107
|
usdcTokenAddress.toString(),
|
|
89
108
|
wallet.publicKey.toString()
|
|
90
109
|
),
|
|
91
|
-
|
|
110
|
+
SpotMarkets['devnet'][0].marketIndex
|
|
92
111
|
);
|
|
93
112
|
}
|
|
94
113
|
|
|
95
114
|
await user.subscribe();
|
|
96
115
|
|
|
97
116
|
// Get current price
|
|
98
|
-
const solMarketInfo = sdkConfig.
|
|
117
|
+
const solMarketInfo = sdkConfig.PERP_MARKETS.find(
|
|
99
118
|
(market) => market.baseAssetSymbol === 'SOL'
|
|
100
119
|
);
|
|
101
120
|
|
|
102
|
-
const currentMarketPrice =
|
|
103
|
-
|
|
121
|
+
const currentMarketPrice = calculateReservePrice(
|
|
122
|
+
driftClient.getPerpMarketAccount(solMarketInfo.marketIndex),
|
|
104
123
|
undefined
|
|
105
124
|
);
|
|
106
125
|
|
|
107
|
-
const formattedPrice = convertToNumber(
|
|
108
|
-
currentMarketPrice,
|
|
109
|
-
MARK_PRICE_PRECISION
|
|
110
|
-
);
|
|
126
|
+
const formattedPrice = convertToNumber(currentMarketPrice, PRICE_PRECISION);
|
|
111
127
|
|
|
112
128
|
console.log(`Current Market Price is $${formattedPrice}`);
|
|
113
129
|
|
|
114
130
|
// Estimate the slippage for a $5000 LONG trade
|
|
115
|
-
const solMarketAccount =
|
|
131
|
+
const solMarketAccount = driftClient.getPerpMarketAccount(
|
|
116
132
|
solMarketInfo.marketIndex
|
|
117
133
|
);
|
|
118
134
|
|
|
@@ -125,7 +141,7 @@ const main = async () => {
|
|
|
125
141
|
'quote',
|
|
126
142
|
undefined
|
|
127
143
|
)[0],
|
|
128
|
-
|
|
144
|
+
PRICE_PRECISION
|
|
129
145
|
);
|
|
130
146
|
|
|
131
147
|
console.log(
|
|
@@ -133,7 +149,7 @@ const main = async () => {
|
|
|
133
149
|
);
|
|
134
150
|
|
|
135
151
|
// Make a $5000 LONG trade
|
|
136
|
-
await
|
|
152
|
+
await driftClient.openPosition(
|
|
137
153
|
PositionDirection.LONG,
|
|
138
154
|
longAmount,
|
|
139
155
|
solMarketInfo.marketIndex
|
|
@@ -142,14 +158,14 @@ const main = async () => {
|
|
|
142
158
|
|
|
143
159
|
// Reduce the position by $2000
|
|
144
160
|
const reduceAmount = new BN(2000).mul(QUOTE_PRECISION);
|
|
145
|
-
await
|
|
161
|
+
await driftClient.openPosition(
|
|
146
162
|
PositionDirection.SHORT,
|
|
147
163
|
reduceAmount,
|
|
148
164
|
solMarketInfo.marketIndex
|
|
149
165
|
);
|
|
150
166
|
|
|
151
167
|
// Close the rest of the position
|
|
152
|
-
await
|
|
168
|
+
await driftClient.closePosition(solMarketInfo.marketIndex);
|
|
153
169
|
};
|
|
154
170
|
|
|
155
171
|
main();
|