@settlr/sdk 0.2.0 → 0.3.1

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/README.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # @settlr/sdk
2
2
 
3
- > Solana USDC payments for games - email checkout, no wallet required
3
+ [![npm version](https://img.shields.io/npm/v/@settlr/sdk.svg)](https://www.npmjs.com/package/@settlr/sdk)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@settlr/sdk.svg)](https://www.npmjs.com/package/@settlr/sdk)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ > **Settlr** - Accept Solana USDC payments in games and apps. Email checkout, gasless transactions, no wallet required.
8
+
9
+ 🌐 **Website:** [settlr.dev](https://settlr.dev)
10
+ 📖 **Docs:** [settlr.dev/docs](https://settlr.dev/docs)
11
+ 🎮 **Demo:** [settlr.dev/demo](https://settlr.dev/demo)
12
+
13
+ ## Why Settlr?
14
+
15
+ - ✅ **No wallet required** - Users pay with just an email
16
+ - ✅ **Gasless transactions** - No SOL needed for fees
17
+ - ✅ **USDC on Solana** - Fast, cheap, stable payments
18
+ - ✅ **Drop-in components** - React components ready to use
19
+ - ✅ **Gaming focused** - Built for in-game purchases
4
20
 
5
21
  ## Installation
6
22
 
package/dist/index.d.mts CHANGED
@@ -584,6 +584,111 @@ declare function usePaymentLink(config: {
584
584
  cancelUrl?: string;
585
585
  }) => string>[0]) => Promise<string>;
586
586
  };
587
+ /**
588
+ * Payment Modal - Iframe-based checkout that keeps users on your site
589
+ *
590
+ * @example
591
+ * ```tsx
592
+ * import { PaymentModal } from '@settlr/sdk';
593
+ *
594
+ * function ProductPage() {
595
+ * const [showPayment, setShowPayment] = useState(false);
596
+ *
597
+ * return (
598
+ * <>
599
+ * <button onClick={() => setShowPayment(true)}>
600
+ * Buy Now - $49.99
601
+ * </button>
602
+ *
603
+ * {showPayment && (
604
+ * <PaymentModal
605
+ * amount={49.99}
606
+ * merchantName="Arena GG"
607
+ * merchantWallet="YOUR_WALLET_ADDRESS"
608
+ * memo="Tournament Entry"
609
+ * onSuccess={(result) => {
610
+ * console.log('Paid!', result.signature);
611
+ * setShowPayment(false);
612
+ * }}
613
+ * onClose={() => setShowPayment(false)}
614
+ * />
615
+ * )}
616
+ * </>
617
+ * );
618
+ * }
619
+ * ```
620
+ */
621
+ interface PaymentModalProps {
622
+ /** Payment amount in USDC */
623
+ amount: number;
624
+ /** Merchant display name */
625
+ merchantName: string;
626
+ /** Merchant wallet address */
627
+ merchantWallet: string;
628
+ /** Optional memo/description */
629
+ memo?: string;
630
+ /** Optional order ID */
631
+ orderId?: string;
632
+ /** Called when payment succeeds */
633
+ onSuccess?: (result: {
634
+ signature: string;
635
+ amount: number;
636
+ }) => void;
637
+ /** Called when modal is closed */
638
+ onClose?: () => void;
639
+ /** Called on error */
640
+ onError?: (error: Error) => void;
641
+ /** Checkout base URL (default: https://settlr.dev/checkout) */
642
+ checkoutUrl?: string;
643
+ }
644
+ declare function PaymentModal({ amount, merchantName, merchantWallet, memo, orderId, onSuccess, onClose, onError, checkoutUrl, }: PaymentModalProps): react_jsx_runtime.JSX.Element;
645
+ /**
646
+ * Hook to open payment modal programmatically
647
+ *
648
+ * @example
649
+ * ```tsx
650
+ * import { usePaymentModal } from '@settlr/sdk';
651
+ *
652
+ * function ProductPage() {
653
+ * const { openPayment, PaymentModalComponent } = usePaymentModal({
654
+ * merchantName: "Arena GG",
655
+ * merchantWallet: "YOUR_WALLET",
656
+ * });
657
+ *
658
+ * return (
659
+ * <>
660
+ * <button onClick={() => openPayment({
661
+ * amount: 49.99,
662
+ * memo: "Tournament Entry",
663
+ * onSuccess: (result) => console.log("Paid!", result),
664
+ * })}>
665
+ * Buy Now
666
+ * </button>
667
+ * <PaymentModalComponent />
668
+ * </>
669
+ * );
670
+ * }
671
+ * ```
672
+ */
673
+ declare function usePaymentModal(config: {
674
+ merchantName: string;
675
+ merchantWallet: string;
676
+ checkoutUrl?: string;
677
+ }): {
678
+ openPayment: (options: {
679
+ amount: number;
680
+ memo?: string;
681
+ orderId?: string;
682
+ onSuccess?: (result: {
683
+ signature: string;
684
+ amount: number;
685
+ }) => void;
686
+ onError?: (error: Error) => void;
687
+ }) => void;
688
+ closePayment: () => void;
689
+ isOpen: boolean;
690
+ PaymentModalComponent: () => react_jsx_runtime.JSX.Element | null;
691
+ };
587
692
 
588
693
  /**
589
694
  * Verify a webhook signature
@@ -667,4 +772,4 @@ declare function createWebhookHandler(options: {
667
772
  onError?: (error: Error) => void;
668
773
  }): (req: any, res: any) => Promise<void>;
669
774
 
670
- export { BuyButton, type BuyButtonProps, CheckoutWidget, type CheckoutWidgetProps, type CreatePaymentOptions, type MerchantConfig, type Payment, type PaymentResult, type PaymentStatus, SETTLR_CHECKOUT_URL, SUPPORTED_NETWORKS, Settlr, type SettlrConfig, SettlrProvider, type TransactionOptions, USDC_MINT_DEVNET, USDC_MINT_MAINNET, type WebhookEventType, type WebhookHandler, type WebhookHandlers, type WebhookPayload, createWebhookHandler, formatUSDC, parseUSDC, parseWebhookPayload, shortenAddress, usePaymentLink, useSettlr, verifyWebhookSignature };
775
+ export { BuyButton, type BuyButtonProps, CheckoutWidget, type CheckoutWidgetProps, type CreatePaymentOptions, type MerchantConfig, type Payment, PaymentModal, type PaymentModalProps, type PaymentResult, type PaymentStatus, SETTLR_CHECKOUT_URL, SUPPORTED_NETWORKS, Settlr, type SettlrConfig, SettlrProvider, type TransactionOptions, USDC_MINT_DEVNET, USDC_MINT_MAINNET, type WebhookEventType, type WebhookHandler, type WebhookHandlers, type WebhookPayload, createWebhookHandler, formatUSDC, parseUSDC, parseWebhookPayload, shortenAddress, usePaymentLink, usePaymentModal, useSettlr, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -584,6 +584,111 @@ declare function usePaymentLink(config: {
584
584
  cancelUrl?: string;
585
585
  }) => string>[0]) => Promise<string>;
586
586
  };
587
+ /**
588
+ * Payment Modal - Iframe-based checkout that keeps users on your site
589
+ *
590
+ * @example
591
+ * ```tsx
592
+ * import { PaymentModal } from '@settlr/sdk';
593
+ *
594
+ * function ProductPage() {
595
+ * const [showPayment, setShowPayment] = useState(false);
596
+ *
597
+ * return (
598
+ * <>
599
+ * <button onClick={() => setShowPayment(true)}>
600
+ * Buy Now - $49.99
601
+ * </button>
602
+ *
603
+ * {showPayment && (
604
+ * <PaymentModal
605
+ * amount={49.99}
606
+ * merchantName="Arena GG"
607
+ * merchantWallet="YOUR_WALLET_ADDRESS"
608
+ * memo="Tournament Entry"
609
+ * onSuccess={(result) => {
610
+ * console.log('Paid!', result.signature);
611
+ * setShowPayment(false);
612
+ * }}
613
+ * onClose={() => setShowPayment(false)}
614
+ * />
615
+ * )}
616
+ * </>
617
+ * );
618
+ * }
619
+ * ```
620
+ */
621
+ interface PaymentModalProps {
622
+ /** Payment amount in USDC */
623
+ amount: number;
624
+ /** Merchant display name */
625
+ merchantName: string;
626
+ /** Merchant wallet address */
627
+ merchantWallet: string;
628
+ /** Optional memo/description */
629
+ memo?: string;
630
+ /** Optional order ID */
631
+ orderId?: string;
632
+ /** Called when payment succeeds */
633
+ onSuccess?: (result: {
634
+ signature: string;
635
+ amount: number;
636
+ }) => void;
637
+ /** Called when modal is closed */
638
+ onClose?: () => void;
639
+ /** Called on error */
640
+ onError?: (error: Error) => void;
641
+ /** Checkout base URL (default: https://settlr.dev/checkout) */
642
+ checkoutUrl?: string;
643
+ }
644
+ declare function PaymentModal({ amount, merchantName, merchantWallet, memo, orderId, onSuccess, onClose, onError, checkoutUrl, }: PaymentModalProps): react_jsx_runtime.JSX.Element;
645
+ /**
646
+ * Hook to open payment modal programmatically
647
+ *
648
+ * @example
649
+ * ```tsx
650
+ * import { usePaymentModal } from '@settlr/sdk';
651
+ *
652
+ * function ProductPage() {
653
+ * const { openPayment, PaymentModalComponent } = usePaymentModal({
654
+ * merchantName: "Arena GG",
655
+ * merchantWallet: "YOUR_WALLET",
656
+ * });
657
+ *
658
+ * return (
659
+ * <>
660
+ * <button onClick={() => openPayment({
661
+ * amount: 49.99,
662
+ * memo: "Tournament Entry",
663
+ * onSuccess: (result) => console.log("Paid!", result),
664
+ * })}>
665
+ * Buy Now
666
+ * </button>
667
+ * <PaymentModalComponent />
668
+ * </>
669
+ * );
670
+ * }
671
+ * ```
672
+ */
673
+ declare function usePaymentModal(config: {
674
+ merchantName: string;
675
+ merchantWallet: string;
676
+ checkoutUrl?: string;
677
+ }): {
678
+ openPayment: (options: {
679
+ amount: number;
680
+ memo?: string;
681
+ orderId?: string;
682
+ onSuccess?: (result: {
683
+ signature: string;
684
+ amount: number;
685
+ }) => void;
686
+ onError?: (error: Error) => void;
687
+ }) => void;
688
+ closePayment: () => void;
689
+ isOpen: boolean;
690
+ PaymentModalComponent: () => react_jsx_runtime.JSX.Element | null;
691
+ };
587
692
 
588
693
  /**
589
694
  * Verify a webhook signature
@@ -667,4 +772,4 @@ declare function createWebhookHandler(options: {
667
772
  onError?: (error: Error) => void;
668
773
  }): (req: any, res: any) => Promise<void>;
669
774
 
670
- export { BuyButton, type BuyButtonProps, CheckoutWidget, type CheckoutWidgetProps, type CreatePaymentOptions, type MerchantConfig, type Payment, type PaymentResult, type PaymentStatus, SETTLR_CHECKOUT_URL, SUPPORTED_NETWORKS, Settlr, type SettlrConfig, SettlrProvider, type TransactionOptions, USDC_MINT_DEVNET, USDC_MINT_MAINNET, type WebhookEventType, type WebhookHandler, type WebhookHandlers, type WebhookPayload, createWebhookHandler, formatUSDC, parseUSDC, parseWebhookPayload, shortenAddress, usePaymentLink, useSettlr, verifyWebhookSignature };
775
+ export { BuyButton, type BuyButtonProps, CheckoutWidget, type CheckoutWidgetProps, type CreatePaymentOptions, type MerchantConfig, type Payment, PaymentModal, type PaymentModalProps, type PaymentResult, type PaymentStatus, SETTLR_CHECKOUT_URL, SUPPORTED_NETWORKS, Settlr, type SettlrConfig, SettlrProvider, type TransactionOptions, USDC_MINT_DEVNET, USDC_MINT_MAINNET, type WebhookEventType, type WebhookHandler, type WebhookHandlers, type WebhookPayload, createWebhookHandler, formatUSDC, parseUSDC, parseWebhookPayload, shortenAddress, usePaymentLink, usePaymentModal, useSettlr, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BuyButton: () => BuyButton,
34
34
  CheckoutWidget: () => CheckoutWidget,
35
+ PaymentModal: () => PaymentModal,
35
36
  SETTLR_CHECKOUT_URL: () => SETTLR_CHECKOUT_URL,
36
37
  SUPPORTED_NETWORKS: () => SUPPORTED_NETWORKS,
37
38
  Settlr: () => Settlr,
@@ -44,6 +45,7 @@ __export(index_exports, {
44
45
  parseWebhookPayload: () => parseWebhookPayload,
45
46
  shortenAddress: () => shortenAddress,
46
47
  usePaymentLink: () => usePaymentLink,
48
+ usePaymentModal: () => usePaymentModal,
47
49
  useSettlr: () => useSettlr,
48
50
  verifyWebhookSignature: () => verifyWebhookSignature
49
51
  });
@@ -893,6 +895,193 @@ function usePaymentLink(config) {
893
895
  generateQRCode
894
896
  };
895
897
  }
898
+ var modalStyles = {
899
+ overlay: {
900
+ position: "fixed",
901
+ top: 0,
902
+ left: 0,
903
+ right: 0,
904
+ bottom: 0,
905
+ backgroundColor: "rgba(0, 0, 0, 0.8)",
906
+ backdropFilter: "blur(4px)",
907
+ display: "flex",
908
+ alignItems: "center",
909
+ justifyContent: "center",
910
+ zIndex: 9999,
911
+ padding: "16px"
912
+ },
913
+ container: {
914
+ position: "relative",
915
+ width: "100%",
916
+ maxWidth: "480px",
917
+ height: "90vh",
918
+ maxHeight: "700px",
919
+ backgroundColor: "#12121a",
920
+ borderRadius: "16px",
921
+ overflow: "hidden",
922
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)"
923
+ },
924
+ closeButton: {
925
+ position: "absolute",
926
+ top: "12px",
927
+ right: "12px",
928
+ width: "32px",
929
+ height: "32px",
930
+ borderRadius: "50%",
931
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
932
+ border: "none",
933
+ cursor: "pointer",
934
+ display: "flex",
935
+ alignItems: "center",
936
+ justifyContent: "center",
937
+ zIndex: 10,
938
+ color: "white",
939
+ fontSize: "18px",
940
+ transition: "background-color 0.2s"
941
+ },
942
+ iframe: {
943
+ width: "100%",
944
+ height: "100%",
945
+ border: "none"
946
+ },
947
+ loading: {
948
+ position: "absolute",
949
+ top: "50%",
950
+ left: "50%",
951
+ transform: "translate(-50%, -50%)",
952
+ color: "white",
953
+ fontSize: "14px",
954
+ display: "flex",
955
+ flexDirection: "column",
956
+ alignItems: "center",
957
+ gap: "12px"
958
+ }
959
+ };
960
+ function PaymentModal({
961
+ amount,
962
+ merchantName,
963
+ merchantWallet,
964
+ memo,
965
+ orderId,
966
+ onSuccess,
967
+ onClose,
968
+ onError,
969
+ checkoutUrl = "https://settlr.dev/checkout"
970
+ }) {
971
+ const [loading, setLoading] = (0, import_react2.useState)(true);
972
+ const params = new URLSearchParams({
973
+ amount: amount.toString(),
974
+ merchant: merchantName,
975
+ to: merchantWallet,
976
+ embed: "true"
977
+ });
978
+ if (memo) params.set("memo", memo);
979
+ if (orderId) params.set("orderId", orderId);
980
+ const iframeSrc = `${checkoutUrl}?${params.toString()}`;
981
+ (0, import_react2.useEffect)(() => {
982
+ const handleMessage = (event) => {
983
+ if (!event.origin.includes("settlr.dev") && !event.origin.includes("localhost")) {
984
+ return;
985
+ }
986
+ const { type, data } = event.data || {};
987
+ switch (type) {
988
+ case "settlr:success":
989
+ onSuccess?.({
990
+ signature: data.signature,
991
+ amount: data.amount || amount
992
+ });
993
+ break;
994
+ case "settlr:error":
995
+ onError?.(new Error(data.message || "Payment failed"));
996
+ break;
997
+ case "settlr:close":
998
+ onClose?.();
999
+ break;
1000
+ }
1001
+ };
1002
+ window.addEventListener("message", handleMessage);
1003
+ return () => window.removeEventListener("message", handleMessage);
1004
+ }, [amount, onSuccess, onError, onClose]);
1005
+ (0, import_react2.useEffect)(() => {
1006
+ const handleEscape = (e) => {
1007
+ if (e.key === "Escape") onClose?.();
1008
+ };
1009
+ window.addEventListener("keydown", handleEscape);
1010
+ return () => window.removeEventListener("keydown", handleEscape);
1011
+ }, [onClose]);
1012
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: modalStyles.overlay, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: modalStyles.container, onClick: (e) => e.stopPropagation(), children: [
1013
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1014
+ "button",
1015
+ {
1016
+ style: modalStyles.closeButton,
1017
+ onClick: onClose,
1018
+ onMouseOver: (e) => e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)",
1019
+ onMouseOut: (e) => e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.1)",
1020
+ children: "\u2715"
1021
+ }
1022
+ ),
1023
+ loading && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: modalStyles.loading, children: [
1024
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Spinner, {}),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Loading checkout..." })
1026
+ ] }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1028
+ "iframe",
1029
+ {
1030
+ src: iframeSrc,
1031
+ style: {
1032
+ ...modalStyles.iframe,
1033
+ opacity: loading ? 0 : 1
1034
+ },
1035
+ onLoad: () => setLoading(false),
1036
+ allow: "payment"
1037
+ }
1038
+ )
1039
+ ] }) });
1040
+ }
1041
+ function usePaymentModal(config) {
1042
+ const [modalState, setModalState] = (0, import_react2.useState)({
1043
+ isOpen: false,
1044
+ amount: 0
1045
+ });
1046
+ const openPayment = (0, import_react2.useCallback)(
1047
+ (options) => {
1048
+ setModalState({
1049
+ isOpen: true,
1050
+ ...options
1051
+ });
1052
+ },
1053
+ []
1054
+ );
1055
+ const closePayment = (0, import_react2.useCallback)(() => {
1056
+ setModalState((prev) => ({ ...prev, isOpen: false }));
1057
+ }, []);
1058
+ const PaymentModalComponent = (0, import_react2.useCallback)(() => {
1059
+ if (!modalState.isOpen) return null;
1060
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1061
+ PaymentModal,
1062
+ {
1063
+ amount: modalState.amount,
1064
+ merchantName: config.merchantName,
1065
+ merchantWallet: config.merchantWallet,
1066
+ memo: modalState.memo,
1067
+ orderId: modalState.orderId,
1068
+ checkoutUrl: config.checkoutUrl,
1069
+ onSuccess: (result) => {
1070
+ modalState.onSuccess?.(result);
1071
+ closePayment();
1072
+ },
1073
+ onError: modalState.onError,
1074
+ onClose: closePayment
1075
+ }
1076
+ );
1077
+ }, [modalState, config, closePayment]);
1078
+ return {
1079
+ openPayment,
1080
+ closePayment,
1081
+ isOpen: modalState.isOpen,
1082
+ PaymentModalComponent
1083
+ };
1084
+ }
896
1085
 
897
1086
  // src/webhooks.ts
898
1087
  var import_crypto = __toESM(require("crypto"));
@@ -956,6 +1145,7 @@ function createWebhookHandler(options) {
956
1145
  0 && (module.exports = {
957
1146
  BuyButton,
958
1147
  CheckoutWidget,
1148
+ PaymentModal,
959
1149
  SETTLR_CHECKOUT_URL,
960
1150
  SUPPORTED_NETWORKS,
961
1151
  Settlr,
@@ -968,6 +1158,7 @@ function createWebhookHandler(options) {
968
1158
  parseWebhookPayload,
969
1159
  shortenAddress,
970
1160
  usePaymentLink,
1161
+ usePaymentModal,
971
1162
  useSettlr,
972
1163
  verifyWebhookSignature
973
1164
  });
package/dist/index.mjs CHANGED
@@ -499,7 +499,8 @@ function useSettlr() {
499
499
  // src/components.tsx
500
500
  import {
501
501
  useState,
502
- useCallback
502
+ useCallback,
503
+ useEffect
503
504
  } from "react";
504
505
  import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
505
506
  var defaultStyles = {
@@ -856,6 +857,193 @@ function usePaymentLink(config) {
856
857
  generateQRCode
857
858
  };
858
859
  }
860
+ var modalStyles = {
861
+ overlay: {
862
+ position: "fixed",
863
+ top: 0,
864
+ left: 0,
865
+ right: 0,
866
+ bottom: 0,
867
+ backgroundColor: "rgba(0, 0, 0, 0.8)",
868
+ backdropFilter: "blur(4px)",
869
+ display: "flex",
870
+ alignItems: "center",
871
+ justifyContent: "center",
872
+ zIndex: 9999,
873
+ padding: "16px"
874
+ },
875
+ container: {
876
+ position: "relative",
877
+ width: "100%",
878
+ maxWidth: "480px",
879
+ height: "90vh",
880
+ maxHeight: "700px",
881
+ backgroundColor: "#12121a",
882
+ borderRadius: "16px",
883
+ overflow: "hidden",
884
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)"
885
+ },
886
+ closeButton: {
887
+ position: "absolute",
888
+ top: "12px",
889
+ right: "12px",
890
+ width: "32px",
891
+ height: "32px",
892
+ borderRadius: "50%",
893
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
894
+ border: "none",
895
+ cursor: "pointer",
896
+ display: "flex",
897
+ alignItems: "center",
898
+ justifyContent: "center",
899
+ zIndex: 10,
900
+ color: "white",
901
+ fontSize: "18px",
902
+ transition: "background-color 0.2s"
903
+ },
904
+ iframe: {
905
+ width: "100%",
906
+ height: "100%",
907
+ border: "none"
908
+ },
909
+ loading: {
910
+ position: "absolute",
911
+ top: "50%",
912
+ left: "50%",
913
+ transform: "translate(-50%, -50%)",
914
+ color: "white",
915
+ fontSize: "14px",
916
+ display: "flex",
917
+ flexDirection: "column",
918
+ alignItems: "center",
919
+ gap: "12px"
920
+ }
921
+ };
922
+ function PaymentModal({
923
+ amount,
924
+ merchantName,
925
+ merchantWallet,
926
+ memo,
927
+ orderId,
928
+ onSuccess,
929
+ onClose,
930
+ onError,
931
+ checkoutUrl = "https://settlr.dev/checkout"
932
+ }) {
933
+ const [loading, setLoading] = useState(true);
934
+ const params = new URLSearchParams({
935
+ amount: amount.toString(),
936
+ merchant: merchantName,
937
+ to: merchantWallet,
938
+ embed: "true"
939
+ });
940
+ if (memo) params.set("memo", memo);
941
+ if (orderId) params.set("orderId", orderId);
942
+ const iframeSrc = `${checkoutUrl}?${params.toString()}`;
943
+ useEffect(() => {
944
+ const handleMessage = (event) => {
945
+ if (!event.origin.includes("settlr.dev") && !event.origin.includes("localhost")) {
946
+ return;
947
+ }
948
+ const { type, data } = event.data || {};
949
+ switch (type) {
950
+ case "settlr:success":
951
+ onSuccess?.({
952
+ signature: data.signature,
953
+ amount: data.amount || amount
954
+ });
955
+ break;
956
+ case "settlr:error":
957
+ onError?.(new Error(data.message || "Payment failed"));
958
+ break;
959
+ case "settlr:close":
960
+ onClose?.();
961
+ break;
962
+ }
963
+ };
964
+ window.addEventListener("message", handleMessage);
965
+ return () => window.removeEventListener("message", handleMessage);
966
+ }, [amount, onSuccess, onError, onClose]);
967
+ useEffect(() => {
968
+ const handleEscape = (e) => {
969
+ if (e.key === "Escape") onClose?.();
970
+ };
971
+ window.addEventListener("keydown", handleEscape);
972
+ return () => window.removeEventListener("keydown", handleEscape);
973
+ }, [onClose]);
974
+ return /* @__PURE__ */ jsx2("div", { style: modalStyles.overlay, onClick: onClose, children: /* @__PURE__ */ jsxs("div", { style: modalStyles.container, onClick: (e) => e.stopPropagation(), children: [
975
+ /* @__PURE__ */ jsx2(
976
+ "button",
977
+ {
978
+ style: modalStyles.closeButton,
979
+ onClick: onClose,
980
+ onMouseOver: (e) => e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)",
981
+ onMouseOut: (e) => e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.1)",
982
+ children: "\u2715"
983
+ }
984
+ ),
985
+ loading && /* @__PURE__ */ jsxs("div", { style: modalStyles.loading, children: [
986
+ /* @__PURE__ */ jsx2(Spinner, {}),
987
+ /* @__PURE__ */ jsx2("span", { children: "Loading checkout..." })
988
+ ] }),
989
+ /* @__PURE__ */ jsx2(
990
+ "iframe",
991
+ {
992
+ src: iframeSrc,
993
+ style: {
994
+ ...modalStyles.iframe,
995
+ opacity: loading ? 0 : 1
996
+ },
997
+ onLoad: () => setLoading(false),
998
+ allow: "payment"
999
+ }
1000
+ )
1001
+ ] }) });
1002
+ }
1003
+ function usePaymentModal(config) {
1004
+ const [modalState, setModalState] = useState({
1005
+ isOpen: false,
1006
+ amount: 0
1007
+ });
1008
+ const openPayment = useCallback(
1009
+ (options) => {
1010
+ setModalState({
1011
+ isOpen: true,
1012
+ ...options
1013
+ });
1014
+ },
1015
+ []
1016
+ );
1017
+ const closePayment = useCallback(() => {
1018
+ setModalState((prev) => ({ ...prev, isOpen: false }));
1019
+ }, []);
1020
+ const PaymentModalComponent = useCallback(() => {
1021
+ if (!modalState.isOpen) return null;
1022
+ return /* @__PURE__ */ jsx2(
1023
+ PaymentModal,
1024
+ {
1025
+ amount: modalState.amount,
1026
+ merchantName: config.merchantName,
1027
+ merchantWallet: config.merchantWallet,
1028
+ memo: modalState.memo,
1029
+ orderId: modalState.orderId,
1030
+ checkoutUrl: config.checkoutUrl,
1031
+ onSuccess: (result) => {
1032
+ modalState.onSuccess?.(result);
1033
+ closePayment();
1034
+ },
1035
+ onError: modalState.onError,
1036
+ onClose: closePayment
1037
+ }
1038
+ );
1039
+ }, [modalState, config, closePayment]);
1040
+ return {
1041
+ openPayment,
1042
+ closePayment,
1043
+ isOpen: modalState.isOpen,
1044
+ PaymentModalComponent
1045
+ };
1046
+ }
859
1047
 
860
1048
  // src/webhooks.ts
861
1049
  import crypto from "crypto";
@@ -918,6 +1106,7 @@ function createWebhookHandler(options) {
918
1106
  export {
919
1107
  BuyButton,
920
1108
  CheckoutWidget,
1109
+ PaymentModal,
921
1110
  SETTLR_CHECKOUT_URL,
922
1111
  SUPPORTED_NETWORKS,
923
1112
  Settlr,
@@ -930,6 +1119,7 @@ export {
930
1119
  parseWebhookPayload,
931
1120
  shortenAddress,
932
1121
  usePaymentLink,
1122
+ usePaymentModal,
933
1123
  useSettlr,
934
1124
  verifyWebhookSignature
935
1125
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@settlr/sdk",
3
- "version": "0.2.0",
4
- "description": "Solana USDC payments for games - email checkout, no wallet required",
3
+ "version": "0.3.1",
4
+ "description": "Settlr SDK - Accept Solana USDC payments in games and apps. Email checkout, gasless transactions, no wallet required. The easiest way to add crypto payments.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -24,21 +24,45 @@
24
24
  "prepublishOnly": "npm run build"
25
25
  },
26
26
  "keywords": [
27
+ "settlr",
28
+ "settlr-sdk",
29
+ "settlr.dev",
27
30
  "solana",
28
- "payments",
31
+ "solana-payments",
29
32
  "usdc",
30
- "crypto",
33
+ "usdc-payments",
34
+ "crypto-payments",
31
35
  "web3",
36
+ "web3-payments",
32
37
  "stablecoin",
33
- "gasless"
38
+ "gasless",
39
+ "gasless-transactions",
40
+ "payment-gateway",
41
+ "checkout",
42
+ "gaming-payments",
43
+ "game-monetization",
44
+ "in-app-purchases",
45
+ "react",
46
+ "typescript",
47
+ "email-checkout",
48
+ "no-wallet",
49
+ "privy"
34
50
  ],
35
- "author": "Settlr",
51
+ "author": "Settlr <hello@settlr.dev> (https://settlr.dev)",
36
52
  "license": "MIT",
37
53
  "repository": {
38
54
  "type": "git",
39
- "url": "git+https://github.com/ABFX15/x402-hack-payment.git"
55
+ "url": "git+https://github.com/ABFX15/x402-hack-payment.git",
56
+ "directory": "packages/sdk"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/ABFX15/x402-hack-payment/issues"
40
60
  },
41
61
  "homepage": "https://settlr.dev",
62
+ "funding": {
63
+ "type": "github",
64
+ "url": "https://github.com/sponsors/ABFX15"
65
+ },
42
66
  "dependencies": {
43
67
  "@solana/spl-token": "^0.4.13",
44
68
  "@solana/web3.js": "^1.98.0"