@settlr/sdk 0.1.0 → 0.3.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
@@ -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
  });
@@ -62,8 +64,8 @@ var SETTLR_API_URL = {
62
64
  development: "http://localhost:3000/api"
63
65
  };
64
66
  var SETTLR_CHECKOUT_URL = {
65
- production: "https://settlr.dev/pay",
66
- development: "http://localhost:3000/pay"
67
+ production: "https://settlr.dev/checkout",
68
+ development: "http://localhost:3000/checkout"
67
69
  };
68
70
  var SUPPORTED_NETWORKS = ["devnet", "mainnet-beta"];
69
71
  var USDC_DECIMALS = 6;
@@ -188,6 +190,37 @@ var Settlr = class {
188
190
  getTier() {
189
191
  return this.tier;
190
192
  }
193
+ /**
194
+ * Get a checkout URL for redirect-based payments
195
+ *
196
+ * This is the simplest integration - just redirect users to this URL.
197
+ * Settlr handles auth (email or wallet) and payment processing.
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const url = settlr.getCheckoutUrl({
202
+ * amount: 29.99,
203
+ * memo: 'Premium Pack',
204
+ * });
205
+ *
206
+ * // Redirect user to checkout
207
+ * window.location.href = url;
208
+ * ```
209
+ */
210
+ getCheckoutUrl(options) {
211
+ const { amount, memo, orderId, successUrl, cancelUrl } = options;
212
+ const baseUrl = this.config.testMode ? SETTLR_CHECKOUT_URL.development : SETTLR_CHECKOUT_URL.production;
213
+ const params = new URLSearchParams({
214
+ amount: amount.toString(),
215
+ merchant: this.config.merchant.name,
216
+ to: this.config.merchant.walletAddress
217
+ });
218
+ if (memo) params.set("memo", memo);
219
+ if (orderId) params.set("orderId", orderId);
220
+ if (successUrl) params.set("successUrl", successUrl);
221
+ if (cancelUrl) params.set("cancelUrl", cancelUrl);
222
+ return `${baseUrl}?${params.toString()}`;
223
+ }
191
224
  /**
192
225
  * Create a payment link
193
226
  *
@@ -221,8 +254,8 @@ var Settlr = class {
221
254
  });
222
255
  if (memo) params.set("memo", memo);
223
256
  if (orderId) params.set("orderId", orderId);
224
- if (successUrl) params.set("successUrl", successUrl);
225
- if (cancelUrl) params.set("cancelUrl", cancelUrl);
257
+ if (successUrl) params.set("success", successUrl);
258
+ if (cancelUrl) params.set("cancel", cancelUrl);
226
259
  if (paymentId) params.set("paymentId", paymentId);
227
260
  const checkoutUrl = `${baseUrl}?${params.toString()}`;
228
261
  const qrCode = await this.generateQRCode(checkoutUrl);
@@ -466,49 +499,34 @@ var Settlr = class {
466
499
 
467
500
  // src/react.tsx
468
501
  var import_react = require("react");
469
- var import_wallet_adapter_react = require("@solana/wallet-adapter-react");
470
502
  var import_jsx_runtime = require("react/jsx-runtime");
471
503
  var SettlrContext = (0, import_react.createContext)(null);
472
- function SettlrProvider({ children, config }) {
473
- const { connection } = (0, import_wallet_adapter_react.useConnection)();
474
- const wallet = (0, import_wallet_adapter_react.useWallet)();
504
+ function SettlrProvider({
505
+ children,
506
+ config,
507
+ authenticated = false
508
+ }) {
475
509
  const settlr = (0, import_react.useMemo)(() => {
476
510
  return new Settlr({
477
511
  ...config,
478
- rpcEndpoint: connection.rpcEndpoint
512
+ rpcEndpoint: config.rpcEndpoint ?? "https://api.devnet.solana.com"
479
513
  });
480
- }, [config, connection.rpcEndpoint]);
514
+ }, [config]);
481
515
  const value = (0, import_react.useMemo)(
482
516
  () => ({
483
517
  settlr,
484
- connected: wallet.connected,
518
+ authenticated,
485
519
  createPayment: (options) => {
486
520
  return settlr.createPayment(options);
487
521
  },
488
- pay: async (options) => {
489
- if (!wallet.publicKey || !wallet.signTransaction) {
490
- return {
491
- success: false,
492
- signature: "",
493
- amount: options.amount,
494
- merchantAddress: settlr.getMerchantAddress().toBase58(),
495
- error: "Wallet not connected"
496
- };
497
- }
498
- return settlr.pay({
499
- wallet: {
500
- publicKey: wallet.publicKey,
501
- signTransaction: wallet.signTransaction
502
- },
503
- amount: options.amount,
504
- memo: options.memo
505
- });
522
+ getCheckoutUrl: (options) => {
523
+ return settlr.getCheckoutUrl(options);
506
524
  },
507
525
  getBalance: () => {
508
526
  return settlr.getMerchantBalance();
509
527
  }
510
528
  }),
511
- [settlr, wallet]
529
+ [settlr, authenticated]
512
530
  );
513
531
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettlrContext.Provider, { value, children });
514
532
  }
@@ -578,7 +596,8 @@ function BuyButton({
578
596
  onSuccess,
579
597
  onError,
580
598
  onProcessing,
581
- useRedirect = false,
599
+ useRedirect = true,
600
+ // Default to redirect flow (works with Privy)
582
601
  successUrl,
583
602
  cancelUrl,
584
603
  className,
@@ -587,7 +606,7 @@ function BuyButton({
587
606
  variant = "primary",
588
607
  size = "md"
589
608
  }) {
590
- const { pay, createPayment, connected } = useSettlr();
609
+ const { getCheckoutUrl, createPayment } = useSettlr();
591
610
  const [loading, setLoading] = (0, import_react2.useState)(false);
592
611
  const [status, setStatus] = (0, import_react2.useState)("idle");
593
612
  const handleClick = (0, import_react2.useCallback)(async () => {
@@ -596,32 +615,17 @@ function BuyButton({
596
615
  setStatus("processing");
597
616
  onProcessing?.();
598
617
  try {
599
- if (useRedirect) {
600
- const payment = await createPayment({
601
- amount,
602
- memo,
603
- orderId,
604
- successUrl,
605
- cancelUrl
606
- });
607
- window.location.href = payment.checkoutUrl;
608
- } else {
609
- const result = await pay({ amount, memo });
610
- if (result.success) {
611
- setStatus("success");
612
- onSuccess?.({
613
- signature: result.signature,
614
- amount: result.amount,
615
- merchantAddress: result.merchantAddress
616
- });
617
- } else {
618
- throw new Error(result.error || "Payment failed");
619
- }
620
- }
618
+ const url = getCheckoutUrl({
619
+ amount,
620
+ memo,
621
+ orderId,
622
+ successUrl,
623
+ cancelUrl
624
+ });
625
+ window.location.href = url;
621
626
  } catch (error) {
622
627
  setStatus("error");
623
628
  onError?.(error instanceof Error ? error : new Error("Payment failed"));
624
- } finally {
625
629
  setLoading(false);
626
630
  }
627
631
  }, [
@@ -630,12 +634,9 @@ function BuyButton({
630
634
  orderId,
631
635
  disabled,
632
636
  loading,
633
- useRedirect,
634
637
  successUrl,
635
638
  cancelUrl,
636
- pay,
637
- createPayment,
638
- onSuccess,
639
+ getCheckoutUrl,
639
640
  onError,
640
641
  onProcessing
641
642
  ]);
@@ -655,11 +656,11 @@ function BuyButton({
655
656
  "button",
656
657
  {
657
658
  onClick: handleClick,
658
- disabled: disabled || loading || !connected,
659
+ disabled: disabled || loading,
659
660
  className,
660
661
  style: buttonStyle,
661
662
  type: "button",
662
- children: !connected ? "Connect Wallet" : buttonContent
663
+ children: buttonContent
663
664
  }
664
665
  );
665
666
  }
@@ -783,7 +784,7 @@ function CheckoutWidget({
783
784
  theme = "dark",
784
785
  showBranding = true
785
786
  }) {
786
- const { connected } = useSettlr();
787
+ const { getCheckoutUrl } = useSettlr();
787
788
  const [status, setStatus] = (0, import_react2.useState)("idle");
788
789
  const containerStyle = {
789
790
  ...widgetStyles.container,
@@ -894,6 +895,193 @@ function usePaymentLink(config) {
894
895
  generateQRCode
895
896
  };
896
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
+ }
897
1085
 
898
1086
  // src/webhooks.ts
899
1087
  var import_crypto = __toESM(require("crypto"));
@@ -957,6 +1145,7 @@ function createWebhookHandler(options) {
957
1145
  0 && (module.exports = {
958
1146
  BuyButton,
959
1147
  CheckoutWidget,
1148
+ PaymentModal,
960
1149
  SETTLR_CHECKOUT_URL,
961
1150
  SUPPORTED_NETWORKS,
962
1151
  Settlr,
@@ -969,6 +1158,7 @@ function createWebhookHandler(options) {
969
1158
  parseWebhookPayload,
970
1159
  shortenAddress,
971
1160
  usePaymentLink,
1161
+ usePaymentModal,
972
1162
  useSettlr,
973
1163
  verifyWebhookSignature
974
1164
  });