@ton-pay/ui-react 0.2.0-beta.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/ton-pay-button/TonPayButton.tsx
2
- var _react = require('react'); var React6 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react); var React9 = _interopRequireWildcard(_react); var React10 = _interopRequireWildcard(_react); var React11 = _interopRequireWildcard(_react); var React12 = _interopRequireWildcard(_react); var React13 = _interopRequireWildcard(_react); var React14 = _interopRequireWildcard(_react);
2
+ var _react = require('react'); var React6 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react);
3
3
 
4
4
  var _uireact = require('@tonconnect/ui-react');
5
5
 
@@ -139,8 +139,24 @@ var CloseIcon = ({
139
139
  "aria-hidden": true,
140
140
  children: [
141
141
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { width: "32", height: "32", rx: "8", fill: "#F4F4F4" }),
142
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.99933 22.251L22.2501 9.00026", stroke: "#7A7A7A", strokeWidth: "1.5", strokeLinecap: "round" }),
143
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M8.99933 9.08296L22.2501 22.3337", stroke: "#7A7A7A", strokeWidth: "1.5", strokeLinecap: "round" })
142
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
143
+ "path",
144
+ {
145
+ d: "M8.99933 22.251L22.2501 9.00026",
146
+ stroke: "#7A7A7A",
147
+ strokeWidth: "1.5",
148
+ strokeLinecap: "round"
149
+ }
150
+ ),
151
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
152
+ "path",
153
+ {
154
+ d: "M8.99933 9.08296L22.2501 22.3337",
155
+ stroke: "#7A7A7A",
156
+ strokeWidth: "1.5",
157
+ strokeLinecap: "round"
158
+ }
159
+ )
144
160
  ]
145
161
  }
146
162
  );
@@ -273,10 +289,7 @@ var ErrorDotIcon = ({
273
289
  ]
274
290
  }
275
291
  );
276
- var CardIcon = ({
277
- size = 20,
278
- className
279
- }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
292
+ var CardIcon = ({ size = 20, className }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
280
293
  "svg",
281
294
  {
282
295
  width: size,
@@ -287,15 +300,24 @@ var CardIcon = ({
287
300
  className,
288
301
  "aria-hidden": true,
289
302
  children: [
290
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M15.4688 5H4.53125C3.68693 5 3 5.71369 3 6.59091V13.4091C3 14.2863 3.68693 15 4.53125 15H15.4688C16.3131 15 17 14.2863 17 13.4091V6.59091C17 5.71369 16.3131 5 15.4688 5ZM4.53125 5.90909H15.4688C15.8306 5.90909 16.125 6.21497 16.125 6.59091V7.5H3.875V6.59091C3.875 6.21497 4.16941 5.90909 4.53125 5.90909ZM15.4688 14.0909H4.53125C4.16941 14.0909 3.875 13.785 3.875 13.4091V8.40909H16.125V13.4091C16.125 13.785 15.8306 14.0909 15.4688 14.0909Z", fill: "white" }),
291
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6.33333 13H5.66667C5.2985 13 5 12.7015 5 12.3333V11.6667C5 11.2985 5.2985 11 5.66667 11H6.33333C6.7015 11 7 11.2985 7 11.6667V12.3333C7 12.7015 6.7015 13 6.33333 13Z", fill: "white" })
303
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
304
+ "path",
305
+ {
306
+ d: "M15.4688 5H4.53125C3.68693 5 3 5.71369 3 6.59091V13.4091C3 14.2863 3.68693 15 4.53125 15H15.4688C16.3131 15 17 14.2863 17 13.4091V6.59091C17 5.71369 16.3131 5 15.4688 5ZM4.53125 5.90909H15.4688C15.8306 5.90909 16.125 6.21497 16.125 6.59091V7.5H3.875V6.59091C3.875 6.21497 4.16941 5.90909 4.53125 5.90909ZM15.4688 14.0909H4.53125C4.16941 14.0909 3.875 13.785 3.875 13.4091V8.40909H16.125V13.4091C16.125 13.785 15.8306 14.0909 15.4688 14.0909Z",
307
+ fill: "white"
308
+ }
309
+ ),
310
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
311
+ "path",
312
+ {
313
+ d: "M6.33333 13H5.66667C5.2985 13 5 12.7015 5 12.3333V11.6667C5 11.2985 5.2985 11 5.66667 11H6.33333C6.7015 11 7 11.2985 7 11.6667V12.3333C7 12.7015 6.7015 13 6.33333 13Z",
314
+ fill: "white"
315
+ }
316
+ )
292
317
  ]
293
318
  }
294
319
  );
295
- var CryptoIcon = ({
296
- size = 20,
297
- className
298
- }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
320
+ var CryptoIcon = ({ size = 20, className }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
299
321
  "svg",
300
322
  {
301
323
  width: size,
@@ -305,19 +327,38 @@ var CryptoIcon = ({
305
327
  xmlns: "http://www.w3.org/2000/svg",
306
328
  className,
307
329
  "aria-hidden": true,
308
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M14.3896 3.5H5.61006C3.99582 3.5 2.97267 5.24122 3.7848 6.64885L9.20318 16.0401C9.55683 16.6533 10.4429 16.6533 10.7965 16.0401L16.216 6.64885C17.027 5.24347 16.0028 3.5 14.3896 3.5ZM9.19879 13.2238L8.01872 10.9401L5.17144 5.84782C4.98361 5.52189 5.21561 5.10422 5.60896 5.10422H9.19772V13.225L9.19879 13.2238ZM14.826 5.84671L11.9798 10.9412L10.7998 13.2238V5.10312H14.3885C14.7818 5.10312 15.0138 5.52078 14.826 5.84671Z", fill: "white" })
330
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
331
+ "path",
332
+ {
333
+ d: "M14.3896 3.5H5.61006C3.99582 3.5 2.97267 5.24122 3.7848 6.64885L9.20318 16.0401C9.55683 16.6533 10.4429 16.6533 10.7965 16.0401L16.216 6.64885C17.027 5.24347 16.0028 3.5 14.3896 3.5ZM9.19879 13.2238L8.01872 10.9401L5.17144 5.84782C4.98361 5.52189 5.21561 5.10422 5.60896 5.10422H9.19772V13.225L9.19879 13.2238ZM14.826 5.84671L11.9798 10.9412L10.7998 13.2238V5.10312H14.3885C14.7818 5.10312 15.0138 5.52078 14.826 5.84671Z",
334
+ fill: "white"
335
+ }
336
+ )
337
+ }
338
+ );
339
+ var TonPayLogo = ({ className }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
340
+ "div",
341
+ {
342
+ className,
343
+ style: { display: "flex", alignItems: "center", gap: "4px" },
344
+ children: [
345
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TonIconBlue, { size: 26 }),
346
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
347
+ "span",
348
+ {
349
+ style: {
350
+ fontWeight: 600,
351
+ fontSize: "18px",
352
+ lineHeight: "24px",
353
+ color: "#000000",
354
+ letterSpacing: "-0.5px"
355
+ },
356
+ children: "Pay"
357
+ }
358
+ )
359
+ ]
309
360
  }
310
361
  );
311
- var TonPayLogo = ({ className }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className, style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
312
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TonIconBlue, { size: 26 }),
313
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: {
314
- fontWeight: 600,
315
- fontSize: "18px",
316
- lineHeight: "24px",
317
- color: "#000000",
318
- letterSpacing: "-0.5px"
319
- }, children: "Pay" })
320
- ] });
321
362
 
322
363
  // src/components/notification/Notification.tsx
323
364
 
@@ -394,7 +435,7 @@ var ErrorTransactionNotification = ({ text, className, style }) => {
394
435
 
395
436
  // src/components/bottom-sheet/BottomSheet.css
396
437
  var _styleinject = require('#style-inject'); var _styleinject2 = _interopRequireDefault(_styleinject);
397
- _styleinject2.default.call(void 0, ".bottom-sheet-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n z-index: 1000;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.bottom-sheet-backdrop.closing {\n animation: fadeOut 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n@keyframes fadeIn {\n from {\n opacity: 0;\n backdrop-filter: blur(0px);\n -webkit-backdrop-filter: blur(0px);\n }\n to {\n opacity: 1;\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n }\n}\n@keyframes fadeOut {\n from {\n opacity: 1;\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n }\n to {\n opacity: 0;\n backdrop-filter: blur(0px);\n -webkit-backdrop-filter: blur(0px);\n }\n}\n.bottom-sheet {\n position: relative;\n width: 100%;\n max-width: 100%;\n background-color: #ffffff;\n border-radius: 20px 20px 0 0;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n touch-action: none;\n transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n will-change: height, transform;\n transform: translateY(0);\n}\n.bottom-sheet.dragging {\n transition: none;\n}\n.bottom-sheet.closing {\n animation: slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n@keyframes slideDown {\n from {\n transform: translateY(0);\n }\n to {\n transform: translateY(100%);\n }\n}\n.bottom-sheet-handle-container {\n width: 100%;\n padding: 12px 0 8px;\n display: flex;\n justify-content: center;\n align-items: center;\n flex-shrink: 0;\n cursor: grab;\n}\n.bottom-sheet-handle-container:active {\n cursor: grabbing;\n}\n.bottom-sheet-handle {\n width: 80px;\n height: 4px;\n background-color: #d1d5db;\n border-radius: 2px;\n cursor: pointer;\n}\n.bottom-sheet-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior: contain;\n padding: 0;\n min-height: 0;\n}\n.bottom-sheet-content.scrolling {\n touch-action: pan-y;\n}\n@media (prefers-color-scheme: dark) {\n .bottom-sheet {\n background-color: #1C2633;\n box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.4);\n }\n .bottom-sheet-handle {\n background-color: #4B5563;\n }\n}\n");
438
+ _styleinject2.default.call(void 0, ".bottom-sheet-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n z-index: 1000;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.bottom-sheet-backdrop.closing {\n animation: fadeOut 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n@keyframes fadeIn {\n from {\n opacity: 0;\n backdrop-filter: blur(0px);\n -webkit-backdrop-filter: blur(0px);\n }\n to {\n opacity: 1;\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n }\n}\n@keyframes fadeOut {\n from {\n opacity: 1;\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n }\n to {\n opacity: 0;\n backdrop-filter: blur(0px);\n -webkit-backdrop-filter: blur(0px);\n }\n}\n.bottom-sheet {\n position: relative;\n width: 100%;\n max-width: 100%;\n background-color: #ffffff;\n border-radius: 20px 20px 0 0;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n touch-action: none;\n transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n will-change: height, transform;\n transform: translateY(0);\n}\n.bottom-sheet.dragging {\n transition: none;\n}\n.bottom-sheet.closing {\n animation: slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n@keyframes slideDown {\n from {\n transform: translateY(0);\n }\n to {\n transform: translateY(100%);\n }\n}\n.bottom-sheet-handle-container {\n width: 100%;\n padding: 12px 0 8px;\n display: flex;\n justify-content: center;\n align-items: center;\n flex-shrink: 0;\n cursor: grab;\n}\n.bottom-sheet-handle-container:active {\n cursor: grabbing;\n}\n.bottom-sheet-handle {\n width: 80px;\n height: 4px;\n background-color: #d1d5db;\n border-radius: 2px;\n cursor: pointer;\n}\n.bottom-sheet-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior: contain;\n padding: 0;\n min-height: 0;\n}\n.bottom-sheet-content.scrolling {\n touch-action: pan-y;\n}\n@media (prefers-color-scheme: dark) {\n .bottom-sheet {\n background-color: #1c2633;\n box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.4);\n }\n .bottom-sheet-handle {\n background-color: #4b5563;\n }\n}\n");
398
439
 
399
440
  // src/components/bottom-sheet/BottomSheet.tsx
400
441
 
@@ -513,7 +554,10 @@ var BottomSheet = ({
513
554
  );
514
555
  const snapToDetent = _react.useCallback.call(void 0,
515
556
  (detentIndex) => {
516
- const clampedIndex = Math.max(0, Math.min(detentIndex, detents.length - 1));
557
+ const clampedIndex = Math.max(
558
+ 0,
559
+ Math.min(detentIndex, detents.length - 1)
560
+ );
517
561
  isSnappingRef.current = true;
518
562
  targetDetentRef.current = clampedIndex;
519
563
  const viewportHeight = window.innerHeight;
@@ -562,10 +606,16 @@ var BottomSheet = ({
562
606
  if (isDraggingDown && enableSwipeToClose) {
563
607
  newHeight = Math.max(0, Math.min(maxDetentHeight, newHeight));
564
608
  } else {
565
- newHeight = Math.max(minDetentHeight, Math.min(maxDetentHeight, newHeight));
609
+ newHeight = Math.max(
610
+ minDetentHeight,
611
+ Math.min(maxDetentHeight, newHeight)
612
+ );
566
613
  }
567
614
  } else {
568
- newHeight = Math.max(minDetentHeight, Math.min(maxDetentHeight, newHeight));
615
+ newHeight = Math.max(
616
+ minDetentHeight,
617
+ Math.min(maxDetentHeight, newHeight)
618
+ );
569
619
  }
570
620
  return newHeight;
571
621
  },
@@ -577,7 +627,7 @@ var BottomSheet = ({
577
627
  const touch = e.touches[0];
578
628
  if (!touch) return;
579
629
  const deltaY = touch.clientY - touchStartYRef.current;
580
- const currentScrollTop = _nullishCoalesce(_optionalChain([contentRef, 'access', _2 => _2.current, 'optionalAccess', _3 => _3.scrollTop]), () => ( 0));
630
+ const currentScrollTop = _nullishCoalesce(_optionalChain([contentRef, 'access', _ => _.current, 'optionalAccess', _2 => _2.scrollTop]), () => ( 0));
581
631
  const isContentScrollable = contentRef.current ? contentRef.current.scrollHeight > contentRef.current.clientHeight : false;
582
632
  if (!contentRef.current) return;
583
633
  const touchTarget = e.target;
@@ -701,14 +751,28 @@ var BottomSheet = ({
701
751
  if (isAtMaxDetent) {
702
752
  newHeight = Math.max(0, Math.min(maxDetentHeight, newHeight));
703
753
  } else if (isAtMinDetent) {
704
- newHeight = Math.max(minDetentHeight, Math.min(maxDetentHeight, newHeight));
754
+ newHeight = Math.max(
755
+ minDetentHeight,
756
+ Math.min(maxDetentHeight, newHeight)
757
+ );
705
758
  } else {
706
- newHeight = Math.max(minDetentHeight, Math.min(maxDetentHeight, newHeight));
759
+ newHeight = Math.max(
760
+ minDetentHeight,
761
+ Math.min(maxDetentHeight, newHeight)
762
+ );
707
763
  }
708
764
  setSheetHeight(newHeight);
709
765
  setCurrentY(e.clientY);
710
766
  },
711
- [isOpen, isDragging, startY, currentDetent, detents, getDetentValue, isClosing]
767
+ [
768
+ isOpen,
769
+ isDragging,
770
+ startY,
771
+ currentDetent,
772
+ detents,
773
+ getDetentValue,
774
+ isClosing
775
+ ]
712
776
  );
713
777
  const handleMouseUp = _react.useCallback.call(void 0, () => {
714
778
  if (!isOpen || !isDragging || isClosing) return;
@@ -891,7 +955,7 @@ var BottomSheet_default = BottomSheet;
891
955
 
892
956
  // src/components/payment-modal/PaymentModal.css
893
957
 
894
- _styleinject2.default.call(void 0, '.pm-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n font-family: "Inter", sans-serif;\n color: #000000;\n --pm-bg: #FFFFFF;\n --pm-text: #000000;\n --pm-text-secondary: #666666;\n --pm-text-muted: #8C8C8C;\n --pm-border: rgba(0, 0, 0, 0.1);\n --pm-order-bg: #E9F5FA;\n --pm-order-border: rgba(0, 100, 153, 0.03);\n --pm-order-text: #004062;\n --pm-hover-bg: #F9F9F9;\n --pm-iframe-bg: #f9f9f9;\n --pm-spinner-track: #E5E7EB;\n --pm-actions-border: hsl(0, 0%, 92%);\n}\n@media (prefers-color-scheme: dark) {\n .pm-content {\n color: #FFFFFF;\n --pm-bg: #1f2937;\n --pm-text: #FFFFFF;\n --pm-text-secondary: #9CA3AF;\n --pm-text-muted: #6B7280;\n --pm-border: rgba(255, 255, 255, 0.1);\n --pm-order-bg: rgba(255, 255, 255, 0.05);\n --pm-order-border: rgba(255, 255, 255, 0.1);\n --pm-order-text: #FFFFFF;\n --pm-hover-bg: rgba(255, 255, 255, 0.05);\n --pm-iframe-bg: #111827;\n --pm-spinner-track: #374151;\n --pm-actions-border: rgba(255, 255, 255, 0.1);\n }\n}\n.pm-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: 16px;\n box-sizing: border-box;\n position: relative;\n}\n.bottom-sheet .pm-header {\n padding: 0 16px;\n}\n.pm-header-left,\n.pm-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 40px;\n}\n.pm-header-right {\n justify-content: flex-end;\n}\n.pm-title {\n font-weight: 600;\n font-size: 18px;\n line-height: 22px;\n text-align: center;\n flex: 1;\n}\n.pm-close-btn,\n.pm-back-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--pm-text, #000000);\n opacity: 0.6;\n}\n.pm-close-btn:hover,\n.pm-back-btn:hover {\n opacity: 1;\n}\n.pm-body-main {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n padding: 0;\n gap: 0;\n box-sizing: border-box;\n}\n.pm-main-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n padding: 0 16px;\n}\n.pm-main-title {\n font-size: 18px;\n font-weight: 600;\n line-height: 20px;\n text-align: center;\n margin: 0 0 8px;\n color: var(--pm-text, #000000);\n}\n.pm-amount-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n margin-bottom: 16px;\n}\n.pm-amount-label {\n font-weight: 500;\n font-size: 12px;\n line-height: 15px;\n color: var(--pm-text-muted, #8C8C8C);\n}\n.pm-amount-value {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 24px;\n line-height: 29px;\n color: var(--pm-text, #000000);\n}\n.pm-order-info {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 36px;\n padding: 8px 16px;\n margin-bottom: 24px;\n gap: 4px;\n background: var(--pm-order-bg, #E9F5FA);\n border-radius: 9px;\n box-sizing: border-box;\n border: 1px solid var(--pm-order-border, rgba(0, 100, 153, 0.03));\n}\n.pm-order-text {\n font-family: "Inter", sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 12px;\n line-height: 15px;\n text-align: center;\n color: var(--pm-order-text, #004062);\n flex: none;\n}\n.pm-actions-card {\n width: 100%;\n background: #F9F9F9;\n border-top: 1px solid var(--pm-actions-border, hsl(0, 0%, 92%));\n padding: 16px;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .pm-actions-card {\n background: var(--pm-hover-bg, rgba(255, 255, 255, 0.05));\n }\n}\n.pm-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n}\n.pm-btn {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n padding: 13px 10px 10px;\n gap: 4px;\n width: 100%;\n height: 44px;\n border-radius: 8px;\n border: none;\n cursor: pointer;\n font-weight: 500;\n font-size: 14px;\n line-height: 19px;\n transition: opacity 0.2s;\n}\n.pm-btn:hover {\n opacity: 0.9;\n}\n.pm-btn-primary {\n background: #0098EA;\n color: #FFFFFF;\n}\n.pm-btn-black {\n background: #000000;\n color: #FFFFFF;\n}\n.pm-btn.processing {\n background: #E6E6E6;\n color: #7A7A7A;\n cursor: default;\n}\n.pm-btn.processing:hover {\n opacity: 1;\n}\n.pm-footer {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: 8px;\n margin-top: 12px;\n font-size: 12px;\n line-height: 15px;\n}\n.pm-footer-text {\n color: var(--pm-text-muted, #808080);\n}\n.pm-footer-link {\n color: #0098EA;\n cursor: pointer;\n text-decoration: none;\n}\n.pm-footer-link:hover {\n text-decoration: underline;\n}\n.pm-desktop-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.44);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease-out;\n}\n.pm-desktop-modal {\n width: 100%;\n max-width: 414px;\n margin: 16px;\n background: var(--pm-bg, #FFFFFF);\n border-radius: 32px;\n box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.25);\n overflow: hidden;\n position: relative;\n animation: scaleIn 0.2s ease-out;\n}\n@media (prefers-color-scheme: dark) {\n .pm-desktop-modal {\n box-shadow: 0px 4px 32px rgba(0, 0, 0, 0.5);\n }\n}\n@keyframes scaleIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n.pm-iframe-container {\n width: 100%;\n height: 100%;\n min-height: 400px;\n display: flex;\n flex-direction: column;\n background: var(--pm-iframe-bg, #f9f9f9);\n position: relative;\n}\n.pm-iframe-container iframe {\n flex: 1;\n width: 100%;\n height: 100%;\n border: none;\n display: block;\n}\n.pm-menu-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n background: var(--pm-bg, #FFFFFF);\n border: 1px solid var(--pm-border, rgba(0, 0, 0, 0.1));\n border-radius: 8px;\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n min-width: 150px;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .pm-menu-dropdown {\n box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.4);\n }\n}\n.pm-menu-item {\n padding: 10px 16px;\n font-size: 14px;\n cursor: pointer;\n color: var(--pm-text, #000000);\n}\n.pm-menu-item:hover {\n background: var(--pm-hover-bg, #F9F9F9);\n}\n.pm-menu-item.danger {\n color: #E74C3C;\n}\n.pm-menu-item.disabled {\n cursor: default;\n color: var(--pm-text-muted, #8C8C8C);\n}\n.pm-menu-item.disabled:hover {\n background: transparent;\n}\n.icon-moonpay {\n background: #7D00FF;\n color: white;\n}\n.icon-onramper {\n background: #000000;\n color: white;\n}\n.icon-transak {\n background:\n linear-gradient(\n 120deg,\n #348BED 22.91%,\n #2B80E8 36.09%,\n #1461DB 60.25%,\n #0E57D7 66.11%);\n color: white;\n}\n.icon-mercurio {\n background: #000000;\n color: white;\n}\n.pm-success-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n}\n.pm-success-icon {\n width: 64px;\n height: 64px;\n background: #0098EA;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n color: white;\n}\n.pm-success-icon svg {\n width: 32px;\n height: 32px;\n}\n.pm-success-title {\n font-size: 24px;\n font-weight: 600;\n color: var(--pm-text, #000000);\n margin: 0 0 8px;\n}\n.pm-success-text {\n font-size: 16px;\n color: var(--pm-text-secondary, #666666);\n margin: 0;\n}\n.pm-error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n}\n.pm-error-icon {\n width: 64px;\n height: 64px;\n background: #E74C3C;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n color: white;\n}\n.pm-error-icon svg {\n width: 32px;\n height: 32px;\n}\n.pm-error-title {\n font-size: 24px;\n font-weight: 600;\n color: var(--pm-text, #000000);\n margin: 0 0 8px;\n}\n.pm-error-text {\n font-size: 16px;\n color: var(--pm-text-secondary, #666666);\n margin: 0 0 24px;\n max-width: 300px;\n}\n.pm-error-actions {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n max-width: 280px;\n}\n.pm-error-inline {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: #E74C3C;\n}\n.pm-error-inline svg {\n width: 48px;\n height: 48px;\n margin-bottom: 16px;\n}\n.pm-error-inline p {\n margin: 0 0 20px;\n color: var(--pm-text-secondary, #666666);\n font-size: 14px;\n}\n.pm-btn-outline {\n background: transparent;\n color: #0098EA;\n border: 1px solid #0098EA;\n}\n.pm-btn-outline:hover {\n background: rgba(0, 152, 234, 0.08);\n}\n.pm-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--pm-text-muted, #6b7280);\n}\n.pm-loading-container p {\n margin: 16px 0 0;\n font-size: 14px;\n}\n.pm-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--pm-iframe-bg, #f9f9f9);\n z-index: 1;\n}\n.pm-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid var(--pm-spinner-track, #E5E7EB);\n border-top-color: #0098EA;\n border-radius: 50%;\n animation: pm-spin 0.8s linear infinite;\n}\n.pm-btn-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid rgba(122, 122, 122, 0.3);\n border-top-color: #7A7A7A;\n border-radius: 50%;\n animation: pm-spin 0.8s linear infinite;\n}\n@keyframes pm-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.pm-retry-link {\n font-family: "Inter", sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 12px;\n line-height: 15px;\n text-align: center;\n color: #004062;\n margin-top: 0px;\n}\n.pm-retry-action {\n cursor: pointer;\n text-decoration: underline;\n color: #0098EA;\n}\n@media (prefers-color-scheme: dark) {\n .pm-header-left span {\n color: #ffffff !important;\n }\n .pm-close-btn svg rect {\n fill: rgba(255, 255, 255, 0.1) !important;\n }\n .pm-close-btn svg path {\n stroke: #ffffff !important;\n }\n .pm-retry-link {\n color: var(--pm-text-muted, #8C8C8C) !important;\n }\n .pm-btn.processing {\n background: rgba(255, 255, 255, 0.1) !important;\n color: var(--pm-text-muted, #8C8C8C) !important;\n }\n}\n');
958
+ _styleinject2.default.call(void 0, ':where(.pm-content, .pm-desktop-modal) {\n color: #000000;\n --pm-bg: #ffffff;\n --pm-text: #000000;\n --pm-text-secondary: #666666;\n --pm-text-muted: #8c8c8c;\n --pm-border: rgba(0, 0, 0, 0.1);\n --pm-order-bg: #e9f5fa;\n --pm-order-border: rgba(0, 100, 153, 0.03);\n --pm-order-text: #004062;\n --pm-hover-bg: #f9f9f9;\n --pm-iframe-bg: #f9f9f9;\n --pm-spinner-track: #e5e7eb;\n --pm-actions-border: hsl(0, 0%, 92%);\n}\n.pm-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n font-family: "Inter", sans-serif;\n}\n@media (prefers-color-scheme: dark) {\n :where(.pm-content, .pm-desktop-modal) {\n color: #ffffff;\n --pm-bg: #1f2937;\n --pm-text: #ffffff;\n --pm-text-secondary: #9ca3af;\n --pm-text-muted: #6b7280;\n --pm-border: rgba(255, 255, 255, 0.1);\n --pm-order-bg: rgba(255, 255, 255, 0.05);\n --pm-order-border: rgba(255, 255, 255, 0.1);\n --pm-order-text: #ffffff;\n --pm-hover-bg: rgba(255, 255, 255, 0.05);\n --pm-iframe-bg: #111827;\n --pm-spinner-track: #374151;\n --pm-actions-border: rgba(255, 255, 255, 0.1);\n }\n}\n.pm-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n padding: 16px;\n box-sizing: border-box;\n position: relative;\n}\n.bottom-sheet .pm-header {\n padding: 0 16px;\n}\n.pm-header-left,\n.pm-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 40px;\n}\n.pm-header-right {\n justify-content: flex-end;\n}\n.pm-title {\n font-weight: 600;\n font-size: 18px;\n line-height: 22px;\n text-align: center;\n flex: 1;\n}\n.pm-close-btn,\n.pm-back-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--pm-text, #000000);\n opacity: 0.6;\n}\n.pm-close-btn:hover,\n.pm-back-btn:hover {\n opacity: 1;\n}\n.pm-body-main {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n padding: 0;\n gap: 0;\n box-sizing: border-box;\n}\n.pm-main-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n padding: 0 16px;\n}\n.pm-main-title {\n font-size: 18px;\n font-weight: 600;\n line-height: 20px;\n text-align: center;\n margin: 0 0 8px;\n color: var(--pm-text, #000000);\n}\n.pm-amount-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n margin-bottom: 16px;\n}\n.pm-amount-label {\n font-weight: 500;\n font-size: 12px;\n line-height: 15px;\n color: var(--pm-text-muted, #8c8c8c);\n}\n.pm-amount-value {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 24px;\n line-height: 29px;\n color: var(--pm-text, #000000);\n}\n.pm-order-info {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 36px;\n padding: 8px 16px;\n margin-bottom: 24px;\n gap: 4px;\n background: var(--pm-order-bg, #e9f5fa);\n border-radius: 9px;\n box-sizing: border-box;\n border: 1px solid var(--pm-order-border, rgba(0, 100, 153, 0.03));\n}\n.pm-order-text {\n font-family: "Inter", sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 12px;\n line-height: 15px;\n text-align: center;\n color: var(--pm-order-text, #004062);\n flex: none;\n}\n.pm-actions-card {\n width: 100%;\n background: #f9f9f9;\n border-top: 1px solid var(--pm-actions-border, hsl(0, 0%, 92%));\n padding: 16px;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .pm-actions-card {\n background: var(--pm-hover-bg, rgba(255, 255, 255, 0.05));\n }\n}\n.pm-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n}\n.pm-btn {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n padding: 13px 10px 10px;\n gap: 4px;\n width: 100%;\n height: 44px;\n border-radius: 8px;\n border: none;\n cursor: pointer;\n font-weight: 500;\n font-size: 14px;\n line-height: 19px;\n transition: opacity 0.2s;\n}\n.pm-btn:hover {\n opacity: 0.9;\n}\n.pm-btn-primary {\n background: #0098ea;\n color: #ffffff;\n}\n.pm-btn-black {\n background: #000000;\n color: #ffffff;\n}\n.pm-btn.processing {\n background: #e6e6e6;\n color: #7a7a7a;\n cursor: default;\n}\n.pm-btn.processing:hover {\n opacity: 1;\n}\n.pm-footer {\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: 8px;\n margin-top: 12px;\n font-size: 12px;\n line-height: 15px;\n}\n.pm-footer-text {\n color: var(--pm-text-muted, #808080);\n}\n.pm-footer-link {\n color: #0098ea;\n cursor: pointer;\n text-decoration: none;\n}\n.pm-footer-link:hover {\n text-decoration: underline;\n}\n.pm-desktop-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.44);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease-out;\n}\n.pm-desktop-modal {\n width: 100%;\n max-width: 414px;\n margin: 16px;\n background: var(--pm-bg, #ffffff);\n border-radius: 32px;\n box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.25);\n overflow: hidden;\n position: relative;\n animation: scaleIn 0.2s ease-out;\n}\n@media (prefers-color-scheme: dark) {\n .pm-desktop-modal {\n box-shadow: 0px 4px 32px rgba(0, 0, 0, 0.5);\n }\n}\n@keyframes scaleIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n.pm-iframe-container {\n width: 100%;\n height: 100%;\n min-height: 400px;\n display: flex;\n flex-direction: column;\n background: var(--pm-iframe-bg, #f9f9f9);\n position: relative;\n}\n.pm-iframe-container iframe {\n flex: 1;\n width: 100%;\n height: 100%;\n border: none;\n display: block;\n}\n.pm-menu-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n background: var(--pm-bg, #ffffff);\n border: 1px solid var(--pm-border, rgba(0, 0, 0, 0.1));\n border-radius: 8px;\n box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n min-width: 150px;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .pm-menu-dropdown {\n box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.4);\n }\n}\n.pm-menu-item {\n padding: 10px 16px;\n font-size: 14px;\n cursor: pointer;\n color: var(--pm-text, #000000);\n}\n.pm-menu-item:hover {\n background: var(--pm-hover-bg, #f9f9f9);\n}\n.pm-menu-item.danger {\n color: #e74c3c;\n}\n.pm-menu-item.disabled {\n cursor: default;\n color: var(--pm-text-muted, #8c8c8c);\n}\n.pm-menu-item.disabled:hover {\n background: transparent;\n}\n.icon-moonpay {\n background: #7d00ff;\n color: white;\n}\n.icon-onramper {\n background: #000000;\n color: white;\n}\n.icon-transak {\n background:\n linear-gradient(\n 120deg,\n #348bed 22.91%,\n #2b80e8 36.09%,\n #1461db 60.25%,\n #0e57d7 66.11%);\n color: white;\n}\n.icon-mercurio {\n background: #000000;\n color: white;\n}\n.pm-success-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n}\n.pm-success-icon {\n width: 64px;\n height: 64px;\n background: #0098ea;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n color: white;\n}\n.pm-success-icon svg {\n width: 32px;\n height: 32px;\n}\n.pm-success-title {\n font-size: 24px;\n font-weight: 600;\n color: var(--pm-text, #000000);\n margin: 0 0 8px;\n}\n.pm-success-text {\n font-size: 16px;\n color: var(--pm-text-secondary, #666666);\n margin: 0;\n}\n.pm-error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n}\n.pm-error-icon {\n width: 64px;\n height: 64px;\n background: #e74c3c;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 20px;\n color: white;\n}\n.pm-error-icon svg {\n width: 32px;\n height: 32px;\n}\n.pm-error-title {\n font-size: 24px;\n font-weight: 600;\n color: var(--pm-text, #000000);\n margin: 0 0 8px;\n}\n.pm-error-text {\n font-size: 16px;\n color: var(--pm-text-secondary, #666666);\n margin: 0 0 24px;\n max-width: 300px;\n}\n.pm-error-actions {\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n max-width: 280px;\n}\n.pm-error-inline {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: #e74c3c;\n}\n.pm-error-inline svg {\n width: 48px;\n height: 48px;\n margin-bottom: 16px;\n}\n.pm-error-inline p {\n margin: 0 0 20px;\n color: var(--pm-text-secondary, #666666);\n font-size: 14px;\n}\n.pm-btn-outline {\n background: transparent;\n color: #0098ea;\n border: 1px solid #0098ea;\n}\n.pm-btn-outline:hover {\n background: rgba(0, 152, 234, 0.08);\n}\n.pm-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--pm-text-muted, #6b7280);\n}\n.pm-loading-container p {\n margin: 16px 0 0;\n font-size: 14px;\n}\n.pm-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--pm-iframe-bg, #f9f9f9);\n z-index: 1;\n}\n.pm-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid var(--pm-spinner-track, #e5e7eb);\n border-top-color: #0098ea;\n border-radius: 50%;\n animation: pm-spin 0.8s linear infinite;\n}\n.pm-btn-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid rgba(122, 122, 122, 0.3);\n border-top-color: #7a7a7a;\n border-radius: 50%;\n animation: pm-spin 0.8s linear infinite;\n}\n@keyframes pm-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.pm-retry-link {\n font-family: "Inter", sans-serif;\n font-style: normal;\n font-weight: 400;\n font-size: 12px;\n line-height: 15px;\n text-align: center;\n color: #004062;\n margin-top: 0px;\n}\n.pm-retry-action {\n cursor: pointer;\n text-decoration: underline;\n color: #0098ea;\n}\n@media (prefers-color-scheme: dark) {\n .pm-header-left span {\n color: #ffffff !important;\n }\n .pm-close-btn svg rect {\n fill: rgba(255, 255, 255, 0.1) !important;\n }\n .pm-close-btn svg path {\n stroke: #ffffff !important;\n }\n .pm-retry-link {\n color: var(--pm-text-muted, #8c8c8c) !important;\n }\n .pm-btn.processing {\n background: rgba(255, 255, 255, 0.1) !important;\n color: var(--pm-text-muted, #8c8c8c) !important;\n }\n}\n');
895
959
 
896
960
  // src/components/payment-modal/PaymentModal.tsx
897
961
 
@@ -928,7 +992,7 @@ var PaymentModal = ({
928
992
  clearTimeout(iframeTimeoutRef.current);
929
993
  }
930
994
  setView("success");
931
- _optionalChain([onPaymentSuccess, 'optionalCall', _4 => _4()]);
995
+ _optionalChain([onPaymentSuccess, 'optionalCall', _3 => _3()]);
932
996
  setTimeout(() => {
933
997
  onClose();
934
998
  }, 2e3);
@@ -950,26 +1014,26 @@ var PaymentModal = ({
950
1014
  }, []);
951
1015
  _react.useEffect.call(void 0, () => {
952
1016
  const handleMessage = (event) => {
953
- if (_optionalChain([event, 'access', _5 => _5.data, 'optionalAccess', _6 => _6.type]) === "TONPAY_PAYMENT_SUCCESS") {
1017
+ if (_optionalChain([event, 'access', _4 => _4.data, 'optionalAccess', _5 => _5.type]) === "TONPAY_PAYMENT_SUCCESS") {
954
1018
  handlePaymentSuccess();
955
1019
  }
956
- if (_optionalChain([event, 'access', _7 => _7.data, 'optionalAccess', _8 => _8.type]) === "TONPAY_PAYMENT_ERROR") {
1020
+ if (_optionalChain([event, 'access', _6 => _6.data, 'optionalAccess', _7 => _7.type]) === "TONPAY_PAYMENT_ERROR") {
957
1021
  const payload = event.data.payload;
958
- handlePaymentError(_optionalChain([payload, 'optionalAccess', _9 => _9.message]) || "Payment failed");
1022
+ handlePaymentError(_optionalChain([payload, 'optionalAccess', _8 => _8.message]) || "Payment failed");
959
1023
  }
960
- if (_optionalChain([event, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.type]) === "TONPAY_IFRAME_LOADED") {
1024
+ if (_optionalChain([event, 'access', _9 => _9.data, 'optionalAccess', _10 => _10.type]) === "TONPAY_IFRAME_LOADED") {
961
1025
  setIframeLoaded(true);
962
1026
  if (iframeTimeoutRef.current) {
963
1027
  clearTimeout(iframeTimeoutRef.current);
964
1028
  }
965
1029
  }
966
- if (_optionalChain([event, 'access', _12 => _12.data, 'optionalAccess', _13 => _13.type]) === "TONPAY_MOONPAY_EVENT") {
1030
+ if (_optionalChain([event, 'access', _11 => _11.data, 'optionalAccess', _12 => _12.type]) === "TONPAY_MOONPAY_EVENT") {
967
1031
  const payload = event.data.payload;
968
- if (_optionalChain([payload, 'optionalAccess', _14 => _14.type]) === "onTransactionCompleted" || _optionalChain([payload, 'optionalAccess', _15 => _15.eventName]) === "transactionCompleted") {
1032
+ if (_optionalChain([payload, 'optionalAccess', _13 => _13.type]) === "onTransactionCompleted" || _optionalChain([payload, 'optionalAccess', _14 => _14.eventName]) === "transactionCompleted") {
969
1033
  handlePaymentSuccess();
970
1034
  }
971
- if (_optionalChain([payload, 'optionalAccess', _16 => _16.type]) === "onTransactionFailed" || _optionalChain([payload, 'optionalAccess', _17 => _17.eventName]) === "transactionFailed") {
972
- handlePaymentError(_optionalChain([payload, 'optionalAccess', _18 => _18.message]) || "Transaction failed");
1035
+ if (_optionalChain([payload, 'optionalAccess', _15 => _15.type]) === "onTransactionFailed" || _optionalChain([payload, 'optionalAccess', _16 => _16.eventName]) === "transactionFailed") {
1036
+ handlePaymentError(_optionalChain([payload, 'optionalAccess', _17 => _17.message]) || "Transaction failed");
973
1037
  }
974
1038
  }
975
1039
  };
@@ -998,7 +1062,7 @@ var PaymentModal = ({
998
1062
  }
999
1063
  }, IFRAME_LOAD_TIMEOUT);
1000
1064
  }).catch((err) => {
1001
- const errorMsg = _optionalChain([err, 'optionalAccess', _19 => _19.message]) || "Failed to initialize payment";
1065
+ const errorMsg = _optionalChain([err, 'optionalAccess', _18 => _18.message]) || "Failed to initialize payment";
1002
1066
  setOnRampError(errorMsg);
1003
1067
  fetchStartedRef.current = false;
1004
1068
  }).finally(() => setIsOnRampLoading(false));
@@ -1008,7 +1072,14 @@ var PaymentModal = ({
1008
1072
  clearTimeout(iframeTimeoutRef.current);
1009
1073
  }
1010
1074
  };
1011
- }, [view, onRampLink, onRampError, fetchOnRampLink, iframeLoaded, handlePaymentError]);
1075
+ }, [
1076
+ view,
1077
+ onRampLink,
1078
+ onRampError,
1079
+ fetchOnRampLink,
1080
+ iframeLoaded,
1081
+ handlePaymentError
1082
+ ]);
1012
1083
  _react.useEffect.call(void 0, () => {
1013
1084
  const checkMobile = () => {
1014
1085
  setIsMobile(window.innerWidth < 768);
@@ -1041,7 +1112,9 @@ var PaymentModal = ({
1041
1112
  const height = contentRef.current.scrollHeight;
1042
1113
  const windowHeight = window.innerHeight;
1043
1114
  const detent = Math.min((height + 40) / windowHeight, 0.95);
1044
- setSheetDetent((prev) => Math.abs(prev[0] - detent) < 0.01 ? prev : [detent]);
1115
+ setSheetDetent(
1116
+ (prev) => Math.abs(prev[0] - detent) < 0.01 ? prev : [detent]
1117
+ );
1045
1118
  }
1046
1119
  };
1047
1120
  setTimeout(updateHeight, 50);
@@ -1066,7 +1139,14 @@ var PaymentModal = ({
1066
1139
  view !== "main" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-title", children: "New Purchase" }),
1067
1140
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-header-right", children: [
1068
1141
  walletAddress && view === "main" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { position: "relative" }, children: [
1069
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { className: "pm-close-btn", onClick: () => setShowMenu(!showMenu), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuIcon, {}) }),
1142
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1143
+ "button",
1144
+ {
1145
+ className: "pm-close-btn",
1146
+ onClick: () => setShowMenu(!showMenu),
1147
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuIcon, {})
1148
+ }
1149
+ ),
1070
1150
  showMenu && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-menu-dropdown", children: [
1071
1151
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-menu-item disabled", children: [
1072
1152
  walletAddress.slice(0, 4),
@@ -1078,7 +1158,7 @@ var PaymentModal = ({
1078
1158
  {
1079
1159
  className: "pm-menu-item danger",
1080
1160
  onClick: () => {
1081
- _optionalChain([onDisconnect, 'optionalCall', _20 => _20()]);
1161
+ _optionalChain([onDisconnect, 'optionalCall', _19 => _19()]);
1082
1162
  setShowMenu(false);
1083
1163
  },
1084
1164
  children: "Disconnect"
@@ -1112,13 +1192,25 @@ var PaymentModal = ({
1112
1192
  className: `pm-btn ${isLoading ? "processing" : "pm-btn-primary"}`,
1113
1193
  onClick: isLoading ? void 0 : onPayWithCrypto,
1114
1194
  disabled: isLoading,
1115
- children: isLoading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
1116
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-btn-spinner" }),
1117
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Processing" })
1118
- ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
1119
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CryptoIcon, {}),
1120
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Pay with Crypto" })
1121
- ] })
1195
+ children: isLoading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1196
+ "div",
1197
+ {
1198
+ style: { display: "flex", alignItems: "center", gap: "4px" },
1199
+ children: [
1200
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-btn-spinner" }),
1201
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Processing" })
1202
+ ]
1203
+ }
1204
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1205
+ "div",
1206
+ {
1207
+ style: { display: "flex", alignItems: "center", gap: "4px" },
1208
+ children: [
1209
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CryptoIcon, {}),
1210
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Pay with Crypto" })
1211
+ ]
1212
+ }
1213
+ )
1122
1214
  }
1123
1215
  ),
1124
1216
  isLoading && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-retry-link", children: [
@@ -1127,10 +1219,17 @@ var PaymentModal = ({
1127
1219
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "pm-retry-action", onClick: onPayWithCrypto, children: "Click here" }),
1128
1220
  "."
1129
1221
  ] }),
1130
- onRampAvailable && !isLoading && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { className: "pm-btn pm-btn-black", onClick: () => setView("card"), children: [
1131
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CardIcon, {}),
1132
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Pay with Card" })
1133
- ] })
1222
+ onRampAvailable && !isLoading && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1223
+ "button",
1224
+ {
1225
+ className: "pm-btn pm-btn-black",
1226
+ onClick: () => setView("card"),
1227
+ children: [
1228
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CardIcon, {}),
1229
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Pay with Card" })
1230
+ ]
1231
+ }
1232
+ )
1134
1233
  ] }),
1135
1234
  onRampAvailable && !isLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-footer", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "pm-footer-text", children: [
1136
1235
  "Processed by ",
@@ -1226,8 +1325,8 @@ var PaymentModal = ({
1226
1325
 
1227
1326
 
1228
1327
  // ../api/src/common/const.ts
1229
- var BASE_URL = "https://tonpay.tech";
1230
- var TESTNET_BASE_URL = "https://testnet.tonpay.tech";
1328
+ var BASE_URL = "https://pay.ton.org";
1329
+ var TESTNET_BASE_URL = "https://testnet.pay.ton.org";
1231
1330
 
1232
1331
  // ../api/src/common/get-base-url.ts
1233
1332
  var getBaseUrl = (chain) => {
@@ -1242,7 +1341,7 @@ var getBaseUrl = (chain) => {
1242
1341
 
1243
1342
  // ../api/src/create-moonpay-transfer/create-moonpay-transfer.ts
1244
1343
  var createMoonpayTransfer = async (params, options) => {
1245
- if (!_optionalChain([options, 'optionalAccess', _21 => _21.apiKey])) {
1344
+ if (!_optionalChain([options, 'optionalAccess', _20 => _20.apiKey])) {
1246
1345
  throw new Error("API key is required for MoonPay transfers");
1247
1346
  }
1248
1347
  const baseUrl = getBaseUrl(options.chain);
@@ -1271,44 +1370,21 @@ var createMoonpayTransfer = async (params, options) => {
1271
1370
  return data;
1272
1371
  };
1273
1372
 
1274
- // ../api/src/check-moonpay-geo/check-moonpay-geo.ts
1275
- var checkMoonpayGeo = async (params, options) => {
1276
- const baseUrl = getBaseUrl(_optionalChain([options, 'optionalAccess', _22 => _22.chain]));
1277
- const headers = {
1278
- "Content-Type": "application/json",
1279
- ..._optionalChain([options, 'optionalAccess', _23 => _23.apiKey]) ? { "x-api-key": options.apiKey } : {}
1280
- };
1281
- const response = await fetch(
1282
- `${baseUrl}/api/external/moonpay/check-geo?ipAddress=${encodeURIComponent(params.ipAddress)}`,
1283
- {
1284
- method: "GET",
1285
- headers
1286
- }
1287
- );
1288
- if (!response.ok) {
1289
- const errorText = await response.text();
1290
- throw new Error(`Failed to check MoonPay geo: ${errorText}`, {
1291
- cause: response.statusText
1292
- });
1293
- }
1294
- return response.json();
1295
- };
1296
-
1297
- // ../api/src/check-moonpay-limits/check-moonpay-limits.ts
1298
- var checkMoonpayLimits = async (params, options) => {
1299
- const baseUrl = getBaseUrl(_optionalChain([options, 'optionalAccess', _24 => _24.chain]));
1373
+ // ../api/src/check-moonpay-availability/check-moonpay-availability.ts
1374
+ var checkMoonpayAvailability = async (params, options) => {
1375
+ const baseUrl = getBaseUrl(_optionalChain([options, 'optionalAccess', _21 => _21.chain]));
1300
1376
  const headers = {
1301
1377
  "Content-Type": "application/json",
1302
- ..._optionalChain([options, 'optionalAccess', _25 => _25.apiKey]) ? { "x-api-key": options.apiKey } : {}
1378
+ ..._optionalChain([options, 'optionalAccess', _22 => _22.apiKey]) ? { "x-api-key": options.apiKey } : {}
1303
1379
  };
1304
- const response = await fetch(`${baseUrl}/api/external/moonpay/limits`, {
1380
+ const response = await fetch(`${baseUrl}/api/external/moonpay/check`, {
1305
1381
  method: "POST",
1306
1382
  body: JSON.stringify(params),
1307
1383
  headers
1308
1384
  });
1309
1385
  if (!response.ok) {
1310
1386
  const errorText = await response.text();
1311
- throw new Error(`Failed to check MoonPay limits: ${errorText}`, {
1387
+ throw new Error(`Failed to check MoonPay availability: ${errorText}`, {
1312
1388
  cause: response.statusText
1313
1389
  });
1314
1390
  }
@@ -1336,18 +1412,17 @@ function useMoonPayIframe({
1336
1412
  setLoading(true);
1337
1413
  setError(null);
1338
1414
  try {
1339
- const geo = await checkMoonpayGeo({ ipAddress }, { apiKey, chain });
1340
- setGeoResult(geo);
1341
- if (!geo.isBuyAllowed) {
1342
- return false;
1343
- }
1344
- const limitRes = await checkMoonpayLimits(
1345
- { asset },
1415
+ const availability = await checkMoonpayAvailability(
1416
+ { asset, ipAddress },
1346
1417
  { apiKey, chain }
1347
1418
  );
1348
- setLimits(limitRes);
1349
- const limitsData = _optionalChain([limitRes, 'optionalAccess', _26 => _26.limits]) || limitRes;
1350
- if (!_optionalChain([limitsData, 'optionalAccess', _27 => _27.quoteCurrency])) {
1419
+ setGeoResult(availability.geo);
1420
+ setLimits(availability.limits);
1421
+ if (!availability.geo.isBuyAllowed) {
1422
+ return false;
1423
+ }
1424
+ const limitsData = availability.limits;
1425
+ if (!_optionalChain([limitsData, 'optionalAccess', _23 => _23.quoteCurrency])) {
1351
1426
  return false;
1352
1427
  }
1353
1428
  const { minBuyAmount, maxBuyAmount } = limitsData.quoteCurrency;
@@ -1551,7 +1626,7 @@ var TonPayButton = ({
1551
1626
  setRedirectToWallet(null);
1552
1627
  await handlePay((redirect) => setRedirectToWallet(() => redirect));
1553
1628
  } catch (err) {
1554
- _optionalChain([onError, 'optionalCall', _28 => _28(err)]);
1629
+ _optionalChain([onError, 'optionalCall', _24 => _24(err)]);
1555
1630
  if (showErrorNotification) {
1556
1631
  const raw = typeof err === "object" && err && "message" in err ? String(err.message) : String(_nullishCoalesce(err, () => ( "")));
1557
1632
  setErrorMessage(raw || "Wallet connection modal closed");
@@ -1581,8 +1656,8 @@ var TonPayButton = ({
1581
1656
  [fetchOnRampLink, amount, currency, address, userIp]
1582
1657
  );
1583
1658
  const presetConfig = preset ? PRESETS[preset] : null;
1584
- const finalBgColor = _nullishCoalesce(_nullishCoalesce(bgColor, () => ( _optionalChain([presetConfig, 'optionalAccess', _29 => _29.bgColor]))), () => ( PRESETS.default.bgColor));
1585
- const finalTextColor = _nullishCoalesce(_nullishCoalesce(textColor, () => ( _optionalChain([presetConfig, 'optionalAccess', _30 => _30.textColor]))), () => ( PRESETS.default.textColor));
1659
+ const finalBgColor = _nullishCoalesce(_nullishCoalesce(bgColor, () => ( _optionalChain([presetConfig, 'optionalAccess', _25 => _25.bgColor]))), () => ( PRESETS.default.bgColor));
1660
+ const finalTextColor = _nullishCoalesce(_nullishCoalesce(textColor, () => ( _optionalChain([presetConfig, 'optionalAccess', _26 => _26.textColor]))), () => ( PRESETS.default.textColor));
1586
1661
  const cssVars = {
1587
1662
  "--tp-bg": finalBgColor,
1588
1663
  "--tp-text": finalTextColor,
@@ -1662,9 +1737,9 @@ var TonPayButton = ({
1662
1737
  showMenu && showDropdown && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tp-menu", children: [
1663
1738
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tp-menu-arrow" }),
1664
1739
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tp-menu-address", children: [
1665
- _optionalChain([address, 'optionalAccess', _31 => _31.slice, 'call', _32 => _32(0, 4)]),
1740
+ _optionalChain([address, 'optionalAccess', _27 => _27.slice, 'call', _28 => _28(0, 4)]),
1666
1741
  "...",
1667
- _optionalChain([address, 'optionalAccess', _33 => _33.slice, 'call', _34 => _34(-4)])
1742
+ _optionalChain([address, 'optionalAccess', _29 => _29.slice, 'call', _30 => _30(-4)])
1668
1743
  ] }),
1669
1744
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1670
1745
  "button",
@@ -1725,7 +1800,7 @@ function useTonPay() {
1725
1800
  }
1726
1801
  modal.open();
1727
1802
  const unsubscribe = tonConnectUI.onStatusChange((wallet) => {
1728
- if (_optionalChain([wallet, 'optionalAccess', _35 => _35.account])) {
1803
+ if (_optionalChain([wallet, 'optionalAccess', _31 => _31.account])) {
1729
1804
  unsubscribe();
1730
1805
  unsubscribeModal();
1731
1806
  resolve(wallet.account.address);
@@ -1757,7 +1832,7 @@ function useTonPay() {
1757
1832
  from: walletAddress
1758
1833
  },
1759
1834
  {
1760
- onRequestSent: _optionalChain([options, 'optionalAccess', _36 => _36.onRequestSent])
1835
+ onRequestSent: _optionalChain([options, 'optionalAccess', _32 => _32.onRequestSent])
1761
1836
  }
1762
1837
  );
1763
1838
  return { ...messageResult, txResult };
@@ -1767,1704 +1842,6 @@ function useTonPay() {
1767
1842
  return { pay, address };
1768
1843
  }
1769
1844
 
1770
- // src/signless/context.tsx
1771
-
1772
-
1773
-
1774
- // src/signless/crypto/ed25519.ts
1775
- var ALGORITHM = "Ed25519";
1776
- function arrayBufferToUint8Array(buffer) {
1777
- return new Uint8Array(buffer);
1778
- }
1779
- async function generateKeyPair() {
1780
- const keyPair = await crypto.subtle.generateKey(ALGORITHM, true, [
1781
- "sign",
1782
- "verify"
1783
- ]);
1784
- const privateKeyBuffer = await crypto.subtle.exportKey(
1785
- "pkcs8",
1786
- keyPair.privateKey
1787
- );
1788
- const publicKeyBuffer = await crypto.subtle.exportKey(
1789
- "spki",
1790
- keyPair.publicKey
1791
- );
1792
- return {
1793
- publicKey: arrayBufferToUint8Array(publicKeyBuffer),
1794
- privateKey: arrayBufferToUint8Array(privateKeyBuffer)
1795
- };
1796
- }
1797
- async function signMessage(privateKey, message) {
1798
- const importedKey = await crypto.subtle.importKey(
1799
- "pkcs8",
1800
- privateKey,
1801
- ALGORITHM,
1802
- false,
1803
- ["sign"]
1804
- );
1805
- const signature = await crypto.subtle.sign(ALGORITHM, importedKey, message);
1806
- return arrayBufferToUint8Array(signature);
1807
- }
1808
- async function verifySignlessSignature(publicKey, message, signature) {
1809
- const importedKey = await crypto.subtle.importKey(
1810
- "spki",
1811
- publicKey,
1812
- ALGORITHM,
1813
- false,
1814
- ["verify"]
1815
- );
1816
- return crypto.subtle.verify(ALGORITHM, importedKey, signature, message);
1817
- }
1818
-
1819
- // src/signless/crypto/encryption.ts
1820
- var PBKDF2_ITERATIONS = 1e5;
1821
- var SALT_LENGTH = 16;
1822
- var IV_LENGTH = 12;
1823
- var KEY_LENGTH = 256;
1824
- function arrayBufferToBase64(buffer) {
1825
- const bytes = new Uint8Array(buffer);
1826
- let binary = "";
1827
- for (let i = 0; i < bytes.byteLength; i++) {
1828
- binary += String.fromCharCode(bytes[i]);
1829
- }
1830
- return btoa(binary);
1831
- }
1832
- function base64ToArrayBuffer(base64) {
1833
- const binary = atob(base64);
1834
- const bytes = new Uint8Array(binary.length);
1835
- for (let i = 0; i < binary.length; i++) {
1836
- bytes[i] = binary.charCodeAt(i);
1837
- }
1838
- return bytes.buffer;
1839
- }
1840
- function generateSalt() {
1841
- return crypto.getRandomValues(new Uint8Array(SALT_LENGTH));
1842
- }
1843
- function generateIv() {
1844
- return crypto.getRandomValues(new Uint8Array(IV_LENGTH));
1845
- }
1846
- async function deriveKeyFromPin(pin, salt) {
1847
- const encoder = new TextEncoder();
1848
- const pinData = encoder.encode(pin);
1849
- const baseKey = await crypto.subtle.importKey(
1850
- "raw",
1851
- pinData,
1852
- "PBKDF2",
1853
- false,
1854
- ["deriveKey"]
1855
- );
1856
- return crypto.subtle.deriveKey(
1857
- {
1858
- name: "PBKDF2",
1859
- salt,
1860
- iterations: PBKDF2_ITERATIONS,
1861
- hash: "SHA-256"
1862
- },
1863
- baseKey,
1864
- { name: "AES-GCM", length: KEY_LENGTH },
1865
- false,
1866
- ["encrypt", "decrypt"]
1867
- );
1868
- }
1869
- async function encryptPrivateKey(privateKey, publicKey, pin) {
1870
- const salt = generateSalt();
1871
- const iv = generateIv();
1872
- const derivedKey = await deriveKeyFromPin(pin, salt);
1873
- const encryptedBuffer = await crypto.subtle.encrypt(
1874
- { name: "AES-GCM", iv },
1875
- derivedKey,
1876
- privateKey
1877
- );
1878
- return {
1879
- salt: arrayBufferToBase64(salt.buffer),
1880
- iv: arrayBufferToBase64(iv.buffer),
1881
- encryptedBlob: arrayBufferToBase64(encryptedBuffer),
1882
- publicKey: arrayBufferToBase64(publicKey.buffer),
1883
- version: 1
1884
- };
1885
- }
1886
- async function decryptPrivateKey(vault, pin) {
1887
- const salt = new Uint8Array(base64ToArrayBuffer(vault.salt));
1888
- const iv = new Uint8Array(base64ToArrayBuffer(vault.iv));
1889
- const encryptedBlob = base64ToArrayBuffer(vault.encryptedBlob);
1890
- const derivedKey = await deriveKeyFromPin(pin, salt);
1891
- try {
1892
- const decryptedBuffer = await crypto.subtle.decrypt(
1893
- { name: "AES-GCM", iv },
1894
- derivedKey,
1895
- encryptedBlob
1896
- );
1897
- return new Uint8Array(decryptedBuffer);
1898
- } catch (e4) {
1899
- throw new Error("Invalid PIN or corrupted vault");
1900
- }
1901
- }
1902
-
1903
- // src/signless/crypto/webauthn.ts
1904
- var WEBAUTHN_RP_NAME = "TON Pay";
1905
- var WEBAUTHN_RP_ID_FALLBACK = "tonpay.io";
1906
- var STATIC_CHALLENGE = new Uint8Array([
1907
- 1,
1908
- 2,
1909
- 3,
1910
- 4,
1911
- 5,
1912
- 6,
1913
- 7,
1914
- 8,
1915
- 9,
1916
- 10,
1917
- 11,
1918
- 12,
1919
- 13,
1920
- 14,
1921
- 15,
1922
- 16
1923
- ]);
1924
- function arrayBufferToBase64Url(buffer) {
1925
- const bytes = new Uint8Array(buffer);
1926
- let binary = "";
1927
- for (let i = 0; i < bytes.byteLength; i++) {
1928
- binary += String.fromCharCode(bytes[i]);
1929
- }
1930
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1931
- }
1932
- function base64UrlToArrayBuffer(base64Url) {
1933
- const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
1934
- const padding = "=".repeat((4 - base64.length % 4) % 4);
1935
- const binary = atob(base64 + padding);
1936
- const bytes = new Uint8Array(binary.length);
1937
- for (let i = 0; i < binary.length; i++) {
1938
- bytes[i] = binary.charCodeAt(i);
1939
- }
1940
- return bytes.buffer;
1941
- }
1942
- function isWebAuthnSupported() {
1943
- return typeof window !== "undefined" && !!window.PublicKeyCredential && typeof window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable === "function";
1944
- }
1945
- function getRpId() {
1946
- if (typeof window === "undefined") return WEBAUTHN_RP_ID_FALLBACK;
1947
- return window.location.hostname || WEBAUTHN_RP_ID_FALLBACK;
1948
- }
1949
- async function createWebAuthnCredential(walletAddress) {
1950
- if (!isWebAuthnSupported()) {
1951
- throw new Error("WebAuthn is not supported in this browser");
1952
- }
1953
- const userId = new TextEncoder().encode(walletAddress);
1954
- const createOptions = {
1955
- challenge: STATIC_CHALLENGE,
1956
- rp: {
1957
- name: WEBAUTHN_RP_NAME,
1958
- id: getRpId()
1959
- },
1960
- user: {
1961
- id: userId,
1962
- name: `TON Pay - ${walletAddress.slice(0, 8)}...`,
1963
- displayName: "TON Pay Signless"
1964
- },
1965
- pubKeyCredParams: [
1966
- { type: "public-key", alg: -7 },
1967
- { type: "public-key", alg: -257 }
1968
- ],
1969
- timeout: 6e4,
1970
- authenticatorSelection: {
1971
- authenticatorAttachment: "platform",
1972
- userVerification: "required",
1973
- residentKey: "preferred"
1974
- },
1975
- attestation: "none"
1976
- };
1977
- const credential = await navigator.credentials.create({
1978
- publicKey: createOptions
1979
- });
1980
- if (!credential) {
1981
- throw new Error("Failed to create WebAuthn credential");
1982
- }
1983
- const response = credential.response;
1984
- return {
1985
- credentialId: arrayBufferToBase64Url(credential.rawId),
1986
- publicKey: arrayBufferToBase64Url(_nullishCoalesce(_optionalChain([response, 'access', _37 => _37.getPublicKey, 'optionalCall', _38 => _38()]), () => ( new ArrayBuffer(0)))),
1987
- transports: _optionalChain([response, 'access', _39 => _39.getTransports, 'optionalCall', _40 => _40()])
1988
- };
1989
- }
1990
- async function getWebAuthnCredential(credentialInfo) {
1991
- if (!isWebAuthnSupported()) {
1992
- throw new Error("WebAuthn is not supported in this browser");
1993
- }
1994
- const credentialId = base64UrlToArrayBuffer(credentialInfo.credentialId);
1995
- const getOptions = {
1996
- challenge: STATIC_CHALLENGE,
1997
- rpId: getRpId(),
1998
- timeout: 6e4,
1999
- userVerification: "required",
2000
- allowCredentials: [
2001
- {
2002
- type: "public-key",
2003
- id: credentialId,
2004
- transports: credentialInfo.transports
2005
- }
2006
- ]
2007
- };
2008
- const assertion = await navigator.credentials.get({
2009
- publicKey: getOptions
2010
- });
2011
- if (!assertion) {
2012
- throw new Error("WebAuthn authentication failed");
2013
- }
2014
- const response = assertion.response;
2015
- return response.signature;
2016
- }
2017
-
2018
- // src/signless/storage.ts
2019
- var DEFAULT_STORAGE_KEY = "tonpay_signless_vault";
2020
- var SignlessStorage = class {
2021
-
2022
- constructor(storageKey = DEFAULT_STORAGE_KEY) {
2023
- this.storageKey = storageKey;
2024
- }
2025
- getStorage() {
2026
- if (typeof window === "undefined") return null;
2027
- return window.localStorage;
2028
- }
2029
- async saveVault(walletAddress, vault, authMethod, webauthnCredential) {
2030
- const storage = this.getStorage();
2031
- if (!storage) return;
2032
- const data = {
2033
- vault,
2034
- authMethod,
2035
- walletAddress,
2036
- webauthnCredential,
2037
- createdAt: Date.now(),
2038
- updatedAt: Date.now()
2039
- };
2040
- const key = this.getStorageKeyForWallet(walletAddress);
2041
- storage.setItem(key, JSON.stringify(data));
2042
- }
2043
- async loadVault(walletAddress) {
2044
- const storage = this.getStorage();
2045
- if (!storage) return null;
2046
- const key = this.getStorageKeyForWallet(walletAddress);
2047
- const data = storage.getItem(key);
2048
- if (!data) return null;
2049
- try {
2050
- return JSON.parse(data);
2051
- } catch (e5) {
2052
- return null;
2053
- }
2054
- }
2055
- async deleteVault(walletAddress) {
2056
- const storage = this.getStorage();
2057
- if (!storage) return;
2058
- const key = this.getStorageKeyForWallet(walletAddress);
2059
- storage.removeItem(key);
2060
- }
2061
- async hasVault(walletAddress) {
2062
- const vault = await this.loadVault(walletAddress);
2063
- return vault !== null;
2064
- }
2065
- async updateVaultTimestamp(walletAddress) {
2066
- const storage = this.getStorage();
2067
- if (!storage) return;
2068
- const vault = await this.loadVault(walletAddress);
2069
- if (!vault) return;
2070
- vault.updatedAt = Date.now();
2071
- const key = this.getStorageKeyForWallet(walletAddress);
2072
- storage.setItem(key, JSON.stringify(vault));
2073
- }
2074
- async getAllWalletsWithVaults() {
2075
- const storage = this.getStorage();
2076
- if (!storage) return [];
2077
- const wallets = [];
2078
- const prefix = `${this.storageKey}_`;
2079
- for (let i = 0; i < storage.length; i++) {
2080
- const key = storage.key(i);
2081
- if (_optionalChain([key, 'optionalAccess', _41 => _41.startsWith, 'call', _42 => _42(prefix)])) {
2082
- const walletAddress = key.slice(prefix.length);
2083
- wallets.push(walletAddress);
2084
- }
2085
- }
2086
- return wallets;
2087
- }
2088
- getStorageKeyForWallet(walletAddress) {
2089
- return `${this.storageKey}_${walletAddress}`;
2090
- }
2091
- };
2092
- var signlessStorage = new SignlessStorage();
2093
-
2094
- // src/signless/context.tsx
2095
-
2096
- var DEFAULT_CONFIG = {
2097
- enabled: false,
2098
- authMethod: "none",
2099
- autoLockTimeout: 5 * 60 * 1e3,
2100
- storageKey: "tonpay_signless_vault"
2101
- };
2102
- var DEFAULT_STATE = {
2103
- status: "disabled",
2104
- isEnabled: false,
2105
- isSetup: false,
2106
- isUnlocked: false,
2107
- authMethod: "none",
2108
- publicKey: null,
2109
- walletAddress: null
2110
- };
2111
- var SignlessContext = React9.createContext(null);
2112
- function SignlessProvider({ children, config }) {
2113
- const walletAddress = _uireact.useTonAddress.call(void 0, true);
2114
- const [state, setState] = React9.useState(DEFAULT_STATE);
2115
- const [currentConfig, setCurrentConfig] = React9.useState({
2116
- ...DEFAULT_CONFIG,
2117
- ...config
2118
- });
2119
- const storageRef = React9.useRef(
2120
- new SignlessStorage(currentConfig.storageKey)
2121
- );
2122
- const privateKeyRef = React9.useRef(null);
2123
- const lockTimeoutRef = React9.useRef(
2124
- null
2125
- );
2126
- const webauthnCredentialRef = React9.useRef(
2127
- null
2128
- );
2129
- const [isBiometricAvailable, setIsBiometricAvailable] = React9.useState(false);
2130
- React9.useEffect(() => {
2131
- async function checkBiometric() {
2132
- if (!isWebAuthnSupported()) {
2133
- setIsBiometricAvailable(false);
2134
- return;
2135
- }
2136
- try {
2137
- const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
2138
- setIsBiometricAvailable(available);
2139
- } catch (e6) {
2140
- setIsBiometricAvailable(false);
2141
- }
2142
- }
2143
- checkBiometric();
2144
- }, []);
2145
- React9.useEffect(() => {
2146
- async function loadVaultState() {
2147
- if (!walletAddress) {
2148
- setState({ ...DEFAULT_STATE });
2149
- return;
2150
- }
2151
- if (!currentConfig.enabled) {
2152
- setState({
2153
- ...DEFAULT_STATE,
2154
- status: "disabled",
2155
- walletAddress
2156
- });
2157
- return;
2158
- }
2159
- const vaultData = await storageRef.current.loadVault(walletAddress);
2160
- if (!vaultData) {
2161
- setState({
2162
- ...DEFAULT_STATE,
2163
- status: "not_setup",
2164
- isEnabled: true,
2165
- walletAddress
2166
- });
2167
- return;
2168
- }
2169
- webauthnCredentialRef.current = vaultData.webauthnCredential || null;
2170
- setState({
2171
- status: "locked",
2172
- isEnabled: true,
2173
- isSetup: true,
2174
- isUnlocked: false,
2175
- authMethod: vaultData.authMethod,
2176
- publicKey: vaultData.vault.publicKey,
2177
- walletAddress
2178
- });
2179
- }
2180
- loadVaultState();
2181
- }, [walletAddress, currentConfig.enabled]);
2182
- const resetLockTimeout = React9.useCallback(() => {
2183
- if (lockTimeoutRef.current) {
2184
- clearTimeout(lockTimeoutRef.current);
2185
- }
2186
- if (currentConfig.autoLockTimeout && currentConfig.autoLockTimeout > 0) {
2187
- lockTimeoutRef.current = setTimeout(() => {
2188
- if (privateKeyRef.current) {
2189
- privateKeyRef.current.fill(0);
2190
- privateKeyRef.current = null;
2191
- }
2192
- setState((prev) => ({
2193
- ...prev,
2194
- status: "locked",
2195
- isUnlocked: false
2196
- }));
2197
- }, currentConfig.autoLockTimeout);
2198
- }
2199
- }, [currentConfig.autoLockTimeout]);
2200
- const setup = React9.useCallback(
2201
- async (params) => {
2202
- if (!walletAddress) {
2203
- throw new Error("Wallet not connected");
2204
- }
2205
- setState((prev) => ({ ...prev, status: "setting_up" }));
2206
- try {
2207
- const keyPair = await generateKeyPair();
2208
- let webauthnCredential;
2209
- if (params.authMethod === "biometric") {
2210
- webauthnCredential = await createWebAuthnCredential(walletAddress);
2211
- webauthnCredentialRef.current = webauthnCredential;
2212
- const signature = await getWebAuthnCredential(webauthnCredential);
2213
- const signatureBytes = new Uint8Array(signature);
2214
- const biometricPin = Array.from(signatureBytes.slice(0, 32)).map((b) => b.toString(16).padStart(2, "0")).join("");
2215
- const vault = await encryptPrivateKey(
2216
- keyPair.privateKey,
2217
- keyPair.publicKey,
2218
- biometricPin
2219
- );
2220
- await storageRef.current.saveVault(
2221
- walletAddress,
2222
- vault,
2223
- "biometric",
2224
- webauthnCredential
2225
- );
2226
- privateKeyRef.current = keyPair.privateKey;
2227
- } else if (params.authMethod === "pin") {
2228
- if (!params.pin) {
2229
- throw new Error("PIN is required for PIN authentication");
2230
- }
2231
- const vault = await encryptPrivateKey(
2232
- keyPair.privateKey,
2233
- keyPair.publicKey,
2234
- params.pin
2235
- );
2236
- await storageRef.current.saveVault(walletAddress, vault, "pin");
2237
- privateKeyRef.current = keyPair.privateKey;
2238
- } else {
2239
- throw new Error("Invalid authentication method");
2240
- }
2241
- setState({
2242
- status: "unlocked",
2243
- isEnabled: true,
2244
- isSetup: true,
2245
- isUnlocked: true,
2246
- authMethod: params.authMethod,
2247
- publicKey: arrayBufferToBase642(keyPair.publicKey.buffer),
2248
- walletAddress
2249
- });
2250
- resetLockTimeout();
2251
- } catch (error) {
2252
- setState((prev) => ({
2253
- ...prev,
2254
- status: prev.isSetup ? "locked" : "not_setup"
2255
- }));
2256
- throw error;
2257
- }
2258
- },
2259
- [walletAddress, resetLockTimeout]
2260
- );
2261
- const unlock = React9.useCallback(
2262
- async (params) => {
2263
- if (!walletAddress) {
2264
- throw new Error("Wallet not connected");
2265
- }
2266
- const vaultData = await storageRef.current.loadVault(walletAddress);
2267
- if (!vaultData) {
2268
- throw new Error("No signless vault found");
2269
- }
2270
- try {
2271
- let pin;
2272
- if (vaultData.authMethod === "biometric") {
2273
- if (!vaultData.webauthnCredential) {
2274
- throw new Error("WebAuthn credential not found");
2275
- }
2276
- const signature = await getWebAuthnCredential(
2277
- vaultData.webauthnCredential
2278
- );
2279
- const signatureBytes = new Uint8Array(signature);
2280
- pin = Array.from(signatureBytes.slice(0, 32)).map((b) => b.toString(16).padStart(2, "0")).join("");
2281
- } else if (vaultData.authMethod === "pin") {
2282
- if (!params.pin) {
2283
- throw new Error("PIN is required");
2284
- }
2285
- pin = params.pin;
2286
- } else {
2287
- throw new Error("Invalid authentication method");
2288
- }
2289
- const privateKey = await decryptPrivateKey(vaultData.vault, pin);
2290
- privateKeyRef.current = privateKey;
2291
- setState((prev) => ({
2292
- ...prev,
2293
- status: "unlocked",
2294
- isUnlocked: true
2295
- }));
2296
- resetLockTimeout();
2297
- } catch (error) {
2298
- throw new Error("Failed to unlock vault");
2299
- }
2300
- },
2301
- [walletAddress, resetLockTimeout]
2302
- );
2303
- const lock = React9.useCallback(() => {
2304
- if (lockTimeoutRef.current) {
2305
- clearTimeout(lockTimeoutRef.current);
2306
- }
2307
- if (privateKeyRef.current) {
2308
- privateKeyRef.current.fill(0);
2309
- privateKeyRef.current = null;
2310
- }
2311
- setState((prev) => ({
2312
- ...prev,
2313
- status: "locked",
2314
- isUnlocked: false
2315
- }));
2316
- }, []);
2317
- const reset = React9.useCallback(async () => {
2318
- if (!walletAddress) return;
2319
- if (lockTimeoutRef.current) {
2320
- clearTimeout(lockTimeoutRef.current);
2321
- }
2322
- if (privateKeyRef.current) {
2323
- privateKeyRef.current.fill(0);
2324
- privateKeyRef.current = null;
2325
- }
2326
- webauthnCredentialRef.current = null;
2327
- await storageRef.current.deleteVault(walletAddress);
2328
- setState({
2329
- ...DEFAULT_STATE,
2330
- status: currentConfig.enabled ? "not_setup" : "disabled",
2331
- isEnabled: currentConfig.enabled,
2332
- walletAddress
2333
- });
2334
- }, [walletAddress, currentConfig.enabled]);
2335
- const signPayload = React9.useCallback(
2336
- async (params) => {
2337
- if (!privateKeyRef.current) {
2338
- throw new Error("Signless is locked. Please unlock first.");
2339
- }
2340
- if (!state.publicKey) {
2341
- throw new Error("Public key not available");
2342
- }
2343
- resetLockTimeout();
2344
- const reference = params.reference || generateReference();
2345
- const validUntil = params.validUntil || Math.floor(Date.now() / 1e3) + 300;
2346
- const payloadData = {
2347
- recipient: params.recipient,
2348
- amount: params.amount,
2349
- token: params.token || "TON",
2350
- payload: params.payload || "",
2351
- reference,
2352
- validUntil
2353
- };
2354
- const encoder = new TextEncoder();
2355
- const payloadBytes = encoder.encode(JSON.stringify(payloadData));
2356
- const signature = await signMessage(privateKeyRef.current, payloadBytes);
2357
- return {
2358
- payload: payloadBytes,
2359
- signature,
2360
- publicKey: state.publicKey,
2361
- reference,
2362
- validUntil
2363
- };
2364
- },
2365
- [state.publicKey, resetLockTimeout]
2366
- );
2367
- const updateConfig = React9.useCallback(
2368
- (newConfig) => {
2369
- setCurrentConfig((prev) => ({ ...prev, ...newConfig }));
2370
- },
2371
- []
2372
- );
2373
- React9.useEffect(() => {
2374
- return () => {
2375
- if (lockTimeoutRef.current) {
2376
- clearTimeout(lockTimeoutRef.current);
2377
- }
2378
- if (privateKeyRef.current) {
2379
- privateKeyRef.current.fill(0);
2380
- privateKeyRef.current = null;
2381
- }
2382
- };
2383
- }, []);
2384
- const contextValue = {
2385
- state,
2386
- config: currentConfig,
2387
- setup,
2388
- unlock,
2389
- lock,
2390
- reset,
2391
- signPayload,
2392
- updateConfig,
2393
- isBiometricAvailable
2394
- };
2395
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SignlessContext.Provider, { value: contextValue, children });
2396
- }
2397
- function useSignless() {
2398
- const context = React9.useContext(SignlessContext);
2399
- if (!context) {
2400
- throw new Error("useSignless must be used within a SignlessProvider");
2401
- }
2402
- return context;
2403
- }
2404
- function generateReference() {
2405
- const bytes = new Uint8Array(16);
2406
- crypto.getRandomValues(bytes);
2407
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2408
- }
2409
- function arrayBufferToBase642(buffer) {
2410
- const bytes = new Uint8Array(buffer);
2411
- let binary = "";
2412
- for (let i = 0; i < bytes.byteLength; i++) {
2413
- binary += String.fromCharCode(bytes[i]);
2414
- }
2415
- return btoa(binary);
2416
- }
2417
-
2418
- // src/signless/hooks/useTonPaySignless.ts
2419
-
2420
- function useTonPaySignless() {
2421
- const { pay, address } = useTonPay();
2422
- const signlessContext = useSignless();
2423
- const {
2424
- state,
2425
- config,
2426
- setup,
2427
- unlock,
2428
- lock,
2429
- reset,
2430
- signPayload,
2431
- updateConfig,
2432
- isBiometricAvailable
2433
- } = signlessContext;
2434
- const paySignless = React10.useCallback(
2435
- async (params) => {
2436
- if (!config.enabled) {
2437
- throw new Error("Signless is not enabled");
2438
- }
2439
- if (!state.isSetup) {
2440
- throw new Error("Signless is not set up. Please complete setup first.");
2441
- }
2442
- if (!state.isUnlocked) {
2443
- throw new Error("Signless is locked. Please unlock first.");
2444
- }
2445
- return signPayload(params);
2446
- },
2447
- [config.enabled, state.isSetup, state.isUnlocked, signPayload]
2448
- );
2449
- const requiresUnlock = React10.useMemo(() => {
2450
- return config.enabled && state.isSetup && !state.isUnlocked;
2451
- }, [config.enabled, state.isSetup, state.isUnlocked]);
2452
- return {
2453
- pay,
2454
- paySignless,
2455
- address,
2456
- signless: {
2457
- state,
2458
- config,
2459
- setup,
2460
- unlock,
2461
- lock,
2462
- reset,
2463
- updateConfig,
2464
- isBiometricAvailable,
2465
- isEnabled: config.enabled,
2466
- isSetup: state.isSetup,
2467
- isUnlocked: state.isUnlocked,
2468
- requiresUnlock
2469
- }
2470
- };
2471
- }
2472
-
2473
- // src/signless/hooks/useSignlessModal.ts
2474
-
2475
- function useSignlessModal() {
2476
- const { state, config } = useSignless();
2477
- const [modalType, setModalType] = React11.useState(null);
2478
- const openSetup = React11.useCallback(() => {
2479
- if (!config.enabled) {
2480
- console.warn("Signless is not enabled");
2481
- return;
2482
- }
2483
- setModalType("setup");
2484
- }, [config.enabled]);
2485
- const openUnlock = React11.useCallback(() => {
2486
- if (!config.enabled) {
2487
- console.warn("Signless is not enabled");
2488
- return;
2489
- }
2490
- if (!state.isSetup) {
2491
- console.warn("Signless is not set up");
2492
- return;
2493
- }
2494
- setModalType("unlock");
2495
- }, [config.enabled, state.isSetup]);
2496
- const close = React11.useCallback(() => {
2497
- setModalType(null);
2498
- }, []);
2499
- const onSetupComplete = React11.useCallback(() => {
2500
- setModalType(null);
2501
- }, []);
2502
- const onUnlockComplete = React11.useCallback(() => {
2503
- setModalType(null);
2504
- }, []);
2505
- return {
2506
- modalType,
2507
- isOpen: modalType !== null,
2508
- openSetup,
2509
- openUnlock,
2510
- close,
2511
- onSetupComplete,
2512
- onUnlockComplete
2513
- };
2514
- }
2515
-
2516
- // src/signless/components/PinInput.tsx
2517
-
2518
-
2519
- // src/signless/components/styles.ts
2520
- var pinInputStyles = {
2521
- container: {
2522
- display: "flex",
2523
- flexDirection: "column",
2524
- alignItems: "center",
2525
- padding: "24px",
2526
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2527
- color: "#ffffff",
2528
- minWidth: "280px"
2529
- },
2530
- header: {
2531
- textAlign: "center",
2532
- marginBottom: "32px"
2533
- },
2534
- title: {
2535
- fontSize: "20px",
2536
- fontWeight: 600,
2537
- margin: "0 0 8px 0",
2538
- color: "#ffffff"
2539
- },
2540
- subtitle: {
2541
- fontSize: "14px",
2542
- color: "rgba(255, 255, 255, 0.6)",
2543
- margin: 0
2544
- },
2545
- hiddenInput: {
2546
- position: "absolute",
2547
- opacity: 0,
2548
- pointerEvents: "none"
2549
- },
2550
- dotsContainer: {
2551
- display: "flex",
2552
- gap: "16px",
2553
- marginBottom: "32px",
2554
- cursor: "pointer"
2555
- },
2556
- dotsContainerShake: {
2557
- animation: "tonpay-pin-shake 0.5s ease-in-out"
2558
- },
2559
- dot: {
2560
- width: "14px",
2561
- height: "14px",
2562
- borderRadius: "50%",
2563
- backgroundColor: "rgba(255, 255, 255, 0.2)",
2564
- border: "2px solid rgba(255, 255, 255, 0.3)",
2565
- transition: "all 0.15s ease"
2566
- },
2567
- dotFilled: {
2568
- backgroundColor: "#0098EA",
2569
- borderColor: "#0098EA",
2570
- transform: "scale(1.1)"
2571
- },
2572
- dotLoading: {
2573
- animation: "tonpay-pin-pulse 1s ease-in-out infinite"
2574
- },
2575
- error: {
2576
- fontSize: "14px",
2577
- color: "#FF5252",
2578
- margin: "-16px 0 24px 0",
2579
- textAlign: "center"
2580
- },
2581
- keypad: {
2582
- display: "grid",
2583
- gridTemplateColumns: "repeat(3, 1fr)",
2584
- gap: "8px",
2585
- width: "100%",
2586
- maxWidth: "260px"
2587
- },
2588
- keypadButton: {
2589
- width: "72px",
2590
- height: "56px",
2591
- fontSize: "24px",
2592
- fontWeight: 500,
2593
- color: "#ffffff",
2594
- backgroundColor: "transparent",
2595
- border: "none",
2596
- borderRadius: "12px",
2597
- cursor: "pointer",
2598
- transition: "background-color 0.15s ease",
2599
- display: "flex",
2600
- alignItems: "center",
2601
- justifyContent: "center"
2602
- },
2603
- keypadButtonEmpty: {
2604
- width: "72px",
2605
- height: "56px",
2606
- display: "flex",
2607
- alignItems: "center",
2608
- justifyContent: "center"
2609
- },
2610
- biometricButton: {
2611
- width: "56px",
2612
- height: "56px",
2613
- fontSize: "24px",
2614
- color: "#0098EA",
2615
- backgroundColor: "transparent",
2616
- border: "none",
2617
- borderRadius: "12px",
2618
- cursor: "pointer",
2619
- transition: "background-color 0.15s ease",
2620
- display: "flex",
2621
- alignItems: "center",
2622
- justifyContent: "center"
2623
- },
2624
- backspaceButton: {
2625
- width: "72px",
2626
- height: "56px",
2627
- fontSize: "24px",
2628
- color: "rgba(255, 255, 255, 0.6)",
2629
- backgroundColor: "transparent",
2630
- border: "none",
2631
- borderRadius: "12px",
2632
- cursor: "pointer",
2633
- transition: "all 0.15s ease",
2634
- display: "flex",
2635
- alignItems: "center",
2636
- justifyContent: "center"
2637
- },
2638
- cancelButton: {
2639
- marginTop: "24px",
2640
- padding: "12px 32px",
2641
- fontSize: "16px",
2642
- fontWeight: 500,
2643
- color: "rgba(255, 255, 255, 0.6)",
2644
- backgroundColor: "transparent",
2645
- border: "none",
2646
- borderRadius: "8px",
2647
- cursor: "pointer",
2648
- transition: "color 0.15s ease"
2649
- }
2650
- };
2651
- var setupModalStyles = {
2652
- container: {
2653
- display: "flex",
2654
- flexDirection: "column",
2655
- alignItems: "center",
2656
- padding: "24px",
2657
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2658
- color: "#ffffff"
2659
- },
2660
- header: {
2661
- textAlign: "center",
2662
- marginBottom: "24px"
2663
- },
2664
- title: {
2665
- fontSize: "22px",
2666
- fontWeight: 600,
2667
- margin: "0 0 8px 0",
2668
- color: "#ffffff"
2669
- },
2670
- subtitle: {
2671
- fontSize: "14px",
2672
- color: "rgba(255, 255, 255, 0.6)",
2673
- margin: 0,
2674
- lineHeight: 1.5,
2675
- maxWidth: "280px"
2676
- },
2677
- methodSelector: {
2678
- display: "flex",
2679
- flexDirection: "column",
2680
- gap: "12px",
2681
- width: "100%",
2682
- marginBottom: "24px"
2683
- },
2684
- methodButton: {
2685
- display: "flex",
2686
- alignItems: "center",
2687
- gap: "16px",
2688
- padding: "16px",
2689
- backgroundColor: "rgba(255, 255, 255, 0.05)",
2690
- border: "1px solid rgba(255, 255, 255, 0.1)",
2691
- borderRadius: "12px",
2692
- cursor: "pointer",
2693
- transition: "all 0.15s ease",
2694
- textAlign: "left",
2695
- width: "100%"
2696
- },
2697
- methodButtonSelected: {
2698
- backgroundColor: "rgba(0, 152, 234, 0.15)",
2699
- borderColor: "#0098EA"
2700
- },
2701
- methodIcon: {
2702
- width: "48px",
2703
- height: "48px",
2704
- borderRadius: "12px",
2705
- backgroundColor: "rgba(255, 255, 255, 0.1)",
2706
- display: "flex",
2707
- alignItems: "center",
2708
- justifyContent: "center",
2709
- color: "#0098EA",
2710
- flexShrink: 0
2711
- },
2712
- methodContent: {
2713
- flex: 1,
2714
- minWidth: 0
2715
- },
2716
- methodTitle: {
2717
- fontSize: "16px",
2718
- fontWeight: 600,
2719
- color: "#ffffff",
2720
- margin: "0 0 4px 0"
2721
- },
2722
- methodDescription: {
2723
- fontSize: "13px",
2724
- color: "rgba(255, 255, 255, 0.5)",
2725
- margin: 0,
2726
- lineHeight: 1.4
2727
- },
2728
- continueButton: {
2729
- width: "100%",
2730
- padding: "14px 24px",
2731
- fontSize: "16px",
2732
- fontWeight: 600,
2733
- color: "#ffffff",
2734
- backgroundColor: "#0098EA",
2735
- border: "none",
2736
- borderRadius: "12px",
2737
- cursor: "pointer",
2738
- transition: "opacity 0.15s ease"
2739
- },
2740
- continueButtonDisabled: {
2741
- opacity: 0.5,
2742
- cursor: "not-allowed"
2743
- },
2744
- stepIndicator: {
2745
- display: "flex",
2746
- gap: "8px",
2747
- marginBottom: "24px"
2748
- },
2749
- stepDot: {
2750
- width: "8px",
2751
- height: "8px",
2752
- borderRadius: "50%",
2753
- backgroundColor: "rgba(255, 255, 255, 0.2)"
2754
- },
2755
- stepDotActive: {
2756
- backgroundColor: "#0098EA"
2757
- }
2758
- };
2759
- var unlockModalStyles = {
2760
- container: {
2761
- display: "flex",
2762
- flexDirection: "column",
2763
- alignItems: "center",
2764
- padding: "24px",
2765
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2766
- color: "#ffffff"
2767
- },
2768
- biometricPrompt: {
2769
- display: "flex",
2770
- flexDirection: "column",
2771
- alignItems: "center",
2772
- padding: "32px",
2773
- textAlign: "center"
2774
- },
2775
- biometricIcon: {
2776
- width: "80px",
2777
- height: "80px",
2778
- borderRadius: "20px",
2779
- backgroundColor: "rgba(0, 152, 234, 0.15)",
2780
- display: "flex",
2781
- alignItems: "center",
2782
- justifyContent: "center",
2783
- color: "#0098EA",
2784
- marginBottom: "24px"
2785
- },
2786
- biometricTitle: {
2787
- fontSize: "20px",
2788
- fontWeight: 600,
2789
- margin: "0 0 8px 0",
2790
- color: "#ffffff"
2791
- },
2792
- biometricSubtitle: {
2793
- fontSize: "14px",
2794
- color: "rgba(255, 255, 255, 0.6)",
2795
- margin: "0 0 24px 0"
2796
- },
2797
- usePinButton: {
2798
- padding: "12px 24px",
2799
- fontSize: "14px",
2800
- fontWeight: 500,
2801
- color: "#0098EA",
2802
- backgroundColor: "transparent",
2803
- border: "none",
2804
- cursor: "pointer",
2805
- transition: "opacity 0.15s ease"
2806
- }
2807
- };
2808
-
2809
- // src/signless/components/PinInput.tsx
2810
-
2811
- var PIN_LENGTH = 6;
2812
- var PinInput = ({
2813
- length = PIN_LENGTH,
2814
- onComplete,
2815
- onCancel,
2816
- title = "Enter PIN",
2817
- subtitle,
2818
- error,
2819
- isLoading = false,
2820
- showBiometric = false,
2821
- onBiometricPress
2822
- }) => {
2823
- const [pin, setPin] = React12.useState("");
2824
- const [shake, setShake] = React12.useState(false);
2825
- const inputRef = React12.useRef(null);
2826
- React12.useEffect(() => {
2827
- if (error) {
2828
- setShake(true);
2829
- setPin("");
2830
- const timer = setTimeout(() => setShake(false), 500);
2831
- return () => clearTimeout(timer);
2832
- }
2833
- }, [error]);
2834
- React12.useEffect(() => {
2835
- _optionalChain([inputRef, 'access', _43 => _43.current, 'optionalAccess', _44 => _44.focus, 'call', _45 => _45()]);
2836
- }, []);
2837
- const handleChange = (e) => {
2838
- const value = e.target.value.replace(/\D/g, "").slice(0, length);
2839
- setPin(value);
2840
- if (value.length === length) {
2841
- onComplete(value);
2842
- }
2843
- };
2844
- const handleKeyDown = (e) => {
2845
- if (e.key === "Escape" && onCancel) {
2846
- onCancel();
2847
- }
2848
- };
2849
- const handleDotClick = () => {
2850
- _optionalChain([inputRef, 'access', _46 => _46.current, 'optionalAccess', _47 => _47.focus, 'call', _48 => _48()]);
2851
- };
2852
- const handleKeyPress = (digit) => {
2853
- if (pin.length >= length || isLoading) return;
2854
- const newPin = pin + digit;
2855
- setPin(newPin);
2856
- if (newPin.length === length) {
2857
- onComplete(newPin);
2858
- }
2859
- };
2860
- const handleBackspace = () => {
2861
- if (isLoading) return;
2862
- setPin((prev) => prev.slice(0, -1));
2863
- };
2864
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: pinInputStyles.container, children: [
2865
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "style", { children: keyframes }),
2866
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: pinInputStyles.header, children: [
2867
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { style: pinInputStyles.title, children: title }),
2868
- subtitle && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: pinInputStyles.subtitle, children: subtitle })
2869
- ] }),
2870
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2871
- "input",
2872
- {
2873
- ref: inputRef,
2874
- type: "text",
2875
- inputMode: "numeric",
2876
- pattern: "[0-9]*",
2877
- value: pin,
2878
- onChange: handleChange,
2879
- onKeyDown: handleKeyDown,
2880
- maxLength: length,
2881
- autoComplete: "off",
2882
- style: pinInputStyles.hiddenInput,
2883
- disabled: isLoading
2884
- }
2885
- ),
2886
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2887
- "div",
2888
- {
2889
- style: {
2890
- ...pinInputStyles.dotsContainer,
2891
- ...shake ? pinInputStyles.dotsContainerShake : {}
2892
- },
2893
- onClick: handleDotClick,
2894
- children: Array.from({ length }, (_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2895
- "div",
2896
- {
2897
- style: {
2898
- ...pinInputStyles.dot,
2899
- ...i < pin.length ? pinInputStyles.dotFilled : {},
2900
- ...isLoading ? pinInputStyles.dotLoading : {}
2901
- }
2902
- },
2903
- i
2904
- ))
2905
- }
2906
- ),
2907
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: pinInputStyles.error, children: error }),
2908
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: pinInputStyles.keypad, children: [
2909
- [1, 2, 3, 4, 5, 6, 7, 8, 9].map((digit) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2910
- "button",
2911
- {
2912
- type: "button",
2913
- style: pinInputStyles.keypadButton,
2914
- onClick: () => handleKeyPress(String(digit)),
2915
- disabled: isLoading,
2916
- onMouseEnter: (e) => {
2917
- e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2918
- },
2919
- onMouseLeave: (e) => {
2920
- e.target.style.backgroundColor = "transparent";
2921
- },
2922
- children: digit
2923
- },
2924
- digit
2925
- )),
2926
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: pinInputStyles.keypadButtonEmpty, children: showBiometric && onBiometricPress && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2927
- "button",
2928
- {
2929
- type: "button",
2930
- style: pinInputStyles.biometricButton,
2931
- onClick: onBiometricPress,
2932
- disabled: isLoading,
2933
- "aria-label": "Use biometric authentication",
2934
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BiometricIcon, {})
2935
- }
2936
- ) }),
2937
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2938
- "button",
2939
- {
2940
- type: "button",
2941
- style: pinInputStyles.keypadButton,
2942
- onClick: () => handleKeyPress("0"),
2943
- disabled: isLoading,
2944
- onMouseEnter: (e) => {
2945
- e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2946
- },
2947
- onMouseLeave: (e) => {
2948
- e.target.style.backgroundColor = "transparent";
2949
- },
2950
- children: "0"
2951
- }
2952
- ),
2953
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2954
- "button",
2955
- {
2956
- type: "button",
2957
- style: pinInputStyles.backspaceButton,
2958
- onClick: handleBackspace,
2959
- disabled: isLoading || pin.length === 0,
2960
- "aria-label": "Backspace",
2961
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BackspaceIcon, {})
2962
- }
2963
- )
2964
- ] }),
2965
- onCancel && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2966
- "button",
2967
- {
2968
- type: "button",
2969
- style: pinInputStyles.cancelButton,
2970
- onClick: onCancel,
2971
- disabled: isLoading,
2972
- children: "Cancel"
2973
- }
2974
- )
2975
- ] });
2976
- };
2977
- var BiometricIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2978
- "svg",
2979
- {
2980
- width: "28",
2981
- height: "28",
2982
- viewBox: "0 0 24 24",
2983
- fill: "none",
2984
- xmlns: "http://www.w3.org/2000/svg",
2985
- children: [
2986
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2987
- "path",
2988
- {
2989
- d: "M12 14.5V16.5M7 10.5C7 7.73858 9.23858 5.5 12 5.5C14.7614 5.5 17 7.73858 17 10.5V11.5M12 11.5C10.6193 11.5 9.5 12.6193 9.5 14C9.5 15.3807 10.6193 16.5 12 16.5C13.3807 16.5 14.5 15.3807 14.5 14C14.5 12.6193 13.3807 11.5 12 11.5Z",
2990
- stroke: "currentColor",
2991
- strokeWidth: "1.5",
2992
- strokeLinecap: "round",
2993
- strokeLinejoin: "round"
2994
- }
2995
- ),
2996
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2997
- "path",
2998
- {
2999
- d: "M3 7V5C3 3.89543 3.89543 3 5 3H7M17 3H19C20.1046 3 21 3.89543 21 5V7M21 17V19C21 20.1046 20.1046 21 19 21H17M7 21H5C3.89543 21 3 20.1046 3 19V17",
3000
- stroke: "currentColor",
3001
- strokeWidth: "1.5",
3002
- strokeLinecap: "round",
3003
- strokeLinejoin: "round"
3004
- }
3005
- )
3006
- ]
3007
- }
3008
- );
3009
- var BackspaceIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3010
- "svg",
3011
- {
3012
- width: "24",
3013
- height: "24",
3014
- viewBox: "0 0 24 24",
3015
- fill: "none",
3016
- xmlns: "http://www.w3.org/2000/svg",
3017
- children: [
3018
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3019
- "path",
3020
- {
3021
- d: "M9.00195 7L4.00195 12L9.00195 17M19.002 7H8.00195L4.00195 12L8.00195 17H19.002C19.5325 17 20.0412 16.7893 20.4163 16.4142C20.7914 16.0391 21.002 15.5304 21.002 15V9C21.002 8.46957 20.7914 7.96086 20.4163 7.58579C20.0412 7.21071 19.5325 7 19.002 7Z",
3022
- stroke: "currentColor",
3023
- strokeWidth: "1.5",
3024
- strokeLinecap: "round",
3025
- strokeLinejoin: "round"
3026
- }
3027
- ),
3028
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3029
- "path",
3030
- {
3031
- d: "M14 10L10 14M10 10L14 14",
3032
- stroke: "currentColor",
3033
- strokeWidth: "1.5",
3034
- strokeLinecap: "round",
3035
- strokeLinejoin: "round"
3036
- }
3037
- )
3038
- ]
3039
- }
3040
- );
3041
- var keyframes = `
3042
- @keyframes tonpay-pin-shake {
3043
- 0%, 100% { transform: translateX(0); }
3044
- 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
3045
- 20%, 40%, 60%, 80% { transform: translateX(4px); }
3046
- }
3047
- @keyframes tonpay-pin-pulse {
3048
- 0%, 100% { opacity: 1; }
3049
- 50% { opacity: 0.5; }
3050
- }
3051
- `;
3052
-
3053
- // src/signless/components/SignlessSetupModal.tsx
3054
-
3055
-
3056
- var SignlessSetupModal = ({
3057
- isOpen,
3058
- onClose,
3059
- onComplete,
3060
- showBiometric = true
3061
- }) => {
3062
- const { setup, isBiometricAvailable, state } = useSignless();
3063
- const [step, setStep] = React13.useState("select_method");
3064
- const [selectedMethod, setSelectedMethod] = React13.useState(null);
3065
- const [pin, setPin] = React13.useState("");
3066
- const [error, setError] = React13.useState(null);
3067
- const [isLoading, setIsLoading] = React13.useState(false);
3068
- React13.useEffect(() => {
3069
- if (isOpen) {
3070
- setStep("select_method");
3071
- setSelectedMethod(null);
3072
- setPin("");
3073
- setError(null);
3074
- setIsLoading(false);
3075
- }
3076
- }, [isOpen]);
3077
- const handleMethodSelect = (method) => {
3078
- setSelectedMethod(method);
3079
- };
3080
- const handleContinue = async () => {
3081
- if (!selectedMethod) return;
3082
- if (selectedMethod === "biometric") {
3083
- setIsLoading(true);
3084
- setError(null);
3085
- try {
3086
- await setup({ authMethod: "biometric" });
3087
- onComplete();
3088
- onClose();
3089
- } catch (err) {
3090
- setError(
3091
- err instanceof Error ? err.message : "Biometric setup failed"
3092
- );
3093
- } finally {
3094
- setIsLoading(false);
3095
- }
3096
- } else if (selectedMethod === "pin") {
3097
- setStep("create_pin");
3098
- }
3099
- };
3100
- const handlePinCreate = (newPin) => {
3101
- setPin(newPin);
3102
- setError(null);
3103
- setStep("confirm_pin");
3104
- };
3105
- const handlePinConfirm = async (confirmPin) => {
3106
- if (confirmPin !== pin) {
3107
- setError("PINs do not match. Please try again.");
3108
- setStep("create_pin");
3109
- setPin("");
3110
- return;
3111
- }
3112
- setIsLoading(true);
3113
- setError(null);
3114
- try {
3115
- await setup({ authMethod: "pin", pin });
3116
- onComplete();
3117
- onClose();
3118
- } catch (err) {
3119
- setError(err instanceof Error ? err.message : "Setup failed");
3120
- setStep("create_pin");
3121
- setPin("");
3122
- } finally {
3123
- setIsLoading(false);
3124
- }
3125
- };
3126
- const handleBack = () => {
3127
- if (step === "confirm_pin") {
3128
- setStep("create_pin");
3129
- setError(null);
3130
- } else if (step === "create_pin") {
3131
- setStep("select_method");
3132
- setPin("");
3133
- setError(null);
3134
- }
3135
- };
3136
- if (!isOpen) return null;
3137
- const renderStepIndicator = () => {
3138
- const steps = selectedMethod === "pin" ? 3 : 2;
3139
- const currentStep = step === "select_method" ? 1 : step === "create_pin" ? 2 : 3;
3140
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: setupModalStyles.stepIndicator, children: Array.from({ length: steps }, (_, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3141
- "div",
3142
- {
3143
- style: {
3144
- ...setupModalStyles.stepDot,
3145
- ...i < currentStep ? setupModalStyles.stepDotActive : {}
3146
- }
3147
- },
3148
- i
3149
- )) });
3150
- };
3151
- const renderMethodSelection = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3152
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: setupModalStyles.header, children: [
3153
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { style: setupModalStyles.title, children: "Setup Signless" }),
3154
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: setupModalStyles.subtitle, children: "Enable fast payments without wallet confirmations. Choose your preferred authentication method." })
3155
- ] }),
3156
- renderStepIndicator(),
3157
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: setupModalStyles.methodSelector, children: [
3158
- showBiometric && isBiometricAvailable && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3159
- "button",
3160
- {
3161
- type: "button",
3162
- style: {
3163
- ...setupModalStyles.methodButton,
3164
- ...selectedMethod === "biometric" ? setupModalStyles.methodButtonSelected : {}
3165
- },
3166
- onClick: () => handleMethodSelect("biometric"),
3167
- children: [
3168
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: setupModalStyles.methodIcon, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FaceIdIcon, {}) }),
3169
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: setupModalStyles.methodContent, children: [
3170
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { style: setupModalStyles.methodTitle, children: "Face ID / Touch ID" }),
3171
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: setupModalStyles.methodDescription, children: "Use biometric authentication for quick and secure access" })
3172
- ] })
3173
- ]
3174
- }
3175
- ),
3176
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3177
- "button",
3178
- {
3179
- type: "button",
3180
- style: {
3181
- ...setupModalStyles.methodButton,
3182
- ...selectedMethod === "pin" ? setupModalStyles.methodButtonSelected : {}
3183
- },
3184
- onClick: () => handleMethodSelect("pin"),
3185
- children: [
3186
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: setupModalStyles.methodIcon, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PinIcon, {}) }),
3187
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: setupModalStyles.methodContent, children: [
3188
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { style: setupModalStyles.methodTitle, children: "PIN Code" }),
3189
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: setupModalStyles.methodDescription, children: "Create a 6-digit PIN for payment authorization" })
3190
- ] })
3191
- ]
3192
- }
3193
- )
3194
- ] }),
3195
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { color: "#FF5252", fontSize: "14px", marginBottom: "16px" }, children: error }),
3196
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3197
- "button",
3198
- {
3199
- type: "button",
3200
- style: {
3201
- ...setupModalStyles.continueButton,
3202
- ...!selectedMethod ? setupModalStyles.continueButtonDisabled : {}
3203
- },
3204
- onClick: handleContinue,
3205
- disabled: !selectedMethod || isLoading,
3206
- children: isLoading ? "Setting up..." : "Continue"
3207
- }
3208
- )
3209
- ] });
3210
- const renderPinCreation = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3211
- renderStepIndicator(),
3212
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3213
- PinInput,
3214
- {
3215
- title: "Create PIN",
3216
- subtitle: "Enter a 6-digit PIN to secure your signless payments",
3217
- onComplete: handlePinCreate,
3218
- onCancel: handleBack,
3219
- error,
3220
- isLoading
3221
- }
3222
- )
3223
- ] });
3224
- const renderPinConfirmation = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3225
- renderStepIndicator(),
3226
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3227
- PinInput,
3228
- {
3229
- title: "Confirm PIN",
3230
- subtitle: "Re-enter your PIN to confirm",
3231
- onComplete: handlePinConfirm,
3232
- onCancel: handleBack,
3233
- error,
3234
- isLoading
3235
- }
3236
- )
3237
- ] });
3238
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: setupModalStyles.container, children: [
3239
- step === "select_method" && renderMethodSelection(),
3240
- step === "create_pin" && renderPinCreation(),
3241
- step === "confirm_pin" && renderPinConfirmation()
3242
- ] });
3243
- };
3244
- var FaceIdIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3245
- "svg",
3246
- {
3247
- width: "28",
3248
- height: "28",
3249
- viewBox: "0 0 24 24",
3250
- fill: "none",
3251
- xmlns: "http://www.w3.org/2000/svg",
3252
- children: [
3253
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3254
- "path",
3255
- {
3256
- d: "M12 14.5V16.5M7 10.5C7 7.73858 9.23858 5.5 12 5.5C14.7614 5.5 17 7.73858 17 10.5V11.5M12 11.5C10.6193 11.5 9.5 12.6193 9.5 14C9.5 15.3807 10.6193 16.5 12 16.5C13.3807 16.5 14.5 15.3807 14.5 14C14.5 12.6193 13.3807 11.5 12 11.5Z",
3257
- stroke: "currentColor",
3258
- strokeWidth: "1.5",
3259
- strokeLinecap: "round",
3260
- strokeLinejoin: "round"
3261
- }
3262
- ),
3263
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3264
- "path",
3265
- {
3266
- d: "M3 7V5C3 3.89543 3.89543 3 5 3H7M17 3H19C20.1046 3 21 3.89543 21 5V7M21 17V19C21 20.1046 20.1046 21 19 21H17M7 21H5C3.89543 21 3 20.1046 3 19V17",
3267
- stroke: "currentColor",
3268
- strokeWidth: "1.5",
3269
- strokeLinecap: "round",
3270
- strokeLinejoin: "round"
3271
- }
3272
- )
3273
- ]
3274
- }
3275
- );
3276
- var PinIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3277
- "svg",
3278
- {
3279
- width: "28",
3280
- height: "28",
3281
- viewBox: "0 0 24 24",
3282
- fill: "none",
3283
- xmlns: "http://www.w3.org/2000/svg",
3284
- children: [
3285
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3286
- "rect",
3287
- {
3288
- x: "3",
3289
- y: "6",
3290
- width: "18",
3291
- height: "12",
3292
- rx: "2",
3293
- stroke: "currentColor",
3294
- strokeWidth: "1.5"
3295
- }
3296
- ),
3297
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "7", cy: "12", r: "1.5", fill: "currentColor" }),
3298
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "12", cy: "12", r: "1.5", fill: "currentColor" }),
3299
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "17", cy: "12", r: "1.5", fill: "currentColor" })
3300
- ]
3301
- }
3302
- );
3303
-
3304
- // src/signless/components/SignlessUnlockModal.tsx
3305
-
3306
-
3307
- var SignlessUnlockModal = ({
3308
- isOpen,
3309
- onClose,
3310
- onUnlock,
3311
- showBiometric = true
3312
- }) => {
3313
- const { unlock, state, isBiometricAvailable } = useSignless();
3314
- const [view, setView] = React14.useState("biometric");
3315
- const [error, setError] = React14.useState(null);
3316
- const [isLoading, setIsLoading] = React14.useState(false);
3317
- const shouldShowBiometric = showBiometric && isBiometricAvailable && state.authMethod === "biometric";
3318
- React14.useEffect(() => {
3319
- if (isOpen) {
3320
- setError(null);
3321
- setIsLoading(false);
3322
- setView(shouldShowBiometric ? "biometric" : "pin");
3323
- }
3324
- }, [isOpen, shouldShowBiometric]);
3325
- React14.useEffect(() => {
3326
- if (isOpen && view === "biometric" && shouldShowBiometric) {
3327
- handleBiometricAuth();
3328
- }
3329
- }, [isOpen, view]);
3330
- const handleBiometricAuth = async () => {
3331
- setIsLoading(true);
3332
- setError(null);
3333
- try {
3334
- await unlock({});
3335
- onUnlock();
3336
- onClose();
3337
- } catch (err) {
3338
- setError(
3339
- err instanceof Error ? err.message : "Biometric authentication failed"
3340
- );
3341
- setView("pin");
3342
- } finally {
3343
- setIsLoading(false);
3344
- }
3345
- };
3346
- const handlePinSubmit = async (pin) => {
3347
- setIsLoading(true);
3348
- setError(null);
3349
- try {
3350
- await unlock({ pin });
3351
- onUnlock();
3352
- onClose();
3353
- } catch (err) {
3354
- setError("Invalid PIN. Please try again.");
3355
- } finally {
3356
- setIsLoading(false);
3357
- }
3358
- };
3359
- const handleUsePinInstead = () => {
3360
- setView("pin");
3361
- setError(null);
3362
- };
3363
- if (!isOpen) return null;
3364
- const renderBiometricPrompt = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: unlockModalStyles.biometricPrompt, children: [
3365
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: unlockModalStyles.biometricIcon, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BiometricLargeIcon, {}) }),
3366
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { style: unlockModalStyles.biometricTitle, children: "Unlock Signless" }),
3367
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: unlockModalStyles.biometricSubtitle, children: isLoading ? "Authenticating..." : "Use Face ID or Touch ID to continue" }),
3368
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { color: "#FF5252", fontSize: "14px", marginBottom: "16px" }, children: error }),
3369
- !isLoading && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3370
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3371
- "button",
3372
- {
3373
- type: "button",
3374
- style: {
3375
- padding: "14px 32px",
3376
- fontSize: "16px",
3377
- fontWeight: 600,
3378
- color: "#ffffff",
3379
- backgroundColor: "#0098EA",
3380
- border: "none",
3381
- borderRadius: "12px",
3382
- cursor: "pointer",
3383
- marginBottom: "16px"
3384
- },
3385
- onClick: handleBiometricAuth,
3386
- children: "Try Again"
3387
- }
3388
- ),
3389
- state.authMethod === "biometric" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3390
- "button",
3391
- {
3392
- type: "button",
3393
- style: unlockModalStyles.usePinButton,
3394
- onClick: handleUsePinInstead,
3395
- children: "Use PIN instead"
3396
- }
3397
- )
3398
- ] })
3399
- ] });
3400
- const renderPinInput = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3401
- PinInput,
3402
- {
3403
- title: "Enter PIN",
3404
- subtitle: "Enter your PIN to unlock signless payments",
3405
- onComplete: handlePinSubmit,
3406
- onCancel: onClose,
3407
- error,
3408
- isLoading,
3409
- showBiometric: shouldShowBiometric,
3410
- onBiometricPress: () => {
3411
- setView("biometric");
3412
- setError(null);
3413
- }
3414
- }
3415
- );
3416
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: unlockModalStyles.container, children: view === "biometric" && shouldShowBiometric ? renderBiometricPrompt() : renderPinInput() });
3417
- };
3418
- var BiometricLargeIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3419
- "svg",
3420
- {
3421
- width: "48",
3422
- height: "48",
3423
- viewBox: "0 0 24 24",
3424
- fill: "none",
3425
- xmlns: "http://www.w3.org/2000/svg",
3426
- children: [
3427
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3428
- "path",
3429
- {
3430
- d: "M12 14.5V16.5M7 10.5C7 7.73858 9.23858 5.5 12 5.5C14.7614 5.5 17 7.73858 17 10.5V11.5M12 11.5C10.6193 11.5 9.5 12.6193 9.5 14C9.5 15.3807 10.6193 16.5 12 16.5C13.3807 16.5 14.5 15.3807 14.5 14C14.5 12.6193 13.3807 11.5 12 11.5Z",
3431
- stroke: "currentColor",
3432
- strokeWidth: "1.5",
3433
- strokeLinecap: "round",
3434
- strokeLinejoin: "round"
3435
- }
3436
- ),
3437
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3438
- "path",
3439
- {
3440
- d: "M3 7V5C3 3.89543 3.89543 3 5 3H7M17 3H19C20.1046 3 21 3.89543 21 5V7M21 17V19C21 20.1046 20.1046 21 19 21H17M7 21H5C3.89543 21 3 20.1046 3 19V17",
3441
- stroke: "currentColor",
3442
- strokeWidth: "1.5",
3443
- strokeLinecap: "round",
3444
- strokeLinejoin: "round"
3445
- }
3446
- )
3447
- ]
3448
- }
3449
- );
3450
-
3451
-
3452
-
3453
-
3454
-
3455
-
3456
-
3457
-
3458
-
3459
-
3460
-
3461
-
3462
-
3463
-
3464
-
3465
-
3466
-
3467
-
3468
1845
 
3469
1846
 
3470
1847
 
@@ -3473,5 +1850,5 @@ var BiometricLargeIcon = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3473
1850
 
3474
1851
 
3475
1852
 
3476
- exports.BottomSheet = BottomSheet_default; exports.ErrorTransactionNotification = ErrorTransactionNotification; exports.NotificationCard = NotificationCard; exports.NotificationRoot = NotificationRoot; exports.PaymentModal = PaymentModal; exports.PinInput = PinInput; exports.SignlessProvider = SignlessProvider; exports.SignlessSetupModal = SignlessSetupModal; exports.SignlessStorage = SignlessStorage; exports.SignlessUnlockModal = SignlessUnlockModal; exports.TonPayButton = TonPayButton; exports.createWebAuthnCredential = createWebAuthnCredential; exports.decryptPrivateKey = decryptPrivateKey; exports.encryptPrivateKey = encryptPrivateKey; exports.generateKeyPair = generateKeyPair; exports.getWebAuthnCredential = getWebAuthnCredential; exports.isWebAuthnSupported = isWebAuthnSupported; exports.signMessage = signMessage; exports.signlessStorage = signlessStorage; exports.useMoonPayIframe = useMoonPayIframe; exports.useSignless = useSignless; exports.useSignlessModal = useSignlessModal; exports.useTonPay = useTonPay; exports.useTonPaySignless = useTonPaySignless; exports.verifySignlessSignature = verifySignlessSignature;
1853
+ exports.BottomSheet = BottomSheet_default; exports.ErrorTransactionNotification = ErrorTransactionNotification; exports.NotificationCard = NotificationCard; exports.NotificationRoot = NotificationRoot; exports.PaymentModal = PaymentModal; exports.TonPayButton = TonPayButton; exports.useMoonPayIframe = useMoonPayIframe; exports.useTonPay = useTonPay;
3477
1854
  //# sourceMappingURL=index.js.map