@drift-labs/sdk 0.2.0-master.11 → 0.2.0-master.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +14 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/admin.d.ts +2 -0
- package/lib/admin.js +18 -0
- package/lib/clearingHouse.d.ts +24 -3
- package/lib/clearingHouse.js +352 -51
- package/lib/clearingHouseConfig.d.ts +1 -0
- package/lib/clearingHouseUser.d.ts +15 -15
- package/lib/clearingHouseUser.js +185 -73
- package/lib/clearingHouseUserStats.d.ts +17 -0
- package/lib/clearingHouseUserStats.js +36 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +4 -3
- package/lib/constants/numericConstants.d.ts +2 -0
- package/lib/constants/numericConstants.js +3 -1
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +2 -1
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +37 -11
- package/lib/idl/clearing_house.json +692 -58
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/amm.js +2 -2
- package/lib/math/bankBalance.d.ts +7 -1
- package/lib/math/bankBalance.js +76 -1
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +25 -5
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +43 -12
- package/lib/math/trade.js +2 -2
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +2 -77
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/tokenFaucet.js +23 -12
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/types.d.ts +78 -10
- package/lib/types.js +12 -0
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +1 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +18 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/pda.ts +13 -0
- package/src/admin.ts +29 -1
- package/src/clearingHouse.ts +619 -62
- package/src/clearingHouseConfig.ts +1 -0
- package/src/clearingHouseUser.ts +317 -105
- package/src/clearingHouseUserStats.ts +53 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +6 -3
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +3 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/types.ts +2 -0
- package/src/factory/bigNum.js +37 -11
- package/src/factory/bigNum.ts +43 -13
- package/src/idl/clearing_house.json +692 -58
- package/src/index.ts +1 -0
- package/src/math/amm.ts +8 -5
- package/src/math/bankBalance.ts +147 -1
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/oracles.ts +42 -5
- package/src/math/position.ts +60 -9
- package/src/math/trade.ts +2 -2
- package/src/orders.ts +4 -157
- package/src/tokenFaucet.js +189 -0
- package/src/tokenFaucet.ts +38 -15
- package/src/tx/retryTxSender.ts +11 -3
- package/src/types.js +12 -1
- package/src/types.ts +83 -10
- package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +2 -0
- 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/pda.js +0 -104
- package/src/index.js +0 -100
- package/src/math/bankBalance.js +0 -75
- package/src/math/market.js +0 -57
- package/src/math/orders.js +0 -110
- package/src/math/position.js +0 -140
- package/src/mockUSDCFaucet.js +0 -280
- package/src/orders.js +0 -134
- package/src/tx/retryTxSender.js +0 -188
package/src/clearingHouse.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
|
|
2
|
-
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
2
|
+
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
3
3
|
import {
|
|
4
4
|
StateAccount,
|
|
5
5
|
IWallet,
|
|
@@ -27,6 +27,10 @@ import {
|
|
|
27
27
|
Transaction,
|
|
28
28
|
TransactionInstruction,
|
|
29
29
|
AccountMeta,
|
|
30
|
+
Keypair,
|
|
31
|
+
LAMPORTS_PER_SOL,
|
|
32
|
+
Signer,
|
|
33
|
+
SystemProgram,
|
|
30
34
|
} from '@solana/web3.js';
|
|
31
35
|
|
|
32
36
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -37,6 +41,7 @@ import {
|
|
|
37
41
|
getMarketPublicKey,
|
|
38
42
|
getUserAccountPublicKey,
|
|
39
43
|
getUserAccountPublicKeySync,
|
|
44
|
+
getUserStatsAccountPublicKey,
|
|
40
45
|
} from './addresses/pda';
|
|
41
46
|
import {
|
|
42
47
|
ClearingHouseAccountSubscriber,
|
|
@@ -57,6 +62,8 @@ import { RetryTxSender } from './tx/retryTxSender';
|
|
|
57
62
|
import { ClearingHouseUser } from './clearingHouseUser';
|
|
58
63
|
import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
|
|
59
64
|
import { getMarketsBanksAndOraclesForSubscription } from './config';
|
|
65
|
+
import { WRAPPED_SOL_MINT } from './constants/banks';
|
|
66
|
+
import { ClearingHouseUserStats } from './clearingHouseUserStats';
|
|
60
67
|
|
|
61
68
|
/**
|
|
62
69
|
* # ClearingHouse
|
|
@@ -69,6 +76,7 @@ export class ClearingHouse {
|
|
|
69
76
|
provider: AnchorProvider;
|
|
70
77
|
opts?: ConfirmOptions;
|
|
71
78
|
users = new Map<number, ClearingHouseUser>();
|
|
79
|
+
userStats?: ClearingHouseUserStats;
|
|
72
80
|
activeUserId: number;
|
|
73
81
|
userAccountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig;
|
|
74
82
|
accountSubscriber: ClearingHouseAccountSubscriber;
|
|
@@ -112,6 +120,16 @@ export class ClearingHouse {
|
|
|
112
120
|
type: 'websocket',
|
|
113
121
|
};
|
|
114
122
|
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
123
|
+
if (config.userStats) {
|
|
124
|
+
this.userStats = new ClearingHouseUserStats({
|
|
125
|
+
clearingHouse: this,
|
|
126
|
+
userStatsAccountPublicKey: getUserStatsAccountPublicKey(
|
|
127
|
+
this.program.programId,
|
|
128
|
+
this.wallet.publicKey
|
|
129
|
+
),
|
|
130
|
+
accountSubscription: this.userAccountSubscriptionConfig,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
115
133
|
|
|
116
134
|
let marketIndexes = config.marketIndexes;
|
|
117
135
|
let bankIndexes = config.bankIndexes;
|
|
@@ -183,6 +201,9 @@ export class ClearingHouse {
|
|
|
183
201
|
const subscribePromises = this.subscribeUsers().concat(
|
|
184
202
|
this.accountSubscriber.subscribe()
|
|
185
203
|
);
|
|
204
|
+
if (this.userStats !== undefined) {
|
|
205
|
+
subscribePromises.concat(this.userStats.subscribe());
|
|
206
|
+
}
|
|
186
207
|
this.isSubscribed = (await Promise.all(subscribePromises)).reduce(
|
|
187
208
|
(success, prevSuccess) => success && prevSuccess
|
|
188
209
|
);
|
|
@@ -208,6 +229,9 @@ export class ClearingHouse {
|
|
|
208
229
|
const unsubscribePromises = this.unsubscribeUsers().concat(
|
|
209
230
|
this.accountSubscriber.unsubscribe()
|
|
210
231
|
);
|
|
232
|
+
if (this.userStats !== undefined) {
|
|
233
|
+
unsubscribePromises.concat(this.userStats.unsubscribe());
|
|
234
|
+
}
|
|
211
235
|
await Promise.all(unsubscribePromises);
|
|
212
236
|
this.isSubscribed = false;
|
|
213
237
|
}
|
|
@@ -297,6 +321,7 @@ export class ClearingHouse {
|
|
|
297
321
|
}
|
|
298
322
|
|
|
299
323
|
this.activeUserId = activeUserId;
|
|
324
|
+
this.userStatsAccountPublicKey = undefined;
|
|
300
325
|
}
|
|
301
326
|
|
|
302
327
|
public async switchActiveUser(userId: number): Promise<void> {
|
|
@@ -320,7 +345,12 @@ export class ClearingHouse {
|
|
|
320
345
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
321
346
|
await this.getInitializeUserInstructions(userId, name);
|
|
322
347
|
|
|
323
|
-
const tx = new Transaction()
|
|
348
|
+
const tx = new Transaction();
|
|
349
|
+
if (userId === 0) {
|
|
350
|
+
// not the safest assumption, can explicitly check if user stats account exists if it causes problems
|
|
351
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
352
|
+
}
|
|
353
|
+
tx.add(initializeUserAccountIx);
|
|
324
354
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
325
355
|
return [txSig, userAccountPublicKey];
|
|
326
356
|
}
|
|
@@ -340,6 +370,7 @@ export class ClearingHouse {
|
|
|
340
370
|
await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
341
371
|
accounts: {
|
|
342
372
|
user: userAccountPublicKey,
|
|
373
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
343
374
|
authority: this.wallet.publicKey,
|
|
344
375
|
payer: this.wallet.publicKey,
|
|
345
376
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
@@ -351,6 +382,19 @@ export class ClearingHouse {
|
|
|
351
382
|
return [userAccountPublicKey, initializeUserAccountIx];
|
|
352
383
|
}
|
|
353
384
|
|
|
385
|
+
async getInitializeUserStatsIx(): Promise<TransactionInstruction> {
|
|
386
|
+
return await this.program.instruction.initializeUserStats({
|
|
387
|
+
accounts: {
|
|
388
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
389
|
+
authority: this.wallet.publicKey,
|
|
390
|
+
payer: this.wallet.publicKey,
|
|
391
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
392
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
393
|
+
state: await this.getStatePublicKey(),
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
354
398
|
public getUser(userId?: number): ClearingHouseUser {
|
|
355
399
|
userId = userId ?? this.activeUserId;
|
|
356
400
|
if (!this.users.has(userId)) {
|
|
@@ -363,6 +407,23 @@ export class ClearingHouse {
|
|
|
363
407
|
return [...this.users.values()];
|
|
364
408
|
}
|
|
365
409
|
|
|
410
|
+
public getUserStats(): ClearingHouseUserStats {
|
|
411
|
+
return this.userStats;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
userStatsAccountPublicKey: PublicKey;
|
|
415
|
+
public getUserStatsAccountPublicKey(): PublicKey {
|
|
416
|
+
if (this.userStatsAccountPublicKey) {
|
|
417
|
+
return this.userStatsAccountPublicKey;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
this.userStatsAccountPublicKey = getUserStatsAccountPublicKey(
|
|
421
|
+
this.program.programId,
|
|
422
|
+
this.wallet.publicKey
|
|
423
|
+
);
|
|
424
|
+
return this.userStatsAccountPublicKey;
|
|
425
|
+
}
|
|
426
|
+
|
|
366
427
|
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
367
428
|
return this.getUser().userAccountPublicKey;
|
|
368
429
|
}
|
|
@@ -399,6 +460,7 @@ export class ClearingHouse {
|
|
|
399
460
|
getRemainingAccounts(params: {
|
|
400
461
|
writableMarketIndex?: BN;
|
|
401
462
|
writableBankIndex?: BN;
|
|
463
|
+
readableMarketIndex?: BN;
|
|
402
464
|
}): AccountMeta[] {
|
|
403
465
|
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
404
466
|
if (!userAccountAndSlot) {
|
|
@@ -439,8 +501,7 @@ export class ClearingHouse {
|
|
|
439
501
|
marketAccountMap.set(marketIndexNum, {
|
|
440
502
|
pubkey: marketAccount.pubkey,
|
|
441
503
|
isSigner: false,
|
|
442
|
-
|
|
443
|
-
isWritable: true,
|
|
504
|
+
isWritable: false,
|
|
444
505
|
});
|
|
445
506
|
oracleAccountMap.set(marketAccount.pubkey.toString(), {
|
|
446
507
|
pubkey: marketAccount.amm.oracle,
|
|
@@ -450,6 +511,22 @@ export class ClearingHouse {
|
|
|
450
511
|
}
|
|
451
512
|
}
|
|
452
513
|
|
|
514
|
+
if (params.readableMarketIndex) {
|
|
515
|
+
const marketAccount = this.getMarketAccount(
|
|
516
|
+
params.readableMarketIndex.toNumber()
|
|
517
|
+
);
|
|
518
|
+
marketAccountMap.set(params.readableMarketIndex.toNumber(), {
|
|
519
|
+
pubkey: marketAccount.pubkey,
|
|
520
|
+
isSigner: false,
|
|
521
|
+
isWritable: true,
|
|
522
|
+
});
|
|
523
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
524
|
+
pubkey: marketAccount.amm.oracle,
|
|
525
|
+
isSigner: false,
|
|
526
|
+
isWritable: false,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
453
530
|
if (params.writableMarketIndex) {
|
|
454
531
|
const marketAccount = this.getMarketAccount(
|
|
455
532
|
params.writableMarketIndex.toNumber()
|
|
@@ -527,6 +604,31 @@ export class ClearingHouse {
|
|
|
527
604
|
userId?: number,
|
|
528
605
|
reduceOnly = false
|
|
529
606
|
): Promise<TransactionSignature> {
|
|
607
|
+
const tx = new Transaction();
|
|
608
|
+
const additionalSigners: Array<Signer> = [];
|
|
609
|
+
|
|
610
|
+
const bank = this.getBankAccount(bankIndex);
|
|
611
|
+
|
|
612
|
+
const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
|
|
613
|
+
|
|
614
|
+
const authority = this.wallet.publicKey;
|
|
615
|
+
|
|
616
|
+
const createWSOLTokenAccount =
|
|
617
|
+
isSolBank && collateralAccountPublicKey.equals(authority);
|
|
618
|
+
|
|
619
|
+
if (createWSOLTokenAccount) {
|
|
620
|
+
const { ixs, signers, pubkey } =
|
|
621
|
+
await this.getWrappedSolAccountCreationIxs(amount);
|
|
622
|
+
|
|
623
|
+
collateralAccountPublicKey = pubkey;
|
|
624
|
+
|
|
625
|
+
ixs.forEach((ix) => {
|
|
626
|
+
tx.add(ix);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
630
|
+
}
|
|
631
|
+
|
|
530
632
|
const depositCollateralIx = await this.getDepositInstruction(
|
|
531
633
|
amount,
|
|
532
634
|
bankIndex,
|
|
@@ -536,9 +638,26 @@ export class ClearingHouse {
|
|
|
536
638
|
true
|
|
537
639
|
);
|
|
538
640
|
|
|
539
|
-
|
|
641
|
+
tx.add(depositCollateralIx);
|
|
642
|
+
|
|
643
|
+
// Close the wrapped sol account at the end of the transaction
|
|
644
|
+
if (createWSOLTokenAccount) {
|
|
645
|
+
tx.add(
|
|
646
|
+
Token.createCloseAccountInstruction(
|
|
647
|
+
TOKEN_PROGRAM_ID,
|
|
648
|
+
collateralAccountPublicKey,
|
|
649
|
+
authority,
|
|
650
|
+
authority,
|
|
651
|
+
[]
|
|
652
|
+
)
|
|
653
|
+
);
|
|
654
|
+
}
|
|
540
655
|
|
|
541
|
-
const { txSig } = await this.txSender.send(
|
|
656
|
+
const { txSig } = await this.txSender.send(
|
|
657
|
+
tx,
|
|
658
|
+
additionalSigners,
|
|
659
|
+
this.opts
|
|
660
|
+
);
|
|
542
661
|
return txSig;
|
|
543
662
|
}
|
|
544
663
|
|
|
@@ -600,12 +719,119 @@ export class ClearingHouse {
|
|
|
600
719
|
);
|
|
601
720
|
}
|
|
602
721
|
|
|
722
|
+
private async checkIfAccountExists(account: PublicKey) {
|
|
723
|
+
try {
|
|
724
|
+
const accountInfo = await this.connection.getAccountInfo(account);
|
|
725
|
+
return accountInfo && true;
|
|
726
|
+
} catch (e) {
|
|
727
|
+
// Doesn't already exist
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
private async getSolWithdrawalIxs(
|
|
733
|
+
bankIndex: BN,
|
|
734
|
+
amount: BN
|
|
735
|
+
): Promise<{
|
|
736
|
+
ixs: anchor.web3.TransactionInstruction[];
|
|
737
|
+
signers: Signer[];
|
|
738
|
+
pubkey: PublicKey;
|
|
739
|
+
}> {
|
|
740
|
+
const result = {
|
|
741
|
+
ixs: [],
|
|
742
|
+
signers: [],
|
|
743
|
+
pubkey: PublicKey.default,
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
// Create a temporary wrapped SOL account to store the SOL that we're withdrawing
|
|
747
|
+
|
|
748
|
+
const authority = this.wallet.publicKey;
|
|
749
|
+
|
|
750
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(
|
|
751
|
+
amount
|
|
752
|
+
);
|
|
753
|
+
result.pubkey = pubkey;
|
|
754
|
+
|
|
755
|
+
ixs.forEach((ix) => {
|
|
756
|
+
result.ixs.push(ix);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
signers.forEach((ix) => {
|
|
760
|
+
result.signers.push(ix);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
const withdrawIx = await this.getWithdrawIx(
|
|
764
|
+
amount,
|
|
765
|
+
bankIndex,
|
|
766
|
+
pubkey,
|
|
767
|
+
true
|
|
768
|
+
);
|
|
769
|
+
|
|
770
|
+
result.ixs.push(withdrawIx);
|
|
771
|
+
|
|
772
|
+
result.ixs.push(
|
|
773
|
+
Token.createCloseAccountInstruction(
|
|
774
|
+
TOKEN_PROGRAM_ID,
|
|
775
|
+
pubkey,
|
|
776
|
+
authority,
|
|
777
|
+
authority,
|
|
778
|
+
[]
|
|
779
|
+
)
|
|
780
|
+
);
|
|
781
|
+
|
|
782
|
+
return result;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private async getWrappedSolAccountCreationIxs(amount: BN): Promise<{
|
|
786
|
+
ixs: anchor.web3.TransactionInstruction[];
|
|
787
|
+
signers: Signer[];
|
|
788
|
+
pubkey: PublicKey;
|
|
789
|
+
}> {
|
|
790
|
+
const wrappedSolAccount = new Keypair();
|
|
791
|
+
|
|
792
|
+
const result = {
|
|
793
|
+
ixs: [],
|
|
794
|
+
signers: [],
|
|
795
|
+
pubkey: wrappedSolAccount.publicKey,
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
const rentSpaceLamports = new BN(LAMPORTS_PER_SOL / 100);
|
|
799
|
+
|
|
800
|
+
const depositAmountLamports = amount.add(rentSpaceLamports);
|
|
801
|
+
|
|
802
|
+
const authority = this.wallet.publicKey;
|
|
803
|
+
|
|
804
|
+
result.ixs.push(
|
|
805
|
+
SystemProgram.createAccount({
|
|
806
|
+
fromPubkey: authority,
|
|
807
|
+
newAccountPubkey: wrappedSolAccount.publicKey,
|
|
808
|
+
lamports: depositAmountLamports.toNumber(),
|
|
809
|
+
space: 165,
|
|
810
|
+
programId: TOKEN_PROGRAM_ID,
|
|
811
|
+
})
|
|
812
|
+
);
|
|
813
|
+
|
|
814
|
+
result.ixs.push(
|
|
815
|
+
Token.createInitAccountInstruction(
|
|
816
|
+
TOKEN_PROGRAM_ID,
|
|
817
|
+
WRAPPED_SOL_MINT,
|
|
818
|
+
wrappedSolAccount.publicKey,
|
|
819
|
+
authority
|
|
820
|
+
)
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
result.signers.push(wrappedSolAccount);
|
|
824
|
+
|
|
825
|
+
return result;
|
|
826
|
+
}
|
|
827
|
+
|
|
603
828
|
/**
|
|
604
829
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
605
|
-
* @param userId
|
|
606
|
-
* @param name
|
|
607
830
|
* @param amount
|
|
608
831
|
* @param userTokenAccount
|
|
832
|
+
* @param bankIndex
|
|
833
|
+
* @param userId
|
|
834
|
+
* @param name
|
|
609
835
|
* @param fromUserId
|
|
610
836
|
* @returns
|
|
611
837
|
*/
|
|
@@ -620,6 +846,35 @@ export class ClearingHouse {
|
|
|
620
846
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
621
847
|
await this.getInitializeUserInstructions(userId, name);
|
|
622
848
|
|
|
849
|
+
const additionalSigners: Array<Signer> = [];
|
|
850
|
+
|
|
851
|
+
const bank = this.getBankAccount(bankIndex);
|
|
852
|
+
|
|
853
|
+
const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
|
|
854
|
+
|
|
855
|
+
const tx = new Transaction();
|
|
856
|
+
|
|
857
|
+
const authority = this.wallet.publicKey;
|
|
858
|
+
|
|
859
|
+
const createWSOLTokenAccount =
|
|
860
|
+
isSolBank && userTokenAccount.equals(authority);
|
|
861
|
+
|
|
862
|
+
if (createWSOLTokenAccount) {
|
|
863
|
+
const {
|
|
864
|
+
ixs: startIxs,
|
|
865
|
+
signers,
|
|
866
|
+
pubkey,
|
|
867
|
+
} = await this.getWrappedSolAccountCreationIxs(amount);
|
|
868
|
+
|
|
869
|
+
userTokenAccount = pubkey;
|
|
870
|
+
|
|
871
|
+
startIxs.forEach((ix) => {
|
|
872
|
+
tx.add(ix);
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
876
|
+
}
|
|
877
|
+
|
|
623
878
|
const depositCollateralIx =
|
|
624
879
|
fromUserId != null
|
|
625
880
|
? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
|
|
@@ -632,11 +887,29 @@ export class ClearingHouse {
|
|
|
632
887
|
false
|
|
633
888
|
);
|
|
634
889
|
|
|
635
|
-
|
|
636
|
-
.add(
|
|
637
|
-
|
|
890
|
+
if (userId === 0) {
|
|
891
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
892
|
+
}
|
|
893
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
638
894
|
|
|
639
|
-
|
|
895
|
+
// Close the wrapped sol account at the end of the transaction
|
|
896
|
+
if (createWSOLTokenAccount) {
|
|
897
|
+
tx.add(
|
|
898
|
+
Token.createCloseAccountInstruction(
|
|
899
|
+
TOKEN_PROGRAM_ID,
|
|
900
|
+
userTokenAccount,
|
|
901
|
+
authority,
|
|
902
|
+
authority,
|
|
903
|
+
[]
|
|
904
|
+
)
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
const { txSig } = await this.txSender.send(
|
|
909
|
+
tx,
|
|
910
|
+
additionalSigners,
|
|
911
|
+
this.opts
|
|
912
|
+
);
|
|
640
913
|
|
|
641
914
|
return [txSig, userAccountPublicKey];
|
|
642
915
|
}
|
|
@@ -666,11 +939,12 @@ export class ClearingHouse {
|
|
|
666
939
|
false
|
|
667
940
|
);
|
|
668
941
|
|
|
669
|
-
const tx = new Transaction()
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
.add(
|
|
673
|
-
|
|
942
|
+
const tx = new Transaction().add(createAssociatedAccountIx).add(mintToIx);
|
|
943
|
+
|
|
944
|
+
if (userId === 0) {
|
|
945
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
946
|
+
}
|
|
947
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
674
948
|
|
|
675
949
|
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
676
950
|
|
|
@@ -683,16 +957,56 @@ export class ClearingHouse {
|
|
|
683
957
|
userTokenAccount: PublicKey,
|
|
684
958
|
reduceOnly = false
|
|
685
959
|
): Promise<TransactionSignature> {
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
960
|
+
const tx = new Transaction();
|
|
961
|
+
const additionalSigners: Array<Signer> = [];
|
|
962
|
+
|
|
963
|
+
const bank = this.getBankAccount(bankIndex);
|
|
964
|
+
|
|
965
|
+
const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
|
|
966
|
+
|
|
967
|
+
const authority = this.wallet.publicKey;
|
|
968
|
+
|
|
969
|
+
const createWSOLTokenAccount =
|
|
970
|
+
isSolBank && userTokenAccount.equals(authority);
|
|
971
|
+
|
|
972
|
+
if (createWSOLTokenAccount) {
|
|
973
|
+
const { ixs, signers, pubkey } =
|
|
974
|
+
await this.getWrappedSolAccountCreationIxs(amount);
|
|
975
|
+
|
|
976
|
+
userTokenAccount = pubkey;
|
|
977
|
+
|
|
978
|
+
ixs.forEach((ix) => {
|
|
979
|
+
tx.add(ix);
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
const withdrawCollateral = await this.getWithdrawIx(
|
|
986
|
+
amount,
|
|
987
|
+
bank.bankIndex,
|
|
988
|
+
userTokenAccount,
|
|
989
|
+
reduceOnly
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
tx.add(withdrawCollateral);
|
|
993
|
+
|
|
994
|
+
// Close the wrapped sol account at the end of the transaction
|
|
995
|
+
if (createWSOLTokenAccount) {
|
|
996
|
+
tx.add(
|
|
997
|
+
Token.createCloseAccountInstruction(
|
|
998
|
+
TOKEN_PROGRAM_ID,
|
|
691
999
|
userTokenAccount,
|
|
692
|
-
|
|
1000
|
+
authority,
|
|
1001
|
+
authority,
|
|
1002
|
+
[]
|
|
693
1003
|
)
|
|
694
|
-
)
|
|
695
|
-
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
const { txSig } = await this.txSender.send(
|
|
1008
|
+
tx,
|
|
1009
|
+
additionalSigners,
|
|
696
1010
|
this.opts
|
|
697
1011
|
);
|
|
698
1012
|
return txSig;
|
|
@@ -802,6 +1116,135 @@ export class ClearingHouse {
|
|
|
802
1116
|
});
|
|
803
1117
|
}
|
|
804
1118
|
|
|
1119
|
+
public async settleLP(
|
|
1120
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1121
|
+
marketIndex: BN
|
|
1122
|
+
): Promise<TransactionSignature> {
|
|
1123
|
+
const { txSig } = await this.txSender.send(
|
|
1124
|
+
wrapInTx(await this.settleLPIx(settleeUserAccountPublicKey, marketIndex)),
|
|
1125
|
+
[],
|
|
1126
|
+
this.opts
|
|
1127
|
+
);
|
|
1128
|
+
return txSig;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
public async settleLPIx(
|
|
1132
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1133
|
+
marketIndex: BN
|
|
1134
|
+
): Promise<TransactionInstruction> {
|
|
1135
|
+
const settleeUserAccount = (await this.program.account.user.fetch(
|
|
1136
|
+
settleeUserAccountPublicKey
|
|
1137
|
+
)) as UserAccount;
|
|
1138
|
+
const userPositions = settleeUserAccount.positions;
|
|
1139
|
+
const remainingAccounts = [];
|
|
1140
|
+
|
|
1141
|
+
let foundMarket = false;
|
|
1142
|
+
for (const position of userPositions) {
|
|
1143
|
+
if (!positionIsAvailable(position)) {
|
|
1144
|
+
const marketPublicKey = await getMarketPublicKey(
|
|
1145
|
+
this.program.programId,
|
|
1146
|
+
position.marketIndex
|
|
1147
|
+
);
|
|
1148
|
+
remainingAccounts.push({
|
|
1149
|
+
pubkey: marketPublicKey,
|
|
1150
|
+
isWritable: true,
|
|
1151
|
+
isSigner: false,
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
if (marketIndex.eq(position.marketIndex)) {
|
|
1155
|
+
foundMarket = true;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
if (!foundMarket) {
|
|
1161
|
+
console.log(
|
|
1162
|
+
'Warning: lp is not in the market specified -- tx will likely fail'
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
return this.program.instruction.settleLp(marketIndex, {
|
|
1167
|
+
accounts: {
|
|
1168
|
+
state: await this.getStatePublicKey(),
|
|
1169
|
+
user: settleeUserAccountPublicKey,
|
|
1170
|
+
},
|
|
1171
|
+
remainingAccounts: remainingAccounts,
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
public async removeLiquidity(
|
|
1176
|
+
marketIndex: BN,
|
|
1177
|
+
sharesToBurn?: BN
|
|
1178
|
+
): Promise<TransactionSignature> {
|
|
1179
|
+
const { txSig } = await this.txSender.send(
|
|
1180
|
+
wrapInTx(await this.getRemoveLiquidityIx(marketIndex, sharesToBurn)),
|
|
1181
|
+
[],
|
|
1182
|
+
this.opts
|
|
1183
|
+
);
|
|
1184
|
+
return txSig;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
public async getRemoveLiquidityIx(
|
|
1188
|
+
marketIndex: BN,
|
|
1189
|
+
sharesToBurn?: BN
|
|
1190
|
+
): Promise<TransactionInstruction> {
|
|
1191
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1192
|
+
|
|
1193
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1194
|
+
writableMarketIndex: marketIndex,
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
if (sharesToBurn == undefined) {
|
|
1198
|
+
const userAccount = this.getUserAccount();
|
|
1199
|
+
const marketPosition = userAccount.positions.filter((position) =>
|
|
1200
|
+
position.marketIndex.eq(marketIndex)
|
|
1201
|
+
)[0];
|
|
1202
|
+
sharesToBurn = marketPosition.lpShares;
|
|
1203
|
+
console.log('burning lp shares:', sharesToBurn.toString());
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
return this.program.instruction.removeLiquidity(sharesToBurn, marketIndex, {
|
|
1207
|
+
accounts: {
|
|
1208
|
+
state: await this.getStatePublicKey(),
|
|
1209
|
+
user: userAccountPublicKey,
|
|
1210
|
+
authority: this.wallet.publicKey,
|
|
1211
|
+
},
|
|
1212
|
+
remainingAccounts: remainingAccounts,
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
public async addLiquidity(
|
|
1217
|
+
amount: BN,
|
|
1218
|
+
marketIndex: BN
|
|
1219
|
+
): Promise<TransactionSignature> {
|
|
1220
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1221
|
+
wrapInTx(await this.getAddLiquidityIx(amount, marketIndex)),
|
|
1222
|
+
[],
|
|
1223
|
+
this.opts
|
|
1224
|
+
);
|
|
1225
|
+
this.marketLastSlotCache.set(marketIndex.toNumber(), slot);
|
|
1226
|
+
return txSig;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
public async getAddLiquidityIx(
|
|
1230
|
+
amount: BN,
|
|
1231
|
+
marketIndex: BN
|
|
1232
|
+
): Promise<TransactionInstruction> {
|
|
1233
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1234
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1235
|
+
writableMarketIndex: marketIndex,
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
return this.program.instruction.addLiquidity(amount, marketIndex, {
|
|
1239
|
+
accounts: {
|
|
1240
|
+
state: await this.getStatePublicKey(),
|
|
1241
|
+
user: userAccountPublicKey,
|
|
1242
|
+
authority: this.wallet.publicKey,
|
|
1243
|
+
},
|
|
1244
|
+
remainingAccounts: remainingAccounts,
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
|
|
805
1248
|
public async openPosition(
|
|
806
1249
|
direction: PositionDirection,
|
|
807
1250
|
amount: BN,
|
|
@@ -840,13 +1283,14 @@ export class ClearingHouse {
|
|
|
840
1283
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
841
1284
|
|
|
842
1285
|
const remainingAccounts = this.getRemainingAccounts({
|
|
843
|
-
|
|
1286
|
+
readableMarketIndex: orderParams.marketIndex,
|
|
844
1287
|
});
|
|
845
1288
|
|
|
846
1289
|
return await this.program.instruction.placeOrder(orderParams, {
|
|
847
1290
|
accounts: {
|
|
848
1291
|
state: await this.getStatePublicKey(),
|
|
849
1292
|
user: userAccountPublicKey,
|
|
1293
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
850
1294
|
authority: this.wallet.publicKey,
|
|
851
1295
|
},
|
|
852
1296
|
remainingAccounts,
|
|
@@ -974,7 +1418,13 @@ export class ClearingHouse {
|
|
|
974
1418
|
order: Order,
|
|
975
1419
|
makerInfo?: MakerInfo
|
|
976
1420
|
): Promise<TransactionInstruction> {
|
|
1421
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
1422
|
+
this.program.programId,
|
|
1423
|
+
userAccount.authority
|
|
1424
|
+
);
|
|
1425
|
+
|
|
977
1426
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1427
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
978
1428
|
|
|
979
1429
|
const marketIndex = order.marketIndex;
|
|
980
1430
|
const marketAccount = this.getMarketAccount(marketIndex);
|
|
@@ -983,24 +1433,13 @@ export class ClearingHouse {
|
|
|
983
1433
|
const bankAccountMap = new Map<number, AccountMeta>();
|
|
984
1434
|
const marketAccountMap = new Map<number, AccountMeta>();
|
|
985
1435
|
|
|
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
1436
|
for (const bankBalance of userAccount.bankBalances) {
|
|
998
1437
|
if (!bankBalance.balance.eq(ZERO)) {
|
|
999
1438
|
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1000
1439
|
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1001
1440
|
pubkey: bankAccount.pubkey,
|
|
1002
1441
|
isSigner: false,
|
|
1003
|
-
isWritable:
|
|
1442
|
+
isWritable: false,
|
|
1004
1443
|
});
|
|
1005
1444
|
|
|
1006
1445
|
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
@@ -1021,7 +1460,7 @@ export class ClearingHouse {
|
|
|
1021
1460
|
const market = this.getMarketAccount(position.marketIndex);
|
|
1022
1461
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1023
1462
|
pubkey: market.pubkey,
|
|
1024
|
-
isWritable:
|
|
1463
|
+
isWritable: false,
|
|
1025
1464
|
isSigner: false,
|
|
1026
1465
|
});
|
|
1027
1466
|
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
@@ -1032,6 +1471,17 @@ export class ClearingHouse {
|
|
|
1032
1471
|
}
|
|
1033
1472
|
}
|
|
1034
1473
|
|
|
1474
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1475
|
+
pubkey: marketAccount.pubkey,
|
|
1476
|
+
isWritable: true,
|
|
1477
|
+
isSigner: false,
|
|
1478
|
+
});
|
|
1479
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1480
|
+
pubkey: marketAccount.amm.oracle,
|
|
1481
|
+
isWritable: false,
|
|
1482
|
+
isSigner: false,
|
|
1483
|
+
});
|
|
1484
|
+
|
|
1035
1485
|
const remainingAccounts = [
|
|
1036
1486
|
...oracleAccountMap.values(),
|
|
1037
1487
|
...bankAccountMap.values(),
|
|
@@ -1044,6 +1494,11 @@ export class ClearingHouse {
|
|
|
1044
1494
|
isWritable: true,
|
|
1045
1495
|
isSigner: false,
|
|
1046
1496
|
});
|
|
1497
|
+
remainingAccounts.push({
|
|
1498
|
+
pubkey: makerInfo.makerStats,
|
|
1499
|
+
isWritable: true,
|
|
1500
|
+
isSigner: false,
|
|
1501
|
+
});
|
|
1047
1502
|
}
|
|
1048
1503
|
|
|
1049
1504
|
const orderId = order.orderId;
|
|
@@ -1053,7 +1508,9 @@ export class ClearingHouse {
|
|
|
1053
1508
|
accounts: {
|
|
1054
1509
|
state: await this.getStatePublicKey(),
|
|
1055
1510
|
filler: fillerPublicKey,
|
|
1511
|
+
fillerStats: fillerStatsPublicKey,
|
|
1056
1512
|
user: userAccountPublicKey,
|
|
1513
|
+
userStats: userStatsPublicKey,
|
|
1057
1514
|
authority: this.wallet.publicKey,
|
|
1058
1515
|
},
|
|
1059
1516
|
remainingAccounts,
|
|
@@ -1087,24 +1544,13 @@ export class ClearingHouse {
|
|
|
1087
1544
|
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1088
1545
|
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1089
1546
|
|
|
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
1547
|
for (const bankBalance of userAccount.bankBalances) {
|
|
1102
1548
|
if (!bankBalance.balance.eq(ZERO)) {
|
|
1103
1549
|
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1104
1550
|
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1105
1551
|
pubkey: bankAccount.pubkey,
|
|
1106
1552
|
isSigner: false,
|
|
1107
|
-
isWritable:
|
|
1553
|
+
isWritable: false,
|
|
1108
1554
|
});
|
|
1109
1555
|
|
|
1110
1556
|
if (!bankAccount.oracle.equals(PublicKey.default)) {
|
|
@@ -1125,7 +1571,7 @@ export class ClearingHouse {
|
|
|
1125
1571
|
const market = this.getMarketAccount(position.marketIndex);
|
|
1126
1572
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1127
1573
|
pubkey: market.pubkey,
|
|
1128
|
-
isWritable:
|
|
1574
|
+
isWritable: false,
|
|
1129
1575
|
isSigner: false,
|
|
1130
1576
|
});
|
|
1131
1577
|
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
@@ -1136,6 +1582,17 @@ export class ClearingHouse {
|
|
|
1136
1582
|
}
|
|
1137
1583
|
}
|
|
1138
1584
|
|
|
1585
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1586
|
+
pubkey: marketAccount.pubkey,
|
|
1587
|
+
isWritable: true,
|
|
1588
|
+
isSigner: false,
|
|
1589
|
+
});
|
|
1590
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1591
|
+
pubkey: marketAccount.amm.oracle,
|
|
1592
|
+
isWritable: false,
|
|
1593
|
+
isSigner: false,
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1139
1596
|
const remainingAccounts = [
|
|
1140
1597
|
...oracleAccountMap.values(),
|
|
1141
1598
|
...bankAccountMap.values(),
|
|
@@ -1172,6 +1629,7 @@ export class ClearingHouse {
|
|
|
1172
1629
|
makerInfo?: MakerInfo
|
|
1173
1630
|
): Promise<TransactionInstruction> {
|
|
1174
1631
|
orderParams = this.getOrderParams(orderParams);
|
|
1632
|
+
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
1175
1633
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1176
1634
|
|
|
1177
1635
|
const remainingAccounts = this.getRemainingAccounts({
|
|
@@ -1187,6 +1645,11 @@ export class ClearingHouse {
|
|
|
1187
1645
|
isSigner: false,
|
|
1188
1646
|
isWritable: true,
|
|
1189
1647
|
});
|
|
1648
|
+
remainingAccounts.push({
|
|
1649
|
+
pubkey: makerInfo.makerStats,
|
|
1650
|
+
isSigner: false,
|
|
1651
|
+
isWritable: true,
|
|
1652
|
+
});
|
|
1190
1653
|
}
|
|
1191
1654
|
|
|
1192
1655
|
return await this.program.instruction.placeAndTake(
|
|
@@ -1196,6 +1659,7 @@ export class ClearingHouse {
|
|
|
1196
1659
|
accounts: {
|
|
1197
1660
|
state: await this.getStatePublicKey(),
|
|
1198
1661
|
user: userAccountPublicKey,
|
|
1662
|
+
userStats: userStatsPublicKey,
|
|
1199
1663
|
authority: this.wallet.publicKey,
|
|
1200
1664
|
},
|
|
1201
1665
|
remainingAccounts,
|
|
@@ -1223,20 +1687,14 @@ export class ClearingHouse {
|
|
|
1223
1687
|
takerInfo: TakerInfo
|
|
1224
1688
|
): Promise<TransactionInstruction> {
|
|
1225
1689
|
orderParams = this.getOrderParams(orderParams);
|
|
1690
|
+
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1226
1691
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1227
1692
|
|
|
1228
1693
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1229
1694
|
writableMarketIndex: orderParams.marketIndex,
|
|
1230
|
-
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1231
1695
|
});
|
|
1232
1696
|
|
|
1233
1697
|
const takerOrderId = takerInfo!.order!.orderId;
|
|
1234
|
-
remainingAccounts.push({
|
|
1235
|
-
pubkey: takerInfo.taker,
|
|
1236
|
-
isSigner: false,
|
|
1237
|
-
isWritable: true,
|
|
1238
|
-
});
|
|
1239
|
-
|
|
1240
1698
|
return await this.program.instruction.placeAndMake(
|
|
1241
1699
|
orderParams,
|
|
1242
1700
|
takerOrderId,
|
|
@@ -1244,7 +1702,9 @@ export class ClearingHouse {
|
|
|
1244
1702
|
accounts: {
|
|
1245
1703
|
state: await this.getStatePublicKey(),
|
|
1246
1704
|
user: userAccountPublicKey,
|
|
1705
|
+
userStats: userStatsPublicKey,
|
|
1247
1706
|
taker: takerInfo.taker,
|
|
1707
|
+
takerStats: takerInfo.takerStats,
|
|
1248
1708
|
authority: this.wallet.publicKey,
|
|
1249
1709
|
},
|
|
1250
1710
|
remainingAccounts,
|
|
@@ -1257,7 +1717,10 @@ export class ClearingHouse {
|
|
|
1257
1717
|
* @param marketIndex
|
|
1258
1718
|
* @returns
|
|
1259
1719
|
*/
|
|
1260
|
-
public async closePosition(
|
|
1720
|
+
public async closePosition(
|
|
1721
|
+
marketIndex: BN,
|
|
1722
|
+
limitPrice?: BN
|
|
1723
|
+
): Promise<TransactionSignature> {
|
|
1261
1724
|
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
1262
1725
|
if (!userPosition) {
|
|
1263
1726
|
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
@@ -1267,8 +1730,9 @@ export class ClearingHouse {
|
|
|
1267
1730
|
orderType: OrderType.MARKET,
|
|
1268
1731
|
marketIndex,
|
|
1269
1732
|
direction: findDirectionToClose(userPosition),
|
|
1270
|
-
baseAssetAmount: userPosition.baseAssetAmount,
|
|
1733
|
+
baseAssetAmount: userPosition.baseAssetAmount.abs(),
|
|
1271
1734
|
reduceOnly: true,
|
|
1735
|
+
price: limitPrice,
|
|
1272
1736
|
});
|
|
1273
1737
|
}
|
|
1274
1738
|
|
|
@@ -1323,12 +1787,13 @@ export class ClearingHouse {
|
|
|
1323
1787
|
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1324
1788
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1325
1789
|
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1790
|
+
|
|
1326
1791
|
for (const position of settleeUserAccount.positions) {
|
|
1327
1792
|
if (!positionIsAvailable(position)) {
|
|
1328
1793
|
const market = this.getMarketAccount(position.marketIndex);
|
|
1329
1794
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1330
1795
|
pubkey: market.pubkey,
|
|
1331
|
-
isWritable:
|
|
1796
|
+
isWritable: false,
|
|
1332
1797
|
isSigner: false,
|
|
1333
1798
|
});
|
|
1334
1799
|
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
@@ -1418,7 +1883,13 @@ export class ClearingHouse {
|
|
|
1418
1883
|
marketIndex: BN,
|
|
1419
1884
|
maxBaseAssetAmount: BN
|
|
1420
1885
|
): Promise<TransactionInstruction> {
|
|
1886
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
1887
|
+
this.program.programId,
|
|
1888
|
+
userAccount.authority
|
|
1889
|
+
);
|
|
1890
|
+
|
|
1421
1891
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1892
|
+
const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1422
1893
|
|
|
1423
1894
|
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
1424
1895
|
writableMarketIndex: marketIndex,
|
|
@@ -1433,7 +1904,9 @@ export class ClearingHouse {
|
|
|
1433
1904
|
state: await this.getStatePublicKey(),
|
|
1434
1905
|
authority: this.wallet.publicKey,
|
|
1435
1906
|
user: userAccountPublicKey,
|
|
1907
|
+
userStats: userStatsPublicKey,
|
|
1436
1908
|
liquidator: liquidatorPublicKey,
|
|
1909
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
1437
1910
|
},
|
|
1438
1911
|
remainingAccounts: remainingAccounts,
|
|
1439
1912
|
}
|
|
@@ -1601,6 +2074,90 @@ export class ClearingHouse {
|
|
|
1601
2074
|
);
|
|
1602
2075
|
}
|
|
1603
2076
|
|
|
2077
|
+
public async resolvePerpBankruptcy(
|
|
2078
|
+
userAccountPublicKey: PublicKey,
|
|
2079
|
+
userAccount: UserAccount,
|
|
2080
|
+
marketIndex: BN
|
|
2081
|
+
): Promise<TransactionSignature> {
|
|
2082
|
+
const { txSig } = await this.txSender.send(
|
|
2083
|
+
wrapInTx(
|
|
2084
|
+
await this.getResolvePerpBankruptcyIx(
|
|
2085
|
+
userAccountPublicKey,
|
|
2086
|
+
userAccount,
|
|
2087
|
+
marketIndex
|
|
2088
|
+
)
|
|
2089
|
+
),
|
|
2090
|
+
[],
|
|
2091
|
+
this.opts
|
|
2092
|
+
);
|
|
2093
|
+
return txSig;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
public async getResolvePerpBankruptcyIx(
|
|
2097
|
+
userAccountPublicKey: PublicKey,
|
|
2098
|
+
userAccount: UserAccount,
|
|
2099
|
+
marketIndex: BN
|
|
2100
|
+
): Promise<TransactionInstruction> {
|
|
2101
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2102
|
+
|
|
2103
|
+
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
2104
|
+
writableMarketIndex: marketIndex,
|
|
2105
|
+
userAccount,
|
|
2106
|
+
});
|
|
2107
|
+
|
|
2108
|
+
return await this.program.instruction.resolvePerpBankruptcy(marketIndex, {
|
|
2109
|
+
accounts: {
|
|
2110
|
+
state: await this.getStatePublicKey(),
|
|
2111
|
+
authority: this.wallet.publicKey,
|
|
2112
|
+
user: userAccountPublicKey,
|
|
2113
|
+
liquidator: liquidatorPublicKey,
|
|
2114
|
+
},
|
|
2115
|
+
remainingAccounts: remainingAccounts,
|
|
2116
|
+
});
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
public async resolveBorrowBankruptcy(
|
|
2120
|
+
userAccountPublicKey: PublicKey,
|
|
2121
|
+
userAccount: UserAccount,
|
|
2122
|
+
bankIndex: BN
|
|
2123
|
+
): Promise<TransactionSignature> {
|
|
2124
|
+
const { txSig } = await this.txSender.send(
|
|
2125
|
+
wrapInTx(
|
|
2126
|
+
await this.getResolveBorrowBankruptcyIx(
|
|
2127
|
+
userAccountPublicKey,
|
|
2128
|
+
userAccount,
|
|
2129
|
+
bankIndex
|
|
2130
|
+
)
|
|
2131
|
+
),
|
|
2132
|
+
[],
|
|
2133
|
+
this.opts
|
|
2134
|
+
);
|
|
2135
|
+
return txSig;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
public async getResolveBorrowBankruptcyIx(
|
|
2139
|
+
userAccountPublicKey: PublicKey,
|
|
2140
|
+
userAccount: UserAccount,
|
|
2141
|
+
bankIndex: BN
|
|
2142
|
+
): Promise<TransactionInstruction> {
|
|
2143
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2144
|
+
|
|
2145
|
+
const remainingAccounts = this.getRemainingAccountsForLiquidation({
|
|
2146
|
+
writableBankIndexes: [bankIndex],
|
|
2147
|
+
userAccount,
|
|
2148
|
+
});
|
|
2149
|
+
|
|
2150
|
+
return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
|
|
2151
|
+
accounts: {
|
|
2152
|
+
state: await this.getStatePublicKey(),
|
|
2153
|
+
authority: this.wallet.publicKey,
|
|
2154
|
+
user: userAccountPublicKey,
|
|
2155
|
+
liquidator: liquidatorPublicKey,
|
|
2156
|
+
},
|
|
2157
|
+
remainingAccounts: remainingAccounts,
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
|
|
1604
2161
|
getRemainingAccountsForLiquidation(params: {
|
|
1605
2162
|
userAccount: UserAccount;
|
|
1606
2163
|
writableMarketIndex?: BN;
|