@drift-labs/sdk 0.2.0-master.18 → 0.2.0-master.20

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/index.d.ts CHANGED
@@ -40,7 +40,6 @@ export * from './math/trade';
40
40
  export * from './math/orders';
41
41
  export * from './math/repeg';
42
42
  export * from './math/margin';
43
- export * from './orders';
44
43
  export * from './orderParams';
45
44
  export * from './slot/SlotSubscriber';
46
45
  export * from './wallet';
package/lib/index.js CHANGED
@@ -63,7 +63,6 @@ __exportStar(require("./math/trade"), exports);
63
63
  __exportStar(require("./math/orders"), exports);
64
64
  __exportStar(require("./math/repeg"), exports);
65
65
  __exportStar(require("./math/margin"), exports);
66
- __exportStar(require("./orders"), exports);
67
66
  __exportStar(require("./orderParams"), exports);
68
67
  __exportStar(require("./slot/SlotSubscriber"), exports);
69
68
  __exportStar(require("./wallet"), exports);
package/lib/math/amm.d.ts CHANGED
@@ -67,3 +67,4 @@ export declare function getSwapDirection(inputAssetType: AssetType, positionDire
67
67
  export declare function calculateTerminalPrice(market: MarketAccount): BN;
68
68
  export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, limit_price: BN, direction: PositionDirection, oraclePriceData?: OraclePriceData): [BN, PositionDirection];
69
69
  export declare function calculateQuoteAssetAmountSwapped(quoteAssetReserves: BN, pegMultiplier: BN, swapDirection: SwapDirection): BN;
70
+ export declare function calculateMaxBaseAssetAmountFillable(amm: AMM, orderDirection: PositionDirection): BN;
package/lib/math/amm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateSpreadBN = exports.calculateMaxSpread = exports.calculateEffectiveLeverage = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = exports.calculateOptimalPegAndBudget = exports.calculatePegFromTargetPrice = void 0;
3
+ exports.calculateMaxBaseAssetAmountFillable = exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateSpreadBN = exports.calculateMaxSpread = exports.calculateEffectiveLeverage = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = exports.calculateOptimalPegAndBudget = exports.calculatePegFromTargetPrice = void 0;
4
4
  const anchor_1 = require("@project-serum/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
@@ -367,3 +367,15 @@ function calculateQuoteAssetAmountSwapped(quoteAssetReserves, pegMultiplier, swa
367
367
  return quoteAssetAmount;
368
368
  }
369
369
  exports.calculateQuoteAssetAmountSwapped = calculateQuoteAssetAmountSwapped;
370
+ function calculateMaxBaseAssetAmountFillable(amm, orderDirection) {
371
+ const maxFillSize = amm.baseAssetReserve.div(new anchor_1.BN(amm.maxBaseAssetAmountRatio));
372
+ let maxBaseAssetAmountOnSide;
373
+ if ((0, types_1.isVariant)(orderDirection, 'long')) {
374
+ maxBaseAssetAmountOnSide = anchor_1.BN.max(numericConstants_1.ZERO, amm.maxBaseAssetReserve.sub(amm.baseAssetReserve));
375
+ }
376
+ else {
377
+ maxBaseAssetAmountOnSide = anchor_1.BN.max(numericConstants_1.ZERO, amm.baseAssetReserve.sub(amm.minBaseAssetReserve));
378
+ }
379
+ return (0, __1.standardizeBaseAssetAmount)(anchor_1.BN.min(maxFillSize, maxBaseAssetAmountOnSide), amm.baseAssetAmountStepSize);
380
+ }
381
+ exports.calculateMaxBaseAssetAmountFillable = calculateMaxBaseAssetAmountFillable;
@@ -27,5 +27,5 @@ export declare function calculateNewMarketAfterTrade(baseAssetAmount: BN, direct
27
27
  export declare function calculateMarkOracleSpread(market: MarketAccount, oraclePriceData: OraclePriceData): BN;
28
28
  export declare function calculateOracleSpread(price: BN, oraclePriceData: OraclePriceData): BN;
29
29
  export declare function calculateMarketMarginRatio(market: MarketAccount, size: BN, marginCategory: MarginCategory): number;
30
- export declare function calculateUnsettledAssetWeight(market: MarketAccount, unsettledPnl: BN, marginCategory: MarginCategory): BN;
30
+ export declare function calculateUnrealizedAssetWeight(market: MarketAccount, unrealizedPnl: BN, marginCategory: MarginCategory): BN;
31
31
  export declare function calculateMarketAvailablePNL(market: MarketAccount, bank: BankAccount): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateMarketAvailablePNL = exports.calculateUnsettledAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
3
+ exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
4
4
  const anchor_1 = require("@project-serum/anchor");
5
5
  const types_1 = require("../types");
6
6
  const amm_1 = require("./amm");
@@ -72,19 +72,19 @@ function calculateMarketMarginRatio(market, size, marginCategory) {
72
72
  return marginRatio;
73
73
  }
74
74
  exports.calculateMarketMarginRatio = calculateMarketMarginRatio;
75
- function calculateUnsettledAssetWeight(market, unsettledPnl, marginCategory) {
75
+ function calculateUnrealizedAssetWeight(market, unrealizedPnl, marginCategory) {
76
76
  let assetWeight;
77
77
  switch (marginCategory) {
78
78
  case 'Initial':
79
- assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unsettledPnl, market.unsettledImfFactor, new anchor_1.BN(market.unsettledInitialAssetWeight));
79
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unrealizedPnl, market.unrealizedImfFactor, new anchor_1.BN(market.unrealizedInitialAssetWeight));
80
80
  break;
81
81
  case 'Maintenance':
82
- assetWeight = new anchor_1.BN(market.unsettledMaintenanceAssetWeight);
82
+ assetWeight = new anchor_1.BN(market.unrealizedMaintenanceAssetWeight);
83
83
  break;
84
84
  }
85
85
  return assetWeight;
86
86
  }
87
- exports.calculateUnsettledAssetWeight = calculateUnsettledAssetWeight;
87
+ exports.calculateUnrealizedAssetWeight = calculateUnrealizedAssetWeight;
88
88
  function calculateMarketAvailablePNL(market, bank) {
89
89
  return (0, bankBalance_1.getTokenAmount)(market.pnlPool.balance, bank, types_1.BankBalanceType.DEPOSIT);
90
90
  }
@@ -8,3 +8,6 @@ export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouse
8
8
  export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
9
9
  export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
10
10
  export declare function getLimitPrice(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
11
+ export declare function isFillableByVAMM(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): boolean;
12
+ export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
13
+ export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, market: MarketAccount, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
4
  const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const anchor_1 = require("@project-serum/anchor");
7
7
  const auction_1 = require("./auction");
8
8
  const market_1 = require("./market");
9
+ const amm_1 = require("./amm");
9
10
  function isOrderRiskIncreasing(user, order) {
10
11
  if ((0, types_1.isVariant)(order.status, 'init')) {
11
12
  return false;
@@ -108,3 +109,36 @@ function getLimitPrice(order, market, oraclePriceData, slot) {
108
109
  return limitPrice;
109
110
  }
110
111
  exports.getLimitPrice = getLimitPrice;
112
+ function isFillableByVAMM(order, market, oraclePriceData, slot) {
113
+ return ((0, auction_1.isAuctionComplete)(order, slot) &&
114
+ !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO));
115
+ }
116
+ exports.isFillableByVAMM = isFillableByVAMM;
117
+ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
118
+ if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) &&
119
+ order.triggered === false) {
120
+ return numericConstants_1.ZERO;
121
+ }
122
+ const limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
123
+ const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
124
+ const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
125
+ return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
126
+ }
127
+ exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
128
+ function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
129
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
130
+ const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
131
+ // Check that directions are the same
132
+ const sameDirection = isSameDirection(direction, order.direction);
133
+ if (!sameDirection) {
134
+ return numericConstants_1.ZERO;
135
+ }
136
+ return baseAssetAmount.gt(order.baseAssetAmount)
137
+ ? order.baseAssetAmount
138
+ : baseAssetAmount;
139
+ }
140
+ exports.calculateBaseAssetAmountToFillUpToLimitPrice = calculateBaseAssetAmountToFillUpToLimitPrice;
141
+ function isSameDirection(firstDirection, secondDirection) {
142
+ return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
143
+ ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
144
+ }
package/lib/types.d.ts CHANGED
@@ -136,6 +136,14 @@ export declare enum TradeSide {
136
136
  Sell = 2
137
137
  }
138
138
  export declare type CandleResolution = '1' | '5' | '15' | '60' | '240' | 'D' | 'W' | 'M';
139
+ export declare type NewUserRecord = {
140
+ ts: BN;
141
+ userAuthority: PublicKey;
142
+ user: PublicKey;
143
+ userId: number;
144
+ name: number[];
145
+ referrer: PublicKey;
146
+ };
139
147
  export declare type DepositRecord = {
140
148
  ts: BN;
141
149
  userAuthority: PublicKey;
@@ -147,6 +155,7 @@ export declare type DepositRecord = {
147
155
  bankIndex: BN;
148
156
  amount: BN;
149
157
  oraclePrice: BN;
158
+ referrer: PublicKey;
150
159
  from?: PublicKey;
151
160
  to?: PublicKey;
152
161
  };
@@ -303,6 +312,9 @@ export declare type OrderRecord = {
303
312
  fillerReward: BN;
304
313
  quoteAssetAmountSurplus: BN;
305
314
  oraclePrice: BN;
315
+ referrer: PublicKey;
316
+ referrerReward: BN;
317
+ refereeDiscount: BN;
306
318
  };
307
319
  export declare type StateAccount = {
308
320
  admin: PublicKey;
@@ -349,9 +361,9 @@ export declare type MarketAccount = {
349
361
  pnlPool: PoolBalance;
350
362
  liquidationFee: BN;
351
363
  imfFactor: BN;
352
- unsettledImfFactor: BN;
353
- unsettledInitialAssetWeight: number;
354
- unsettledMaintenanceAssetWeight: number;
364
+ unrealizedImfFactor: BN;
365
+ unrealizedInitialAssetWeight: number;
366
+ unrealizedMaintenanceAssetWeight: number;
355
367
  };
356
368
  export declare type BankAccount = {
357
369
  bankIndex: BN;
@@ -439,6 +451,8 @@ export declare type AMM = {
439
451
  maxSpread: number;
440
452
  marketPosition: UserPosition;
441
453
  marketPositionPerLp: UserPosition;
454
+ maxBaseAssetReserve: BN;
455
+ minBaseAssetReserve: BN;
442
456
  };
443
457
  export declare type UserPosition = {
444
458
  baseAssetAmount: BN;
@@ -467,11 +481,12 @@ export declare type UserStatsAccount = {
467
481
  totalFeePaid: BN;
468
482
  totalFeeRebate: BN;
469
483
  totalTokenDiscount: BN;
470
- totalReferralReward: BN;
471
484
  totalRefereeDiscount: BN;
472
485
  };
473
- authority: PublicKey;
474
486
  referrer: PublicKey;
487
+ isReferrer: boolean;
488
+ totalReferrerReward: BN;
489
+ authority: PublicKey;
475
490
  };
476
491
  export declare type UserAccount = {
477
492
  authority: PublicKey;
@@ -483,6 +498,7 @@ export declare type UserAccount = {
483
498
  beingLiquidated: boolean;
484
499
  bankrupt: boolean;
485
500
  nextLiquidationId: number;
501
+ nextOrderId: BN;
486
502
  };
487
503
  export declare type UserBankBalance = {
488
504
  bankIndex: BN;
@@ -508,9 +524,7 @@ export declare type Order = {
508
524
  triggerPrice: BN;
509
525
  triggerCondition: OrderTriggerCondition;
510
526
  triggered: boolean;
511
- discountTier: OrderDiscountTier;
512
527
  existingPositionDirection: PositionDirection;
513
- referrer: PublicKey;
514
528
  postOnly: boolean;
515
529
  immediateOrCancel: boolean;
516
530
  oraclePriceOffset: BN;
@@ -585,6 +599,10 @@ export declare type TakerInfo = {
585
599
  takerStats: PublicKey;
586
600
  order: Order;
587
601
  };
602
+ export declare type ReferrerInfo = {
603
+ referrer: PublicKey;
604
+ referrerStats: PublicKey;
605
+ };
588
606
  export interface IWallet {
589
607
  signTransaction(tx: Transaction): Promise<Transaction>;
590
608
  signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.2.0-master.18",
3
+ "version": "0.2.0-master.20",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -15,6 +15,7 @@ import {
15
15
  OptionalOrderParams,
16
16
  DefaultOrderParams,
17
17
  OrderType,
18
+ ReferrerInfo,
18
19
  } from './types';
19
20
  import * as anchor from '@project-serum/anchor';
20
21
  import clearingHouseIDL from './idl/clearing_house.json';
@@ -31,6 +32,7 @@ import {
31
32
  LAMPORTS_PER_SOL,
32
33
  Signer,
33
34
  SystemProgram,
35
+ ComputeBudgetProgram,
34
36
  } from '@solana/web3.js';
35
37
 
36
38
  import { TokenFaucet } from './tokenFaucet';
@@ -50,7 +52,11 @@ import {
50
52
  } from './accounts/types';
51
53
  import { TxSender } from './tx/types';
52
54
  import { wrapInTx } from './tx/utils';
53
- import { QUOTE_ASSET_BANK_INDEX, ZERO } from './constants/numericConstants';
55
+ import {
56
+ ONE,
57
+ QUOTE_ASSET_BANK_INDEX,
58
+ ZERO,
59
+ } from './constants/numericConstants';
54
60
  import { findDirectionToClose, positionIsAvailable } from './math/position';
55
61
  import { getTokenAmount } from './math/bankBalance';
56
62
  import { DEFAULT_USER_NAME, encodeName } from './userName';
@@ -340,10 +346,11 @@ export class ClearingHouse {
340
346
 
341
347
  public async initializeUserAccount(
342
348
  userId = 0,
343
- name = DEFAULT_USER_NAME
349
+ name = DEFAULT_USER_NAME,
350
+ referrerInfo?: ReferrerInfo
344
351
  ): Promise<[TransactionSignature, PublicKey]> {
345
352
  const [userAccountPublicKey, initializeUserAccountIx] =
346
- await this.getInitializeUserInstructions(userId, name);
353
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
347
354
 
348
355
  const tx = new Transaction();
349
356
  if (userId === 0) {
@@ -357,7 +364,8 @@ export class ClearingHouse {
357
364
 
358
365
  async getInitializeUserInstructions(
359
366
  userId = 0,
360
- name = DEFAULT_USER_NAME
367
+ name = DEFAULT_USER_NAME,
368
+ referrerInfo?: ReferrerInfo
361
369
  ): Promise<[PublicKey, TransactionInstruction]> {
362
370
  const userAccountPublicKey = await getUserAccountPublicKey(
363
371
  this.program.programId,
@@ -365,6 +373,20 @@ export class ClearingHouse {
365
373
  userId
366
374
  );
367
375
 
376
+ const remainingAccounts = new Array<AccountMeta>();
377
+ if (referrerInfo !== undefined) {
378
+ remainingAccounts.push({
379
+ pubkey: referrerInfo.referrer,
380
+ isWritable: true,
381
+ isSigner: false,
382
+ });
383
+ remainingAccounts.push({
384
+ pubkey: referrerInfo.referrerStats,
385
+ isWritable: true,
386
+ isSigner: false,
387
+ });
388
+ }
389
+
368
390
  const nameBuffer = encodeName(name);
369
391
  const initializeUserAccountIx =
370
392
  await this.program.instruction.initializeUser(userId, nameBuffer, {
@@ -377,6 +399,7 @@ export class ClearingHouse {
377
399
  systemProgram: anchor.web3.SystemProgram.programId,
378
400
  state: await this.getStatePublicKey(),
379
401
  },
402
+ remainingAccounts,
380
403
  });
381
404
 
382
405
  return [userAccountPublicKey, initializeUserAccountIx];
@@ -710,6 +733,7 @@ export class ClearingHouse {
710
733
  bank: bank.pubkey,
711
734
  bankVault: bank.vault,
712
735
  user: userAccountPublicKey,
736
+ userStats: this.getUserStatsAccountPublicKey(),
713
737
  userTokenAccount: userTokenAccount,
714
738
  authority: this.wallet.publicKey,
715
739
  tokenProgram: TOKEN_PROGRAM_ID,
@@ -841,10 +865,11 @@ export class ClearingHouse {
841
865
  bankIndex = new BN(0),
842
866
  userId = 0,
843
867
  name = DEFAULT_USER_NAME,
844
- fromUserId?: number
868
+ fromUserId?: number,
869
+ referrerInfo?: ReferrerInfo
845
870
  ): Promise<[TransactionSignature, PublicKey]> {
846
871
  const [userAccountPublicKey, initializeUserAccountIx] =
847
- await this.getInitializeUserInstructions(userId, name);
872
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
848
873
 
849
874
  const additionalSigners: Array<Signer> = [];
850
875
 
@@ -919,7 +944,8 @@ export class ClearingHouse {
919
944
  name = DEFAULT_USER_NAME,
920
945
  bankIndex: BN,
921
946
  tokenFaucet: TokenFaucet,
922
- amount: BN
947
+ amount: BN,
948
+ referrerInfo?: ReferrerInfo
923
949
  ): Promise<[TransactionSignature, PublicKey]> {
924
950
  const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] =
925
951
  await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(
@@ -928,7 +954,7 @@ export class ClearingHouse {
928
954
  );
929
955
 
930
956
  const [userAccountPublicKey, initializeUserAccountIx] =
931
- await this.getInitializeUserInstructions(userId, name);
957
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
932
958
 
933
959
  const depositCollateralIx = await this.getDepositInstruction(
934
960
  amount,
@@ -1037,6 +1063,7 @@ export class ClearingHouse {
1037
1063
  bankVault: bank.vault,
1038
1064
  bankVaultAuthority: bank.vaultAuthority,
1039
1065
  user: userAccountPublicKey,
1066
+ userStats: this.getUserStatsAccountPublicKey(),
1040
1067
  userTokenAccount: userTokenAccount,
1041
1068
  authority: this.wallet.publicKey,
1042
1069
  tokenProgram: TOKEN_PROGRAM_ID,
@@ -1088,6 +1115,7 @@ export class ClearingHouse {
1088
1115
  authority: this.wallet.publicKey,
1089
1116
  fromUser,
1090
1117
  toUser,
1118
+ userStats: this.getUserStatsAccountPublicKey(),
1091
1119
  state: await this.getStatePublicKey(),
1092
1120
  },
1093
1121
  remainingAccounts,
@@ -1400,11 +1428,18 @@ export class ClearingHouse {
1400
1428
  userAccountPublicKey: PublicKey,
1401
1429
  user: UserAccount,
1402
1430
  order?: Order,
1403
- makerInfo?: MakerInfo
1431
+ makerInfo?: MakerInfo,
1432
+ referrerInfo?: ReferrerInfo
1404
1433
  ): Promise<TransactionSignature> {
1405
1434
  const { txSig } = await this.txSender.send(
1406
1435
  wrapInTx(
1407
- await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
1436
+ await this.getFillOrderIx(
1437
+ userAccountPublicKey,
1438
+ user,
1439
+ order,
1440
+ makerInfo,
1441
+ referrerInfo
1442
+ )
1408
1443
  ),
1409
1444
  [],
1410
1445
  this.opts
@@ -1416,7 +1451,8 @@ export class ClearingHouse {
1416
1451
  userAccountPublicKey: PublicKey,
1417
1452
  userAccount: UserAccount,
1418
1453
  order: Order,
1419
- makerInfo?: MakerInfo
1454
+ makerInfo?: MakerInfo,
1455
+ referrerInfo?: ReferrerInfo
1420
1456
  ): Promise<TransactionInstruction> {
1421
1457
  const userStatsPublicKey = getUserStatsAccountPublicKey(
1422
1458
  this.program.programId,
@@ -1426,7 +1462,11 @@ export class ClearingHouse {
1426
1462
  const fillerPublicKey = await this.getUserAccountPublicKey();
1427
1463
  const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1428
1464
 
1429
- const marketIndex = order.marketIndex;
1465
+ const marketIndex = order
1466
+ ? order.marketIndex
1467
+ : userAccount.orders.find((order) =>
1468
+ order.orderId.eq(userAccount.nextOrderId.sub(ONE))
1469
+ ).marketIndex;
1430
1470
  const marketAccount = this.getMarketAccount(marketIndex);
1431
1471
 
1432
1472
  const oracleAccountMap = new Map<string, AccountMeta>();
@@ -1501,6 +1541,19 @@ export class ClearingHouse {
1501
1541
  });
1502
1542
  }
1503
1543
 
1544
+ if (referrerInfo) {
1545
+ remainingAccounts.push({
1546
+ pubkey: referrerInfo.referrer,
1547
+ isWritable: true,
1548
+ isSigner: false,
1549
+ });
1550
+ remainingAccounts.push({
1551
+ pubkey: referrerInfo.referrerStats,
1552
+ isWritable: true,
1553
+ isSigner: false,
1554
+ });
1555
+ }
1556
+
1504
1557
  const orderId = order.orderId;
1505
1558
  const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1506
1559
 
@@ -1613,10 +1666,13 @@ export class ClearingHouse {
1613
1666
 
1614
1667
  public async placeAndTake(
1615
1668
  orderParams: OptionalOrderParams,
1616
- makerInfo?: MakerInfo
1669
+ makerInfo?: MakerInfo,
1670
+ referrerInfo?: ReferrerInfo
1617
1671
  ): Promise<TransactionSignature> {
1618
1672
  const { txSig, slot } = await this.txSender.send(
1619
- wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
1673
+ wrapInTx(
1674
+ await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
1675
+ ),
1620
1676
  [],
1621
1677
  this.opts
1622
1678
  );
@@ -1626,7 +1682,8 @@ export class ClearingHouse {
1626
1682
 
1627
1683
  public async getPlaceAndTakeIx(
1628
1684
  orderParams: OptionalOrderParams,
1629
- makerInfo?: MakerInfo
1685
+ makerInfo?: MakerInfo,
1686
+ referrerInfo?: ReferrerInfo
1630
1687
  ): Promise<TransactionInstruction> {
1631
1688
  orderParams = this.getOrderParams(orderParams);
1632
1689
  const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
@@ -1652,6 +1709,19 @@ export class ClearingHouse {
1652
1709
  });
1653
1710
  }
1654
1711
 
1712
+ if (referrerInfo) {
1713
+ remainingAccounts.push({
1714
+ pubkey: referrerInfo.referrer,
1715
+ isWritable: true,
1716
+ isSigner: false,
1717
+ });
1718
+ remainingAccounts.push({
1719
+ pubkey: referrerInfo.referrerStats,
1720
+ isWritable: true,
1721
+ isSigner: false,
1722
+ });
1723
+ }
1724
+
1655
1725
  return await this.program.instruction.placeAndTake(
1656
1726
  orderParams,
1657
1727
  makerOrderId,
@@ -1669,10 +1739,13 @@ export class ClearingHouse {
1669
1739
 
1670
1740
  public async placeAndMake(
1671
1741
  orderParams: OptionalOrderParams,
1672
- takerInfo: TakerInfo
1742
+ takerInfo: TakerInfo,
1743
+ referrerInfo?: ReferrerInfo
1673
1744
  ): Promise<TransactionSignature> {
1674
1745
  const { txSig, slot } = await this.txSender.send(
1675
- wrapInTx(await this.getPlaceAndMakeIx(orderParams, takerInfo)),
1746
+ wrapInTx(
1747
+ await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)
1748
+ ),
1676
1749
  [],
1677
1750
  this.opts
1678
1751
  );
@@ -1684,7 +1757,8 @@ export class ClearingHouse {
1684
1757
 
1685
1758
  public async getPlaceAndMakeIx(
1686
1759
  orderParams: OptionalOrderParams,
1687
- takerInfo: TakerInfo
1760
+ takerInfo: TakerInfo,
1761
+ referrerInfo?: ReferrerInfo
1688
1762
  ): Promise<TransactionInstruction> {
1689
1763
  orderParams = this.getOrderParams(orderParams);
1690
1764
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
@@ -1694,6 +1768,19 @@ export class ClearingHouse {
1694
1768
  writableMarketIndex: orderParams.marketIndex,
1695
1769
  });
1696
1770
 
1771
+ if (referrerInfo) {
1772
+ remainingAccounts.push({
1773
+ pubkey: referrerInfo.referrer,
1774
+ isWritable: true,
1775
+ isSigner: false,
1776
+ });
1777
+ remainingAccounts.push({
1778
+ pubkey: referrerInfo.referrerStats,
1779
+ isWritable: true,
1780
+ isSigner: false,
1781
+ });
1782
+ }
1783
+
1697
1784
  const takerOrderId = takerInfo!.order!.orderId;
1698
1785
  return await this.program.instruction.placeAndMake(
1699
1786
  orderParams,
@@ -1754,7 +1841,14 @@ export class ClearingHouse {
1754
1841
  );
1755
1842
  }
1756
1843
 
1757
- const tx = new Transaction().add(...ixs);
1844
+ const tx = new Transaction()
1845
+ .add(
1846
+ ComputeBudgetProgram.requestUnits({
1847
+ units: 1_000_000,
1848
+ additionalFee: 0,
1849
+ })
1850
+ )
1851
+ .add(...ixs);
1758
1852
 
1759
1853
  const { txSig } = await this.txSender.send(tx, [], this.opts);
1760
1854
  return txSig;
@@ -33,7 +33,7 @@ import {
33
33
  calculateBaseAssetValue,
34
34
  calculatePositionFundingPNL,
35
35
  calculatePositionPNL,
36
- calculateUnsettledAssetWeight,
36
+ calculateUnrealizedAssetWeight,
37
37
  calculateMarketMarginRatio,
38
38
  PositionDirection,
39
39
  calculateTradeSlippage,
@@ -372,11 +372,11 @@ export class ClearingHouseUser {
372
372
  .positions.filter((pos) =>
373
373
  marketIndex ? pos.marketIndex === marketIndex : true
374
374
  )
375
- .reduce((pnl, marketPosition) => {
375
+ .reduce((unrealizedPnl, marketPosition) => {
376
376
  const market = this.clearingHouse.getMarketAccount(
377
377
  marketPosition.marketIndex
378
378
  );
379
- let pnl0 = calculatePositionPNL(
379
+ let positionUnrealizedPnl = calculatePositionPNL(
380
380
  market,
381
381
  marketPosition,
382
382
  withFunding,
@@ -384,12 +384,12 @@ export class ClearingHouseUser {
384
384
  );
385
385
 
386
386
  if (withWeightMarginCategory !== undefined) {
387
- if (pnl0.gt(ZERO)) {
388
- pnl0 = pnl0
387
+ if (positionUnrealizedPnl.gt(ZERO)) {
388
+ positionUnrealizedPnl = positionUnrealizedPnl
389
389
  .mul(
390
- calculateUnsettledAssetWeight(
390
+ calculateUnrealizedAssetWeight(
391
391
  market,
392
- pnl0,
392
+ positionUnrealizedPnl,
393
393
  withWeightMarginCategory
394
394
  )
395
395
  )
@@ -397,7 +397,7 @@ export class ClearingHouseUser {
397
397
  }
398
398
  }
399
399
 
400
- return pnl.add(pnl0);
400
+ return unrealizedPnl.add(positionUnrealizedPnl);
401
401
  }, ZERO);
402
402
  }
403
403
 
@@ -528,47 +528,9 @@ export class ClearingHouseUser {
528
528
  * @returns : Precision QUOTE_PRECISION
529
529
  */
530
530
  public getTotalCollateral(marginCategory: MarginCategory = 'Initial'): BN {
531
- return this.getUserAccount()
532
- .bankBalances.reduce((totalAssetValue, bankBalance) => {
533
- if (
534
- bankBalance.balance.eq(ZERO) ||
535
- isVariant(bankBalance.balanceType, 'borrow')
536
- ) {
537
- return totalAssetValue;
538
- }
539
-
540
- // Todo this needs to account for whether it's based on initial or maintenance requirements
541
- const bankAccount: BankAccount = this.clearingHouse.getBankAccount(
542
- bankBalance.bankIndex
543
- );
544
-
545
- const tokenAmount = getTokenAmount(
546
- bankBalance.balance,
547
- bankAccount,
548
- bankBalance.balanceType
549
- );
550
-
551
- const weight = calculateAssetWeight(
552
- tokenAmount,
553
- bankAccount,
554
- marginCategory
555
- );
556
-
557
- return totalAssetValue.add(
558
- tokenAmount
559
- .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
560
- .mul(weight)
561
- .div(BANK_WEIGHT_PRECISION)
562
- .div(MARK_PRICE_PRECISION)
563
- // Adjust for decimals of bank account
564
- .div(
565
- new BN(10).pow(
566
- new BN(bankAccount.decimals).sub(BANK_BALANCE_PRECISION_EXP)
567
- )
568
- )
569
- );
570
- }, ZERO)
571
- .add(this.getUnrealizedPNL(true, undefined, marginCategory));
531
+ return this.getBankAssetValue(undefined, marginCategory).add(
532
+ this.getUnrealizedPNL(true, undefined, marginCategory)
533
+ );
572
534
  }
573
535
 
574
536
  /**