@superlogic/spree-pay 0.1.39 → 0.1.42

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.js CHANGED
@@ -3,9 +3,6 @@ import { useCallback as useCallback9, useEffect as useEffect12, useMemo as useMe
3
3
  import NiceModal9 from "@ebay/nice-modal-react";
4
4
  import { SWRConfig } from "swr";
5
5
 
6
- // package.json
7
- var version = "0.1.39";
8
-
9
6
  // src/context/SpreePayActionsContext.tsx
10
7
  import { createContext, useCallback, useContext, useRef, useState } from "react";
11
8
 
@@ -31,8 +28,126 @@ var PaymentType = /* @__PURE__ */ ((PaymentType2) => {
31
28
  return PaymentType2;
32
29
  })(PaymentType || {});
33
30
 
31
+ // package.json
32
+ var version = "0.1.41";
33
+
34
+ // src/utils/logger.ts
35
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
36
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
37
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
38
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
39
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
40
+ LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
41
+ return LogLevel2;
42
+ })(LogLevel || {});
43
+ var Logger = class _Logger {
44
+ config;
45
+ constructor(config2 = {}) {
46
+ this.config = {
47
+ minLevel: this.getDefaultLogLevel(config2.environment),
48
+ prefix: "[spree-pay]",
49
+ ...config2
50
+ };
51
+ }
52
+ /**
53
+ * Determines default log level based on environment
54
+ * - Production: Only ERROR and version info
55
+ * - Development/Staging: All logs
56
+ */
57
+ getDefaultLogLevel(environment) {
58
+ if (typeof window === "undefined") return 1 /* INFO */;
59
+ if (environment) {
60
+ return environment === "prod" ? 3 /* ERROR */ : 0 /* DEBUG */;
61
+ }
62
+ return 3 /* ERROR */;
63
+ }
64
+ /**
65
+ * Set the environment and update log level accordingly
66
+ */
67
+ setEnvironment(environment) {
68
+ this.config.environment = environment;
69
+ this.config.minLevel = this.getDefaultLogLevel(environment);
70
+ }
71
+ shouldLog(level) {
72
+ return level >= this.config.minLevel;
73
+ }
74
+ formatMessage(level, message, context) {
75
+ const levelName = LogLevel[level];
76
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
77
+ const contextStr = context && Object.keys(context).length > 0 ? ` ${JSON.stringify(context)}` : "";
78
+ return `${this.config.prefix} [${levelName}] ${timestamp} - ${message}${contextStr}`;
79
+ }
80
+ /**
81
+ * Log debug information (only in dev/stg)
82
+ */
83
+ debug(message, context) {
84
+ if (!this.shouldLog(0 /* DEBUG */)) return;
85
+ console.log(this.formatMessage(0 /* DEBUG */, message, context));
86
+ }
87
+ /**
88
+ * Log informational messages (only in dev/stg)
89
+ */
90
+ info(message, context) {
91
+ if (!this.shouldLog(1 /* INFO */)) return;
92
+ console.log(this.formatMessage(1 /* INFO */, message, context));
93
+ }
94
+ /**
95
+ * Log warnings (only in dev/stg)
96
+ */
97
+ warn(message, context) {
98
+ if (!this.shouldLog(2 /* WARN */)) return;
99
+ console.warn(this.formatMessage(2 /* WARN */, message, context));
100
+ }
101
+ /**
102
+ * Log errors (shows in all environments)
103
+ */
104
+ error(message, error, context) {
105
+ if (!this.shouldLog(3 /* ERROR */)) return;
106
+ const errorContext = {
107
+ ...context,
108
+ ...error instanceof Error ? {
109
+ errorName: error.name,
110
+ errorMessage: error.message,
111
+ errorStack: error.stack
112
+ } : { error }
113
+ };
114
+ console.error(this.formatMessage(3 /* ERROR */, message, errorContext));
115
+ }
116
+ /**
117
+ * Always logs the version, regardless of environment
118
+ */
119
+ logVersion() {
120
+ console.log(`${this.config.prefix} v${version} - ${this.config.environment}`);
121
+ }
122
+ /**
123
+ * Creates a child logger with additional context
124
+ * Useful for component-specific logging
125
+ */
126
+ child(prefix) {
127
+ return new _Logger({
128
+ ...this.config,
129
+ prefix: `${this.config.prefix}:${prefix}`
130
+ });
131
+ }
132
+ /**
133
+ * Override log level (useful for testing or debugging)
134
+ */
135
+ setLogLevel(level) {
136
+ this.config.minLevel = level;
137
+ }
138
+ };
139
+ var logger = new Logger();
140
+ var configureLogger = (config2) => {
141
+ if (config2.environment) {
142
+ logger.setEnvironment(config2.environment);
143
+ }
144
+ const { environment, ...restConfig } = config2;
145
+ Object.assign(logger["config"], restConfig);
146
+ };
147
+
34
148
  // src/context/SpreePayActionsContext.tsx
35
149
  import { jsx } from "react/jsx-runtime";
150
+ var processLogger = logger.child("process");
36
151
  var SpreePayActionsContext = createContext(void 0);
37
152
  var SpreePayProvider = ({ children, env }) => {
38
153
  const processRef = useRef(null);
@@ -44,18 +159,43 @@ var SpreePayProvider = ({ children, env }) => {
44
159
  const register = useCallback((fn) => {
45
160
  processRef.current = fn;
46
161
  }, []);
47
- const process = useCallback(async (data) => {
48
- if (!processRef.current) throw new Error("SpreePay process function not registered");
49
- setInternalProcessing(true);
50
- try {
51
- return await processRef.current(data);
52
- } catch (e) {
53
- if (e instanceof Error) throw e;
54
- throw new PaymentError("Payment failed", "FAILED" /* FAILED */, e);
55
- } finally {
56
- setInternalProcessing(false);
57
- }
58
- }, []);
162
+ const process = useCallback(
163
+ async (data) => {
164
+ if (!processRef.current) {
165
+ const error = new Error("SpreePay process function not registered");
166
+ processLogger.error("Process function not registered", error);
167
+ throw error;
168
+ }
169
+ processLogger.info("Payment process started", {
170
+ hash: data.hash,
171
+ capture: data.capture,
172
+ hasMetadata: Boolean(data.metadata),
173
+ paymentType: selectedPaymentMethod.type
174
+ });
175
+ setInternalProcessing(true);
176
+ try {
177
+ const result = await processRef.current(data);
178
+ processLogger.info("Payment process completed", {
179
+ status: result.status,
180
+ paymentId: result.paymentId,
181
+ paymentType: result.paymentType,
182
+ txHash: result.txHash
183
+ });
184
+ return result;
185
+ } catch (e) {
186
+ processLogger.error("Payment process failed", e instanceof Error ? e : void 0, {
187
+ hash: data.hash,
188
+ paymentType: selectedPaymentMethod.type,
189
+ errorMessage: e instanceof Error ? e.message : String(e)
190
+ });
191
+ if (e instanceof Error) throw e;
192
+ throw new PaymentError("Payment failed", "FAILED" /* FAILED */, e);
193
+ } finally {
194
+ setInternalProcessing(false);
195
+ }
196
+ },
197
+ [selectedPaymentMethod.type]
198
+ );
59
199
  const value = {
60
200
  // Set default to true for web3 points to backward compatibility
61
201
  env: { ...env, useWeb3Points: env.useWeb3Points ?? true },
@@ -199,7 +339,10 @@ var StaticConfigProvider = ({ children, props }) => {
199
339
  const envConfig = config[env.environment];
200
340
  const isKnownTenant = env.tenantId in envConfig;
201
341
  if (!isKnownTenant) {
202
- console.warn(`[spree-pay] Unknown tenantId "${env.tenantId}", falling back to "moca"`);
342
+ logger.warn(`Unknown tenantId "${env.tenantId}", falling back to "moca"`, {
343
+ tenantId: env.tenantId,
344
+ environment: env.environment
345
+ });
203
346
  }
204
347
  const appKey = isKnownTenant ? env.tenantId : "moca";
205
348
  return envConfig[appKey];
@@ -548,11 +691,11 @@ var CheckoutButton = ({ isLoggedIn }) => {
548
691
  ),
549
692
  /* @__PURE__ */ jsxs5("a", { href: "https://www.spree.finance/", className: "flex items-center justify-center gap-2 hover:underline", children: [
550
693
  /* @__PURE__ */ jsx9("p", { children: "Powered by" }),
551
- /* @__PURE__ */ jsx9("svg", { className: "shrink-0", xmlns: "http://www.w3.org/2000/svg", width: "66", height: "30", fill: "none", children: /* @__PURE__ */ jsx9(
694
+ /* @__PURE__ */ jsx9("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "h-[30px]", viewBox: "0 0 66 30", children: /* @__PURE__ */ jsx9(
552
695
  "path",
553
696
  {
554
697
  fill: "currentColor",
555
- d: "M57.79 25.48a4.82 4.82 0 0 1-1.55-.25l.55-1.86c.34.1.65.15.92.15s.51-.1.72-.26c.21-.16.39-.43.53-.81l.2-.55-3.65-10.3h2.52l2.32 7.62h.1l2.34-7.62h2.53l-4.04 11.31c-.19.54-.44 1-.75 1.38-.31.38-.7.68-1.14.88-.45.2-.98.3-1.6.3ZM48.95 21.9a4.2 4.2 0 0 1-1.73-.35c-.5-.23-.9-.57-1.2-1.02a3 3 0 0 1-.44-1.67 2.44 2.44 0 0 1 1.18-2.3c.35-.23.76-.4 1.22-.5.46-.13.93-.21 1.42-.27l1.44-.16c.37-.05.64-.13.8-.24.18-.1.26-.27.26-.5v-.04c0-.5-.15-.88-.44-1.15-.3-.27-.72-.4-1.27-.4-.58 0-1.04.12-1.38.37-.34.26-.57.56-.69.9l-2.22-.31a3.54 3.54 0 0 1 2.35-2.47 6.29 6.29 0 0 1 3.38-.14c.48.1.92.3 1.32.56.4.26.72.6.96 1.06.25.44.37 1 .37 1.67v6.75h-2.29v-1.38h-.08a2.9 2.9 0 0 1-1.59 1.37c-.39.14-.84.22-1.37.22Zm.62-1.75c.48 0 .89-.1 1.24-.28.35-.2.62-.45.8-.77.2-.31.3-.65.3-1.03V16.9c-.08.06-.2.11-.38.17a18.34 18.34 0 0 1-1.8.32c-.36.05-.68.12-.96.23-.28.11-.5.27-.66.46-.16.2-.24.45-.24.75 0 .44.16.77.48 1 .32.22.72.33 1.22.33ZM34.43 21.7V8.23h5.05c1.03 0 1.9.2 2.6.58.7.38 1.23.91 1.6 1.59.36.67.54 1.43.54 2.28 0 .87-.18 1.63-.55 2.3a3.9 3.9 0 0 1-1.6 1.59c-.72.38-1.59.57-2.63.57H36.1v-2h3.01c.6 0 1.1-.11 1.49-.32.38-.21.67-.5.85-.87.2-.37.29-.79.29-1.27 0-.47-.1-.9-.29-1.26a1.92 1.92 0 0 0-.86-.84c-.38-.2-.88-.31-1.49-.31h-2.23v11.41h-2.44ZM14.54.46a14.54 14.54 0 1 1 0 29.08 14.54 14.54 0 0 1 0-29.08ZM5.59 18.12l-.84 3.35h.83l.84-3.35h-.83Zm1.66 0-.83 3.35h1.66l.84-3.35H7.25Zm3.35-9.58c-1.03 0-2.08.84-2.34 1.87l-1.1 4.4c-.26 1.03.37 1.87 1.4 1.87h9.64l-.34 1.44h-8.1l-.85 3.35h9.6c1.04 0 2.1-.85 2.35-1.89l1.05-4.4c.25-1.03-.38-1.85-1.4-1.85h-9.63l.36-1.44h8.13l.84-3.35H10.6Zm10.44 0-.84 3.35h1.67l.83-3.35h-1.66Zm2.5 0-.84 3.35h.83l.84-3.35h-.83Z"
698
+ d: "M57.79 25.48a5 5 0 0 1-1.55-.25l.55-1.86q.51.15.92.15c.41 0 .51-.1.72-.26q.32-.24.53-.81l.2-.55-3.65-10.3h2.52l2.32 7.62h.1l2.34-7.62h2.53l-4.04 11.31q-.28.81-.75 1.38t-1.14.88-1.6.3Zm-8.84-3.58a4 4 0 0 1-1.73-.35q-.75-.34-1.2-1.02a3 3 0 0 1-.44-1.67 2.4 2.4 0 0 1 1.18-2.3q.53-.35 1.22-.5.69-.19 1.42-.27l1.44-.16q.56-.08.8-.24.27-.15.26-.5v-.04q0-.75-.44-1.15-.45-.4-1.27-.4-.87 0-1.38.37-.51.39-.69.9l-2.22-.31a3.5 3.5 0 0 1 2.35-2.47 6.3 6.3 0 0 1 3.38-.14q.72.16 1.32.56.6.38.96 1.06.37.66.37 1.67v6.75h-2.29v-1.38h-.08a3 3 0 0 1-1.59 1.37q-.58.21-1.37.22m.62-1.75q.72 0 1.24-.28.53-.3.8-.77.3-.46.3-1.03V16.9q-.11.09-.38.17a18 18 0 0 1-1.8.32q-.54.07-.96.23-.42.17-.66.46t-.24.75q0 .66.48 1t1.22.33ZM34.43 21.7V8.23h5.05q1.55 0 2.6.58 1.05.57 1.6 1.59.54 1 .54 2.28 0 1.3-.55 2.3a4 4 0 0 1-1.6 1.59q-1.07.57-2.63.57H36.1v-2h3.01q.9 0 1.49-.32.57-.32.85-.87.3-.55.29-1.27 0-.71-.29-1.26a2 2 0 0 0-.86-.84 3 3 0 0 0-1.49-.31h-2.23v11.41h-2.44ZM14.54.46a14.54 14.54 0 1 1 0 29.08 14.54 14.54 0 0 1 0-29.08M5.59 18.12l-.84 3.35h.83l.84-3.35zm1.66 0-.83 3.35h1.66l.84-3.35zm3.35-9.58c-1.03 0-2.08.84-2.34 1.87l-1.1 4.4c-.26 1.03.37 1.87 1.4 1.87h9.64l-.34 1.44h-8.1l-.85 3.35h9.6c1.04 0 2.1-.85 2.35-1.89l1.05-4.4c.25-1.03-.38-1.85-1.4-1.85h-9.63l.36-1.44h8.13l.84-3.35zm10.44 0-.84 3.35h1.67l.83-3.35zm2.5 0-.84 3.35h.83l.84-3.35z"
556
699
  }
557
700
  ) })
558
701
  ] })
@@ -804,49 +947,181 @@ var registerApi = (config2) => {
804
947
  };
805
948
 
806
949
  // src/services/slapi.ts
950
+ var slapiLogger = logger.child("slapi");
807
951
  var SlapiPaymentService = {
808
- createPayment: ({ capture = false, ...rest }) => {
809
- return slapiApi.post("/v1/payments", { ...rest, capture }).then((data) => ({ data }));
952
+ createPayment: async ({ capture = false, ...rest }) => {
953
+ slapiLogger.debug("Creating payment", {
954
+ type: rest.type,
955
+ hash: rest.hash,
956
+ capture
957
+ });
958
+ try {
959
+ const data = await slapiApi.post("/v1/payments", { ...rest, capture });
960
+ slapiLogger.info("Payment created successfully", {
961
+ paymentId: data.id,
962
+ status: data.status,
963
+ txId: data.txId
964
+ });
965
+ return { data };
966
+ } catch (error) {
967
+ slapiLogger.error("Failed to create payment", error, {
968
+ type: rest.type,
969
+ hash: rest.hash
970
+ });
971
+ throw error;
972
+ }
810
973
  },
811
- baseVerify: ({ id, txHash }) => {
812
- return slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, { txHash });
974
+ baseVerify: async ({ id, txHash }) => {
975
+ slapiLogger.debug("Verifying base transaction", { id, txHash });
976
+ try {
977
+ const result = await slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, {
978
+ txHash
979
+ });
980
+ slapiLogger.info("Base transaction verified", {
981
+ id,
982
+ txHash,
983
+ verified: result.verified
984
+ });
985
+ return result;
986
+ } catch (error) {
987
+ slapiLogger.error("Base transaction verification failed", error, {
988
+ id,
989
+ txHash
990
+ });
991
+ throw error;
992
+ }
813
993
  },
814
- addCard: ({ source, hash }) => {
815
- return slapiApi.post("/v1/payments/cards", { hash, source }).then((data) => ({ data }));
994
+ addCard: async ({ source, hash }) => {
995
+ slapiLogger.debug("Adding card", { hash, sourcePrefix: source.substring(0, 10) });
996
+ try {
997
+ const data = await slapiApi.post("/v1/payments/cards", { hash, source });
998
+ slapiLogger.info("Card added successfully", { cardId: data.id, hash });
999
+ return { data };
1000
+ } catch (error) {
1001
+ slapiLogger.error("Failed to add card", error, { hash });
1002
+ throw error;
1003
+ }
816
1004
  },
817
- validate3DS: ({ paymentId }) => {
818
- return slapiApi.post("/v1/payments/validate", { paymentId, type: "CREDIT_CARD" /* CREDIT_CARD */ }).then((data) => ({ data }));
1005
+ validate3DS: async ({ paymentId }) => {
1006
+ slapiLogger.debug("Validating 3DS", { paymentId });
1007
+ try {
1008
+ const data = await slapiApi.post("/v1/payments/validate", {
1009
+ paymentId,
1010
+ type: "CREDIT_CARD" /* CREDIT_CARD */
1011
+ });
1012
+ slapiLogger.info("3DS validated successfully", {
1013
+ paymentId,
1014
+ status: data.status
1015
+ });
1016
+ return { data };
1017
+ } catch (error) {
1018
+ slapiLogger.error("3DS validation failed", error, { paymentId });
1019
+ throw error;
1020
+ }
819
1021
  },
820
- validateCDC: ({ paymentId }) => {
821
- return slapiApi.post("/v1/payments/validate", { paymentId, type: "CDC" /* CDC */ }).then((data) => ({ data }));
1022
+ validateCDC: async ({ paymentId }) => {
1023
+ slapiLogger.debug("Validating CDC payment", { paymentId });
1024
+ try {
1025
+ const data = await slapiApi.post("/v1/payments/validate", {
1026
+ paymentId,
1027
+ type: "CDC" /* CDC */
1028
+ });
1029
+ slapiLogger.info("CDC payment validated successfully", {
1030
+ paymentId,
1031
+ status: data.status
1032
+ });
1033
+ return { data };
1034
+ } catch (error) {
1035
+ slapiLogger.error("CDC payment validation failed", error, {
1036
+ paymentId
1037
+ });
1038
+ throw error;
1039
+ }
822
1040
  },
823
- validatePoints: ({ paymentId, txHash }) => {
824
- return slapiApi.post("/v1/payments/validate", { txHash, paymentId, type: "POINTS" /* POINTS */ }).then((data) => ({ data }));
1041
+ validatePoints: async ({ paymentId, txHash }) => {
1042
+ slapiLogger.debug("Validating points payment", { paymentId, txHash });
1043
+ try {
1044
+ const data = await slapiApi.post("/v1/payments/validate", {
1045
+ txHash,
1046
+ paymentId,
1047
+ type: "POINTS" /* POINTS */
1048
+ });
1049
+ slapiLogger.info("Points payment validated successfully", {
1050
+ paymentId,
1051
+ status: data.status,
1052
+ txHash
1053
+ });
1054
+ return { data };
1055
+ } catch (error) {
1056
+ slapiLogger.error("Points payment validation failed", error, {
1057
+ paymentId,
1058
+ txHash
1059
+ });
1060
+ throw error;
1061
+ }
825
1062
  },
826
- getStatus: (paymentId) => {
827
- return slapiApi.get(`/v1/payments/${paymentId}/status`);
1063
+ getStatus: async (paymentId) => {
1064
+ slapiLogger.debug("Getting payment status", { paymentId });
1065
+ try {
1066
+ const result = await slapiApi.get(`/v1/payments/${paymentId}/status`);
1067
+ slapiLogger.debug("Payment status retrieved", {
1068
+ paymentId,
1069
+ status: result.detail.status
1070
+ });
1071
+ return result;
1072
+ } catch (error) {
1073
+ slapiLogger.error("Failed to get payment status", error, {
1074
+ paymentId
1075
+ });
1076
+ throw error;
1077
+ }
828
1078
  }
829
1079
  };
830
1080
 
831
1081
  // src/hooks/payments/useCardPayment.ts
1082
+ var cardPaymentLogger = logger.child("card-payment");
832
1083
  var useCardPayment = () => {
833
1084
  const { selectedPaymentMethod } = useSpreePaymentMethod();
834
1085
  const { env } = useSpreePayEnv();
835
1086
  const { appProps } = useStaticConfig();
836
1087
  const cardPayment = async (params) => {
837
1088
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method) {
838
- throw new Error("Unsupported payment method");
1089
+ const error = new Error("Unsupported payment method");
1090
+ cardPaymentLogger.error("Invalid payment method for card payment", error, {
1091
+ actualType: selectedPaymentMethod.type,
1092
+ hasMethod: Boolean(selectedPaymentMethod.method)
1093
+ });
1094
+ throw error;
839
1095
  }
840
1096
  const { hash, capture, metadata } = params;
1097
+ cardPaymentLogger.info("Starting card payment", {
1098
+ hash,
1099
+ capture,
1100
+ hasMetadata: Boolean(metadata)
1101
+ });
841
1102
  const card = selectedPaymentMethod.method;
842
1103
  let cardId;
843
1104
  if ("token" in card) {
1105
+ cardPaymentLogger.debug("Adding new card from token", {
1106
+ lastFour: card.lastFourNumbers,
1107
+ schema: card.schema
1108
+ });
844
1109
  const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
845
1110
  cardId = cardResData.id;
1111
+ cardPaymentLogger.info("New card added successfully", { cardId });
846
1112
  } else {
847
1113
  cardId = card.id;
1114
+ cardPaymentLogger.debug("Using existing card", {
1115
+ cardId,
1116
+ lastFour: card.lastFourNumbers
1117
+ });
848
1118
  }
849
1119
  const transactionFee = getTransactionFee(appProps.amount, appProps.transactionFeePercentage);
1120
+ cardPaymentLogger.debug("Creating payment", {
1121
+ transactionFee,
1122
+ amount: appProps.amount,
1123
+ capture
1124
+ });
850
1125
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
851
1126
  hash,
852
1127
  capture,
@@ -859,13 +1134,38 @@ var useCardPayment = () => {
859
1134
  }
860
1135
  });
861
1136
  let { status } = paymentResData;
1137
+ cardPaymentLogger.info("Payment created", {
1138
+ paymentId: paymentResData.id,
1139
+ status,
1140
+ has3DS: Boolean(paymentResData.redirectUrl)
1141
+ });
862
1142
  if (paymentResData.redirectUrl) {
1143
+ cardPaymentLogger.debug("Starting 3DS flow", {
1144
+ paymentId: paymentResData.id
1145
+ });
863
1146
  const paymentIntent = await NiceModal2.show(Iframe3ds, { url: paymentResData.redirectUrl });
864
1147
  if (paymentIntent) {
1148
+ cardPaymentLogger.debug("3DS completed, validating", {
1149
+ paymentId: paymentResData.id,
1150
+ paymentIntent
1151
+ });
865
1152
  const { data: validateData } = await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
866
1153
  ({ status } = validateData);
1154
+ cardPaymentLogger.info("3DS validation completed", {
1155
+ paymentId: paymentResData.id,
1156
+ status
1157
+ });
1158
+ } else {
1159
+ cardPaymentLogger.warn("3DS flow cancelled by user", {
1160
+ paymentId: paymentResData.id
1161
+ });
867
1162
  }
868
1163
  }
1164
+ cardPaymentLogger.info("Card payment completed", {
1165
+ paymentId: paymentResData.id,
1166
+ status,
1167
+ txId: paymentResData.txId
1168
+ });
869
1169
  return {
870
1170
  status,
871
1171
  paymentType: "CREDIT_CARD" /* CREDIT_CARD */,
@@ -880,6 +1180,7 @@ var useCardPayment = () => {
880
1180
  // src/services/AirWalletService.ts
881
1181
  import { AirService, BUILD_ENV } from "@mocanetwork/airkit";
882
1182
  import { createWalletClient, custom, encodeFunctionData, erc20Abi, parseUnits } from "viem";
1183
+ var airWalletLogger = logger.child("airwallet");
883
1184
  var singletonState = null;
884
1185
  var initPromise = null;
885
1186
  var cachedKey = null;
@@ -931,16 +1232,19 @@ function peekAirWallet() {
931
1232
  async function handleSendErc20(params) {
932
1233
  const state = singletonState;
933
1234
  if (!state?.walletClient) {
934
- console.error("Air wallet is not initialized");
935
- throw new Error("Air wallet is not initialized");
1235
+ const error = new Error("Air wallet is not initialized");
1236
+ airWalletLogger.error("Wallet not initialized", error);
1237
+ throw error;
936
1238
  }
937
1239
  if (!params?.recipient) {
938
- console.error("Recipient address is not set");
939
- throw new Error("Recipient address is not set");
1240
+ const error = new Error("Recipient address is not set");
1241
+ airWalletLogger.error("Recipient address missing", error, { params });
1242
+ throw error;
940
1243
  }
941
1244
  if (!params?.token?.address || !params?.token?.decimals) {
942
- console.error("Token address or decimals not set");
943
- throw new Error("Token address or decimals not set");
1245
+ const error = new Error("Token address or decimals not set");
1246
+ airWalletLogger.error("Token configuration invalid", error, { token: params?.token });
1247
+ throw error;
944
1248
  }
945
1249
  try {
946
1250
  const { walletClient } = state;
@@ -961,9 +1265,17 @@ async function handleSendErc20(params) {
961
1265
  return { txHash: hash };
962
1266
  } catch (error) {
963
1267
  if (typeof error === "object" && error !== null && "shortMessage" in error) {
964
- console.error(error.shortMessage);
1268
+ const { shortMessage } = error;
1269
+ airWalletLogger.error("ERC20 transfer failed", error instanceof Error ? error : void 0, {
1270
+ shortMessage,
1271
+ recipient: params.recipient,
1272
+ amount: params.amount
1273
+ });
965
1274
  } else {
966
- console.error("Your wallet balances are insufficient to complete this transaction.");
1275
+ airWalletLogger.error("Insufficient wallet balance for transaction", error instanceof Error ? error : void 0, {
1276
+ recipient: params.recipient,
1277
+ amount: params.amount
1278
+ });
967
1279
  }
968
1280
  }
969
1281
  }
@@ -1016,14 +1328,29 @@ async function longPollCardStatus(paymentId) {
1016
1328
  }
1017
1329
 
1018
1330
  // src/hooks/payments/usePointsPayment.ts
1331
+ var pointsPaymentLogger = logger.child("points-payment");
1019
1332
  var usePointsPayment = (mode = "web2") => {
1020
1333
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1021
1334
  const { spreePayConfig } = useSpreePayConfig();
1022
1335
  const pointsPayment = async (params) => {
1023
1336
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */) {
1024
- throw new Error("Unsupported payment method");
1337
+ const error = new Error("Unsupported payment method");
1338
+ pointsPaymentLogger.error("Invalid payment method for points payment", error, {
1339
+ actualType: selectedPaymentMethod.type
1340
+ });
1341
+ throw error;
1025
1342
  }
1026
1343
  const { hash, capture, metadata } = params;
1344
+ pointsPaymentLogger.info("Starting points payment", {
1345
+ hash,
1346
+ capture,
1347
+ mode,
1348
+ points: params.points
1349
+ });
1350
+ pointsPaymentLogger.debug("Creating points payment", {
1351
+ mode,
1352
+ captureOverride: mode === "web2" ? true : capture
1353
+ });
1027
1354
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
1028
1355
  hash,
1029
1356
  // capture should be always true for web2 points payments
@@ -1031,24 +1358,57 @@ var usePointsPayment = (mode = "web2") => {
1031
1358
  metadata,
1032
1359
  type: "POINTS" /* POINTS */
1033
1360
  });
1361
+ pointsPaymentLogger.info("Points payment created", {
1362
+ paymentId: paymentResData.id,
1363
+ txId: paymentResData.txId,
1364
+ mode
1365
+ });
1034
1366
  if (mode === "web3") {
1367
+ pointsPaymentLogger.debug("Processing web3 points payment");
1035
1368
  const wallet = peekAirWallet();
1036
1369
  if (!wallet || !spreePayConfig?.pointsChain) {
1037
- throw new Error("AirWallet not found");
1370
+ const error = new Error("AirWallet not found");
1371
+ pointsPaymentLogger.error("AirWallet not available for web3 points", error, {
1372
+ hasWallet: Boolean(wallet),
1373
+ hasPointsChain: Boolean(spreePayConfig?.pointsChain)
1374
+ });
1375
+ throw error;
1038
1376
  }
1377
+ pointsPaymentLogger.debug("Sending ERC20 points transfer", {
1378
+ amount: params.points,
1379
+ recipient: spreePayConfig.pointsChain.recipientAddress
1380
+ });
1039
1381
  const transaction = await handleSendErc20({
1040
1382
  amount: params.points,
1041
1383
  token: spreePayConfig.pointsChain.pointsCoin,
1042
1384
  recipient: spreePayConfig.pointsChain.recipientAddress
1043
1385
  });
1044
1386
  if (!transaction) {
1045
- throw new Error("Points transaction failed");
1387
+ const error = new Error("Points transaction failed");
1388
+ pointsPaymentLogger.error("Points ERC20 transfer failed", error);
1389
+ throw error;
1046
1390
  }
1391
+ pointsPaymentLogger.info("Points transfer completed", {
1392
+ txHash: transaction.txHash,
1393
+ amount: params.points
1394
+ });
1395
+ pointsPaymentLogger.debug("Validating points transaction", {
1396
+ paymentId: paymentResData.id,
1397
+ txHash: transaction.txHash
1398
+ });
1047
1399
  await SlapiPaymentService.validatePoints({
1048
1400
  paymentId: paymentResData.id,
1049
1401
  txHash: transaction.txHash
1050
1402
  });
1403
+ pointsPaymentLogger.debug("Polling for points payment status", {
1404
+ paymentId: paymentResData.id
1405
+ });
1051
1406
  const pointsStatus2 = await longPollPoints(paymentResData.id);
1407
+ pointsPaymentLogger.info("Web3 points payment completed", {
1408
+ paymentId: paymentResData.id,
1409
+ status: pointsStatus2,
1410
+ txHash: transaction.txHash
1411
+ });
1052
1412
  return {
1053
1413
  status: pointsStatus2,
1054
1414
  txId: paymentResData.txId,
@@ -1057,7 +1417,14 @@ var usePointsPayment = (mode = "web2") => {
1057
1417
  paymentType: "POINTS" /* POINTS */
1058
1418
  };
1059
1419
  }
1420
+ pointsPaymentLogger.debug("Polling for web2 points payment status", {
1421
+ paymentId: paymentResData.id
1422
+ });
1060
1423
  const pointsStatus = await longPollPoints(paymentResData.id);
1424
+ pointsPaymentLogger.info("Web2 points payment completed", {
1425
+ paymentId: paymentResData.id,
1426
+ status: pointsStatus
1427
+ });
1061
1428
  return {
1062
1429
  status: pointsStatus,
1063
1430
  txId: paymentResData.txId,
@@ -1071,6 +1438,7 @@ var usePointsPayment = (mode = "web2") => {
1071
1438
 
1072
1439
  // src/hooks/payments/useSplitCardPayments.ts
1073
1440
  import NiceModal4 from "@ebay/nice-modal-react";
1441
+ var splitPaymentLogger = logger.child("split-card-payment");
1074
1442
  var useSplitCardPayments = (mode = "web2") => {
1075
1443
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1076
1444
  const { env } = useSpreePayEnv();
@@ -1081,16 +1449,30 @@ var useSplitCardPayments = (mode = "web2") => {
1081
1449
  throw new Error("Unsupported payment method");
1082
1450
  }
1083
1451
  const { hash, capture, metadata, points } = params;
1452
+ splitPaymentLogger.info("Starting split card+points payment", { hash, mode, points, capture });
1084
1453
  const card = selectedPaymentMethod.method;
1085
1454
  let cardId;
1086
1455
  if ("token" in card) {
1456
+ splitPaymentLogger.debug("Adding new card from token", {
1457
+ lastFour: card.lastFourNumbers,
1458
+ schema: card.schema
1459
+ });
1087
1460
  const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
1088
1461
  cardId = cardResData.id;
1462
+ splitPaymentLogger.debug("Card added successfully", { cardId });
1089
1463
  } else {
1090
1464
  cardId = card.id;
1465
+ splitPaymentLogger.debug("Using existing card", { cardId });
1091
1466
  }
1092
1467
  const usdAmount = getSplitAmount(appProps.amount ?? 0, points, spreePayConfig?.pointsConversionRatio);
1093
1468
  const transactionFee = getTransactionFee(usdAmount, appProps.transactionFeePercentage);
1469
+ splitPaymentLogger.debug("Calculated split amounts", {
1470
+ totalAmount: appProps.amount,
1471
+ points,
1472
+ usdAmount,
1473
+ transactionFee,
1474
+ conversionRatio: spreePayConfig?.pointsConversionRatio
1475
+ });
1094
1476
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
1095
1477
  hash,
1096
1478
  capture,
@@ -1105,31 +1487,64 @@ var useSplitCardPayments = (mode = "web2") => {
1105
1487
  amount: points
1106
1488
  }
1107
1489
  });
1490
+ splitPaymentLogger.info("Split payment created", {
1491
+ paymentId: paymentResData.id,
1492
+ status: paymentResData.status,
1493
+ has3DS: Boolean(paymentResData.redirectUrl)
1494
+ });
1108
1495
  if (paymentResData.redirectUrl) {
1496
+ splitPaymentLogger.debug("Starting 3DS flow for card portion", { paymentId: paymentResData.id });
1109
1497
  const paymentIntent = await NiceModal4.show(Iframe3ds, { url: paymentResData.redirectUrl });
1110
1498
  if (paymentIntent) {
1499
+ splitPaymentLogger.debug("3DS completed, validating", { paymentId: paymentResData.id });
1111
1500
  await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
1501
+ } else {
1502
+ splitPaymentLogger.warn("3DS flow canceled or failed", { paymentId: paymentResData.id });
1112
1503
  }
1113
1504
  }
1505
+ splitPaymentLogger.debug("Polling card payment status", { paymentId: paymentResData.id });
1114
1506
  const cardStatus = await longPollCardStatus(paymentResData.id);
1507
+ splitPaymentLogger.info("Card portion completed", { paymentId: paymentResData.id, cardStatus });
1115
1508
  if (mode === "web3") {
1509
+ splitPaymentLogger.info("Processing web3 points transfer", { points });
1116
1510
  const wallet = peekAirWallet();
1117
1511
  if (!wallet || !spreePayConfig?.pointsChain) {
1512
+ splitPaymentLogger.error("AirWallet not initialized for web3 points transfer", void 0, {
1513
+ hasWallet: Boolean(wallet),
1514
+ hasPointsChain: Boolean(spreePayConfig?.pointsChain)
1515
+ });
1118
1516
  throw new Error("AirWallet not found");
1119
1517
  }
1518
+ splitPaymentLogger.debug("Sending ERC20 points transfer", {
1519
+ amount: params.points,
1520
+ token: spreePayConfig.pointsChain.pointsCoin,
1521
+ recipient: spreePayConfig.pointsChain.recipientAddress
1522
+ });
1120
1523
  const transaction = await handleSendErc20({
1121
1524
  amount: params.points,
1122
1525
  token: spreePayConfig.pointsChain.pointsCoin,
1123
1526
  recipient: spreePayConfig.pointsChain.recipientAddress
1124
1527
  });
1125
1528
  if (!transaction) {
1529
+ splitPaymentLogger.error("Points transaction failed", void 0, { points });
1126
1530
  throw new Error("Points transaction failed");
1127
1531
  }
1532
+ splitPaymentLogger.info("Points transfer completed", { txHash: transaction.txHash });
1533
+ splitPaymentLogger.debug("Validating points transaction", {
1534
+ paymentId: paymentResData.id,
1535
+ txHash: transaction.txHash
1536
+ });
1128
1537
  await SlapiPaymentService.validatePoints({
1129
1538
  paymentId: paymentResData.id,
1130
1539
  txHash: transaction.txHash
1131
1540
  });
1541
+ splitPaymentLogger.debug("Polling points payment status", { paymentId: paymentResData.id });
1132
1542
  const pointsStatus = await longPollPoints(paymentResData.id);
1543
+ splitPaymentLogger.info("Web3 split payment completed", {
1544
+ paymentId: paymentResData.id,
1545
+ status: pointsStatus,
1546
+ txHash: transaction.txHash
1547
+ });
1133
1548
  return {
1134
1549
  paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
1135
1550
  status: pointsStatus,
@@ -1138,6 +1553,10 @@ var useSplitCardPayments = (mode = "web2") => {
1138
1553
  txHash: transaction.txHash
1139
1554
  };
1140
1555
  }
1556
+ splitPaymentLogger.info("Web2 split payment completed", {
1557
+ paymentId: paymentResData.id,
1558
+ status: cardStatus
1559
+ });
1141
1560
  return {
1142
1561
  paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
1143
1562
  status: cardStatus,
@@ -1218,13 +1637,7 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
1218
1637
  "cursor-not-allowed opacity-50": isSelected || isRemoveDisabled
1219
1638
  // 'cursor-pointer': !isSelected || !isRemoveDisabled,
1220
1639
  }),
1221
- children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "currentColor", children: /* @__PURE__ */ jsx12(
1222
- "path",
1223
- {
1224
- fill: "currentColor",
1225
- d: "M6.35 16.17c-.38 0-.7-.13-.96-.4a1.3 1.3 0 0 1-.39-.95V4.5h-.83v-.83H7.5v-.64h5v.64h3.33v.83H15v10.32c0 .39-.13.7-.39.96a1.3 1.3 0 0 1-.96.39h-7.3ZM14.17 4.5H5.83v10.32c0 .15.05.28.15.37.1.1.22.15.37.15h7.3c.13 0 .25-.06.36-.16.1-.11.16-.23.16-.36V4.5Zm-6 9.17h.84v-7.5h-.84v7.5Zm2.82 0h.84v-7.5h-.84v7.5Z"
1226
- }
1227
- ) })
1640
+ children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", className: "size-5", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx12("path", { d: "M6.35 16.17q-.57 0-.96-.4a1.3 1.3 0 0 1-.39-.95V4.5h-.83v-.83H7.5v-.64h5v.64h3.33v.83H15v10.32q0 .58-.39.96a1.3 1.3 0 0 1-.96.39zM14.17 4.5H5.83v10.32q0 .23.15.37.15.15.37.15h7.3q.2 0 .36-.16.15-.17.16-.36zm-6 9.17h.84v-7.5h-.84zm2.82 0h.84v-7.5h-.84z" }) })
1228
1641
  }
1229
1642
  )
1230
1643
  ] })
@@ -1317,6 +1730,7 @@ function Checkbox({ className, ...props }) {
1317
1730
 
1318
1731
  // src/components/CreditCardTab/CreditCard/CreditCardForm.tsx
1319
1732
  import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1733
+ var cardFormLogger = logger.child("card-form");
1320
1734
  var styleDark = {
1321
1735
  base: {
1322
1736
  fontSize: "16px",
@@ -1384,7 +1798,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
1384
1798
  }
1385
1799
  }
1386
1800
  } catch (error) {
1387
- console.error("Error creating card token:", error);
1801
+ cardFormLogger.error("Failed to create Stripe card token", error);
1388
1802
  setCardError("An error occurred while processing your card. Please try again.");
1389
1803
  }
1390
1804
  };
@@ -2587,6 +3001,7 @@ var PointsSelector = (props) => {
2587
3001
 
2588
3002
  // src/components/CreditCardTab/Points/SplitBlock.tsx
2589
3003
  import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
3004
+ var splitBlockLogger = logger.child("split-block");
2590
3005
  var SplitBlock = (props) => {
2591
3006
  const { onToggle, isSelected, onSelect } = props;
2592
3007
  const { balance, isBalanceLoading } = useSlapiBalance();
@@ -2611,7 +3026,10 @@ var SplitBlock = (props) => {
2611
3026
  onToggle(false);
2612
3027
  }
2613
3028
  } catch (e) {
2614
- console.error("Air Wallet init failed:", e);
3029
+ splitBlockLogger.error("Air Wallet initialization failed", e, {
3030
+ partnerId: pointsChain?.partnerId,
3031
+ environment: env.environment
3032
+ });
2615
3033
  }
2616
3034
  },
2617
3035
  [onToggle, env.environment]
@@ -2746,6 +3164,7 @@ import { useCallback as useCallback6, useEffect as useEffect8 } from "react";
2746
3164
 
2747
3165
  // src/hooks/payments/useCryptoComPayment.ts
2748
3166
  import NiceModal5 from "@ebay/nice-modal-react";
3167
+ var cryptoComLogger = logger.child("crypto-com-payment");
2749
3168
  var useCryptoComPayment = () => {
2750
3169
  const { selectedPaymentMethod } = useSpreePaymentMethod();
2751
3170
  const { env } = useSpreePayEnv();
@@ -2754,6 +3173,7 @@ var useCryptoComPayment = () => {
2754
3173
  throw new Error("Unsupported payment method");
2755
3174
  }
2756
3175
  const { hash, metadata } = params;
3176
+ cryptoComLogger.info("Starting Crypto.com Pay payment", { hash });
2757
3177
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
2758
3178
  hash,
2759
3179
  metadata,
@@ -2763,16 +3183,31 @@ var useCryptoComPayment = () => {
2763
3183
  cancelUrl: `${typeof window !== "undefined" ? window.location.origin : ""}${env.redirect3dsURI}?payment_intent=canceled`
2764
3184
  }
2765
3185
  });
3186
+ cryptoComLogger.info("Payment created", {
3187
+ paymentId: paymentResData.id,
3188
+ status: paymentResData.status,
3189
+ hasRedirect: Boolean(paymentResData.redirectUrl)
3190
+ });
2766
3191
  let { status } = paymentResData;
2767
3192
  if (paymentResData.redirectUrl) {
3193
+ cryptoComLogger.debug("Opening CDC payment redirect", { paymentId: paymentResData.id });
2768
3194
  const paymentIntent = await NiceModal5.show(Iframe3ds, { url: paymentResData.redirectUrl });
3195
+ cryptoComLogger.info("CDC payment redirect completed", { paymentIntent });
2769
3196
  if (paymentIntent === "success") {
3197
+ cryptoComLogger.debug("Validating CDC payment", { paymentId: paymentResData.id });
2770
3198
  const { data: validateData } = await SlapiPaymentService.validateCDC({ paymentId: paymentResData.id });
2771
3199
  ({ status } = validateData);
3200
+ cryptoComLogger.info("CDC payment validated", { paymentId: paymentResData.id, status });
2772
3201
  } else {
2773
3202
  status = "FAILED" /* FAILED */;
3203
+ cryptoComLogger.warn("CDC payment canceled or failed", { paymentIntent });
2774
3204
  }
2775
3205
  }
3206
+ cryptoComLogger.info("Crypto.com Pay payment completed", {
3207
+ paymentId: paymentResData.id,
3208
+ status,
3209
+ txId: paymentResData.txId
3210
+ });
2776
3211
  return {
2777
3212
  status,
2778
3213
  paymentType: "CDC" /* CDC */,
@@ -2794,7 +3229,7 @@ var Checkout = () => {
2794
3229
  onClick: appProps.onProcess,
2795
3230
  disabled: appProps.isProcessing,
2796
3231
  className: "flex flex-col items-center rounded-md bg-[#00307D] p-2 text-(--brand-primary) hover:bg-[#002655] disabled:cursor-not-allowed disabled:bg-[#002655] disabled:text-(--disabled)",
2797
- children: /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", width: "76", height: "28", fill: "none", viewBox: "0 0 76 28", children: [
3232
+ children: /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-7 w-[76px]", fill: "none", viewBox: "0 0 76 28", children: [
2798
3233
  /* @__PURE__ */ jsx29(
2799
3234
  "path",
2800
3235
  {
@@ -2985,6 +3420,7 @@ var BASE_TOKENS = [
2985
3420
 
2986
3421
  // src/hooks/payments/useCryptoPayment.ts
2987
3422
  var MAX_UINT256 = BigInt(2) ** BigInt(256) - BigInt(1);
3423
+ var cryptoPaymentLogger = logger.child("crypto-payment");
2988
3424
  var useCryptoPayment = () => {
2989
3425
  const { data: walletClient } = useWalletClient();
2990
3426
  const { spreePayConfig } = useSpreePayConfig();
@@ -2992,21 +3428,43 @@ var useCryptoPayment = () => {
2992
3428
  const { selectedPaymentMethod } = useSpreePaymentMethod();
2993
3429
  const cryptoPayment = async (params) => {
2994
3430
  if (!walletClient) {
2995
- throw new Error("Wallet not connected");
3431
+ const error = new Error("Wallet not connected");
3432
+ cryptoPaymentLogger.error("Wallet not connected for crypto payment", error);
3433
+ throw error;
2996
3434
  }
2997
3435
  if (!spreePayConfig) {
2998
- throw new Error("Spree Pay config not loaded");
3436
+ const error = new Error("Spree Pay config not loaded");
3437
+ cryptoPaymentLogger.error("Config not loaded for crypto payment", error);
3438
+ throw error;
2999
3439
  }
3000
3440
  if (selectedPaymentMethod.type !== "CRYPTO" /* CRYPTO */ || !selectedPaymentMethod.method?.symbol) {
3001
- throw new Error("Unsupported payment method");
3441
+ const error = new Error("Unsupported payment method");
3442
+ cryptoPaymentLogger.error("Invalid payment method for crypto payment", error, {
3443
+ actualType: selectedPaymentMethod.type,
3444
+ hasMethod: Boolean(selectedPaymentMethod.method)
3445
+ });
3446
+ throw error;
3002
3447
  }
3003
3448
  const { capture, hash, metadata } = params;
3004
3449
  const TOKEN = selectedPaymentMethod.method.symbol;
3450
+ cryptoPaymentLogger.info("Starting crypto payment", {
3451
+ hash,
3452
+ capture,
3453
+ token: TOKEN,
3454
+ walletAddress: walletClient.account.address
3455
+ });
3005
3456
  if (["MOCA" /* MOCA */, "WETH" /* WETH */, "USDC" /* USDC */, "USDT" /* USDT */].includes(TOKEN)) {
3006
3457
  const tokenAddress = selectedPaymentMethod.method.address;
3007
3458
  if (!tokenAddress) {
3008
- throw new Error("Token address not found");
3459
+ const error = new Error("Token address not found");
3460
+ cryptoPaymentLogger.error("Token address missing", error, { token: TOKEN });
3461
+ throw error;
3009
3462
  }
3463
+ cryptoPaymentLogger.debug("Checking token allowance", {
3464
+ token: TOKEN,
3465
+ tokenAddress,
3466
+ router: spreePayConfig.crypto.oneInchAggregationRouter
3467
+ });
3010
3468
  const allowance = await readContract(config2, {
3011
3469
  address: tokenAddress,
3012
3470
  abi: erc20Abi2,
@@ -3014,19 +3472,36 @@ var useCryptoPayment = () => {
3014
3472
  args: [walletClient.account.address, spreePayConfig.crypto.oneInchAggregationRouter]
3015
3473
  });
3016
3474
  if (allowance <= 0n) {
3475
+ cryptoPaymentLogger.info("Requesting token approval", {
3476
+ token: TOKEN,
3477
+ tokenAddress
3478
+ });
3017
3479
  const result = await walletClient.writeContract({
3018
3480
  address: tokenAddress,
3019
3481
  abi: erc20Abi2,
3020
3482
  functionName: "approve",
3021
3483
  args: [spreePayConfig.crypto.oneInchAggregationRouter, MAX_UINT256]
3022
3484
  });
3485
+ cryptoPaymentLogger.debug("Waiting for approval confirmation", {
3486
+ approvalTxHash: result
3487
+ });
3023
3488
  await waitForTransactionReceipt(config2, {
3024
3489
  hash: result,
3025
3490
  confirmations: 1
3026
- // You can change the number of block confirmations as per your requirement
3491
+ });
3492
+ cryptoPaymentLogger.info("Token approval confirmed", {
3493
+ approvalTxHash: result
3494
+ });
3495
+ } else {
3496
+ cryptoPaymentLogger.debug("Sufficient allowance exists", {
3497
+ allowance: allowance.toString()
3027
3498
  });
3028
3499
  }
3029
3500
  }
3501
+ cryptoPaymentLogger.debug("Creating crypto payment", {
3502
+ token: TOKEN,
3503
+ slippageBps: Math.round(0.5 * 100)
3504
+ });
3030
3505
  const paymentRes = await SlapiPaymentService.createPayment({
3031
3506
  hash,
3032
3507
  capture,
@@ -3039,19 +3514,42 @@ var useCryptoPayment = () => {
3039
3514
  slippageBps: Math.round(0.5 * 100)
3040
3515
  }
3041
3516
  });
3517
+ cryptoPaymentLogger.info("Crypto payment created", {
3518
+ paymentId: paymentRes.data.id,
3519
+ txId: paymentRes.data.txId
3520
+ });
3042
3521
  const parsedTX = JSON.parse(paymentRes.data.encodedTx);
3522
+ cryptoPaymentLogger.debug("Sending transaction", {
3523
+ to: parsedTX.to,
3524
+ value: parsedTX.value.toString()
3525
+ });
3043
3526
  const txHash = await walletClient.sendTransaction({
3044
3527
  account: walletClient.account.address,
3045
3528
  to: parsedTX.to,
3046
3529
  data: parsedTX.data,
3047
3530
  value: parsedTX.value
3048
3531
  });
3532
+ cryptoPaymentLogger.info("Transaction sent", {
3533
+ txHash,
3534
+ paymentId: paymentRes.data.id
3535
+ });
3536
+ cryptoPaymentLogger.debug("Verifying transaction on chain", {
3537
+ txId: paymentRes.data.txId,
3538
+ txHash
3539
+ });
3049
3540
  const res = await SlapiPaymentService.baseVerify({ id: paymentRes.data.txId, txHash });
3541
+ const finalStatus = res.verified ? "CAPTURED" /* CAPTURED */ : "FAILED" /* FAILED */;
3542
+ cryptoPaymentLogger.info("Crypto payment completed", {
3543
+ paymentId: paymentRes.data.id,
3544
+ txHash,
3545
+ verified: res.verified,
3546
+ status: finalStatus
3547
+ });
3050
3548
  return {
3051
3549
  txHash,
3052
3550
  paymentId: paymentRes.data.id,
3053
3551
  txId: paymentRes.data.txId,
3054
- status: res.verified ? "CAPTURED" /* CAPTURED */ : "FAILED" /* FAILED */,
3552
+ status: finalStatus,
3055
3553
  paymentType: "CRYPTO" /* CRYPTO */
3056
3554
  };
3057
3555
  };
@@ -3082,48 +3580,45 @@ var ConnectButton = () => {
3082
3580
 
3083
3581
  // src/config/symbolLogos.tsx
3084
3582
  import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
3085
- var MOCA_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3086
- /* @__PURE__ */ jsx32("circle", { cx: "14", cy: "14", r: "13.5", fill: "#C15F97" }),
3583
+ var MOCA_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-7", viewBox: "0 0 28 28", children: [
3584
+ /* @__PURE__ */ jsx32("circle", { cx: "14", cy: "14", r: "13.5", fill: "#c15f97" }),
3087
3585
  /* @__PURE__ */ jsx32(
3088
3586
  "path",
3089
3587
  {
3090
3588
  fill: "#fff",
3091
- d: "M16.06 6.65c.3 0 .59.16.74.43l6.06 10.5a.85.85 0 1 1-1.47.84L16.06 9.2l-1.51 2.62-.02.03-3.8 6.57a.85.85 0 0 1-1.47-.84l3.57-6.18-1.27-2.2-5.32 9.22a.85.85 0 0 1-1.48-.84l6.07-10.5.06-.1a.85.85 0 0 1 1.4.1l1.52 2.62 1.52-2.62.06-.1c.16-.2.4-.33.67-.33Z"
3589
+ d: "M16.06 6.65c.3 0 .59.16.74.43l6.06 10.5a.85.85 0 1 1-1.47.84L16.06 9.2l-1.51 2.62-.02.03-3.8 6.57a.85.85 0 0 1-1.47-.84l3.57-6.18-1.27-2.2-5.32 9.22a.85.85 0 0 1-1.48-.84l6.07-10.5.06-.1a.85.85 0 0 1 1.4.1l1.52 2.62 1.52-2.62.06-.1c.16-.2.4-.33.67-.33"
3092
3590
  }
3093
3591
  ),
3094
3592
  /* @__PURE__ */ jsx32("circle", { cx: "16", cy: "14", r: "1.5", fill: "#fff" })
3095
3593
  ] });
3096
- var USDC_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3097
- /* @__PURE__ */ jsxs20("g", { clipPath: "url(#clip0_528_9163)", children: [
3098
- /* @__PURE__ */ jsx32("path", { fill: "#2775CA", d: "M14 28c7.76 0 14-6.24 14-14S21.76 0 14 0 0 6.24 0 14s6.24 14 14 14Z" }),
3099
- /* @__PURE__ */ jsx32(
3100
- "path",
3101
- {
3102
- fill: "#fff",
3103
- d: "M17.85 16.22c0-2.04-1.23-2.74-3.68-3.04-1.75-.23-2.1-.7-2.1-1.51 0-.82.59-1.34 1.75-1.34 1.05 0 1.64.35 1.93 1.22.06.18.23.3.4.3h.94a.4.4 0 0 0 .41-.42v-.05a2.91 2.91 0 0 0-2.63-2.4v-1.4c0-.23-.17-.4-.46-.46h-.88c-.23 0-.4.17-.46.46v1.35c-1.75.23-2.86 1.4-2.86 2.85 0 1.93 1.16 2.69 3.61 2.98 1.64.29 2.16.64 2.16 1.57 0 .94-.81 1.58-1.92 1.58-1.52 0-2.04-.64-2.22-1.52-.06-.23-.23-.35-.4-.35h-1a.4.4 0 0 0-.4.41v.06c.23 1.46 1.16 2.5 3.08 2.8v1.4c0 .23.18.4.47.47h.88c.23 0 .4-.18.46-.47v-1.4c1.75-.3 2.92-1.52 2.92-3.1Z"
3104
- }
3105
- ),
3106
- /* @__PURE__ */ jsx32(
3107
- "path",
3108
- {
3109
- fill: "#fff",
3110
- d: "M11.03 22.34a8.69 8.69 0 0 1-5.2-11.2 8.63 8.63 0 0 1 5.2-5.19c.23-.12.35-.3.35-.58v-.82c0-.23-.12-.4-.35-.47-.06 0-.18 0-.24.06a10.48 10.48 0 0 0 0 20.01c.24.12.47 0 .53-.23.06-.06.06-.12.06-.24v-.81c0-.18-.18-.41-.35-.53Zm6.18-18.2c-.23-.12-.47 0-.53.23-.05.06-.05.12-.05.24v.81c0 .24.17.47.35.59a8.69 8.69 0 0 1 5.19 11.2 8.63 8.63 0 0 1-5.2 5.19c-.23.12-.34.3-.34.58v.82c0 .23.11.4.35.47.05 0 .17 0 .23-.06a10.48 10.48 0 0 0 6.82-13.19 10.58 10.58 0 0 0-6.82-6.88Z"
3111
- }
3112
- )
3113
- ] }),
3114
- /* @__PURE__ */ jsx32("defs", { children: /* @__PURE__ */ jsx32("clipPath", { id: "clip0_528_9163", children: /* @__PURE__ */ jsx32("path", { fill: "#fff", d: "M0 0h28v28H0z" }) }) })
3594
+ var USDC_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-7", fill: "none", viewBox: "0 0 28 28", children: [
3595
+ /* @__PURE__ */ jsx32("path", { fill: "#2775ca", d: "M14 28c7.76 0 14-6.24 14-14S21.76 0 14 0 0 6.24 0 14s6.24 14 14 14" }),
3596
+ /* @__PURE__ */ jsx32(
3597
+ "path",
3598
+ {
3599
+ fill: "#fff",
3600
+ d: "M17.85 16.22c0-2.04-1.23-2.74-3.68-3.04-1.75-.23-2.1-.7-2.1-1.51 0-.82.59-1.34 1.75-1.34 1.05 0 1.64.35 1.93 1.22.06.18.23.3.4.3h.94a.4.4 0 0 0 .41-.42v-.05a2.91 2.91 0 0 0-2.63-2.4v-1.4c0-.23-.17-.4-.46-.46h-.88c-.23 0-.4.17-.46.46v1.35c-1.75.23-2.86 1.4-2.86 2.85 0 1.93 1.16 2.69 3.61 2.98 1.64.29 2.16.64 2.16 1.57 0 .94-.81 1.58-1.92 1.58-1.52 0-2.04-.64-2.22-1.52-.06-.23-.23-.35-.4-.35h-1a.4.4 0 0 0-.4.41v.06c.23 1.46 1.16 2.5 3.08 2.8v1.4c0 .23.18.4.47.47h.88c.23 0 .4-.18.46-.47v-1.4c1.75-.3 2.92-1.52 2.92-3.1Z"
3601
+ }
3602
+ ),
3603
+ /* @__PURE__ */ jsx32(
3604
+ "path",
3605
+ {
3606
+ fill: "#fff",
3607
+ d: "M11.03 22.34a8.69 8.69 0 0 1-5.2-11.2 8.63 8.63 0 0 1 5.2-5.19.6.6 0 0 0 .35-.58v-.82c0-.23-.12-.4-.35-.47-.06 0-.18 0-.24.06a10.48 10.48 0 0 0 0 20.01c.24.12.47 0 .53-.23.06-.06.06-.12.06-.24v-.81c0-.18-.18-.41-.35-.53m6.18-18.2c-.23-.12-.47 0-.53.23-.05.06-.05.12-.05.24v.81c0 .24.17.47.35.59a8.69 8.69 0 0 1 5.19 11.2 8.63 8.63 0 0 1-5.2 5.19c-.23.12-.34.3-.34.58v.82c0 .23.11.4.35.47.05 0 .17 0 .23-.06a10.48 10.48 0 0 0 6.82-13.19 10.58 10.58 0 0 0-6.82-6.88"
3608
+ }
3609
+ )
3115
3610
  ] });
3116
- var USDT_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3117
- /* @__PURE__ */ jsx32("path", { fill: "#26A17B", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28Z" }),
3611
+ var USDT_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-7", fill: "none", viewBox: "0 0 28 28", children: [
3612
+ /* @__PURE__ */ jsx32("path", { fill: "#26a17b", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28" }),
3118
3613
  /* @__PURE__ */ jsx32(
3119
3614
  "path",
3120
3615
  {
3121
3616
  fill: "#fff",
3122
- d: "M15.5 15.3v-.01c-.1 0-.6.04-1.72.04-.88 0-1.5-.03-1.73-.04-3.42-.15-5.97-.74-5.97-1.46 0-.7 2.55-1.3 5.97-1.46v2.33a26 26 0 0 0 3.44 0v-2.32c3.42.15 5.96.74 5.96 1.46 0 .7-2.55 1.3-5.96 1.45m0-3.15v-2.08h4.76V6.89H7.3v3.17h4.76v2.08c-3.87.17-6.77.94-6.77 1.86 0 .92 2.9 1.68 6.77 1.86v6.67h3.45v-6.67c3.86-.18 6.76-.94 6.76-1.86 0-.92-2.9-1.68-6.76-1.86"
3617
+ d: "M15.5 15.3v-.01c-.1 0-.6.04-1.72.04-.88 0-1.5-.03-1.73-.04-3.42-.15-5.97-.74-5.97-1.46 0-.7 2.55-1.3 5.97-1.46v2.33a26 26 0 0 0 3.44 0v-2.32c3.42.15 5.96.74 5.96 1.46 0 .7-2.55 1.3-5.96 1.45m0-3.15v-2.08h4.76V6.89H7.3v3.17h4.76v2.08c-3.87.17-6.77.94-6.77 1.86s2.9 1.68 6.77 1.86v6.67h3.45v-6.67c3.86-.18 6.76-.94 6.76-1.86s-2.9-1.68-6.76-1.86"
3123
3618
  }
3124
3619
  )
3125
3620
  ] });
3126
- var WETH_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", width: "28", height: "28", viewBox: "0 0 24 24", children: [
3621
+ var WETH_SVG = /* @__PURE__ */ jsxs20("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-7", viewBox: "0 0 24 24", children: [
3127
3622
  /* @__PURE__ */ jsxs20("g", { clipPath: "url(#clip0_528_9173)", children: [
3128
3623
  /* @__PURE__ */ jsx32(
3129
3624
  "path",
@@ -3421,9 +3916,9 @@ var CryptoSelectModal = NiceModal6.create(() => {
3421
3916
  /* @__PURE__ */ jsxs22(DialogContent, { showCloseButton: false, className: "max-h-[90vh] gap-0 p-0", children: [
3422
3917
  /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-4 px-5 py-5 md:px-7", children: [
3423
3918
  /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between gap-4", children: [
3424
- /* @__PURE__ */ jsx38("button", { className: "rounded-md hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ jsx38("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "25", fill: "none", children: /* @__PURE__ */ jsx38("path", { stroke: "currentColor", d: "m15 6.5-6 6 6 6" }) }) }),
3919
+ /* @__PURE__ */ jsx38("button", { className: "rounded-md hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ jsx38("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-6", viewBox: "0 0 24 25", children: /* @__PURE__ */ jsx38("path", { stroke: "currentColor", d: "m15 6.5-6 6 6 6" }) }) }),
3425
3920
  /* @__PURE__ */ jsx38(DialogTitle, { className: "text-2xl font-medium text-(--brand-primary)", children: "Select a token" }),
3426
- /* @__PURE__ */ jsx38("button", { className: "rounded-md p-1 hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ jsx38("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "17", fill: "none", children: /* @__PURE__ */ jsx38(
3921
+ /* @__PURE__ */ jsx38("button", { className: "rounded-md p-1 hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ jsx38("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-4", viewBox: "0 0 16 17", children: /* @__PURE__ */ jsx38(
3427
3922
  "path",
3428
3923
  {
3429
3924
  fill: "currentColor",
@@ -3521,7 +4016,7 @@ var SelectCoinButton = () => {
3521
4016
  className: "flex h-11 w-full overflow-hidden rounded-md bg-(--s-primary) hover:bg-(--s-primary-hover)",
3522
4017
  children: /* @__PURE__ */ jsxs23("div", { className: "flex h-full w-full items-center justify-between px-3", children: [
3523
4018
  /* @__PURE__ */ jsx39("div", { className: "flex items-center", children: /* @__PURE__ */ jsx39("p", { className: "font-medium text-(--secondary)", children: "Select a token" }) }),
3524
- /* @__PURE__ */ jsx39("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx39("path", { stroke: "currentColor", strokeLinecap: "round", d: "m6 12.43 4-4-4-4" }) })
4019
+ /* @__PURE__ */ jsx39("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-4", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx39("path", { stroke: "currentColor", d: "m6 12.43 4-4-4-4" }) })
3525
4020
  ] })
3526
4021
  }
3527
4022
  );
@@ -3539,7 +4034,7 @@ var SelectedCoin = (props) => {
3539
4034
  Icon,
3540
4035
  !Icon && logoURI && /* @__PURE__ */ jsx40("img", { className: "mr-1 size-8 shrink-0", src: logoURI, alt: `${coin} logo` }),
3541
4036
  /* @__PURE__ */ jsx40("p", { className: "font-semibold text-(--brand-primary)", children: coin }),
3542
- /* @__PURE__ */ jsx40("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx40("path", { d: "M6 12.4341L10 8.43408L6 4.43408", stroke: "currentColor", strokeLinecap: "round" }) })
4037
+ /* @__PURE__ */ jsx40("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-4", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx40("path", { stroke: "currentColor", d: "m6 12.434 4-4-4-4" }) })
3543
4038
  ] }),
3544
4039
  /* @__PURE__ */ jsxs24("p", { className: "text-xs font-medium text-(--secondary)", children: [
3545
4040
  "Wallet balance ",
@@ -3659,49 +4154,39 @@ var TabButtons = (props) => {
3659
4154
  return /* @__PURE__ */ jsxs27("div", { className: "flex gap-4", children: [
3660
4155
  configIsLoading && /* @__PURE__ */ jsx44("div", { className: "h-[74px] w-[180px] animate-pulse rounded-md bg-(--s-primary)" }),
3661
4156
  spreePayConfig?.creditCard.enabled && /* @__PURE__ */ jsxs27(TabButton, { onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */), isActive: value === "CREDIT_CARD" /* CREDIT_CARD */, children: [
3662
- /* @__PURE__ */ jsxs27("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", fill: "none", viewBox: "0 0 32 32", children: [
3663
- /* @__PURE__ */ jsx44("mask", { id: "a", width: "32", height: "32", x: "0", y: "0", maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx44("path", { fill: "#d9d9d9", d: "M0 0h32v32H0z" }) }),
3664
- /* @__PURE__ */ jsx44("g", { mask: "url(#a)", children: /* @__PURE__ */ jsx44(
3665
- "path",
3666
- {
3667
- fill: "currentColor",
3668
- d: "M28 8.82v14.36q0 .92-.62 1.54-.6.6-1.53.61H6.15q-.91 0-1.53-.61A2 2 0 0 1 4 23.18V8.82q0-.92.62-1.54.6-.6 1.53-.61h19.7q.91 0 1.53.61.62.62.62 1.54M5.33 11.74h21.34V8.82q0-.31-.26-.56a.8.8 0 0 0-.56-.26H6.15q-.3 0-.56.26a.8.8 0 0 0-.26.56zm0 3.18v8.26q0 .31.26.56t.56.26h19.7q.3 0 .56-.26a.8.8 0 0 0 .26-.56v-8.26z"
3669
- }
3670
- ) })
3671
- ] }),
4157
+ /* @__PURE__ */ jsx44("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-8", viewBox: "0 0 32 32", children: /* @__PURE__ */ jsx44(
4158
+ "path",
4159
+ {
4160
+ fill: "currentColor",
4161
+ d: "M28 8.82v14.36q0 .92-.62 1.54-.6.6-1.53.61H6.15q-.91 0-1.53-.61A2 2 0 0 1 4 23.18V8.82q0-.92.62-1.54.6-.6 1.53-.61h19.7q.91 0 1.53.61.62.62.62 1.54M5.33 11.74h21.34V8.82q0-.31-.26-.56a.8.8 0 0 0-.56-.26H6.15q-.3 0-.56.26a.8.8 0 0 0-.26.56zm0 3.18v8.26q0 .31.26.56t.56.26h19.7q.3 0 .56-.26a.8.8 0 0 0 .26-.56v-8.26z"
4162
+ }
4163
+ ) }),
3672
4164
  /* @__PURE__ */ jsx44("p", { className: "text-md font-medium", children: "Card" })
3673
4165
  ] }),
3674
4166
  spreePayConfig?.crypto.enabled && /* @__PURE__ */ jsxs27(TabButton, { onClick: handleChange("CRYPTO" /* CRYPTO */), isActive: value === "CRYPTO" /* CRYPTO */, children: [
3675
- /* @__PURE__ */ jsx44("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", fill: "none", viewBox: "0 0 32 32", children: /* @__PURE__ */ jsx44(
4167
+ /* @__PURE__ */ jsx44("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-8", viewBox: "0 0 32 32", children: /* @__PURE__ */ jsx44(
3676
4168
  "path",
3677
4169
  {
3678
4170
  fill: "currentColor",
3679
- fillRule: "evenodd",
3680
- d: "M21 9.86a8 8 0 0 1 3 5.43l-2.85-.71a5.4 5.4 0 0 0-3.86-3.67 5.3 5.3 0 0 0-6.46 3.8 5.3 5.3 0 0 0 3.91 6.4 5.4 5.4 0 0 0 5.14-1.43l2.85.7a8 8 0 0 1-5.2 3.39L16.72 27l-2.6-.65.64-2.57a8 8 0 0 1-1.3-.32l-.64 2.57-2.6-.65.82-3.24a7.9 7.9 0 0 1-2.8-8.08 7.9 7.9 0 0 1 6.27-5.82L15.32 5l2.6.64-.65 2.58q.67.1 1.3.32l.65-2.57 2.6.64z",
3681
- clipRule: "evenodd"
4171
+ d: "M21 9.86a8 8 0 0 1 3 5.43l-2.85-.71a5.4 5.4 0 0 0-3.86-3.67 5.3 5.3 0 0 0-6.46 3.8 5.3 5.3 0 0 0 3.91 6.4 5.4 5.4 0 0 0 5.14-1.43l2.85.7a8 8 0 0 1-5.2 3.39L16.72 27l-2.6-.65.64-2.57a8 8 0 0 1-1.3-.32l-.64 2.57-2.6-.65.82-3.24a7.9 7.9 0 0 1-2.8-8.08 7.9 7.9 0 0 1 6.27-5.82L15.32 5l2.6.64-.65 2.58q.67.1 1.3.32l.65-2.57 2.6.64z"
3682
4172
  }
3683
4173
  ) }),
3684
4174
  /* @__PURE__ */ jsx44("p", { className: "text-md font-medium", children: "Crypto" })
3685
4175
  ] }),
3686
4176
  spreePayConfig?.cryptoCom.enabled && /* @__PURE__ */ jsxs27(TabButton, { onClick: handleChange("CDC" /* CDC */), isActive: value === "CDC" /* CDC */, children: [
3687
- /* @__PURE__ */ jsxs27("svg", { xmlns: "http://www.w3.org/2000/svg", width: "44", height: "32", fill: "none", viewBox: "0 0 44 32", children: [
4177
+ /* @__PURE__ */ jsxs27("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "h-8 w-11", viewBox: "0 0 44 32", children: [
3688
4178
  /* @__PURE__ */ jsx44(
3689
4179
  "path",
3690
4180
  {
3691
4181
  fill: "currentColor",
3692
- fillRule: "evenodd",
3693
- d: "M17.6 11v10l-8.8 5L0 21V11l8.8-5zM2.2 16.69l3.15 5.42h1.26l1.5-1.37v-.7L6.56 18.6v-2.32L4.51 15zm8.87-.42v2.32l-1.55 1.46v.69l1.5 1.35h1.24l3.15-5.4-2.32-1.72zm-4.5-1.95.75 1.95-.23 2.17H8.8l1.72-.01-.21-2.17.74-1.94zm-1.25-4-.8 3.48h8.56l-.83-3.47z",
3694
- clipRule: "evenodd"
4182
+ d: "M17.6 11v10l-8.8 5L0 21V11l8.8-5zM2.2 16.69l3.15 5.42h1.26l1.5-1.37v-.7L6.56 18.6v-2.32L4.51 15zm8.87-.42v2.32l-1.55 1.46v.69l1.5 1.35h1.24l3.15-5.4-2.32-1.72zm-4.5-1.95.75 1.95-.23 2.17H8.8l1.72-.01-.21-2.17.74-1.94zm-1.25-4-.8 3.48h8.56l-.83-3.47z"
3695
4183
  }
3696
4184
  ),
3697
- /* @__PURE__ */ jsx44("path", { fill: "#009fff", d: "m39.84 18.25 1.94-4.64h1.42l-4.05 9.17H37.7l1.4-3.1-2.64-6.07h1.5z" }),
3698
4185
  /* @__PURE__ */ jsx44(
3699
4186
  "path",
3700
4187
  {
3701
4188
  fill: "#009fff",
3702
- fillRule: "evenodd",
3703
- d: "M32.91 13.46q.92 0 1.52.34.62.34.91.94t.31 1.37v1.94q0 .37.15.55.15.17.54.2v1.16q-.51 0-.9-.11-.37-.12-.61-.35a2 2 0 0 1-.38-.61 2.6 2.6 0 0 1-2.24 1.22q-.62 0-1.13-.21a2 2 0 0 1-.82-.67q-.3-.44-.3-1.05 0-.73.35-1.16.38-.45.99-.66.63-.21 1.37-.21h1.61q0-.56-.18-.89a1 1 0 0 0-.49-.5q-.3-.15-.71-.16-.54 0-.95.25a1.1 1.1 0 0 0-.5.78h-1.37q.06-.69.46-1.17.41-.5 1.04-.75t1.33-.25m-.14 3.63q-.37 0-.7.1-.33.07-.53.3a.8.8 0 0 0-.2.58q0 .48.35.71t.84.22a1.7 1.7 0 0 0 1.53-.95q.22-.44.22-.93v-.03zM26.34 11q.94 0 1.63.3.69.29 1.08.88.4.57.4 1.43t-.4 1.45-1.1.88q-.7.28-1.61.28h-1.78v3.74H23.2V11zm-1.78 4.07h1.75q.97 0 1.36-.38.4-.4.4-1.08 0-.7-.4-1.07-.4-.4-1.36-.4h-1.75z",
3704
- clipRule: "evenodd"
4189
+ d: "m39.84 18.25 1.94-4.64h1.42l-4.05 9.17H37.7l1.4-3.1-2.64-6.07h1.5zm-6.93-4.79q.92 0 1.52.34.62.34.91.94t.31 1.37v1.94q0 .37.15.55.15.17.54.2v1.16q-.51 0-.9-.11-.37-.12-.61-.35a2 2 0 0 1-.38-.61 2.6 2.6 0 0 1-2.24 1.22q-.62 0-1.13-.21a2 2 0 0 1-.82-.67q-.3-.44-.3-1.05 0-.73.35-1.16.38-.45.99-.66.63-.21 1.37-.21h1.61q0-.56-.18-.89a1 1 0 0 0-.49-.5q-.3-.15-.71-.16-.54 0-.95.25a1.1 1.1 0 0 0-.5.78h-1.37q.06-.69.46-1.17.41-.5 1.04-.75t1.33-.25m-.14 3.63q-.37 0-.7.1-.33.07-.53.3a.8.8 0 0 0-.2.58q0 .48.35.71t.84.22a1.7 1.7 0 0 0 1.53-.95q.22-.44.22-.93v-.03zM26.34 11q.94 0 1.63.3.69.29 1.08.88.4.57.4 1.43t-.4 1.45-1.1.88q-.7.28-1.61.28h-1.78v3.74H23.2V11zm-1.78 4.07h1.75q.97 0 1.36-.38.4-.4.4-1.08 0-.7-.4-1.07-.4-.4-1.36-.4h-1.75z"
3705
4190
  }
3706
4191
  )
3707
4192
  ] }),
@@ -3731,10 +4216,59 @@ var SpreePayContent = ({ isLoggedIn }) => {
3731
4216
  ] });
3732
4217
  };
3733
4218
 
4219
+ // src/components/ErrorBoundary.tsx
4220
+ import { Component } from "react";
4221
+ import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
4222
+ var ErrorBoundary = class extends Component {
4223
+ constructor(props) {
4224
+ super(props);
4225
+ this.state = { hasError: false, error: null };
4226
+ }
4227
+ static getDerivedStateFromError(error) {
4228
+ return { hasError: true, error };
4229
+ }
4230
+ componentDidCatch(error, errorInfo) {
4231
+ logger.error("Widget error caught by ErrorBoundary", error, {
4232
+ componentStack: errorInfo.componentStack
4233
+ });
4234
+ }
4235
+ render() {
4236
+ if (this.state.hasError) {
4237
+ if (this.props.fallback) {
4238
+ return this.props.fallback;
4239
+ }
4240
+ return /* @__PURE__ */ jsxs29("div", { className: "flex w-full flex-col items-center justify-center rounded-3xl border border-(--b-inverse) bg-(--s-primary) p-8", children: [
4241
+ /* @__PURE__ */ jsx46("div", { className: "mb-4 flex size-12 items-center justify-center rounded-full bg-(--s-secondary)", children: /* @__PURE__ */ jsxs29(
4242
+ "svg",
4243
+ {
4244
+ xmlns: "http://www.w3.org/2000/svg",
4245
+ viewBox: "0 0 24 24",
4246
+ fill: "none",
4247
+ stroke: "currentColor",
4248
+ strokeWidth: "2",
4249
+ strokeLinecap: "round",
4250
+ strokeLinejoin: "round",
4251
+ className: "size-10 text-(--warning)",
4252
+ children: [
4253
+ /* @__PURE__ */ jsx46("circle", { cx: "12", cy: "12", r: "10" }),
4254
+ /* @__PURE__ */ jsx46("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
4255
+ /* @__PURE__ */ jsx46("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
4256
+ ]
4257
+ }
4258
+ ) }),
4259
+ /* @__PURE__ */ jsx46("h3", { className: "mb-2 text-lg font-semibold text-(--primary)", children: "Payment Widget Error" }),
4260
+ /* @__PURE__ */ jsx46("p", { className: "text-center text-sm text-(--secondary)", children: "Something went wrong loading the payment widget. Please refresh the page and try again." })
4261
+ ] });
4262
+ }
4263
+ return this.props.children;
4264
+ }
4265
+ };
4266
+
3734
4267
  // src/hooks/useKeycloakSSO.ts
3735
4268
  import { useCallback as useCallback8, useEffect as useEffect11, useRef as useRef7, useState as useState13 } from "react";
3736
4269
  import Keycloak from "keycloak-js";
3737
4270
  var refreshAheadSeconds = 60;
4271
+ var keycloakLogger = logger.child("keycloak");
3738
4272
  function useKeycloakSSO(config2) {
3739
4273
  const { url, realm, clientId, ssoPageURI, enabled } = config2;
3740
4274
  const initRef = useRef7(false);
@@ -3761,8 +4295,11 @@ function useKeycloakSSO(config2) {
3761
4295
  setAccessToken(kc.token ?? null);
3762
4296
  scheduleRefreshRef.current();
3763
4297
  }
3764
- }).catch((_) => {
3765
- kc.login().catch(console.error);
4298
+ }).catch((err) => {
4299
+ keycloakLogger.error("Token refresh failed, redirecting to login", err);
4300
+ kc.login().catch((loginErr) => {
4301
+ keycloakLogger.error("Login redirect failed", loginErr);
4302
+ });
3766
4303
  });
3767
4304
  }, delayMs);
3768
4305
  }, []);
@@ -3781,7 +4318,7 @@ function useKeycloakSSO(config2) {
3781
4318
  scheduleRefresh();
3782
4319
  }
3783
4320
  }).catch((err) => {
3784
- console.error("[Keycloak] onTokenExpired refresh failed", err);
4321
+ keycloakLogger.error("Token expired refresh failed", err);
3785
4322
  });
3786
4323
  };
3787
4324
  kc.init({
@@ -3789,7 +4326,7 @@ function useKeycloakSSO(config2) {
3789
4326
  silentCheckSsoRedirectUri: `${window.location.origin}${ssoPageURI}`,
3790
4327
  silentCheckSsoFallback: true
3791
4328
  }).then((auth) => {
3792
- console.info("[Keycloak] init success, authenticated=", auth);
4329
+ keycloakLogger.info("SSO initialization successful", { authenticated: auth });
3793
4330
  setAccessToken(kc.token ?? null);
3794
4331
  if (auth) scheduleRefresh();
3795
4332
  }).catch((err) => {
@@ -3803,7 +4340,7 @@ function useKeycloakSSO(config2) {
3803
4340
  }
3804
4341
 
3805
4342
  // src/SpreePay.tsx
3806
- import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
4343
+ import { jsx as jsx47, jsxs as jsxs30 } from "react/jsx-runtime";
3807
4344
  var SpreePayInner = () => {
3808
4345
  const [portalEl, setPortalEl] = useState14(null);
3809
4346
  const rootRef = useCallback9((node) => {
@@ -3811,10 +4348,11 @@ var SpreePayInner = () => {
3811
4348
  const el = node.querySelector(":scope > .sl-spreepay__portal");
3812
4349
  setPortalEl(el ?? null);
3813
4350
  }, []);
3814
- useEffect12(() => {
3815
- console.log(`[spree-pay] v${version}`);
3816
- }, []);
3817
4351
  const { env } = useSpreePayEnv();
4352
+ useEffect12(() => {
4353
+ configureLogger({ environment: env.environment });
4354
+ logger.logVersion();
4355
+ }, [env.environment]);
3818
4356
  const { staticConfig, appProps } = useStaticConfig();
3819
4357
  const tenantId = env?.tenantId;
3820
4358
  const { isChecking, accessToken } = useKeycloakSSO({
@@ -3838,12 +4376,12 @@ var SpreePayInner = () => {
3838
4376
  }, [_accessToken, staticConfig, tenantId, unauthenticatedFetcher]);
3839
4377
  const getContent = () => {
3840
4378
  if (isChecking) {
3841
- return /* @__PURE__ */ jsxs29("div", { className: "flex w-full flex-col", children: [
3842
- /* @__PURE__ */ jsx46("div", { className: "mb-4 h-[315px] animate-pulse rounded-3xl bg-(--s-primary)" }),
3843
- /* @__PURE__ */ jsx46("div", { className: "h-[135px] animate-pulse rounded-3xl bg-(--s-primary)" })
4379
+ return /* @__PURE__ */ jsxs30("div", { className: "flex w-full flex-col", children: [
4380
+ /* @__PURE__ */ jsx47("div", { className: "mb-4 h-[315px] animate-pulse rounded-3xl bg-(--s-primary)" }),
4381
+ /* @__PURE__ */ jsx47("div", { className: "h-[135px] animate-pulse rounded-3xl bg-(--s-primary)" })
3844
4382
  ] });
3845
4383
  }
3846
- return /* @__PURE__ */ jsx46(
4384
+ return /* @__PURE__ */ jsx47(
3847
4385
  SWRConfig,
3848
4386
  {
3849
4387
  value: {
@@ -3852,17 +4390,17 @@ var SpreePayInner = () => {
3852
4390
  revalidateOnFocus: false,
3853
4391
  revalidateIfStale: false
3854
4392
  },
3855
- children: /* @__PURE__ */ jsx46(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ jsx46(NiceModal9.Provider, { children: /* @__PURE__ */ jsx46(SpreePayContent, { isLoggedIn: Boolean(_accessToken) }) }) })
4393
+ children: /* @__PURE__ */ jsx47(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ jsx47(NiceModal9.Provider, { children: /* @__PURE__ */ jsx47(SpreePayContent, { isLoggedIn: Boolean(_accessToken) }) }) })
3856
4394
  }
3857
4395
  );
3858
4396
  };
3859
- return /* @__PURE__ */ jsxs29("div", { ref: rootRef, className: cn("sl-spreepay", appProps.className), children: [
3860
- /* @__PURE__ */ jsx46("div", { className: "sl-spreepay__portal" }),
4397
+ return /* @__PURE__ */ jsxs30("div", { ref: rootRef, className: cn("sl-spreepay", appProps.className), children: [
4398
+ /* @__PURE__ */ jsx47("div", { className: "sl-spreepay__portal" }),
3861
4399
  getContent()
3862
4400
  ] });
3863
4401
  };
3864
4402
  var SpreePay = (props) => {
3865
- return /* @__PURE__ */ jsx46(StaticConfigProvider, { props, children: /* @__PURE__ */ jsx46(SpreePayInner, {}) });
4403
+ return /* @__PURE__ */ jsx47(ErrorBoundary, { children: /* @__PURE__ */ jsx47(StaticConfigProvider, { props, children: /* @__PURE__ */ jsx47(SpreePayInner, {}) }) });
3866
4404
  };
3867
4405
 
3868
4406
  // src/hooks/useCapture3DS.ts
@@ -3875,9 +4413,12 @@ var useCapture3DS = (searchParams) => {
3875
4413
  }, [searchParams]);
3876
4414
  };
3877
4415
  export {
4416
+ LogLevel,
3878
4417
  PaymentType,
3879
4418
  SpreePay,
3880
4419
  SpreePayProvider,
4420
+ configureLogger,
4421
+ logger,
3881
4422
  useCapture3DS,
3882
4423
  useSpreePay
3883
4424
  };