@drift-labs/sdk 0.2.0-master.11 → 0.2.0-master.12

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.
Files changed (72) hide show
  1. package/lib/clearingHouse.d.ts +7 -2
  2. package/lib/clearingHouse.js +157 -37
  3. package/lib/clearingHouseUser.d.ts +10 -15
  4. package/lib/clearingHouseUser.js +92 -74
  5. package/lib/config.js +1 -1
  6. package/lib/constants/banks.d.ts +2 -2
  7. package/lib/constants/banks.js +4 -3
  8. package/lib/constants/numericConstants.d.ts +2 -0
  9. package/lib/constants/numericConstants.js +3 -1
  10. package/lib/events/eventList.js +3 -0
  11. package/lib/events/types.d.ts +2 -1
  12. package/lib/factory/bigNum.d.ts +1 -0
  13. package/lib/factory/bigNum.js +37 -11
  14. package/lib/idl/clearing_house.json +97 -19
  15. package/lib/index.d.ts +1 -0
  16. package/lib/index.js +1 -0
  17. package/lib/math/bankBalance.d.ts +3 -1
  18. package/lib/math/bankBalance.js +54 -1
  19. package/lib/math/margin.d.ts +11 -0
  20. package/lib/math/margin.js +72 -0
  21. package/lib/math/market.d.ts +4 -1
  22. package/lib/math/market.js +35 -1
  23. package/lib/math/position.d.ts +8 -0
  24. package/lib/math/position.js +42 -12
  25. package/lib/orders.d.ts +1 -2
  26. package/lib/orders.js +2 -77
  27. package/lib/tokenFaucet.d.ts +1 -0
  28. package/lib/tokenFaucet.js +23 -12
  29. package/lib/tx/retryTxSender.js +9 -2
  30. package/lib/types.d.ts +24 -3
  31. package/lib/types.js +6 -0
  32. package/lib/util/getTokenAddress.d.ts +2 -0
  33. package/lib/util/getTokenAddress.js +9 -0
  34. package/package.json +1 -1
  35. package/src/clearingHouse.ts +301 -47
  36. package/src/clearingHouseConfig.js +2 -0
  37. package/src/clearingHouseUser.ts +213 -104
  38. package/src/clearingHouseUserConfig.js +2 -0
  39. package/src/config.ts +1 -1
  40. package/src/constants/banks.js +42 -0
  41. package/src/constants/banks.ts +6 -3
  42. package/src/constants/markets.js +42 -0
  43. package/src/constants/numericConstants.js +41 -0
  44. package/src/constants/numericConstants.ts +3 -0
  45. package/src/events/eventList.ts +3 -0
  46. package/src/events/types.ts +2 -0
  47. package/src/factory/bigNum.js +37 -11
  48. package/src/factory/bigNum.ts +43 -13
  49. package/src/idl/clearing_house.json +97 -19
  50. package/src/index.js +67 -98
  51. package/src/index.ts +1 -0
  52. package/src/math/bankBalance.ts +98 -1
  53. package/src/math/margin.ts +124 -0
  54. package/src/math/market.ts +66 -1
  55. package/src/math/position.ts +59 -9
  56. package/src/orders.ts +4 -157
  57. package/src/tokenFaucet.js +189 -0
  58. package/src/tokenFaucet.ts +38 -15
  59. package/src/tx/retryTxSender.ts +11 -3
  60. package/src/types.js +12 -1
  61. package/src/types.ts +25 -3
  62. package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
  63. package/src/util/getTokenAddress.js +9 -0
  64. package/src/util/getTokenAddress.ts +18 -0
  65. package/tests/bn/test.ts +2 -0
  66. package/src/addresses/pda.js +0 -104
  67. package/src/math/bankBalance.js +0 -75
  68. package/src/math/market.js +0 -57
  69. package/src/math/orders.js +0 -110
  70. package/src/math/position.js +0 -140
  71. package/src/orders.js +0 -134
  72. package/src/tx/retryTxSender.js +0 -188
@@ -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';
@@ -57,6 +61,7 @@ import { RetryTxSender } from './tx/retryTxSender';
57
61
  import { ClearingHouseUser } from './clearingHouseUser';
58
62
  import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
59
63
  import { getMarketsBanksAndOraclesForSubscription } from './config';
64
+ import { WRAPPED_SOL_MINT } from './constants/banks';
60
65
 
61
66
  /**
62
67
  * # ClearingHouse
@@ -399,6 +404,7 @@ export class ClearingHouse {
399
404
  getRemainingAccounts(params: {
400
405
  writableMarketIndex?: BN;
401
406
  writableBankIndex?: BN;
407
+ readableMarketIndex?: BN;
402
408
  }): AccountMeta[] {
403
409
  const userAccountAndSlot = this.getUserAccountAndSlot();
404
410
  if (!userAccountAndSlot) {
@@ -439,8 +445,7 @@ export class ClearingHouse {
439
445
  marketAccountMap.set(marketIndexNum, {
440
446
  pubkey: marketAccount.pubkey,
441
447
  isSigner: false,
442
- // isWritable: false, // TODO
443
- isWritable: true,
448
+ isWritable: false,
444
449
  });
445
450
  oracleAccountMap.set(marketAccount.pubkey.toString(), {
446
451
  pubkey: marketAccount.amm.oracle,
@@ -450,6 +455,22 @@ export class ClearingHouse {
450
455
  }
451
456
  }
452
457
 
458
+ if (params.readableMarketIndex) {
459
+ const marketAccount = this.getMarketAccount(
460
+ params.readableMarketIndex.toNumber()
461
+ );
462
+ marketAccountMap.set(params.readableMarketIndex.toNumber(), {
463
+ pubkey: marketAccount.pubkey,
464
+ isSigner: false,
465
+ isWritable: true,
466
+ });
467
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
468
+ pubkey: marketAccount.amm.oracle,
469
+ isSigner: false,
470
+ isWritable: false,
471
+ });
472
+ }
473
+
453
474
  if (params.writableMarketIndex) {
454
475
  const marketAccount = this.getMarketAccount(
455
476
  params.writableMarketIndex.toNumber()
@@ -527,6 +548,31 @@ export class ClearingHouse {
527
548
  userId?: number,
528
549
  reduceOnly = false
529
550
  ): Promise<TransactionSignature> {
551
+ const tx = new Transaction();
552
+ const additionalSigners: Array<Signer> = [];
553
+
554
+ const bank = this.getBankAccount(bankIndex);
555
+
556
+ const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
557
+
558
+ const authority = this.wallet.publicKey;
559
+
560
+ const createWSOLTokenAccount =
561
+ isSolBank && collateralAccountPublicKey.equals(authority);
562
+
563
+ if (createWSOLTokenAccount) {
564
+ const { ixs, signers, pubkey } =
565
+ await this.getWrappedSolAccountCreationIxs(amount);
566
+
567
+ collateralAccountPublicKey = pubkey;
568
+
569
+ ixs.forEach((ix) => {
570
+ tx.add(ix);
571
+ });
572
+
573
+ signers.forEach((signer) => additionalSigners.push(signer));
574
+ }
575
+
530
576
  const depositCollateralIx = await this.getDepositInstruction(
531
577
  amount,
532
578
  bankIndex,
@@ -536,9 +582,26 @@ export class ClearingHouse {
536
582
  true
537
583
  );
538
584
 
539
- const tx = new Transaction().add(depositCollateralIx);
585
+ tx.add(depositCollateralIx);
586
+
587
+ // Close the wrapped sol account at the end of the transaction
588
+ if (createWSOLTokenAccount) {
589
+ tx.add(
590
+ Token.createCloseAccountInstruction(
591
+ TOKEN_PROGRAM_ID,
592
+ collateralAccountPublicKey,
593
+ authority,
594
+ authority,
595
+ []
596
+ )
597
+ );
598
+ }
540
599
 
541
- const { txSig } = await this.txSender.send(tx);
600
+ const { txSig } = await this.txSender.send(
601
+ tx,
602
+ additionalSigners,
603
+ this.opts
604
+ );
542
605
  return txSig;
543
606
  }
544
607
 
@@ -600,12 +663,119 @@ export class ClearingHouse {
600
663
  );
601
664
  }
602
665
 
666
+ private async checkIfAccountExists(account: PublicKey) {
667
+ try {
668
+ const accountInfo = await this.connection.getAccountInfo(account);
669
+ return accountInfo && true;
670
+ } catch (e) {
671
+ // Doesn't already exist
672
+ return false;
673
+ }
674
+ }
675
+
676
+ private async getSolWithdrawalIxs(
677
+ bankIndex: BN,
678
+ amount: BN
679
+ ): Promise<{
680
+ ixs: anchor.web3.TransactionInstruction[];
681
+ signers: Signer[];
682
+ pubkey: PublicKey;
683
+ }> {
684
+ const result = {
685
+ ixs: [],
686
+ signers: [],
687
+ pubkey: PublicKey.default,
688
+ };
689
+
690
+ // Create a temporary wrapped SOL account to store the SOL that we're withdrawing
691
+
692
+ const authority = this.wallet.publicKey;
693
+
694
+ const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(
695
+ amount
696
+ );
697
+ result.pubkey = pubkey;
698
+
699
+ ixs.forEach((ix) => {
700
+ result.ixs.push(ix);
701
+ });
702
+
703
+ signers.forEach((ix) => {
704
+ result.signers.push(ix);
705
+ });
706
+
707
+ const withdrawIx = await this.getWithdrawIx(
708
+ amount,
709
+ bankIndex,
710
+ pubkey,
711
+ true
712
+ );
713
+
714
+ result.ixs.push(withdrawIx);
715
+
716
+ result.ixs.push(
717
+ Token.createCloseAccountInstruction(
718
+ TOKEN_PROGRAM_ID,
719
+ pubkey,
720
+ authority,
721
+ authority,
722
+ []
723
+ )
724
+ );
725
+
726
+ return result;
727
+ }
728
+
729
+ private async getWrappedSolAccountCreationIxs(amount: BN): Promise<{
730
+ ixs: anchor.web3.TransactionInstruction[];
731
+ signers: Signer[];
732
+ pubkey: PublicKey;
733
+ }> {
734
+ const wrappedSolAccount = new Keypair();
735
+
736
+ const result = {
737
+ ixs: [],
738
+ signers: [],
739
+ pubkey: wrappedSolAccount.publicKey,
740
+ };
741
+
742
+ const rentSpaceLamports = new BN(LAMPORTS_PER_SOL / 100);
743
+
744
+ const depositAmountLamports = amount.add(rentSpaceLamports);
745
+
746
+ const authority = this.wallet.publicKey;
747
+
748
+ result.ixs.push(
749
+ SystemProgram.createAccount({
750
+ fromPubkey: authority,
751
+ newAccountPubkey: wrappedSolAccount.publicKey,
752
+ lamports: depositAmountLamports.toNumber(),
753
+ space: 165,
754
+ programId: TOKEN_PROGRAM_ID,
755
+ })
756
+ );
757
+
758
+ result.ixs.push(
759
+ Token.createInitAccountInstruction(
760
+ TOKEN_PROGRAM_ID,
761
+ WRAPPED_SOL_MINT,
762
+ wrappedSolAccount.publicKey,
763
+ authority
764
+ )
765
+ );
766
+
767
+ result.signers.push(wrappedSolAccount);
768
+
769
+ return result;
770
+ }
771
+
603
772
  /**
604
773
  * Creates the Clearing House User account for a user, and deposits some initial collateral
605
- * @param userId
606
- * @param name
607
774
  * @param amount
608
775
  * @param userTokenAccount
776
+ * @param bankIndex
777
+ * @param userId
778
+ * @param name
609
779
  * @param fromUserId
610
780
  * @returns
611
781
  */
@@ -620,6 +790,35 @@ export class ClearingHouse {
620
790
  const [userAccountPublicKey, initializeUserAccountIx] =
621
791
  await this.getInitializeUserInstructions(userId, name);
622
792
 
793
+ const additionalSigners: Array<Signer> = [];
794
+
795
+ const bank = this.getBankAccount(bankIndex);
796
+
797
+ const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
798
+
799
+ const tx = new Transaction();
800
+
801
+ const authority = this.wallet.publicKey;
802
+
803
+ const createWSOLTokenAccount =
804
+ isSolBank && userTokenAccount.equals(authority);
805
+
806
+ if (createWSOLTokenAccount) {
807
+ const {
808
+ ixs: startIxs,
809
+ signers,
810
+ pubkey,
811
+ } = await this.getWrappedSolAccountCreationIxs(amount);
812
+
813
+ userTokenAccount = pubkey;
814
+
815
+ startIxs.forEach((ix) => {
816
+ tx.add(ix);
817
+ });
818
+
819
+ signers.forEach((signer) => additionalSigners.push(signer));
820
+ }
821
+
623
822
  const depositCollateralIx =
624
823
  fromUserId != null
625
824
  ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
@@ -632,11 +831,26 @@ export class ClearingHouse {
632
831
  false
633
832
  );
634
833
 
635
- const tx = new Transaction()
636
- .add(initializeUserAccountIx)
637
- .add(depositCollateralIx);
834
+ tx.add(initializeUserAccountIx).add(depositCollateralIx);
638
835
 
639
- const { txSig } = await this.txSender.send(tx, []);
836
+ // Close the wrapped sol account at the end of the transaction
837
+ if (createWSOLTokenAccount) {
838
+ tx.add(
839
+ Token.createCloseAccountInstruction(
840
+ TOKEN_PROGRAM_ID,
841
+ userTokenAccount,
842
+ authority,
843
+ authority,
844
+ []
845
+ )
846
+ );
847
+ }
848
+
849
+ const { txSig } = await this.txSender.send(
850
+ tx,
851
+ additionalSigners,
852
+ this.opts
853
+ );
640
854
 
641
855
  return [txSig, userAccountPublicKey];
642
856
  }
@@ -683,16 +897,56 @@ export class ClearingHouse {
683
897
  userTokenAccount: PublicKey,
684
898
  reduceOnly = false
685
899
  ): Promise<TransactionSignature> {
686
- const { txSig } = await this.txSender.send(
687
- wrapInTx(
688
- await this.getWithdrawIx(
689
- amount,
690
- bankIndex,
900
+ const tx = new Transaction();
901
+ const additionalSigners: Array<Signer> = [];
902
+
903
+ const bank = this.getBankAccount(bankIndex);
904
+
905
+ const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
906
+
907
+ const authority = this.wallet.publicKey;
908
+
909
+ const createWSOLTokenAccount =
910
+ isSolBank && userTokenAccount.equals(authority);
911
+
912
+ if (createWSOLTokenAccount) {
913
+ const { ixs, signers, pubkey } =
914
+ await this.getWrappedSolAccountCreationIxs(amount);
915
+
916
+ userTokenAccount = pubkey;
917
+
918
+ ixs.forEach((ix) => {
919
+ tx.add(ix);
920
+ });
921
+
922
+ signers.forEach((signer) => additionalSigners.push(signer));
923
+ }
924
+
925
+ const withdrawCollateral = await this.getWithdrawIx(
926
+ amount,
927
+ bank.bankIndex,
928
+ userTokenAccount,
929
+ reduceOnly
930
+ );
931
+
932
+ tx.add(withdrawCollateral);
933
+
934
+ // Close the wrapped sol account at the end of the transaction
935
+ if (createWSOLTokenAccount) {
936
+ tx.add(
937
+ Token.createCloseAccountInstruction(
938
+ TOKEN_PROGRAM_ID,
691
939
  userTokenAccount,
692
- reduceOnly
940
+ authority,
941
+ authority,
942
+ []
693
943
  )
694
- ),
695
- [],
944
+ );
945
+ }
946
+
947
+ const { txSig } = await this.txSender.send(
948
+ tx,
949
+ additionalSigners,
696
950
  this.opts
697
951
  );
698
952
  return txSig;
@@ -840,7 +1094,7 @@ export class ClearingHouse {
840
1094
  const userAccountPublicKey = await this.getUserAccountPublicKey();
841
1095
 
842
1096
  const remainingAccounts = this.getRemainingAccounts({
843
- writableMarketIndex: orderParams.marketIndex,
1097
+ readableMarketIndex: orderParams.marketIndex,
844
1098
  });
845
1099
 
846
1100
  return await this.program.instruction.placeOrder(orderParams, {
@@ -983,24 +1237,13 @@ export class ClearingHouse {
983
1237
  const bankAccountMap = new Map<number, AccountMeta>();
984
1238
  const marketAccountMap = new Map<number, AccountMeta>();
985
1239
 
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
1240
  for (const bankBalance of userAccount.bankBalances) {
998
1241
  if (!bankBalance.balance.eq(ZERO)) {
999
1242
  const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1000
1243
  bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1001
1244
  pubkey: bankAccount.pubkey,
1002
1245
  isSigner: false,
1003
- isWritable: true,
1246
+ isWritable: false,
1004
1247
  });
1005
1248
 
1006
1249
  if (!bankAccount.oracle.equals(PublicKey.default)) {
@@ -1021,7 +1264,7 @@ export class ClearingHouse {
1021
1264
  const market = this.getMarketAccount(position.marketIndex);
1022
1265
  marketAccountMap.set(position.marketIndex.toNumber(), {
1023
1266
  pubkey: market.pubkey,
1024
- isWritable: true,
1267
+ isWritable: false,
1025
1268
  isSigner: false,
1026
1269
  });
1027
1270
  oracleAccountMap.set(market.amm.oracle.toString(), {
@@ -1032,6 +1275,17 @@ export class ClearingHouse {
1032
1275
  }
1033
1276
  }
1034
1277
 
1278
+ marketAccountMap.set(marketIndex.toNumber(), {
1279
+ pubkey: marketAccount.pubkey,
1280
+ isWritable: true,
1281
+ isSigner: false,
1282
+ });
1283
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1284
+ pubkey: marketAccount.amm.oracle,
1285
+ isWritable: false,
1286
+ isSigner: false,
1287
+ });
1288
+
1035
1289
  const remainingAccounts = [
1036
1290
  ...oracleAccountMap.values(),
1037
1291
  ...bankAccountMap.values(),
@@ -1087,24 +1341,13 @@ export class ClearingHouse {
1087
1341
  const bankAccountMap = new Map<number, AccountMeta>();
1088
1342
  const marketAccountMap = new Map<number, AccountMeta>();
1089
1343
 
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
1344
  for (const bankBalance of userAccount.bankBalances) {
1102
1345
  if (!bankBalance.balance.eq(ZERO)) {
1103
1346
  const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1104
1347
  bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1105
1348
  pubkey: bankAccount.pubkey,
1106
1349
  isSigner: false,
1107
- isWritable: true,
1350
+ isWritable: false,
1108
1351
  });
1109
1352
 
1110
1353
  if (!bankAccount.oracle.equals(PublicKey.default)) {
@@ -1125,7 +1368,7 @@ export class ClearingHouse {
1125
1368
  const market = this.getMarketAccount(position.marketIndex);
1126
1369
  marketAccountMap.set(position.marketIndex.toNumber(), {
1127
1370
  pubkey: market.pubkey,
1128
- isWritable: true,
1371
+ isWritable: false,
1129
1372
  isSigner: false,
1130
1373
  });
1131
1374
  oracleAccountMap.set(market.amm.oracle.toString(), {
@@ -1136,6 +1379,17 @@ export class ClearingHouse {
1136
1379
  }
1137
1380
  }
1138
1381
 
1382
+ marketAccountMap.set(marketIndex.toNumber(), {
1383
+ pubkey: marketAccount.pubkey,
1384
+ isWritable: true,
1385
+ isSigner: false,
1386
+ });
1387
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1388
+ pubkey: marketAccount.amm.oracle,
1389
+ isWritable: false,
1390
+ isSigner: false,
1391
+ });
1392
+
1139
1393
  const remainingAccounts = [
1140
1394
  ...oracleAccountMap.values(),
1141
1395
  ...bankAccountMap.values(),
@@ -1328,7 +1582,7 @@ export class ClearingHouse {
1328
1582
  const market = this.getMarketAccount(position.marketIndex);
1329
1583
  marketAccountMap.set(position.marketIndex.toNumber(), {
1330
1584
  pubkey: market.pubkey,
1331
- isWritable: true, // TODO
1585
+ isWritable: false,
1332
1586
  isSigner: false,
1333
1587
  });
1334
1588
  oracleAccountMap.set(market.amm.oracle.toString(), {
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });