@p2pdotme/sdk 1.2.18 → 1.2.19

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.cjs CHANGED
@@ -34,6 +34,7 @@ __export(react_exports, {
34
34
  useFingerprint: () => useFingerprint,
35
35
  useFraudEngine: () => useFraudEngine,
36
36
  useOrders: () => useOrders,
37
+ usePlacementLimits: () => usePlacementLimits,
37
38
  usePrices: () => usePrices,
38
39
  useProfile: () => useProfile,
39
40
  useSdk: () => useSdk,
@@ -1724,6 +1725,9 @@ var ZodGetOrderParamsSchema = import_zod3.z.object({
1724
1725
  var ZodGetFeeConfigParamsSchema = import_zod3.z.object({
1725
1726
  currency: ZodCurrencySchema
1726
1727
  });
1728
+ var ZodGetPlacementLimitsParamsSchema = import_zod3.z.object({
1729
+ userAddress: ZodAddressSchema
1730
+ });
1727
1731
  var ZodGetOrdersParamsSchema = import_zod3.z.object({
1728
1732
  userAddress: ZodAddressSchema,
1729
1733
  skip: import_zod3.z.number().int().min(0).default(0),
@@ -1784,6 +1788,19 @@ var ZodSubgraphOrderSchema = import_zod3.z.object({
1784
1788
  var ZodSubgraphOrdersResponseSchema = import_zod3.z.object({
1785
1789
  orders_collection: import_zod3.z.array(ZodSubgraphOrderSchema)
1786
1790
  });
1791
+ var ZodSubgraphPlacementLimitsResponseSchema = import_zod3.z.object({
1792
+ userDailyPlacements: import_zod3.z.object({
1793
+ dayIndex: import_zod3.z.string(),
1794
+ buyPlacements: import_zod3.z.string(),
1795
+ sellPlacements: import_zod3.z.string()
1796
+ }).nullish(),
1797
+ orderPlacementLimitConfig: import_zod3.z.object({
1798
+ dailyBuyOrderPlacementLimit: import_zod3.z.string(),
1799
+ buyLimitConfigured: import_zod3.z.boolean(),
1800
+ dailySellOrderPlacementLimit: import_zod3.z.string(),
1801
+ sellLimitConfigured: import_zod3.z.boolean()
1802
+ }).nullish()
1803
+ });
1787
1804
 
1788
1805
  // src/orders/actions/approve-usdc.ts
1789
1806
  function createApproveUsdcAction(input) {
@@ -5157,6 +5174,10 @@ var contractErrors = {
5157
5174
  // Order limits
5158
5175
  DailyBuyOrderLimitExceeded: "DAILY_BUY_ORDER_LIMIT_EXCEEDED",
5159
5176
  MonthlyBuyOrderLimitExceeded: "MONTHLY_BUY_ORDER_LIMIT_EXCEEDED",
5177
+ // Gross placement caps: counted when the order is placed and never given
5178
+ // back when it is cancelled, unlike the volume limits above.
5179
+ DailyBuyOrderPlacementLimitExceeded: "DAILY_BUY_ORDER_PLACEMENT_LIMIT_EXCEEDED",
5180
+ DailySellOrderPlacementLimitExceeded: "DAILY_SELL_ORDER_PLACEMENT_LIMIT_EXCEEDED",
5160
5181
  SellOrderAmountLimitExceeded: "SELL_ORDER_AMOUNT_LIMIT_EXCEEDED",
5161
5182
  BuyOrderAmountExceedsLimit: "BUY_ORDER_AMOUNT_EXCEEDS_LIMIT",
5162
5183
  SellOrderAmountExceedsLimit: "SELL_ORDER_AMOUNT_EXCEEDS_LIMIT",
@@ -5368,6 +5389,8 @@ var hexContractErrors = {
5368
5389
  // Order limits
5369
5390
  "0xe595a7bf": contractErrors.DailyBuyOrderLimitExceeded,
5370
5391
  "0x675dbc86": contractErrors.MonthlyBuyOrderLimitExceeded,
5392
+ "0x917c7aef": contractErrors.DailyBuyOrderPlacementLimitExceeded,
5393
+ "0x4688ce73": contractErrors.DailySellOrderPlacementLimitExceeded,
5371
5394
  "0x64301cb8": contractErrors.SellOrderAmountLimitExceeded,
5372
5395
  "0x91da284f": contractErrors.BuyOrderAmountExceedsLimit,
5373
5396
  "0xb407b9ec": contractErrors.SellOrderAmountExceedsLimit,
@@ -6569,6 +6592,7 @@ function normalizeSubgraphOrder(raw) {
6569
6592
 
6570
6593
  // src/orders/subgraph/index.ts
6571
6594
  var import_neverthrow17 = require("neverthrow");
6595
+ var import_viem19 = require("viem");
6572
6596
 
6573
6597
  // src/orders/subgraph/queries.ts
6574
6598
  var ORDERS_BY_USER_QUERY = (
@@ -6605,8 +6629,35 @@ var ORDERS_BY_USER_QUERY = (
6605
6629
  }
6606
6630
  `
6607
6631
  );
6632
+ var PLACEMENT_LIMITS_QUERY = (
6633
+ /* GraphQL */
6634
+ `
6635
+ query PlacementLimits($placementsId: ID!, $configId: ID!) {
6636
+ userDailyPlacements(id: $placementsId) {
6637
+ dayIndex
6638
+ buyPlacements
6639
+ sellPlacements
6640
+ }
6641
+ orderPlacementLimitConfig(id: $configId) {
6642
+ dailyBuyOrderPlacementLimit
6643
+ buyLimitConfigured
6644
+ dailySellOrderPlacementLimit
6645
+ sellLimitConfigured
6646
+ }
6647
+ }
6648
+ `
6649
+ );
6608
6650
 
6609
6651
  // src/orders/subgraph/index.ts
6652
+ var SECONDS_PER_DAY = 86400;
6653
+ var PLACEMENT_LIMIT_CONFIG_ID = (0, import_viem19.stringToHex)("placement-limits");
6654
+ function bucket(used, limit, configured, zeroMeansUnlimited) {
6655
+ if (!configured) return { used, limit: null, remaining: null, state: "unknown" };
6656
+ if (limit === 0 && zeroMeansUnlimited) {
6657
+ return { used, limit: null, remaining: null, state: "unlimited" };
6658
+ }
6659
+ return { used, limit, remaining: Math.max(0, limit - used), state: "enforced" };
6660
+ }
6610
6661
  function getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger = noopLogger) {
6611
6662
  const user = userAddress.toLowerCase();
6612
6663
  logger.debug("fetching orders from subgraph", { subgraphUrl, user, skip, limit });
@@ -6633,6 +6684,54 @@ function getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger = noopLo
6633
6684
  )
6634
6685
  );
6635
6686
  }
6687
+ function getPlacementLimitsForUser(subgraphUrl, userAddress, nowSeconds, logger = noopLogger) {
6688
+ const user = userAddress.toLowerCase();
6689
+ const dayIndex = Math.floor(nowSeconds / SECONDS_PER_DAY);
6690
+ const placementsId = (0, import_viem19.stringToHex)(`${user}-${dayIndex}`);
6691
+ logger.debug("fetching placement limits from subgraph", { subgraphUrl, user, dayIndex });
6692
+ return querySubgraph(subgraphUrl, {
6693
+ query: PLACEMENT_LIMITS_QUERY,
6694
+ variables: { placementsId, configId: PLACEMENT_LIMIT_CONFIG_ID }
6695
+ }).mapErr(
6696
+ (e) => new OrdersError(e.message, {
6697
+ code: "SUBGRAPH_REQUEST_FAILED",
6698
+ cause: e.cause ?? e,
6699
+ context: { user, dayIndex, ...e.context ?? {} }
6700
+ })
6701
+ ).andThen(
6702
+ (data) => validate(
6703
+ ZodSubgraphPlacementLimitsResponseSchema,
6704
+ data,
6705
+ (message, cause, d) => new OrdersError(message, {
6706
+ code: "SUBGRAPH_VALIDATION_FAILED",
6707
+ cause,
6708
+ context: { data: d }
6709
+ })
6710
+ )
6711
+ ).map((validated) => {
6712
+ const placements = validated.userDailyPlacements;
6713
+ const config = validated.orderPlacementLimitConfig;
6714
+ const buyUsed = placements ? Number(placements.buyPlacements) : 0;
6715
+ const sellUsed = placements ? Number(placements.sellPlacements) : 0;
6716
+ return {
6717
+ dayIndex,
6718
+ resetsAt: (dayIndex + 1) * SECONDS_PER_DAY,
6719
+ // A zero BUY cap is a hard block on-chain, not "unlimited".
6720
+ buy: bucket(
6721
+ buyUsed,
6722
+ config ? Number(config.dailyBuyOrderPlacementLimit) : 0,
6723
+ config?.buyLimitConfigured ?? false,
6724
+ false
6725
+ ),
6726
+ sellPay: bucket(
6727
+ sellUsed,
6728
+ config ? Number(config.dailySellOrderPlacementLimit) : 0,
6729
+ config?.sellLimitConfigured ?? false,
6730
+ true
6731
+ )
6732
+ };
6733
+ });
6734
+ }
6636
6735
 
6637
6736
  // src/orders/watch-events.ts
6638
6737
  var PLACED_CONFIG = {
@@ -6808,6 +6907,19 @@ function createOrders(config) {
6808
6907
  ({ userAddress, skip, limit }) => getOrdersForUser(subgraphUrl, userAddress, skip, limit, logger)
6809
6908
  );
6810
6909
  },
6910
+ getPlacementLimits(params) {
6911
+ return validate(
6912
+ ZodGetPlacementLimitsParamsSchema,
6913
+ params,
6914
+ (message, cause, d) => new OrdersError(message, {
6915
+ code: "INVALID_PLACEMENT_LIMITS_PARAMS",
6916
+ cause,
6917
+ context: { params: d }
6918
+ })
6919
+ ).asyncAndThen(
6920
+ ({ userAddress }) => getPlacementLimitsForUser(subgraphUrl, userAddress, Math.floor(Date.now() / 1e3), logger)
6921
+ );
6922
+ },
6811
6923
  getFeeConfig(params) {
6812
6924
  return validate(
6813
6925
  ZodGetFeeConfigParamsSchema,
@@ -6878,7 +6990,7 @@ function createPrices(config) {
6878
6990
 
6879
6991
  // src/profile/contracts/actions.ts
6880
6992
  var import_neverthrow19 = require("neverthrow");
6881
- var import_viem19 = require("viem");
6993
+ var import_viem20 = require("viem");
6882
6994
  function getBalances(publicClient, usdcAddress, diamondAddress, params) {
6883
6995
  return validate(
6884
6996
  ZodGetBalancesParamsSchema,
@@ -6903,8 +7015,8 @@ function getBalances(publicClient, usdcAddress, diamondAddress, params) {
6903
7015
  })
6904
7016
  )
6905
7017
  ]).map(([usdc, priceConfig]) => {
6906
- const usdcFormatted = Number((0, import_viem19.formatUnits)(usdc, 6));
6907
- const sellPriceFormatted = Number((0, import_viem19.formatUnits)(priceConfig.sellPrice, 6));
7018
+ const usdcFormatted = Number((0, import_viem20.formatUnits)(usdc, 6));
7019
+ const sellPriceFormatted = Number((0, import_viem20.formatUnits)(priceConfig.sellPrice, 6));
6908
7020
  return {
6909
7021
  usdc: usdcFormatted,
6910
7022
  fiat: usdcFormatted * sellPriceFormatted,
@@ -6927,7 +7039,7 @@ function createProfile(config) {
6927
7039
 
6928
7040
  // src/stake/actions/cancel-unstake.ts
6929
7041
  var import_neverthrow21 = require("neverthrow");
6930
- var import_viem20 = require("viem");
7042
+ var import_viem21 = require("viem");
6931
7043
 
6932
7044
  // src/stake/tx.ts
6933
7045
  var import_neverthrow20 = require("neverthrow");
@@ -6983,7 +7095,7 @@ function createCancelUnstakeAction(input) {
6983
7095
  const { publicClient, diamondAddress } = input;
6984
7096
  const prepareFn = () => (0, import_neverthrow21.okAsync)({
6985
7097
  to: diamondAddress,
6986
- data: (0, import_viem20.encodeFunctionData)({
7098
+ data: (0, import_viem21.encodeFunctionData)({
6987
7099
  abi: ABIS.FACETS.STAKE,
6988
7100
  functionName: "p2pBoostCancelUnstake",
6989
7101
  args: []
@@ -7004,12 +7116,12 @@ function createCancelUnstakeAction(input) {
7004
7116
 
7005
7117
  // src/stake/actions/claim-unstake.ts
7006
7118
  var import_neverthrow22 = require("neverthrow");
7007
- var import_viem21 = require("viem");
7119
+ var import_viem22 = require("viem");
7008
7120
  function createClaimUnstakeAction(input) {
7009
7121
  const { publicClient, diamondAddress } = input;
7010
7122
  const prepareFn = () => (0, import_neverthrow22.okAsync)({
7011
7123
  to: diamondAddress,
7012
- data: (0, import_viem21.encodeFunctionData)({
7124
+ data: (0, import_viem22.encodeFunctionData)({
7013
7125
  abi: ABIS.FACETS.STAKE,
7014
7126
  functionName: "p2pBoostClaimUnstake",
7015
7127
  args: []
@@ -7030,12 +7142,12 @@ function createClaimUnstakeAction(input) {
7030
7142
 
7031
7143
  // src/stake/actions/request-unstake.ts
7032
7144
  var import_neverthrow23 = require("neverthrow");
7033
- var import_viem22 = require("viem");
7145
+ var import_viem23 = require("viem");
7034
7146
  function createRequestUnstakeAction(input) {
7035
7147
  const { publicClient, diamondAddress } = input;
7036
7148
  const prepareFn = () => (0, import_neverthrow23.okAsync)({
7037
7149
  to: diamondAddress,
7038
- data: (0, import_viem22.encodeFunctionData)({
7150
+ data: (0, import_viem23.encodeFunctionData)({
7039
7151
  abi: ABIS.FACETS.STAKE,
7040
7152
  functionName: "p2pBoostRequestUnstake",
7041
7153
  args: []
@@ -7055,7 +7167,7 @@ function createRequestUnstakeAction(input) {
7055
7167
  }
7056
7168
 
7057
7169
  // src/stake/actions/stake.ts
7058
- var import_viem23 = require("viem");
7170
+ var import_viem24 = require("viem");
7059
7171
  function createStakeAction(input) {
7060
7172
  const { publicClient, diamondAddress } = input;
7061
7173
  const prepareFn = (params) => validate(
@@ -7068,7 +7180,7 @@ function createStakeAction(input) {
7068
7180
  })
7069
7181
  ).map(({ tokens }) => ({
7070
7182
  to: diamondAddress,
7071
- data: (0, import_viem23.encodeFunctionData)({
7183
+ data: (0, import_viem24.encodeFunctionData)({
7072
7184
  abi: ABIS.FACETS.STAKE,
7073
7185
  functionName: "p2pBoostStake",
7074
7186
  args: [tokens]
@@ -7088,7 +7200,7 @@ function createStakeAction(input) {
7088
7200
  }
7089
7201
 
7090
7202
  // src/stake/actions/top-up.ts
7091
- var import_viem24 = require("viem");
7203
+ var import_viem25 = require("viem");
7092
7204
  function createTopUpAction(input) {
7093
7205
  const { publicClient, diamondAddress } = input;
7094
7206
  const prepareFn = (params) => validate(
@@ -7101,7 +7213,7 @@ function createTopUpAction(input) {
7101
7213
  })
7102
7214
  ).map(({ tokens }) => ({
7103
7215
  to: diamondAddress,
7104
- data: (0, import_viem24.encodeFunctionData)({
7216
+ data: (0, import_viem25.encodeFunctionData)({
7105
7217
  abi: ABIS.FACETS.STAKE,
7106
7218
  functionName: "p2pBoostTopUp",
7107
7219
  args: [tokens]
@@ -7291,16 +7403,74 @@ function useFraudEngine() {
7291
7403
  return fraudEngine;
7292
7404
  }
7293
7405
 
7294
- // src/react/use-watch-orders.ts
7406
+ // src/react/use-placement-limits.ts
7295
7407
  var import_react2 = require("react");
7408
+ function usePlacementLimits(params) {
7409
+ const orders = useOrders();
7410
+ const { userAddress, pollMs } = params;
7411
+ const [limits, setLimits] = (0, import_react2.useState)(null);
7412
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
7413
+ const [error, setError] = (0, import_react2.useState)(null);
7414
+ const requestIdRef = (0, import_react2.useRef)(0);
7415
+ const mountedRef = (0, import_react2.useRef)(true);
7416
+ (0, import_react2.useEffect)(() => {
7417
+ mountedRef.current = true;
7418
+ return () => {
7419
+ mountedRef.current = false;
7420
+ };
7421
+ }, []);
7422
+ const refresh = (0, import_react2.useCallback)(() => {
7423
+ if (!userAddress) {
7424
+ requestIdRef.current++;
7425
+ setLimits(null);
7426
+ setError(null);
7427
+ setIsLoading(false);
7428
+ return;
7429
+ }
7430
+ const requestId = ++requestIdRef.current;
7431
+ setIsLoading(true);
7432
+ orders.getPlacementLimits({ userAddress }).match(
7433
+ (next) => {
7434
+ if (!mountedRef.current || requestId !== requestIdRef.current) return;
7435
+ setLimits(next);
7436
+ setError(null);
7437
+ setIsLoading(false);
7438
+ },
7439
+ (cause) => {
7440
+ if (!mountedRef.current || requestId !== requestIdRef.current) return;
7441
+ setError(cause);
7442
+ setIsLoading(false);
7443
+ }
7444
+ );
7445
+ }, [orders, userAddress]);
7446
+ (0, import_react2.useEffect)(() => {
7447
+ refresh();
7448
+ }, [refresh]);
7449
+ (0, import_react2.useEffect)(() => {
7450
+ if (!pollMs || !userAddress) return;
7451
+ const timer = setInterval(refresh, pollMs);
7452
+ return () => clearInterval(timer);
7453
+ }, [pollMs, userAddress, refresh]);
7454
+ (0, import_react2.useEffect)(() => {
7455
+ if (!limits || !userAddress) return;
7456
+ const msUntilReset = limits.resetsAt * 1e3 - Date.now();
7457
+ if (msUntilReset <= 0) return;
7458
+ const timer = setTimeout(refresh, msUntilReset + 1e3);
7459
+ return () => clearTimeout(timer);
7460
+ }, [limits, userAddress, refresh]);
7461
+ return { limits, isLoading, error, refresh };
7462
+ }
7463
+
7464
+ // src/react/use-watch-orders.ts
7465
+ var import_react3 = require("react");
7296
7466
  function useWatchOrders(params) {
7297
7467
  const orders = useOrders();
7298
7468
  const { user, onEvent, onError } = params;
7299
- const onEventRef = (0, import_react2.useRef)(onEvent);
7300
- const onErrorRef = (0, import_react2.useRef)(onError);
7469
+ const onEventRef = (0, import_react3.useRef)(onEvent);
7470
+ const onErrorRef = (0, import_react3.useRef)(onError);
7301
7471
  onEventRef.current = onEvent;
7302
7472
  onErrorRef.current = onError;
7303
- (0, import_react2.useEffect)(() => {
7473
+ (0, import_react3.useEffect)(() => {
7304
7474
  const unsubscribe = orders.watchEvents({
7305
7475
  user,
7306
7476
  onEvent: (event) => onEventRef.current(event),
@@ -7311,12 +7481,12 @@ function useWatchOrders(params) {
7311
7481
  }
7312
7482
 
7313
7483
  // src/fraud-engine/react/use-fingerprint.ts
7314
- var import_react3 = require("react");
7484
+ var import_react4 = require("react");
7315
7485
  function useFingerprint(enabled) {
7316
- const [data, setData] = (0, import_react3.useState)(null);
7317
- const [error, setError] = (0, import_react3.useState)(null);
7318
- const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
7319
- (0, import_react3.useEffect)(() => {
7486
+ const [data, setData] = (0, import_react4.useState)(null);
7487
+ const [error, setError] = (0, import_react4.useState)(null);
7488
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
7489
+ (0, import_react4.useEffect)(() => {
7320
7490
  if (!enabled) return;
7321
7491
  let cancelled = false;
7322
7492
  setIsLoading(true);
@@ -7349,6 +7519,7 @@ function useFingerprint(enabled) {
7349
7519
  useFingerprint,
7350
7520
  useFraudEngine,
7351
7521
  useOrders,
7522
+ usePlacementLimits,
7352
7523
  usePrices,
7353
7524
  useProfile,
7354
7525
  useSdk,