@mysten/deepbook-v3 1.3.6 → 1.4.1

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 (54) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/contracts/deepbook/account.d.mts +18 -18
  3. package/dist/contracts/deepbook/account.d.mts.map +1 -1
  4. package/dist/contracts/deepbook/balances.d.mts +4 -4
  5. package/dist/contracts/deepbook/deep_price.d.mts +3 -3
  6. package/dist/contracts/deepbook/deep_price.d.mts.map +1 -1
  7. package/dist/contracts/deepbook/order.d.mts +12 -12
  8. package/dist/transactions/deepbookAdmin.d.mts +29 -0
  9. package/dist/transactions/deepbookAdmin.d.mts.map +1 -1
  10. package/dist/transactions/deepbookAdmin.mjs +34 -2
  11. package/dist/transactions/deepbookAdmin.mjs.map +1 -1
  12. package/dist/transactions/marginAdmin.d.mts +38 -7
  13. package/dist/transactions/marginAdmin.d.mts.map +1 -1
  14. package/dist/transactions/marginAdmin.mjs +48 -0
  15. package/dist/transactions/marginAdmin.mjs.map +1 -1
  16. package/dist/transactions/marginLiquidations.d.mts +3 -3
  17. package/dist/transactions/marginMaintainer.d.mts +5 -5
  18. package/dist/transactions/marginMaintainer.mjs +4 -4
  19. package/dist/transactions/marginMaintainer.mjs.map +1 -1
  20. package/dist/transactions/marginManager.d.mts +116 -23
  21. package/dist/transactions/marginManager.d.mts.map +1 -1
  22. package/dist/transactions/marginManager.mjs +133 -1
  23. package/dist/transactions/marginManager.mjs.map +1 -1
  24. package/dist/transactions/marginPool.d.mts +18 -18
  25. package/dist/transactions/marginRegistry.d.mts +15 -15
  26. package/dist/transactions/marginRegistry.d.mts.map +1 -1
  27. package/dist/transactions/marginTPSL.d.mts +14 -11
  28. package/dist/transactions/marginTPSL.d.mts.map +1 -1
  29. package/dist/transactions/marginTPSL.mjs +5 -1
  30. package/dist/transactions/marginTPSL.mjs.map +1 -1
  31. package/dist/transactions/poolProxy.d.mts +19 -9
  32. package/dist/transactions/poolProxy.d.mts.map +1 -1
  33. package/dist/transactions/poolProxy.mjs +31 -21
  34. package/dist/transactions/poolProxy.mjs.map +1 -1
  35. package/dist/types/index.d.mts +1 -1
  36. package/dist/types/index.mjs.map +1 -1
  37. package/dist/utils/config.d.mts +1 -0
  38. package/dist/utils/config.d.mts.map +1 -1
  39. package/dist/utils/config.mjs +3 -0
  40. package/dist/utils/config.mjs.map +1 -1
  41. package/dist/utils/constants.d.mts +3 -0
  42. package/dist/utils/constants.d.mts.map +1 -1
  43. package/dist/utils/constants.mjs +5 -3
  44. package/dist/utils/constants.mjs.map +1 -1
  45. package/package.json +2 -2
  46. package/src/transactions/deepbookAdmin.ts +64 -2
  47. package/src/transactions/marginAdmin.ts +79 -0
  48. package/src/transactions/marginMaintainer.ts +4 -4
  49. package/src/transactions/marginManager.ts +244 -1
  50. package/src/transactions/marginTPSL.ts +10 -3
  51. package/src/transactions/poolProxy.ts +45 -21
  52. package/src/types/index.ts +1 -1
  53. package/src/utils/config.ts +4 -0
  54. package/src/utils/constants.ts +6 -3
@@ -155,6 +155,85 @@ export class MarginAdminContract {
155
155
  });
156
156
  };
157
157
 
158
+ /**
159
+ * @description Set the price deviation tolerance for a pool. `tolerance` is
160
+ * in 9-decimal float scaling (1.0 = `FLOAT_SCALAR`); the SDK applies the
161
+ * scaling, so callers pass a human-readable fraction (e.g. `0.1` for 10%).
162
+ * Requires the pool's current price to have been initialized via
163
+ * `PoolProxyContract.updateCurrentPrice` first.
164
+ * @param {string} poolKey The key of the pool to update
165
+ * @param {number | bigint} tolerance Tolerance as a fraction (e.g. 0.1 for 10%)
166
+ * @returns A function that takes a Transaction object
167
+ */
168
+ setPriceTolerance = (poolKey: string, tolerance: number | bigint) => (tx: Transaction) => {
169
+ const pool = this.#config.getPool(poolKey);
170
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
171
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
172
+ tx.moveCall({
173
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_registry::set_price_tolerance`,
174
+ arguments: [
175
+ tx.object(this.#config.MARGIN_REGISTRY_ID),
176
+ tx.object(this.#marginAdminCap()),
177
+ tx.object(pool.address),
178
+ tx.pure.u64(convertRate(tolerance, FLOAT_SCALAR)),
179
+ tx.object.clock(),
180
+ ],
181
+ typeArguments: [baseCoin.type, quoteCoin.type],
182
+ });
183
+ };
184
+
185
+ /**
186
+ * @description Set the maximum acceptable Pyth price age (in milliseconds)
187
+ * for a pool. Requires the pool's current price to have been initialized
188
+ * via `PoolProxyContract.updateCurrentPrice` first.
189
+ * @param {string} poolKey The key of the pool to update
190
+ * @param {number | bigint} maxAgeMs Max age in milliseconds (raw u64)
191
+ * @returns A function that takes a Transaction object
192
+ */
193
+ setMaxPriceAge = (poolKey: string, maxAgeMs: number | bigint) => (tx: Transaction) => {
194
+ const pool = this.#config.getPool(poolKey);
195
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
196
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
197
+ tx.moveCall({
198
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_registry::set_max_price_age`,
199
+ arguments: [
200
+ tx.object(this.#config.MARGIN_REGISTRY_ID),
201
+ tx.object(this.#marginAdminCap()),
202
+ tx.object(pool.address),
203
+ tx.pure.u64(maxAgeMs),
204
+ tx.object.clock(),
205
+ ],
206
+ typeArguments: [baseCoin.type, quoteCoin.type],
207
+ });
208
+ };
209
+
210
+ /**
211
+ * @description Set the maximum lifetime (in milliseconds) of margin limit
212
+ * orders for a pool. `pool_proxy::place_limit_order_v2` and
213
+ * `place_reduce_only_limit_order_v2` clamp the user-supplied
214
+ * `expire_timestamp` to at most `now + max_order_ttl_ms`, bounding margin
215
+ * orders' exposure to stale-price exploitation.
216
+ * @param {string} poolKey The key of the pool to update
217
+ * @param {number | bigint} maxOrderTtlMs Max order TTL in milliseconds (raw u64)
218
+ * @returns A function that takes a Transaction object
219
+ */
220
+ setMaxOrderTtl = (poolKey: string, maxOrderTtlMs: number | bigint) => (tx: Transaction) => {
221
+ const pool = this.#config.getPool(poolKey);
222
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
223
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
224
+ tx.moveCall({
225
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_registry::set_max_order_ttl`,
226
+ arguments: [
227
+ tx.object(this.#config.MARGIN_REGISTRY_ID),
228
+ tx.object(this.#marginAdminCap()),
229
+ tx.object(pool.address),
230
+ tx.pure.u64(maxOrderTtlMs),
231
+ tx.object.clock(),
232
+ ],
233
+ typeArguments: [baseCoin.type, quoteCoin.type],
234
+ });
235
+ };
236
+
158
237
  /**
159
238
  * @description Add the PythConfig to the margin registry
160
239
  * @param {Transaction} tx The transaction object
@@ -99,13 +99,13 @@ export class MarginMaintainerContract {
99
99
  newMarginPoolConfig =
100
100
  (coinKey: string, marginPoolConfig: MarginPoolConfigParams) => (tx: Transaction) => {
101
101
  const coin = this.#config.getCoin(coinKey);
102
- const { supplyCap, maxUtilizationRate, referralSpread, minBorrow } = marginPoolConfig;
102
+ const { supplyCap, maxUtilizationRate, protocolSpread, minBorrow } = marginPoolConfig;
103
103
  return tx.moveCall({
104
104
  target: `${this.#config.MARGIN_PACKAGE_ID}::protocol_config::new_margin_pool_config`,
105
105
  arguments: [
106
106
  tx.pure.u64(convertQuantity(supplyCap, coin.scalar)),
107
107
  tx.pure.u64(convertRate(maxUtilizationRate, FLOAT_SCALAR)),
108
- tx.pure.u64(convertRate(referralSpread, FLOAT_SCALAR)),
108
+ tx.pure.u64(convertRate(protocolSpread, FLOAT_SCALAR)),
109
109
  tx.pure.u64(convertQuantity(minBorrow, coin.scalar)),
110
110
  ],
111
111
  });
@@ -133,7 +133,7 @@ export class MarginMaintainerContract {
133
133
  const {
134
134
  supplyCap,
135
135
  maxUtilizationRate,
136
- referralSpread,
136
+ protocolSpread,
137
137
  minBorrow,
138
138
  rateLimitCapacity,
139
139
  rateLimitRefillRatePerMs,
@@ -144,7 +144,7 @@ export class MarginMaintainerContract {
144
144
  arguments: [
145
145
  tx.pure.u64(convertQuantity(supplyCap, coin.scalar)),
146
146
  tx.pure.u64(convertRate(maxUtilizationRate, FLOAT_SCALAR)),
147
- tx.pure.u64(convertRate(referralSpread, FLOAT_SCALAR)),
147
+ tx.pure.u64(convertRate(protocolSpread, FLOAT_SCALAR)),
148
148
  tx.pure.u64(convertQuantity(minBorrow, coin.scalar)),
149
149
  tx.pure.u64(convertQuantity(rateLimitCapacity, coin.scalar)),
150
150
  tx.pure.u64(convertQuantity(rateLimitRefillRatePerMs, coin.scalar)),
@@ -5,7 +5,8 @@ import { coinWithBalance } from '@mysten/sui/transactions';
5
5
 
6
6
  import type { DeepBookConfig } from '../utils/config.js';
7
7
  import type { DepositParams, DepositDuringInitParams } from '../types/index.js';
8
- import { convertQuantity } from '../utils/conversion.js';
8
+ import { FLOAT_SCALAR } from '../utils/config.js';
9
+ import { convertPrice, convertQuantity } from '../utils/conversion.js';
9
10
 
10
11
  /**
11
12
  * MarginManagerContract class for managing MarginManager operations.
@@ -83,6 +84,43 @@ export class MarginManagerContract {
83
84
  });
84
85
  };
85
86
 
87
+ /**
88
+ * @description Register a margin manager back to the margin registry. Lets
89
+ * owners restore visibility of a manager that was unregistered by another
90
+ * platform.
91
+ * @param {string} managerKey The key to identify the margin manager
92
+ * @returns A function that takes a Transaction object
93
+ */
94
+ registerMarginManager = (managerKey: string) => (tx: Transaction) => {
95
+ const manager = this.#config.getMarginManager(managerKey);
96
+ const pool = this.#config.getPool(manager.poolKey);
97
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
98
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
99
+ tx.moveCall({
100
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::register_margin_manager`,
101
+ arguments: [tx.object(manager.address), tx.object(this.#config.MARGIN_REGISTRY_ID)],
102
+ typeArguments: [baseCoin.type, quoteCoin.type],
103
+ });
104
+ };
105
+
106
+ /**
107
+ * @description Unregister a margin manager from the margin registry. Aborts
108
+ * if the manager holds any outstanding debt or base/quote/DEEP balance.
109
+ * @param {string} managerKey The key to identify the margin manager
110
+ * @returns A function that takes a Transaction object
111
+ */
112
+ unregisterMarginManager = (managerKey: string) => (tx: Transaction) => {
113
+ const manager = this.#config.getMarginManager(managerKey);
114
+ const pool = this.#config.getPool(manager.poolKey);
115
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
116
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
117
+ tx.moveCall({
118
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::unregister_margin_manager`,
119
+ arguments: [tx.object(manager.address), tx.object(this.#config.MARGIN_REGISTRY_ID)],
120
+ typeArguments: [baseCoin.type, quoteCoin.type],
121
+ });
122
+ };
123
+
86
124
  /**
87
125
  * @description Deposit into a margin manager during initialization (before sharing).
88
126
  * Use this when you need to deposit funds into a newly created manager in the same transaction.
@@ -754,4 +792,209 @@ export class MarginManagerContract {
754
792
  typeArguments: [baseCoin.type, quoteCoin.type],
755
793
  });
756
794
  };
795
+
796
+ /**
797
+ * @description Get the underlying BalanceManager ID for a margin manager.
798
+ * Returns an ID (not a `&BalanceManager`), so it composes in PTBs unlike
799
+ * `balanceManager`.
800
+ * @param {string} poolKey The key to identify the pool
801
+ * @param {string} marginManagerId The ID of the margin manager
802
+ * @returns A function that takes a Transaction object
803
+ */
804
+ balanceManagerId = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
805
+ const pool = this.#config.getPool(poolKey);
806
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
807
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
808
+ return tx.moveCall({
809
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::balance_manager_id`,
810
+ arguments: [tx.object(marginManagerId)],
811
+ typeArguments: [baseCoin.type, quoteCoin.type],
812
+ });
813
+ };
814
+
815
+ /**
816
+ * @description Get the BalanceManager referral ID for a pool (Option<ID>).
817
+ * @param {string} poolKey The key to identify the pool
818
+ * @param {string} marginManagerId The ID of the margin manager
819
+ * @returns A function that takes a Transaction object
820
+ */
821
+ getBalanceManagerReferralId = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
822
+ const pool = this.#config.getPool(poolKey);
823
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
824
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
825
+ return tx.moveCall({
826
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::get_balance_manager_referral_id`,
827
+ arguments: [tx.object(marginManagerId), tx.pure.id(pool.address)],
828
+ typeArguments: [baseCoin.type, quoteCoin.type],
829
+ });
830
+ };
831
+
832
+ /**
833
+ * @description Check if the margin manager's account exists in the pool.
834
+ * @param {string} poolKey The key to identify the pool
835
+ * @param {string} marginManagerId The ID of the margin manager
836
+ * @returns A function that takes a Transaction object
837
+ */
838
+ accountExists = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
839
+ const pool = this.#config.getPool(poolKey);
840
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
841
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
842
+ return tx.moveCall({
843
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::account_exists`,
844
+ arguments: [tx.object(marginManagerId), tx.object(pool.address)],
845
+ typeArguments: [baseCoin.type, quoteCoin.type],
846
+ });
847
+ };
848
+
849
+ /**
850
+ * @description Get the pool account data for the margin manager.
851
+ * @param {string} poolKey The key to identify the pool
852
+ * @param {string} marginManagerId The ID of the margin manager
853
+ * @returns A function that takes a Transaction object
854
+ */
855
+ account = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
856
+ const pool = this.#config.getPool(poolKey);
857
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
858
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
859
+ return tx.moveCall({
860
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::account`,
861
+ arguments: [tx.object(marginManagerId), tx.object(pool.address)],
862
+ typeArguments: [baseCoin.type, quoteCoin.type],
863
+ });
864
+ };
865
+
866
+ /**
867
+ * @description Get the open order IDs for the margin manager's account in
868
+ * the pool.
869
+ * @param {string} poolKey The key to identify the pool
870
+ * @param {string} marginManagerId The ID of the margin manager
871
+ * @returns A function that takes a Transaction object
872
+ */
873
+ accountOpenOrders = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
874
+ const pool = this.#config.getPool(poolKey);
875
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
876
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
877
+ return tx.moveCall({
878
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::account_open_orders`,
879
+ arguments: [tx.object(marginManagerId), tx.object(pool.address)],
880
+ typeArguments: [baseCoin.type, quoteCoin.type],
881
+ });
882
+ };
883
+
884
+ /**
885
+ * @description Get full order details for the margin manager's account in
886
+ * the pool.
887
+ * @param {string} poolKey The key to identify the pool
888
+ * @param {string} marginManagerId The ID of the margin manager
889
+ * @returns A function that takes a Transaction object
890
+ */
891
+ getAccountOrderDetails = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
892
+ const pool = this.#config.getPool(poolKey);
893
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
894
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
895
+ return tx.moveCall({
896
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::get_account_order_details`,
897
+ arguments: [tx.object(marginManagerId), tx.object(pool.address)],
898
+ typeArguments: [baseCoin.type, quoteCoin.type],
899
+ });
900
+ };
901
+
902
+ /**
903
+ * @description Get locked balances (base, quote, deep) for the margin
904
+ * manager's account in the pool.
905
+ * @param {string} poolKey The key to identify the pool
906
+ * @param {string} marginManagerId The ID of the margin manager
907
+ * @returns A function that takes a Transaction object
908
+ */
909
+ lockedBalance = (poolKey: string, marginManagerId: string) => (tx: Transaction) => {
910
+ const pool = this.#config.getPool(poolKey);
911
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
912
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
913
+ return tx.moveCall({
914
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::locked_balance`,
915
+ arguments: [tx.object(marginManagerId), tx.object(pool.address)],
916
+ typeArguments: [baseCoin.type, quoteCoin.type],
917
+ });
918
+ };
919
+
920
+ /**
921
+ * @description Check whether a limit order can be placed given the
922
+ * manager's current state.
923
+ * @param {string} poolKey The key to identify the pool
924
+ * @param {string} marginManagerId The ID of the margin manager
925
+ * @param {number | bigint} price Limit price
926
+ * @param {number | bigint} quantity Order quantity (base units)
927
+ * @param {boolean} isBid True for bid, false for ask
928
+ * @param {boolean} payWithDeep Whether to pay fees in DEEP
929
+ * @param {number | bigint} expireTimestamp Order expiration timestamp (ms)
930
+ * @returns A function that takes a Transaction object
931
+ */
932
+ canPlaceLimitOrder =
933
+ (
934
+ poolKey: string,
935
+ marginManagerId: string,
936
+ price: number | bigint,
937
+ quantity: number | bigint,
938
+ isBid: boolean,
939
+ payWithDeep: boolean,
940
+ expireTimestamp: number | bigint,
941
+ ) =>
942
+ (tx: Transaction) => {
943
+ const pool = this.#config.getPool(poolKey);
944
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
945
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
946
+ const inputPrice = convertPrice(price, FLOAT_SCALAR, quoteCoin.scalar, baseCoin.scalar);
947
+ const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
948
+ return tx.moveCall({
949
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::can_place_limit_order`,
950
+ arguments: [
951
+ tx.object(marginManagerId),
952
+ tx.object(pool.address),
953
+ tx.pure.u64(inputPrice),
954
+ tx.pure.u64(inputQuantity),
955
+ tx.pure.bool(isBid),
956
+ tx.pure.bool(payWithDeep),
957
+ tx.pure.u64(expireTimestamp),
958
+ tx.object.clock(),
959
+ ],
960
+ typeArguments: [baseCoin.type, quoteCoin.type],
961
+ });
962
+ };
963
+
964
+ /**
965
+ * @description Check whether a market order can be placed given the
966
+ * manager's current state.
967
+ * @param {string} poolKey The key to identify the pool
968
+ * @param {string} marginManagerId The ID of the margin manager
969
+ * @param {number | bigint} quantity Order quantity (base units)
970
+ * @param {boolean} isBid True for bid, false for ask
971
+ * @param {boolean} payWithDeep Whether to pay fees in DEEP
972
+ * @returns A function that takes a Transaction object
973
+ */
974
+ canPlaceMarketOrder =
975
+ (
976
+ poolKey: string,
977
+ marginManagerId: string,
978
+ quantity: number | bigint,
979
+ isBid: boolean,
980
+ payWithDeep: boolean,
981
+ ) =>
982
+ (tx: Transaction) => {
983
+ const pool = this.#config.getPool(poolKey);
984
+ const baseCoin = this.#config.getCoin(pool.baseCoin);
985
+ const quoteCoin = this.#config.getCoin(pool.quoteCoin);
986
+ const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
987
+ return tx.moveCall({
988
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::can_place_market_order`,
989
+ arguments: [
990
+ tx.object(marginManagerId),
991
+ tx.object(pool.address),
992
+ tx.pure.u64(inputQuantity),
993
+ tx.pure.bool(isBid),
994
+ tx.pure.bool(payWithDeep),
995
+ tx.object.clock(),
996
+ ],
997
+ typeArguments: [baseCoin.type, quoteCoin.type],
998
+ });
999
+ };
757
1000
  }
@@ -198,8 +198,11 @@ export class MarginTPSLContract {
198
198
  };
199
199
 
200
200
  /**
201
- * @description Execute conditional orders that have been triggered
202
- * This is a permissionless function that can be called by anyone
201
+ * @description Execute conditional orders that have been triggered.
202
+ * Permissionless anyone can call this. After the inner fill loop, the
203
+ * manager's post-trade `risk_ratio` is checked against
204
+ * `min_borrow_risk_ratio`; if any triggered fill breaches that floor, the
205
+ * whole txn aborts (no partial-state landing).
203
206
  * @param {string} managerAddress The address of the margin manager
204
207
  * @param {string} poolKey The key to identify the pool (e.g., 'SUI_USDC')
205
208
  * @param {number} maxOrdersToExecute Maximum number of orders to execute in this call
@@ -210,11 +213,15 @@ export class MarginTPSLContract {
210
213
  const pool = this.#config.getPool(poolKey);
211
214
  const baseCoin = this.#config.getCoin(pool.baseCoin);
212
215
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
216
+ const baseMarginPool = this.#config.getMarginPool(pool.baseCoin);
217
+ const quoteMarginPool = this.#config.getMarginPool(pool.quoteCoin);
213
218
  return tx.moveCall({
214
- target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::execute_conditional_orders`,
219
+ target: `${this.#config.MARGIN_PACKAGE_ID}::margin_manager::execute_conditional_orders_v2`,
215
220
  arguments: [
216
221
  tx.object(managerAddress),
217
222
  tx.object(pool.address),
223
+ tx.object(baseMarginPool.address),
224
+ tx.object(quoteMarginPool.address),
218
225
  tx.object(baseCoin.priceInfoObjectId!),
219
226
  tx.object(quoteCoin.priceInfoObjectId!),
220
227
  tx.object(this.#config.MARGIN_REGISTRY_ID),
@@ -26,7 +26,9 @@ export class PoolProxyContract {
26
26
  }
27
27
 
28
28
  /**
29
- * @description Place a limit order
29
+ * @description Place a limit order. Enforces a post-trade `risk_ratio >=
30
+ * min_borrow_risk_ratio` invariant on the manager (skipped when the manager
31
+ * has no debt).
30
32
  * @param {PlaceMarginLimitOrderParams} params Parameters for placing a limit order
31
33
  * @returns A function that takes a Transaction object
32
34
  */
@@ -47,14 +49,20 @@ export class PoolProxyContract {
47
49
  const manager = this.#config.getMarginManager(marginManagerKey);
48
50
  const baseCoin = this.#config.getCoin(pool.baseCoin);
49
51
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
52
+ const baseMarginPool = this.#config.getMarginPool(pool.baseCoin);
53
+ const quoteMarginPool = this.#config.getMarginPool(pool.quoteCoin);
50
54
  const inputPrice = convertPrice(price, FLOAT_SCALAR, quoteCoin.scalar, baseCoin.scalar);
51
55
  const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
52
56
  return tx.moveCall({
53
- target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_limit_order`,
57
+ target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_limit_order_v2`,
54
58
  arguments: [
55
59
  tx.object(this.#config.MARGIN_REGISTRY_ID),
56
60
  tx.object(manager.address),
57
61
  tx.object(pool.address),
62
+ tx.object(baseMarginPool.address),
63
+ tx.object(quoteMarginPool.address),
64
+ tx.object(baseCoin.priceInfoObjectId!),
65
+ tx.object(quoteCoin.priceInfoObjectId!),
58
66
  tx.pure.u64(clientOrderId),
59
67
  tx.pure.u8(orderType),
60
68
  tx.pure.u8(selfMatchingOption),
@@ -70,7 +78,9 @@ export class PoolProxyContract {
70
78
  };
71
79
 
72
80
  /**
73
- * @description Place a market order
81
+ * @description Place a market order. Enforces a post-trade `risk_ratio >=
82
+ * min_borrow_risk_ratio` invariant on the manager (skipped when the manager
83
+ * has no debt).
74
84
  * @param {PlaceMarginMarketOrderParams} params Parameters for placing a market order
75
85
  * @returns A function that takes a Transaction object
76
86
  */
@@ -88,13 +98,19 @@ export class PoolProxyContract {
88
98
  const manager = this.#config.getMarginManager(marginManagerKey);
89
99
  const baseCoin = this.#config.getCoin(pool.baseCoin);
90
100
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
101
+ const baseMarginPool = this.#config.getMarginPool(pool.baseCoin);
102
+ const quoteMarginPool = this.#config.getMarginPool(pool.quoteCoin);
91
103
  const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
92
104
  return tx.moveCall({
93
- target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_market_order`,
105
+ target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_market_order_v2`,
94
106
  arguments: [
95
107
  tx.object(this.#config.MARGIN_REGISTRY_ID),
96
108
  tx.object(manager.address),
97
109
  tx.object(pool.address),
110
+ tx.object(baseMarginPool.address),
111
+ tx.object(quoteMarginPool.address),
112
+ tx.object(baseCoin.priceInfoObjectId!),
113
+ tx.object(quoteCoin.priceInfoObjectId!),
98
114
  tx.pure.u64(clientOrderId),
99
115
  tx.pure.u8(selfMatchingOption),
100
116
  tx.pure.u64(inputQuantity),
@@ -107,7 +123,10 @@ export class PoolProxyContract {
107
123
  };
108
124
 
109
125
  /**
110
- * @description Place a reduce only limit order
126
+ * @description Place a reduce only limit order. Requires the manager to have
127
+ * debt on the relevant side; enforces a monotonic `risk_ratio_after >=
128
+ * risk_ratio_before` invariant so the fill cannot leak value to the
129
+ * counterparty.
111
130
  * @param {PlaceMarginLimitOrderParams} params Parameters for placing a reduce only limit order
112
131
  * @returns A function that takes a Transaction object
113
132
  */
@@ -128,19 +147,20 @@ export class PoolProxyContract {
128
147
  const manager = this.#config.getMarginManager(marginManagerKey);
129
148
  const baseCoin = this.#config.getCoin(pool.baseCoin);
130
149
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
150
+ const baseMarginPool = this.#config.getMarginPool(pool.baseCoin);
151
+ const quoteMarginPool = this.#config.getMarginPool(pool.quoteCoin);
131
152
  const inputPrice = convertPrice(price, FLOAT_SCALAR, quoteCoin.scalar, baseCoin.scalar);
132
153
  const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
133
- const marginPool = isBid
134
- ? this.#config.getMarginPool(pool.baseCoin)
135
- : this.#config.getMarginPool(pool.quoteCoin);
136
- const debtType = isBid ? baseCoin.type : quoteCoin.type;
137
154
  return tx.moveCall({
138
- target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_reduce_only_limit_order`,
155
+ target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_reduce_only_limit_order_v2`,
139
156
  arguments: [
140
157
  tx.object(this.#config.MARGIN_REGISTRY_ID),
141
158
  tx.object(manager.address),
142
159
  tx.object(pool.address),
143
- tx.object(marginPool.address),
160
+ tx.object(baseMarginPool.address),
161
+ tx.object(quoteMarginPool.address),
162
+ tx.object(baseCoin.priceInfoObjectId!),
163
+ tx.object(quoteCoin.priceInfoObjectId!),
144
164
  tx.pure.u64(clientOrderId),
145
165
  tx.pure.u8(orderType),
146
166
  tx.pure.u8(selfMatchingOption),
@@ -151,12 +171,15 @@ export class PoolProxyContract {
151
171
  tx.pure.u64(expiration),
152
172
  tx.object.clock(),
153
173
  ],
154
- typeArguments: [baseCoin.type, quoteCoin.type, debtType],
174
+ typeArguments: [baseCoin.type, quoteCoin.type],
155
175
  });
156
176
  };
157
177
 
158
178
  /**
159
- * @description Place a reduce only market order
179
+ * @description Place a reduce only market order. Requires the manager to
180
+ * have debt on the relevant side; enforces a monotonic `risk_ratio_after >=
181
+ * risk_ratio_before` invariant so the fill cannot leak value to the
182
+ * counterparty.
160
183
  * @param {PlaceMarginMarketOrderParams} params Parameters for placing a reduce only market order
161
184
  * @returns A function that takes a Transaction object
162
185
  */
@@ -174,18 +197,19 @@ export class PoolProxyContract {
174
197
  const manager = this.#config.getMarginManager(marginManagerKey);
175
198
  const baseCoin = this.#config.getCoin(pool.baseCoin);
176
199
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
200
+ const baseMarginPool = this.#config.getMarginPool(pool.baseCoin);
201
+ const quoteMarginPool = this.#config.getMarginPool(pool.quoteCoin);
177
202
  const inputQuantity = convertQuantity(quantity, baseCoin.scalar);
178
- const marginPool = isBid
179
- ? this.#config.getMarginPool(pool.baseCoin)
180
- : this.#config.getMarginPool(pool.quoteCoin);
181
- const debtType = isBid ? baseCoin.type : quoteCoin.type;
182
203
  return tx.moveCall({
183
- target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_reduce_only_market_order`,
204
+ target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::place_reduce_only_market_order_v2`,
184
205
  arguments: [
185
206
  tx.object(this.#config.MARGIN_REGISTRY_ID),
186
207
  tx.object(manager.address),
187
208
  tx.object(pool.address),
188
- tx.object(marginPool.address),
209
+ tx.object(baseMarginPool.address),
210
+ tx.object(quoteMarginPool.address),
211
+ tx.object(baseCoin.priceInfoObjectId!),
212
+ tx.object(quoteCoin.priceInfoObjectId!),
189
213
  tx.pure.u64(clientOrderId),
190
214
  tx.pure.u8(selfMatchingOption),
191
215
  tx.pure.u64(inputQuantity),
@@ -193,7 +217,7 @@ export class PoolProxyContract {
193
217
  tx.pure.bool(payWithDeep),
194
218
  tx.object.clock(),
195
219
  ],
196
- typeArguments: [baseCoin.type, quoteCoin.type, debtType],
220
+ typeArguments: [baseCoin.type, quoteCoin.type],
197
221
  });
198
222
  };
199
223
 
@@ -427,7 +451,7 @@ export class PoolProxyContract {
427
451
  const baseCoin = this.#config.getCoin(pool.baseCoin);
428
452
  const quoteCoin = this.#config.getCoin(pool.quoteCoin);
429
453
  tx.moveCall({
430
- target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::claim_rebate`,
454
+ target: `${this.#config.MARGIN_PACKAGE_ID}::pool_proxy::claim_rebates`,
431
455
  arguments: [
432
456
  tx.object(this.#config.MARGIN_REGISTRY_ID),
433
457
  tx.object(marginManager.address),
@@ -232,7 +232,7 @@ export interface PoolConfigParams {
232
232
  export interface MarginPoolConfigParams {
233
233
  supplyCap: number | bigint;
234
234
  maxUtilizationRate: number | bigint;
235
- referralSpread: number | bigint;
235
+ protocolSpread: number | bigint;
236
236
  minBorrow: number | bigint;
237
237
  rateLimitCapacity?: number | bigint;
238
238
  rateLimitRefillRatePerMs?: number | bigint;
@@ -49,6 +49,7 @@ export class DeepBookConfig {
49
49
  REGISTRY_ID: string;
50
50
  DEEP_TREASURY_ID: string;
51
51
  MARGIN_PACKAGE_ID: string;
52
+ MARGIN_V1: string;
52
53
  MARGIN_REGISTRY_ID: string;
53
54
  LIQUIDATION_PACKAGE_ID: string;
54
55
  adminCap?: string;
@@ -97,6 +98,7 @@ export class DeepBookConfig {
97
98
  this.REGISTRY_ID = packageIds.REGISTRY_ID || '';
98
99
  this.DEEP_TREASURY_ID = packageIds.DEEP_TREASURY_ID || '';
99
100
  this.MARGIN_PACKAGE_ID = packageIds.MARGIN_PACKAGE_ID || '';
101
+ this.MARGIN_V1 = packageIds.MARGIN_V1 || '';
100
102
  this.MARGIN_REGISTRY_ID = packageIds.MARGIN_REGISTRY_ID || '';
101
103
  this.LIQUIDATION_PACKAGE_ID = packageIds.LIQUIDATION_PACKAGE_ID || '';
102
104
  this.#coins = coins || {};
@@ -111,6 +113,7 @@ export class DeepBookConfig {
111
113
  this.REGISTRY_ID = mainnetPackageIds.REGISTRY_ID;
112
114
  this.DEEP_TREASURY_ID = mainnetPackageIds.DEEP_TREASURY_ID;
113
115
  this.MARGIN_PACKAGE_ID = mainnetPackageIds.MARGIN_PACKAGE_ID;
116
+ this.MARGIN_V1 = mainnetPackageIds.MARGIN_V1;
114
117
  this.MARGIN_REGISTRY_ID = mainnetPackageIds.MARGIN_REGISTRY_ID;
115
118
  this.LIQUIDATION_PACKAGE_ID = mainnetPackageIds.LIQUIDATION_PACKAGE_ID;
116
119
  this.pyth = mainnetPythConfigs;
@@ -122,6 +125,7 @@ export class DeepBookConfig {
122
125
  this.REGISTRY_ID = testnetPackageIds.REGISTRY_ID;
123
126
  this.DEEP_TREASURY_ID = testnetPackageIds.DEEP_TREASURY_ID;
124
127
  this.MARGIN_PACKAGE_ID = testnetPackageIds.MARGIN_PACKAGE_ID;
128
+ this.MARGIN_V1 = testnetPackageIds.MARGIN_V1;
125
129
  this.MARGIN_REGISTRY_ID = testnetPackageIds.MARGIN_REGISTRY_ID;
126
130
  this.LIQUIDATION_PACKAGE_ID = testnetPackageIds.LIQUIDATION_PACKAGE_ID;
127
131
  this.pyth = testnetPythConfigs;
@@ -11,6 +11,7 @@ export interface DeepbookPackageIds {
11
11
  REGISTRY_ID?: string;
12
12
  DEEP_TREASURY_ID?: string;
13
13
  MARGIN_PACKAGE_ID?: string;
14
+ MARGIN_V1?: string;
14
15
  MARGIN_REGISTRY_ID?: string;
15
16
  LIQUIDATION_PACKAGE_ID?: string;
16
17
  }
@@ -20,17 +21,19 @@ export const testnetPackageIds = {
20
21
  REGISTRY_ID: '0x7c256edbda983a2cd6f946655f4bf3f00a41043993781f8674a7046e8c0e11d1',
21
22
  DEEP_TREASURY_ID: '0x69fffdae0075f8f71f4fa793549c11079266910e8905169845af1f5d00e09dcb',
22
23
  MARGIN_PACKAGE_ID: '0xd6a42f4df4db73d68cbeb52be66698d2fe6a9464f45ad113ca52b0c6ebd918b6',
24
+ MARGIN_V1: '0xd6a42f4df4db73d68cbeb52be66698d2fe6a9464f45ad113ca52b0c6ebd918b6',
23
25
  MARGIN_REGISTRY_ID: '0x48d7640dfae2c6e9ceeada197a7a1643984b5a24c55a0c6c023dac77e0339f75',
24
26
  LIQUIDATION_PACKAGE_ID: '0x8d69c3ef3ef580e5bf87b933ce28de19a5d0323588d1a44b9c60b4001741aa24',
25
27
  } satisfies DeepbookPackageIds;
26
28
 
27
29
  export const mainnetPackageIds = {
28
- DEEPBOOK_PACKAGE_ID: '0xf48222c4e057fa468baf136bff8e12504209d43850c5778f76159292a96f621e',
30
+ DEEPBOOK_PACKAGE_ID: '0x0e735f8c93a95722efd73521aca7a7652c0bb71ed1daf41b26dfd7d1ff71f748',
29
31
  REGISTRY_ID: '0xaf16199a2dff736e9f07a845f23c5da6df6f756eddb631aed9d24a93efc4549d',
30
32
  DEEP_TREASURY_ID: '0x032abf8948dda67a271bcc18e776dbbcfb0d58c8d288a700ff0d5521e57a1ffe',
31
- MARGIN_PACKAGE_ID: '0xfbd322126f1452fd4c89aedbaeb9fd0c44df9b5cedbe70d76bf80dc086031377',
33
+ MARGIN_PACKAGE_ID: '0x124bb3d8105d6d301c0d40feaa54d65df6b301e4d8ddd5eb8475b0f8a18cff2e',
34
+ MARGIN_V1: '0x97d9473771b01f77b0940c589484184b49f6444627ec121314fae6a6d36fb86b',
32
35
  MARGIN_REGISTRY_ID: '0x0e40998b359a9ccbab22a98ed21bd4346abf19158bc7980c8291908086b3a742',
33
- LIQUIDATION_PACKAGE_ID: '0x55718c06706bee34c9f3c39f662f10be354a4dcc719699ad72091dc343b641b8',
36
+ LIQUIDATION_PACKAGE_ID: '0xf17bff1bf21e9587acc5708714e520aa967f82f256f626938a33c4109b08adb9',
34
37
  } satisfies DeepbookPackageIds;
35
38
 
36
39
  export const testnetCoins: CoinMap = {