@drift-labs/sdk 0.2.0-master.4 → 0.2.0-master.41
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/pollingUserAccountSubscriber.d.ts +1 -1
- package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -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 +694 -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 +234 -0
- package/lib/driftClient.js +2108 -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 +11 -3
- package/lib/events/types.js +8 -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 +8386 -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 +16 -6
- package/lib/math/orders.js +97 -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 +688 -216
- package/lib/types.js +153 -24
- package/lib/user.d.ts +228 -0
- package/lib/user.js +959 -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 +11 -4
- 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/pollingUserAccountSubscriber.ts +5 -12
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -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/assert/assert.js +9 -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 +1120 -0
- package/src/dlob/DLOBNode.ts +155 -0
- package/src/dlob/NodeList.ts +195 -0
- package/src/driftClient.ts +3594 -0
- package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
- package/src/events/eventList.js +77 -0
- 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 +27 -2
- package/src/events/webSocketLogProvider.ts +1 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +44 -28
- package/src/factory/bigNum.ts +150 -22
- package/src/idl/drift.json +8386 -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 +168 -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/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +650 -189
- package/src/user.ts +1599 -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.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +46 -11
- package/tests/dlob/helpers.ts +620 -0
- package/tests/dlob/test.ts +4586 -0
- package/yarn-error.log +3160 -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.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
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventList = void 0;
|
|
4
|
+
class Node {
|
|
5
|
+
constructor(event, next, prev) {
|
|
6
|
+
this.event = event;
|
|
7
|
+
this.next = next;
|
|
8
|
+
this.prev = prev;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
class EventList {
|
|
12
|
+
constructor(eventType, maxSize, sortFn, orderDirection) {
|
|
13
|
+
this.eventType = eventType;
|
|
14
|
+
this.maxSize = maxSize;
|
|
15
|
+
this.sortFn = sortFn;
|
|
16
|
+
this.orderDirection = orderDirection;
|
|
17
|
+
this.size = 0;
|
|
18
|
+
}
|
|
19
|
+
insert(event) {
|
|
20
|
+
this.size++;
|
|
21
|
+
const newNode = new Node(event);
|
|
22
|
+
if (this.head === undefined) {
|
|
23
|
+
this.head = this.tail = newNode;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (this.sortFn(this.head.event, newNode.event) ===
|
|
27
|
+
(this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
|
|
28
|
+
this.head.prev = newNode;
|
|
29
|
+
newNode.next = this.head;
|
|
30
|
+
this.head = newNode;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
let currentNode = this.head;
|
|
34
|
+
while (currentNode.next !== undefined &&
|
|
35
|
+
this.sortFn(currentNode.next.event, newNode.event) !==
|
|
36
|
+
(this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
|
|
37
|
+
currentNode = currentNode.next;
|
|
38
|
+
}
|
|
39
|
+
newNode.next = currentNode.next;
|
|
40
|
+
if (currentNode.next !== undefined) {
|
|
41
|
+
newNode.next.prev = newNode;
|
|
42
|
+
}
|
|
43
|
+
currentNode.next = newNode;
|
|
44
|
+
newNode.prev = currentNode;
|
|
45
|
+
}
|
|
46
|
+
if (this.size > this.maxSize) {
|
|
47
|
+
this.detach();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
detach() {
|
|
51
|
+
const node = this.tail;
|
|
52
|
+
if (node.prev !== undefined) {
|
|
53
|
+
node.prev.next = node.next;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.head = node.next;
|
|
57
|
+
}
|
|
58
|
+
if (node.next !== undefined) {
|
|
59
|
+
node.next.prev = node.prev;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.tail = node.prev;
|
|
63
|
+
}
|
|
64
|
+
this.size--;
|
|
65
|
+
}
|
|
66
|
+
toArray() {
|
|
67
|
+
return Array.from(this);
|
|
68
|
+
}
|
|
69
|
+
*[Symbol.iterator]() {
|
|
70
|
+
let node = this.head;
|
|
71
|
+
while (node) {
|
|
72
|
+
yield node.event;
|
|
73
|
+
node = node.next;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.EventList = EventList;
|
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,15 @@ 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,
|
|
14
|
+
InsuranceFundStakeRecord,
|
|
15
|
+
CurveRecord,
|
|
8
16
|
} from '../index';
|
|
9
17
|
|
|
10
18
|
export type EventSubscriptionOptions = {
|
|
@@ -26,7 +34,15 @@ export const DefaultEventSubscriptionOptions: EventSubscriptionOptions = {
|
|
|
26
34
|
'FundingPaymentRecord',
|
|
27
35
|
'LiquidationRecord',
|
|
28
36
|
'OrderRecord',
|
|
37
|
+
'OrderActionRecord',
|
|
29
38
|
'FundingRateRecord',
|
|
39
|
+
'NewUserRecord',
|
|
40
|
+
'SettlePnlRecord',
|
|
41
|
+
'LPRecord',
|
|
42
|
+
'InsuranceFundRecord',
|
|
43
|
+
'SpotInterestRecord',
|
|
44
|
+
'InsuranceFundStakeRecord',
|
|
45
|
+
'CurveRecord',
|
|
30
46
|
],
|
|
31
47
|
maxEventsPerType: 4096,
|
|
32
48
|
orderBy: 'blockchain',
|
|
@@ -59,6 +75,14 @@ export type EventMap = {
|
|
|
59
75
|
LiquidationRecord: Event<LiquidationRecord>;
|
|
60
76
|
FundingRateRecord: Event<FundingRateRecord>;
|
|
61
77
|
OrderRecord: Event<OrderRecord>;
|
|
78
|
+
OrderActionRecord: Event<OrderActionRecord>;
|
|
79
|
+
SettlePnlRecord: Event<SettlePnlRecord>;
|
|
80
|
+
NewUserRecord: Event<NewUserRecord>;
|
|
81
|
+
LPRecord: Event<LPRecord>;
|
|
82
|
+
InsuranceFundRecord: Event<InsuranceFundRecord>;
|
|
83
|
+
SpotInterestRecord: Event<SpotInterestRecord>;
|
|
84
|
+
InsuranceFundStakeRecord: Event<InsuranceFundStakeRecord>;
|
|
85
|
+
CurveRecord: Event<CurveRecord>;
|
|
62
86
|
};
|
|
63
87
|
|
|
64
88
|
export type EventType = keyof EventMap;
|
|
@@ -75,12 +99,13 @@ export type SortFn = (
|
|
|
75
99
|
export type logProviderCallback = (
|
|
76
100
|
txSig: TransactionSignature,
|
|
77
101
|
slot: number,
|
|
78
|
-
logs: string[]
|
|
102
|
+
logs: string[],
|
|
103
|
+
mostRecentBlockTime: number | undefined
|
|
79
104
|
) => void;
|
|
80
105
|
|
|
81
106
|
export interface LogProvider {
|
|
82
107
|
isSubscribed(): boolean;
|
|
83
|
-
subscribe(callback: logProviderCallback): boolean;
|
|
108
|
+
subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
|
|
84
109
|
unsubscribe(): Promise<boolean>;
|
|
85
110
|
}
|
|
86
111
|
|
|
@@ -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
|
);
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __awaiter =
|
|
3
|
+
(this && this.__awaiter) ||
|
|
4
|
+
function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) {
|
|
6
|
+
return value instanceof P
|
|
7
|
+
? value
|
|
8
|
+
: new P(function (resolve) {
|
|
9
|
+
resolve(value);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
13
|
+
function fulfilled(value) {
|
|
14
|
+
try {
|
|
15
|
+
step(generator.next(value));
|
|
16
|
+
} catch (e) {
|
|
17
|
+
reject(e);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function rejected(value) {
|
|
21
|
+
try {
|
|
22
|
+
step(generator['throw'](value));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
reject(e);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function step(result) {
|
|
28
|
+
result.done
|
|
29
|
+
? resolve(result.value)
|
|
30
|
+
: adopt(result.value).then(fulfilled, rejected);
|
|
31
|
+
}
|
|
32
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
36
|
+
exports.getTokenAddress = void 0;
|
|
37
|
+
const anchor_1 = require('@project-serum/anchor');
|
|
38
|
+
const __1 = require('..');
|
|
39
|
+
const spl_token_1 = require('@solana/spl-token');
|
|
40
|
+
const web3_js_1 = require('@solana/web3.js');
|
|
41
|
+
const __2 = require('..');
|
|
42
|
+
const banks_1 = require('../constants/spotMarkets');
|
|
43
|
+
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
44
|
+
return spl_token_1.Token.getAssociatedTokenAddress(
|
|
45
|
+
new web3_js_1.PublicKey(`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`),
|
|
46
|
+
spl_token_1.TOKEN_PROGRAM_ID,
|
|
47
|
+
new web3_js_1.PublicKey(mintAddress),
|
|
48
|
+
new web3_js_1.PublicKey(userPubKey)
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
exports.getTokenAddress = getTokenAddress;
|
|
52
|
+
const main = () =>
|
|
53
|
+
__awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
// Initialize Drift SDK
|
|
55
|
+
const sdkConfig = __2.initialize({ env: 'devnet' });
|
|
56
|
+
// Set up the Wallet and Provider
|
|
57
|
+
const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
|
|
58
|
+
const keypair = web3_js_1.Keypair.fromSecretKey(
|
|
59
|
+
Uint8Array.from(JSON.parse(privateKey))
|
|
60
|
+
);
|
|
61
|
+
const wallet = new __1.Wallet(keypair);
|
|
62
|
+
// Set up the Connection
|
|
63
|
+
const rpcAddress = process.env.RPC_ADDRESS; // can use: https://api.devnet.solana.com for devnet; https://api.mainnet-beta.solana.com for mainnet;
|
|
64
|
+
const connection = new web3_js_1.Connection(rpcAddress);
|
|
65
|
+
// Set up the Provider
|
|
66
|
+
const provider = new anchor_1.AnchorProvider(
|
|
67
|
+
connection,
|
|
68
|
+
wallet,
|
|
69
|
+
anchor_1.AnchorProvider.defaultOptions()
|
|
70
|
+
);
|
|
71
|
+
// Check SOL Balance
|
|
72
|
+
const lamportsBalance = yield connection.getBalance(wallet.publicKey);
|
|
73
|
+
console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
|
|
74
|
+
// Misc. other things to set up
|
|
75
|
+
const usdcTokenAddress = yield exports.getTokenAddress(
|
|
76
|
+
sdkConfig.USDC_MINT_ADDRESS,
|
|
77
|
+
wallet.publicKey.toString()
|
|
78
|
+
);
|
|
79
|
+
// Set up the Drift Clearing House
|
|
80
|
+
const clearingHousePublicKey = new web3_js_1.PublicKey(
|
|
81
|
+
sdkConfig.CLEARING_HOUSE_PROGRAM_ID
|
|
82
|
+
);
|
|
83
|
+
const clearingHouse = new __2.ClearingHouse({
|
|
84
|
+
connection,
|
|
85
|
+
wallet: provider.wallet,
|
|
86
|
+
programID: clearingHousePublicKey,
|
|
87
|
+
});
|
|
88
|
+
yield clearingHouse.subscribe();
|
|
89
|
+
// Set up Clearing House user client
|
|
90
|
+
const user = new __2.ClearingHouseUser({
|
|
91
|
+
clearingHouse,
|
|
92
|
+
userAccountPublicKey: yield clearingHouse.getUserAccountPublicKey(),
|
|
93
|
+
});
|
|
94
|
+
//// Check if clearing house account exists for the current wallet
|
|
95
|
+
const userAccountExists = yield user.exists();
|
|
96
|
+
if (!userAccountExists) {
|
|
97
|
+
//// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
|
|
98
|
+
const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
|
|
99
|
+
yield clearingHouse.initializeUserAccountAndDepositCollateral(
|
|
100
|
+
depositAmount,
|
|
101
|
+
yield exports.getTokenAddress(
|
|
102
|
+
usdcTokenAddress.toString(),
|
|
103
|
+
wallet.publicKey.toString()
|
|
104
|
+
),
|
|
105
|
+
banks_1.SpotMarkets['devnet'][0].marketIndex
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
yield user.subscribe();
|
|
109
|
+
// Get current price
|
|
110
|
+
const solMarketInfo = sdkConfig.PERP_MARKETS.find(
|
|
111
|
+
(market) => market.baseAssetSymbol === 'SOL'
|
|
112
|
+
);
|
|
113
|
+
const currentMarketPrice = __2.calculateMarkPrice(
|
|
114
|
+
clearingHouse.getMarketAccount(solMarketInfo.marketIndex),
|
|
115
|
+
undefined
|
|
116
|
+
);
|
|
117
|
+
const formattedPrice = __2.convertToNumber(
|
|
118
|
+
currentMarketPrice,
|
|
119
|
+
__2.PRICE_PRECISION
|
|
120
|
+
);
|
|
121
|
+
console.log(`Current Market Price is $${formattedPrice}`);
|
|
122
|
+
// Estimate the slippage for a $5000 LONG trade
|
|
123
|
+
const solMarketAccount = clearingHouse.getMarketAccount(
|
|
124
|
+
solMarketInfo.marketIndex
|
|
125
|
+
);
|
|
126
|
+
const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
|
|
127
|
+
const slippage = __2.convertToNumber(
|
|
128
|
+
__2.calculateTradeSlippage(
|
|
129
|
+
__2.PositionDirection.LONG,
|
|
130
|
+
longAmount,
|
|
131
|
+
solMarketAccount,
|
|
132
|
+
'quote',
|
|
133
|
+
undefined
|
|
134
|
+
)[0],
|
|
135
|
+
__2.PRICE_PRECISION
|
|
136
|
+
);
|
|
137
|
+
console.log(
|
|
138
|
+
`Slippage for a $5000 LONG on the SOL market would be $${slippage}`
|
|
139
|
+
);
|
|
140
|
+
// Make a $5000 LONG trade
|
|
141
|
+
yield clearingHouse.openPosition(
|
|
142
|
+
__2.PositionDirection.LONG,
|
|
143
|
+
longAmount,
|
|
144
|
+
solMarketInfo.marketIndex
|
|
145
|
+
);
|
|
146
|
+
console.log(`LONGED $5000 SOL`);
|
|
147
|
+
// Reduce the position by $2000
|
|
148
|
+
const reduceAmount = new anchor_1.BN(2000).mul(__2.QUOTE_PRECISION);
|
|
149
|
+
yield clearingHouse.openPosition(
|
|
150
|
+
__2.PositionDirection.SHORT,
|
|
151
|
+
reduceAmount,
|
|
152
|
+
solMarketInfo.marketIndex
|
|
153
|
+
);
|
|
154
|
+
// Close the rest of the position
|
|
155
|
+
yield clearingHouse.closePosition(solMarketInfo.marketIndex);
|
|
156
|
+
});
|
|
157
|
+
main();
|