@superlogic/spree-pay 0.1.21 → 0.1.23

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/build/index.cjs CHANGED
@@ -62,7 +62,7 @@ var PaymentError = class extends Error {
62
62
  var PaymentType = /* @__PURE__ */ ((PaymentType2) => {
63
63
  PaymentType2["CREDIT_CARD"] = "CREDIT_CARD";
64
64
  PaymentType2["CRYPTO"] = "CRYPTO";
65
- PaymentType2["SPLIT"] = "SPLIT";
65
+ PaymentType2["CREDIT_CARD_SPLIT"] = "SPLIT";
66
66
  PaymentType2["POINTS"] = "POINTS";
67
67
  return PaymentType2;
68
68
  })(PaymentType || {});
@@ -141,48 +141,36 @@ var CONFIG = {
141
141
  bookit: {
142
142
  slapiUrl: "https://slapi.dev.superlogic.com",
143
143
  keycloakUrl: "https://auth.dev.join.bookit.com",
144
- keycloakClientId: "oneof-next",
145
- pointsConversionRatio: 100,
146
- pointsTitle: "AIR SP"
144
+ keycloakClientId: "oneof-next"
147
145
  },
148
146
  moca: {
149
147
  slapiUrl: "https://slapi.dev.air.shop",
150
148
  keycloakUrl: "https://login.dev.air.shop",
151
- keycloakClientId: "oneof-next",
152
- pointsConversionRatio: 100,
153
- pointsTitle: "AIR SP"
149
+ keycloakClientId: "oneof-next"
154
150
  }
155
151
  },
156
152
  stg: {
157
153
  bookit: {
158
154
  slapiUrl: "https://slapi.stg.superlogic.com",
159
155
  keycloakUrl: "https://auth.stg.join.bookit.com",
160
- keycloakClientId: "oneof-next",
161
- pointsConversionRatio: 100,
162
- pointsTitle: "AIR SP"
156
+ keycloakClientId: "oneof-next"
163
157
  },
164
158
  moca: {
165
159
  slapiUrl: "https://slapi.stg.air.shop",
166
160
  keycloakUrl: "https://login.stg.air.shop",
167
- keycloakClientId: "oneof-next",
168
- pointsConversionRatio: 100,
169
- pointsTitle: "AIR SP"
161
+ keycloakClientId: "oneof-next"
170
162
  }
171
163
  },
172
164
  prod: {
173
165
  bookit: {
174
166
  slapiUrl: "https://slapi.superlogic.com",
175
167
  keycloakUrl: "https://auth.join.bookit.com",
176
- keycloakClientId: "oneof-next",
177
- pointsConversionRatio: 100,
178
- pointsTitle: "AIR SP"
168
+ keycloakClientId: "oneof-next"
179
169
  },
180
170
  moca: {
181
171
  slapiUrl: "https://slapi.air.shop",
182
172
  keycloakUrl: "https://login.air.shop",
183
- keycloakClientId: "oneof-next",
184
- pointsConversionRatio: 100,
185
- pointsTitle: "AIR SP"
173
+ keycloakClientId: "oneof-next"
186
174
  }
187
175
  }
188
176
  };
@@ -210,7 +198,20 @@ var useStaticConfig = () => {
210
198
  var import_swr = __toESM(require("swr"), 1);
211
199
  var useSpreePayConfig = () => {
212
200
  const { data, isLoading } = (0, import_swr.default)("/v1/tenants/configs/spree-pay");
213
- return { spreePayConfig: data, configIsLoading: isLoading };
201
+ return {
202
+ spreePayConfig: data ? {
203
+ ...data,
204
+ rainbowProjectId: data.rainbowProjectId ?? "3fdcd5ff50cb84917cd05e40146975d8",
205
+ rainbowAppName: data.rainbowAppName ?? "AIR Shop",
206
+ pointsTitle: data.pointsTitle ?? "AIR SP",
207
+ pointsConversionRatio: data.pointsConversionRatio ?? 100,
208
+ crypto: {
209
+ ...data.crypto,
210
+ oneInchAggregationRouter: data.crypto?.oneInchAggregationRouter || "0x111111125421ca6dc452d289314280a0f8842a65"
211
+ }
212
+ } : null,
213
+ configIsLoading: isLoading
214
+ };
214
215
  };
215
216
 
216
217
  // src/lib/utils.ts
@@ -277,7 +278,7 @@ var formatUSD = (amount, currency = "USD") => {
277
278
  }).format(amount);
278
279
  return formattedAmount;
279
280
  };
280
- var formatPoints = (amount, pointsTitle = "Pts") => {
281
+ var formatPoints = (amount, pointsTitle = "") => {
281
282
  const formattedAmount = new Intl.NumberFormat("en-US", {
282
283
  notation: "compact",
283
284
  style: "decimal",
@@ -297,7 +298,7 @@ var formatCoin = (amount, currency = "USDC") => {
297
298
 
298
299
  // src/utils/split.ts
299
300
  var getSplitAmount = (amount, splitTokens, pointsConversionRatio) => {
300
- if (!Number.isFinite(amount) || !Number.isFinite(splitTokens) || !Number.isFinite(pointsConversionRatio)) {
301
+ if (!Number.isFinite(amount) || !Number.isFinite(splitTokens) || !pointsConversionRatio || !Number.isFinite(pointsConversionRatio)) {
301
302
  return amount;
302
303
  }
303
304
  if (pointsConversionRatio <= 0) return amount;
@@ -319,13 +320,13 @@ var getTransactionFee = (amount = 0, transactionFeePercentage) => {
319
320
  // src/components/CheckoutButton.tsx
320
321
  var import_jsx_runtime4 = require("react/jsx-runtime");
321
322
  var CheckoutButton = ({ isLoggedIn }) => {
322
- const { staticConfig, appProps } = useStaticConfig();
323
+ const { appProps } = useStaticConfig();
323
324
  const { amount, onProcess, isProcessing, transactionFeePercentage } = appProps;
324
325
  const { spreePayConfig } = useSpreePayConfig();
325
- const { pointsTitle, pointsConversionRatio } = staticConfig;
326
326
  const { selectedPaymentMethod, isInternalProcessing } = useSpreePaymentMethod();
327
327
  const { splitAmount, type, method } = selectedPaymentMethod;
328
- const isDisabled = !amount || !method || !!isProcessing || isInternalProcessing || !isLoggedIn;
328
+ const usdAmount = getSplitAmount(amount ?? 0, splitAmount ?? 0, spreePayConfig?.pointsConversionRatio);
329
+ const isDisabled = !amount || !method && usdAmount !== 0 || !!isProcessing || isInternalProcessing || !isLoggedIn;
329
330
  const isCC = type === "CREDIT_CARD" /* CREDIT_CARD */;
330
331
  const isCrypto = type === "CRYPTO" /* CRYPTO */;
331
332
  const getCheckoutContent = () => {
@@ -333,15 +334,14 @@ var CheckoutButton = ({ isLoggedIn }) => {
333
334
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Spinner, { className: "inline", size: "sm" });
334
335
  }
335
336
  if (isCC && amount) {
336
- const usdAmount = getSplitAmount(amount, splitAmount ?? 0, pointsConversionRatio);
337
337
  if (splitAmount && usdAmount) {
338
- return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))} + ${formatPoints(splitAmount, pointsTitle)}`;
338
+ return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))} + ${formatPoints(splitAmount, spreePayConfig?.pointsTitle)}`;
339
339
  }
340
340
  if (usdAmount) {
341
341
  return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))}`;
342
342
  }
343
343
  if (splitAmount) {
344
- return `Pay ${formatPoints(splitAmount, pointsTitle)}`;
344
+ return `Pay ${formatPoints(splitAmount, spreePayConfig?.pointsTitle)}`;
345
345
  }
346
346
  return "Checkout";
347
347
  }
@@ -394,7 +394,7 @@ var SpreeLegal = () => {
394
394
  // src/components/CreditCardTab/CreditCardTab.tsx
395
395
  var import_react13 = require("react");
396
396
 
397
- // src/hooks/useCardPayment.ts
397
+ // src/hooks/payments/useCardPayment.ts
398
398
  var import_nice_modal_react2 = __toESM(require("@ebay/nice-modal-react"), 1);
399
399
 
400
400
  // src/modals/Iframe3ds.tsx
@@ -629,17 +629,8 @@ var registerApi = (config) => {
629
629
 
630
630
  // src/services/slapi.ts
631
631
  var SlapiPaymentService = {
632
- createPayment: (params) => {
633
- const { type, hash, metadata, capture = false } = params;
634
- let reqParams;
635
- if (type === "CRYPTO" /* CRYPTO */) {
636
- reqParams = { type, hash, crypto: params.crypto };
637
- } else if (type === "CREDIT_CARD" /* CREDIT_CARD */ && params.points && params.points.amount > 0) {
638
- reqParams = { type: "SPLIT" /* SPLIT */, hash, card: params.card, points: params.points };
639
- } else {
640
- reqParams = { type, hash, card: params.card };
641
- }
642
- return slapiApi.post("/v1/payments", { ...reqParams, capture, metadata }).then((data) => ({ data }));
632
+ createPayment: ({ capture = false, ...rest }) => {
633
+ return slapiApi.post("/v1/payments", { ...rest, capture }).then((data) => ({ data }));
643
634
  },
644
635
  baseVerify: ({ id, txHash }) => {
645
636
  return slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, { txHash });
@@ -658,7 +649,7 @@ var SlapiPaymentService = {
658
649
  }
659
650
  };
660
651
 
661
- // src/hooks/useCardPayment.ts
652
+ // src/hooks/payments/useCardPayment.ts
662
653
  var useCardPayment = () => {
663
654
  const { selectedPaymentMethod } = useSpreePaymentMethod();
664
655
  const { env } = useSpreePayEnv();
@@ -707,20 +698,6 @@ var useCardPayment = () => {
707
698
  return { cardPayment };
708
699
  };
709
700
 
710
- // src/hooks/useCards.ts
711
- var import_swr2 = __toESM(require("swr"), 1);
712
- var useCards = () => {
713
- const { data, isLoading, mutate } = (0, import_swr2.default)(`/v1/payments/cards`);
714
- return {
715
- cards: data?.data.filter((c) => c.active) || [],
716
- cardsIsLoading: isLoading,
717
- mutateCards: mutate
718
- };
719
- };
720
-
721
- // src/hooks/useSplitCardPayments.ts
722
- var import_nice_modal_react3 = __toESM(require("@ebay/nice-modal-react"), 1);
723
-
724
701
  // src/services/AirWalletService.ts
725
702
  var import_airkit = require("@mocanetwork/airkit");
726
703
  var import_viem = require("viem");
@@ -812,7 +789,8 @@ async function handleSendErc20(params) {
812
789
  }
813
790
  }
814
791
 
815
- // src/hooks/useSplitCardPayments.ts
792
+ // src/hooks/payments/utils.ts
793
+ var import_nice_modal_react3 = __toESM(require("@ebay/nice-modal-react"), 1);
816
794
  var REFRESH_INTERVAL = 3 * 1e3;
817
795
  var MAX_RETRIES = 10;
818
796
  async function longPollPoints(paymentId) {
@@ -853,10 +831,55 @@ async function longPollCardStatus(paymentId) {
853
831
  }
854
832
  throw new Error("Payment polling timed out");
855
833
  }
834
+
835
+ // src/hooks/payments/usePointsPayment.ts
836
+ var usePointsPayment = () => {
837
+ const { selectedPaymentMethod } = useSpreePaymentMethod();
838
+ const { spreePayConfig } = useSpreePayConfig();
839
+ const pointsPayment = async (params) => {
840
+ if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */) {
841
+ throw new Error("Unsupported payment method");
842
+ }
843
+ const { hash, capture, metadata } = params;
844
+ const { data: paymentResData } = await SlapiPaymentService.createPayment({
845
+ hash,
846
+ capture,
847
+ metadata,
848
+ type: "POINTS" /* POINTS */
849
+ });
850
+ const wallet = peekAirWallet();
851
+ if (!wallet || !spreePayConfig?.pointsChain) {
852
+ throw new Error("AirWallet not found");
853
+ }
854
+ const transaction = await handleSendErc20({
855
+ amount: params.points,
856
+ token: spreePayConfig.pointsChain.pointsCoin,
857
+ recipient: spreePayConfig.pointsChain.recipientAddress
858
+ });
859
+ if (!transaction) {
860
+ throw new Error("Points transaction failed");
861
+ }
862
+ await SlapiPaymentService.validatePoints({
863
+ paymentId: paymentResData.id,
864
+ txHash: transaction.txHash
865
+ });
866
+ const pointsStatus = await longPollPoints(paymentResData.id);
867
+ return {
868
+ status: pointsStatus,
869
+ txId: paymentResData.txId,
870
+ txHash: transaction.txHash,
871
+ paymentId: paymentResData.id,
872
+ paymentType: "POINTS" /* POINTS */
873
+ };
874
+ };
875
+ return { pointsPayment };
876
+ };
877
+
878
+ // src/hooks/payments/useSplitCardPayments.ts
856
879
  var useSplitCardPayments = () => {
857
880
  const { selectedPaymentMethod } = useSpreePaymentMethod();
858
881
  const { env } = useSpreePayEnv();
859
- const { appProps, staticConfig } = useStaticConfig();
882
+ const { appProps } = useStaticConfig();
860
883
  const { spreePayConfig } = useSpreePayConfig();
861
884
  const splitPayment = async (params) => {
862
885
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method || !params.points) {
@@ -871,13 +894,13 @@ var useSplitCardPayments = () => {
871
894
  } else {
872
895
  cardId = card.id;
873
896
  }
874
- const usdAmount = getSplitAmount(appProps.amount ?? 0, points, staticConfig.pointsConversionRatio);
897
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, points, spreePayConfig?.pointsConversionRatio);
875
898
  const transactionFee = getTransactionFee(usdAmount, appProps.transactionFeePercentage);
876
899
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
877
900
  hash,
878
901
  capture,
879
902
  metadata,
880
- type: "CREDIT_CARD" /* CREDIT_CARD */,
903
+ type: "SPLIT" /* CREDIT_CARD_SPLIT */,
881
904
  card: {
882
905
  cardId,
883
906
  transactionFee,
@@ -906,7 +929,7 @@ var useSplitCardPayments = () => {
906
929
  });
907
930
  const pointsStatus = await longPollPoints(paymentResData.id);
908
931
  return {
909
- paymentType: "SPLIT" /* SPLIT */,
932
+ paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
910
933
  status: pointsStatus,
911
934
  paymentId: paymentResData.id,
912
935
  txId: paymentResData.txId,
@@ -916,6 +939,17 @@ var useSplitCardPayments = () => {
916
939
  return { splitPayment };
917
940
  };
918
941
 
942
+ // src/hooks/useCards.ts
943
+ var import_swr2 = __toESM(require("swr"), 1);
944
+ var useCards = () => {
945
+ const { data, isLoading, mutate } = (0, import_swr2.default)(`/v1/payments/cards`);
946
+ return {
947
+ cards: data?.data.filter((c) => c.active) || [],
948
+ cardsIsLoading: isLoading,
949
+ mutateCards: mutate
950
+ };
951
+ };
952
+
919
953
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
920
954
  var import_react6 = require("react");
921
955
  var import_react_stripe_js2 = require("@stripe/react-stripe-js");
@@ -1269,24 +1303,35 @@ function Switch({ className, ...props }) {
1269
1303
  // src/components/common/PointsSwitch.tsx
1270
1304
  var import_jsx_runtime15 = require("react/jsx-runtime");
1271
1305
  var PointsSwitch = (props) => {
1272
- const { disabled = false, value, onChange } = props;
1273
- const { staticConfig } = useStaticConfig();
1274
- const { pointsConversionRatio, pointsTitle } = staticConfig;
1306
+ const { disabled = false, value, onChange, message } = props;
1307
+ const { spreePayConfig } = useSpreePayConfig();
1275
1308
  const { balance } = useSlapiBalance();
1276
1309
  const id = (0, import_react7.useId)();
1277
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
1278
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-3", children: [
1279
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
1280
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
1281
- "Use Points ",
1282
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs font-medium", children: "Optional" })
1283
- ] })
1310
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-6", children: [
1311
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
1312
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-3", children: [
1313
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
1314
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
1315
+ "Use Points ",
1316
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs font-medium", children: "Optional" })
1317
+ ] })
1318
+ ] }),
1319
+ balance?.availablePoints ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
1320
+ formatPoints(balance.availablePoints, spreePayConfig?.pointsTitle),
1321
+ " ",
1322
+ !!spreePayConfig?.pointsConversionRatio && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / spreePayConfig.pointsConversionRatio) })
1323
+ ] }) : null
1284
1324
  ] }),
1285
- balance?.availablePoints ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
1286
- formatPoints(balance.availablePoints, pointsTitle),
1287
- " ",
1288
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
1289
- ] }) : null
1325
+ message && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-start gap-1 rounded-sm border-1 border-[#006FD533] bg-[#006FD50D] p-1.5", children: [
1326
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("svg", { className: "size-5 shrink-0", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1327
+ "path",
1328
+ {
1329
+ fill: "#000",
1330
+ d: "M9.6 13.8h.8V9.2h-.8zM10 8q.2 0 .4-.2l.1-.3-.1-.4L10 7l-.4.1-.1.4.1.3zm0 9.5a7 7 0 0 1-5.3-2.2 8 8 0 0 1-1.6-8.2 8 8 0 0 1 4-4q1.4-.6 2.9-.6a7 7 0 0 1 5.3 2.2 8 8 0 0 1 1.6 8.2 8 8 0 0 1-4 4q-1.4.6-2.9.6m0-.8q2.8 0 4.7-2 2-1.9 2-4.7t-2-4.7a6 6 0 0 0-4.7-2q-2.8 0-4.7 2a6 6 0 0 0-2 4.7q0 2.8 2 4.7 1.9 2 4.7 2"
1331
+ }
1332
+ ) }),
1333
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-xs font-medium text-black", children: message })
1334
+ ] })
1290
1335
  ] });
1291
1336
  };
1292
1337
 
@@ -2290,12 +2335,14 @@ var PointsSelector = (props) => {
2290
2335
  const { isDisabled, isSelected, onSelect, children } = props;
2291
2336
  const { balance } = useSlapiBalance();
2292
2337
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2293
- const { appProps, staticConfig } = useStaticConfig();
2338
+ const { appProps } = useStaticConfig();
2339
+ const { spreePayConfig } = useSpreePayConfig();
2340
+ const { pointsConversionRatio } = spreePayConfig || {};
2294
2341
  const min = 0;
2295
- const max = Math.min((appProps.amount ?? 0) * staticConfig.pointsConversionRatio, balance?.availablePoints ?? 0);
2342
+ const max = Math.min((appProps.amount ?? 0) * (pointsConversionRatio ?? 0), balance?.availablePoints ?? 0);
2296
2343
  const step = 10;
2297
2344
  const [splitTokens, setSplitTokens] = (0, import_react10.useState)(0);
2298
- const splitAmount = getSplitAmount(appProps.amount ?? 0, splitTokens, staticConfig.pointsConversionRatio);
2345
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, splitTokens, pointsConversionRatio);
2299
2346
  const handleCommit = (value) => {
2300
2347
  setSelectedPaymentMethod({ ...selectedPaymentMethod, splitAmount: value });
2301
2348
  };
@@ -2323,7 +2370,15 @@ var PointsSelector = (props) => {
2323
2370
  ] }),
2324
2371
  isSelected && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-3 pt-6 pb-2 md:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex justify-between gap-3", children: [
2325
2372
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex max-w-[100px] flex-col gap-1", children: [
2326
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Input, { readOnly: true, value: splitTokens, className: "bg-white text-center font-medium" }),
2373
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2374
+ Input,
2375
+ {
2376
+ readOnly: true,
2377
+ value: Math.round(splitTokens),
2378
+ className: "bg-white text-center font-medium",
2379
+ onClick: (e) => e.stopPropagation()
2380
+ }
2381
+ ),
2327
2382
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Points" })
2328
2383
  ] }),
2329
2384
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-full items-center pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
@@ -2332,6 +2387,7 @@ var PointsSelector = (props) => {
2332
2387
  value: [splitTokens],
2333
2388
  onValueCommit: ([v]) => handleCommit(v),
2334
2389
  onValueChange: ([v]) => setSplitTokens(v),
2390
+ onPointerDown: (e) => e.stopPropagation(),
2335
2391
  min,
2336
2392
  max,
2337
2393
  step
@@ -2342,8 +2398,9 @@ var PointsSelector = (props) => {
2342
2398
  Input,
2343
2399
  {
2344
2400
  readOnly: true,
2345
- value: formatUSD(splitAmount + getTransactionFee(splitAmount, appProps.transactionFeePercentage)),
2346
- className: "bg-white text-center font-medium"
2401
+ value: formatUSD(usdAmount + getTransactionFee(usdAmount, appProps.transactionFeePercentage)),
2402
+ className: "bg-white text-center font-medium",
2403
+ onClick: (e) => e.stopPropagation()
2347
2404
  }
2348
2405
  ),
2349
2406
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Card" })
@@ -2362,8 +2419,7 @@ var SplitBlock = (props) => {
2362
2419
  const { spreePayConfig } = useSpreePayConfig();
2363
2420
  const [address, setAddress] = (0, import_react11.useState)(null);
2364
2421
  const [walletReady, setWalletReady] = (0, import_react11.useState)(false);
2365
- const { staticConfig } = useStaticConfig();
2366
- const { pointsConversionRatio, pointsTitle } = staticConfig;
2422
+ const { pointsConversionRatio, pointsTitle } = spreePayConfig || {};
2367
2423
  const initWallet = (0, import_react11.useCallback)(
2368
2424
  async (pointsChain) => {
2369
2425
  if (!pointsChain) return;
@@ -2394,7 +2450,7 @@ var SplitBlock = (props) => {
2394
2450
  " ",
2395
2451
  formatPoints(balance.availablePoints, pointsTitle),
2396
2452
  " ",
2397
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
2453
+ pointsConversionRatio && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
2398
2454
  ] }) : null }),
2399
2455
  isBalanceLoading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-6 animate-pulse bg-gray-200" }) : !balance?.availablePoints && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-sm font-medium text-black", children: "No points available" }),
2400
2456
  address && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-sm font-medium text-black", children: address.length > 8 ? `${address.slice(0, 4)}...${address.slice(-4)}` : address })
@@ -2416,7 +2472,15 @@ var Points = () => {
2416
2472
  }
2417
2473
  };
2418
2474
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
2419
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PointsSwitch, { disabled: !spreePayConfig?.creditCard.enabled, value: usePoints, onChange: handleTogglePoints }),
2475
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2476
+ PointsSwitch,
2477
+ {
2478
+ value: usePoints,
2479
+ onChange: handleTogglePoints,
2480
+ message: spreePayConfig?.creditCard.pointsInfoMessage,
2481
+ disabled: !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points
2482
+ }
2483
+ ),
2420
2484
  usePoints && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2421
2485
  SplitBlock,
2422
2486
  {
@@ -2432,26 +2496,30 @@ var Points = () => {
2432
2496
  var import_jsx_runtime27 = require("react/jsx-runtime");
2433
2497
  var CreditCardTab = () => {
2434
2498
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2499
+ const { appProps } = useStaticConfig();
2500
+ const { spreePayConfig } = useSpreePayConfig();
2435
2501
  const { register } = useSpreePayRegister();
2436
2502
  const { mutateCards } = useCards();
2437
2503
  const { cardPayment } = useCardPayment();
2438
2504
  const { splitPayment } = useSplitCardPayments();
2505
+ const { pointsPayment } = usePointsPayment();
2439
2506
  const handlePay = (0, import_react13.useCallback)(
2440
2507
  async (data) => {
2441
2508
  try {
2442
- if (selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method) {
2443
- let res = null;
2444
- if (selectedPaymentMethod.splitAmount && selectedPaymentMethod.splitAmount > 0) {
2445
- res = await splitPayment({ ...data, points: selectedPaymentMethod.splitAmount });
2446
- } else {
2447
- res = await cardPayment(data);
2448
- }
2449
- if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
2450
- return Promise.resolve(res);
2451
- }
2452
- return Promise.reject(new PaymentError("Card payment failed", res.status));
2509
+ let res = null;
2510
+ const pointsAmount = selectedPaymentMethod.splitAmount ?? 0;
2511
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, pointsAmount, spreePayConfig?.pointsConversionRatio);
2512
+ if (usdAmount && pointsAmount) {
2513
+ res = await splitPayment({ ...data, points: pointsAmount });
2514
+ } else if (!usdAmount && pointsAmount) {
2515
+ res = await pointsPayment({ ...data, points: pointsAmount });
2516
+ } else {
2517
+ res = await cardPayment(data);
2453
2518
  }
2454
- return Promise.reject(new PaymentError("Unsupported payment method", "FAILED" /* FAILED */));
2519
+ if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
2520
+ return Promise.resolve(res);
2521
+ }
2522
+ return Promise.reject(new PaymentError("Card payment failed", res.status));
2455
2523
  } catch (_) {
2456
2524
  return Promise.reject(new PaymentError("Payment failed", "FAILED" /* FAILED */));
2457
2525
  } finally {
@@ -2459,7 +2527,16 @@ var CreditCardTab = () => {
2459
2527
  mutateCards();
2460
2528
  }
2461
2529
  },
2462
- [mutateCards, selectedPaymentMethod, setSelectedPaymentMethod, cardPayment, splitPayment]
2530
+ [
2531
+ mutateCards,
2532
+ selectedPaymentMethod,
2533
+ pointsPayment,
2534
+ appProps.amount,
2535
+ setSelectedPaymentMethod,
2536
+ cardPayment,
2537
+ splitPayment,
2538
+ spreePayConfig
2539
+ ]
2463
2540
  );
2464
2541
  (0, import_react13.useEffect)(() => {
2465
2542
  register(handlePay);
@@ -2534,7 +2611,7 @@ async function waitForTransactionReceipt(config, parameters) {
2534
2611
  // ../../node_modules/@wagmi/core/dist/esm/exports/index.js
2535
2612
  var import_viem3 = require("viem");
2536
2613
 
2537
- // src/hooks/useCryptoPayment.ts
2614
+ // src/hooks/payments/useCryptoPayment.ts
2538
2615
  var import_viem4 = require("viem");
2539
2616
  var import_wagmi = require("wagmi");
2540
2617
 
@@ -2575,17 +2652,20 @@ var BASE_TOKENS = [
2575
2652
  }
2576
2653
  ];
2577
2654
 
2578
- // src/hooks/useCryptoPayment.ts
2655
+ // src/hooks/payments/useCryptoPayment.ts
2579
2656
  var MAX_UINT256 = BigInt(2) ** BigInt(256) - BigInt(1);
2580
- var ONE_INCH_AGGREGATION_ROUTER_V6 = "0x111111125421ca6dc452d289314280a0f8842a65";
2581
2657
  var useCryptoPayment = () => {
2582
2658
  const { data: walletClient } = (0, import_wagmi.useWalletClient)();
2659
+ const { spreePayConfig } = useSpreePayConfig();
2583
2660
  const config = (0, import_wagmi.useConfig)();
2584
2661
  const { selectedPaymentMethod } = useSpreePaymentMethod();
2585
2662
  const cryptoPayment = async (params) => {
2586
2663
  if (!walletClient) {
2587
2664
  throw new Error("Wallet not connected");
2588
2665
  }
2666
+ if (!spreePayConfig) {
2667
+ throw new Error("Spree Pay config not loaded");
2668
+ }
2589
2669
  if (selectedPaymentMethod.type !== "CRYPTO" /* CRYPTO */ || !selectedPaymentMethod.method?.symbol) {
2590
2670
  throw new Error("Unsupported payment method");
2591
2671
  }
@@ -2600,14 +2680,14 @@ var useCryptoPayment = () => {
2600
2680
  address: tokenAddress,
2601
2681
  abi: import_viem4.erc20Abi,
2602
2682
  functionName: "allowance",
2603
- args: [walletClient.account.address, ONE_INCH_AGGREGATION_ROUTER_V6]
2683
+ args: [walletClient.account.address, spreePayConfig.crypto.oneInchAggregationRouter]
2604
2684
  });
2605
2685
  if (allowance <= 0n) {
2606
2686
  const result = await walletClient.writeContract({
2607
2687
  address: tokenAddress,
2608
2688
  abi: import_viem4.erc20Abi,
2609
2689
  functionName: "approve",
2610
- args: [ONE_INCH_AGGREGATION_ROUTER_V6, MAX_UINT256]
2690
+ args: [spreePayConfig.crypto.oneInchAggregationRouter, MAX_UINT256]
2611
2691
  });
2612
2692
  await waitForTransactionReceipt(config, {
2613
2693
  hash: result,
@@ -2625,7 +2705,7 @@ var useCryptoPayment = () => {
2625
2705
  token: TOKEN,
2626
2706
  publicKey: walletClient.account.address,
2627
2707
  slippageType: "fixed",
2628
- slippageBps: 0.5 * 100
2708
+ slippageBps: Math.round(0.5 * 100)
2629
2709
  }
2630
2710
  });
2631
2711
  const parsedTX = JSON.parse(paymentRes.data.encodedTx);
@@ -3172,8 +3252,8 @@ var CryptoWrapper = () => {
3172
3252
  const config = (0, import_react16.useMemo)(() => {
3173
3253
  if (!spreePayConfig) return null;
3174
3254
  return (0, import_rainbowkit2.getDefaultConfig)({
3175
- appName: spreePayConfig.rainbowAppName || "AIR Shop",
3176
- projectId: spreePayConfig.rainbowProjectId || "3fdcd5ff50cb84917cd05e40146975d8",
3255
+ appName: spreePayConfig.rainbowAppName,
3256
+ projectId: spreePayConfig.rainbowProjectId,
3177
3257
  chains: [import_chains.base],
3178
3258
  ssr: true
3179
3259
  });
@@ -3185,9 +3265,10 @@ var CryptoWrapper = () => {
3185
3265
  // src/components/CryptoTab/CryptoTab.tsx
3186
3266
  var import_jsx_runtime39 = require("react/jsx-runtime");
3187
3267
  var CryptoTab = () => {
3268
+ const { spreePayConfig } = useSpreePayConfig();
3188
3269
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
3189
3270
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-5", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(CryptoWrapper, {}) }),
3190
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(PointsSwitch, { disabled: true }) })
3271
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(PointsSwitch, { disabled: true, message: spreePayConfig?.crypto.pointsInfoMessage }) })
3191
3272
  ] });
3192
3273
  };
3193
3274
 
@@ -3239,7 +3320,7 @@ var TabButtons = (props) => {
3239
3320
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
3240
3321
  TabButton,
3241
3322
  {
3242
- isDisabled: !spreePayConfig?.creditCard.enabled,
3323
+ isDisabled: !spreePayConfig?.crypto.enabled,
3243
3324
  onClick: handleChange("CRYPTO" /* CRYPTO */),
3244
3325
  isActive: value === "CRYPTO" /* CRYPTO */,
3245
3326
  children: [
package/build/index.css CHANGED
@@ -344,6 +344,10 @@
344
344
  width: calc(var(--spacing) * 4);
345
345
  height: calc(var(--spacing) * 4);
346
346
  }
347
+ .sl-spreepay .size-5 {
348
+ width: calc(var(--spacing) * 5);
349
+ height: calc(var(--spacing) * 5);
350
+ }
347
351
  .sl-spreepay .size-6 {
348
352
  width: calc(var(--spacing) * 6);
349
353
  height: calc(var(--spacing) * 6);
@@ -507,6 +511,9 @@
507
511
  .sl-spreepay .items-center {
508
512
  align-items: center;
509
513
  }
514
+ .sl-spreepay .items-start {
515
+ align-items: flex-start;
516
+ }
510
517
  .sl-spreepay .justify-between {
511
518
  justify-content: space-between;
512
519
  }
@@ -591,6 +598,9 @@
591
598
  border-left-style: var(--tw-border-style) !important;
592
599
  border-left-width: 0px !important;
593
600
  }
601
+ .sl-spreepay .border-\[\#006FD533\] {
602
+ border-color: #006FD533;
603
+ }
594
604
  .sl-spreepay .border-\[\#F5F7FA\] {
595
605
  border-color: #F5F7FA;
596
606
  }
@@ -630,6 +640,9 @@
630
640
  .sl-spreepay .border-transparent {
631
641
  border-color: transparent;
632
642
  }
643
+ .sl-spreepay .bg-\[\#006FD50D\] {
644
+ background-color: #006FD50D;
645
+ }
633
646
  .sl-spreepay .bg-\[\#F5F7FA\] {
634
647
  background-color: #F5F7FA;
635
648
  }
@@ -699,6 +712,9 @@
699
712
  .sl-spreepay .p-1 {
700
713
  padding: calc(var(--spacing) * 1);
701
714
  }
715
+ .sl-spreepay .p-1\.5 {
716
+ padding: calc(var(--spacing) * 1.5);
717
+ }
702
718
  .sl-spreepay .p-6 {
703
719
  padding: calc(var(--spacing) * 6);
704
720
  }
package/build/index.d.cts CHANGED
@@ -50,7 +50,7 @@ type Card = {
50
50
  active: boolean;
51
51
  addressZipCheck: string;
52
52
  cardId: string;
53
- createdAt: Date;
53
+ createdAt: string | Date;
54
54
  default: boolean;
55
55
  expireMonth: string;
56
56
  expireYear: string;
@@ -62,7 +62,7 @@ type Card = {
62
62
  name: string;
63
63
  paymentProvider: string;
64
64
  schema: string | undefined;
65
- updatedAt: Date;
65
+ updatedAt: string | Date;
66
66
  userId: string;
67
67
  zipCode: string;
68
68
  };
@@ -84,10 +84,10 @@ type SelectedPaymentMethod = CardPaymentMethod | CryptoPaymentMethod;
84
84
  declare enum PaymentType {
85
85
  CREDIT_CARD = "CREDIT_CARD",
86
86
  CRYPTO = "CRYPTO",
87
- SPLIT = "SPLIT",
87
+ CREDIT_CARD_SPLIT = "SPLIT",
88
88
  POINTS = "POINTS"
89
89
  }
90
- declare const enum SlapiPaymentStatus {
90
+ declare enum SlapiPaymentStatus {
91
91
  NOT_INITIALIZED = "NOT_INITIALIZED",// back-end only
92
92
  PENDING = "PENDING",// back-end only
93
93
  AUTHORIZED = "AUTHORIZED",// success
package/build/index.d.ts CHANGED
@@ -50,7 +50,7 @@ type Card = {
50
50
  active: boolean;
51
51
  addressZipCheck: string;
52
52
  cardId: string;
53
- createdAt: Date;
53
+ createdAt: string | Date;
54
54
  default: boolean;
55
55
  expireMonth: string;
56
56
  expireYear: string;
@@ -62,7 +62,7 @@ type Card = {
62
62
  name: string;
63
63
  paymentProvider: string;
64
64
  schema: string | undefined;
65
- updatedAt: Date;
65
+ updatedAt: string | Date;
66
66
  userId: string;
67
67
  zipCode: string;
68
68
  };
@@ -84,10 +84,10 @@ type SelectedPaymentMethod = CardPaymentMethod | CryptoPaymentMethod;
84
84
  declare enum PaymentType {
85
85
  CREDIT_CARD = "CREDIT_CARD",
86
86
  CRYPTO = "CRYPTO",
87
- SPLIT = "SPLIT",
87
+ CREDIT_CARD_SPLIT = "SPLIT",
88
88
  POINTS = "POINTS"
89
89
  }
90
- declare const enum SlapiPaymentStatus {
90
+ declare enum SlapiPaymentStatus {
91
91
  NOT_INITIALIZED = "NOT_INITIALIZED",// back-end only
92
92
  PENDING = "PENDING",// back-end only
93
93
  AUTHORIZED = "AUTHORIZED",// success
package/build/index.js CHANGED
@@ -22,7 +22,7 @@ var PaymentError = class extends Error {
22
22
  var PaymentType = /* @__PURE__ */ ((PaymentType2) => {
23
23
  PaymentType2["CREDIT_CARD"] = "CREDIT_CARD";
24
24
  PaymentType2["CRYPTO"] = "CRYPTO";
25
- PaymentType2["SPLIT"] = "SPLIT";
25
+ PaymentType2["CREDIT_CARD_SPLIT"] = "SPLIT";
26
26
  PaymentType2["POINTS"] = "POINTS";
27
27
  return PaymentType2;
28
28
  })(PaymentType || {});
@@ -101,48 +101,36 @@ var CONFIG = {
101
101
  bookit: {
102
102
  slapiUrl: "https://slapi.dev.superlogic.com",
103
103
  keycloakUrl: "https://auth.dev.join.bookit.com",
104
- keycloakClientId: "oneof-next",
105
- pointsConversionRatio: 100,
106
- pointsTitle: "AIR SP"
104
+ keycloakClientId: "oneof-next"
107
105
  },
108
106
  moca: {
109
107
  slapiUrl: "https://slapi.dev.air.shop",
110
108
  keycloakUrl: "https://login.dev.air.shop",
111
- keycloakClientId: "oneof-next",
112
- pointsConversionRatio: 100,
113
- pointsTitle: "AIR SP"
109
+ keycloakClientId: "oneof-next"
114
110
  }
115
111
  },
116
112
  stg: {
117
113
  bookit: {
118
114
  slapiUrl: "https://slapi.stg.superlogic.com",
119
115
  keycloakUrl: "https://auth.stg.join.bookit.com",
120
- keycloakClientId: "oneof-next",
121
- pointsConversionRatio: 100,
122
- pointsTitle: "AIR SP"
116
+ keycloakClientId: "oneof-next"
123
117
  },
124
118
  moca: {
125
119
  slapiUrl: "https://slapi.stg.air.shop",
126
120
  keycloakUrl: "https://login.stg.air.shop",
127
- keycloakClientId: "oneof-next",
128
- pointsConversionRatio: 100,
129
- pointsTitle: "AIR SP"
121
+ keycloakClientId: "oneof-next"
130
122
  }
131
123
  },
132
124
  prod: {
133
125
  bookit: {
134
126
  slapiUrl: "https://slapi.superlogic.com",
135
127
  keycloakUrl: "https://auth.join.bookit.com",
136
- keycloakClientId: "oneof-next",
137
- pointsConversionRatio: 100,
138
- pointsTitle: "AIR SP"
128
+ keycloakClientId: "oneof-next"
139
129
  },
140
130
  moca: {
141
131
  slapiUrl: "https://slapi.air.shop",
142
132
  keycloakUrl: "https://login.air.shop",
143
- keycloakClientId: "oneof-next",
144
- pointsConversionRatio: 100,
145
- pointsTitle: "AIR SP"
133
+ keycloakClientId: "oneof-next"
146
134
  }
147
135
  }
148
136
  };
@@ -170,7 +158,20 @@ var useStaticConfig = () => {
170
158
  import useSWR from "swr";
171
159
  var useSpreePayConfig = () => {
172
160
  const { data, isLoading } = useSWR("/v1/tenants/configs/spree-pay");
173
- return { spreePayConfig: data, configIsLoading: isLoading };
161
+ return {
162
+ spreePayConfig: data ? {
163
+ ...data,
164
+ rainbowProjectId: data.rainbowProjectId ?? "3fdcd5ff50cb84917cd05e40146975d8",
165
+ rainbowAppName: data.rainbowAppName ?? "AIR Shop",
166
+ pointsTitle: data.pointsTitle ?? "AIR SP",
167
+ pointsConversionRatio: data.pointsConversionRatio ?? 100,
168
+ crypto: {
169
+ ...data.crypto,
170
+ oneInchAggregationRouter: data.crypto?.oneInchAggregationRouter || "0x111111125421ca6dc452d289314280a0f8842a65"
171
+ }
172
+ } : null,
173
+ configIsLoading: isLoading
174
+ };
174
175
  };
175
176
 
176
177
  // src/lib/utils.ts
@@ -237,7 +238,7 @@ var formatUSD = (amount, currency = "USD") => {
237
238
  }).format(amount);
238
239
  return formattedAmount;
239
240
  };
240
- var formatPoints = (amount, pointsTitle = "Pts") => {
241
+ var formatPoints = (amount, pointsTitle = "") => {
241
242
  const formattedAmount = new Intl.NumberFormat("en-US", {
242
243
  notation: "compact",
243
244
  style: "decimal",
@@ -257,7 +258,7 @@ var formatCoin = (amount, currency = "USDC") => {
257
258
 
258
259
  // src/utils/split.ts
259
260
  var getSplitAmount = (amount, splitTokens, pointsConversionRatio) => {
260
- if (!Number.isFinite(amount) || !Number.isFinite(splitTokens) || !Number.isFinite(pointsConversionRatio)) {
261
+ if (!Number.isFinite(amount) || !Number.isFinite(splitTokens) || !pointsConversionRatio || !Number.isFinite(pointsConversionRatio)) {
261
262
  return amount;
262
263
  }
263
264
  if (pointsConversionRatio <= 0) return amount;
@@ -279,13 +280,13 @@ var getTransactionFee = (amount = 0, transactionFeePercentage) => {
279
280
  // src/components/CheckoutButton.tsx
280
281
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
281
282
  var CheckoutButton = ({ isLoggedIn }) => {
282
- const { staticConfig, appProps } = useStaticConfig();
283
+ const { appProps } = useStaticConfig();
283
284
  const { amount, onProcess, isProcessing, transactionFeePercentage } = appProps;
284
285
  const { spreePayConfig } = useSpreePayConfig();
285
- const { pointsTitle, pointsConversionRatio } = staticConfig;
286
286
  const { selectedPaymentMethod, isInternalProcessing } = useSpreePaymentMethod();
287
287
  const { splitAmount, type, method } = selectedPaymentMethod;
288
- const isDisabled = !amount || !method || !!isProcessing || isInternalProcessing || !isLoggedIn;
288
+ const usdAmount = getSplitAmount(amount ?? 0, splitAmount ?? 0, spreePayConfig?.pointsConversionRatio);
289
+ const isDisabled = !amount || !method && usdAmount !== 0 || !!isProcessing || isInternalProcessing || !isLoggedIn;
289
290
  const isCC = type === "CREDIT_CARD" /* CREDIT_CARD */;
290
291
  const isCrypto = type === "CRYPTO" /* CRYPTO */;
291
292
  const getCheckoutContent = () => {
@@ -293,15 +294,14 @@ var CheckoutButton = ({ isLoggedIn }) => {
293
294
  return /* @__PURE__ */ jsx4(Spinner, { className: "inline", size: "sm" });
294
295
  }
295
296
  if (isCC && amount) {
296
- const usdAmount = getSplitAmount(amount, splitAmount ?? 0, pointsConversionRatio);
297
297
  if (splitAmount && usdAmount) {
298
- return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))} + ${formatPoints(splitAmount, pointsTitle)}`;
298
+ return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))} + ${formatPoints(splitAmount, spreePayConfig?.pointsTitle)}`;
299
299
  }
300
300
  if (usdAmount) {
301
301
  return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))}`;
302
302
  }
303
303
  if (splitAmount) {
304
- return `Pay ${formatPoints(splitAmount, pointsTitle)}`;
304
+ return `Pay ${formatPoints(splitAmount, spreePayConfig?.pointsTitle)}`;
305
305
  }
306
306
  return "Checkout";
307
307
  }
@@ -354,7 +354,7 @@ var SpreeLegal = () => {
354
354
  // src/components/CreditCardTab/CreditCardTab.tsx
355
355
  import { useCallback as useCallback5, useEffect as useEffect7 } from "react";
356
356
 
357
- // src/hooks/useCardPayment.ts
357
+ // src/hooks/payments/useCardPayment.ts
358
358
  import NiceModal2 from "@ebay/nice-modal-react";
359
359
 
360
360
  // src/modals/Iframe3ds.tsx
@@ -589,17 +589,8 @@ var registerApi = (config) => {
589
589
 
590
590
  // src/services/slapi.ts
591
591
  var SlapiPaymentService = {
592
- createPayment: (params) => {
593
- const { type, hash, metadata, capture = false } = params;
594
- let reqParams;
595
- if (type === "CRYPTO" /* CRYPTO */) {
596
- reqParams = { type, hash, crypto: params.crypto };
597
- } else if (type === "CREDIT_CARD" /* CREDIT_CARD */ && params.points && params.points.amount > 0) {
598
- reqParams = { type: "SPLIT" /* SPLIT */, hash, card: params.card, points: params.points };
599
- } else {
600
- reqParams = { type, hash, card: params.card };
601
- }
602
- return slapiApi.post("/v1/payments", { ...reqParams, capture, metadata }).then((data) => ({ data }));
592
+ createPayment: ({ capture = false, ...rest }) => {
593
+ return slapiApi.post("/v1/payments", { ...rest, capture }).then((data) => ({ data }));
603
594
  },
604
595
  baseVerify: ({ id, txHash }) => {
605
596
  return slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, { txHash });
@@ -618,7 +609,7 @@ var SlapiPaymentService = {
618
609
  }
619
610
  };
620
611
 
621
- // src/hooks/useCardPayment.ts
612
+ // src/hooks/payments/useCardPayment.ts
622
613
  var useCardPayment = () => {
623
614
  const { selectedPaymentMethod } = useSpreePaymentMethod();
624
615
  const { env } = useSpreePayEnv();
@@ -667,20 +658,6 @@ var useCardPayment = () => {
667
658
  return { cardPayment };
668
659
  };
669
660
 
670
- // src/hooks/useCards.ts
671
- import useSWR2 from "swr";
672
- var useCards = () => {
673
- const { data, isLoading, mutate } = useSWR2(`/v1/payments/cards`);
674
- return {
675
- cards: data?.data.filter((c) => c.active) || [],
676
- cardsIsLoading: isLoading,
677
- mutateCards: mutate
678
- };
679
- };
680
-
681
- // src/hooks/useSplitCardPayments.ts
682
- import NiceModal3 from "@ebay/nice-modal-react";
683
-
684
661
  // src/services/AirWalletService.ts
685
662
  import { AirService, BUILD_ENV } from "@mocanetwork/airkit";
686
663
  import { createWalletClient, custom, encodeFunctionData, erc20Abi, parseUnits } from "viem";
@@ -772,7 +749,8 @@ async function handleSendErc20(params) {
772
749
  }
773
750
  }
774
751
 
775
- // src/hooks/useSplitCardPayments.ts
752
+ // src/hooks/payments/utils.ts
753
+ import NiceModal3 from "@ebay/nice-modal-react";
776
754
  var REFRESH_INTERVAL = 3 * 1e3;
777
755
  var MAX_RETRIES = 10;
778
756
  async function longPollPoints(paymentId) {
@@ -813,10 +791,55 @@ async function longPollCardStatus(paymentId) {
813
791
  }
814
792
  throw new Error("Payment polling timed out");
815
793
  }
794
+
795
+ // src/hooks/payments/usePointsPayment.ts
796
+ var usePointsPayment = () => {
797
+ const { selectedPaymentMethod } = useSpreePaymentMethod();
798
+ const { spreePayConfig } = useSpreePayConfig();
799
+ const pointsPayment = async (params) => {
800
+ if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */) {
801
+ throw new Error("Unsupported payment method");
802
+ }
803
+ const { hash, capture, metadata } = params;
804
+ const { data: paymentResData } = await SlapiPaymentService.createPayment({
805
+ hash,
806
+ capture,
807
+ metadata,
808
+ type: "POINTS" /* POINTS */
809
+ });
810
+ const wallet = peekAirWallet();
811
+ if (!wallet || !spreePayConfig?.pointsChain) {
812
+ throw new Error("AirWallet not found");
813
+ }
814
+ const transaction = await handleSendErc20({
815
+ amount: params.points,
816
+ token: spreePayConfig.pointsChain.pointsCoin,
817
+ recipient: spreePayConfig.pointsChain.recipientAddress
818
+ });
819
+ if (!transaction) {
820
+ throw new Error("Points transaction failed");
821
+ }
822
+ await SlapiPaymentService.validatePoints({
823
+ paymentId: paymentResData.id,
824
+ txHash: transaction.txHash
825
+ });
826
+ const pointsStatus = await longPollPoints(paymentResData.id);
827
+ return {
828
+ status: pointsStatus,
829
+ txId: paymentResData.txId,
830
+ txHash: transaction.txHash,
831
+ paymentId: paymentResData.id,
832
+ paymentType: "POINTS" /* POINTS */
833
+ };
834
+ };
835
+ return { pointsPayment };
836
+ };
837
+
838
+ // src/hooks/payments/useSplitCardPayments.ts
816
839
  var useSplitCardPayments = () => {
817
840
  const { selectedPaymentMethod } = useSpreePaymentMethod();
818
841
  const { env } = useSpreePayEnv();
819
- const { appProps, staticConfig } = useStaticConfig();
842
+ const { appProps } = useStaticConfig();
820
843
  const { spreePayConfig } = useSpreePayConfig();
821
844
  const splitPayment = async (params) => {
822
845
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method || !params.points) {
@@ -831,13 +854,13 @@ var useSplitCardPayments = () => {
831
854
  } else {
832
855
  cardId = card.id;
833
856
  }
834
- const usdAmount = getSplitAmount(appProps.amount ?? 0, points, staticConfig.pointsConversionRatio);
857
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, points, spreePayConfig?.pointsConversionRatio);
835
858
  const transactionFee = getTransactionFee(usdAmount, appProps.transactionFeePercentage);
836
859
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
837
860
  hash,
838
861
  capture,
839
862
  metadata,
840
- type: "CREDIT_CARD" /* CREDIT_CARD */,
863
+ type: "SPLIT" /* CREDIT_CARD_SPLIT */,
841
864
  card: {
842
865
  cardId,
843
866
  transactionFee,
@@ -866,7 +889,7 @@ var useSplitCardPayments = () => {
866
889
  });
867
890
  const pointsStatus = await longPollPoints(paymentResData.id);
868
891
  return {
869
- paymentType: "SPLIT" /* SPLIT */,
892
+ paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
870
893
  status: pointsStatus,
871
894
  paymentId: paymentResData.id,
872
895
  txId: paymentResData.txId,
@@ -876,6 +899,17 @@ var useSplitCardPayments = () => {
876
899
  return { splitPayment };
877
900
  };
878
901
 
902
+ // src/hooks/useCards.ts
903
+ import useSWR2 from "swr";
904
+ var useCards = () => {
905
+ const { data, isLoading, mutate } = useSWR2(`/v1/payments/cards`);
906
+ return {
907
+ cards: data?.data.filter((c) => c.active) || [],
908
+ cardsIsLoading: isLoading,
909
+ mutateCards: mutate
910
+ };
911
+ };
912
+
879
913
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
880
914
  import { useMemo as useMemo2, useState as useState4 } from "react";
881
915
  import { Elements } from "@stripe/react-stripe-js";
@@ -1229,24 +1263,35 @@ function Switch({ className, ...props }) {
1229
1263
  // src/components/common/PointsSwitch.tsx
1230
1264
  import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1231
1265
  var PointsSwitch = (props) => {
1232
- const { disabled = false, value, onChange } = props;
1233
- const { staticConfig } = useStaticConfig();
1234
- const { pointsConversionRatio, pointsTitle } = staticConfig;
1266
+ const { disabled = false, value, onChange, message } = props;
1267
+ const { spreePayConfig } = useSpreePayConfig();
1235
1268
  const { balance } = useSlapiBalance();
1236
1269
  const id = useId2();
1237
- return /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
1238
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
1239
- /* @__PURE__ */ jsx15(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
1240
- /* @__PURE__ */ jsxs9(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
1241
- "Use Points ",
1242
- /* @__PURE__ */ jsx15("span", { className: "text-xs font-medium", children: "Optional" })
1243
- ] })
1270
+ return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-6", children: [
1271
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
1272
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
1273
+ /* @__PURE__ */ jsx15(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
1274
+ /* @__PURE__ */ jsxs9(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
1275
+ "Use Points ",
1276
+ /* @__PURE__ */ jsx15("span", { className: "text-xs font-medium", children: "Optional" })
1277
+ ] })
1278
+ ] }),
1279
+ balance?.availablePoints ? /* @__PURE__ */ jsxs9("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
1280
+ formatPoints(balance.availablePoints, spreePayConfig?.pointsTitle),
1281
+ " ",
1282
+ !!spreePayConfig?.pointsConversionRatio && /* @__PURE__ */ jsx15("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / spreePayConfig.pointsConversionRatio) })
1283
+ ] }) : null
1244
1284
  ] }),
1245
- balance?.availablePoints ? /* @__PURE__ */ jsxs9("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
1246
- formatPoints(balance.availablePoints, pointsTitle),
1247
- " ",
1248
- /* @__PURE__ */ jsx15("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
1249
- ] }) : null
1285
+ message && /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-1 rounded-sm border-1 border-[#006FD533] bg-[#006FD50D] p-1.5", children: [
1286
+ /* @__PURE__ */ jsx15("svg", { className: "size-5 shrink-0", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx15(
1287
+ "path",
1288
+ {
1289
+ fill: "#000",
1290
+ d: "M9.6 13.8h.8V9.2h-.8zM10 8q.2 0 .4-.2l.1-.3-.1-.4L10 7l-.4.1-.1.4.1.3zm0 9.5a7 7 0 0 1-5.3-2.2 8 8 0 0 1-1.6-8.2 8 8 0 0 1 4-4q1.4-.6 2.9-.6a7 7 0 0 1 5.3 2.2 8 8 0 0 1 1.6 8.2 8 8 0 0 1-4 4q-1.4.6-2.9.6m0-.8q2.8 0 4.7-2 2-1.9 2-4.7t-2-4.7a6 6 0 0 0-4.7-2q-2.8 0-4.7 2a6 6 0 0 0-2 4.7q0 2.8 2 4.7 1.9 2 4.7 2"
1291
+ }
1292
+ ) }),
1293
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-medium text-black", children: message })
1294
+ ] })
1250
1295
  ] });
1251
1296
  };
1252
1297
 
@@ -2250,12 +2295,14 @@ var PointsSelector = (props) => {
2250
2295
  const { isDisabled, isSelected, onSelect, children } = props;
2251
2296
  const { balance } = useSlapiBalance();
2252
2297
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2253
- const { appProps, staticConfig } = useStaticConfig();
2298
+ const { appProps } = useStaticConfig();
2299
+ const { spreePayConfig } = useSpreePayConfig();
2300
+ const { pointsConversionRatio } = spreePayConfig || {};
2254
2301
  const min = 0;
2255
- const max = Math.min((appProps.amount ?? 0) * staticConfig.pointsConversionRatio, balance?.availablePoints ?? 0);
2302
+ const max = Math.min((appProps.amount ?? 0) * (pointsConversionRatio ?? 0), balance?.availablePoints ?? 0);
2256
2303
  const step = 10;
2257
2304
  const [splitTokens, setSplitTokens] = useState8(0);
2258
- const splitAmount = getSplitAmount(appProps.amount ?? 0, splitTokens, staticConfig.pointsConversionRatio);
2305
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, splitTokens, pointsConversionRatio);
2259
2306
  const handleCommit = (value) => {
2260
2307
  setSelectedPaymentMethod({ ...selectedPaymentMethod, splitAmount: value });
2261
2308
  };
@@ -2283,7 +2330,15 @@ var PointsSelector = (props) => {
2283
2330
  ] }),
2284
2331
  isSelected && /* @__PURE__ */ jsx24("div", { className: "px-3 pt-6 pb-2 md:px-4", children: /* @__PURE__ */ jsxs12("div", { className: "flex justify-between gap-3", children: [
2285
2332
  /* @__PURE__ */ jsxs12("div", { className: "flex max-w-[100px] flex-col gap-1", children: [
2286
- /* @__PURE__ */ jsx24(Input, { readOnly: true, value: splitTokens, className: "bg-white text-center font-medium" }),
2333
+ /* @__PURE__ */ jsx24(
2334
+ Input,
2335
+ {
2336
+ readOnly: true,
2337
+ value: Math.round(splitTokens),
2338
+ className: "bg-white text-center font-medium",
2339
+ onClick: (e) => e.stopPropagation()
2340
+ }
2341
+ ),
2287
2342
  /* @__PURE__ */ jsx24("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Points" })
2288
2343
  ] }),
2289
2344
  /* @__PURE__ */ jsx24("div", { className: "flex w-full items-center pb-6", children: /* @__PURE__ */ jsx24(
@@ -2292,6 +2347,7 @@ var PointsSelector = (props) => {
2292
2347
  value: [splitTokens],
2293
2348
  onValueCommit: ([v]) => handleCommit(v),
2294
2349
  onValueChange: ([v]) => setSplitTokens(v),
2350
+ onPointerDown: (e) => e.stopPropagation(),
2295
2351
  min,
2296
2352
  max,
2297
2353
  step
@@ -2302,8 +2358,9 @@ var PointsSelector = (props) => {
2302
2358
  Input,
2303
2359
  {
2304
2360
  readOnly: true,
2305
- value: formatUSD(splitAmount + getTransactionFee(splitAmount, appProps.transactionFeePercentage)),
2306
- className: "bg-white text-center font-medium"
2361
+ value: formatUSD(usdAmount + getTransactionFee(usdAmount, appProps.transactionFeePercentage)),
2362
+ className: "bg-white text-center font-medium",
2363
+ onClick: (e) => e.stopPropagation()
2307
2364
  }
2308
2365
  ),
2309
2366
  /* @__PURE__ */ jsx24("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Card" })
@@ -2322,8 +2379,7 @@ var SplitBlock = (props) => {
2322
2379
  const { spreePayConfig } = useSpreePayConfig();
2323
2380
  const [address, setAddress] = useState9(null);
2324
2381
  const [walletReady, setWalletReady] = useState9(false);
2325
- const { staticConfig } = useStaticConfig();
2326
- const { pointsConversionRatio, pointsTitle } = staticConfig;
2382
+ const { pointsConversionRatio, pointsTitle } = spreePayConfig || {};
2327
2383
  const initWallet = useCallback4(
2328
2384
  async (pointsChain) => {
2329
2385
  if (!pointsChain) return;
@@ -2354,7 +2410,7 @@ var SplitBlock = (props) => {
2354
2410
  " ",
2355
2411
  formatPoints(balance.availablePoints, pointsTitle),
2356
2412
  " ",
2357
- /* @__PURE__ */ jsx25("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
2413
+ pointsConversionRatio && /* @__PURE__ */ jsx25("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
2358
2414
  ] }) : null }),
2359
2415
  isBalanceLoading ? /* @__PURE__ */ jsx25("div", { className: "h-4 w-6 animate-pulse bg-gray-200" }) : !balance?.availablePoints && /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-black", children: "No points available" }),
2360
2416
  address && /* @__PURE__ */ jsx25("div", { className: "text-sm font-medium text-black", children: address.length > 8 ? `${address.slice(0, 4)}...${address.slice(-4)}` : address })
@@ -2376,7 +2432,15 @@ var Points = () => {
2376
2432
  }
2377
2433
  };
2378
2434
  return /* @__PURE__ */ jsxs14(Fragment3, { children: [
2379
- /* @__PURE__ */ jsx26(PointsSwitch, { disabled: !spreePayConfig?.creditCard.enabled, value: usePoints, onChange: handleTogglePoints }),
2435
+ /* @__PURE__ */ jsx26(
2436
+ PointsSwitch,
2437
+ {
2438
+ value: usePoints,
2439
+ onChange: handleTogglePoints,
2440
+ message: spreePayConfig?.creditCard.pointsInfoMessage,
2441
+ disabled: !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points
2442
+ }
2443
+ ),
2380
2444
  usePoints && /* @__PURE__ */ jsx26(
2381
2445
  SplitBlock,
2382
2446
  {
@@ -2392,26 +2456,30 @@ var Points = () => {
2392
2456
  import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
2393
2457
  var CreditCardTab = () => {
2394
2458
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2459
+ const { appProps } = useStaticConfig();
2460
+ const { spreePayConfig } = useSpreePayConfig();
2395
2461
  const { register } = useSpreePayRegister();
2396
2462
  const { mutateCards } = useCards();
2397
2463
  const { cardPayment } = useCardPayment();
2398
2464
  const { splitPayment } = useSplitCardPayments();
2465
+ const { pointsPayment } = usePointsPayment();
2399
2466
  const handlePay = useCallback5(
2400
2467
  async (data) => {
2401
2468
  try {
2402
- if (selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method) {
2403
- let res = null;
2404
- if (selectedPaymentMethod.splitAmount && selectedPaymentMethod.splitAmount > 0) {
2405
- res = await splitPayment({ ...data, points: selectedPaymentMethod.splitAmount });
2406
- } else {
2407
- res = await cardPayment(data);
2408
- }
2409
- if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
2410
- return Promise.resolve(res);
2411
- }
2412
- return Promise.reject(new PaymentError("Card payment failed", res.status));
2469
+ let res = null;
2470
+ const pointsAmount = selectedPaymentMethod.splitAmount ?? 0;
2471
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, pointsAmount, spreePayConfig?.pointsConversionRatio);
2472
+ if (usdAmount && pointsAmount) {
2473
+ res = await splitPayment({ ...data, points: pointsAmount });
2474
+ } else if (!usdAmount && pointsAmount) {
2475
+ res = await pointsPayment({ ...data, points: pointsAmount });
2476
+ } else {
2477
+ res = await cardPayment(data);
2413
2478
  }
2414
- return Promise.reject(new PaymentError("Unsupported payment method", "FAILED" /* FAILED */));
2479
+ if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
2480
+ return Promise.resolve(res);
2481
+ }
2482
+ return Promise.reject(new PaymentError("Card payment failed", res.status));
2415
2483
  } catch (_) {
2416
2484
  return Promise.reject(new PaymentError("Payment failed", "FAILED" /* FAILED */));
2417
2485
  } finally {
@@ -2419,7 +2487,16 @@ var CreditCardTab = () => {
2419
2487
  mutateCards();
2420
2488
  }
2421
2489
  },
2422
- [mutateCards, selectedPaymentMethod, setSelectedPaymentMethod, cardPayment, splitPayment]
2490
+ [
2491
+ mutateCards,
2492
+ selectedPaymentMethod,
2493
+ pointsPayment,
2494
+ appProps.amount,
2495
+ setSelectedPaymentMethod,
2496
+ cardPayment,
2497
+ splitPayment,
2498
+ spreePayConfig
2499
+ ]
2423
2500
  );
2424
2501
  useEffect7(() => {
2425
2502
  register(handlePay);
@@ -2494,7 +2571,7 @@ async function waitForTransactionReceipt(config, parameters) {
2494
2571
  // ../../node_modules/@wagmi/core/dist/esm/exports/index.js
2495
2572
  import { custom as custom2, http, webSocket } from "viem";
2496
2573
 
2497
- // src/hooks/useCryptoPayment.ts
2574
+ // src/hooks/payments/useCryptoPayment.ts
2498
2575
  import { erc20Abi as erc20Abi2 } from "viem";
2499
2576
  import { useConfig, useWalletClient } from "wagmi";
2500
2577
 
@@ -2535,17 +2612,20 @@ var BASE_TOKENS = [
2535
2612
  }
2536
2613
  ];
2537
2614
 
2538
- // src/hooks/useCryptoPayment.ts
2615
+ // src/hooks/payments/useCryptoPayment.ts
2539
2616
  var MAX_UINT256 = BigInt(2) ** BigInt(256) - BigInt(1);
2540
- var ONE_INCH_AGGREGATION_ROUTER_V6 = "0x111111125421ca6dc452d289314280a0f8842a65";
2541
2617
  var useCryptoPayment = () => {
2542
2618
  const { data: walletClient } = useWalletClient();
2619
+ const { spreePayConfig } = useSpreePayConfig();
2543
2620
  const config = useConfig();
2544
2621
  const { selectedPaymentMethod } = useSpreePaymentMethod();
2545
2622
  const cryptoPayment = async (params) => {
2546
2623
  if (!walletClient) {
2547
2624
  throw new Error("Wallet not connected");
2548
2625
  }
2626
+ if (!spreePayConfig) {
2627
+ throw new Error("Spree Pay config not loaded");
2628
+ }
2549
2629
  if (selectedPaymentMethod.type !== "CRYPTO" /* CRYPTO */ || !selectedPaymentMethod.method?.symbol) {
2550
2630
  throw new Error("Unsupported payment method");
2551
2631
  }
@@ -2560,14 +2640,14 @@ var useCryptoPayment = () => {
2560
2640
  address: tokenAddress,
2561
2641
  abi: erc20Abi2,
2562
2642
  functionName: "allowance",
2563
- args: [walletClient.account.address, ONE_INCH_AGGREGATION_ROUTER_V6]
2643
+ args: [walletClient.account.address, spreePayConfig.crypto.oneInchAggregationRouter]
2564
2644
  });
2565
2645
  if (allowance <= 0n) {
2566
2646
  const result = await walletClient.writeContract({
2567
2647
  address: tokenAddress,
2568
2648
  abi: erc20Abi2,
2569
2649
  functionName: "approve",
2570
- args: [ONE_INCH_AGGREGATION_ROUTER_V6, MAX_UINT256]
2650
+ args: [spreePayConfig.crypto.oneInchAggregationRouter, MAX_UINT256]
2571
2651
  });
2572
2652
  await waitForTransactionReceipt(config, {
2573
2653
  hash: result,
@@ -2585,7 +2665,7 @@ var useCryptoPayment = () => {
2585
2665
  token: TOKEN,
2586
2666
  publicKey: walletClient.account.address,
2587
2667
  slippageType: "fixed",
2588
- slippageBps: 0.5 * 100
2668
+ slippageBps: Math.round(0.5 * 100)
2589
2669
  }
2590
2670
  });
2591
2671
  const parsedTX = JSON.parse(paymentRes.data.encodedTx);
@@ -3132,8 +3212,8 @@ var CryptoWrapper = () => {
3132
3212
  const config = useMemo9(() => {
3133
3213
  if (!spreePayConfig) return null;
3134
3214
  return getDefaultConfig({
3135
- appName: spreePayConfig.rainbowAppName || "AIR Shop",
3136
- projectId: spreePayConfig.rainbowProjectId || "3fdcd5ff50cb84917cd05e40146975d8",
3215
+ appName: spreePayConfig.rainbowAppName,
3216
+ projectId: spreePayConfig.rainbowProjectId,
3137
3217
  chains: [base],
3138
3218
  ssr: true
3139
3219
  });
@@ -3145,9 +3225,10 @@ var CryptoWrapper = () => {
3145
3225
  // src/components/CryptoTab/CryptoTab.tsx
3146
3226
  import { jsx as jsx39, jsxs as jsxs23 } from "react/jsx-runtime";
3147
3227
  var CryptoTab = () => {
3228
+ const { spreePayConfig } = useSpreePayConfig();
3148
3229
  return /* @__PURE__ */ jsxs23("div", { children: [
3149
3230
  /* @__PURE__ */ jsx39("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-5", children: /* @__PURE__ */ jsx39(CryptoWrapper, {}) }),
3150
- /* @__PURE__ */ jsx39("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx39(PointsSwitch, { disabled: true }) })
3231
+ /* @__PURE__ */ jsx39("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx39(PointsSwitch, { disabled: true, message: spreePayConfig?.crypto.pointsInfoMessage }) })
3151
3232
  ] });
3152
3233
  };
3153
3234
 
@@ -3199,7 +3280,7 @@ var TabButtons = (props) => {
3199
3280
  /* @__PURE__ */ jsxs24(
3200
3281
  TabButton,
3201
3282
  {
3202
- isDisabled: !spreePayConfig?.creditCard.enabled,
3283
+ isDisabled: !spreePayConfig?.crypto.enabled,
3203
3284
  onClick: handleChange("CRYPTO" /* CRYPTO */),
3204
3285
  isActive: value === "CRYPTO" /* CRYPTO */,
3205
3286
  children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superlogic/spree-pay",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Spree-pay React component and utilities",
5
5
  "private": false,
6
6
  "type": "module",