@drift-labs/common 1.0.0 → 1.0.2

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 (92) hide show
  1. package/lib/clients/swiftClient.d.ts +5 -1
  2. package/lib/clients/swiftClient.js +17 -7
  3. package/lib/clients/swiftClient.js.map +1 -1
  4. package/lib/clients/tvFeed.d.ts +3 -1
  5. package/lib/clients/tvFeed.js +27 -13
  6. package/lib/clients/tvFeed.js.map +1 -1
  7. package/lib/common-ui-utils/commonUiUtils.d.ts +7 -0
  8. package/lib/common-ui-utils/market.d.ts +6 -1
  9. package/lib/common-ui-utils/market.js +46 -0
  10. package/lib/common-ui-utils/market.js.map +1 -1
  11. package/lib/common-ui-utils/order.d.ts +8 -1
  12. package/lib/common-ui-utils/order.js +39 -0
  13. package/lib/common-ui-utils/order.js.map +1 -1
  14. package/lib/common-ui-utils/user.js +1 -0
  15. package/lib/common-ui-utils/user.js.map +1 -1
  16. package/lib/constants/markets.d.ts +1 -0
  17. package/lib/constants/markets.js +2 -1
  18. package/lib/constants/markets.js.map +1 -1
  19. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.d.ts +1 -6
  20. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.js +8 -22
  21. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.js.map +1 -1
  22. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/types.d.ts +2 -2
  23. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/types.js.map +1 -1
  24. package/lib/drift/Drift/clients/AuthorityDrift/index.d.ts +1 -2
  25. package/lib/drift/Drift/clients/AuthorityDrift/index.js.map +1 -1
  26. package/lib/drift/Drift/clients/CentralServerDrift.d.ts +10 -5
  27. package/lib/drift/Drift/clients/CentralServerDrift.js +5 -48
  28. package/lib/drift/Drift/clients/CentralServerDrift.js.map +1 -1
  29. package/lib/drift/Drift/constants/errors.d.ts +9 -1
  30. package/lib/drift/Drift/constants/errors.js +13 -2
  31. package/lib/drift/Drift/constants/errors.js.map +1 -1
  32. package/lib/drift/Drift/data/PollingDlob.d.ts +0 -20
  33. package/lib/drift/Drift/data/PollingDlob.js +2 -78
  34. package/lib/drift/Drift/data/PollingDlob.js.map +1 -1
  35. package/lib/drift/base/actions/perp/settlePnl.d.ts +3 -3
  36. package/lib/drift/base/actions/perp/settlePnl.js +3 -3
  37. package/lib/drift/base/actions/perp/settlePnl.js.map +1 -1
  38. package/lib/drift/base/actions/spot/index.d.ts +0 -1
  39. package/lib/drift/base/actions/spot/index.js +0 -1
  40. package/lib/drift/base/actions/spot/index.js.map +1 -1
  41. package/lib/drift/base/actions/trade/openPerpOrder/dlobServer/index.d.ts +81 -0
  42. package/lib/drift/base/actions/trade/openPerpOrder/dlobServer/index.js +255 -0
  43. package/lib/drift/base/actions/trade/openPerpOrder/dlobServer/index.js.map +1 -0
  44. package/lib/drift/base/actions/trade/openPerpOrder/index.d.ts +2 -0
  45. package/lib/drift/base/actions/trade/openPerpOrder/index.js +2 -0
  46. package/lib/drift/base/actions/trade/openPerpOrder/index.js.map +1 -1
  47. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.d.ts +53 -43
  48. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.js +180 -201
  49. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.js.map +1 -1
  50. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.d.ts +37 -9
  51. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.js +194 -83
  52. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.js.map +1 -1
  53. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.d.ts +40 -27
  54. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.js +111 -32
  55. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.js.map +1 -1
  56. package/lib/drift/base/actions/trade/openPerpOrder/types.d.ts +64 -0
  57. package/lib/drift/base/actions/trade/openPerpOrder/types.js +3 -0
  58. package/lib/drift/base/actions/trade/openPerpOrder/types.js.map +1 -0
  59. package/lib/drift/base/actions/user/create.js +9 -3
  60. package/lib/drift/base/actions/user/create.js.map +1 -1
  61. package/lib/drift/cli.js +114 -71
  62. package/lib/drift/cli.js.map +1 -1
  63. package/lib/drift/index.d.ts +1 -0
  64. package/lib/drift/index.js +1 -0
  65. package/lib/drift/index.js.map +1 -1
  66. package/lib/drift/utils/auctionParamsResponseMapper.d.ts +25 -23
  67. package/lib/drift/utils/auctionParamsResponseMapper.js +4 -6
  68. package/lib/drift/utils/auctionParamsResponseMapper.js.map +1 -1
  69. package/lib/drift/utils/index.d.ts +1 -1
  70. package/lib/drift/utils/index.js +1 -4
  71. package/lib/drift/utils/index.js.map +1 -1
  72. package/lib/drift/utils/orderParams.d.ts +3 -28
  73. package/lib/drift/utils/orderParams.js +9 -1
  74. package/lib/drift/utils/orderParams.js.map +1 -1
  75. package/lib/index.d.ts +2 -0
  76. package/lib/index.js +2 -0
  77. package/lib/index.js.map +1 -1
  78. package/lib/types/user.d.ts +1 -0
  79. package/lib/types/user.js.map +1 -1
  80. package/lib/utils/fetch.d.ts +1 -0
  81. package/lib/utils/fetch.js +11 -0
  82. package/lib/utils/fetch.js.map +1 -0
  83. package/lib/utils/orderbook/index.d.ts +18 -0
  84. package/lib/utils/orderbook/index.js +68 -1
  85. package/lib/utils/orderbook/index.js.map +1 -1
  86. package/lib/utils/priceImpact.d.ts +14 -0
  87. package/lib/utils/priceImpact.js +71 -0
  88. package/lib/utils/priceImpact.js.map +1 -0
  89. package/package.json +1 -1
  90. package/lib/drift/base/actions/spot/borrow.d.ts +0 -1
  91. package/lib/drift/base/actions/spot/borrow.js +0 -8
  92. package/lib/drift/base/actions/spot/borrow.js.map +0 -1
@@ -73,7 +73,7 @@ const getTriggerCondition = (direction, tpOrSl) => {
73
73
  /**
74
74
  * Builds proper order parameters for non-market orders using the same logic as the UI
75
75
  */
76
- function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAssetAmount, orderConfig, reduceOnly = false, postOnly = sdk_1.PostOnlyParams.NONE, }) {
76
+ function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAssetAmount, orderConfig, reduceOnly = false, postOnly = sdk_1.PostOnlyParams.NONE, userOrderId = 0, }) {
77
77
  const orderType = orderConfig.orderType;
78
78
  // Build order params based on order type using SDK functions
79
79
  if (orderType === 'limit') {
@@ -88,6 +88,7 @@ function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAss
88
88
  price: orderConfig.limitPrice,
89
89
  reduceOnly,
90
90
  postOnly,
91
+ userOrderId,
91
92
  });
92
93
  }
93
94
  if (orderType === 'takeProfit' || orderType === 'stopLoss') {
@@ -106,6 +107,8 @@ function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAss
106
107
  price: orderConfig.limitPrice,
107
108
  triggerCondition,
108
109
  reduceOnly,
110
+ postOnly,
111
+ userOrderId,
109
112
  });
110
113
  }
111
114
  else {
@@ -118,6 +121,8 @@ function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAss
118
121
  price: orderConfig.limitPrice,
119
122
  triggerCondition,
120
123
  reduceOnly,
124
+ postOnly,
125
+ userOrderId,
121
126
  });
122
127
  }
123
128
  }
@@ -132,6 +137,9 @@ function buildNonMarketOrderParams({ marketIndex, marketType, direction, baseAss
132
137
  baseAssetAmount,
133
138
  price: sdk_1.ZERO,
134
139
  oraclePriceOffset: orderConfig.oraclePriceOffset.toNumber(),
140
+ userOrderId,
141
+ postOnly,
142
+ reduceOnly,
135
143
  });
136
144
  }
137
145
  throw new Error(`Unsupported order type: ${orderType}`);
@@ -1 +1 @@
1
- {"version":3,"file":"orderParams.js","sourceRoot":"","sources":["../../../src/drift/utils/orderParams.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tBN,\n\tMarketType,\n\tPositionDirection,\n\tPostOnlyParams,\n\tOptionalOrderParams,\n\tgetLimitOrderParams,\n\tgetTriggerMarketOrderParams,\n\tgetTriggerLimitOrderParams,\n\tOrderTriggerCondition,\n\tZERO,\n} from '@drift-labs/sdk';\nimport { ENUM_UTILS } from '../../utils';\nimport { OptionalTriggerOrderParams } from '../base/actions/trade/openPerpOrder/openSwiftOrder';\n\n/**\n * Converts amount and assetType to base asset amount\n * @param amount - The amount to convert\n * @param assetType - 'base' or 'quote'\n * @param limitPrice - Required when assetType is 'quote' for conversion\n * @returns Base asset amount\n */\nexport function convertToBaseAssetAmount(\n\tamount: BN,\n\tassetType: 'base' | 'quote',\n\tlimitPrice?: BN\n): BN {\n\tif (assetType === 'quote') {\n\t\tif (!limitPrice || limitPrice.isZero()) {\n\t\t\tthrow new Error(\n\t\t\t\t'When using quote asset type, limitPrice is required for conversion to base amount'\n\t\t\t);\n\t\t}\n\t\t// Convert quote amount to base amount: quoteAmount / price = baseAmount\n\t\t// Using PRICE_PRECISION as the limit price is in price precision\n\t\tconst PRICE_PRECISION = new BN(10).pow(new BN(6));\n\t\treturn amount.mul(PRICE_PRECISION).div(limitPrice);\n\t} else {\n\t\t// Base amount, use directly\n\t\treturn amount;\n\t}\n}\n\n/**\n * Resolves amount parameters from either new (amount + assetType) or legacy (baseAssetAmount) approach\n */\nexport function resolveBaseAssetAmount(params: {\n\tamount?: BN;\n\tassetType?: 'base' | 'quote';\n\tbaseAssetAmount?: BN;\n\tlimitPrice?: BN;\n}): BN {\n\tconst { amount, assetType, baseAssetAmount, limitPrice } = params;\n\n\tif (amount && assetType) {\n\t\t// New approach: convert if needed\n\t\treturn convertToBaseAssetAmount(amount, assetType, limitPrice);\n\t} else if (baseAssetAmount) {\n\t\t// Legacy approach\n\t\treturn baseAssetAmount;\n\t} else {\n\t\tthrow new Error(\n\t\t\t'Either (amount + assetType) or baseAssetAmount must be provided'\n\t\t);\n\t}\n}\n\nexport type NonMarketOrderType =\n\t| 'limit'\n\t| 'takeProfit'\n\t| 'stopLoss'\n\t| 'oracleLimit';\n\nexport interface NonMarketOrderParamsConfig {\n\tmarketIndex: number;\n\tmarketType: MarketType;\n\tdirection: PositionDirection;\n\tbaseAssetAmount: BN;\n\treduceOnly?: boolean;\n\tpostOnly?: PostOnlyParams;\n\torderConfig:\n\t\t| {\n\t\t\t\torderType: Extract<NonMarketOrderType, 'limit'>;\n\t\t\t\tlimitPrice: BN;\n\t\t\t\tdisableSwift?: boolean;\n\t\t\t\tbracketOrders?: {\n\t\t\t\t\ttakeProfit?: OptionalTriggerOrderParams;\n\t\t\t\t\tstopLoss?: OptionalTriggerOrderParams;\n\t\t\t\t};\n\t\t }\n\t\t| {\n\t\t\t\torderType: Extract<NonMarketOrderType, 'takeProfit' | 'stopLoss'>;\n\t\t\t\ttriggerPrice: BN;\n\t\t\t\tlimitPrice?: BN;\n\t\t }\n\t\t| {\n\t\t\t\torderType: Extract<NonMarketOrderType, 'oracleLimit'>;\n\t\t\t\toraclePriceOffset: BN;\n\t\t };\n}\n\n/**\n * Determine trigger condition based on direction\n * For stop orders: ABOVE when long, BELOW when short\n * For take profit orders: BELOW when long, ABOVE when short\n */\nconst getTriggerCondition = (\n\tdirection: PositionDirection,\n\ttpOrSl: 'takeProfit' | 'stopLoss'\n) => {\n\tconst isTakeProfit = tpOrSl === 'takeProfit';\n\tconst isLong = ENUM_UTILS.match(direction, PositionDirection.LONG);\n\n\tif (isTakeProfit) {\n\t\tif (isLong) {\n\t\t\treturn OrderTriggerCondition.BELOW;\n\t\t} else {\n\t\t\treturn OrderTriggerCondition.ABOVE;\n\t\t}\n\t} else {\n\t\t// Stop loss\n\t\tif (isLong) {\n\t\t\treturn OrderTriggerCondition.ABOVE;\n\t\t} else {\n\t\t\treturn OrderTriggerCondition.BELOW;\n\t\t}\n\t}\n};\n\n/**\n * Builds proper order parameters for non-market orders using the same logic as the UI\n */\nexport function buildNonMarketOrderParams({\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tbaseAssetAmount,\n\torderConfig,\n\treduceOnly = false,\n\tpostOnly = PostOnlyParams.NONE,\n}: NonMarketOrderParamsConfig): OptionalOrderParams {\n\tconst orderType = orderConfig.orderType;\n\n\t// Build order params based on order type using SDK functions\n\tif (orderType === 'limit') {\n\t\tif (!orderConfig.limitPrice) {\n\t\t\tthrow new Error('LIMIT orders require limitPrice');\n\t\t}\n\n\t\treturn getLimitOrderParams({\n\t\t\tmarketIndex,\n\t\t\tmarketType,\n\t\t\tdirection,\n\t\t\tbaseAssetAmount,\n\t\t\tprice: orderConfig.limitPrice,\n\t\t\treduceOnly,\n\t\t\tpostOnly,\n\t\t});\n\t}\n\n\tif (orderType === 'takeProfit' || orderType === 'stopLoss') {\n\t\tif (!orderConfig.triggerPrice) {\n\t\t\tthrow new Error('TRIGGER_MARKET orders require triggerPrice');\n\t\t}\n\n\t\tconst triggerCondition = getTriggerCondition(direction, orderType);\n\t\tconst hasLimitPrice = !!orderConfig.limitPrice;\n\n\t\tif (hasLimitPrice) {\n\t\t\treturn getTriggerLimitOrderParams({\n\t\t\t\tmarketIndex,\n\t\t\t\tmarketType,\n\t\t\t\tdirection,\n\t\t\t\tbaseAssetAmount,\n\t\t\t\ttriggerPrice: orderConfig.triggerPrice,\n\t\t\t\tprice: orderConfig.limitPrice,\n\t\t\t\ttriggerCondition,\n\t\t\t\treduceOnly,\n\t\t\t});\n\t\t} else {\n\t\t\treturn getTriggerMarketOrderParams({\n\t\t\t\tmarketIndex,\n\t\t\t\tmarketType,\n\t\t\t\tdirection,\n\t\t\t\tbaseAssetAmount,\n\t\t\t\ttriggerPrice: orderConfig.triggerPrice,\n\t\t\t\tprice: orderConfig.limitPrice,\n\t\t\t\ttriggerCondition,\n\t\t\t\treduceOnly,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (orderType === 'oracleLimit') {\n\t\tif (!orderConfig.oraclePriceOffset) {\n\t\t\tthrow new Error('ORACLE orders require oraclePriceOffset');\n\t\t}\n\n\t\treturn getLimitOrderParams({\n\t\t\tmarketIndex,\n\t\t\tmarketType,\n\t\t\tdirection,\n\t\t\tbaseAssetAmount,\n\t\t\tprice: ZERO,\n\t\t\toraclePriceOffset: orderConfig.oraclePriceOffset.toNumber(),\n\t\t});\n\t}\n\n\tthrow new Error(`Unsupported order type: ${orderType}`);\n}\n"]}
1
+ {"version":3,"file":"orderParams.js","sourceRoot":"","sources":["../../../src/drift/utils/orderParams.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tBN,\n\tPositionDirection,\n\tPostOnlyParams,\n\tOptionalOrderParams,\n\tgetLimitOrderParams,\n\tgetTriggerMarketOrderParams,\n\tgetTriggerLimitOrderParams,\n\tOrderTriggerCondition,\n\tZERO,\n} from '@drift-labs/sdk';\nimport { ENUM_UTILS } from '../../utils';\nimport { NonMarketOrderParamsConfig } from '../base/actions/trade/openPerpOrder/types';\n\n/**\n * Converts amount and assetType to base asset amount\n * @param amount - The amount to convert\n * @param assetType - 'base' or 'quote'\n * @param limitPrice - Required when assetType is 'quote' for conversion\n * @returns Base asset amount\n */\nexport function convertToBaseAssetAmount(\n\tamount: BN,\n\tassetType: 'base' | 'quote',\n\tlimitPrice?: BN\n): BN {\n\tif (assetType === 'quote') {\n\t\tif (!limitPrice || limitPrice.isZero()) {\n\t\t\tthrow new Error(\n\t\t\t\t'When using quote asset type, limitPrice is required for conversion to base amount'\n\t\t\t);\n\t\t}\n\t\t// Convert quote amount to base amount: quoteAmount / price = baseAmount\n\t\t// Using PRICE_PRECISION as the limit price is in price precision\n\t\tconst PRICE_PRECISION = new BN(10).pow(new BN(6));\n\t\treturn amount.mul(PRICE_PRECISION).div(limitPrice);\n\t} else {\n\t\t// Base amount, use directly\n\t\treturn amount;\n\t}\n}\n\n/**\n * Resolves amount parameters from either new (amount + assetType) or legacy (baseAssetAmount) approach\n */\nexport function resolveBaseAssetAmount(params: {\n\tamount?: BN;\n\tassetType?: 'base' | 'quote';\n\tbaseAssetAmount?: BN;\n\tlimitPrice?: BN;\n}): BN {\n\tconst { amount, assetType, baseAssetAmount, limitPrice } = params;\n\n\tif (amount && assetType) {\n\t\t// New approach: convert if needed\n\t\treturn convertToBaseAssetAmount(amount, assetType, limitPrice);\n\t} else if (baseAssetAmount) {\n\t\t// Legacy approach\n\t\treturn baseAssetAmount;\n\t} else {\n\t\tthrow new Error(\n\t\t\t'Either (amount + assetType) or baseAssetAmount must be provided'\n\t\t);\n\t}\n}\n\n/**\n * Determine trigger condition based on direction\n * For stop orders: ABOVE when long, BELOW when short\n * For take profit orders: BELOW when long, ABOVE when short\n */\nconst getTriggerCondition = (\n\tdirection: PositionDirection,\n\ttpOrSl: 'takeProfit' | 'stopLoss'\n) => {\n\tconst isTakeProfit = tpOrSl === 'takeProfit';\n\tconst isLong = ENUM_UTILS.match(direction, PositionDirection.LONG);\n\n\tif (isTakeProfit) {\n\t\tif (isLong) {\n\t\t\treturn OrderTriggerCondition.BELOW;\n\t\t} else {\n\t\t\treturn OrderTriggerCondition.ABOVE;\n\t\t}\n\t} else {\n\t\t// Stop loss\n\t\tif (isLong) {\n\t\t\treturn OrderTriggerCondition.ABOVE;\n\t\t} else {\n\t\t\treturn OrderTriggerCondition.BELOW;\n\t\t}\n\t}\n};\n\n/**\n * Builds proper order parameters for non-market orders using the same logic as the UI\n */\nexport function buildNonMarketOrderParams({\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tbaseAssetAmount,\n\torderConfig,\n\treduceOnly = false,\n\tpostOnly = PostOnlyParams.NONE,\n\tuserOrderId = 0,\n}: NonMarketOrderParamsConfig): OptionalOrderParams {\n\tconst orderType = orderConfig.orderType;\n\n\t// Build order params based on order type using SDK functions\n\tif (orderType === 'limit') {\n\t\tif (!orderConfig.limitPrice) {\n\t\t\tthrow new Error('LIMIT orders require limitPrice');\n\t\t}\n\n\t\treturn getLimitOrderParams({\n\t\t\tmarketIndex,\n\t\t\tmarketType,\n\t\t\tdirection,\n\t\t\tbaseAssetAmount,\n\t\t\tprice: orderConfig.limitPrice,\n\t\t\treduceOnly,\n\t\t\tpostOnly,\n\t\t\tuserOrderId,\n\t\t});\n\t}\n\n\tif (orderType === 'takeProfit' || orderType === 'stopLoss') {\n\t\tif (!orderConfig.triggerPrice) {\n\t\t\tthrow new Error('TRIGGER_MARKET orders require triggerPrice');\n\t\t}\n\n\t\tconst triggerCondition = getTriggerCondition(direction, orderType);\n\t\tconst hasLimitPrice = !!orderConfig.limitPrice;\n\n\t\tif (hasLimitPrice) {\n\t\t\treturn getTriggerLimitOrderParams({\n\t\t\t\tmarketIndex,\n\t\t\t\tmarketType,\n\t\t\t\tdirection,\n\t\t\t\tbaseAssetAmount,\n\t\t\t\ttriggerPrice: orderConfig.triggerPrice,\n\t\t\t\tprice: orderConfig.limitPrice!,\n\t\t\t\ttriggerCondition,\n\t\t\t\treduceOnly,\n\t\t\t\tpostOnly,\n\t\t\t\tuserOrderId,\n\t\t\t});\n\t\t} else {\n\t\t\treturn getTriggerMarketOrderParams({\n\t\t\t\tmarketIndex,\n\t\t\t\tmarketType,\n\t\t\t\tdirection,\n\t\t\t\tbaseAssetAmount,\n\t\t\t\ttriggerPrice: orderConfig.triggerPrice,\n\t\t\t\tprice: orderConfig.limitPrice,\n\t\t\t\ttriggerCondition,\n\t\t\t\treduceOnly,\n\t\t\t\tpostOnly,\n\t\t\t\tuserOrderId,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (orderType === 'oracleLimit') {\n\t\tif (!orderConfig.oraclePriceOffset) {\n\t\t\tthrow new Error('ORACLE orders require oraclePriceOffset');\n\t\t}\n\n\t\treturn getLimitOrderParams({\n\t\t\tmarketIndex,\n\t\t\tmarketType,\n\t\t\tdirection,\n\t\t\tbaseAssetAmount,\n\t\t\tprice: ZERO,\n\t\t\toraclePriceOffset: orderConfig.oraclePriceOffset.toNumber(),\n\t\t\tuserOrderId,\n\t\t\tpostOnly,\n\t\t\treduceOnly,\n\t\t});\n\t}\n\n\tthrow new Error(`Unsupported order type: ${orderType}`);\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -21,6 +21,8 @@ export * from './utils/SharedInterval';
21
21
  export * from './utils/Stopwatch';
22
22
  export * from './utils/priority-fees';
23
23
  export * from './utils/superstake';
24
+ export * from './utils/fetch';
25
+ export * from './utils/priceImpact';
24
26
  export * from './utils/dlob-server/DlobServerWebsocketUtils';
25
27
  export * from './common-ui-utils/settings/settings';
26
28
  export * from './utils/priority-fees';
package/lib/index.js CHANGED
@@ -41,6 +41,8 @@ __exportStar(require("./utils/SharedInterval"), exports);
41
41
  __exportStar(require("./utils/Stopwatch"), exports);
42
42
  __exportStar(require("./utils/priority-fees"), exports);
43
43
  __exportStar(require("./utils/superstake"), exports);
44
+ __exportStar(require("./utils/fetch"), exports);
45
+ __exportStar(require("./utils/priceImpact"), exports);
44
46
  __exportStar(require("./utils/dlob-server/DlobServerWebsocketUtils"), exports);
45
47
  __exportStar(require("./common-ui-utils/settings/settings"), exports);
46
48
  __exportStar(require("./utils/priority-fees"), exports);
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,0CAAwB;AACxB,yDAAuC;AACvC,0CAAwB;AACxB,gDAA8B;AAC9B,oDAAkC;AAClC,sDAAoC;AACpC,yDAAuC;AACvC,uDAAqC;AACrC,gEAA8C;AAC9C,qDAAmC;AACnC,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,yDAAuC;AACvC,oDAAkC;AAClC,8CAA4B;AAC5B,wEAAsD;AACtD,yDAAuC;AACvC,oDAAkC;AAClC,wDAAsC;AACtC,qDAAmC;AACnC,+EAA6D;AAC7D,sEAAoD;AACpD,wDAAsC;AACtC,oDAAkC;AAClC,yDAAuC;AACvC,2DAAyC;AACzC,wDAAsC;AACtC,mDAAiC;AACjC,+DAA6C;AAC7C,sDAAoC;AACpC,6DAA2C;AAC3C,mEAAiD;AACjD,0DAAwC;AACxC,+CAA6B;AAC7B,uDAAqC;AACrC,iDAA+B;AAC/B,0CAAwB;AAExB,0BAA0B;AAC1B,gHAA4E;AAEnE,sBAFF,iCAAW,CAEE;AADpB,gHAA4E;AACtD,sBADf,iCAAW,CACe;AAEjC,kGAAqE;AAC5D,sBADF,0BAAW,CACE","sourcesContent":["export * from './Config';\nexport * from './chartConstants';\nexport * from './types';\nexport * from './EnvironmentConstants';\nexport * from './utils';\nexport * from './utils/index';\nexport * from './utils/s3Buckets';\nexport * from './serializableTypes';\nexport * from './utils/candles/Candle';\nexport * from './utils/featureFlags';\nexport * from './utils/WalletConnectionState';\nexport * from './utils/rpcLatency';\nexport * from './utils/token';\nexport * from './utils/math';\nexport * from './utils/logger';\nexport * from './utils/equalityChecks';\nexport * from './common-ui-utils';\nexport * from './constants';\nexport * from './actions/actionHelpers/actionHelpers';\nexport * from './utils/SharedInterval';\nexport * from './utils/Stopwatch';\nexport * from './utils/priority-fees';\nexport * from './utils/superstake';\nexport * from './utils/dlob-server/DlobServerWebsocketUtils';\nexport * from './common-ui-utils/settings/settings';\nexport * from './utils/priority-fees';\nexport * from './utils/orderbook';\nexport * from './clients/candleClient';\nexport * from './clients/marketDataFeed';\nexport * from './clients/swiftClient';\nexport * from './clients/tvFeed';\nexport * from './utils/pollingSequenceGuard';\nexport * from './utils/driftEvents';\nexport * from './utils/MultiplexWebSocket';\nexport * from './utils/SlotBasedResultValidator';\nexport * from './utils/CircularBuffers';\nexport * from './utils/rxjs';\nexport * from './utils/priorityFees';\nexport * from './utils/NumLib';\nexport * from './drift';\n\n// External Program Errors\nimport JupV4Errors from './constants/autogenerated/jup-v4-error-codes.json';\nimport JupV6Errors from './constants/autogenerated/jup-v6-error-codes.json';\nexport { JupV4Errors, JupV6Errors };\n\nimport DriftErrors from './constants/autogenerated/driftErrors.json';\nexport { DriftErrors };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,0CAAwB;AACxB,yDAAuC;AACvC,0CAAwB;AACxB,gDAA8B;AAC9B,oDAAkC;AAClC,sDAAoC;AACpC,yDAAuC;AACvC,uDAAqC;AACrC,gEAA8C;AAC9C,qDAAmC;AACnC,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,yDAAuC;AACvC,oDAAkC;AAClC,8CAA4B;AAC5B,wEAAsD;AACtD,yDAAuC;AACvC,oDAAkC;AAClC,wDAAsC;AACtC,qDAAmC;AACnC,gDAA8B;AAC9B,sDAAoC;AACpC,+EAA6D;AAC7D,sEAAoD;AACpD,wDAAsC;AACtC,oDAAkC;AAClC,yDAAuC;AACvC,2DAAyC;AACzC,wDAAsC;AACtC,mDAAiC;AACjC,+DAA6C;AAC7C,sDAAoC;AACpC,6DAA2C;AAC3C,mEAAiD;AACjD,0DAAwC;AACxC,+CAA6B;AAC7B,uDAAqC;AACrC,iDAA+B;AAC/B,0CAAwB;AAExB,0BAA0B;AAC1B,gHAA4E;AAEnE,sBAFF,iCAAW,CAEE;AADpB,gHAA4E;AACtD,sBADf,iCAAW,CACe;AAEjC,kGAAqE;AAC5D,sBADF,0BAAW,CACE","sourcesContent":["export * from './Config';\nexport * from './chartConstants';\nexport * from './types';\nexport * from './EnvironmentConstants';\nexport * from './utils';\nexport * from './utils/index';\nexport * from './utils/s3Buckets';\nexport * from './serializableTypes';\nexport * from './utils/candles/Candle';\nexport * from './utils/featureFlags';\nexport * from './utils/WalletConnectionState';\nexport * from './utils/rpcLatency';\nexport * from './utils/token';\nexport * from './utils/math';\nexport * from './utils/logger';\nexport * from './utils/equalityChecks';\nexport * from './common-ui-utils';\nexport * from './constants';\nexport * from './actions/actionHelpers/actionHelpers';\nexport * from './utils/SharedInterval';\nexport * from './utils/Stopwatch';\nexport * from './utils/priority-fees';\nexport * from './utils/superstake';\nexport * from './utils/fetch';\nexport * from './utils/priceImpact';\nexport * from './utils/dlob-server/DlobServerWebsocketUtils';\nexport * from './common-ui-utils/settings/settings';\nexport * from './utils/priority-fees';\nexport * from './utils/orderbook';\nexport * from './clients/candleClient';\nexport * from './clients/marketDataFeed';\nexport * from './clients/swiftClient';\nexport * from './clients/tvFeed';\nexport * from './utils/pollingSequenceGuard';\nexport * from './utils/driftEvents';\nexport * from './utils/MultiplexWebSocket';\nexport * from './utils/SlotBasedResultValidator';\nexport * from './utils/CircularBuffers';\nexport * from './utils/rxjs';\nexport * from './utils/priorityFees';\nexport * from './utils/NumLib';\nexport * from './drift';\n\n// External Program Errors\nimport JupV4Errors from './constants/autogenerated/jup-v4-error-codes.json';\nimport JupV6Errors from './constants/autogenerated/jup-v6-error-codes.json';\nexport { JupV4Errors, JupV6Errors };\n\nimport DriftErrors from './constants/autogenerated/driftErrors.json';\nexport { DriftErrors };\n"]}
@@ -32,6 +32,7 @@ export type OpenPosition = {
32
32
  pnlIsClaimable: boolean;
33
33
  remainderBaseAmount?: number;
34
34
  lpDeriskPrice?: BN;
35
+ maxMarginRatio: number;
35
36
  };
36
37
  export type BankBalanceUI = SpotPosition & {
37
38
  accountId: number;
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/types/user.ts"],"names":[],"mappings":"","sourcesContent":["import { BN, PublicKey, SpotPosition } from '@drift-labs/sdk';\n\nexport type OpenPosition = {\n\tmarketIndex: number;\n\tmarketSymbol: string;\n\tdirection: 'short' | 'long';\n\tnotional: BN;\n\tbaseSize: BN;\n\tentryPrice: BN;\n\texitPrice: BN;\n\tliqPrice: BN;\n\tpnlVsOracle: BN;\n\tpnlVsMark: BN;\n\tquoteAssetNotionalAmount: BN;\n\tquoteEntryAmount: BN;\n\tquoteBreakEvenAmount: BN;\n\tunrealizedFundingPnl: BN;\n\tfeesAndFundingPnl: BN;\n\tlastCumulativeFundingRate: BN;\n\topenOrders: number;\n\t/**\n\t * This is the unsettled pnl that is claimable. Naming is a bit confusing here.\n\t */\n\tunsettledPnl: BN;\n\tunsettledFundingPnl: BN;\n\t/**\n\t * This is the total of unsettled pnl and unsettled funding.\n\t */\n\ttotalUnrealizedPnl: BN;\n\tcostBasis: BN;\n\trealizedPnl: BN;\n\tlpShares: BN;\n\tpnlIsClaimable: boolean;\n\tremainderBaseAmount?: number; // LP only\n\tlpDeriskPrice?: BN; //LP only\n};\n\nexport type BankBalanceUI = SpotPosition & {\n\taccountId: number;\n\taccountName: string;\n\taccountAuthority: PublicKey;\n};\n"]}
1
+ {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/types/user.ts"],"names":[],"mappings":"","sourcesContent":["import { BN, PublicKey, SpotPosition } from '@drift-labs/sdk';\n\nexport type OpenPosition = {\n\tmarketIndex: number;\n\tmarketSymbol: string;\n\tdirection: 'short' | 'long';\n\tnotional: BN;\n\tbaseSize: BN;\n\tentryPrice: BN;\n\texitPrice: BN;\n\tliqPrice: BN;\n\tpnlVsOracle: BN;\n\tpnlVsMark: BN;\n\tquoteAssetNotionalAmount: BN;\n\tquoteEntryAmount: BN;\n\tquoteBreakEvenAmount: BN;\n\tunrealizedFundingPnl: BN;\n\tfeesAndFundingPnl: BN;\n\tlastCumulativeFundingRate: BN;\n\topenOrders: number;\n\t/**\n\t * This is the unsettled pnl that is claimable. Naming is a bit confusing here.\n\t */\n\tunsettledPnl: BN;\n\tunsettledFundingPnl: BN;\n\t/**\n\t * This is the total of unsettled pnl and unsettled funding.\n\t */\n\ttotalUnrealizedPnl: BN;\n\tcostBasis: BN;\n\trealizedPnl: BN;\n\tlpShares: BN;\n\tpnlIsClaimable: boolean;\n\tremainderBaseAmount?: number; // LP only\n\tlpDeriskPrice?: BN; //LP only\n\tmaxMarginRatio: number;\n};\n\nexport type BankBalanceUI = SpotPosition & {\n\taccountId: number;\n\taccountName: string;\n\taccountAuthority: PublicKey;\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const encodeQueryParams: (params: Record<string, string | undefined>) => string;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeQueryParams = void 0;
4
+ const encodeQueryParams = (params) => {
5
+ return Object.entries(params)
6
+ .filter(([_, value]) => value !== undefined)
7
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
8
+ .join('&');
9
+ };
10
+ exports.encodeQueryParams = encodeQueryParams;
11
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":";;;AAAO,MAAM,iBAAiB,GAAG,CAChC,MAA0C,EACjC,EAAE;IACX,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;SAC3C,GAAG,CACH,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAChB,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,kBAAkB,CAAC,KAAM,CAAC,EAAE,CAC3D;SACA,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC,CAAC;AAVW,QAAA,iBAAiB,qBAU5B","sourcesContent":["export const encodeQueryParams = (\n\tparams: Record<string, string | undefined>\n): string => {\n\treturn Object.entries(params)\n\t\t.filter(([_, value]) => value !== undefined)\n\t\t.map(\n\t\t\t([key, value]) =>\n\t\t\t\t`${encodeURIComponent(key)}=${encodeURIComponent(value!)}`\n\t\t)\n\t\t.join('&');\n};\n"]}
@@ -1,4 +1,5 @@
1
1
  import { MarketType, OraclePriceData, L2OrderBook, BN, MMOraclePriceData } from '@drift-labs/sdk';
2
+ import { MarketId } from '../../types';
2
3
  export interface L2WithOracle extends L2OrderBook {
3
4
  oracleData: OraclePriceData;
4
5
  markPrice: BN;
@@ -63,3 +64,20 @@ export type LiquidityType = 'vamm' | 'dlob' | 'serum' | 'phoenix' | 'openbook';
63
64
  * @returns
64
65
  */
65
66
  export declare const deserializeL2Response: (serializedOrderbook: RawL2Output) => L2WithOracleAndMarketData;
67
+ export declare const convertToL2OrderBook: (l2Data: L2WithOracleAndMarketData[]) => L2OrderBook;
68
+ export interface DynamicSlippageConfig {
69
+ dynamicSlippageMin?: number;
70
+ dynamicSlippageMax?: number;
71
+ dynamicBaseSlippageMajor?: number;
72
+ dynamicBaseSlippageNonMajor?: number;
73
+ dynamicSlippageMultiplierMajor?: number;
74
+ dynamicSlippageMultiplierNonMajor?: number;
75
+ }
76
+ export declare const calculateDynamicSlippageFromL2: ({ l2Data, marketId, startPrice, worstPrice, oraclePrice, dynamicSlippageConfig, }: {
77
+ l2Data: L2OrderBook;
78
+ marketId: MarketId;
79
+ startPrice: BN;
80
+ worstPrice: BN;
81
+ oraclePrice?: BN;
82
+ dynamicSlippageConfig?: DynamicSlippageConfig;
83
+ }) => number;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deserializeL2Response = void 0;
3
+ exports.calculateDynamicSlippageFromL2 = exports.convertToL2OrderBook = exports.deserializeL2Response = void 0;
4
4
  const sdk_1 = require("@drift-labs/sdk");
5
+ const math_1 = require("../math");
5
6
  /**
6
7
  * Helper function to deserialize the response from the dlob server. (See https://drift-labs.github.io/v2-teacher/#get-l2-l3)
7
8
  * @param serializedOrderbook
@@ -77,4 +78,70 @@ const deserializeL2Response = (serializedOrderbook) => {
77
78
  };
78
79
  };
79
80
  exports.deserializeL2Response = deserializeL2Response;
81
+ const convertToL2OrderBook = (l2Data) => {
82
+ // Find the market data - there should be one entry for our market
83
+ const marketData = l2Data[0];
84
+ if (!marketData) {
85
+ throw new Error('No L2 data available for market');
86
+ }
87
+ // L2WithOracleAndMarketData extends L2OrderBook, so we can use it directly
88
+ return {
89
+ asks: marketData.asks,
90
+ bids: marketData.bids,
91
+ slot: marketData.slot,
92
+ };
93
+ };
94
+ exports.convertToL2OrderBook = convertToL2OrderBook;
95
+ const DEFAULT_DYNAMIC_SLIPPAGE_CONFIG = {
96
+ dynamicSlippageMin: 0.05,
97
+ dynamicSlippageMax: 5,
98
+ dynamicBaseSlippageMajor: 0,
99
+ dynamicBaseSlippageNonMajor: 0.5,
100
+ dynamicSlippageMultiplierMajor: 1.02,
101
+ dynamicSlippageMultiplierNonMajor: 1.2,
102
+ };
103
+ const calculateDynamicSlippageFromL2 = ({ l2Data, marketId, startPrice, worstPrice, oraclePrice, dynamicSlippageConfig, }) => {
104
+ var _a, _b, _c, _d;
105
+ const dynamicSlippageConfigToUse = dynamicSlippageConfig
106
+ ? { ...DEFAULT_DYNAMIC_SLIPPAGE_CONFIG, ...dynamicSlippageConfig }
107
+ : DEFAULT_DYNAMIC_SLIPPAGE_CONFIG;
108
+ // Calculate spread information from L2 data using the oracle price
109
+ const spreadBidAskMark = math_1.COMMON_MATH.calculateSpreadBidAskMark(l2Data, oraclePrice);
110
+ const bestAskNum = ((_b = (_a = spreadBidAskMark.bestAskPrice) === null || _a === void 0 ? void 0 : _a.toNumber) === null || _b === void 0 ? void 0 : _b.call(_a)) || 0;
111
+ const bestBidNum = ((_d = (_c = spreadBidAskMark.bestBidPrice) === null || _c === void 0 ? void 0 : _c.toNumber) === null || _d === void 0 ? void 0 : _d.call(_c)) || 0;
112
+ const spreadPctFromL2 = sdk_1.BigNum.from(spreadBidAskMark.spreadPct, sdk_1.PERCENTAGE_PRECISION_EXP).toNum();
113
+ // Calculate spread percentage
114
+ const spreadPct = spreadPctFromL2 ||
115
+ (Math.abs(bestAskNum - bestBidNum) / ((bestAskNum + bestBidNum) / 2)) * 100;
116
+ // Default to 0.5% if we get invalid spread info
117
+ if (isNaN(spreadPct) || spreadPct <= 0) {
118
+ return 0.5;
119
+ }
120
+ // Apply a buffer based on the tier of the contract
121
+ // Currently no buffer for SOL/BTC/ETH perp and a +10% buffer for other markets
122
+ const isMajor = marketId.isPerp && marketId.marketIndex < 3;
123
+ const spreadBaseSlippage = spreadPct / 2;
124
+ const baseSlippage = isMajor
125
+ ? dynamicSlippageConfigToUse.dynamicBaseSlippageMajor
126
+ : dynamicSlippageConfigToUse.dynamicBaseSlippageNonMajor;
127
+ let dynamicSlippage = baseSlippage + spreadBaseSlippage;
128
+ // Use halfway to worst price as size adjusted slippage
129
+ if (startPrice && worstPrice) {
130
+ const sizeAdjustedSlippage = (startPrice.sub(worstPrice).abs().toNumber() /
131
+ sdk_1.BN.max(startPrice, worstPrice).toNumber() /
132
+ 2) *
133
+ 100;
134
+ dynamicSlippage = Math.max(dynamicSlippage, sizeAdjustedSlippage);
135
+ }
136
+ // Apply multiplier from env var
137
+ const multiplier = isMajor
138
+ ? dynamicSlippageConfigToUse.dynamicSlippageMultiplierMajor
139
+ : dynamicSlippageConfigToUse.dynamicSlippageMultiplierNonMajor;
140
+ dynamicSlippage = dynamicSlippage * multiplier;
141
+ // Enforce .05% minimum, 5% maximum, can change these in env vars
142
+ const finalSlippage = Math.min(Math.max(dynamicSlippage, dynamicSlippageConfigToUse.dynamicSlippageMin), dynamicSlippageConfigToUse.dynamicSlippageMax);
143
+ // Round to avoid floating point precision issues, preserving 6 decimal places
144
+ return Math.round(finalSlippage * 1000000) / 1000000;
145
+ };
146
+ exports.calculateDynamicSlippageFromL2 = calculateDynamicSlippageFromL2;
80
147
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/orderbook/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tMarketType,\n\tOraclePriceData,\n\tL2OrderBook,\n\tBN,\n\tMMOraclePriceData,\n} from '@drift-labs/sdk';\n\nexport interface L2WithOracle extends L2OrderBook {\n\toracleData: OraclePriceData;\n\tmarkPrice: BN;\n\tbestBidPrice: BN;\n\tbestAskPrice: BN;\n\tspreadPct: BN;\n\tspreadQuote: BN;\n\tmmOracleData?: MMOraclePriceData;\n}\n\nexport interface L2WithOracleAndMarketData extends L2WithOracle {\n\tmarketSlot: number;\n\tmarketIndex: number;\n\tmarketName: string;\n\tmarketType?: MarketType;\n}\n\nexport type RawL2Output = {\n\tmarketIndex: number;\n\tmarketType: MarketType;\n\tmarketName: string;\n\tmarketSlot: number;\n\tasks: {\n\t\tprice: string;\n\t\tsize: string;\n\t\tsources: {\n\t\t\t[key: string]: string;\n\t\t};\n\t}[];\n\tbids: {\n\t\tprice: string;\n\t\tsize: string;\n\t\tsources: {\n\t\t\t[key: string]: string;\n\t\t};\n\t}[];\n\toracleData: {\n\t\tprice: string;\n\t\tslot: string;\n\t\tconfidence: string;\n\t\thasSufficientNumberOfDataPoints: boolean;\n\t\ttwap?: string;\n\t\ttwapConfidence?: string;\n\t\tmaxPrice?: string;\n\t};\n\tmmOracleData?: {\n\t\tprice: string;\n\t\tslot: string;\n\t\tconfidence: string;\n\t\thasSufficientNumberOfDataPoints: boolean;\n\t\tisMMOracleActive: boolean;\n\t};\n\tmarkPrice: string;\n\tbestBidPrice: string;\n\tbestAskPrice: string;\n\tspreadPct: string;\n\tspreadQuote: string;\n\tslot?: number;\n};\n\nexport type LiquidityType = 'vamm' | 'dlob' | 'serum' | 'phoenix' | 'openbook';\n\n/**\n * Helper function to deserialize the response from the dlob server. (See https://drift-labs.github.io/v2-teacher/#get-l2-l3)\n * @param serializedOrderbook\n * @returns\n */\nexport const deserializeL2Response = (\n\tserializedOrderbook: RawL2Output\n): L2WithOracleAndMarketData => {\n\treturn {\n\t\tasks: serializedOrderbook.asks.map((ask) => ({\n\t\t\tprice: new BN(ask.price),\n\t\t\tsize: new BN(ask.size),\n\t\t\tsources: Object.entries(ask.sources).reduce((previous, [key, val]) => {\n\t\t\t\treturn {\n\t\t\t\t\t...previous,\n\t\t\t\t\t[key]: new BN(val),\n\t\t\t\t};\n\t\t\t}, {}),\n\t\t})),\n\t\tbids: serializedOrderbook.bids.map((bid) => ({\n\t\t\tprice: new BN(bid.price),\n\t\t\tsize: new BN(bid.size),\n\t\t\tsources: Object.entries(bid.sources).reduce((previous, [key, val]) => {\n\t\t\t\treturn {\n\t\t\t\t\t...previous,\n\t\t\t\t\t[key]: new BN(val),\n\t\t\t\t};\n\t\t\t}, {}),\n\t\t})),\n\t\toracleData: {\n\t\t\tprice: serializedOrderbook.oracleData.price\n\t\t\t\t? new BN(serializedOrderbook.oracleData.price)\n\t\t\t\t: undefined,\n\t\t\tslot: serializedOrderbook.oracleData.slot\n\t\t\t\t? new BN(serializedOrderbook.oracleData.slot)\n\t\t\t\t: undefined,\n\t\t\tconfidence: serializedOrderbook.oracleData.confidence\n\t\t\t\t? new BN(serializedOrderbook.oracleData.confidence)\n\t\t\t\t: undefined,\n\t\t\thasSufficientNumberOfDataPoints:\n\t\t\t\tserializedOrderbook.oracleData.hasSufficientNumberOfDataPoints,\n\t\t\ttwap: serializedOrderbook.oracleData.twap\n\t\t\t\t? new BN(serializedOrderbook.oracleData.twap)\n\t\t\t\t: undefined,\n\t\t\ttwapConfidence: serializedOrderbook.oracleData.twapConfidence\n\t\t\t\t? new BN(serializedOrderbook.oracleData.twapConfidence)\n\t\t\t\t: undefined,\n\t\t\tmaxPrice: serializedOrderbook.oracleData.maxPrice\n\t\t\t\t? new BN(serializedOrderbook.oracleData.maxPrice)\n\t\t\t\t: undefined,\n\t\t},\n\t\tmmOracleData: {\n\t\t\tprice: serializedOrderbook.mmOracleData?.price\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.price)\n\t\t\t\t: undefined,\n\t\t\tslot: serializedOrderbook.mmOracleData?.slot\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.slot)\n\t\t\t\t: undefined,\n\t\t\tconfidence: serializedOrderbook.mmOracleData?.confidence\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.confidence)\n\t\t\t\t: undefined,\n\t\t\thasSufficientNumberOfDataPoints:\n\t\t\t\tserializedOrderbook.mmOracleData?.hasSufficientNumberOfDataPoints,\n\t\t\tisMMOracleActive:\n\t\t\t\tserializedOrderbook.mmOracleData?.isMMOracleActive ?? false,\n\t\t},\n\t\tslot: serializedOrderbook.slot,\n\t\tmarketSlot: serializedOrderbook.marketSlot,\n\t\tmarketType: serializedOrderbook.marketType,\n\t\tmarketIndex: serializedOrderbook.marketIndex,\n\t\tmarketName: serializedOrderbook.marketName,\n\t\tmarkPrice: new BN(serializedOrderbook.markPrice),\n\t\tbestBidPrice: new BN(serializedOrderbook.bestBidPrice),\n\t\tbestAskPrice: new BN(serializedOrderbook.bestAskPrice),\n\t\tspreadPct: new BN(serializedOrderbook.spreadPct),\n\t\tspreadQuote: new BN(serializedOrderbook.spreadQuote),\n\t};\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/orderbook/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tMarketType,\n\tOraclePriceData,\n\tL2OrderBook,\n\tBN,\n\tMMOraclePriceData,\n\tBigNum,\n\tPERCENTAGE_PRECISION_EXP,\n} from '@drift-labs/sdk';\nimport { MarketId } from '../../types';\nimport { COMMON_MATH } from '../math';\n\nexport interface L2WithOracle extends L2OrderBook {\n\toracleData: OraclePriceData;\n\tmarkPrice: BN;\n\tbestBidPrice: BN;\n\tbestAskPrice: BN;\n\tspreadPct: BN;\n\tspreadQuote: BN;\n\tmmOracleData?: MMOraclePriceData;\n}\n\nexport interface L2WithOracleAndMarketData extends L2WithOracle {\n\tmarketSlot: number;\n\tmarketIndex: number;\n\tmarketName: string;\n\tmarketType?: MarketType;\n}\n\nexport type RawL2Output = {\n\tmarketIndex: number;\n\tmarketType: MarketType;\n\tmarketName: string;\n\tmarketSlot: number;\n\tasks: {\n\t\tprice: string;\n\t\tsize: string;\n\t\tsources: {\n\t\t\t[key: string]: string;\n\t\t};\n\t}[];\n\tbids: {\n\t\tprice: string;\n\t\tsize: string;\n\t\tsources: {\n\t\t\t[key: string]: string;\n\t\t};\n\t}[];\n\toracleData: {\n\t\tprice: string;\n\t\tslot: string;\n\t\tconfidence: string;\n\t\thasSufficientNumberOfDataPoints: boolean;\n\t\ttwap?: string;\n\t\ttwapConfidence?: string;\n\t\tmaxPrice?: string;\n\t};\n\tmmOracleData?: {\n\t\tprice: string;\n\t\tslot: string;\n\t\tconfidence: string;\n\t\thasSufficientNumberOfDataPoints: boolean;\n\t\tisMMOracleActive: boolean;\n\t};\n\tmarkPrice: string;\n\tbestBidPrice: string;\n\tbestAskPrice: string;\n\tspreadPct: string;\n\tspreadQuote: string;\n\tslot?: number;\n};\n\nexport type LiquidityType = 'vamm' | 'dlob' | 'serum' | 'phoenix' | 'openbook';\n\n/**\n * Helper function to deserialize the response from the dlob server. (See https://drift-labs.github.io/v2-teacher/#get-l2-l3)\n * @param serializedOrderbook\n * @returns\n */\nexport const deserializeL2Response = (\n\tserializedOrderbook: RawL2Output\n): L2WithOracleAndMarketData => {\n\treturn {\n\t\tasks: serializedOrderbook.asks.map((ask) => ({\n\t\t\tprice: new BN(ask.price),\n\t\t\tsize: new BN(ask.size),\n\t\t\tsources: Object.entries(ask.sources).reduce((previous, [key, val]) => {\n\t\t\t\treturn {\n\t\t\t\t\t...previous,\n\t\t\t\t\t[key]: new BN(val),\n\t\t\t\t};\n\t\t\t}, {}),\n\t\t})),\n\t\tbids: serializedOrderbook.bids.map((bid) => ({\n\t\t\tprice: new BN(bid.price),\n\t\t\tsize: new BN(bid.size),\n\t\t\tsources: Object.entries(bid.sources).reduce((previous, [key, val]) => {\n\t\t\t\treturn {\n\t\t\t\t\t...previous,\n\t\t\t\t\t[key]: new BN(val),\n\t\t\t\t};\n\t\t\t}, {}),\n\t\t})),\n\t\toracleData: {\n\t\t\tprice: serializedOrderbook.oracleData.price\n\t\t\t\t? new BN(serializedOrderbook.oracleData.price)\n\t\t\t\t: undefined,\n\t\t\tslot: serializedOrderbook.oracleData.slot\n\t\t\t\t? new BN(serializedOrderbook.oracleData.slot)\n\t\t\t\t: undefined,\n\t\t\tconfidence: serializedOrderbook.oracleData.confidence\n\t\t\t\t? new BN(serializedOrderbook.oracleData.confidence)\n\t\t\t\t: undefined,\n\t\t\thasSufficientNumberOfDataPoints:\n\t\t\t\tserializedOrderbook.oracleData.hasSufficientNumberOfDataPoints,\n\t\t\ttwap: serializedOrderbook.oracleData.twap\n\t\t\t\t? new BN(serializedOrderbook.oracleData.twap)\n\t\t\t\t: undefined,\n\t\t\ttwapConfidence: serializedOrderbook.oracleData.twapConfidence\n\t\t\t\t? new BN(serializedOrderbook.oracleData.twapConfidence)\n\t\t\t\t: undefined,\n\t\t\tmaxPrice: serializedOrderbook.oracleData.maxPrice\n\t\t\t\t? new BN(serializedOrderbook.oracleData.maxPrice)\n\t\t\t\t: undefined,\n\t\t},\n\t\tmmOracleData: {\n\t\t\tprice: serializedOrderbook.mmOracleData?.price\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.price)\n\t\t\t\t: undefined,\n\t\t\tslot: serializedOrderbook.mmOracleData?.slot\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.slot)\n\t\t\t\t: undefined,\n\t\t\tconfidence: serializedOrderbook.mmOracleData?.confidence\n\t\t\t\t? new BN(serializedOrderbook.mmOracleData.confidence)\n\t\t\t\t: undefined,\n\t\t\thasSufficientNumberOfDataPoints:\n\t\t\t\tserializedOrderbook.mmOracleData?.hasSufficientNumberOfDataPoints,\n\t\t\tisMMOracleActive:\n\t\t\t\tserializedOrderbook.mmOracleData?.isMMOracleActive ?? false,\n\t\t},\n\t\tslot: serializedOrderbook.slot,\n\t\tmarketSlot: serializedOrderbook.marketSlot,\n\t\tmarketType: serializedOrderbook.marketType,\n\t\tmarketIndex: serializedOrderbook.marketIndex,\n\t\tmarketName: serializedOrderbook.marketName,\n\t\tmarkPrice: new BN(serializedOrderbook.markPrice),\n\t\tbestBidPrice: new BN(serializedOrderbook.bestBidPrice),\n\t\tbestAskPrice: new BN(serializedOrderbook.bestAskPrice),\n\t\tspreadPct: new BN(serializedOrderbook.spreadPct),\n\t\tspreadQuote: new BN(serializedOrderbook.spreadQuote),\n\t};\n};\n\nexport const convertToL2OrderBook = (\n\tl2Data: L2WithOracleAndMarketData[]\n): L2OrderBook => {\n\t// Find the market data - there should be one entry for our market\n\tconst marketData = l2Data[0];\n\n\tif (!marketData) {\n\t\tthrow new Error('No L2 data available for market');\n\t}\n\n\t// L2WithOracleAndMarketData extends L2OrderBook, so we can use it directly\n\treturn {\n\t\tasks: marketData.asks,\n\t\tbids: marketData.bids,\n\t\tslot: marketData.slot,\n\t};\n};\n\nexport interface DynamicSlippageConfig {\n\tdynamicSlippageMin?: number;\n\tdynamicSlippageMax?: number;\n\tdynamicBaseSlippageMajor?: number;\n\tdynamicBaseSlippageNonMajor?: number;\n\tdynamicSlippageMultiplierMajor?: number;\n\tdynamicSlippageMultiplierNonMajor?: number;\n}\n\nconst DEFAULT_DYNAMIC_SLIPPAGE_CONFIG: DynamicSlippageConfig = {\n\tdynamicSlippageMin: 0.05,\n\tdynamicSlippageMax: 5,\n\tdynamicBaseSlippageMajor: 0,\n\tdynamicBaseSlippageNonMajor: 0.5,\n\tdynamicSlippageMultiplierMajor: 1.02,\n\tdynamicSlippageMultiplierNonMajor: 1.2,\n};\n\nexport const calculateDynamicSlippageFromL2 = ({\n\tl2Data,\n\tmarketId,\n\tstartPrice,\n\tworstPrice,\n\toraclePrice,\n\tdynamicSlippageConfig,\n}: {\n\tl2Data: L2OrderBook;\n\tmarketId: MarketId;\n\tstartPrice: BN;\n\tworstPrice: BN;\n\toraclePrice?: BN;\n\tdynamicSlippageConfig?: DynamicSlippageConfig;\n}): number => {\n\tconst dynamicSlippageConfigToUse = dynamicSlippageConfig\n\t\t? { ...DEFAULT_DYNAMIC_SLIPPAGE_CONFIG, ...dynamicSlippageConfig }\n\t\t: DEFAULT_DYNAMIC_SLIPPAGE_CONFIG;\n\n\t// Calculate spread information from L2 data using the oracle price\n\tconst spreadBidAskMark = COMMON_MATH.calculateSpreadBidAskMark(\n\t\tl2Data,\n\t\toraclePrice\n\t);\n\n\tconst bestAskNum = spreadBidAskMark.bestAskPrice?.toNumber?.() || 0;\n\tconst bestBidNum = spreadBidAskMark.bestBidPrice?.toNumber?.() || 0;\n\n\tconst spreadPctFromL2 = BigNum.from(\n\t\tspreadBidAskMark.spreadPct,\n\t\tPERCENTAGE_PRECISION_EXP\n\t).toNum();\n\n\t// Calculate spread percentage\n\tconst spreadPct =\n\t\tspreadPctFromL2 ||\n\t\t(Math.abs(bestAskNum - bestBidNum) / ((bestAskNum + bestBidNum) / 2)) * 100;\n\n\t// Default to 0.5% if we get invalid spread info\n\tif (isNaN(spreadPct) || spreadPct <= 0) {\n\t\treturn 0.5;\n\t}\n\n\t// Apply a buffer based on the tier of the contract\n\t// Currently no buffer for SOL/BTC/ETH perp and a +10% buffer for other markets\n\tconst isMajor = marketId.isPerp && marketId.marketIndex < 3;\n\n\tconst spreadBaseSlippage = spreadPct / 2;\n\n\tconst baseSlippage = isMajor\n\t\t? dynamicSlippageConfigToUse.dynamicBaseSlippageMajor\n\t\t: dynamicSlippageConfigToUse.dynamicBaseSlippageNonMajor;\n\tlet dynamicSlippage = baseSlippage + spreadBaseSlippage;\n\n\t// Use halfway to worst price as size adjusted slippage\n\tif (startPrice && worstPrice) {\n\t\tconst sizeAdjustedSlippage =\n\t\t\t(startPrice.sub(worstPrice).abs().toNumber() /\n\t\t\t\tBN.max(startPrice, worstPrice).toNumber() /\n\t\t\t\t2) *\n\t\t\t100;\n\n\t\tdynamicSlippage = Math.max(dynamicSlippage, sizeAdjustedSlippage);\n\t}\n\n\t// Apply multiplier from env var\n\tconst multiplier = isMajor\n\t\t? dynamicSlippageConfigToUse.dynamicSlippageMultiplierMajor\n\t\t: dynamicSlippageConfigToUse.dynamicSlippageMultiplierNonMajor;\n\n\tdynamicSlippage = dynamicSlippage * multiplier;\n\n\t// Enforce .05% minimum, 5% maximum, can change these in env vars\n\tconst finalSlippage = Math.min(\n\t\tMath.max(dynamicSlippage, dynamicSlippageConfigToUse.dynamicSlippageMin),\n\t\tdynamicSlippageConfigToUse.dynamicSlippageMax\n\t);\n\n\t// Round to avoid floating point precision issues, preserving 6 decimal places\n\treturn Math.round(finalSlippage * 1000000) / 1000000;\n};\n"]}
@@ -0,0 +1,14 @@
1
+ import { BN, L2OrderBook, PositionDirection } from '@drift-labs/sdk';
2
+ import { MarketId } from '../types/MarketId';
3
+ /**
4
+ * Calculates the price impact of an order, based on an L2
5
+ */
6
+ export declare const calculatePriceImpactFromL2: (marketId: MarketId, direction: PositionDirection, baseAmount: BN, l2Data: L2OrderBook, _oraclePrice?: BN) => {
7
+ entryPrice: BN;
8
+ priceImpact: BN;
9
+ baseAvailable: BN;
10
+ bestPrice: BN;
11
+ worstPrice: BN;
12
+ exceedsLiquidity: boolean;
13
+ showPriceEstimateOracleDivergenceWarning: boolean;
14
+ };
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculatePriceImpactFromL2 = void 0;
4
+ const sdk_1 = require("@drift-labs/sdk");
5
+ const UIMarket_1 = require("../types/UIMarket");
6
+ const _1 = require(".");
7
+ /**
8
+ * Calculates the price impact of an order, based on an L2
9
+ */
10
+ const calculatePriceImpactFromL2 = (marketId, direction, baseAmount, l2Data, _oraclePrice) => {
11
+ var _a, _b, _c;
12
+ let [entryPrice, priceImpact, baseFilled, bestPrice, worstPrice] = [
13
+ sdk_1.ZERO,
14
+ sdk_1.ZERO,
15
+ sdk_1.ZERO,
16
+ sdk_1.ZERO,
17
+ sdk_1.ZERO,
18
+ ];
19
+ let exceedsLiquidity = false;
20
+ try {
21
+ if (marketId.isPerp) {
22
+ const entryResult = (0, sdk_1.calculateEstimatedEntryPriceWithL2)('base', // leadSide
23
+ baseAmount, direction, sdk_1.BASE_PRECISION, l2Data);
24
+ entryPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.entryPrice) || sdk_1.ZERO;
25
+ priceImpact = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.priceImpact) || sdk_1.ZERO;
26
+ baseFilled = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.baseFilled) || sdk_1.ZERO;
27
+ bestPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.bestPrice) || sdk_1.ZERO;
28
+ worstPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.worstPrice) || sdk_1.ZERO;
29
+ }
30
+ else {
31
+ const precisionExp = ((_a = UIMarket_1.UIMarket.spotMarkets[marketId.marketIndex]) === null || _a === void 0 ? void 0 : _a.precisionExp) ||
32
+ sdk_1.BASE_PRECISION_EXP;
33
+ const entryResult = (0, sdk_1.calculateEstimatedEntryPriceWithL2)('base', // leadSide
34
+ baseAmount, direction, precisionExp, l2Data);
35
+ entryPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.entryPrice) || sdk_1.ZERO;
36
+ priceImpact = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.priceImpact) || sdk_1.ZERO;
37
+ baseFilled = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.baseFilled) || sdk_1.ZERO;
38
+ bestPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.bestPrice) || sdk_1.ZERO;
39
+ worstPrice = (entryResult === null || entryResult === void 0 ? void 0 : entryResult.worstPrice) || sdk_1.ZERO;
40
+ }
41
+ // Check if we exceeded available liquidity
42
+ if (baseFilled.lt(baseAmount)) {
43
+ exceedsLiquidity = true;
44
+ }
45
+ }
46
+ catch (e) {
47
+ // SDK function may throw error if no liquidity, use fallback values
48
+ console.warn('Error calculating price impact from L2:', e);
49
+ // Use best bid/ask as fallback
50
+ const bestBid = (_b = l2Data.bids) === null || _b === void 0 ? void 0 : _b[0];
51
+ const bestAsk = (_c = l2Data.asks) === null || _c === void 0 ? void 0 : _c[0];
52
+ if (bestBid && bestAsk) {
53
+ const isLong = _1.ENUM_UTILS.match(direction, sdk_1.PositionDirection.LONG);
54
+ entryPrice = isLong ? bestAsk.price : bestBid.price;
55
+ bestPrice = isLong ? bestAsk.price : bestBid.price;
56
+ worstPrice = isLong ? bestAsk.price : bestBid.price;
57
+ baseFilled = isLong ? bestAsk.size : bestBid.size;
58
+ }
59
+ }
60
+ return {
61
+ entryPrice,
62
+ priceImpact,
63
+ baseAvailable: baseFilled,
64
+ bestPrice,
65
+ worstPrice,
66
+ exceedsLiquidity,
67
+ showPriceEstimateOracleDivergenceWarning: false, // Will be calculated by the caller
68
+ };
69
+ };
70
+ exports.calculatePriceImpactFromL2 = calculatePriceImpactFromL2;
71
+ //# sourceMappingURL=priceImpact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priceImpact.js","sourceRoot":"","sources":["../../src/utils/priceImpact.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tBN,\n\tZERO,\n\tL2OrderBook,\n\tPositionDirection,\n\tBASE_PRECISION,\n\tcalculateEstimatedEntryPriceWithL2,\n\tBASE_PRECISION_EXP,\n} from '@drift-labs/sdk';\nimport { UIMarket } from '../types/UIMarket';\nimport { MarketId } from '../types/MarketId';\nimport { ENUM_UTILS } from '.';\n\n/**\n * Calculates the price impact of an order, based on an L2\n */\nexport const calculatePriceImpactFromL2 = (\n\tmarketId: MarketId,\n\tdirection: PositionDirection,\n\tbaseAmount: BN,\n\tl2Data: L2OrderBook,\n\t_oraclePrice?: BN\n): {\n\tentryPrice: BN;\n\tpriceImpact: BN;\n\tbaseAvailable: BN;\n\tbestPrice: BN;\n\tworstPrice: BN;\n\texceedsLiquidity: boolean;\n\tshowPriceEstimateOracleDivergenceWarning: boolean;\n} => {\n\tlet [entryPrice, priceImpact, baseFilled, bestPrice, worstPrice] = [\n\t\tZERO,\n\t\tZERO,\n\t\tZERO,\n\t\tZERO,\n\t\tZERO,\n\t];\n\tlet exceedsLiquidity = false;\n\n\ttry {\n\t\tif (marketId.isPerp) {\n\t\t\tconst entryResult = calculateEstimatedEntryPriceWithL2(\n\t\t\t\t'base', // leadSide\n\t\t\t\tbaseAmount,\n\t\t\t\tdirection,\n\t\t\t\tBASE_PRECISION,\n\t\t\t\tl2Data\n\t\t\t);\n\n\t\t\tentryPrice = entryResult?.entryPrice || ZERO;\n\t\t\tpriceImpact = entryResult?.priceImpact || ZERO;\n\t\t\tbaseFilled = entryResult?.baseFilled || ZERO;\n\t\t\tbestPrice = entryResult?.bestPrice || ZERO;\n\t\t\tworstPrice = entryResult?.worstPrice || ZERO;\n\t\t} else {\n\t\t\tconst precisionExp =\n\t\t\t\tUIMarket.spotMarkets[marketId.marketIndex]?.precisionExp ||\n\t\t\t\tBASE_PRECISION_EXP;\n\n\t\t\tconst entryResult = calculateEstimatedEntryPriceWithL2(\n\t\t\t\t'base', // leadSide\n\t\t\t\tbaseAmount,\n\t\t\t\tdirection,\n\t\t\t\tprecisionExp,\n\t\t\t\tl2Data\n\t\t\t);\n\n\t\t\tentryPrice = entryResult?.entryPrice || ZERO;\n\t\t\tpriceImpact = entryResult?.priceImpact || ZERO;\n\t\t\tbaseFilled = entryResult?.baseFilled || ZERO;\n\t\t\tbestPrice = entryResult?.bestPrice || ZERO;\n\t\t\tworstPrice = entryResult?.worstPrice || ZERO;\n\t\t}\n\n\t\t// Check if we exceeded available liquidity\n\t\tif (baseFilled.lt(baseAmount)) {\n\t\t\texceedsLiquidity = true;\n\t\t}\n\t} catch (e) {\n\t\t// SDK function may throw error if no liquidity, use fallback values\n\t\tconsole.warn('Error calculating price impact from L2:', e);\n\n\t\t// Use best bid/ask as fallback\n\t\tconst bestBid = l2Data.bids?.[0];\n\t\tconst bestAsk = l2Data.asks?.[0];\n\n\t\tif (bestBid && bestAsk) {\n\t\t\tconst isLong = ENUM_UTILS.match(direction, PositionDirection.LONG);\n\t\t\tentryPrice = isLong ? bestAsk.price : bestBid.price;\n\t\t\tbestPrice = isLong ? bestAsk.price : bestBid.price;\n\t\t\tworstPrice = isLong ? bestAsk.price : bestBid.price;\n\t\t\tbaseFilled = isLong ? bestAsk.size : bestBid.size;\n\t\t}\n\t}\n\n\treturn {\n\t\tentryPrice,\n\t\tpriceImpact,\n\t\tbaseAvailable: baseFilled,\n\t\tbestPrice,\n\t\tworstPrice,\n\t\texceedsLiquidity,\n\t\tshowPriceEstimateOracleDivergenceWarning: false, // Will be calculated by the caller\n\t};\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/common",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Common functions for Drift",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -1 +0,0 @@
1
- export declare const createBorrowIx: () => Promise<void>;
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createBorrowIx = void 0;
4
- const createBorrowIx = async () => {
5
- // TODO:
6
- };
7
- exports.createBorrowIx = createBorrowIx;
8
- //# sourceMappingURL=borrow.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"borrow.js","sourceRoot":"","sources":["../../../../../src/drift/base/actions/spot/borrow.ts"],"names":[],"mappings":";;;AAAO,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;IACxC,QAAQ;AACT,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB","sourcesContent":["export const createBorrowIx = async () => {\n\t// TODO:\n};\n"]}