@moneymq/react 0.9.2 → 0.10.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.d.cts CHANGED
@@ -40,7 +40,7 @@ declare const MoneyMQContext: React.Context<MoneyMQClient | null>;
40
40
  declare const SandboxContext: React.Context<SandboxContextState>;
41
41
  declare function useMoneyMQ(): MoneyMQClient;
42
42
  declare function useSandbox(): SandboxContextState;
43
- declare function MoneyMQProvider({ children, client, branding, }: MoneyMQProviderProps): react_jsx_runtime.JSX.Element;
43
+ declare function MoneyMQProvider({ children, client, branding }: MoneyMQProviderProps): react_jsx_runtime.JSX.Element;
44
44
 
45
45
  /**
46
46
  * Represents a completed payment transaction.
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ declare const MoneyMQContext: React.Context<MoneyMQClient | null>;
40
40
  declare const SandboxContext: React.Context<SandboxContextState>;
41
41
  declare function useMoneyMQ(): MoneyMQClient;
42
42
  declare function useSandbox(): SandboxContextState;
43
- declare function MoneyMQProvider({ children, client, branding, }: MoneyMQProviderProps): react_jsx_runtime.JSX.Element;
43
+ declare function MoneyMQProvider({ children, client, branding }: MoneyMQProviderProps): react_jsx_runtime.JSX.Element;
44
44
 
45
45
  /**
46
46
  * Represents a completed payment transaction.
package/dist/index.js CHANGED
@@ -46734,46 +46734,31 @@ var SandboxContext = createContext2({
46734
46734
  sandboxAccounts: []
46735
46735
  });
46736
46736
  var DEFAULT_RPC_URL = "https://api.devnet.solana.com";
46737
- var SANDBOX_HASH_PREFIX = "SURFNETxSAFEHASH";
46738
46737
  function normalizeRpcUrl(url2) {
46739
46738
  return url2.replace("0.0.0.0", "localhost").replace("127.0.0.1", "localhost");
46740
46739
  }
46741
- async function getRpcUrl(apiUrl) {
46740
+ async function getFacilitatorConfig(apiUrl) {
46742
46741
  try {
46743
- console.log("[MoneyMQ] Fetching config from:", `${apiUrl}/config`);
46744
- const response = await fetch(`${apiUrl}/config`);
46742
+ const configUrl = `${apiUrl}/payment/v1/config?attrs=studio`;
46743
+ console.log("[MoneyMQ] Fetching facilitator config from:", configUrl);
46744
+ const response = await fetch(configUrl);
46745
+ if (!response.ok) {
46746
+ throw new Error(`Failed to fetch config: ${response.status}`);
46747
+ }
46745
46748
  const config2 = await response.json();
46746
- const rawRpcUrl = config2.x402?.validator?.rpcUrl || DEFAULT_RPC_URL;
46747
- console.log("[MoneyMQ] Raw RPC URL from config:", rawRpcUrl);
46749
+ const rawRpcUrl = config2.studio?.rpcUrl || DEFAULT_RPC_URL;
46748
46750
  const normalizedUrl = normalizeRpcUrl(rawRpcUrl);
46749
- console.log("[MoneyMQ] Normalized RPC URL:", normalizedUrl);
46750
- return normalizedUrl;
46751
- } catch (err2) {
46752
- console.error("[MoneyMQ] Error fetching config:", err2);
46753
- return DEFAULT_RPC_URL;
46754
- }
46755
- }
46756
- async function checkSandboxMode(rpcUrl) {
46757
- try {
46758
- console.log("[MoneyMQ] Checking sandbox mode with RPC:", rpcUrl);
46759
- const response = await fetch(rpcUrl, {
46760
- method: "POST",
46761
- headers: { "Content-Type": "application/json" },
46762
- body: JSON.stringify({
46763
- jsonrpc: "2.0",
46764
- id: 1,
46765
- method: "getLatestBlockhash",
46766
- params: [{ commitment: "finalized" }]
46767
- })
46768
- });
46769
- const data = await response.json();
46770
- const blockhash = data?.result?.value?.blockhash || "";
46771
- const isSandbox = blockhash.startsWith(SANDBOX_HASH_PREFIX);
46772
- console.log("[MoneyMQ] Blockhash:", blockhash, "| Sandbox:", isSandbox);
46773
- return isSandbox;
46751
+ console.log("[MoneyMQ] Facilitator config:", { isSandbox: config2.isSandbox, rpcUrl: normalizedUrl });
46752
+ return {
46753
+ isSandbox: config2.isSandbox,
46754
+ rpcUrl: normalizedUrl
46755
+ };
46774
46756
  } catch (err2) {
46775
- console.error("[MoneyMQ] Error checking sandbox mode:", err2);
46776
- return false;
46757
+ console.error("[MoneyMQ] Error fetching facilitator config:", err2);
46758
+ return {
46759
+ isSandbox: false,
46760
+ rpcUrl: DEFAULT_RPC_URL
46761
+ };
46777
46762
  }
46778
46763
  }
46779
46764
  async function fetchTokenBalance(rpcUrl, tokenAccountAddress) {
@@ -46799,8 +46784,8 @@ async function fetchTokenBalance(rpcUrl, tokenAccountAddress) {
46799
46784
  }
46800
46785
  async function fetchSandboxAccounts(apiUrl, rpcUrl) {
46801
46786
  try {
46802
- console.log("[MoneyMQ] Fetching sandbox accounts from:", `${apiUrl}/sandbox/accounts`);
46803
- const response = await fetch(`${apiUrl}/sandbox/accounts`);
46787
+ console.log("[MoneyMQ] Fetching sandbox accounts from:", `${apiUrl}/payment/v1/accounts`);
46788
+ const response = await fetch(`${apiUrl}/payment/v1/accounts`);
46804
46789
  if (!response.ok) {
46805
46790
  console.log("[MoneyMQ] Sandbox accounts fetch failed:", response.status);
46806
46791
  return [];
@@ -46842,19 +46827,14 @@ function useMoneyMQ() {
46842
46827
  function useSandbox() {
46843
46828
  return useContext2(SandboxContext);
46844
46829
  }
46845
- function MoneyMQProvider({
46846
- children,
46847
- client,
46848
- branding
46849
- }) {
46830
+ function MoneyMQProvider({ children, client, branding }) {
46850
46831
  const [rpcEndpoint, setRpcEndpoint] = useState3(null);
46851
46832
  const [isSandboxMode, setIsSandboxMode] = useState3(false);
46852
46833
  const [sandboxAccounts, setSandboxAccounts] = useState3([]);
46853
46834
  useEffect2(() => {
46854
46835
  async function initialize() {
46855
- const rpcUrl = await getRpcUrl(client.config.endpoint);
46836
+ const { isSandbox, rpcUrl } = await getFacilitatorConfig(client.config.endpoint);
46856
46837
  setRpcEndpoint(rpcUrl);
46857
- const isSandbox = await checkSandboxMode(rpcUrl);
46858
46838
  setIsSandboxMode(isSandbox);
46859
46839
  if (isSandbox) {
46860
46840
  const accounts = await fetchSandboxAccounts(client.config.endpoint, rpcUrl);
@@ -49371,9 +49351,9 @@ var logo_animation_default = { assets: [{ id: "4", layers: [{ ind: 3, ty: 4, ks:
49371
49351
  // src/checkout-modal.tsx
49372
49352
  import {
49373
49353
  EventStream,
49374
- EventReader,
49375
49354
  CheckoutReceipt,
49376
- isPaymentSettlementSucceeded
49355
+ isPaymentSettlementSucceeded,
49356
+ isTransactionCompleted
49377
49357
  } from "@moneymq/sdk";
49378
49358
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
49379
49359
  function encodeFormData(data) {
@@ -49541,31 +49521,38 @@ function waitForSettlementEvent(apiUrl, paymentIntentId, timeoutMs = 3e4) {
49541
49521
  stream.connect();
49542
49522
  });
49543
49523
  }
49544
- function waitForChannelEvent(apiUrl, channelId, eventType, timeoutMs = 3e4) {
49524
+ function waitForTransactionCompleted(apiUrl, transactionId, timeoutMs = 3e4) {
49545
49525
  return new Promise((resolve, reject) => {
49546
- console.log("[MoneyMQ] Waiting for channel event:", eventType, "on channel:", channelId);
49547
- const reader = new EventReader(apiUrl, channelId, { replay: 10 });
49526
+ console.log("[MoneyMQ] Waiting for transaction:completed event for tx:", transactionId);
49527
+ const stream = new EventStream(apiUrl, { last: 5 });
49548
49528
  let resolved = false;
49549
49529
  const cleanup = () => {
49550
49530
  if (!resolved) {
49551
- reader.disconnect();
49531
+ stream.disconnect();
49552
49532
  }
49553
49533
  };
49554
49534
  const timeout = setTimeout(() => {
49555
49535
  cleanup();
49556
- reject(new Error(`Channel event timeout waiting for ${eventType}`));
49536
+ reject(new Error("Transaction completed event timeout"));
49557
49537
  }, timeoutMs);
49558
- reader.on(eventType, (event) => {
49559
- console.log("[MoneyMQ] Channel event received:", eventType);
49560
- resolved = true;
49561
- clearTimeout(timeout);
49562
- reader.disconnect();
49563
- resolve(event);
49538
+ stream.on("payment", (event) => {
49539
+ console.log("[MoneyMQ] Received event while waiting for transaction:completed:", event.type);
49540
+ if (isTransactionCompleted(event)) {
49541
+ if (event.data.transaction_id === transactionId) {
49542
+ console.log("[MoneyMQ] Transaction completed event received for tx:", transactionId);
49543
+ resolved = true;
49544
+ clearTimeout(timeout);
49545
+ stream.disconnect();
49546
+ resolve(event);
49547
+ } else {
49548
+ console.log("[MoneyMQ] Transaction completed event for different tx:", event.data.transaction_id);
49549
+ }
49550
+ }
49564
49551
  });
49565
- reader.on("error", (error46) => {
49566
- console.error("[MoneyMQ] Channel reader error:", error46);
49552
+ stream.on("error", (error46) => {
49553
+ console.error("[MoneyMQ] Stream error while waiting for transaction:completed:", error46);
49567
49554
  });
49568
- reader.connect();
49555
+ stream.connect();
49569
49556
  });
49570
49557
  }
49571
49558
  function getLineItemSubtotal(item) {
@@ -49716,10 +49703,10 @@ function CheckoutModal({
49716
49703
  if (currentSelection?.type === "browser_extension" && publicKey) {
49717
49704
  const apiUrl = normalizeRpcUrl2(client.config.endpoint);
49718
49705
  try {
49719
- const configResponse = await fetch(`${apiUrl}/config`);
49706
+ const configResponse = await fetch(`${apiUrl}/payment/v1/config?attrs=studio`);
49720
49707
  const config2 = await configResponse.json();
49721
49708
  const rpcUrl = normalizeRpcUrl2(
49722
- config2.x402?.validator?.rpcUrl || "http://localhost:8899"
49709
+ config2.studio?.rpcUrl || "http://localhost:8899"
49723
49710
  );
49724
49711
  const response = await fetch(rpcUrl, {
49725
49712
  method: "POST",
@@ -49774,9 +49761,9 @@ function CheckoutModal({
49774
49761
  const apiUrl2 = normalizeRpcUrl2(client.config.endpoint);
49775
49762
  let rpcUrl = "http://localhost:8899";
49776
49763
  try {
49777
- const configResponse = await fetch(`${apiUrl2}/config`);
49764
+ const configResponse = await fetch(`${apiUrl2}/payment/v1/config?attrs=studio`);
49778
49765
  const config2 = await configResponse.json();
49779
- rpcUrl = normalizeRpcUrl2(config2.x402?.validator?.rpcUrl || rpcUrl);
49766
+ rpcUrl = normalizeRpcUrl2(config2.studio?.rpcUrl || rpcUrl);
49780
49767
  } catch {
49781
49768
  console.log("[MoneyMQ] Using default RPC URL");
49782
49769
  }
@@ -49796,17 +49783,9 @@ function CheckoutModal({
49796
49783
  if (!transactionId2) {
49797
49784
  throw new Error("No transaction ID received from settlement event");
49798
49785
  }
49799
- console.log("[MoneyMQ] Waiting for transaction:completed on channel:", transactionId2);
49800
- const completedEvent2 = await waitForChannelEvent(
49801
- apiUrl2,
49802
- transactionId2,
49803
- "transaction:completed",
49804
- 3e4
49805
- );
49806
- const receiptToken2 = completedEvent2.data?.receipt;
49807
- if (!receiptToken2) {
49808
- throw new Error("No receipt token in transaction:completed event");
49809
- }
49786
+ console.log("[MoneyMQ] Waiting for transaction:completed CloudEvent for tx:", transactionId2);
49787
+ const completedEvent2 = await waitForTransactionCompleted(apiUrl2, transactionId2, 3e4);
49788
+ const receiptToken2 = completedEvent2.data.receipt;
49810
49789
  console.log("[MoneyMQ] Receipt received, creating CheckoutReceipt");
49811
49790
  const receipt2 = new CheckoutReceipt(receiptToken2);
49812
49791
  setIsSending(false);
@@ -49832,17 +49811,9 @@ function CheckoutModal({
49832
49811
  if (!transactionId) {
49833
49812
  throw new Error("No transaction ID received from settlement event");
49834
49813
  }
49835
- console.log("[MoneyMQ] Waiting for transaction:completed on channel:", transactionId);
49836
- const completedEvent = await waitForChannelEvent(
49837
- apiUrl,
49838
- transactionId,
49839
- "transaction:completed",
49840
- 3e4
49841
- );
49842
- const receiptToken = completedEvent.data?.receipt;
49843
- if (!receiptToken) {
49844
- throw new Error("No receipt token in transaction:completed event");
49845
- }
49814
+ console.log("[MoneyMQ] Waiting for transaction:completed CloudEvent for tx:", transactionId);
49815
+ const completedEvent = await waitForTransactionCompleted(apiUrl, transactionId, 3e4);
49816
+ const receiptToken = completedEvent.data.receipt;
49846
49817
  console.log("[MoneyMQ] Receipt received, creating CheckoutReceipt");
49847
49818
  const receipt = new CheckoutReceipt(receiptToken);
49848
49819
  setIsSending(false);
@@ -49867,9 +49838,10 @@ function CheckoutModal({
49867
49838
  ]);
49868
49839
  const canPay = (connected && publicKey || selectedPaymentMethod?.type === "sandbox_account") && recipient && !isSending;
49869
49840
  const dotLottieRef = useRef3(null);
49841
+ const processingLottieRef = useRef3(null);
49870
49842
  useEffect4(() => {
49871
49843
  if (!dotLottieRef.current) return;
49872
- if (canPay) {
49844
+ if (canPay && !isSending) {
49873
49845
  dotLottieRef.current.setFrame(0);
49874
49846
  dotLottieRef.current.play();
49875
49847
  const interval = setInterval(() => {
@@ -49882,7 +49854,15 @@ function CheckoutModal({
49882
49854
  } else {
49883
49855
  dotLottieRef.current.stop();
49884
49856
  }
49885
- }, [canPay]);
49857
+ }, [canPay, isSending]);
49858
+ useEffect4(() => {
49859
+ if (!processingLottieRef.current) return;
49860
+ if (isSending) {
49861
+ processingLottieRef.current.setSpeed(2);
49862
+ processingLottieRef.current.setLoop(true);
49863
+ processingLottieRef.current.play();
49864
+ }
49865
+ }, [isSending]);
49886
49866
  if (typeof document === "undefined") return null;
49887
49867
  if (!shouldRender) return null;
49888
49868
  const WalletIcon = () => /* @__PURE__ */ jsxs3(
@@ -50744,11 +50724,11 @@ function CheckoutModal({
50744
50724
  }
50745
50725
  )
50746
50726
  ] }),
50747
- /* @__PURE__ */ jsx5(
50727
+ /* @__PURE__ */ jsxs3(
50748
50728
  "button",
50749
50729
  {
50750
50730
  onClick: handlePay,
50751
- disabled: !canPay,
50731
+ disabled: !canPay || isSending,
50752
50732
  style: {
50753
50733
  width: "100%",
50754
50734
  padding: "0.5rem 1rem",
@@ -50756,63 +50736,97 @@ function CheckoutModal({
50756
50736
  border: "none",
50757
50737
  fontSize: "1.0625rem",
50758
50738
  fontWeight: 600,
50759
- cursor: canPay ? "pointer" : "not-allowed",
50760
- backgroundColor: canPay ? "#000" : "#48484a",
50761
- color: canPay ? "#fff" : "#8e8e93",
50739
+ cursor: canPay && !isSending ? "pointer" : "not-allowed",
50740
+ backgroundColor: canPay || isSending ? "#000" : "#48484a",
50741
+ color: canPay || isSending ? "#fff" : "#8e8e93",
50762
50742
  display: "flex",
50763
50743
  alignItems: "center",
50764
50744
  justifyContent: "center",
50765
50745
  gap: "0.25rem",
50766
- transition: "opacity 150ms"
50746
+ transition: "background-color 150ms, color 150ms",
50747
+ position: "relative",
50748
+ overflow: "hidden"
50767
50749
  },
50768
- children: isSending ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
50750
+ children: [
50769
50751
  /* @__PURE__ */ jsx5(
50770
50752
  "div",
50771
50753
  {
50772
50754
  style: {
50773
- width: "1.25rem",
50774
- height: "1.25rem",
50775
- border: "2px solid currentColor",
50776
- borderTopColor: "transparent",
50777
- borderRadius: "50%",
50778
- animation: "spin 1s linear infinite"
50779
- }
50755
+ position: "absolute",
50756
+ inset: 0,
50757
+ display: "flex",
50758
+ alignItems: "center",
50759
+ justifyContent: "center",
50760
+ opacity: isSending ? 1 : 0,
50761
+ transform: isSending ? "scale(1)" : "scale(0.8)",
50762
+ transition: "opacity 200ms ease-out, transform 200ms ease-out",
50763
+ pointerEvents: "none"
50764
+ },
50765
+ children: /* @__PURE__ */ jsx5(
50766
+ l9,
50767
+ {
50768
+ dotLottieRefCallback: (dotLottie) => {
50769
+ processingLottieRef.current = dotLottie;
50770
+ },
50771
+ data: JSON.stringify(logo_animation_default),
50772
+ loop: false,
50773
+ autoplay: false,
50774
+ style: {
50775
+ width: 48,
50776
+ height: 48
50777
+ }
50778
+ }
50779
+ )
50780
50780
  }
50781
50781
  ),
50782
- /* @__PURE__ */ jsx5("span", { children: "Processing..." })
50783
- ] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
50784
- /* @__PURE__ */ jsx5(
50785
- l9,
50782
+ /* @__PURE__ */ jsxs3(
50783
+ "div",
50786
50784
  {
50787
- dotLottieRefCallback: (dotLottie) => {
50788
- dotLottieRef.current = dotLottie;
50789
- },
50790
- data: JSON.stringify(logo_animation_default),
50791
- loop: false,
50792
- autoplay: false,
50793
50785
  style: {
50794
- width: 48,
50795
- height: 48,
50796
- marginTop: "-8px",
50797
- marginBottom: "-8px",
50798
- marginLeft: "-8px",
50799
- marginRight: "4px",
50800
- opacity: canPay ? 1 : 0.55,
50801
- transition: "opacity 150ms"
50802
- }
50786
+ display: "flex",
50787
+ alignItems: "center",
50788
+ justifyContent: "center",
50789
+ gap: "0.25rem",
50790
+ opacity: isSending ? 0 : 1,
50791
+ transform: isSending ? "scale(0.95)" : "scale(1)",
50792
+ transition: "opacity 200ms ease-out, transform 200ms ease-out"
50793
+ },
50794
+ children: [
50795
+ /* @__PURE__ */ jsx5(
50796
+ l9,
50797
+ {
50798
+ dotLottieRefCallback: (dotLottie) => {
50799
+ dotLottieRef.current = dotLottie;
50800
+ },
50801
+ data: JSON.stringify(logo_animation_default),
50802
+ loop: false,
50803
+ autoplay: false,
50804
+ style: {
50805
+ width: 48,
50806
+ height: 48,
50807
+ marginTop: "-8px",
50808
+ marginBottom: "-8px",
50809
+ marginLeft: "-8px",
50810
+ marginRight: "4px",
50811
+ opacity: canPay ? 1 : 0.55,
50812
+ transition: "opacity 150ms"
50813
+ }
50814
+ }
50815
+ ),
50816
+ /* @__PURE__ */ jsxs3("span", { children: [
50817
+ "Pay",
50818
+ " ",
50819
+ amount.toLocaleString(void 0, {
50820
+ minimumFractionDigits: 2,
50821
+ maximumFractionDigits: 2
50822
+ }),
50823
+ " ",
50824
+ currency
50825
+ ] })
50826
+ ]
50803
50827
  }
50804
- ),
50805
- /* @__PURE__ */ jsxs3("span", { children: [
50806
- "Pay",
50807
- " ",
50808
- amount.toLocaleString(void 0, {
50809
- minimumFractionDigits: 2,
50810
- maximumFractionDigits: 2
50811
- }),
50812
- " ",
50813
- currency
50814
- ] })
50815
- ] })
50828
+ )
50829
+ ]
50816
50830
  }
50817
50831
  )
50818
50832
  ]
@@ -50898,16 +50912,17 @@ var CheckoutButton = forwardRef(
50898
50912
  setError(null);
50899
50913
  try {
50900
50914
  if (!basket || basket.length === 0) {
50901
- throw new Error("Basket is empty");
50915
+ setIsLoading(true);
50916
+ return;
50902
50917
  }
50903
50918
  const apiUrl = client.config.endpoint;
50904
- const configResponse = await fetch(`${apiUrl}/config`);
50919
+ const configResponse = await fetch(`${apiUrl}/payment/v1/config`);
50905
50920
  if (!configResponse.ok) {
50906
50921
  throw new Error(`Failed to fetch config: ${configResponse.status}`);
50907
50922
  }
50908
50923
  const config2 = await configResponse.json();
50909
- if (config2.x402?.payoutAccount?.address) {
50910
- setRecipient(config2.x402.payoutAccount.address);
50924
+ if (config2.x402?.solana?.payout?.recipientAddress) {
50925
+ setRecipient(config2.x402.solana.payout.recipientAddress);
50911
50926
  }
50912
50927
  } catch (err2) {
50913
50928
  console.error("[CheckoutButton] Error fetching payment details:", err2);