@d8x/perpetuals-sdk 2.1.12-alpha2 → 2.1.24-alpha2

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/doc/marketData.md CHANGED
@@ -44,7 +44,7 @@ No gas required for the queries here.</p>
44
44
  * [.fetchPricesForPerpetual(symbol)](#MarketData+fetchPricesForPerpetual) ⇒
45
45
  * [.fetchPrdMktMetaData(symbol)](#MarketData+fetchPrdMktMetaData) ⇒
46
46
  * _static_
47
- * [.exchangeFeePrdMkts(state, maxMaintMgnRate, Sm, tradeAmtBC, tradeMgnRate)](#MarketData.exchangeFeePrdMkts) ⇒
47
+ * [.exchangeFeePrdMkts(maxMaintMgnRate, Sm, tradeAmtBC, tradeMgnRate)](#MarketData.exchangeFeePrdMkts) ⇒
48
48
 
49
49
  <a name="new_MarketData_new"></a>
50
50
 
@@ -810,7 +810,7 @@ main();
810
810
 
811
811
  <a name="MarketData.exchangeFeePrdMkts"></a>
812
812
 
813
- ### MarketData.exchangeFeePrdMkts(state, maxMaintMgnRate, Sm, tradeAmtBC, tradeMgnRate) ⇒
813
+ ### MarketData.exchangeFeePrdMkts(maxMaintMgnRate, Sm, tradeAmtBC, tradeMgnRate) ⇒
814
814
  <p>Fee is relative to base-currency amount (=trade amount)</p>
815
815
 
816
816
  **Kind**: static method of [<code>MarketData</code>](#MarketData)
@@ -818,7 +818,6 @@ main();
818
818
 
819
819
  | Param | Description |
820
820
  | --- | --- |
821
- | state | <p>current perpetual state (need longBC and shortBC)</p> |
822
821
  | maxMaintMgnRate | <p>maintenance margin rate param for pred mkts</p> |
823
822
  | Sm | <p>Mark price</p> |
824
823
  | tradeAmtBC | <p>signed trade amount</p> |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d8x/perpetuals-sdk",
3
- "version": "2.1.12-alpha2",
3
+ "version": "2.1.24-alpha2",
4
4
  "description": "Node TypeScript SDK for D8X Perpetual Futures",
5
5
  "author": "D8X",
6
6
  "homepage": "https://github.com/D8-X/d8x-futures-node-sdk#readme",
package/src/d8XMath.ts CHANGED
@@ -505,6 +505,7 @@ export function pmInitialMarginRate(posSign: number, sm: number, m: number | und
505
505
  * @param totShort total short
506
506
  * @param tradeAmt signed trade amount, can be zero
507
507
  * @param tradeMgnRate margin rate of the trader
508
+ * @returns expected loss in dollars
508
509
  */
509
510
  export function expectedLoss(
510
511
  p: number,
@@ -532,7 +533,18 @@ export function expectedLoss(
532
533
  return p * (1 - p) * Math.max(0, a + b);
533
534
  }
534
535
 
535
- function newFee(p: number, m: number, tradeAmt: number, tradeMgnRate: number) {
536
+ /**
537
+ * Equivalent to
538
+ * const el0 = expectedLoss(prob, m, totLong, totShort, 0, 0);
539
+ * const el1 = expectedLoss(prob, m, totLong, totShort, tradeAmt, tradeMgnRate)
540
+ * const fee = (el1 - el0) / Math.abs(tradeAmt);
541
+ * @param p prob long probability
542
+ * @param m max maintenance margin rate (0.18)
543
+ * @param tradeAmt trade amount in base currency
544
+ * @param tradeMgnRate margin rate for this trade
545
+ * @returns dollar fee
546
+ */
547
+ function expectedLossImpact(p: number, m: number, tradeAmt: number, tradeMgnRate: number) {
536
548
  m = (0.4 - m) * entropy(p) + m;
537
549
  let dlm = 0;
538
550
  let dl = 0;
@@ -556,26 +568,18 @@ function newFee(p: number, m: number, tradeAmt: number, tradeMgnRate: number) {
556
568
  * For opening trades only
557
569
  * @param prob long probability
558
570
  * @param m max maintenance margin rate (0.18)
559
- * @param totShort
560
- * @param totLong
561
571
  * @param tradeAmt trade amount in base currency
562
572
  * @param tradeMgnRate margin rate for this trade
563
- * @returns fee relative to tradeAmt
573
+ * @returns dollar fee relative to tradeAmt
564
574
  */
565
- export function pmExchangeFee(
566
- prob: number,
567
- m: number,
568
- totShort: number,
569
- totLong: number,
570
- tradeAmt: number,
571
- tradeMgnRate: number
572
- ): number {
573
- const el0 = expectedLoss(prob, m, totLong, totShort, 0, 0);
574
- const el1 = expectedLoss(prob, m, totLong, totShort, tradeAmt, tradeMgnRate);
575
- console.log("el0=", el0);
576
- console.log("el1=", el1);
577
- const fee = (el1 - el0) / Math.abs(tradeAmt);
578
- console.log("diff=", el1 - el0);
575
+ export function pmExchangeFee(prob: number, m: number, tradeAmt: number, tradeMgnRate: number): number {
576
+ /*
577
+ equivalent:
578
+ const el0 = expectedLoss(prob, m, totLong, totShort, 0, 0);
579
+ const el1 = expectedLoss(prob, m, totLong, totShort, tradeAmt, tradeMgnRate);
580
+ const fee = (el1 - el0) / Math.abs(tradeAmt);
581
+ */
582
+ let fee = expectedLossImpact(prob, m, tradeAmt, tradeMgnRate) / Math.abs(tradeAmt);
579
583
  return Math.max(fee, 0.001);
580
584
  }
581
585
 
@@ -644,8 +648,6 @@ export function pmFindLiquidationPrice(
644
648
  * @param limitPrice
645
649
  * @param Sm
646
650
  * @param S3
647
- * @param totLong
648
- * @param totShort
649
651
  * @returns excess margin as defined above
650
652
  */
651
653
  function excessMargin(
@@ -655,9 +657,7 @@ function excessMargin(
655
657
  currentLockedInQC: number,
656
658
  limitPrice: number,
657
659
  Sm: number,
658
- S3: number,
659
- totLong: number,
660
- totShort: number
660
+ S3: number
661
661
  ): number {
662
662
  const m = 0.18; //max maintenance margin rate
663
663
  const m0 = 0.2; //max initial margin rate
@@ -672,7 +672,7 @@ function excessMargin(
672
672
  const b0 = currentCashCC + Math.abs(currentPos) * Sm - currentLockedInQC + Math.max(0, tradeAmt * (Sm - limitPrice));
673
673
  // b0 + margin - fee > threshold
674
674
  // margin = threshold - b0 + fee
675
- const fee_cc = pmExchangeFee(p, m, totShort, totLong, tradeAmt, tau) / S3;
675
+ const fee_cc = pmExchangeFee(p, m, tradeAmt, tau) / S3;
676
676
 
677
677
  // missing: referral rebate
678
678
  return b0 / S3 - thresh / S3 - fee_cc;
@@ -737,9 +737,7 @@ function pmExcessCashAtLvg(
737
737
  slippage: number,
738
738
  S2: number,
739
739
  Sm: number,
740
- S3: number,
741
- totLong: number,
742
- totShort: number
740
+ S3: number
743
741
  ): number {
744
742
  //determine deposit amount for given leverage
745
743
  const limitPrice = S2 * (1 + Math.sign(tradeAmt) * slippage);
@@ -750,10 +748,10 @@ function pmExcessCashAtLvg(
750
748
  if (tradeAmt < 0) {
751
749
  p0 = 2 - Sm; //=1-(Sm-1)
752
750
  }
753
- const feeCc = pmExchangeFee(p0, m0, totShort, totLong, tradeAmt, 1 / lvg) / S3;
751
+ const feeCc = (tradeAmt * pmExchangeFee(p0, m0, tradeAmt, 1 / lvg)) / S3;
754
752
 
755
753
  //excess cash
756
- let exc = walletBalCC - depositFromWallet - feeCc;
754
+ let exc = walletBalCC - depositFromWallet;
757
755
 
758
756
  // margin balance
759
757
  let pos = currentPosition + tradeAmt;
@@ -794,10 +792,8 @@ function pmExcessCashAtLvg(
794
792
  * @param S2
795
793
  * @param Sm
796
794
  * @param S3
797
- * @param totLong
798
- * @param totShort
799
- * @param maxShort
800
- * @param maxLong
795
+ * @param maxShort global max short order size (sign irrelevant)
796
+ * @param maxLong global max long order size (positive)
801
797
  * @returns max trade size
802
798
  */
803
799
  export function pmFindMaxPersonalTradeSizeAtLeverage(
@@ -811,8 +807,6 @@ export function pmFindMaxPersonalTradeSizeAtLeverage(
811
807
  S2: number,
812
808
  Sm: number,
813
809
  S3: number,
814
- totLong: number,
815
- totShort: number,
816
810
  maxShort: number,
817
811
  maxLong: number
818
812
  ): number {
@@ -833,9 +827,7 @@ export function pmFindMaxPersonalTradeSizeAtLeverage(
833
827
  slippage,
834
828
  S2,
835
829
  Sm,
836
- S3,
837
- totLong,
838
- totShort
830
+ S3
839
831
  );
840
832
  if (f0 < lot) {
841
833
  // no trade possible
@@ -859,9 +851,7 @@ export function pmFindMaxPersonalTradeSizeAtLeverage(
859
851
  slippage,
860
852
  S2,
861
853
  Sm,
862
- S3,
863
- totLong,
864
- totShort
854
+ S3
865
855
  ) ** 2;
866
856
  const f2 =
867
857
  pmExcessCashAtLvg(
@@ -874,9 +864,7 @@ export function pmFindMaxPersonalTradeSizeAtLeverage(
874
864
  slippage,
875
865
  S2,
876
866
  Sm,
877
- S3,
878
- totLong,
879
- totShort
867
+ S3
880
868
  ) ** 2;
881
869
  let ds = (f2 - f) / deltaS;
882
870
  if (ds == 0) {
@@ -899,10 +887,10 @@ export function pmFindMaxPersonalTradeSizeAtLeverage(
899
887
  }
900
888
  // ensure trade maximal trade sNew does not exceed
901
889
  // the contract limits
902
- if (currentPosition + sNew < maxShort) {
903
- sNew = maxShort - currentPosition;
904
- } else if (currentPosition + sNew > maxLong) {
905
- sNew = maxLong - currentPosition;
890
+ if (sNew < -Math.abs(maxShort)) {
891
+ sNew = -Math.abs(maxShort);
892
+ } else if (sNew > maxLong) {
893
+ sNew = maxLong;
906
894
  }
907
895
  // round trade size down to lot
908
896
  sNew = Math.sign(sNew) * Math.floor(Math.abs(sNew) / lot) * lot;
@@ -934,8 +922,6 @@ export function pmFindMaxTradeSize(
934
922
  limitPrice: number,
935
923
  Sm: number,
936
924
  S3: number,
937
- totLong: number,
938
- totShort: number,
939
925
  maxShort: number,
940
926
  maxLong: number
941
927
  ): number {
@@ -946,17 +932,7 @@ export function pmFindMaxTradeSize(
946
932
  }
947
933
  const lot = 10;
948
934
  const deltaS = 1; //for derivative
949
- const f0 = excessMargin(
950
- dir * deltaS,
951
- currentCashCC,
952
- currentPosition,
953
- currentLockedInValue,
954
- limitPrice,
955
- Sm,
956
- S3,
957
- totLong,
958
- totShort
959
- );
935
+ const f0 = excessMargin(dir * deltaS, currentCashCC, currentPosition, currentLockedInValue, limitPrice, Sm, S3);
960
936
  if (f0 < lot) {
961
937
  // no trade possible
962
938
  return 0;
@@ -968,21 +944,9 @@ export function pmFindMaxTradeSize(
968
944
  let count = 0;
969
945
  while (Math.abs(sNew - s) > 1 && count < 100) {
970
946
  s = sNew;
971
- const f =
972
- excessMargin(s, currentCashCC, currentPosition, currentLockedInValue, limitPrice, Sm, S3, totLong, totShort) **
973
- 2;
947
+ const f = excessMargin(s, currentCashCC, currentPosition, currentLockedInValue, limitPrice, Sm, S3) ** 2;
974
948
  const f2 =
975
- excessMargin(
976
- s + deltaS,
977
- currentCashCC,
978
- currentPosition,
979
- currentLockedInValue,
980
- limitPrice,
981
- Sm,
982
- S3,
983
- totLong,
984
- totShort
985
- ) ** 2;
949
+ excessMargin(s + deltaS, currentCashCC, currentPosition, currentLockedInValue, limitPrice, Sm, S3) ** 2;
986
950
  let ds = (f2 - f) / deltaS;
987
951
  sNew = s - f / ds;
988
952
  count += 1;
@@ -1,4 +1,11 @@
1
- import { ContractTransactionResponse, JsonRpcProvider, Overrides, Signer, TransactionResponse } from "ethers";
1
+ import {
2
+ BigNumberish,
3
+ ContractTransactionResponse,
4
+ JsonRpcProvider,
5
+ Overrides,
6
+ Signer,
7
+ TransactionResponse,
8
+ } from "ethers";
2
9
  import { PayableOverrides } from "./contracts/common";
3
10
  import { IPyth__factory } from "./contracts/factories";
4
11
  import { ABK64x64ToFloat, floatToABK64x64, entropy } from "./d8XMath";
@@ -98,7 +105,7 @@ export default class LiquidatorTool extends WriteAccessHandler {
98
105
  traderAddr: string,
99
106
  liquidatorAddr: string = "",
100
107
  submission?: PriceFeedSubmission,
101
- overrides?: PayableOverrides & { rpcURL?: string; splitTx?: boolean }
108
+ overrides?: PayableOverrides & { rpcURL?: string; splitTx?: boolean; maxGasLimit?: BigNumberish }
102
109
  ): Promise<TransactionResponse> {
103
110
  // this operation spends gas, so signer is required
104
111
  if (this.proxyContract == null || this.signer == null) {
@@ -110,20 +117,17 @@ export default class LiquidatorTool extends WriteAccessHandler {
110
117
  }
111
118
  let rpcURL: string | undefined;
112
119
  let splitTx: boolean | undefined;
120
+ let maxGasLimit: BigNumberish | undefined;
113
121
  if (overrides) {
114
- ({ rpcURL, splitTx, ...overrides } = overrides);
122
+ ({ rpcURL, splitTx, maxGasLimit, ...overrides } = overrides);
115
123
  }
124
+
116
125
  const provider = new JsonRpcProvider(rpcURL ?? this.nodeURL, this.network, { staticNetwork: true });
117
126
  let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
118
127
  if (submission == undefined) {
119
128
  submission = await this.fetchLatestFeedPriceInfo(symbol);
120
129
  }
121
- if (!overrides || overrides.gasLimit == undefined) {
122
- overrides = {
123
- gasLimit: overrides?.gasLimit ?? this.gasLimit,
124
- ...overrides,
125
- } as PayableOverrides;
126
- }
130
+
127
131
  // update first
128
132
  let nonceInc = 0;
129
133
  let txData: string;
@@ -139,7 +143,7 @@ export default class LiquidatorTool extends WriteAccessHandler {
139
143
  {
140
144
  value: this.PRICE_UPDATE_FEE_GWEI * submission.timestamps.length,
141
145
  gasLimit: overrides?.gasLimit ?? this.gasLimit,
142
- nonce: overrides.nonce,
146
+ nonce: overrides?.nonce,
143
147
  }
144
148
  );
145
149
  nonceInc += 1;
@@ -164,21 +168,50 @@ export default class LiquidatorTool extends WriteAccessHandler {
164
168
  ]);
165
169
  value = this.PRICE_UPDATE_FEE_GWEI * submission.timestamps.length;
166
170
  }
167
- if (!!overrides?.nonce) {
171
+ if (overrides?.nonce != undefined) {
168
172
  overrides.nonce = overrides.nonce + nonceInc;
169
173
  }
174
+
175
+ if (overrides?.gasLimit !== undefined) {
176
+ overrides.gasLimit = await overrides.gasLimit;
177
+ }
178
+
179
+ if (overrides?.gasPrice !== undefined) {
180
+ overrides.gasPrice = await overrides.gasPrice;
181
+ }
170
182
  let unsignedTx = {
171
183
  to: this.proxyAddr,
172
184
  from: this.traderAddr,
173
- nonce: overrides.nonce,
185
+ nonce: overrides?.nonce,
174
186
  data: txData,
175
187
  value: value,
176
- gasLimit: overrides.gasLimit,
188
+ gasLimit: overrides?.gasLimit,
177
189
  // gas price is populated by the provider if undefined
178
- gasPrice: overrides.gasPrice,
190
+ gasPrice: overrides?.gasPrice,
179
191
  chainId: this.chainId,
180
192
  };
181
- return await this.signer.sendTransaction(unsignedTx);
193
+ // no gas limit was specified, explicitly estimate
194
+ if (!overrides?.gasLimit) {
195
+ let gasLimit = await this.signer
196
+ .estimateGas(unsignedTx)
197
+ .then((gas) => (gas * 1500n) / 1000n)
198
+ .catch((_e) => undefined);
199
+ if (!gasLimit) {
200
+ // gas estimate failed - txn would probably revert, double check (and possibly re-throw):
201
+ overrides = { gasLimit: maxGasLimit ?? this.gasLimit, value: unsignedTx.value, ...overrides };
202
+ await this.proxyContract.liquidateByAMM.staticCall(
203
+ perpID,
204
+ liquidatorAddr,
205
+ traderAddr,
206
+ submission.priceFeedVaas,
207
+ submission.timestamps,
208
+ overrides
209
+ );
210
+ gasLimit = BigInt(maxGasLimit ?? this.gasLimit);
211
+ }
212
+ unsignedTx.gasLimit = gasLimit;
213
+ }
214
+ return await this.signer.connect(provider).sendTransaction(unsignedTx);
182
215
  }
183
216
 
184
217
  /**
package/src/marketData.ts CHANGED
@@ -804,7 +804,6 @@ export default class MarketData extends PerpetualDataHandler {
804
804
 
805
805
  /**
806
806
  * Fee is relative to base-currency amount (=trade amount)
807
- * @param state current perpetual state (need longBC and shortBC)
808
807
  * @param maxMaintMgnRate maintenance margin rate param for pred mkts
809
808
  * @param Sm Mark price
810
809
  * @param tradeAmtBC signed trade amount
@@ -812,7 +811,6 @@ export default class MarketData extends PerpetualDataHandler {
812
811
  * @returns relative exchange fee in decimals
813
812
  */
814
813
  public static exchangeFeePrdMkts(
815
- state: PerpetualState,
816
814
  maxMaintMgnRate: number,
817
815
  Sm: number,
818
816
  tradeAmtBC: number,
@@ -826,7 +824,7 @@ export default class MarketData extends PerpetualDataHandler {
826
824
  // 0.1cents if is close
827
825
  return 0.001;
828
826
  }
829
- return pmExchangeFee(Sm - 1, maxMaintMgnRate, state.shortBC, state.longBC, tradeAmtBC, tradeMgnRate);
827
+ return pmExchangeFee(Sm - 1, maxMaintMgnRate, tradeAmtBC, tradeMgnRate);
830
828
  }
831
829
 
832
830
  /**
@@ -1279,8 +1277,6 @@ export default class MarketData extends PerpetualDataHandler {
1279
1277
  Sm,
1280
1278
  Sm,
1281
1279
  indexPriceInfo.s3 ?? 0,
1282
- totLong,
1283
- totShort,
1284
1280
  maxShortPosPerp,
1285
1281
  maxLongPosPerp
1286
1282
  );
@@ -1292,8 +1288,6 @@ export default class MarketData extends PerpetualDataHandler {
1292
1288
  Sm,
1293
1289
  Sm,
1294
1290
  indexPriceInfo.s3 ?? 0,
1295
- totLong,
1296
- totShort,
1297
1291
  maxShortPosPerp,
1298
1292
  maxLongPosPerp
1299
1293
  );
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const D8X_SDK_VERSION = "2.1.12-alpha2";
1
+ export const D8X_SDK_VERSION = "2.1.24-alpha2";