@ostium/builder-sdk 0.2.0 → 0.3.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.
package/dist/index.d.cts CHANGED
@@ -191,7 +191,7 @@ interface CommonParams {
191
191
  slippageBps?: number;
192
192
  /**
193
193
  * Optional builder fee sharing.
194
- * `feeBps` is in basis points max 50 (0.5%).
194
+ * `feeBps` in basis points (e.g. 10 = 10 bps / 0.1%, 2.55 = 2.55 bps). Max 50 (0.5%), step 0.01 bps.
195
195
  */
196
196
  builder?: {
197
197
  address: Address;
@@ -624,11 +624,24 @@ interface GetPairsParams {
624
624
  interface GetUserParams {
625
625
  user: Address;
626
626
  }
627
- interface GetOpenPositionsParams extends GetUserParams {
627
+ interface GetOpenPositionsParams {
628
+ /**
629
+ * Trader address — pass `'ALL'` to fetch every trader's open positions
630
+ * (no trader filter applied to the subgraph query).
631
+ */
632
+ user: Address | AllTraders;
628
633
  /** Current Arbitrum block number — required for live PnL. Auto-fetched on `OstiumClient`. */
629
634
  blockNumber?: bigint;
635
+ /**
636
+ * Maximum number of positions to return. Defaults to `Infinity` (all positions).
637
+ */
638
+ limit?: number;
639
+ /**
640
+ * Number of positions to skip (for pagination). Defaults to `0`.
641
+ */
642
+ skip?: number;
630
643
  }
631
- /** Sentinel value for `getFills` / `getFillsByTime` to fetch every trader's fills. */
644
+ /** Sentinel value for `getOpenPositions`, `getFills`, and `getFillsByTime` to fetch across every trader. */
632
645
  type AllTraders = 'ALL';
633
646
  interface GetFillsParams {
634
647
  /**
@@ -1349,6 +1362,11 @@ declare class OstiumClient {
1349
1362
  /**
1350
1363
  * Open positions + margin summary for a user. Defaults to the connected
1351
1364
  * trader. Live prices and the current block number are fetched automatically.
1365
+ *
1366
+ * - `user`: pass an address to scope to a single trader, or `'ALL'` to fetch
1367
+ * positions across every trader (no trader filter).
1368
+ * - `limit`: cap the number of positions returned (default: all).
1369
+ * - `skip`: offset into the result set for pagination (default: `0`).
1352
1370
  */
1353
1371
  getOpenPositions(params?: Partial<GetOpenPositionsParams>): Promise<OpenPositionsResponse>;
1354
1372
  /**
package/dist/index.d.ts CHANGED
@@ -191,7 +191,7 @@ interface CommonParams {
191
191
  slippageBps?: number;
192
192
  /**
193
193
  * Optional builder fee sharing.
194
- * `feeBps` is in basis points max 50 (0.5%).
194
+ * `feeBps` in basis points (e.g. 10 = 10 bps / 0.1%, 2.55 = 2.55 bps). Max 50 (0.5%), step 0.01 bps.
195
195
  */
196
196
  builder?: {
197
197
  address: Address;
@@ -624,11 +624,24 @@ interface GetPairsParams {
624
624
  interface GetUserParams {
625
625
  user: Address;
626
626
  }
627
- interface GetOpenPositionsParams extends GetUserParams {
627
+ interface GetOpenPositionsParams {
628
+ /**
629
+ * Trader address — pass `'ALL'` to fetch every trader's open positions
630
+ * (no trader filter applied to the subgraph query).
631
+ */
632
+ user: Address | AllTraders;
628
633
  /** Current Arbitrum block number — required for live PnL. Auto-fetched on `OstiumClient`. */
629
634
  blockNumber?: bigint;
635
+ /**
636
+ * Maximum number of positions to return. Defaults to `Infinity` (all positions).
637
+ */
638
+ limit?: number;
639
+ /**
640
+ * Number of positions to skip (for pagination). Defaults to `0`.
641
+ */
642
+ skip?: number;
630
643
  }
631
- /** Sentinel value for `getFills` / `getFillsByTime` to fetch every trader's fills. */
644
+ /** Sentinel value for `getOpenPositions`, `getFills`, and `getFillsByTime` to fetch across every trader. */
632
645
  type AllTraders = 'ALL';
633
646
  interface GetFillsParams {
634
647
  /**
@@ -1349,6 +1362,11 @@ declare class OstiumClient {
1349
1362
  /**
1350
1363
  * Open positions + margin summary for a user. Defaults to the connected
1351
1364
  * trader. Live prices and the current block number are fetched automatically.
1365
+ *
1366
+ * - `user`: pass an address to scope to a single trader, or `'ALL'` to fetch
1367
+ * positions across every trader (no trader filter).
1368
+ * - `limit`: cap the number of positions returned (default: all).
1369
+ * - `skip`: offset into the result set for pagination (default: `0`).
1352
1370
  */
1353
1371
  getOpenPositions(params?: Partial<GetOpenPositionsParams>): Promise<OpenPositionsResponse>;
1354
1372
  /**
package/dist/index.js CHANGED
@@ -54,6 +54,32 @@ var ERC20_ABI = [
54
54
  }
55
55
  ];
56
56
 
57
+ // src/internal/builder-fee.ts
58
+ var MAX_BUILDER_FEE_BPS = 50;
59
+ var MIN_BUILDER_FEE_BPS_STEP = 0.01;
60
+ var MAX_BUILDER_FEE_CONTRACT = 5e5;
61
+ var BPS_TO_CONTRACT = 1e4;
62
+ function bpsToContractBuilderFee(feeBps) {
63
+ if (feeBps === 0) return 0n;
64
+ return BigInt(Math.round(feeBps * BPS_TO_CONTRACT));
65
+ }
66
+ function validateBuilderFeeBps(feeBps) {
67
+ if (!Number.isFinite(feeBps)) {
68
+ return "builder.feeBps must be a finite number";
69
+ }
70
+ if (feeBps < 0 || feeBps > MAX_BUILDER_FEE_BPS) {
71
+ return `builder.feeBps must be between 0 and ${MAX_BUILDER_FEE_BPS} (0%\u20130.5%)`;
72
+ }
73
+ const centiBps = Math.round(feeBps * 100);
74
+ if (Math.abs(feeBps * 100 - centiBps) > 1e-6) {
75
+ return `builder.feeBps must be a multiple of ${MIN_BUILDER_FEE_BPS_STEP} (0.01 bps)`;
76
+ }
77
+ if (bpsToContractBuilderFee(feeBps) > MAX_BUILDER_FEE_CONTRACT) {
78
+ return "builder.feeBps exceeds on-chain maximum (0.5%)";
79
+ }
80
+ return null;
81
+ }
82
+
57
83
  // src/internal/decimal.ts
58
84
  function parseUsdc(amount) {
59
85
  const amountStr = typeof amount === "number" ? amount.toString() : amount;
@@ -212,7 +238,7 @@ function buildBuilderFee(builder) {
212
238
  }
213
239
  return {
214
240
  builder: builder.b,
215
- builderFee: BigInt(builder.f)
241
+ builderFee: bpsToContractBuilderFee(builder.f)
216
242
  };
217
243
  }
218
244
 
@@ -2938,6 +2964,17 @@ query GetTraderOpenTrades($trader: String!, $skip: Int!, $first: Int!) {
2938
2964
  ${PAIR_FULL}
2939
2965
  }
2940
2966
  }`;
2967
+ var GetAllOpenTradesQuery = `
2968
+ query GetAllOpenTrades($skip: Int!, $first: Int!) {
2969
+ trades(
2970
+ where: { isOpen: true }
2971
+ skip: $skip first: $first
2972
+ orderBy: timestamp orderDirection: desc
2973
+ ) {
2974
+ ${TRADE_CORE}
2975
+ ${PAIR_FULL}
2976
+ }
2977
+ }`;
2941
2978
  var ORDER_FIELDS = `
2942
2979
  id tradeID limitID trader
2943
2980
  pair { id from to group { id name } }
@@ -3017,9 +3054,9 @@ query GetTraderActiveLimits($trader: String!, $skip: Int!, $first: Int!) {
3017
3054
  }`;
3018
3055
 
3019
3056
  // src/data/internal/pagination.ts
3020
- async function paginateAll(fetcher, batchSize = 1e3, max = Infinity) {
3057
+ async function paginateAll(fetcher, batchSize = 1e3, max = Infinity, initialSkip = 0) {
3021
3058
  const results = [];
3022
- let skip = 0;
3059
+ let skip = initialSkip;
3023
3060
  while (results.length < max) {
3024
3061
  const remaining = max - results.length;
3025
3062
  const fetchSize = Math.min(batchSize, remaining);
@@ -3948,15 +3985,28 @@ var OstiumSubgraphClient = class _OstiumSubgraphClient {
3948
3985
  * PnL fields are zeroed.
3949
3986
  */
3950
3987
  async getOpenPositions(params) {
3951
- const { user, blockNumber } = params;
3988
+ const { user, blockNumber, limit = Infinity, skip: initialSkip = 0 } = params;
3989
+ const isGlobal = user === "ALL";
3952
3990
  const [trades, prices] = await Promise.all([
3953
- paginateAll(async (skip, first) => {
3954
- const data = await this.query(
3955
- GetTraderOpenTradesQuery,
3956
- { trader: user.toLowerCase(), skip, first }
3957
- );
3958
- return data.trades;
3959
- }),
3991
+ paginateAll(
3992
+ async (skip, first) => {
3993
+ if (isGlobal) {
3994
+ const data2 = await this.query(
3995
+ GetAllOpenTradesQuery,
3996
+ { skip, first }
3997
+ );
3998
+ return data2.trades;
3999
+ }
4000
+ const data = await this.query(
4001
+ GetTraderOpenTradesQuery,
4002
+ { trader: user.toLowerCase(), skip, first }
4003
+ );
4004
+ return data.trades;
4005
+ },
4006
+ 1e3,
4007
+ limit,
4008
+ initialSkip
4009
+ ),
3960
4010
  this.fetchLivePricesSafe()
3961
4011
  ]);
3962
4012
  const pairPositions = trades.map((trade) => {
@@ -4324,11 +4374,11 @@ function validateConfig(config) {
4324
4374
  "INVALID_CONFIG" /* INVALID_CONFIG */
4325
4375
  );
4326
4376
  }
4327
- if (config.builder !== void 0 && (config.builder.feeBps < 0 || config.builder.feeBps > 50)) {
4328
- throw new OstiumError(
4329
- "builder.feeBps must be between 0 and 50 (max 0.5%)",
4330
- "INVALID_CONFIG" /* INVALID_CONFIG */
4331
- );
4377
+ if (config.builder !== void 0) {
4378
+ const feeError = validateBuilderFeeBps(config.builder.feeBps);
4379
+ if (feeError) {
4380
+ throw new OstiumError(feeError, "INVALID_CONFIG" /* INVALID_CONFIG */);
4381
+ }
4332
4382
  }
4333
4383
  let mode;
4334
4384
  try {
@@ -5124,11 +5174,18 @@ var OstiumClient = class _OstiumClient {
5124
5174
  /**
5125
5175
  * Open positions + margin summary for a user. Defaults to the connected
5126
5176
  * trader. Live prices and the current block number are fetched automatically.
5177
+ *
5178
+ * - `user`: pass an address to scope to a single trader, or `'ALL'` to fetch
5179
+ * positions across every trader (no trader filter).
5180
+ * - `limit`: cap the number of positions returned (default: all).
5181
+ * - `skip`: offset into the result set for pagination (default: `0`).
5127
5182
  */
5128
5183
  async getOpenPositions(params) {
5129
5184
  return this.subgraph.getOpenPositions({
5130
5185
  user: params?.user ?? this.getTraderAddress(),
5131
- blockNumber: params?.blockNumber ?? await this.publicClient.getBlockNumber()
5186
+ blockNumber: params?.blockNumber ?? await this.publicClient.getBlockNumber(),
5187
+ limit: params?.limit,
5188
+ skip: params?.skip
5132
5189
  });
5133
5190
  }
5134
5191
  /**