@drift-labs/sdk 0.2.0-temp.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -29
- 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 +10 -10
- package/lib/config.js +26 -22
- package/lib/constants/numericConstants.d.ts +29 -12
- package/lib/constants/numericConstants.js +40 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +20 -9
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +63 -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 +45 -14
- 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 +8392 -0
- package/lib/index.d.ts +29 -12
- package/lib/index.js +29 -12
- 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 +91 -37
- 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/{src/oracles → lib/serum}/types.js +0 -0
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/tokenFaucet.js +23 -12
- 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/types.d.ts +631 -222
- package/lib/types.js +137 -24
- package/lib/user.d.ts +228 -0
- package/lib/user.js +959 -0
- package/lib/userConfig.d.ts +14 -0
- package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -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/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -5
- 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/config.ts +41 -34
- package/src/constants/numericConstants.ts +59 -26
- package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
- package/src/constants/spotMarkets.ts +83 -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.ts +3 -0
- package/src/events/eventSubscriber.ts +36 -14
- package/src/events/fetchLogs.ts +60 -15
- 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 +152 -75
- package/src/examples/makeTradeExample.ts +44 -28
- package/src/factory/bigNum.ts +150 -22
- package/src/idl/drift.json +8392 -0
- package/src/idl/pyth.json +98 -2
- package/src/index.ts +29 -12
- 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 +133 -59
- 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/tokenFaucet.ts +38 -15
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.ts +2 -1
- package/src/types.ts +594 -195
- 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/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +46 -11
- package/tests/dlob/helpers.ts +619 -0
- package/tests/dlob/test.ts +4586 -0
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
- package/lib/admin.d.ts +0 -44
- package/lib/admin.js +0 -438
- package/lib/clearingHouse.d.ts +0 -146
- package/lib/clearingHouse.js +0 -1154
- package/lib/clearingHouseUser.d.ts +0 -187
- package/lib/clearingHouseUser.js +0 -634
- package/lib/clearingHouseUserConfig.d.ts +0 -14
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -41
- package/lib/constants/markets.d.ts +0 -19
- package/lib/idl/clearing_house.json +0 -4464
- 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/accounts/bulkAccountLoader.js +0 -197
- package/src/accounts/bulkUserSubscription.js +0 -33
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
- package/src/accounts/pollingOracleSubscriber.js +0 -93
- package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
- package/src/accounts/pollingUserAccountSubscriber.js +0 -132
- package/src/accounts/types.js +0 -10
- package/src/accounts/utils.js +0 -7
- package/src/accounts/webSocketAccountSubscriber.js +0 -93
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
- package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
- package/src/addresses/marketAddresses.js +0 -26
- package/src/admin.js +0 -517
- package/src/admin.ts +0 -730
- package/src/clearingHouse.ts +0 -1828
- package/src/clearingHouseUser.ts +0 -978
- package/src/clearingHouseUserConfig.js +0 -2
- package/src/config.js +0 -67
- package/src/constants/banks.js +0 -42
- package/src/constants/banks.ts +0 -50
- package/src/constants/markets.js +0 -42
- package/src/constants/numericConstants.js +0 -41
- package/src/events/eventSubscriber.js +0 -139
- package/src/events/fetchLogs.js +0 -50
- package/src/events/pollingLogProvider.js +0 -64
- package/src/events/sort.js +0 -44
- package/src/events/txEventCache.js +0 -71
- package/src/events/types.js +0 -20
- package/src/events/webSocketLogProvider.js +0 -41
- package/src/factory/bigNum.js +0 -390
- package/src/factory/oracleClient.js +0 -20
- package/src/idl/clearing_house.json +0 -4464
- package/src/index.js +0 -69
- package/src/math/amm.js +0 -369
- package/src/math/auction.js +0 -42
- package/src/math/bankBalance.ts +0 -112
- package/src/math/conversion.js +0 -11
- package/src/math/funding.js +0 -248
- package/src/math/oracles.js +0 -26
- package/src/math/repeg.js +0 -128
- package/src/math/state.js +0 -15
- package/src/math/state.ts +0 -14
- package/src/math/trade.js +0 -253
- package/src/math/utils.js +0 -26
- package/src/math/utils.js.map +0 -1
- package/src/mockUSDCFaucet.js +0 -280
- package/src/oracles/oracleClientCache.js +0 -19
- package/src/oracles/pythClient.js +0 -46
- package/src/oracles/quoteAssetOracleClient.js +0 -32
- package/src/oracles/switchboardClient.js +0 -69
- package/src/orderParams.js +0 -20
- package/src/orders.ts +0 -245
- package/src/slot/SlotSubscriber.js +0 -39
- package/src/tokenFaucet.js +0 -189
- package/src/types.js +0 -125
- package/src/userName.js +0 -20
- package/src/wallet.js +0 -35
package/src/clearingHouse.ts
DELETED
|
@@ -1,1828 +0,0 @@
|
|
|
1
|
-
import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
|
|
2
|
-
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
3
|
-
import {
|
|
4
|
-
StateAccount,
|
|
5
|
-
IWallet,
|
|
6
|
-
PositionDirection,
|
|
7
|
-
UserAccount,
|
|
8
|
-
MarketAccount,
|
|
9
|
-
OrderParams,
|
|
10
|
-
Order,
|
|
11
|
-
BankAccount,
|
|
12
|
-
UserBankBalance,
|
|
13
|
-
MakerInfo,
|
|
14
|
-
TakerInfo,
|
|
15
|
-
OptionalOrderParams,
|
|
16
|
-
DefaultOrderParams,
|
|
17
|
-
OrderType,
|
|
18
|
-
} from './types';
|
|
19
|
-
import * as anchor from '@project-serum/anchor';
|
|
20
|
-
import clearingHouseIDL from './idl/clearing_house.json';
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
Connection,
|
|
24
|
-
PublicKey,
|
|
25
|
-
TransactionSignature,
|
|
26
|
-
ConfirmOptions,
|
|
27
|
-
Transaction,
|
|
28
|
-
TransactionInstruction,
|
|
29
|
-
AccountMeta,
|
|
30
|
-
} from '@solana/web3.js';
|
|
31
|
-
|
|
32
|
-
import { TokenFaucet } from './tokenFaucet';
|
|
33
|
-
import { EventEmitter } from 'events';
|
|
34
|
-
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
35
|
-
import {
|
|
36
|
-
getClearingHouseStateAccountPublicKey,
|
|
37
|
-
getMarketPublicKey,
|
|
38
|
-
getUserAccountPublicKey,
|
|
39
|
-
getUserAccountPublicKeySync,
|
|
40
|
-
} from './addresses/pda';
|
|
41
|
-
import {
|
|
42
|
-
ClearingHouseAccountSubscriber,
|
|
43
|
-
ClearingHouseAccountEvents,
|
|
44
|
-
DataAndSlot,
|
|
45
|
-
} from './accounts/types';
|
|
46
|
-
import { TxSender } from './tx/types';
|
|
47
|
-
import { wrapInTx } from './tx/utils';
|
|
48
|
-
import { QUOTE_ASSET_BANK_INDEX, ZERO } from './constants/numericConstants';
|
|
49
|
-
import { findDirectionToClose, positionIsAvailable } from './math/position';
|
|
50
|
-
import { getTokenAmount } from './math/bankBalance';
|
|
51
|
-
import { DEFAULT_USER_NAME, encodeName } from './userName';
|
|
52
|
-
import { OraclePriceData } from './oracles/types';
|
|
53
|
-
import { ClearingHouseConfig } from './clearingHouseConfig';
|
|
54
|
-
import { PollingClearingHouseAccountSubscriber } from './accounts/pollingClearingHouseAccountSubscriber';
|
|
55
|
-
import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketClearingHouseAccountSubscriber';
|
|
56
|
-
import { RetryTxSender } from './tx/retryTxSender';
|
|
57
|
-
import { ClearingHouseUser } from './clearingHouseUser';
|
|
58
|
-
import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
|
|
59
|
-
import { getMarketsBanksAndOraclesForSubscription } from './config';
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* # ClearingHouse
|
|
63
|
-
* This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
|
|
64
|
-
*/
|
|
65
|
-
export class ClearingHouse {
|
|
66
|
-
connection: Connection;
|
|
67
|
-
wallet: IWallet;
|
|
68
|
-
public program: Program;
|
|
69
|
-
provider: AnchorProvider;
|
|
70
|
-
opts?: ConfirmOptions;
|
|
71
|
-
users = new Map<number, ClearingHouseUser>();
|
|
72
|
-
activeUserId: number;
|
|
73
|
-
userAccountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig;
|
|
74
|
-
accountSubscriber: ClearingHouseAccountSubscriber;
|
|
75
|
-
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
76
|
-
_isSubscribed = false;
|
|
77
|
-
txSender: TxSender;
|
|
78
|
-
marketLastSlotCache = new Map<number, number>();
|
|
79
|
-
|
|
80
|
-
public get isSubscribed() {
|
|
81
|
-
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public set isSubscribed(val: boolean) {
|
|
85
|
-
this._isSubscribed = val;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public constructor(config: ClearingHouseConfig) {
|
|
89
|
-
this.connection = config.connection;
|
|
90
|
-
this.wallet = config.wallet;
|
|
91
|
-
this.opts = config.opts || AnchorProvider.defaultOptions();
|
|
92
|
-
this.provider = new AnchorProvider(
|
|
93
|
-
config.connection,
|
|
94
|
-
config.wallet,
|
|
95
|
-
this.opts
|
|
96
|
-
);
|
|
97
|
-
this.program = new Program(
|
|
98
|
-
clearingHouseIDL as Idl,
|
|
99
|
-
config.programID,
|
|
100
|
-
this.provider
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const userIds = config.userIds ?? [0];
|
|
104
|
-
this.activeUserId = config.activeUserId ?? userIds[0];
|
|
105
|
-
this.userAccountSubscriptionConfig =
|
|
106
|
-
config.accountSubscription?.type === 'polling'
|
|
107
|
-
? {
|
|
108
|
-
type: 'polling',
|
|
109
|
-
accountLoader: config.accountSubscription.accountLoader,
|
|
110
|
-
}
|
|
111
|
-
: {
|
|
112
|
-
type: 'websocket',
|
|
113
|
-
};
|
|
114
|
-
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
115
|
-
|
|
116
|
-
let marketIndexes = config.marketIndexes;
|
|
117
|
-
let bankIndexes = config.bankIndexes;
|
|
118
|
-
let oracleInfos = config.oracleInfos;
|
|
119
|
-
if (config.env) {
|
|
120
|
-
const {
|
|
121
|
-
marketIndexes: envMarketIndexes,
|
|
122
|
-
bankIndexes: envBankIndexes,
|
|
123
|
-
oracleInfos: envOralceInfos,
|
|
124
|
-
} = getMarketsBanksAndOraclesForSubscription(config.env);
|
|
125
|
-
marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
|
|
126
|
-
bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
|
|
127
|
-
oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (config.accountSubscription?.type === 'polling') {
|
|
131
|
-
this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
|
|
132
|
-
this.program,
|
|
133
|
-
config.accountSubscription.accountLoader,
|
|
134
|
-
marketIndexes ?? [],
|
|
135
|
-
bankIndexes ?? [],
|
|
136
|
-
oracleInfos ?? []
|
|
137
|
-
);
|
|
138
|
-
} else {
|
|
139
|
-
this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
|
|
140
|
-
this.program,
|
|
141
|
-
config.marketIndexes ?? [],
|
|
142
|
-
config.bankIndexes ?? [],
|
|
143
|
-
config.oracleInfos ?? []
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
147
|
-
this.txSender = new RetryTxSender(
|
|
148
|
-
this.provider,
|
|
149
|
-
config.txSenderConfig?.timeout,
|
|
150
|
-
config.txSenderConfig?.retrySleep,
|
|
151
|
-
config.txSenderConfig?.additionalConnections
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
createUsers(
|
|
156
|
-
userIds: number[],
|
|
157
|
-
accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
|
|
158
|
-
): void {
|
|
159
|
-
for (const userId of userIds) {
|
|
160
|
-
const user = this.createUser(userId, accountSubscriptionConfig);
|
|
161
|
-
this.users.set(userId, user);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
createUser(
|
|
166
|
-
userId: number,
|
|
167
|
-
accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
|
|
168
|
-
): ClearingHouseUser {
|
|
169
|
-
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
170
|
-
this.program.programId,
|
|
171
|
-
this.wallet.publicKey,
|
|
172
|
-
userId
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
return new ClearingHouseUser({
|
|
176
|
-
clearingHouse: this,
|
|
177
|
-
userAccountPublicKey,
|
|
178
|
-
accountSubscription: accountSubscriptionConfig,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
public async subscribe(): Promise<boolean> {
|
|
183
|
-
const subscribePromises = this.subscribeUsers().concat(
|
|
184
|
-
this.accountSubscriber.subscribe()
|
|
185
|
-
);
|
|
186
|
-
this.isSubscribed = (await Promise.all(subscribePromises)).reduce(
|
|
187
|
-
(success, prevSuccess) => success && prevSuccess
|
|
188
|
-
);
|
|
189
|
-
return this.isSubscribed;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
subscribeUsers(): Promise<boolean>[] {
|
|
193
|
-
return [...this.users.values()].map((user) => user.subscribe());
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Forces the accountSubscriber to fetch account updates from rpc
|
|
198
|
-
*/
|
|
199
|
-
public async fetchAccounts(): Promise<void> {
|
|
200
|
-
await Promise.all(
|
|
201
|
-
[...this.users.values()]
|
|
202
|
-
.map((user) => user.fetchAccounts())
|
|
203
|
-
.concat(this.accountSubscriber.fetch())
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
public async unsubscribe(): Promise<void> {
|
|
208
|
-
const unsubscribePromises = this.unsubscribeUsers().concat(
|
|
209
|
-
this.accountSubscriber.unsubscribe()
|
|
210
|
-
);
|
|
211
|
-
await Promise.all(unsubscribePromises);
|
|
212
|
-
this.isSubscribed = false;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
unsubscribeUsers(): Promise<void>[] {
|
|
216
|
-
return [...this.users.values()].map((user) => user.unsubscribe());
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
statePublicKey?: PublicKey;
|
|
220
|
-
public async getStatePublicKey(): Promise<PublicKey> {
|
|
221
|
-
if (this.statePublicKey) {
|
|
222
|
-
return this.statePublicKey;
|
|
223
|
-
}
|
|
224
|
-
this.statePublicKey = await getClearingHouseStateAccountPublicKey(
|
|
225
|
-
this.program.programId
|
|
226
|
-
);
|
|
227
|
-
return this.statePublicKey;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
public getStateAccount(): StateAccount {
|
|
231
|
-
return this.accountSubscriber.getStateAccountAndSlot().data;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
|
|
235
|
-
marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
236
|
-
return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
public getMarketAccounts(): MarketAccount[] {
|
|
240
|
-
return this.accountSubscriber
|
|
241
|
-
.getMarketAccountsAndSlots()
|
|
242
|
-
.map((value) => value.data);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
|
|
246
|
-
bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
247
|
-
return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
public getQuoteAssetBankAccount(): BankAccount {
|
|
251
|
-
return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
|
|
252
|
-
.data;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
public getOraclePriceDataAndSlot(
|
|
256
|
-
oraclePublicKey: PublicKey
|
|
257
|
-
): DataAndSlot<OraclePriceData> | undefined {
|
|
258
|
-
return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Update the wallet to use for clearing house transactions and linked user account
|
|
263
|
-
* @param newWallet
|
|
264
|
-
* @param userIds
|
|
265
|
-
* @param activeUserId
|
|
266
|
-
*/
|
|
267
|
-
public async updateWallet(
|
|
268
|
-
newWallet: IWallet,
|
|
269
|
-
userIds = [0],
|
|
270
|
-
activeUserId = 0
|
|
271
|
-
): Promise<void> {
|
|
272
|
-
const newProvider = new AnchorProvider(
|
|
273
|
-
this.connection,
|
|
274
|
-
newWallet,
|
|
275
|
-
this.opts
|
|
276
|
-
);
|
|
277
|
-
const newProgram = new Program(
|
|
278
|
-
clearingHouseIDL as Idl,
|
|
279
|
-
this.program.programId,
|
|
280
|
-
newProvider
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
// Update provider for txSender with new wallet details
|
|
284
|
-
this.txSender.provider = newProvider;
|
|
285
|
-
|
|
286
|
-
this.wallet = newWallet;
|
|
287
|
-
this.provider = newProvider;
|
|
288
|
-
this.program = newProgram;
|
|
289
|
-
|
|
290
|
-
if (this.isSubscribed) {
|
|
291
|
-
await Promise.all(this.unsubscribeUsers());
|
|
292
|
-
}
|
|
293
|
-
this.users.clear();
|
|
294
|
-
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
295
|
-
if (this.isSubscribed) {
|
|
296
|
-
await Promise.all(this.subscribeUsers());
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
this.activeUserId = activeUserId;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
public async switchActiveUser(userId: number): Promise<void> {
|
|
303
|
-
this.activeUserId = userId;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
public async addUser(userId: number): Promise<void> {
|
|
307
|
-
if (this.users.has(userId)) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const user = this.createUser(userId, this.userAccountSubscriptionConfig);
|
|
312
|
-
await user.subscribe();
|
|
313
|
-
this.users.set(userId, user);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
public async initializeUserAccount(
|
|
317
|
-
userId = 0,
|
|
318
|
-
name = DEFAULT_USER_NAME
|
|
319
|
-
): Promise<[TransactionSignature, PublicKey]> {
|
|
320
|
-
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
321
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
322
|
-
|
|
323
|
-
const tx = new Transaction().add(initializeUserAccountIx);
|
|
324
|
-
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
325
|
-
return [txSig, userAccountPublicKey];
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
async getInitializeUserInstructions(
|
|
329
|
-
userId = 0,
|
|
330
|
-
name = DEFAULT_USER_NAME
|
|
331
|
-
): Promise<[PublicKey, TransactionInstruction]> {
|
|
332
|
-
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
333
|
-
this.program.programId,
|
|
334
|
-
this.wallet.publicKey,
|
|
335
|
-
userId
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
const nameBuffer = encodeName(name);
|
|
339
|
-
const initializeUserAccountIx =
|
|
340
|
-
await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
341
|
-
accounts: {
|
|
342
|
-
user: userAccountPublicKey,
|
|
343
|
-
authority: this.wallet.publicKey,
|
|
344
|
-
payer: this.wallet.publicKey,
|
|
345
|
-
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
346
|
-
systemProgram: anchor.web3.SystemProgram.programId,
|
|
347
|
-
state: await this.getStatePublicKey(),
|
|
348
|
-
},
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
return [userAccountPublicKey, initializeUserAccountIx];
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
public getUser(userId?: number): ClearingHouseUser {
|
|
355
|
-
userId = userId ?? this.activeUserId;
|
|
356
|
-
if (!this.users.has(userId)) {
|
|
357
|
-
throw new Error(`Clearing House has no user for user id ${userId}`);
|
|
358
|
-
}
|
|
359
|
-
return this.users.get(userId);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
public getUsers(): ClearingHouseUser[] {
|
|
363
|
-
return [...this.users.values()];
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
367
|
-
return this.getUser().userAccountPublicKey;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
public getUserAccount(userId?: number): UserAccount | undefined {
|
|
371
|
-
return this.getUser(userId).getUserAccount();
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
public getUserAccountAndSlot(
|
|
375
|
-
userId?: number
|
|
376
|
-
): DataAndSlot<UserAccount> | undefined {
|
|
377
|
-
return this.getUser(userId).getUserAccountAndSlot();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
public getUserBankBalance(
|
|
381
|
-
bankIndex: number | BN
|
|
382
|
-
): UserBankBalance | undefined {
|
|
383
|
-
const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
384
|
-
return this.getUserAccount().bankBalances.find((bankBalance) =>
|
|
385
|
-
bankBalance.bankIndex.eq(bankIndexBN)
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
public getQuoteAssetTokenAmount(): BN {
|
|
390
|
-
const bank = this.getBankAccount(QUOTE_ASSET_BANK_INDEX);
|
|
391
|
-
const userBankBalance = this.getUserBankBalance(QUOTE_ASSET_BANK_INDEX);
|
|
392
|
-
return getTokenAmount(
|
|
393
|
-
userBankBalance.balance,
|
|
394
|
-
bank,
|
|
395
|
-
userBankBalance.balanceType
|
|
396
|
-
);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
getRemainingAccounts(params: {
|
|
400
|
-
writableMarketIndex?: BN;
|
|
401
|
-
writableBankIndex?: BN;
|
|
402
|
-
}): AccountMeta[] {
|
|
403
|
-
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
404
|
-
if (!userAccountAndSlot) {
|
|
405
|
-
throw Error(
|
|
406
|
-
'No user account found. Most likely user account does not exist or failed to fetch account'
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
const { data: userAccount, slot: lastUserPositionsSlot } =
|
|
410
|
-
userAccountAndSlot;
|
|
411
|
-
|
|
412
|
-
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
413
|
-
const bankAccountMap = new Map<number, AccountMeta>();
|
|
414
|
-
const marketAccountMap = new Map<number, AccountMeta>();
|
|
415
|
-
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
416
|
-
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
417
|
-
// otherwise remove from slot
|
|
418
|
-
if (slot > lastUserPositionsSlot) {
|
|
419
|
-
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
420
|
-
marketAccountMap.set(marketIndexNum, {
|
|
421
|
-
pubkey: marketAccount.pubkey,
|
|
422
|
-
isSigner: false,
|
|
423
|
-
isWritable: false,
|
|
424
|
-
});
|
|
425
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
426
|
-
pubkey: marketAccount.amm.oracle,
|
|
427
|
-
isSigner: false,
|
|
428
|
-
isWritable: false,
|
|
429
|
-
});
|
|
430
|
-
} else {
|
|
431
|
-
this.marketLastSlotCache.delete(marketIndexNum);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
for (const position of userAccount.positions) {
|
|
436
|
-
if (!positionIsAvailable(position)) {
|
|
437
|
-
const marketIndexNum = position.marketIndex.toNumber();
|
|
438
|
-
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
439
|
-
marketAccountMap.set(marketIndexNum, {
|
|
440
|
-
pubkey: marketAccount.pubkey,
|
|
441
|
-
isSigner: false,
|
|
442
|
-
// isWritable: false, // TODO
|
|
443
|
-
isWritable: true,
|
|
444
|
-
});
|
|
445
|
-
oracleAccountMap.set(marketAccount.pubkey.toString(), {
|
|
446
|
-
pubkey: marketAccount.amm.oracle,
|
|
447
|
-
isSigner: false,
|
|
448
|
-
isWritable: false,
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (params.writableMarketIndex) {
|
|
454
|
-
const marketAccount = this.getMarketAccount(
|
|
455
|
-
params.writableMarketIndex.toNumber()
|
|
456
|
-
);
|
|
457
|
-
marketAccountMap.set(params.writableMarketIndex.toNumber(), {
|
|
458
|
-
pubkey: marketAccount.pubkey,
|
|
459
|
-
isSigner: false,
|
|
460
|
-
isWritable: true,
|
|
461
|
-
});
|
|
462
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
463
|
-
pubkey: marketAccount.amm.oracle,
|
|
464
|
-
isSigner: false,
|
|
465
|
-
isWritable: false,
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
for (const userBankBalance of userAccount.bankBalances) {
|
|
470
|
-
if (!userBankBalance.balance.eq(ZERO)) {
|
|
471
|
-
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
472
|
-
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
473
|
-
pubkey: bankAccount.pubkey,
|
|
474
|
-
isSigner: false,
|
|
475
|
-
isWritable: false,
|
|
476
|
-
});
|
|
477
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
478
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
479
|
-
pubkey: bankAccount.oracle,
|
|
480
|
-
isSigner: false,
|
|
481
|
-
isWritable: false,
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
if (params.writableBankIndex) {
|
|
488
|
-
const bankAccount = this.getBankAccount(params.writableBankIndex);
|
|
489
|
-
bankAccountMap.set(params.writableBankIndex.toNumber(), {
|
|
490
|
-
pubkey: bankAccount.pubkey,
|
|
491
|
-
isSigner: false,
|
|
492
|
-
isWritable: true,
|
|
493
|
-
});
|
|
494
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
495
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
496
|
-
pubkey: bankAccount.oracle,
|
|
497
|
-
isSigner: false,
|
|
498
|
-
isWritable: false,
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
return [
|
|
504
|
-
...oracleAccountMap.values(),
|
|
505
|
-
...bankAccountMap.values(),
|
|
506
|
-
...marketAccountMap.values(),
|
|
507
|
-
];
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
public getOrder(orderId: BN | number): Order | undefined {
|
|
511
|
-
const orderIdBN = orderId instanceof BN ? orderId : new BN(orderId);
|
|
512
|
-
return this.getUserAccount()?.orders.find((order) =>
|
|
513
|
-
order.orderId.eq(orderIdBN)
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
public getOrderByUserId(userOrderId: number): Order | undefined {
|
|
518
|
-
return this.getUserAccount()?.orders.find(
|
|
519
|
-
(order) => order.userOrderId === userOrderId
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
public async deposit(
|
|
524
|
-
amount: BN,
|
|
525
|
-
bankIndex: BN,
|
|
526
|
-
collateralAccountPublicKey: PublicKey,
|
|
527
|
-
userId?: number,
|
|
528
|
-
reduceOnly = false
|
|
529
|
-
): Promise<TransactionSignature> {
|
|
530
|
-
const depositCollateralIx = await this.getDepositInstruction(
|
|
531
|
-
amount,
|
|
532
|
-
bankIndex,
|
|
533
|
-
collateralAccountPublicKey,
|
|
534
|
-
userId,
|
|
535
|
-
reduceOnly,
|
|
536
|
-
true
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
const tx = new Transaction().add(depositCollateralIx);
|
|
540
|
-
|
|
541
|
-
const { txSig } = await this.txSender.send(tx);
|
|
542
|
-
return txSig;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
async getDepositInstruction(
|
|
546
|
-
amount: BN,
|
|
547
|
-
bankIndex: BN,
|
|
548
|
-
userTokenAccount: PublicKey,
|
|
549
|
-
userId?: number,
|
|
550
|
-
reduceOnly = false,
|
|
551
|
-
userInitialized = true
|
|
552
|
-
): Promise<TransactionInstruction> {
|
|
553
|
-
const userAccountPublicKey = userId
|
|
554
|
-
? await getUserAccountPublicKey(
|
|
555
|
-
this.program.programId,
|
|
556
|
-
this.wallet.publicKey,
|
|
557
|
-
userId
|
|
558
|
-
)
|
|
559
|
-
: await this.getUserAccountPublicKey();
|
|
560
|
-
|
|
561
|
-
let remainingAccounts = [];
|
|
562
|
-
if (userInitialized) {
|
|
563
|
-
remainingAccounts = this.getRemainingAccounts({
|
|
564
|
-
writableBankIndex: bankIndex,
|
|
565
|
-
});
|
|
566
|
-
} else {
|
|
567
|
-
const bankAccount = this.getBankAccount(bankIndex);
|
|
568
|
-
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
569
|
-
remainingAccounts.push({
|
|
570
|
-
pubkey: bankAccount.oracle,
|
|
571
|
-
isSigner: false,
|
|
572
|
-
isWritable: false,
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
remainingAccounts.push({
|
|
576
|
-
pubkey: bankAccount.pubkey,
|
|
577
|
-
isSigner: false,
|
|
578
|
-
isWritable: true,
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const bank = this.getBankAccount(bankIndex);
|
|
583
|
-
|
|
584
|
-
return await this.program.instruction.deposit(
|
|
585
|
-
bankIndex,
|
|
586
|
-
amount,
|
|
587
|
-
reduceOnly,
|
|
588
|
-
{
|
|
589
|
-
accounts: {
|
|
590
|
-
state: await this.getStatePublicKey(),
|
|
591
|
-
bank: bank.pubkey,
|
|
592
|
-
bankVault: bank.vault,
|
|
593
|
-
user: userAccountPublicKey,
|
|
594
|
-
userTokenAccount: userTokenAccount,
|
|
595
|
-
authority: this.wallet.publicKey,
|
|
596
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
597
|
-
},
|
|
598
|
-
remainingAccounts,
|
|
599
|
-
}
|
|
600
|
-
);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/**
|
|
604
|
-
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
605
|
-
* @param userId
|
|
606
|
-
* @param name
|
|
607
|
-
* @param amount
|
|
608
|
-
* @param userTokenAccount
|
|
609
|
-
* @param fromUserId
|
|
610
|
-
* @returns
|
|
611
|
-
*/
|
|
612
|
-
public async initializeUserAccountAndDepositCollateral(
|
|
613
|
-
amount: BN,
|
|
614
|
-
userTokenAccount: PublicKey,
|
|
615
|
-
bankIndex = new BN(0),
|
|
616
|
-
userId = 0,
|
|
617
|
-
name = DEFAULT_USER_NAME,
|
|
618
|
-
fromUserId?: number
|
|
619
|
-
): Promise<[TransactionSignature, PublicKey]> {
|
|
620
|
-
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
621
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
622
|
-
|
|
623
|
-
const depositCollateralIx =
|
|
624
|
-
fromUserId != null
|
|
625
|
-
? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
|
|
626
|
-
: await this.getDepositInstruction(
|
|
627
|
-
amount,
|
|
628
|
-
bankIndex,
|
|
629
|
-
userTokenAccount,
|
|
630
|
-
userId,
|
|
631
|
-
false,
|
|
632
|
-
false
|
|
633
|
-
);
|
|
634
|
-
|
|
635
|
-
const tx = new Transaction()
|
|
636
|
-
.add(initializeUserAccountIx)
|
|
637
|
-
.add(depositCollateralIx);
|
|
638
|
-
|
|
639
|
-
const { txSig } = await this.txSender.send(tx, []);
|
|
640
|
-
|
|
641
|
-
return [txSig, userAccountPublicKey];
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
public async initializeUserAccountForDevnet(
|
|
645
|
-
userId = 0,
|
|
646
|
-
name = DEFAULT_USER_NAME,
|
|
647
|
-
bankIndex: BN,
|
|
648
|
-
tokenFaucet: TokenFaucet,
|
|
649
|
-
amount: BN
|
|
650
|
-
): Promise<[TransactionSignature, PublicKey]> {
|
|
651
|
-
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] =
|
|
652
|
-
await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(
|
|
653
|
-
this.wallet.publicKey,
|
|
654
|
-
amount
|
|
655
|
-
);
|
|
656
|
-
|
|
657
|
-
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
658
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
659
|
-
|
|
660
|
-
const depositCollateralIx = await this.getDepositInstruction(
|
|
661
|
-
amount,
|
|
662
|
-
bankIndex,
|
|
663
|
-
associateTokenPublicKey,
|
|
664
|
-
userId,
|
|
665
|
-
false,
|
|
666
|
-
false
|
|
667
|
-
);
|
|
668
|
-
|
|
669
|
-
const tx = new Transaction()
|
|
670
|
-
.add(createAssociatedAccountIx)
|
|
671
|
-
.add(mintToIx)
|
|
672
|
-
.add(initializeUserAccountIx)
|
|
673
|
-
.add(depositCollateralIx);
|
|
674
|
-
|
|
675
|
-
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
676
|
-
|
|
677
|
-
return [txSig, userAccountPublicKey];
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
public async withdraw(
|
|
681
|
-
amount: BN,
|
|
682
|
-
bankIndex: BN,
|
|
683
|
-
userTokenAccount: PublicKey,
|
|
684
|
-
reduceOnly = false
|
|
685
|
-
): Promise<TransactionSignature> {
|
|
686
|
-
const { txSig } = await this.txSender.send(
|
|
687
|
-
wrapInTx(
|
|
688
|
-
await this.getWithdrawIx(
|
|
689
|
-
amount,
|
|
690
|
-
bankIndex,
|
|
691
|
-
userTokenAccount,
|
|
692
|
-
reduceOnly
|
|
693
|
-
)
|
|
694
|
-
),
|
|
695
|
-
[],
|
|
696
|
-
this.opts
|
|
697
|
-
);
|
|
698
|
-
return txSig;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
public async getWithdrawIx(
|
|
702
|
-
amount: BN,
|
|
703
|
-
bankIndex: BN,
|
|
704
|
-
userTokenAccount: PublicKey,
|
|
705
|
-
reduceOnly = false
|
|
706
|
-
): Promise<TransactionInstruction> {
|
|
707
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
708
|
-
|
|
709
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
710
|
-
writableBankIndex: bankIndex,
|
|
711
|
-
});
|
|
712
|
-
|
|
713
|
-
const bank = this.getBankAccount(bankIndex);
|
|
714
|
-
|
|
715
|
-
return await this.program.instruction.withdraw(
|
|
716
|
-
bankIndex,
|
|
717
|
-
amount,
|
|
718
|
-
reduceOnly,
|
|
719
|
-
{
|
|
720
|
-
accounts: {
|
|
721
|
-
state: await this.getStatePublicKey(),
|
|
722
|
-
bank: bank.pubkey,
|
|
723
|
-
bankVault: bank.vault,
|
|
724
|
-
bankVaultAuthority: bank.vaultAuthority,
|
|
725
|
-
user: userAccountPublicKey,
|
|
726
|
-
userTokenAccount: userTokenAccount,
|
|
727
|
-
authority: this.wallet.publicKey,
|
|
728
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
729
|
-
},
|
|
730
|
-
remainingAccounts,
|
|
731
|
-
}
|
|
732
|
-
);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
public async transferDeposit(
|
|
736
|
-
amount: BN,
|
|
737
|
-
bankIndex: BN,
|
|
738
|
-
fromUserId: number,
|
|
739
|
-
toUserId: number
|
|
740
|
-
): Promise<TransactionSignature> {
|
|
741
|
-
const { txSig } = await this.txSender.send(
|
|
742
|
-
wrapInTx(
|
|
743
|
-
await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
|
|
744
|
-
),
|
|
745
|
-
[],
|
|
746
|
-
this.opts
|
|
747
|
-
);
|
|
748
|
-
return txSig;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
public async getTransferDepositIx(
|
|
752
|
-
amount: BN,
|
|
753
|
-
bankIndex: BN,
|
|
754
|
-
fromUserId: number,
|
|
755
|
-
toUserId: number
|
|
756
|
-
): Promise<TransactionInstruction> {
|
|
757
|
-
const fromUser = await getUserAccountPublicKey(
|
|
758
|
-
this.program.programId,
|
|
759
|
-
this.wallet.publicKey,
|
|
760
|
-
fromUserId
|
|
761
|
-
);
|
|
762
|
-
const toUser = await getUserAccountPublicKey(
|
|
763
|
-
this.program.programId,
|
|
764
|
-
this.wallet.publicKey,
|
|
765
|
-
toUserId
|
|
766
|
-
);
|
|
767
|
-
|
|
768
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
769
|
-
writableBankIndex: bankIndex,
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
return await this.program.instruction.transferDeposit(bankIndex, amount, {
|
|
773
|
-
accounts: {
|
|
774
|
-
authority: this.wallet.publicKey,
|
|
775
|
-
fromUser,
|
|
776
|
-
toUser,
|
|
777
|
-
state: await this.getStatePublicKey(),
|
|
778
|
-
},
|
|
779
|
-
remainingAccounts,
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
public async updateBankCumulativeInterest(
|
|
784
|
-
bankIndex: BN
|
|
785
|
-
): Promise<TransactionSignature> {
|
|
786
|
-
const { txSig } = await this.txSender.send(
|
|
787
|
-
wrapInTx(await this.updateBankCumulativeInterestIx(bankIndex)),
|
|
788
|
-
[],
|
|
789
|
-
this.opts
|
|
790
|
-
);
|
|
791
|
-
return txSig;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
public async updateBankCumulativeInterestIx(
|
|
795
|
-
bankIndex: BN
|
|
796
|
-
): Promise<TransactionInstruction> {
|
|
797
|
-
const bank = this.getBankAccount(bankIndex);
|
|
798
|
-
return await this.program.instruction.updateBankCumulativeInterest({
|
|
799
|
-
accounts: {
|
|
800
|
-
bank: bank.pubkey,
|
|
801
|
-
},
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
public async openPosition(
|
|
806
|
-
direction: PositionDirection,
|
|
807
|
-
amount: BN,
|
|
808
|
-
marketIndex: BN,
|
|
809
|
-
limitPrice?: BN
|
|
810
|
-
): Promise<TransactionSignature> {
|
|
811
|
-
return await this.placeAndTake({
|
|
812
|
-
orderType: OrderType.MARKET,
|
|
813
|
-
marketIndex,
|
|
814
|
-
direction,
|
|
815
|
-
baseAssetAmount: amount,
|
|
816
|
-
price: limitPrice,
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
public async placeOrder(
|
|
821
|
-
orderParams: OptionalOrderParams
|
|
822
|
-
): Promise<TransactionSignature> {
|
|
823
|
-
const { txSig, slot } = await this.txSender.send(
|
|
824
|
-
wrapInTx(await this.getPlaceOrderIx(orderParams)),
|
|
825
|
-
[],
|
|
826
|
-
this.opts
|
|
827
|
-
);
|
|
828
|
-
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
829
|
-
return txSig;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
getOrderParams(optionalOrderParams: OptionalOrderParams): OrderParams {
|
|
833
|
-
return Object.assign({}, DefaultOrderParams, optionalOrderParams);
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
public async getPlaceOrderIx(
|
|
837
|
-
orderParams: OptionalOrderParams
|
|
838
|
-
): Promise<TransactionInstruction> {
|
|
839
|
-
orderParams = this.getOrderParams(orderParams);
|
|
840
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
841
|
-
|
|
842
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
843
|
-
writableMarketIndex: orderParams.marketIndex,
|
|
844
|
-
});
|
|
845
|
-
|
|
846
|
-
return await this.program.instruction.placeOrder(orderParams, {
|
|
847
|
-
accounts: {
|
|
848
|
-
state: await this.getStatePublicKey(),
|
|
849
|
-
user: userAccountPublicKey,
|
|
850
|
-
authority: this.wallet.publicKey,
|
|
851
|
-
},
|
|
852
|
-
remainingAccounts,
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
public async updateAMMs(marketIndexes: BN[]): Promise<TransactionSignature> {
|
|
857
|
-
const { txSig } = await this.txSender.send(
|
|
858
|
-
wrapInTx(await this.getUpdateAMMsIx(marketIndexes)),
|
|
859
|
-
[],
|
|
860
|
-
this.opts
|
|
861
|
-
);
|
|
862
|
-
return txSig;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
public async getUpdateAMMsIx(
|
|
866
|
-
marketIndexes: BN[]
|
|
867
|
-
): Promise<TransactionInstruction> {
|
|
868
|
-
for (let i = marketIndexes.length; i < 5; i++) {
|
|
869
|
-
marketIndexes.push(new BN(100));
|
|
870
|
-
}
|
|
871
|
-
const marketAccountInfos = [];
|
|
872
|
-
const oracleAccountInfos = [];
|
|
873
|
-
for (const marketIndex of marketIndexes) {
|
|
874
|
-
if (!marketIndex.eq(new BN(100))) {
|
|
875
|
-
const market = this.getMarketAccount(marketIndex);
|
|
876
|
-
marketAccountInfos.push({
|
|
877
|
-
pubkey: market.pubkey,
|
|
878
|
-
isWritable: true,
|
|
879
|
-
isSigner: false,
|
|
880
|
-
});
|
|
881
|
-
oracleAccountInfos.push({
|
|
882
|
-
pubkey: market.amm.oracle,
|
|
883
|
-
isWritable: false,
|
|
884
|
-
isSigner: false,
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
const remainingAccounts = oracleAccountInfos.concat(marketAccountInfos);
|
|
889
|
-
|
|
890
|
-
return await this.program.instruction.updateAmms(marketIndexes, {
|
|
891
|
-
accounts: {
|
|
892
|
-
state: await this.getStatePublicKey(),
|
|
893
|
-
authority: this.wallet.publicKey,
|
|
894
|
-
},
|
|
895
|
-
remainingAccounts,
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
|
|
900
|
-
const { txSig } = await this.txSender.send(
|
|
901
|
-
wrapInTx(await this.getCancelOrderIx(orderId)),
|
|
902
|
-
[],
|
|
903
|
-
this.opts
|
|
904
|
-
);
|
|
905
|
-
return txSig;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
public async getCancelOrderIx(orderId?: BN): Promise<TransactionInstruction> {
|
|
909
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
910
|
-
|
|
911
|
-
const remainingAccounts = this.getRemainingAccounts({});
|
|
912
|
-
|
|
913
|
-
return await this.program.instruction.cancelOrder(orderId ?? null, {
|
|
914
|
-
accounts: {
|
|
915
|
-
state: await this.getStatePublicKey(),
|
|
916
|
-
user: userAccountPublicKey,
|
|
917
|
-
authority: this.wallet.publicKey,
|
|
918
|
-
},
|
|
919
|
-
remainingAccounts,
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
public async cancelOrderByUserId(
|
|
924
|
-
userOrderId: number
|
|
925
|
-
): Promise<TransactionSignature> {
|
|
926
|
-
const { txSig } = await this.txSender.send(
|
|
927
|
-
wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId)),
|
|
928
|
-
[],
|
|
929
|
-
this.opts
|
|
930
|
-
);
|
|
931
|
-
return txSig;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
public async getCancelOrderByUserIdIx(
|
|
935
|
-
userOrderId: number
|
|
936
|
-
): Promise<TransactionInstruction> {
|
|
937
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
938
|
-
|
|
939
|
-
const order = this.getOrderByUserId(userOrderId);
|
|
940
|
-
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
941
|
-
|
|
942
|
-
const remainingAccounts = this.getRemainingAccounts({});
|
|
943
|
-
|
|
944
|
-
return await this.program.instruction.cancelOrderByUserId(userOrderId, {
|
|
945
|
-
accounts: {
|
|
946
|
-
state: await this.getStatePublicKey(),
|
|
947
|
-
user: userAccountPublicKey,
|
|
948
|
-
authority: this.wallet.publicKey,
|
|
949
|
-
oracle,
|
|
950
|
-
},
|
|
951
|
-
remainingAccounts,
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
public async fillOrder(
|
|
956
|
-
userAccountPublicKey: PublicKey,
|
|
957
|
-
user: UserAccount,
|
|
958
|
-
order?: Order,
|
|
959
|
-
makerInfo?: MakerInfo
|
|
960
|
-
): Promise<TransactionSignature> {
|
|
961
|
-
const { txSig } = await this.txSender.send(
|
|
962
|
-
wrapInTx(
|
|
963
|
-
await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
|
|
964
|
-
),
|
|
965
|
-
[],
|
|
966
|
-
this.opts
|
|
967
|
-
);
|
|
968
|
-
return txSig;
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
public async getFillOrderIx(
|
|
972
|
-
userAccountPublicKey: PublicKey,
|
|
973
|
-
userAccount: UserAccount,
|
|
974
|
-
order: Order,
|
|
975
|
-
makerInfo?: MakerInfo
|
|
976
|
-
): Promise<TransactionInstruction> {
|
|
977
|
-
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
978
|
-
|
|
979
|
-
const marketIndex = order.marketIndex;
|
|
980
|
-
const marketAccount = this.getMarketAccount(marketIndex);
|
|
981
|
-
|
|
982
|
-
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
983
|
-
const bankAccountMap = new Map<number, AccountMeta>();
|
|
984
|
-
const marketAccountMap = new Map<number, AccountMeta>();
|
|
985
|
-
|
|
986
|
-
marketAccountMap.set(marketIndex.toNumber(), {
|
|
987
|
-
pubkey: marketAccount.pubkey,
|
|
988
|
-
isWritable: true,
|
|
989
|
-
isSigner: false,
|
|
990
|
-
});
|
|
991
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
992
|
-
pubkey: marketAccount.amm.oracle,
|
|
993
|
-
isWritable: false,
|
|
994
|
-
isSigner: false,
|
|
995
|
-
});
|
|
996
|
-
|
|
997
|
-
for (const bankBalance of userAccount.bankBalances) {
|
|
998
|
-
if (!bankBalance.balance.eq(ZERO)) {
|
|
999
|
-
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1000
|
-
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1001
|
-
pubkey: bankAccount.pubkey,
|
|
1002
|
-
isSigner: false,
|
|
1003
|
-
isWritable: true,
|
|
1004
|
-
});
|
|
1005
|
-
|
|
1006
|
-
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
1007
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1008
|
-
pubkey: bankAccount.oracle,
|
|
1009
|
-
isSigner: false,
|
|
1010
|
-
isWritable: false,
|
|
1011
|
-
});
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
for (const position of userAccount.positions) {
|
|
1017
|
-
if (
|
|
1018
|
-
!positionIsAvailable(position) &&
|
|
1019
|
-
!position.marketIndex.eq(order.marketIndex)
|
|
1020
|
-
) {
|
|
1021
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1022
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1023
|
-
pubkey: market.pubkey,
|
|
1024
|
-
isWritable: true,
|
|
1025
|
-
isSigner: false,
|
|
1026
|
-
});
|
|
1027
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1028
|
-
pubkey: market.amm.oracle,
|
|
1029
|
-
isWritable: false,
|
|
1030
|
-
isSigner: false,
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
const remainingAccounts = [
|
|
1036
|
-
...oracleAccountMap.values(),
|
|
1037
|
-
...bankAccountMap.values(),
|
|
1038
|
-
...marketAccountMap.values(),
|
|
1039
|
-
];
|
|
1040
|
-
|
|
1041
|
-
if (makerInfo) {
|
|
1042
|
-
remainingAccounts.push({
|
|
1043
|
-
pubkey: makerInfo.maker,
|
|
1044
|
-
isWritable: true,
|
|
1045
|
-
isSigner: false,
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const orderId = order.orderId;
|
|
1050
|
-
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1051
|
-
|
|
1052
|
-
return await this.program.instruction.fillOrder(orderId, makerOrderId, {
|
|
1053
|
-
accounts: {
|
|
1054
|
-
state: await this.getStatePublicKey(),
|
|
1055
|
-
filler: fillerPublicKey,
|
|
1056
|
-
user: userAccountPublicKey,
|
|
1057
|
-
authority: this.wallet.publicKey,
|
|
1058
|
-
},
|
|
1059
|
-
remainingAccounts,
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
public async triggerOrder(
|
|
1064
|
-
userAccountPublicKey: PublicKey,
|
|
1065
|
-
user: UserAccount,
|
|
1066
|
-
order: Order
|
|
1067
|
-
): Promise<TransactionSignature> {
|
|
1068
|
-
const { txSig } = await this.txSender.send(
|
|
1069
|
-
wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
|
|
1070
|
-
[],
|
|
1071
|
-
this.opts
|
|
1072
|
-
);
|
|
1073
|
-
return txSig;
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
public async getTriggerOrderIx(
|
|
1077
|
-
userAccountPublicKey: PublicKey,
|
|
1078
|
-
userAccount: UserAccount,
|
|
1079
|
-
order: Order
|
|
1080
|
-
): Promise<TransactionInstruction> {
|
|
1081
|
-
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1082
|
-
|
|
1083
|
-
const marketIndex = order.marketIndex;
|
|
1084
|
-
const marketAccount = this.getMarketAccount(marketIndex);
|
|
1085
|
-
|
|
1086
|
-
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1087
|
-
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1088
|
-
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1089
|
-
|
|
1090
|
-
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1091
|
-
pubkey: marketAccount.pubkey,
|
|
1092
|
-
isWritable: true,
|
|
1093
|
-
isSigner: false,
|
|
1094
|
-
});
|
|
1095
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1096
|
-
pubkey: marketAccount.amm.oracle,
|
|
1097
|
-
isWritable: false,
|
|
1098
|
-
isSigner: false,
|
|
1099
|
-
});
|
|
1100
|
-
|
|
1101
|
-
for (const bankBalance of userAccount.bankBalances) {
|
|
1102
|
-
if (!bankBalance.balance.eq(ZERO)) {
|
|
1103
|
-
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1104
|
-
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1105
|
-
pubkey: bankAccount.pubkey,
|
|
1106
|
-
isSigner: false,
|
|
1107
|
-
isWritable: true,
|
|
1108
|
-
});
|
|
1109
|
-
|
|
1110
|
-
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
1111
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1112
|
-
pubkey: bankAccount.oracle,
|
|
1113
|
-
isSigner: false,
|
|
1114
|
-
isWritable: false,
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
for (const position of userAccount.positions) {
|
|
1121
|
-
if (
|
|
1122
|
-
!positionIsAvailable(position) &&
|
|
1123
|
-
!position.marketIndex.eq(order.marketIndex)
|
|
1124
|
-
) {
|
|
1125
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1126
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1127
|
-
pubkey: market.pubkey,
|
|
1128
|
-
isWritable: true,
|
|
1129
|
-
isSigner: false,
|
|
1130
|
-
});
|
|
1131
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1132
|
-
pubkey: market.amm.oracle,
|
|
1133
|
-
isWritable: false,
|
|
1134
|
-
isSigner: false,
|
|
1135
|
-
});
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
const remainingAccounts = [
|
|
1140
|
-
...oracleAccountMap.values(),
|
|
1141
|
-
...bankAccountMap.values(),
|
|
1142
|
-
...marketAccountMap.values(),
|
|
1143
|
-
];
|
|
1144
|
-
|
|
1145
|
-
const orderId = order.orderId;
|
|
1146
|
-
return await this.program.instruction.triggerOrder(orderId, {
|
|
1147
|
-
accounts: {
|
|
1148
|
-
state: await this.getStatePublicKey(),
|
|
1149
|
-
filler: fillerPublicKey,
|
|
1150
|
-
user: userAccountPublicKey,
|
|
1151
|
-
authority: this.wallet.publicKey,
|
|
1152
|
-
},
|
|
1153
|
-
remainingAccounts,
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
public async placeAndTake(
|
|
1158
|
-
orderParams: OptionalOrderParams,
|
|
1159
|
-
makerInfo?: MakerInfo
|
|
1160
|
-
): Promise<TransactionSignature> {
|
|
1161
|
-
const { txSig, slot } = await this.txSender.send(
|
|
1162
|
-
wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
|
|
1163
|
-
[],
|
|
1164
|
-
this.opts
|
|
1165
|
-
);
|
|
1166
|
-
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1167
|
-
return txSig;
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
public async getPlaceAndTakeIx(
|
|
1171
|
-
orderParams: OptionalOrderParams,
|
|
1172
|
-
makerInfo?: MakerInfo
|
|
1173
|
-
): Promise<TransactionInstruction> {
|
|
1174
|
-
orderParams = this.getOrderParams(orderParams);
|
|
1175
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1176
|
-
|
|
1177
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
1178
|
-
writableMarketIndex: orderParams.marketIndex,
|
|
1179
|
-
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1180
|
-
});
|
|
1181
|
-
|
|
1182
|
-
let makerOrderId = null;
|
|
1183
|
-
if (makerInfo) {
|
|
1184
|
-
makerOrderId = makerInfo.order.orderId;
|
|
1185
|
-
remainingAccounts.push({
|
|
1186
|
-
pubkey: makerInfo.maker,
|
|
1187
|
-
isSigner: false,
|
|
1188
|
-
isWritable: true,
|
|
1189
|
-
});
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
return await this.program.instruction.placeAndTake(
|
|
1193
|
-
orderParams,
|
|
1194
|
-
makerOrderId,
|
|
1195
|
-
{
|
|
1196
|
-
accounts: {
|
|
1197
|
-
state: await this.getStatePublicKey(),
|
|
1198
|
-
user: userAccountPublicKey,
|
|
1199
|
-
authority: this.wallet.publicKey,
|
|
1200
|
-
},
|
|
1201
|
-
remainingAccounts,
|
|
1202
|
-
}
|
|
1203
|
-
);
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
public async placeAndMake(
|
|
1207
|
-
orderParams: OptionalOrderParams,
|
|
1208
|
-
takerInfo: TakerInfo
|
|
1209
|
-
): Promise<TransactionSignature> {
|
|
1210
|
-
const { txSig, slot } = await this.txSender.send(
|
|
1211
|
-
wrapInTx(await this.getPlaceAndMakeIx(orderParams, takerInfo)),
|
|
1212
|
-
[],
|
|
1213
|
-
this.opts
|
|
1214
|
-
);
|
|
1215
|
-
|
|
1216
|
-
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1217
|
-
|
|
1218
|
-
return txSig;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
public async getPlaceAndMakeIx(
|
|
1222
|
-
orderParams: OptionalOrderParams,
|
|
1223
|
-
takerInfo: TakerInfo
|
|
1224
|
-
): Promise<TransactionInstruction> {
|
|
1225
|
-
orderParams = this.getOrderParams(orderParams);
|
|
1226
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1227
|
-
|
|
1228
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
1229
|
-
writableMarketIndex: orderParams.marketIndex,
|
|
1230
|
-
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1231
|
-
});
|
|
1232
|
-
|
|
1233
|
-
const takerOrderId = takerInfo!.order!.orderId;
|
|
1234
|
-
remainingAccounts.push({
|
|
1235
|
-
pubkey: takerInfo.taker,
|
|
1236
|
-
isSigner: false,
|
|
1237
|
-
isWritable: true,
|
|
1238
|
-
});
|
|
1239
|
-
|
|
1240
|
-
return await this.program.instruction.placeAndMake(
|
|
1241
|
-
orderParams,
|
|
1242
|
-
takerOrderId,
|
|
1243
|
-
{
|
|
1244
|
-
accounts: {
|
|
1245
|
-
state: await this.getStatePublicKey(),
|
|
1246
|
-
user: userAccountPublicKey,
|
|
1247
|
-
taker: takerInfo.taker,
|
|
1248
|
-
authority: this.wallet.publicKey,
|
|
1249
|
-
},
|
|
1250
|
-
remainingAccounts,
|
|
1251
|
-
}
|
|
1252
|
-
);
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
/**
|
|
1256
|
-
* Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
|
|
1257
|
-
* @param marketIndex
|
|
1258
|
-
* @returns
|
|
1259
|
-
*/
|
|
1260
|
-
public async closePosition(marketIndex: BN): Promise<TransactionSignature> {
|
|
1261
|
-
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
1262
|
-
if (!userPosition) {
|
|
1263
|
-
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
return await this.placeAndTake({
|
|
1267
|
-
orderType: OrderType.MARKET,
|
|
1268
|
-
marketIndex,
|
|
1269
|
-
direction: findDirectionToClose(userPosition),
|
|
1270
|
-
baseAssetAmount: userPosition.baseAssetAmount,
|
|
1271
|
-
reduceOnly: true,
|
|
1272
|
-
});
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
public async settlePNLs(
|
|
1276
|
-
users: {
|
|
1277
|
-
settleeUserAccountPublicKey: PublicKey;
|
|
1278
|
-
settleeUserAccount: UserAccount;
|
|
1279
|
-
}[],
|
|
1280
|
-
marketIndex: BN
|
|
1281
|
-
): Promise<TransactionSignature> {
|
|
1282
|
-
const ixs = [];
|
|
1283
|
-
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
1284
|
-
ixs.push(
|
|
1285
|
-
await this.settlePNLIx(
|
|
1286
|
-
settleeUserAccountPublicKey,
|
|
1287
|
-
settleeUserAccount,
|
|
1288
|
-
marketIndex
|
|
1289
|
-
)
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
const tx = new Transaction().add(...ixs);
|
|
1294
|
-
|
|
1295
|
-
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
1296
|
-
return txSig;
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
public async settlePNL(
|
|
1300
|
-
settleeUserAccountPublicKey: PublicKey,
|
|
1301
|
-
settleeUserAccount: UserAccount,
|
|
1302
|
-
marketIndex: BN
|
|
1303
|
-
): Promise<TransactionSignature> {
|
|
1304
|
-
const { txSig } = await this.txSender.send(
|
|
1305
|
-
wrapInTx(
|
|
1306
|
-
await this.settlePNLIx(
|
|
1307
|
-
settleeUserAccountPublicKey,
|
|
1308
|
-
settleeUserAccount,
|
|
1309
|
-
marketIndex
|
|
1310
|
-
)
|
|
1311
|
-
),
|
|
1312
|
-
[],
|
|
1313
|
-
this.opts
|
|
1314
|
-
);
|
|
1315
|
-
return txSig;
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
public async settlePNLIx(
|
|
1319
|
-
settleeUserAccountPublicKey: PublicKey,
|
|
1320
|
-
settleeUserAccount: UserAccount,
|
|
1321
|
-
marketIndex: BN
|
|
1322
|
-
): Promise<TransactionInstruction> {
|
|
1323
|
-
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1324
|
-
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1325
|
-
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1326
|
-
for (const position of settleeUserAccount.positions) {
|
|
1327
|
-
if (!positionIsAvailable(position)) {
|
|
1328
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1329
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1330
|
-
pubkey: market.pubkey,
|
|
1331
|
-
isWritable: true, // TODO
|
|
1332
|
-
isSigner: false,
|
|
1333
|
-
});
|
|
1334
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1335
|
-
pubkey: market.amm.oracle,
|
|
1336
|
-
isWritable: false,
|
|
1337
|
-
isSigner: false,
|
|
1338
|
-
});
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
for (const userBankBalance of settleeUserAccount.bankBalances) {
|
|
1343
|
-
if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
|
|
1344
|
-
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
1345
|
-
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
1346
|
-
pubkey: bankAccount.pubkey,
|
|
1347
|
-
isSigner: false,
|
|
1348
|
-
isWritable: false,
|
|
1349
|
-
});
|
|
1350
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
1351
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1352
|
-
pubkey: bankAccount.oracle,
|
|
1353
|
-
isSigner: false,
|
|
1354
|
-
isWritable: false,
|
|
1355
|
-
});
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
const marketAccount = this.getMarketAccount(marketIndex.toNumber());
|
|
1361
|
-
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1362
|
-
pubkey: marketAccount.pubkey,
|
|
1363
|
-
isSigner: false,
|
|
1364
|
-
isWritable: true,
|
|
1365
|
-
});
|
|
1366
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1367
|
-
pubkey: marketAccount.amm.oracle,
|
|
1368
|
-
isSigner: false,
|
|
1369
|
-
isWritable: false,
|
|
1370
|
-
});
|
|
1371
|
-
|
|
1372
|
-
bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
|
|
1373
|
-
pubkey: this.getBankAccount(QUOTE_ASSET_BANK_INDEX).pubkey,
|
|
1374
|
-
isSigner: false,
|
|
1375
|
-
isWritable: true,
|
|
1376
|
-
});
|
|
1377
|
-
|
|
1378
|
-
const remainingAccounts = [
|
|
1379
|
-
...oracleAccountMap.values(),
|
|
1380
|
-
...bankAccountMap.values(),
|
|
1381
|
-
...marketAccountMap.values(),
|
|
1382
|
-
];
|
|
1383
|
-
|
|
1384
|
-
return await this.program.instruction.settlePnl(marketIndex, {
|
|
1385
|
-
accounts: {
|
|
1386
|
-
state: await this.getStatePublicKey(),
|
|
1387
|
-
authority: this.wallet.publicKey,
|
|
1388
|
-
user: settleeUserAccountPublicKey,
|
|
1389
|
-
},
|
|
1390
|
-
remainingAccounts: remainingAccounts,
|
|
1391
|
-
});
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
public async liquidatePerp(
|
|
1395
|
-
userAccountPublicKey: PublicKey,
|
|
1396
|
-
userAccount: UserAccount,
|
|
1397
|
-
marketIndex: BN,
|
|
1398
|
-
maxBaseAssetAmount: BN
|
|
1399
|
-
): Promise<TransactionSignature> {
|
|
1400
|
-
const { txSig } = await this.txSender.send(
|
|
1401
|
-
wrapInTx(
|
|
1402
|
-
await this.getLiquidatePerpIx(
|
|
1403
|
-
userAccountPublicKey,
|
|
1404
|
-
userAccount,
|
|
1405
|
-
marketIndex,
|
|
1406
|
-
maxBaseAssetAmount
|
|
1407
|
-
)
|
|
1408
|
-
),
|
|
1409
|
-
[],
|
|
1410
|
-
this.opts
|
|
1411
|
-
);
|
|
1412
|
-
return txSig;
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
public async getLiquidatePerpIx(
|
|
1416
|
-
userAccountPublicKey: PublicKey,
|
|
1417
|
-
userAccount: UserAccount,
|
|
1418
|
-
marketIndex: BN,
|
|
1419
|
-
maxBaseAssetAmount: BN
|
|
1420
|
-
): Promise<TransactionInstruction> {
|
|
1421
|
-
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1422
|
-
|
|
1423
|
-
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
1424
|
-
writableMarketIndex: marketIndex,
|
|
1425
|
-
userAccount,
|
|
1426
|
-
});
|
|
1427
|
-
|
|
1428
|
-
return await this.program.instruction.liquidatePerp(
|
|
1429
|
-
marketIndex,
|
|
1430
|
-
maxBaseAssetAmount,
|
|
1431
|
-
{
|
|
1432
|
-
accounts: {
|
|
1433
|
-
state: await this.getStatePublicKey(),
|
|
1434
|
-
authority: this.wallet.publicKey,
|
|
1435
|
-
user: userAccountPublicKey,
|
|
1436
|
-
liquidator: liquidatorPublicKey,
|
|
1437
|
-
},
|
|
1438
|
-
remainingAccounts: remainingAccounts,
|
|
1439
|
-
}
|
|
1440
|
-
);
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
public async liquidateBorrow(
|
|
1444
|
-
userAccountPublicKey: PublicKey,
|
|
1445
|
-
userAccount: UserAccount,
|
|
1446
|
-
assetBankIndex: BN,
|
|
1447
|
-
liabilityBankIndex: BN,
|
|
1448
|
-
maxLiabilityTransfer: BN
|
|
1449
|
-
): Promise<TransactionSignature> {
|
|
1450
|
-
const { txSig } = await this.txSender.send(
|
|
1451
|
-
wrapInTx(
|
|
1452
|
-
await this.getLiquidateBorrowIx(
|
|
1453
|
-
userAccountPublicKey,
|
|
1454
|
-
userAccount,
|
|
1455
|
-
assetBankIndex,
|
|
1456
|
-
liabilityBankIndex,
|
|
1457
|
-
maxLiabilityTransfer
|
|
1458
|
-
)
|
|
1459
|
-
),
|
|
1460
|
-
[],
|
|
1461
|
-
this.opts
|
|
1462
|
-
);
|
|
1463
|
-
return txSig;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
public async getLiquidateBorrowIx(
|
|
1467
|
-
userAccountPublicKey: PublicKey,
|
|
1468
|
-
userAccount: UserAccount,
|
|
1469
|
-
assetBankIndex: BN,
|
|
1470
|
-
liabilityBankIndex: BN,
|
|
1471
|
-
maxLiabilityTransfer: BN
|
|
1472
|
-
): Promise<TransactionInstruction> {
|
|
1473
|
-
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1474
|
-
|
|
1475
|
-
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
1476
|
-
userAccount,
|
|
1477
|
-
writableBankIndexes: [liabilityBankIndex, assetBankIndex],
|
|
1478
|
-
});
|
|
1479
|
-
|
|
1480
|
-
return await this.program.instruction.liquidateBorrow(
|
|
1481
|
-
assetBankIndex,
|
|
1482
|
-
liabilityBankIndex,
|
|
1483
|
-
maxLiabilityTransfer,
|
|
1484
|
-
{
|
|
1485
|
-
accounts: {
|
|
1486
|
-
state: await this.getStatePublicKey(),
|
|
1487
|
-
authority: this.wallet.publicKey,
|
|
1488
|
-
user: userAccountPublicKey,
|
|
1489
|
-
liquidator: liquidatorPublicKey,
|
|
1490
|
-
},
|
|
1491
|
-
remainingAccounts: remainingAccounts,
|
|
1492
|
-
}
|
|
1493
|
-
);
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
public async liquidateBorrowForPerpPnl(
|
|
1497
|
-
userAccountPublicKey: PublicKey,
|
|
1498
|
-
userAccount: UserAccount,
|
|
1499
|
-
perpMarketIndex: BN,
|
|
1500
|
-
liabilityBankIndex: BN,
|
|
1501
|
-
maxLiabilityTransfer: BN
|
|
1502
|
-
): Promise<TransactionSignature> {
|
|
1503
|
-
const { txSig } = await this.txSender.send(
|
|
1504
|
-
wrapInTx(
|
|
1505
|
-
await this.getLiquidateBorrowForPerpPnlIx(
|
|
1506
|
-
userAccountPublicKey,
|
|
1507
|
-
userAccount,
|
|
1508
|
-
perpMarketIndex,
|
|
1509
|
-
liabilityBankIndex,
|
|
1510
|
-
maxLiabilityTransfer
|
|
1511
|
-
)
|
|
1512
|
-
),
|
|
1513
|
-
[],
|
|
1514
|
-
this.opts
|
|
1515
|
-
);
|
|
1516
|
-
return txSig;
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
public async getLiquidateBorrowForPerpPnlIx(
|
|
1520
|
-
userAccountPublicKey: PublicKey,
|
|
1521
|
-
userAccount: UserAccount,
|
|
1522
|
-
perpMarketIndex: BN,
|
|
1523
|
-
liabilityBankIndex: BN,
|
|
1524
|
-
maxLiabilityTransfer: BN
|
|
1525
|
-
): Promise<TransactionInstruction> {
|
|
1526
|
-
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1527
|
-
|
|
1528
|
-
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
1529
|
-
userAccount,
|
|
1530
|
-
writableMarketIndex: perpMarketIndex,
|
|
1531
|
-
writableBankIndexes: [liabilityBankIndex],
|
|
1532
|
-
});
|
|
1533
|
-
|
|
1534
|
-
return await this.program.instruction.liquidateBorrowForPerpPnl(
|
|
1535
|
-
perpMarketIndex,
|
|
1536
|
-
liabilityBankIndex,
|
|
1537
|
-
maxLiabilityTransfer,
|
|
1538
|
-
{
|
|
1539
|
-
accounts: {
|
|
1540
|
-
state: await this.getStatePublicKey(),
|
|
1541
|
-
authority: this.wallet.publicKey,
|
|
1542
|
-
user: userAccountPublicKey,
|
|
1543
|
-
liquidator: liquidatorPublicKey,
|
|
1544
|
-
},
|
|
1545
|
-
remainingAccounts: remainingAccounts,
|
|
1546
|
-
}
|
|
1547
|
-
);
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
public async liquidatePerpPnlForDeposit(
|
|
1551
|
-
userAccountPublicKey: PublicKey,
|
|
1552
|
-
userAccount: UserAccount,
|
|
1553
|
-
perpMarketIndex: BN,
|
|
1554
|
-
assetBankIndex: BN,
|
|
1555
|
-
maxPnlTransfer: BN
|
|
1556
|
-
): Promise<TransactionSignature> {
|
|
1557
|
-
const { txSig } = await this.txSender.send(
|
|
1558
|
-
wrapInTx(
|
|
1559
|
-
await this.getLiquidatePerpPnlForDepositIx(
|
|
1560
|
-
userAccountPublicKey,
|
|
1561
|
-
userAccount,
|
|
1562
|
-
perpMarketIndex,
|
|
1563
|
-
assetBankIndex,
|
|
1564
|
-
maxPnlTransfer
|
|
1565
|
-
)
|
|
1566
|
-
),
|
|
1567
|
-
[],
|
|
1568
|
-
this.opts
|
|
1569
|
-
);
|
|
1570
|
-
return txSig;
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
public async getLiquidatePerpPnlForDepositIx(
|
|
1574
|
-
userAccountPublicKey: PublicKey,
|
|
1575
|
-
userAccount: UserAccount,
|
|
1576
|
-
perpMarketIndex: BN,
|
|
1577
|
-
assetBankIndex: BN,
|
|
1578
|
-
maxPnlTransfer: BN
|
|
1579
|
-
): Promise<TransactionInstruction> {
|
|
1580
|
-
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1581
|
-
|
|
1582
|
-
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
1583
|
-
userAccount,
|
|
1584
|
-
writableMarketIndex: perpMarketIndex,
|
|
1585
|
-
writableBankIndexes: [assetBankIndex],
|
|
1586
|
-
});
|
|
1587
|
-
|
|
1588
|
-
return await this.program.instruction.liquidatePerpPnlForDeposit(
|
|
1589
|
-
perpMarketIndex,
|
|
1590
|
-
assetBankIndex,
|
|
1591
|
-
maxPnlTransfer,
|
|
1592
|
-
{
|
|
1593
|
-
accounts: {
|
|
1594
|
-
state: await this.getStatePublicKey(),
|
|
1595
|
-
authority: this.wallet.publicKey,
|
|
1596
|
-
user: userAccountPublicKey,
|
|
1597
|
-
liquidator: liquidatorPublicKey,
|
|
1598
|
-
},
|
|
1599
|
-
remainingAccounts: remainingAccounts,
|
|
1600
|
-
}
|
|
1601
|
-
);
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
getRemainingAccountsForLiquidation(params: {
|
|
1605
|
-
userAccount: UserAccount;
|
|
1606
|
-
writableMarketIndex?: BN;
|
|
1607
|
-
writableBankIndexes?: BN[];
|
|
1608
|
-
}): AccountMeta[] {
|
|
1609
|
-
const liquidateeUserAccount = params.userAccount;
|
|
1610
|
-
|
|
1611
|
-
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1612
|
-
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1613
|
-
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1614
|
-
for (const bankBalance of liquidateeUserAccount.bankBalances) {
|
|
1615
|
-
if (!bankBalance.balance.eq(ZERO)) {
|
|
1616
|
-
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1617
|
-
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1618
|
-
pubkey: bankAccount.pubkey,
|
|
1619
|
-
isSigner: false,
|
|
1620
|
-
isWritable: false,
|
|
1621
|
-
});
|
|
1622
|
-
|
|
1623
|
-
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
1624
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1625
|
-
pubkey: bankAccount.oracle,
|
|
1626
|
-
isSigner: false,
|
|
1627
|
-
isWritable: false,
|
|
1628
|
-
});
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
for (const position of liquidateeUserAccount.positions) {
|
|
1633
|
-
if (!positionIsAvailable(position)) {
|
|
1634
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1635
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1636
|
-
pubkey: market.pubkey,
|
|
1637
|
-
isWritable: false,
|
|
1638
|
-
isSigner: false,
|
|
1639
|
-
});
|
|
1640
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1641
|
-
pubkey: market.amm.oracle,
|
|
1642
|
-
isWritable: false,
|
|
1643
|
-
isSigner: false,
|
|
1644
|
-
});
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
1649
|
-
if (!userAccountAndSlot) {
|
|
1650
|
-
throw Error(
|
|
1651
|
-
'No user account found. Most likely user account does not exist or failed to fetch account'
|
|
1652
|
-
);
|
|
1653
|
-
}
|
|
1654
|
-
const { data: userAccount, slot: lastUserPositionsSlot } =
|
|
1655
|
-
userAccountAndSlot;
|
|
1656
|
-
|
|
1657
|
-
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
1658
|
-
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
1659
|
-
// otherwise remove from slot
|
|
1660
|
-
if (slot > lastUserPositionsSlot) {
|
|
1661
|
-
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
1662
|
-
marketAccountMap.set(marketIndexNum, {
|
|
1663
|
-
pubkey: marketAccount.pubkey,
|
|
1664
|
-
isSigner: false,
|
|
1665
|
-
isWritable: false,
|
|
1666
|
-
});
|
|
1667
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1668
|
-
pubkey: marketAccount.amm.oracle,
|
|
1669
|
-
isSigner: false,
|
|
1670
|
-
isWritable: false,
|
|
1671
|
-
});
|
|
1672
|
-
} else {
|
|
1673
|
-
this.marketLastSlotCache.delete(marketIndexNum);
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
for (const bankBalance of userAccount.bankBalances) {
|
|
1677
|
-
if (!bankBalance.balance.eq(ZERO)) {
|
|
1678
|
-
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1679
|
-
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1680
|
-
pubkey: bankAccount.pubkey,
|
|
1681
|
-
isSigner: false,
|
|
1682
|
-
isWritable: false,
|
|
1683
|
-
});
|
|
1684
|
-
|
|
1685
|
-
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
1686
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1687
|
-
pubkey: bankAccount.oracle,
|
|
1688
|
-
isSigner: false,
|
|
1689
|
-
isWritable: false,
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
for (const position of userAccount.positions) {
|
|
1695
|
-
if (!positionIsAvailable(position)) {
|
|
1696
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1697
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1698
|
-
pubkey: market.pubkey,
|
|
1699
|
-
isWritable: false,
|
|
1700
|
-
isSigner: false,
|
|
1701
|
-
});
|
|
1702
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1703
|
-
pubkey: market.amm.oracle,
|
|
1704
|
-
isWritable: false,
|
|
1705
|
-
isSigner: false,
|
|
1706
|
-
});
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
if (params.writableMarketIndex) {
|
|
1711
|
-
const market = this.getMarketAccount(params.writableMarketIndex);
|
|
1712
|
-
marketAccountMap.set(market.marketIndex.toNumber(), {
|
|
1713
|
-
pubkey: market.pubkey,
|
|
1714
|
-
isSigner: false,
|
|
1715
|
-
isWritable: true,
|
|
1716
|
-
});
|
|
1717
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1718
|
-
pubkey: market.amm.oracle,
|
|
1719
|
-
isSigner: false,
|
|
1720
|
-
isWritable: false,
|
|
1721
|
-
});
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
if (params.writableBankIndexes) {
|
|
1725
|
-
for (const writableBankIndex of params.writableBankIndexes) {
|
|
1726
|
-
const bank = this.getBankAccount(writableBankIndex);
|
|
1727
|
-
bankAccountMap.set(bank.bankIndex.toNumber(), {
|
|
1728
|
-
pubkey: bank.pubkey,
|
|
1729
|
-
isSigner: false,
|
|
1730
|
-
isWritable: true,
|
|
1731
|
-
});
|
|
1732
|
-
if (!bank.oracle.equals(PublicKey.default)) {
|
|
1733
|
-
oracleAccountMap.set(bank.oracle.toString(), {
|
|
1734
|
-
pubkey: bank.oracle,
|
|
1735
|
-
isSigner: false,
|
|
1736
|
-
isWritable: false,
|
|
1737
|
-
});
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
return [
|
|
1743
|
-
...oracleAccountMap.values(),
|
|
1744
|
-
...bankAccountMap.values(),
|
|
1745
|
-
...marketAccountMap.values(),
|
|
1746
|
-
];
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
public async updateFundingRate(
|
|
1750
|
-
oracle: PublicKey,
|
|
1751
|
-
marketIndex: BN
|
|
1752
|
-
): Promise<TransactionSignature> {
|
|
1753
|
-
const { txSig } = await this.txSender.send(
|
|
1754
|
-
wrapInTx(await this.getUpdateFundingRateIx(oracle, marketIndex)),
|
|
1755
|
-
[],
|
|
1756
|
-
this.opts
|
|
1757
|
-
);
|
|
1758
|
-
return txSig;
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
public async getUpdateFundingRateIx(
|
|
1762
|
-
oracle: PublicKey,
|
|
1763
|
-
marketIndex: BN
|
|
1764
|
-
): Promise<TransactionInstruction> {
|
|
1765
|
-
return await this.program.instruction.updateFundingRate(marketIndex, {
|
|
1766
|
-
accounts: {
|
|
1767
|
-
state: await this.getStatePublicKey(),
|
|
1768
|
-
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
1769
|
-
oracle: oracle,
|
|
1770
|
-
},
|
|
1771
|
-
});
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
public async settleFundingPayment(
|
|
1775
|
-
userAccount: PublicKey
|
|
1776
|
-
): Promise<TransactionSignature> {
|
|
1777
|
-
const { txSig } = await this.txSender.send(
|
|
1778
|
-
wrapInTx(await this.getSettleFundingPaymentIx(userAccount)),
|
|
1779
|
-
[],
|
|
1780
|
-
this.opts
|
|
1781
|
-
);
|
|
1782
|
-
return txSig;
|
|
1783
|
-
}
|
|
1784
|
-
|
|
1785
|
-
public async getSettleFundingPaymentIx(
|
|
1786
|
-
userAccount: PublicKey
|
|
1787
|
-
): Promise<TransactionInstruction> {
|
|
1788
|
-
const user = (await this.program.account.user.fetch(
|
|
1789
|
-
userAccount
|
|
1790
|
-
)) as UserAccount;
|
|
1791
|
-
|
|
1792
|
-
const userPositions = user.positions;
|
|
1793
|
-
|
|
1794
|
-
const remainingAccounts = [];
|
|
1795
|
-
for (const position of userPositions) {
|
|
1796
|
-
if (!positionIsAvailable(position)) {
|
|
1797
|
-
const marketPublicKey = await getMarketPublicKey(
|
|
1798
|
-
this.program.programId,
|
|
1799
|
-
position.marketIndex
|
|
1800
|
-
);
|
|
1801
|
-
remainingAccounts.push({
|
|
1802
|
-
pubkey: marketPublicKey,
|
|
1803
|
-
isWritable: false,
|
|
1804
|
-
isSigner: false,
|
|
1805
|
-
});
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
return await this.program.instruction.settleFundingPayment({
|
|
1810
|
-
accounts: {
|
|
1811
|
-
state: await this.getStatePublicKey(),
|
|
1812
|
-
user: userAccount,
|
|
1813
|
-
},
|
|
1814
|
-
remainingAccounts,
|
|
1815
|
-
});
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
public triggerEvent(eventName: keyof ClearingHouseAccountEvents, data?: any) {
|
|
1819
|
-
this.eventEmitter.emit(eventName, data);
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
|
|
1823
|
-
const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
|
|
1824
|
-
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
1825
|
-
|
|
1826
|
-
return oracleData;
|
|
1827
|
-
}
|
|
1828
|
-
}
|