@p2pdotme/sdk 1.2.18 → 1.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.d.cts CHANGED
@@ -282,7 +282,7 @@ interface StakeClient {
282
282
  readonly claimUnstake: ClaimUnstakeAction;
283
283
  }
284
284
 
285
- type OrdersErrorCode = "VALIDATION_ERROR" | "INVALID_ORDER_ID" | "INVALID_GET_ORDERS_PARAMS" | "INVALID_FEE_CONFIG_PARAMS" | "ORDER_NOT_FOUND" | "CONTRACT_READ_FAILED" | "SUBGRAPH_REQUEST_FAILED" | "SUBGRAPH_VALIDATION_FAILED" | "MALFORMED_ORDER" | "CIRCLE_SELECTION_FAILED" | "ENCRYPTION_FAILED" | "RELAY_IDENTITY_CORRUPT" | "RELAY_IDENTITY_STORE_FAILED" | "TX_SUBMISSION_FAILED" | "RECEIPT_TIMEOUT" | "TX_REVERTED" | "EVENT_WATCH_FAILED";
285
+ type OrdersErrorCode = "VALIDATION_ERROR" | "INVALID_ORDER_ID" | "INVALID_GET_ORDERS_PARAMS" | "INVALID_FEE_CONFIG_PARAMS" | "INVALID_PLACEMENT_LIMITS_PARAMS" | "ORDER_NOT_FOUND" | "CONTRACT_READ_FAILED" | "SUBGRAPH_REQUEST_FAILED" | "SUBGRAPH_VALIDATION_FAILED" | "MALFORMED_ORDER" | "CIRCLE_SELECTION_FAILED" | "ENCRYPTION_FAILED" | "RELAY_IDENTITY_CORRUPT" | "RELAY_IDENTITY_STORE_FAILED" | "TX_SUBMISSION_FAILED" | "RECEIPT_TIMEOUT" | "TX_REVERTED" | "EVENT_WATCH_FAILED";
286
286
  declare class OrdersError extends SdkError<OrdersErrorCode> {
287
287
  constructor(message: string, options: {
288
288
  code: OrdersErrorCode;
@@ -333,6 +333,10 @@ declare const ZodGetFeeConfigParamsSchema: z.ZodObject<{
333
333
  }>;
334
334
  }, z.core.$strip>;
335
335
  type GetFeeConfigParams = z.infer<typeof ZodGetFeeConfigParamsSchema>;
336
+ declare const ZodGetPlacementLimitsParamsSchema: z.ZodObject<{
337
+ userAddress: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
338
+ }, z.core.$strip>;
339
+ type GetPlacementLimitsParams = z.infer<typeof ZodGetPlacementLimitsParamsSchema>;
336
340
  declare const ZodGetOrdersParamsSchema: z.ZodObject<{
337
341
  userAddress: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
338
342
  skip: z.ZodDefault<z.ZodNumber>;
@@ -443,6 +447,40 @@ interface FeeConfig {
443
447
  /** Fixed fee applied to small orders (6 decimals). */
444
448
  smallOrderFixedFee: bigint;
445
449
  }
450
+ /**
451
+ * Whether a daily placement cap is actually in force.
452
+ * - `enforced` — a cap is set and the contract will reject placements past it.
453
+ * - `unlimited` — the cap is explicitly zero, which the contract reads as no
454
+ * cap at all (sell/pay only; a zero buy cap blocks every buy instead).
455
+ * - `unknown` — no cap has been indexed yet, so nothing here should be shown
456
+ * as a limit. Let the contract be the judge.
457
+ */
458
+ type PlacementLimitState = "enforced" | "unlimited" | "unknown";
459
+ /**
460
+ * One daily placement bucket. `used` counts every order placed today INCLUDING
461
+ * ones that were later cancelled — the on-chain counter is never credited back,
462
+ * so cancelling does not free up an allowance.
463
+ */
464
+ interface PlacementBucket {
465
+ used: number;
466
+ /** The cap itself. Null unless `state` is `enforced`. */
467
+ limit: number | null;
468
+ /** `limit - used`, floored at zero. Null unless `state` is `enforced`. */
469
+ remaining: number | null;
470
+ state: PlacementLimitState;
471
+ }
472
+ /**
473
+ * Per-user daily order placement allowances, read from the subgraph. SELL and
474
+ * PAY draw on one shared bucket; BUY has its own. Both reset at UTC midnight.
475
+ */
476
+ interface PlacementLimits {
477
+ /** UTC day these counts belong to (unix seconds / 86400). */
478
+ dayIndex: number;
479
+ /** Unix seconds at which the buckets reset (the next UTC midnight). */
480
+ resetsAt: number;
481
+ buy: PlacementBucket;
482
+ sellPay: PlacementBucket;
483
+ }
446
484
  interface PreparedTxMeta {
447
485
  readonly circleId?: bigint;
448
486
  readonly relayIdentity?: RelayIdentity;
@@ -551,6 +589,15 @@ interface OrdersClient {
551
589
  * fee itself. Both are 6-decimal bigints.
552
590
  */
553
591
  getFeeConfig(params: GetFeeConfigParams): ResultAsync<FeeConfig, OrdersError>;
592
+ /**
593
+ * Reads the user's daily order placement allowances from the subgraph — how
594
+ * many buy and sell/pay orders they have placed today and the caps in force.
595
+ * Cancelled orders still count; SELL and PAY share one bucket.
596
+ *
597
+ * Advisory only: the subgraph lags the chain, so use it to warn or disable a
598
+ * button, never as the final word on whether a placement will succeed.
599
+ */
600
+ getPlacementLimits(params: GetPlacementLimitsParams): ResultAsync<PlacementLimits, OrdersError>;
554
601
  readonly placeOrder: PlaceOrderAction;
555
602
  readonly cancelOrder: CancelOrderAction;
556
603
  readonly setSellOrderUpi: SetSellOrderUpiAction;
@@ -928,6 +975,29 @@ declare function useZkkyc(): Zkkyc;
928
975
  /** Returns the FraudEngine instance from the nearest SdkProvider. */
929
976
  declare function useFraudEngine(): FraudEngine;
930
977
 
978
+ interface UsePlacementLimitsParams {
979
+ /** Omit or pass undefined while no wallet is connected — no request is made. */
980
+ readonly userAddress?: Address;
981
+ /** Optional polling interval in ms. Omit for no polling. */
982
+ readonly pollMs?: number;
983
+ }
984
+ interface UsePlacementLimitsResult {
985
+ limits: PlacementLimits | null;
986
+ isLoading: boolean;
987
+ error: OrdersError | null;
988
+ /** Refetches immediately. Call after a placement lands so the count catches up. */
989
+ refresh: () => void;
990
+ }
991
+ /**
992
+ * Reads the user's daily order placement allowances and keeps them fresh:
993
+ * refetches on address change, on an optional interval, and once the UTC day
994
+ * rolls over so a form left open across midnight stops showing a spent bucket.
995
+ *
996
+ * Advisory only — the subgraph lags the chain, so use this to warn or disable a
997
+ * control, never to decide whether a placement is legal.
998
+ */
999
+ declare function usePlacementLimits(params: UsePlacementLimitsParams): UsePlacementLimitsResult;
1000
+
931
1001
  /**
932
1002
  * Subscribes to Diamond order lifecycle events for the lifetime of the
933
1003
  * component. Unsubscribes automatically on unmount or when `user` changes.
@@ -948,4 +1018,4 @@ interface UseFingerprintResult {
948
1018
  }
949
1019
  declare function useFingerprint(enabled: boolean): UseFingerprintResult;
950
1020
 
951
- export { type FraudEngineSdkConfig, type OrdersSdkConfig, type SdkConfig, SdkProvider, useFingerprint, useFraudEngine, useOrders, usePrices, useProfile, useSdk, useStake, useWatchOrders, useZkkyc };
1021
+ export { type FraudEngineSdkConfig, type OrdersSdkConfig, type SdkConfig, SdkProvider, type UsePlacementLimitsParams, type UsePlacementLimitsResult, useFingerprint, useFraudEngine, useOrders, usePlacementLimits, usePrices, useProfile, useSdk, useStake, useWatchOrders, useZkkyc };
package/dist/react.d.ts CHANGED
@@ -282,7 +282,7 @@ interface StakeClient {
282
282
  readonly claimUnstake: ClaimUnstakeAction;
283
283
  }
284
284
 
285
- type OrdersErrorCode = "VALIDATION_ERROR" | "INVALID_ORDER_ID" | "INVALID_GET_ORDERS_PARAMS" | "INVALID_FEE_CONFIG_PARAMS" | "ORDER_NOT_FOUND" | "CONTRACT_READ_FAILED" | "SUBGRAPH_REQUEST_FAILED" | "SUBGRAPH_VALIDATION_FAILED" | "MALFORMED_ORDER" | "CIRCLE_SELECTION_FAILED" | "ENCRYPTION_FAILED" | "RELAY_IDENTITY_CORRUPT" | "RELAY_IDENTITY_STORE_FAILED" | "TX_SUBMISSION_FAILED" | "RECEIPT_TIMEOUT" | "TX_REVERTED" | "EVENT_WATCH_FAILED";
285
+ type OrdersErrorCode = "VALIDATION_ERROR" | "INVALID_ORDER_ID" | "INVALID_GET_ORDERS_PARAMS" | "INVALID_FEE_CONFIG_PARAMS" | "INVALID_PLACEMENT_LIMITS_PARAMS" | "ORDER_NOT_FOUND" | "CONTRACT_READ_FAILED" | "SUBGRAPH_REQUEST_FAILED" | "SUBGRAPH_VALIDATION_FAILED" | "MALFORMED_ORDER" | "CIRCLE_SELECTION_FAILED" | "ENCRYPTION_FAILED" | "RELAY_IDENTITY_CORRUPT" | "RELAY_IDENTITY_STORE_FAILED" | "TX_SUBMISSION_FAILED" | "RECEIPT_TIMEOUT" | "TX_REVERTED" | "EVENT_WATCH_FAILED";
286
286
  declare class OrdersError extends SdkError<OrdersErrorCode> {
287
287
  constructor(message: string, options: {
288
288
  code: OrdersErrorCode;
@@ -333,6 +333,10 @@ declare const ZodGetFeeConfigParamsSchema: z.ZodObject<{
333
333
  }>;
334
334
  }, z.core.$strip>;
335
335
  type GetFeeConfigParams = z.infer<typeof ZodGetFeeConfigParamsSchema>;
336
+ declare const ZodGetPlacementLimitsParamsSchema: z.ZodObject<{
337
+ userAddress: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
338
+ }, z.core.$strip>;
339
+ type GetPlacementLimitsParams = z.infer<typeof ZodGetPlacementLimitsParamsSchema>;
336
340
  declare const ZodGetOrdersParamsSchema: z.ZodObject<{
337
341
  userAddress: z.ZodString & z.ZodType<`0x${string}`, string, z.core.$ZodTypeInternals<`0x${string}`, string>>;
338
342
  skip: z.ZodDefault<z.ZodNumber>;
@@ -443,6 +447,40 @@ interface FeeConfig {
443
447
  /** Fixed fee applied to small orders (6 decimals). */
444
448
  smallOrderFixedFee: bigint;
445
449
  }
450
+ /**
451
+ * Whether a daily placement cap is actually in force.
452
+ * - `enforced` — a cap is set and the contract will reject placements past it.
453
+ * - `unlimited` — the cap is explicitly zero, which the contract reads as no
454
+ * cap at all (sell/pay only; a zero buy cap blocks every buy instead).
455
+ * - `unknown` — no cap has been indexed yet, so nothing here should be shown
456
+ * as a limit. Let the contract be the judge.
457
+ */
458
+ type PlacementLimitState = "enforced" | "unlimited" | "unknown";
459
+ /**
460
+ * One daily placement bucket. `used` counts every order placed today INCLUDING
461
+ * ones that were later cancelled — the on-chain counter is never credited back,
462
+ * so cancelling does not free up an allowance.
463
+ */
464
+ interface PlacementBucket {
465
+ used: number;
466
+ /** The cap itself. Null unless `state` is `enforced`. */
467
+ limit: number | null;
468
+ /** `limit - used`, floored at zero. Null unless `state` is `enforced`. */
469
+ remaining: number | null;
470
+ state: PlacementLimitState;
471
+ }
472
+ /**
473
+ * Per-user daily order placement allowances, read from the subgraph. SELL and
474
+ * PAY draw on one shared bucket; BUY has its own. Both reset at UTC midnight.
475
+ */
476
+ interface PlacementLimits {
477
+ /** UTC day these counts belong to (unix seconds / 86400). */
478
+ dayIndex: number;
479
+ /** Unix seconds at which the buckets reset (the next UTC midnight). */
480
+ resetsAt: number;
481
+ buy: PlacementBucket;
482
+ sellPay: PlacementBucket;
483
+ }
446
484
  interface PreparedTxMeta {
447
485
  readonly circleId?: bigint;
448
486
  readonly relayIdentity?: RelayIdentity;
@@ -551,6 +589,15 @@ interface OrdersClient {
551
589
  * fee itself. Both are 6-decimal bigints.
552
590
  */
553
591
  getFeeConfig(params: GetFeeConfigParams): ResultAsync<FeeConfig, OrdersError>;
592
+ /**
593
+ * Reads the user's daily order placement allowances from the subgraph — how
594
+ * many buy and sell/pay orders they have placed today and the caps in force.
595
+ * Cancelled orders still count; SELL and PAY share one bucket.
596
+ *
597
+ * Advisory only: the subgraph lags the chain, so use it to warn or disable a
598
+ * button, never as the final word on whether a placement will succeed.
599
+ */
600
+ getPlacementLimits(params: GetPlacementLimitsParams): ResultAsync<PlacementLimits, OrdersError>;
554
601
  readonly placeOrder: PlaceOrderAction;
555
602
  readonly cancelOrder: CancelOrderAction;
556
603
  readonly setSellOrderUpi: SetSellOrderUpiAction;
@@ -928,6 +975,29 @@ declare function useZkkyc(): Zkkyc;
928
975
  /** Returns the FraudEngine instance from the nearest SdkProvider. */
929
976
  declare function useFraudEngine(): FraudEngine;
930
977
 
978
+ interface UsePlacementLimitsParams {
979
+ /** Omit or pass undefined while no wallet is connected — no request is made. */
980
+ readonly userAddress?: Address;
981
+ /** Optional polling interval in ms. Omit for no polling. */
982
+ readonly pollMs?: number;
983
+ }
984
+ interface UsePlacementLimitsResult {
985
+ limits: PlacementLimits | null;
986
+ isLoading: boolean;
987
+ error: OrdersError | null;
988
+ /** Refetches immediately. Call after a placement lands so the count catches up. */
989
+ refresh: () => void;
990
+ }
991
+ /**
992
+ * Reads the user's daily order placement allowances and keeps them fresh:
993
+ * refetches on address change, on an optional interval, and once the UTC day
994
+ * rolls over so a form left open across midnight stops showing a spent bucket.
995
+ *
996
+ * Advisory only — the subgraph lags the chain, so use this to warn or disable a
997
+ * control, never to decide whether a placement is legal.
998
+ */
999
+ declare function usePlacementLimits(params: UsePlacementLimitsParams): UsePlacementLimitsResult;
1000
+
931
1001
  /**
932
1002
  * Subscribes to Diamond order lifecycle events for the lifetime of the
933
1003
  * component. Unsubscribes automatically on unmount or when `user` changes.
@@ -948,4 +1018,4 @@ interface UseFingerprintResult {
948
1018
  }
949
1019
  declare function useFingerprint(enabled: boolean): UseFingerprintResult;
950
1020
 
951
- export { type FraudEngineSdkConfig, type OrdersSdkConfig, type SdkConfig, SdkProvider, useFingerprint, useFraudEngine, useOrders, usePrices, useProfile, useSdk, useStake, useWatchOrders, useZkkyc };
1021
+ export { type FraudEngineSdkConfig, type OrdersSdkConfig, type SdkConfig, SdkProvider, type UsePlacementLimitsParams, type UsePlacementLimitsResult, useFingerprint, useFraudEngine, useOrders, usePlacementLimits, usePrices, useProfile, useSdk, useStake, useWatchOrders, useZkkyc };
package/dist/react.mjs CHANGED
@@ -1679,6 +1679,9 @@ var ZodGetOrderParamsSchema = z3.object({
1679
1679
  var ZodGetFeeConfigParamsSchema = z3.object({
1680
1680
  currency: ZodCurrencySchema
1681
1681
  });
1682
+ var ZodGetPlacementLimitsParamsSchema = z3.object({
1683
+ userAddress: ZodAddressSchema
1684
+ });
1682
1685
  var ZodGetOrdersParamsSchema = z3.object({
1683
1686
  userAddress: ZodAddressSchema,
1684
1687
  skip: z3.number().int().min(0).default(0),
@@ -1739,6 +1742,19 @@ var ZodSubgraphOrderSchema = z3.object({
1739
1742
  var ZodSubgraphOrdersResponseSchema = z3.object({
1740
1743
  orders_collection: z3.array(ZodSubgraphOrderSchema)
1741
1744
  });
1745
+ var ZodSubgraphPlacementLimitsResponseSchema = z3.object({
1746
+ userDailyPlacements: z3.object({
1747
+ dayIndex: z3.string(),
1748
+ buyPlacements: z3.string(),
1749
+ sellPlacements: z3.string()
1750
+ }).nullish(),
1751
+ orderPlacementLimitConfig: z3.object({
1752
+ dailyBuyOrderPlacementLimit: z3.string(),
1753
+ buyLimitConfigured: z3.boolean(),
1754
+ dailySellOrderPlacementLimit: z3.string(),
1755
+ sellLimitConfigured: z3.boolean()
1756
+ }).nullish()
1757
+ });
1742
1758
 
1743
1759
  // src/orders/actions/approve-usdc.ts
1744
1760
  function createApproveUsdcAction(input) {
@@ -5112,6 +5128,10 @@ var contractErrors = {
5112
5128
  // Order limits
5113
5129
  DailyBuyOrderLimitExceeded: "DAILY_BUY_ORDER_LIMIT_EXCEEDED",
5114
5130
  MonthlyBuyOrderLimitExceeded: "MONTHLY_BUY_ORDER_LIMIT_EXCEEDED",
5131
+ // Gross placement caps: counted when the order is placed and never given
5132
+ // back when it is cancelled, unlike the volume limits above.
5133
+ DailyBuyOrderPlacementLimitExceeded: "DAILY_BUY_ORDER_PLACEMENT_LIMIT_EXCEEDED",
5134
+ DailySellOrderPlacementLimitExceeded: "DAILY_SELL_ORDER_PLACEMENT_LIMIT_EXCEEDED",
5115
5135
  SellOrderAmountLimitExceeded: "SELL_ORDER_AMOUNT_LIMIT_EXCEEDED",
5116
5136
  BuyOrderAmountExceedsLimit: "BUY_ORDER_AMOUNT_EXCEEDS_LIMIT",
5117
5137
  SellOrderAmountExceedsLimit: "SELL_ORDER_AMOUNT_EXCEEDS_LIMIT",
@@ -5323,6 +5343,8 @@ var hexContractErrors = {
5323
5343
  // Order limits
5324
5344
  "0xe595a7bf": contractErrors.DailyBuyOrderLimitExceeded,
5325
5345
  "0x675dbc86": contractErrors.MonthlyBuyOrderLimitExceeded,
5346
+ "0x917c7aef": contractErrors.DailyBuyOrderPlacementLimitExceeded,
5347
+ "0x4688ce73": contractErrors.DailySellOrderPlacementLimitExceeded,
5326
5348
  "0x64301cb8": contractErrors.SellOrderAmountLimitExceeded,
5327
5349
  "0x91da284f": contractErrors.BuyOrderAmountExceedsLimit,
5328
5350
  "0xb407b9ec": contractErrors.SellOrderAmountExceedsLimit,
@@ -6524,6 +6546,7 @@ function normalizeSubgraphOrder(raw) {
6524
6546
 
6525
6547
  // src/orders/subgraph/index.ts
6526
6548
  import { Result as Result4 } from "neverthrow";
6549
+ import { stringToHex as stringToHex8 } from "viem";
6527
6550
 
6528
6551
  // src/orders/subgraph/queries.ts
6529
6552
  var ORDERS_BY_USER_QUERY = (
@@ -6560,8 +6583,35 @@ var ORDERS_BY_USER_QUERY = (
6560
6583
  }
6561
6584
  `
6562
6585
  );
6586
+ var PLACEMENT_LIMITS_QUERY = (
6587
+ /* GraphQL */
6588
+ `
6589
+ query PlacementLimits($placementsId: ID!, $configId: ID!) {
6590
+ userDailyPlacements(id: $placementsId) {
6591
+ dayIndex
6592
+ buyPlacements
6593
+ sellPlacements
6594
+ }
6595
+ orderPlacementLimitConfig(id: $configId) {
6596
+ dailyBuyOrderPlacementLimit
6597
+ buyLimitConfigured
6598
+ dailySellOrderPlacementLimit
6599
+ sellLimitConfigured
6600
+ }
6601
+ }
6602
+ `
6603
+ );
6563
6604
 
6564
6605
  // src/orders/subgraph/index.ts
6606
+ var SECONDS_PER_DAY = 86400;
6607
+ var PLACEMENT_LIMIT_CONFIG_ID = stringToHex8("placement-limits");
6608
+ function bucket(used, limit, configured, zeroMeansUnlimited) {
6609
+ if (!configured) return { used, limit: null, remaining: null, state: "unknown" };
6610
+ if (limit === 0 && zeroMeansUnlimited) {
6611
+ return { used, limit: null, remaining: null, state: "unlimited" };
6612
+ }
6613
+ return { used, limit, remaining: Math.max(0, limit - used), state: "enforced" };
6614
+ }
6565
6615
  function getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger = noopLogger) {
6566
6616
  const user = userAddress.toLowerCase();
6567
6617
  logger.debug("fetching orders from subgraph", { subgraphUrl, user, skip, limit });
@@ -6588,6 +6638,54 @@ function getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger = noopLo
6588
6638
  )
6589
6639
  );
6590
6640
  }
6641
+ function getPlacementLimitsForUser(subgraphUrl, userAddress, nowSeconds, logger = noopLogger) {
6642
+ const user = userAddress.toLowerCase();
6643
+ const dayIndex = Math.floor(nowSeconds / SECONDS_PER_DAY);
6644
+ const placementsId = stringToHex8(`${user}-${dayIndex}`);
6645
+ logger.debug("fetching placement limits from subgraph", { subgraphUrl, user, dayIndex });
6646
+ return querySubgraph(subgraphUrl, {
6647
+ query: PLACEMENT_LIMITS_QUERY,
6648
+ variables: { placementsId, configId: PLACEMENT_LIMIT_CONFIG_ID }
6649
+ }).mapErr(
6650
+ (e) => new OrdersError(e.message, {
6651
+ code: "SUBGRAPH_REQUEST_FAILED",
6652
+ cause: e.cause ?? e,
6653
+ context: { user, dayIndex, ...e.context ?? {} }
6654
+ })
6655
+ ).andThen(
6656
+ (data) => validate(
6657
+ ZodSubgraphPlacementLimitsResponseSchema,
6658
+ data,
6659
+ (message, cause, d) => new OrdersError(message, {
6660
+ code: "SUBGRAPH_VALIDATION_FAILED",
6661
+ cause,
6662
+ context: { data: d }
6663
+ })
6664
+ )
6665
+ ).map((validated) => {
6666
+ const placements = validated.userDailyPlacements;
6667
+ const config = validated.orderPlacementLimitConfig;
6668
+ const buyUsed = placements ? Number(placements.buyPlacements) : 0;
6669
+ const sellUsed = placements ? Number(placements.sellPlacements) : 0;
6670
+ return {
6671
+ dayIndex,
6672
+ resetsAt: (dayIndex + 1) * SECONDS_PER_DAY,
6673
+ // A zero BUY cap is a hard block on-chain, not "unlimited".
6674
+ buy: bucket(
6675
+ buyUsed,
6676
+ config ? Number(config.dailyBuyOrderPlacementLimit) : 0,
6677
+ config?.buyLimitConfigured ?? false,
6678
+ false
6679
+ ),
6680
+ sellPay: bucket(
6681
+ sellUsed,
6682
+ config ? Number(config.dailySellOrderPlacementLimit) : 0,
6683
+ config?.sellLimitConfigured ?? false,
6684
+ true
6685
+ )
6686
+ };
6687
+ });
6688
+ }
6591
6689
 
6592
6690
  // src/orders/watch-events.ts
6593
6691
  var PLACED_CONFIG = {
@@ -6763,6 +6861,19 @@ function createOrders(config) {
6763
6861
  ({ userAddress, skip, limit }) => getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger)
6764
6862
  );
6765
6863
  },
6864
+ getPlacementLimits(params) {
6865
+ return validate(
6866
+ ZodGetPlacementLimitsParamsSchema,
6867
+ params,
6868
+ (message, cause, d) => new OrdersError(message, {
6869
+ code: "INVALID_PLACEMENT_LIMITS_PARAMS",
6870
+ cause,
6871
+ context: { params: d }
6872
+ })
6873
+ ).asyncAndThen(
6874
+ ({ userAddress }) => getPlacementLimitsForUser(subgraphUrl, userAddress, Math.floor(Date.now() / 1e3), logger)
6875
+ );
6876
+ },
6766
6877
  getFeeConfig(params) {
6767
6878
  return validate(
6768
6879
  ZodGetFeeConfigParamsSchema,
@@ -7246,16 +7357,74 @@ function useFraudEngine() {
7246
7357
  return fraudEngine;
7247
7358
  }
7248
7359
 
7360
+ // src/react/use-placement-limits.ts
7361
+ import { useCallback, useEffect as useEffect2, useRef as useRef2, useState } from "react";
7362
+ function usePlacementLimits(params) {
7363
+ const orders = useOrders();
7364
+ const { userAddress, pollMs } = params;
7365
+ const [limits, setLimits] = useState(null);
7366
+ const [isLoading, setIsLoading] = useState(false);
7367
+ const [error, setError] = useState(null);
7368
+ const requestIdRef = useRef2(0);
7369
+ const mountedRef = useRef2(true);
7370
+ useEffect2(() => {
7371
+ mountedRef.current = true;
7372
+ return () => {
7373
+ mountedRef.current = false;
7374
+ };
7375
+ }, []);
7376
+ const refresh = useCallback(() => {
7377
+ if (!userAddress) {
7378
+ requestIdRef.current++;
7379
+ setLimits(null);
7380
+ setError(null);
7381
+ setIsLoading(false);
7382
+ return;
7383
+ }
7384
+ const requestId = ++requestIdRef.current;
7385
+ setIsLoading(true);
7386
+ orders.getPlacementLimits({ userAddress }).match(
7387
+ (next) => {
7388
+ if (!mountedRef.current || requestId !== requestIdRef.current) return;
7389
+ setLimits(next);
7390
+ setError(null);
7391
+ setIsLoading(false);
7392
+ },
7393
+ (cause) => {
7394
+ if (!mountedRef.current || requestId !== requestIdRef.current) return;
7395
+ setError(cause);
7396
+ setIsLoading(false);
7397
+ }
7398
+ );
7399
+ }, [orders, userAddress]);
7400
+ useEffect2(() => {
7401
+ refresh();
7402
+ }, [refresh]);
7403
+ useEffect2(() => {
7404
+ if (!pollMs || !userAddress) return;
7405
+ const timer = setInterval(refresh, pollMs);
7406
+ return () => clearInterval(timer);
7407
+ }, [pollMs, userAddress, refresh]);
7408
+ useEffect2(() => {
7409
+ if (!limits || !userAddress) return;
7410
+ const msUntilReset = limits.resetsAt * 1e3 - Date.now();
7411
+ if (msUntilReset <= 0) return;
7412
+ const timer = setTimeout(refresh, msUntilReset + 1e3);
7413
+ return () => clearTimeout(timer);
7414
+ }, [limits, userAddress, refresh]);
7415
+ return { limits, isLoading, error, refresh };
7416
+ }
7417
+
7249
7418
  // src/react/use-watch-orders.ts
7250
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
7419
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
7251
7420
  function useWatchOrders(params) {
7252
7421
  const orders = useOrders();
7253
7422
  const { user, onEvent, onError } = params;
7254
- const onEventRef = useRef2(onEvent);
7255
- const onErrorRef = useRef2(onError);
7423
+ const onEventRef = useRef3(onEvent);
7424
+ const onErrorRef = useRef3(onError);
7256
7425
  onEventRef.current = onEvent;
7257
7426
  onErrorRef.current = onError;
7258
- useEffect2(() => {
7427
+ useEffect3(() => {
7259
7428
  const unsubscribe = orders.watchEvents({
7260
7429
  user,
7261
7430
  onEvent: (event) => onEventRef.current(event),
@@ -7266,12 +7435,12 @@ function useWatchOrders(params) {
7266
7435
  }
7267
7436
 
7268
7437
  // src/fraud-engine/react/use-fingerprint.ts
7269
- import { useEffect as useEffect3, useState } from "react";
7438
+ import { useEffect as useEffect4, useState as useState2 } from "react";
7270
7439
  function useFingerprint(enabled) {
7271
- const [data, setData] = useState(null);
7272
- const [error, setError] = useState(null);
7273
- const [isLoading, setIsLoading] = useState(false);
7274
- useEffect3(() => {
7440
+ const [data, setData] = useState2(null);
7441
+ const [error, setError] = useState2(null);
7442
+ const [isLoading, setIsLoading] = useState2(false);
7443
+ useEffect4(() => {
7275
7444
  if (!enabled) return;
7276
7445
  let cancelled = false;
7277
7446
  setIsLoading(true);
@@ -7303,6 +7472,7 @@ export {
7303
7472
  useFingerprint,
7304
7473
  useFraudEngine,
7305
7474
  useOrders,
7475
+ usePlacementLimits,
7306
7476
  usePrices,
7307
7477
  useProfile,
7308
7478
  useSdk,