@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.cjs CHANGED
@@ -30,22 +30,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ LogLevel: () => LogLevel,
33
34
  PaymentType: () => PaymentType,
34
35
  SpreePay: () => SpreePay,
35
36
  SpreePayProvider: () => SpreePayProvider,
37
+ configureLogger: () => configureLogger,
38
+ logger: () => logger,
36
39
  useCapture3DS: () => useCapture3DS,
37
40
  useSpreePay: () => useSpreePay
38
41
  });
39
42
  module.exports = __toCommonJS(index_exports);
40
43
 
41
44
  // src/SpreePay.tsx
42
- var import_react19 = require("react");
45
+ var import_react20 = require("react");
43
46
  var import_nice_modal_react9 = __toESM(require("@ebay/nice-modal-react"), 1);
44
47
  var import_swr5 = require("swr");
45
48
 
46
- // package.json
47
- var version = "0.1.39";
48
-
49
49
  // src/context/SpreePayActionsContext.tsx
50
50
  var import_react = require("react");
51
51
 
@@ -71,8 +71,126 @@ var PaymentType = /* @__PURE__ */ ((PaymentType2) => {
71
71
  return PaymentType2;
72
72
  })(PaymentType || {});
73
73
 
74
+ // package.json
75
+ var version = "0.1.41";
76
+
77
+ // src/utils/logger.ts
78
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
79
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
80
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
81
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
82
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
83
+ LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
84
+ return LogLevel2;
85
+ })(LogLevel || {});
86
+ var Logger = class _Logger {
87
+ config;
88
+ constructor(config2 = {}) {
89
+ this.config = {
90
+ minLevel: this.getDefaultLogLevel(config2.environment),
91
+ prefix: "[spree-pay]",
92
+ ...config2
93
+ };
94
+ }
95
+ /**
96
+ * Determines default log level based on environment
97
+ * - Production: Only ERROR and version info
98
+ * - Development/Staging: All logs
99
+ */
100
+ getDefaultLogLevel(environment) {
101
+ if (typeof window === "undefined") return 1 /* INFO */;
102
+ if (environment) {
103
+ return environment === "prod" ? 3 /* ERROR */ : 0 /* DEBUG */;
104
+ }
105
+ return 3 /* ERROR */;
106
+ }
107
+ /**
108
+ * Set the environment and update log level accordingly
109
+ */
110
+ setEnvironment(environment) {
111
+ this.config.environment = environment;
112
+ this.config.minLevel = this.getDefaultLogLevel(environment);
113
+ }
114
+ shouldLog(level) {
115
+ return level >= this.config.minLevel;
116
+ }
117
+ formatMessage(level, message, context) {
118
+ const levelName = LogLevel[level];
119
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
120
+ const contextStr = context && Object.keys(context).length > 0 ? ` ${JSON.stringify(context)}` : "";
121
+ return `${this.config.prefix} [${levelName}] ${timestamp} - ${message}${contextStr}`;
122
+ }
123
+ /**
124
+ * Log debug information (only in dev/stg)
125
+ */
126
+ debug(message, context) {
127
+ if (!this.shouldLog(0 /* DEBUG */)) return;
128
+ console.log(this.formatMessage(0 /* DEBUG */, message, context));
129
+ }
130
+ /**
131
+ * Log informational messages (only in dev/stg)
132
+ */
133
+ info(message, context) {
134
+ if (!this.shouldLog(1 /* INFO */)) return;
135
+ console.log(this.formatMessage(1 /* INFO */, message, context));
136
+ }
137
+ /**
138
+ * Log warnings (only in dev/stg)
139
+ */
140
+ warn(message, context) {
141
+ if (!this.shouldLog(2 /* WARN */)) return;
142
+ console.warn(this.formatMessage(2 /* WARN */, message, context));
143
+ }
144
+ /**
145
+ * Log errors (shows in all environments)
146
+ */
147
+ error(message, error, context) {
148
+ if (!this.shouldLog(3 /* ERROR */)) return;
149
+ const errorContext = {
150
+ ...context,
151
+ ...error instanceof Error ? {
152
+ errorName: error.name,
153
+ errorMessage: error.message,
154
+ errorStack: error.stack
155
+ } : { error }
156
+ };
157
+ console.error(this.formatMessage(3 /* ERROR */, message, errorContext));
158
+ }
159
+ /**
160
+ * Always logs the version, regardless of environment
161
+ */
162
+ logVersion() {
163
+ console.log(`${this.config.prefix} v${version} - ${this.config.environment}`);
164
+ }
165
+ /**
166
+ * Creates a child logger with additional context
167
+ * Useful for component-specific logging
168
+ */
169
+ child(prefix) {
170
+ return new _Logger({
171
+ ...this.config,
172
+ prefix: `${this.config.prefix}:${prefix}`
173
+ });
174
+ }
175
+ /**
176
+ * Override log level (useful for testing or debugging)
177
+ */
178
+ setLogLevel(level) {
179
+ this.config.minLevel = level;
180
+ }
181
+ };
182
+ var logger = new Logger();
183
+ var configureLogger = (config2) => {
184
+ if (config2.environment) {
185
+ logger.setEnvironment(config2.environment);
186
+ }
187
+ const { environment, ...restConfig } = config2;
188
+ Object.assign(logger["config"], restConfig);
189
+ };
190
+
74
191
  // src/context/SpreePayActionsContext.tsx
75
192
  var import_jsx_runtime = require("react/jsx-runtime");
193
+ var processLogger = logger.child("process");
76
194
  var SpreePayActionsContext = (0, import_react.createContext)(void 0);
77
195
  var SpreePayProvider = ({ children, env }) => {
78
196
  const processRef = (0, import_react.useRef)(null);
@@ -84,18 +202,43 @@ var SpreePayProvider = ({ children, env }) => {
84
202
  const register = (0, import_react.useCallback)((fn) => {
85
203
  processRef.current = fn;
86
204
  }, []);
87
- const process = (0, import_react.useCallback)(async (data) => {
88
- if (!processRef.current) throw new Error("SpreePay process function not registered");
89
- setInternalProcessing(true);
90
- try {
91
- return await processRef.current(data);
92
- } catch (e) {
93
- if (e instanceof Error) throw e;
94
- throw new PaymentError("Payment failed", "FAILED" /* FAILED */, e);
95
- } finally {
96
- setInternalProcessing(false);
97
- }
98
- }, []);
205
+ const process = (0, import_react.useCallback)(
206
+ async (data) => {
207
+ if (!processRef.current) {
208
+ const error = new Error("SpreePay process function not registered");
209
+ processLogger.error("Process function not registered", error);
210
+ throw error;
211
+ }
212
+ processLogger.info("Payment process started", {
213
+ hash: data.hash,
214
+ capture: data.capture,
215
+ hasMetadata: Boolean(data.metadata),
216
+ paymentType: selectedPaymentMethod.type
217
+ });
218
+ setInternalProcessing(true);
219
+ try {
220
+ const result = await processRef.current(data);
221
+ processLogger.info("Payment process completed", {
222
+ status: result.status,
223
+ paymentId: result.paymentId,
224
+ paymentType: result.paymentType,
225
+ txHash: result.txHash
226
+ });
227
+ return result;
228
+ } catch (e) {
229
+ processLogger.error("Payment process failed", e instanceof Error ? e : void 0, {
230
+ hash: data.hash,
231
+ paymentType: selectedPaymentMethod.type,
232
+ errorMessage: e instanceof Error ? e.message : String(e)
233
+ });
234
+ if (e instanceof Error) throw e;
235
+ throw new PaymentError("Payment failed", "FAILED" /* FAILED */, e);
236
+ } finally {
237
+ setInternalProcessing(false);
238
+ }
239
+ },
240
+ [selectedPaymentMethod.type]
241
+ );
99
242
  const value = {
100
243
  // Set default to true for web3 points to backward compatibility
101
244
  env: { ...env, useWeb3Points: env.useWeb3Points ?? true },
@@ -239,7 +382,10 @@ var StaticConfigProvider = ({ children, props }) => {
239
382
  const envConfig = config[env.environment];
240
383
  const isKnownTenant = env.tenantId in envConfig;
241
384
  if (!isKnownTenant) {
242
- console.warn(`[spree-pay] Unknown tenantId "${env.tenantId}", falling back to "moca"`);
385
+ logger.warn(`Unknown tenantId "${env.tenantId}", falling back to "moca"`, {
386
+ tenantId: env.tenantId,
387
+ environment: env.environment
388
+ });
243
389
  }
244
390
  const appKey = isKnownTenant ? env.tenantId : "moca";
245
391
  return envConfig[appKey];
@@ -588,11 +734,11 @@ var CheckoutButton = ({ isLoggedIn }) => {
588
734
  ),
589
735
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("a", { href: "https://www.spree.finance/", className: "flex items-center justify-center gap-2 hover:underline", children: [
590
736
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: "Powered by" }),
591
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "shrink-0", xmlns: "http://www.w3.org/2000/svg", width: "66", height: "30", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
737
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "h-[30px]", viewBox: "0 0 66 30", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
592
738
  "path",
593
739
  {
594
740
  fill: "currentColor",
595
- 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"
741
+ 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"
596
742
  }
597
743
  ) })
598
744
  ] })
@@ -844,49 +990,181 @@ var registerApi = (config2) => {
844
990
  };
845
991
 
846
992
  // src/services/slapi.ts
993
+ var slapiLogger = logger.child("slapi");
847
994
  var SlapiPaymentService = {
848
- createPayment: ({ capture = false, ...rest }) => {
849
- return slapiApi.post("/v1/payments", { ...rest, capture }).then((data) => ({ data }));
995
+ createPayment: async ({ capture = false, ...rest }) => {
996
+ slapiLogger.debug("Creating payment", {
997
+ type: rest.type,
998
+ hash: rest.hash,
999
+ capture
1000
+ });
1001
+ try {
1002
+ const data = await slapiApi.post("/v1/payments", { ...rest, capture });
1003
+ slapiLogger.info("Payment created successfully", {
1004
+ paymentId: data.id,
1005
+ status: data.status,
1006
+ txId: data.txId
1007
+ });
1008
+ return { data };
1009
+ } catch (error) {
1010
+ slapiLogger.error("Failed to create payment", error, {
1011
+ type: rest.type,
1012
+ hash: rest.hash
1013
+ });
1014
+ throw error;
1015
+ }
850
1016
  },
851
- baseVerify: ({ id, txHash }) => {
852
- return slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, { txHash });
1017
+ baseVerify: async ({ id, txHash }) => {
1018
+ slapiLogger.debug("Verifying base transaction", { id, txHash });
1019
+ try {
1020
+ const result = await slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, {
1021
+ txHash
1022
+ });
1023
+ slapiLogger.info("Base transaction verified", {
1024
+ id,
1025
+ txHash,
1026
+ verified: result.verified
1027
+ });
1028
+ return result;
1029
+ } catch (error) {
1030
+ slapiLogger.error("Base transaction verification failed", error, {
1031
+ id,
1032
+ txHash
1033
+ });
1034
+ throw error;
1035
+ }
853
1036
  },
854
- addCard: ({ source, hash }) => {
855
- return slapiApi.post("/v1/payments/cards", { hash, source }).then((data) => ({ data }));
1037
+ addCard: async ({ source, hash }) => {
1038
+ slapiLogger.debug("Adding card", { hash, sourcePrefix: source.substring(0, 10) });
1039
+ try {
1040
+ const data = await slapiApi.post("/v1/payments/cards", { hash, source });
1041
+ slapiLogger.info("Card added successfully", { cardId: data.id, hash });
1042
+ return { data };
1043
+ } catch (error) {
1044
+ slapiLogger.error("Failed to add card", error, { hash });
1045
+ throw error;
1046
+ }
856
1047
  },
857
- validate3DS: ({ paymentId }) => {
858
- return slapiApi.post("/v1/payments/validate", { paymentId, type: "CREDIT_CARD" /* CREDIT_CARD */ }).then((data) => ({ data }));
1048
+ validate3DS: async ({ paymentId }) => {
1049
+ slapiLogger.debug("Validating 3DS", { paymentId });
1050
+ try {
1051
+ const data = await slapiApi.post("/v1/payments/validate", {
1052
+ paymentId,
1053
+ type: "CREDIT_CARD" /* CREDIT_CARD */
1054
+ });
1055
+ slapiLogger.info("3DS validated successfully", {
1056
+ paymentId,
1057
+ status: data.status
1058
+ });
1059
+ return { data };
1060
+ } catch (error) {
1061
+ slapiLogger.error("3DS validation failed", error, { paymentId });
1062
+ throw error;
1063
+ }
859
1064
  },
860
- validateCDC: ({ paymentId }) => {
861
- return slapiApi.post("/v1/payments/validate", { paymentId, type: "CDC" /* CDC */ }).then((data) => ({ data }));
1065
+ validateCDC: async ({ paymentId }) => {
1066
+ slapiLogger.debug("Validating CDC payment", { paymentId });
1067
+ try {
1068
+ const data = await slapiApi.post("/v1/payments/validate", {
1069
+ paymentId,
1070
+ type: "CDC" /* CDC */
1071
+ });
1072
+ slapiLogger.info("CDC payment validated successfully", {
1073
+ paymentId,
1074
+ status: data.status
1075
+ });
1076
+ return { data };
1077
+ } catch (error) {
1078
+ slapiLogger.error("CDC payment validation failed", error, {
1079
+ paymentId
1080
+ });
1081
+ throw error;
1082
+ }
862
1083
  },
863
- validatePoints: ({ paymentId, txHash }) => {
864
- return slapiApi.post("/v1/payments/validate", { txHash, paymentId, type: "POINTS" /* POINTS */ }).then((data) => ({ data }));
1084
+ validatePoints: async ({ paymentId, txHash }) => {
1085
+ slapiLogger.debug("Validating points payment", { paymentId, txHash });
1086
+ try {
1087
+ const data = await slapiApi.post("/v1/payments/validate", {
1088
+ txHash,
1089
+ paymentId,
1090
+ type: "POINTS" /* POINTS */
1091
+ });
1092
+ slapiLogger.info("Points payment validated successfully", {
1093
+ paymentId,
1094
+ status: data.status,
1095
+ txHash
1096
+ });
1097
+ return { data };
1098
+ } catch (error) {
1099
+ slapiLogger.error("Points payment validation failed", error, {
1100
+ paymentId,
1101
+ txHash
1102
+ });
1103
+ throw error;
1104
+ }
865
1105
  },
866
- getStatus: (paymentId) => {
867
- return slapiApi.get(`/v1/payments/${paymentId}/status`);
1106
+ getStatus: async (paymentId) => {
1107
+ slapiLogger.debug("Getting payment status", { paymentId });
1108
+ try {
1109
+ const result = await slapiApi.get(`/v1/payments/${paymentId}/status`);
1110
+ slapiLogger.debug("Payment status retrieved", {
1111
+ paymentId,
1112
+ status: result.detail.status
1113
+ });
1114
+ return result;
1115
+ } catch (error) {
1116
+ slapiLogger.error("Failed to get payment status", error, {
1117
+ paymentId
1118
+ });
1119
+ throw error;
1120
+ }
868
1121
  }
869
1122
  };
870
1123
 
871
1124
  // src/hooks/payments/useCardPayment.ts
1125
+ var cardPaymentLogger = logger.child("card-payment");
872
1126
  var useCardPayment = () => {
873
1127
  const { selectedPaymentMethod } = useSpreePaymentMethod();
874
1128
  const { env } = useSpreePayEnv();
875
1129
  const { appProps } = useStaticConfig();
876
1130
  const cardPayment = async (params) => {
877
1131
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method) {
878
- throw new Error("Unsupported payment method");
1132
+ const error = new Error("Unsupported payment method");
1133
+ cardPaymentLogger.error("Invalid payment method for card payment", error, {
1134
+ actualType: selectedPaymentMethod.type,
1135
+ hasMethod: Boolean(selectedPaymentMethod.method)
1136
+ });
1137
+ throw error;
879
1138
  }
880
1139
  const { hash, capture, metadata } = params;
1140
+ cardPaymentLogger.info("Starting card payment", {
1141
+ hash,
1142
+ capture,
1143
+ hasMetadata: Boolean(metadata)
1144
+ });
881
1145
  const card = selectedPaymentMethod.method;
882
1146
  let cardId;
883
1147
  if ("token" in card) {
1148
+ cardPaymentLogger.debug("Adding new card from token", {
1149
+ lastFour: card.lastFourNumbers,
1150
+ schema: card.schema
1151
+ });
884
1152
  const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
885
1153
  cardId = cardResData.id;
1154
+ cardPaymentLogger.info("New card added successfully", { cardId });
886
1155
  } else {
887
1156
  cardId = card.id;
1157
+ cardPaymentLogger.debug("Using existing card", {
1158
+ cardId,
1159
+ lastFour: card.lastFourNumbers
1160
+ });
888
1161
  }
889
1162
  const transactionFee = getTransactionFee(appProps.amount, appProps.transactionFeePercentage);
1163
+ cardPaymentLogger.debug("Creating payment", {
1164
+ transactionFee,
1165
+ amount: appProps.amount,
1166
+ capture
1167
+ });
890
1168
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
891
1169
  hash,
892
1170
  capture,
@@ -899,13 +1177,38 @@ var useCardPayment = () => {
899
1177
  }
900
1178
  });
901
1179
  let { status } = paymentResData;
1180
+ cardPaymentLogger.info("Payment created", {
1181
+ paymentId: paymentResData.id,
1182
+ status,
1183
+ has3DS: Boolean(paymentResData.redirectUrl)
1184
+ });
902
1185
  if (paymentResData.redirectUrl) {
1186
+ cardPaymentLogger.debug("Starting 3DS flow", {
1187
+ paymentId: paymentResData.id
1188
+ });
903
1189
  const paymentIntent = await import_nice_modal_react2.default.show(Iframe3ds, { url: paymentResData.redirectUrl });
904
1190
  if (paymentIntent) {
1191
+ cardPaymentLogger.debug("3DS completed, validating", {
1192
+ paymentId: paymentResData.id,
1193
+ paymentIntent
1194
+ });
905
1195
  const { data: validateData } = await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
906
1196
  ({ status } = validateData);
1197
+ cardPaymentLogger.info("3DS validation completed", {
1198
+ paymentId: paymentResData.id,
1199
+ status
1200
+ });
1201
+ } else {
1202
+ cardPaymentLogger.warn("3DS flow cancelled by user", {
1203
+ paymentId: paymentResData.id
1204
+ });
907
1205
  }
908
1206
  }
1207
+ cardPaymentLogger.info("Card payment completed", {
1208
+ paymentId: paymentResData.id,
1209
+ status,
1210
+ txId: paymentResData.txId
1211
+ });
909
1212
  return {
910
1213
  status,
911
1214
  paymentType: "CREDIT_CARD" /* CREDIT_CARD */,
@@ -920,6 +1223,7 @@ var useCardPayment = () => {
920
1223
  // src/services/AirWalletService.ts
921
1224
  var import_airkit = require("@mocanetwork/airkit");
922
1225
  var import_viem = require("viem");
1226
+ var airWalletLogger = logger.child("airwallet");
923
1227
  var singletonState = null;
924
1228
  var initPromise = null;
925
1229
  var cachedKey = null;
@@ -971,16 +1275,19 @@ function peekAirWallet() {
971
1275
  async function handleSendErc20(params) {
972
1276
  const state = singletonState;
973
1277
  if (!state?.walletClient) {
974
- console.error("Air wallet is not initialized");
975
- throw new Error("Air wallet is not initialized");
1278
+ const error = new Error("Air wallet is not initialized");
1279
+ airWalletLogger.error("Wallet not initialized", error);
1280
+ throw error;
976
1281
  }
977
1282
  if (!params?.recipient) {
978
- console.error("Recipient address is not set");
979
- throw new Error("Recipient address is not set");
1283
+ const error = new Error("Recipient address is not set");
1284
+ airWalletLogger.error("Recipient address missing", error, { params });
1285
+ throw error;
980
1286
  }
981
1287
  if (!params?.token?.address || !params?.token?.decimals) {
982
- console.error("Token address or decimals not set");
983
- throw new Error("Token address or decimals not set");
1288
+ const error = new Error("Token address or decimals not set");
1289
+ airWalletLogger.error("Token configuration invalid", error, { token: params?.token });
1290
+ throw error;
984
1291
  }
985
1292
  try {
986
1293
  const { walletClient } = state;
@@ -1001,9 +1308,17 @@ async function handleSendErc20(params) {
1001
1308
  return { txHash: hash };
1002
1309
  } catch (error) {
1003
1310
  if (typeof error === "object" && error !== null && "shortMessage" in error) {
1004
- console.error(error.shortMessage);
1311
+ const { shortMessage } = error;
1312
+ airWalletLogger.error("ERC20 transfer failed", error instanceof Error ? error : void 0, {
1313
+ shortMessage,
1314
+ recipient: params.recipient,
1315
+ amount: params.amount
1316
+ });
1005
1317
  } else {
1006
- console.error("Your wallet balances are insufficient to complete this transaction.");
1318
+ airWalletLogger.error("Insufficient wallet balance for transaction", error instanceof Error ? error : void 0, {
1319
+ recipient: params.recipient,
1320
+ amount: params.amount
1321
+ });
1007
1322
  }
1008
1323
  }
1009
1324
  }
@@ -1056,14 +1371,29 @@ async function longPollCardStatus(paymentId) {
1056
1371
  }
1057
1372
 
1058
1373
  // src/hooks/payments/usePointsPayment.ts
1374
+ var pointsPaymentLogger = logger.child("points-payment");
1059
1375
  var usePointsPayment = (mode = "web2") => {
1060
1376
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1061
1377
  const { spreePayConfig } = useSpreePayConfig();
1062
1378
  const pointsPayment = async (params) => {
1063
1379
  if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */) {
1064
- throw new Error("Unsupported payment method");
1380
+ const error = new Error("Unsupported payment method");
1381
+ pointsPaymentLogger.error("Invalid payment method for points payment", error, {
1382
+ actualType: selectedPaymentMethod.type
1383
+ });
1384
+ throw error;
1065
1385
  }
1066
1386
  const { hash, capture, metadata } = params;
1387
+ pointsPaymentLogger.info("Starting points payment", {
1388
+ hash,
1389
+ capture,
1390
+ mode,
1391
+ points: params.points
1392
+ });
1393
+ pointsPaymentLogger.debug("Creating points payment", {
1394
+ mode,
1395
+ captureOverride: mode === "web2" ? true : capture
1396
+ });
1067
1397
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
1068
1398
  hash,
1069
1399
  // capture should be always true for web2 points payments
@@ -1071,24 +1401,57 @@ var usePointsPayment = (mode = "web2") => {
1071
1401
  metadata,
1072
1402
  type: "POINTS" /* POINTS */
1073
1403
  });
1404
+ pointsPaymentLogger.info("Points payment created", {
1405
+ paymentId: paymentResData.id,
1406
+ txId: paymentResData.txId,
1407
+ mode
1408
+ });
1074
1409
  if (mode === "web3") {
1410
+ pointsPaymentLogger.debug("Processing web3 points payment");
1075
1411
  const wallet = peekAirWallet();
1076
1412
  if (!wallet || !spreePayConfig?.pointsChain) {
1077
- throw new Error("AirWallet not found");
1413
+ const error = new Error("AirWallet not found");
1414
+ pointsPaymentLogger.error("AirWallet not available for web3 points", error, {
1415
+ hasWallet: Boolean(wallet),
1416
+ hasPointsChain: Boolean(spreePayConfig?.pointsChain)
1417
+ });
1418
+ throw error;
1078
1419
  }
1420
+ pointsPaymentLogger.debug("Sending ERC20 points transfer", {
1421
+ amount: params.points,
1422
+ recipient: spreePayConfig.pointsChain.recipientAddress
1423
+ });
1079
1424
  const transaction = await handleSendErc20({
1080
1425
  amount: params.points,
1081
1426
  token: spreePayConfig.pointsChain.pointsCoin,
1082
1427
  recipient: spreePayConfig.pointsChain.recipientAddress
1083
1428
  });
1084
1429
  if (!transaction) {
1085
- throw new Error("Points transaction failed");
1430
+ const error = new Error("Points transaction failed");
1431
+ pointsPaymentLogger.error("Points ERC20 transfer failed", error);
1432
+ throw error;
1086
1433
  }
1434
+ pointsPaymentLogger.info("Points transfer completed", {
1435
+ txHash: transaction.txHash,
1436
+ amount: params.points
1437
+ });
1438
+ pointsPaymentLogger.debug("Validating points transaction", {
1439
+ paymentId: paymentResData.id,
1440
+ txHash: transaction.txHash
1441
+ });
1087
1442
  await SlapiPaymentService.validatePoints({
1088
1443
  paymentId: paymentResData.id,
1089
1444
  txHash: transaction.txHash
1090
1445
  });
1446
+ pointsPaymentLogger.debug("Polling for points payment status", {
1447
+ paymentId: paymentResData.id
1448
+ });
1091
1449
  const pointsStatus2 = await longPollPoints(paymentResData.id);
1450
+ pointsPaymentLogger.info("Web3 points payment completed", {
1451
+ paymentId: paymentResData.id,
1452
+ status: pointsStatus2,
1453
+ txHash: transaction.txHash
1454
+ });
1092
1455
  return {
1093
1456
  status: pointsStatus2,
1094
1457
  txId: paymentResData.txId,
@@ -1097,7 +1460,14 @@ var usePointsPayment = (mode = "web2") => {
1097
1460
  paymentType: "POINTS" /* POINTS */
1098
1461
  };
1099
1462
  }
1463
+ pointsPaymentLogger.debug("Polling for web2 points payment status", {
1464
+ paymentId: paymentResData.id
1465
+ });
1100
1466
  const pointsStatus = await longPollPoints(paymentResData.id);
1467
+ pointsPaymentLogger.info("Web2 points payment completed", {
1468
+ paymentId: paymentResData.id,
1469
+ status: pointsStatus
1470
+ });
1101
1471
  return {
1102
1472
  status: pointsStatus,
1103
1473
  txId: paymentResData.txId,
@@ -1111,6 +1481,7 @@ var usePointsPayment = (mode = "web2") => {
1111
1481
 
1112
1482
  // src/hooks/payments/useSplitCardPayments.ts
1113
1483
  var import_nice_modal_react4 = __toESM(require("@ebay/nice-modal-react"), 1);
1484
+ var splitPaymentLogger = logger.child("split-card-payment");
1114
1485
  var useSplitCardPayments = (mode = "web2") => {
1115
1486
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1116
1487
  const { env } = useSpreePayEnv();
@@ -1121,16 +1492,30 @@ var useSplitCardPayments = (mode = "web2") => {
1121
1492
  throw new Error("Unsupported payment method");
1122
1493
  }
1123
1494
  const { hash, capture, metadata, points } = params;
1495
+ splitPaymentLogger.info("Starting split card+points payment", { hash, mode, points, capture });
1124
1496
  const card = selectedPaymentMethod.method;
1125
1497
  let cardId;
1126
1498
  if ("token" in card) {
1499
+ splitPaymentLogger.debug("Adding new card from token", {
1500
+ lastFour: card.lastFourNumbers,
1501
+ schema: card.schema
1502
+ });
1127
1503
  const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
1128
1504
  cardId = cardResData.id;
1505
+ splitPaymentLogger.debug("Card added successfully", { cardId });
1129
1506
  } else {
1130
1507
  cardId = card.id;
1508
+ splitPaymentLogger.debug("Using existing card", { cardId });
1131
1509
  }
1132
1510
  const usdAmount = getSplitAmount(appProps.amount ?? 0, points, spreePayConfig?.pointsConversionRatio);
1133
1511
  const transactionFee = getTransactionFee(usdAmount, appProps.transactionFeePercentage);
1512
+ splitPaymentLogger.debug("Calculated split amounts", {
1513
+ totalAmount: appProps.amount,
1514
+ points,
1515
+ usdAmount,
1516
+ transactionFee,
1517
+ conversionRatio: spreePayConfig?.pointsConversionRatio
1518
+ });
1134
1519
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
1135
1520
  hash,
1136
1521
  capture,
@@ -1145,31 +1530,64 @@ var useSplitCardPayments = (mode = "web2") => {
1145
1530
  amount: points
1146
1531
  }
1147
1532
  });
1533
+ splitPaymentLogger.info("Split payment created", {
1534
+ paymentId: paymentResData.id,
1535
+ status: paymentResData.status,
1536
+ has3DS: Boolean(paymentResData.redirectUrl)
1537
+ });
1148
1538
  if (paymentResData.redirectUrl) {
1539
+ splitPaymentLogger.debug("Starting 3DS flow for card portion", { paymentId: paymentResData.id });
1149
1540
  const paymentIntent = await import_nice_modal_react4.default.show(Iframe3ds, { url: paymentResData.redirectUrl });
1150
1541
  if (paymentIntent) {
1542
+ splitPaymentLogger.debug("3DS completed, validating", { paymentId: paymentResData.id });
1151
1543
  await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
1544
+ } else {
1545
+ splitPaymentLogger.warn("3DS flow canceled or failed", { paymentId: paymentResData.id });
1152
1546
  }
1153
1547
  }
1548
+ splitPaymentLogger.debug("Polling card payment status", { paymentId: paymentResData.id });
1154
1549
  const cardStatus = await longPollCardStatus(paymentResData.id);
1550
+ splitPaymentLogger.info("Card portion completed", { paymentId: paymentResData.id, cardStatus });
1155
1551
  if (mode === "web3") {
1552
+ splitPaymentLogger.info("Processing web3 points transfer", { points });
1156
1553
  const wallet = peekAirWallet();
1157
1554
  if (!wallet || !spreePayConfig?.pointsChain) {
1555
+ splitPaymentLogger.error("AirWallet not initialized for web3 points transfer", void 0, {
1556
+ hasWallet: Boolean(wallet),
1557
+ hasPointsChain: Boolean(spreePayConfig?.pointsChain)
1558
+ });
1158
1559
  throw new Error("AirWallet not found");
1159
1560
  }
1561
+ splitPaymentLogger.debug("Sending ERC20 points transfer", {
1562
+ amount: params.points,
1563
+ token: spreePayConfig.pointsChain.pointsCoin,
1564
+ recipient: spreePayConfig.pointsChain.recipientAddress
1565
+ });
1160
1566
  const transaction = await handleSendErc20({
1161
1567
  amount: params.points,
1162
1568
  token: spreePayConfig.pointsChain.pointsCoin,
1163
1569
  recipient: spreePayConfig.pointsChain.recipientAddress
1164
1570
  });
1165
1571
  if (!transaction) {
1572
+ splitPaymentLogger.error("Points transaction failed", void 0, { points });
1166
1573
  throw new Error("Points transaction failed");
1167
1574
  }
1575
+ splitPaymentLogger.info("Points transfer completed", { txHash: transaction.txHash });
1576
+ splitPaymentLogger.debug("Validating points transaction", {
1577
+ paymentId: paymentResData.id,
1578
+ txHash: transaction.txHash
1579
+ });
1168
1580
  await SlapiPaymentService.validatePoints({
1169
1581
  paymentId: paymentResData.id,
1170
1582
  txHash: transaction.txHash
1171
1583
  });
1584
+ splitPaymentLogger.debug("Polling points payment status", { paymentId: paymentResData.id });
1172
1585
  const pointsStatus = await longPollPoints(paymentResData.id);
1586
+ splitPaymentLogger.info("Web3 split payment completed", {
1587
+ paymentId: paymentResData.id,
1588
+ status: pointsStatus,
1589
+ txHash: transaction.txHash
1590
+ });
1173
1591
  return {
1174
1592
  paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
1175
1593
  status: pointsStatus,
@@ -1178,6 +1596,10 @@ var useSplitCardPayments = (mode = "web2") => {
1178
1596
  txHash: transaction.txHash
1179
1597
  };
1180
1598
  }
1599
+ splitPaymentLogger.info("Web2 split payment completed", {
1600
+ paymentId: paymentResData.id,
1601
+ status: cardStatus
1602
+ });
1181
1603
  return {
1182
1604
  paymentType: "SPLIT" /* CREDIT_CARD_SPLIT */,
1183
1605
  status: cardStatus,
@@ -1258,13 +1680,7 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
1258
1680
  "cursor-not-allowed opacity-50": isSelected || isRemoveDisabled
1259
1681
  // 'cursor-pointer': !isSelected || !isRemoveDisabled,
1260
1682
  }),
1261
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1262
- "path",
1263
- {
1264
- fill: "currentColor",
1265
- 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"
1266
- }
1267
- ) })
1683
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", className: "size-5", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" }) })
1268
1684
  }
1269
1685
  )
1270
1686
  ] })
@@ -1357,6 +1773,7 @@ function Checkbox({ className, ...props }) {
1357
1773
 
1358
1774
  // src/components/CreditCardTab/CreditCard/CreditCardForm.tsx
1359
1775
  var import_jsx_runtime15 = require("react/jsx-runtime");
1776
+ var cardFormLogger = logger.child("card-form");
1360
1777
  var styleDark = {
1361
1778
  base: {
1362
1779
  fontSize: "16px",
@@ -1424,7 +1841,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
1424
1841
  }
1425
1842
  }
1426
1843
  } catch (error) {
1427
- console.error("Error creating card token:", error);
1844
+ cardFormLogger.error("Failed to create Stripe card token", error);
1428
1845
  setCardError("An error occurred while processing your card. Please try again.");
1429
1846
  }
1430
1847
  };
@@ -2627,6 +3044,7 @@ var PointsSelector = (props) => {
2627
3044
 
2628
3045
  // src/components/CreditCardTab/Points/SplitBlock.tsx
2629
3046
  var import_jsx_runtime26 = require("react/jsx-runtime");
3047
+ var splitBlockLogger = logger.child("split-block");
2630
3048
  var SplitBlock = (props) => {
2631
3049
  const { onToggle, isSelected, onSelect } = props;
2632
3050
  const { balance, isBalanceLoading } = useSlapiBalance();
@@ -2651,7 +3069,10 @@ var SplitBlock = (props) => {
2651
3069
  onToggle(false);
2652
3070
  }
2653
3071
  } catch (e) {
2654
- console.error("Air Wallet init failed:", e);
3072
+ splitBlockLogger.error("Air Wallet initialization failed", e, {
3073
+ partnerId: pointsChain?.partnerId,
3074
+ environment: env.environment
3075
+ });
2655
3076
  }
2656
3077
  },
2657
3078
  [onToggle, env.environment]
@@ -2786,6 +3207,7 @@ var import_react14 = require("react");
2786
3207
 
2787
3208
  // src/hooks/payments/useCryptoComPayment.ts
2788
3209
  var import_nice_modal_react5 = __toESM(require("@ebay/nice-modal-react"), 1);
3210
+ var cryptoComLogger = logger.child("crypto-com-payment");
2789
3211
  var useCryptoComPayment = () => {
2790
3212
  const { selectedPaymentMethod } = useSpreePaymentMethod();
2791
3213
  const { env } = useSpreePayEnv();
@@ -2794,6 +3216,7 @@ var useCryptoComPayment = () => {
2794
3216
  throw new Error("Unsupported payment method");
2795
3217
  }
2796
3218
  const { hash, metadata } = params;
3219
+ cryptoComLogger.info("Starting Crypto.com Pay payment", { hash });
2797
3220
  const { data: paymentResData } = await SlapiPaymentService.createPayment({
2798
3221
  hash,
2799
3222
  metadata,
@@ -2803,16 +3226,31 @@ var useCryptoComPayment = () => {
2803
3226
  cancelUrl: `${typeof window !== "undefined" ? window.location.origin : ""}${env.redirect3dsURI}?payment_intent=canceled`
2804
3227
  }
2805
3228
  });
3229
+ cryptoComLogger.info("Payment created", {
3230
+ paymentId: paymentResData.id,
3231
+ status: paymentResData.status,
3232
+ hasRedirect: Boolean(paymentResData.redirectUrl)
3233
+ });
2806
3234
  let { status } = paymentResData;
2807
3235
  if (paymentResData.redirectUrl) {
3236
+ cryptoComLogger.debug("Opening CDC payment redirect", { paymentId: paymentResData.id });
2808
3237
  const paymentIntent = await import_nice_modal_react5.default.show(Iframe3ds, { url: paymentResData.redirectUrl });
3238
+ cryptoComLogger.info("CDC payment redirect completed", { paymentIntent });
2809
3239
  if (paymentIntent === "success") {
3240
+ cryptoComLogger.debug("Validating CDC payment", { paymentId: paymentResData.id });
2810
3241
  const { data: validateData } = await SlapiPaymentService.validateCDC({ paymentId: paymentResData.id });
2811
3242
  ({ status } = validateData);
3243
+ cryptoComLogger.info("CDC payment validated", { paymentId: paymentResData.id, status });
2812
3244
  } else {
2813
3245
  status = "FAILED" /* FAILED */;
3246
+ cryptoComLogger.warn("CDC payment canceled or failed", { paymentIntent });
2814
3247
  }
2815
3248
  }
3249
+ cryptoComLogger.info("Crypto.com Pay payment completed", {
3250
+ paymentId: paymentResData.id,
3251
+ status,
3252
+ txId: paymentResData.txId
3253
+ });
2816
3254
  return {
2817
3255
  status,
2818
3256
  paymentType: "CDC" /* CDC */,
@@ -2834,7 +3272,7 @@ var Checkout = () => {
2834
3272
  onClick: appProps.onProcess,
2835
3273
  disabled: appProps.isProcessing,
2836
3274
  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)",
2837
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "76", height: "28", fill: "none", viewBox: "0 0 76 28", children: [
3275
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-7 w-[76px]", fill: "none", viewBox: "0 0 76 28", children: [
2838
3276
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2839
3277
  "path",
2840
3278
  {
@@ -3025,6 +3463,7 @@ var BASE_TOKENS = [
3025
3463
 
3026
3464
  // src/hooks/payments/useCryptoPayment.ts
3027
3465
  var MAX_UINT256 = BigInt(2) ** BigInt(256) - BigInt(1);
3466
+ var cryptoPaymentLogger = logger.child("crypto-payment");
3028
3467
  var useCryptoPayment = () => {
3029
3468
  const { data: walletClient } = (0, import_wagmi.useWalletClient)();
3030
3469
  const { spreePayConfig } = useSpreePayConfig();
@@ -3032,21 +3471,43 @@ var useCryptoPayment = () => {
3032
3471
  const { selectedPaymentMethod } = useSpreePaymentMethod();
3033
3472
  const cryptoPayment = async (params) => {
3034
3473
  if (!walletClient) {
3035
- throw new Error("Wallet not connected");
3474
+ const error = new Error("Wallet not connected");
3475
+ cryptoPaymentLogger.error("Wallet not connected for crypto payment", error);
3476
+ throw error;
3036
3477
  }
3037
3478
  if (!spreePayConfig) {
3038
- throw new Error("Spree Pay config not loaded");
3479
+ const error = new Error("Spree Pay config not loaded");
3480
+ cryptoPaymentLogger.error("Config not loaded for crypto payment", error);
3481
+ throw error;
3039
3482
  }
3040
3483
  if (selectedPaymentMethod.type !== "CRYPTO" /* CRYPTO */ || !selectedPaymentMethod.method?.symbol) {
3041
- throw new Error("Unsupported payment method");
3484
+ const error = new Error("Unsupported payment method");
3485
+ cryptoPaymentLogger.error("Invalid payment method for crypto payment", error, {
3486
+ actualType: selectedPaymentMethod.type,
3487
+ hasMethod: Boolean(selectedPaymentMethod.method)
3488
+ });
3489
+ throw error;
3042
3490
  }
3043
3491
  const { capture, hash, metadata } = params;
3044
3492
  const TOKEN = selectedPaymentMethod.method.symbol;
3493
+ cryptoPaymentLogger.info("Starting crypto payment", {
3494
+ hash,
3495
+ capture,
3496
+ token: TOKEN,
3497
+ walletAddress: walletClient.account.address
3498
+ });
3045
3499
  if (["MOCA" /* MOCA */, "WETH" /* WETH */, "USDC" /* USDC */, "USDT" /* USDT */].includes(TOKEN)) {
3046
3500
  const tokenAddress = selectedPaymentMethod.method.address;
3047
3501
  if (!tokenAddress) {
3048
- throw new Error("Token address not found");
3502
+ const error = new Error("Token address not found");
3503
+ cryptoPaymentLogger.error("Token address missing", error, { token: TOKEN });
3504
+ throw error;
3049
3505
  }
3506
+ cryptoPaymentLogger.debug("Checking token allowance", {
3507
+ token: TOKEN,
3508
+ tokenAddress,
3509
+ router: spreePayConfig.crypto.oneInchAggregationRouter
3510
+ });
3050
3511
  const allowance = await readContract(config2, {
3051
3512
  address: tokenAddress,
3052
3513
  abi: import_viem4.erc20Abi,
@@ -3054,19 +3515,36 @@ var useCryptoPayment = () => {
3054
3515
  args: [walletClient.account.address, spreePayConfig.crypto.oneInchAggregationRouter]
3055
3516
  });
3056
3517
  if (allowance <= 0n) {
3518
+ cryptoPaymentLogger.info("Requesting token approval", {
3519
+ token: TOKEN,
3520
+ tokenAddress
3521
+ });
3057
3522
  const result = await walletClient.writeContract({
3058
3523
  address: tokenAddress,
3059
3524
  abi: import_viem4.erc20Abi,
3060
3525
  functionName: "approve",
3061
3526
  args: [spreePayConfig.crypto.oneInchAggregationRouter, MAX_UINT256]
3062
3527
  });
3528
+ cryptoPaymentLogger.debug("Waiting for approval confirmation", {
3529
+ approvalTxHash: result
3530
+ });
3063
3531
  await waitForTransactionReceipt(config2, {
3064
3532
  hash: result,
3065
3533
  confirmations: 1
3066
- // You can change the number of block confirmations as per your requirement
3534
+ });
3535
+ cryptoPaymentLogger.info("Token approval confirmed", {
3536
+ approvalTxHash: result
3537
+ });
3538
+ } else {
3539
+ cryptoPaymentLogger.debug("Sufficient allowance exists", {
3540
+ allowance: allowance.toString()
3067
3541
  });
3068
3542
  }
3069
3543
  }
3544
+ cryptoPaymentLogger.debug("Creating crypto payment", {
3545
+ token: TOKEN,
3546
+ slippageBps: Math.round(0.5 * 100)
3547
+ });
3070
3548
  const paymentRes = await SlapiPaymentService.createPayment({
3071
3549
  hash,
3072
3550
  capture,
@@ -3079,19 +3557,42 @@ var useCryptoPayment = () => {
3079
3557
  slippageBps: Math.round(0.5 * 100)
3080
3558
  }
3081
3559
  });
3560
+ cryptoPaymentLogger.info("Crypto payment created", {
3561
+ paymentId: paymentRes.data.id,
3562
+ txId: paymentRes.data.txId
3563
+ });
3082
3564
  const parsedTX = JSON.parse(paymentRes.data.encodedTx);
3565
+ cryptoPaymentLogger.debug("Sending transaction", {
3566
+ to: parsedTX.to,
3567
+ value: parsedTX.value.toString()
3568
+ });
3083
3569
  const txHash = await walletClient.sendTransaction({
3084
3570
  account: walletClient.account.address,
3085
3571
  to: parsedTX.to,
3086
3572
  data: parsedTX.data,
3087
3573
  value: parsedTX.value
3088
3574
  });
3575
+ cryptoPaymentLogger.info("Transaction sent", {
3576
+ txHash,
3577
+ paymentId: paymentRes.data.id
3578
+ });
3579
+ cryptoPaymentLogger.debug("Verifying transaction on chain", {
3580
+ txId: paymentRes.data.txId,
3581
+ txHash
3582
+ });
3089
3583
  const res = await SlapiPaymentService.baseVerify({ id: paymentRes.data.txId, txHash });
3584
+ const finalStatus = res.verified ? "CAPTURED" /* CAPTURED */ : "FAILED" /* FAILED */;
3585
+ cryptoPaymentLogger.info("Crypto payment completed", {
3586
+ paymentId: paymentRes.data.id,
3587
+ txHash,
3588
+ verified: res.verified,
3589
+ status: finalStatus
3590
+ });
3090
3591
  return {
3091
3592
  txHash,
3092
3593
  paymentId: paymentRes.data.id,
3093
3594
  txId: paymentRes.data.txId,
3094
- status: res.verified ? "CAPTURED" /* CAPTURED */ : "FAILED" /* FAILED */,
3595
+ status: finalStatus,
3095
3596
  paymentType: "CRYPTO" /* CRYPTO */
3096
3597
  };
3097
3598
  };
@@ -3122,48 +3623,45 @@ var ConnectButton = () => {
3122
3623
 
3123
3624
  // src/config/symbolLogos.tsx
3124
3625
  var import_jsx_runtime32 = require("react/jsx-runtime");
3125
- var MOCA_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3126
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("circle", { cx: "14", cy: "14", r: "13.5", fill: "#C15F97" }),
3626
+ var MOCA_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-7", viewBox: "0 0 28 28", children: [
3627
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("circle", { cx: "14", cy: "14", r: "13.5", fill: "#c15f97" }),
3127
3628
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3128
3629
  "path",
3129
3630
  {
3130
3631
  fill: "#fff",
3131
- 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"
3632
+ 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"
3132
3633
  }
3133
3634
  ),
3134
3635
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("circle", { cx: "16", cy: "14", r: "1.5", fill: "#fff" })
3135
3636
  ] });
3136
- var USDC_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3137
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("g", { clipPath: "url(#clip0_528_9163)", children: [
3138
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }),
3139
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3140
- "path",
3141
- {
3142
- fill: "#fff",
3143
- 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"
3144
- }
3145
- ),
3146
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3147
- "path",
3148
- {
3149
- fill: "#fff",
3150
- 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"
3151
- }
3152
- )
3153
- ] }),
3154
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("clipPath", { id: "clip0_528_9163", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { fill: "#fff", d: "M0 0h28v28H0z" }) }) })
3637
+ var USDC_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-7", fill: "none", viewBox: "0 0 28 28", children: [
3638
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }),
3639
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3640
+ "path",
3641
+ {
3642
+ fill: "#fff",
3643
+ 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"
3644
+ }
3645
+ ),
3646
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3647
+ "path",
3648
+ {
3649
+ fill: "#fff",
3650
+ 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"
3651
+ }
3652
+ )
3155
3653
  ] });
3156
- var USDT_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
3157
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { fill: "#26A17B", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28Z" }),
3654
+ var USDT_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-7", fill: "none", viewBox: "0 0 28 28", children: [
3655
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { fill: "#26a17b", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28" }),
3158
3656
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3159
3657
  "path",
3160
3658
  {
3161
3659
  fill: "#fff",
3162
- 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"
3660
+ 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"
3163
3661
  }
3164
3662
  )
3165
3663
  ] });
3166
- var WETH_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", width: "28", height: "28", viewBox: "0 0 24 24", children: [
3664
+ var WETH_SVG = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-7", viewBox: "0 0 24 24", children: [
3167
3665
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("g", { clipPath: "url(#clip0_528_9173)", children: [
3168
3666
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3169
3667
  "path",
@@ -3461,9 +3959,9 @@ var CryptoSelectModal = import_nice_modal_react6.default.create(() => {
3461
3959
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(DialogContent, { showCloseButton: false, className: "max-h-[90vh] gap-0 p-0", children: [
3462
3960
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-4 px-5 py-5 md:px-7", children: [
3463
3961
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
3464
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { className: "rounded-md hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "25", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("path", { stroke: "currentColor", d: "m15 6.5-6 6 6 6" }) }) }),
3962
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { className: "rounded-md hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-6", viewBox: "0 0 24 25", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("path", { stroke: "currentColor", d: "m15 6.5-6 6 6 6" }) }) }),
3465
3963
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(DialogTitle, { className: "text-2xl font-medium text-(--brand-primary)", children: "Select a token" }),
3466
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { className: "rounded-md p-1 hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "17", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3964
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { className: "rounded-md p-1 hover:bg-(--s-primary-hover)", onClick: modal.remove, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-4", viewBox: "0 0 16 17", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3467
3965
  "path",
3468
3966
  {
3469
3967
  fill: "currentColor",
@@ -3561,7 +4059,7 @@ var SelectCoinButton = () => {
3561
4059
  className: "flex h-11 w-full overflow-hidden rounded-md bg-(--s-primary) hover:bg-(--s-primary-hover)",
3562
4060
  children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex h-full w-full items-center justify-between px-3", children: [
3563
4061
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "font-medium text-(--secondary)", children: "Select a token" }) }),
3564
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", d: "m6 12.43 4-4-4-4" }) })
4062
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-4", viewBox: "0 0 16 16", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("path", { stroke: "currentColor", d: "m6 12.43 4-4-4-4" }) })
3565
4063
  ] })
3566
4064
  }
3567
4065
  );
@@ -3579,7 +4077,7 @@ var SelectedCoin = (props) => {
3579
4077
  Icon,
3580
4078
  !Icon && logoURI && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("img", { className: "mr-1 size-8 shrink-0", src: logoURI, alt: `${coin} logo` }),
3581
4079
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "font-semibold text-(--brand-primary)", children: coin }),
3582
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("path", { d: "M6 12.4341L10 8.43408L6 4.43408", stroke: "currentColor", strokeLinecap: "round" }) })
4080
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-4", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("path", { stroke: "currentColor", d: "m6 12.434 4-4-4-4" }) })
3583
4081
  ] }),
3584
4082
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "text-xs font-medium text-(--secondary)", children: [
3585
4083
  "Wallet balance ",
@@ -3699,49 +4197,39 @@ var TabButtons = (props) => {
3699
4197
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-4", children: [
3700
4198
  configIsLoading && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "h-[74px] w-[180px] animate-pulse rounded-md bg-(--s-primary)" }),
3701
4199
  spreePayConfig?.creditCard.enabled && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(TabButton, { onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */), isActive: value === "CREDIT_CARD" /* CREDIT_CARD */, children: [
3702
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", fill: "none", viewBox: "0 0 32 32", children: [
3703
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("mask", { id: "a", width: "32", height: "32", x: "0", y: "0", maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { fill: "#d9d9d9", d: "M0 0h32v32H0z" }) }),
3704
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("g", { mask: "url(#a)", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3705
- "path",
3706
- {
3707
- fill: "currentColor",
3708
- 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"
3709
- }
3710
- ) })
3711
- ] }),
4200
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-8", viewBox: "0 0 32 32", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4201
+ "path",
4202
+ {
4203
+ fill: "currentColor",
4204
+ 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"
4205
+ }
4206
+ ) }),
3712
4207
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-md font-medium", children: "Card" })
3713
4208
  ] }),
3714
4209
  spreePayConfig?.crypto.enabled && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(TabButton, { onClick: handleChange("CRYPTO" /* CRYPTO */), isActive: value === "CRYPTO" /* CRYPTO */, children: [
3715
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", fill: "none", viewBox: "0 0 32 32", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4210
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "size-8", viewBox: "0 0 32 32", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3716
4211
  "path",
3717
4212
  {
3718
4213
  fill: "currentColor",
3719
- fillRule: "evenodd",
3720
- 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",
3721
- clipRule: "evenodd"
4214
+ 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"
3722
4215
  }
3723
4216
  ) }),
3724
4217
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-md font-medium", children: "Crypto" })
3725
4218
  ] }),
3726
4219
  spreePayConfig?.cryptoCom.enabled && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(TabButton, { onClick: handleChange("CDC" /* CDC */), isActive: value === "CDC" /* CDC */, children: [
3727
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "44", height: "32", fill: "none", viewBox: "0 0 44 32", children: [
4220
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", className: "h-8 w-11", viewBox: "0 0 44 32", children: [
3728
4221
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3729
4222
  "path",
3730
4223
  {
3731
4224
  fill: "currentColor",
3732
- fillRule: "evenodd",
3733
- 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",
3734
- clipRule: "evenodd"
4225
+ 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"
3735
4226
  }
3736
4227
  ),
3737
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("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" }),
3738
4228
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3739
4229
  "path",
3740
4230
  {
3741
4231
  fill: "#009fff",
3742
- fillRule: "evenodd",
3743
- 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",
3744
- clipRule: "evenodd"
4232
+ 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"
3745
4233
  }
3746
4234
  )
3747
4235
  ] }),
@@ -3771,21 +4259,70 @@ var SpreePayContent = ({ isLoggedIn }) => {
3771
4259
  ] });
3772
4260
  };
3773
4261
 
3774
- // src/hooks/useKeycloakSSO.ts
4262
+ // src/components/ErrorBoundary.tsx
3775
4263
  var import_react18 = require("react");
4264
+ var import_jsx_runtime46 = require("react/jsx-runtime");
4265
+ var ErrorBoundary = class extends import_react18.Component {
4266
+ constructor(props) {
4267
+ super(props);
4268
+ this.state = { hasError: false, error: null };
4269
+ }
4270
+ static getDerivedStateFromError(error) {
4271
+ return { hasError: true, error };
4272
+ }
4273
+ componentDidCatch(error, errorInfo) {
4274
+ logger.error("Widget error caught by ErrorBoundary", error, {
4275
+ componentStack: errorInfo.componentStack
4276
+ });
4277
+ }
4278
+ render() {
4279
+ if (this.state.hasError) {
4280
+ if (this.props.fallback) {
4281
+ return this.props.fallback;
4282
+ }
4283
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col items-center justify-center rounded-3xl border border-(--b-inverse) bg-(--s-primary) p-8", children: [
4284
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mb-4 flex size-12 items-center justify-center rounded-full bg-(--s-secondary)", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
4285
+ "svg",
4286
+ {
4287
+ xmlns: "http://www.w3.org/2000/svg",
4288
+ viewBox: "0 0 24 24",
4289
+ fill: "none",
4290
+ stroke: "currentColor",
4291
+ strokeWidth: "2",
4292
+ strokeLinecap: "round",
4293
+ strokeLinejoin: "round",
4294
+ className: "size-10 text-(--warning)",
4295
+ children: [
4296
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
4297
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
4298
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
4299
+ ]
4300
+ }
4301
+ ) }),
4302
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h3", { className: "mb-2 text-lg font-semibold text-(--primary)", children: "Payment Widget Error" }),
4303
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-center text-sm text-(--secondary)", children: "Something went wrong loading the payment widget. Please refresh the page and try again." })
4304
+ ] });
4305
+ }
4306
+ return this.props.children;
4307
+ }
4308
+ };
4309
+
4310
+ // src/hooks/useKeycloakSSO.ts
4311
+ var import_react19 = require("react");
3776
4312
  var import_keycloak_js = __toESM(require("keycloak-js"), 1);
3777
4313
  var refreshAheadSeconds = 60;
4314
+ var keycloakLogger = logger.child("keycloak");
3778
4315
  function useKeycloakSSO(config2) {
3779
4316
  const { url, realm, clientId, ssoPageURI, enabled } = config2;
3780
- const initRef = (0, import_react18.useRef)(false);
3781
- const kcRef = (0, import_react18.useRef)(null);
3782
- const refreshTimerRef = (0, import_react18.useRef)(null);
3783
- const scheduleRefreshRef = (0, import_react18.useRef)(() => {
4317
+ const initRef = (0, import_react19.useRef)(false);
4318
+ const kcRef = (0, import_react19.useRef)(null);
4319
+ const refreshTimerRef = (0, import_react19.useRef)(null);
4320
+ const scheduleRefreshRef = (0, import_react19.useRef)(() => {
3784
4321
  });
3785
- const [error, setError] = (0, import_react18.useState)(null);
3786
- const [isChecking, setIsChecking] = (0, import_react18.useState)(enabled);
3787
- const [accessToken, setAccessToken] = (0, import_react18.useState)(null);
3788
- const scheduleRefresh = (0, import_react18.useCallback)(() => {
4322
+ const [error, setError] = (0, import_react19.useState)(null);
4323
+ const [isChecking, setIsChecking] = (0, import_react19.useState)(enabled);
4324
+ const [accessToken, setAccessToken] = (0, import_react19.useState)(null);
4325
+ const scheduleRefresh = (0, import_react19.useCallback)(() => {
3789
4326
  const kc = kcRef.current;
3790
4327
  if (!kc || !kc.tokenParsed || !kc.tokenParsed.exp) {
3791
4328
  return;
@@ -3801,15 +4338,18 @@ function useKeycloakSSO(config2) {
3801
4338
  setAccessToken(kc.token ?? null);
3802
4339
  scheduleRefreshRef.current();
3803
4340
  }
3804
- }).catch((_) => {
3805
- kc.login().catch(console.error);
4341
+ }).catch((err) => {
4342
+ keycloakLogger.error("Token refresh failed, redirecting to login", err);
4343
+ kc.login().catch((loginErr) => {
4344
+ keycloakLogger.error("Login redirect failed", loginErr);
4345
+ });
3806
4346
  });
3807
4347
  }, delayMs);
3808
4348
  }, []);
3809
- (0, import_react18.useEffect)(() => {
4349
+ (0, import_react19.useEffect)(() => {
3810
4350
  scheduleRefreshRef.current = scheduleRefresh;
3811
4351
  }, [scheduleRefresh]);
3812
- (0, import_react18.useEffect)(() => {
4352
+ (0, import_react19.useEffect)(() => {
3813
4353
  if (initRef.current || !enabled) return;
3814
4354
  initRef.current = true;
3815
4355
  const kc = new import_keycloak_js.default({ url, realm, clientId });
@@ -3821,7 +4361,7 @@ function useKeycloakSSO(config2) {
3821
4361
  scheduleRefresh();
3822
4362
  }
3823
4363
  }).catch((err) => {
3824
- console.error("[Keycloak] onTokenExpired refresh failed", err);
4364
+ keycloakLogger.error("Token expired refresh failed", err);
3825
4365
  });
3826
4366
  };
3827
4367
  kc.init({
@@ -3829,7 +4369,7 @@ function useKeycloakSSO(config2) {
3829
4369
  silentCheckSsoRedirectUri: `${window.location.origin}${ssoPageURI}`,
3830
4370
  silentCheckSsoFallback: true
3831
4371
  }).then((auth) => {
3832
- console.info("[Keycloak] init success, authenticated=", auth);
4372
+ keycloakLogger.info("SSO initialization successful", { authenticated: auth });
3833
4373
  setAccessToken(kc.token ?? null);
3834
4374
  if (auth) scheduleRefresh();
3835
4375
  }).catch((err) => {
@@ -3843,18 +4383,19 @@ function useKeycloakSSO(config2) {
3843
4383
  }
3844
4384
 
3845
4385
  // src/SpreePay.tsx
3846
- var import_jsx_runtime46 = require("react/jsx-runtime");
4386
+ var import_jsx_runtime47 = require("react/jsx-runtime");
3847
4387
  var SpreePayInner = () => {
3848
- const [portalEl, setPortalEl] = (0, import_react19.useState)(null);
3849
- const rootRef = (0, import_react19.useCallback)((node) => {
4388
+ const [portalEl, setPortalEl] = (0, import_react20.useState)(null);
4389
+ const rootRef = (0, import_react20.useCallback)((node) => {
3850
4390
  if (!node) return;
3851
4391
  const el = node.querySelector(":scope > .sl-spreepay__portal");
3852
4392
  setPortalEl(el ?? null);
3853
4393
  }, []);
3854
- (0, import_react19.useEffect)(() => {
3855
- console.log(`[spree-pay] v${version}`);
3856
- }, []);
3857
4394
  const { env } = useSpreePayEnv();
4395
+ (0, import_react20.useEffect)(() => {
4396
+ configureLogger({ environment: env.environment });
4397
+ logger.logVersion();
4398
+ }, [env.environment]);
3858
4399
  const { staticConfig, appProps } = useStaticConfig();
3859
4400
  const tenantId = env?.tenantId;
3860
4401
  const { isChecking, accessToken } = useKeycloakSSO({
@@ -3865,8 +4406,8 @@ var SpreePayInner = () => {
3865
4406
  enabled: !env?.accessToken
3866
4407
  });
3867
4408
  const _accessToken = env.accessToken ?? accessToken;
3868
- const unauthenticatedFetcher = (0, import_react19.useCallback)(() => Promise.resolve(null), []);
3869
- const slapiFetcher = (0, import_react19.useMemo)(() => {
4409
+ const unauthenticatedFetcher = (0, import_react20.useCallback)(() => Promise.resolve(null), []);
4410
+ const slapiFetcher = (0, import_react20.useMemo)(() => {
3870
4411
  if (_accessToken) {
3871
4412
  return registerApi({
3872
4413
  accessToken: _accessToken,
@@ -3878,12 +4419,12 @@ var SpreePayInner = () => {
3878
4419
  }, [_accessToken, staticConfig, tenantId, unauthenticatedFetcher]);
3879
4420
  const getContent = () => {
3880
4421
  if (isChecking) {
3881
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col", children: [
3882
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mb-4 h-[315px] animate-pulse rounded-3xl bg-(--s-primary)" }),
3883
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "h-[135px] animate-pulse rounded-3xl bg-(--s-primary)" })
4422
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex w-full flex-col", children: [
4423
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "mb-4 h-[315px] animate-pulse rounded-3xl bg-(--s-primary)" }),
4424
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "h-[135px] animate-pulse rounded-3xl bg-(--s-primary)" })
3884
4425
  ] });
3885
4426
  }
3886
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4427
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3887
4428
  import_swr5.SWRConfig,
3888
4429
  {
3889
4430
  value: {
@@ -3892,23 +4433,23 @@ var SpreePayInner = () => {
3892
4433
  revalidateOnFocus: false,
3893
4434
  revalidateIfStale: false
3894
4435
  },
3895
- children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_nice_modal_react9.default.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(SpreePayContent, { isLoggedIn: Boolean(_accessToken) }) }) })
4436
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_nice_modal_react9.default.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SpreePayContent, { isLoggedIn: Boolean(_accessToken) }) }) })
3896
4437
  }
3897
4438
  );
3898
4439
  };
3899
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { ref: rootRef, className: cn("sl-spreepay", appProps.className), children: [
3900
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "sl-spreepay__portal" }),
4440
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { ref: rootRef, className: cn("sl-spreepay", appProps.className), children: [
4441
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "sl-spreepay__portal" }),
3901
4442
  getContent()
3902
4443
  ] });
3903
4444
  };
3904
4445
  var SpreePay = (props) => {
3905
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(StaticConfigProvider, { props, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(SpreePayInner, {}) });
4446
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(StaticConfigProvider, { props, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SpreePayInner, {}) }) });
3906
4447
  };
3907
4448
 
3908
4449
  // src/hooks/useCapture3DS.ts
3909
- var import_react20 = require("react");
4450
+ var import_react21 = require("react");
3910
4451
  var useCapture3DS = (searchParams) => {
3911
- (0, import_react20.useEffect)(() => {
4452
+ (0, import_react21.useEffect)(() => {
3912
4453
  if (typeof window !== "undefined" && window.parent && searchParams?.paymentIntent) {
3913
4454
  window.parent.SP_EVENT_BUS?.emit("paymentIntent", { paymentIntent: searchParams.paymentIntent });
3914
4455
  }
@@ -3916,9 +4457,12 @@ var useCapture3DS = (searchParams) => {
3916
4457
  };
3917
4458
  // Annotate the CommonJS export names for ESM import in node:
3918
4459
  0 && (module.exports = {
4460
+ LogLevel,
3919
4461
  PaymentType,
3920
4462
  SpreePay,
3921
4463
  SpreePayProvider,
4464
+ configureLogger,
4465
+ logger,
3922
4466
  useCapture3DS,
3923
4467
  useSpreePay
3924
4468
  });