x402-mantle-sdk 0.1.0 → 0.2.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.
@@ -2,6 +2,32 @@
2
2
  import { useState, useEffect, useCallback } from "react";
3
3
 
4
4
  // src/client/constants.ts
5
+ var NETWORKS = {
6
+ mantle: {
7
+ chainId: 5e3,
8
+ rpcUrl: "https://rpc.mantle.xyz",
9
+ name: "Mantle",
10
+ environment: "mainnet",
11
+ nativeCurrency: { name: "Mantle", symbol: "MNT", decimals: 18 },
12
+ blockExplorer: "https://explorer.mantle.xyz"
13
+ },
14
+ "mantle-sepolia": {
15
+ chainId: 5003,
16
+ rpcUrl: "https://rpc.sepolia.mantle.xyz",
17
+ name: "Mantle Sepolia",
18
+ environment: "testnet",
19
+ nativeCurrency: { name: "Mantle", symbol: "MNT", decimals: 18 },
20
+ blockExplorer: "https://explorer.sepolia.mantle.xyz"
21
+ },
22
+ "mantle-testnet": {
23
+ chainId: 5003,
24
+ rpcUrl: "https://rpc.sepolia.mantle.xyz",
25
+ name: "Mantle Testnet",
26
+ environment: "testnet",
27
+ nativeCurrency: { name: "Mantle", symbol: "MNT", decimals: 18 },
28
+ blockExplorer: "https://explorer.sepolia.mantle.xyz"
29
+ }
30
+ };
5
31
  var TOKENS = {
6
32
  mantle: {
7
33
  USDC: {
@@ -63,7 +89,20 @@ var TOKENS = {
63
89
  var TREASURY_ADDRESS = "0xB27705342ACE73736AE490540Ea031cc06C3eF49";
64
90
  var PLATFORM_FEE_BPS = 50n;
65
91
  var BPS_DENOMINATOR = 10000n;
92
+ var customNetworks = /* @__PURE__ */ new Map();
66
93
  var customTokens = /* @__PURE__ */ new Map();
94
+ function getNetworkConfig(network) {
95
+ const networkKey = network.toLowerCase();
96
+ const custom = customNetworks.get(networkKey);
97
+ if (custom) {
98
+ return custom;
99
+ }
100
+ const preset = NETWORKS[networkKey];
101
+ if (preset) {
102
+ return preset;
103
+ }
104
+ return NETWORKS.mantle;
105
+ }
67
106
  function getTokenConfig(token, network) {
68
107
  const networkKey = network.toLowerCase();
69
108
  const tokenKey = token.toUpperCase();
@@ -160,11 +199,33 @@ var MetaMaskProvider = class {
160
199
  if (!this.ethereum) {
161
200
  throw new Error("MetaMask is not available");
162
201
  }
163
- const txHash = await this.ethereum.request({
164
- method: "eth_sendTransaction",
165
- params: [tx]
166
- });
167
- return txHash;
202
+ const account = await this.getAccount();
203
+ if (!account) {
204
+ throw new Error("No account connected. Please connect your wallet first.");
205
+ }
206
+ const txWithFrom = {
207
+ ...tx,
208
+ from: account
209
+ };
210
+ try {
211
+ const txHash = await this.ethereum.request({
212
+ method: "eth_sendTransaction",
213
+ params: [txWithFrom]
214
+ });
215
+ return txHash;
216
+ } catch (error) {
217
+ if (error.code === 4001) {
218
+ throw new Error("Transaction rejected by user");
219
+ } else if (error.code === -32602) {
220
+ throw new Error("Invalid transaction parameters");
221
+ } else if (error.message?.includes("insufficient funds") || error.message?.includes("insufficient balance")) {
222
+ throw new Error("Insufficient funds for this transaction");
223
+ } else if (error.message) {
224
+ throw new Error(error.message);
225
+ } else {
226
+ throw new Error(`Transaction failed: ${error.code || "Unknown error"}`);
227
+ }
228
+ }
168
229
  }
169
230
  async signMessage(message) {
170
231
  if (!this.ethereum) {
@@ -197,6 +258,30 @@ async function connectWallet(provider) {
197
258
  }
198
259
  return wallet.connect();
199
260
  }
261
+ async function ensureNetwork(wallet, network, autoAdd = true) {
262
+ const config = getNetworkConfig(network);
263
+ const targetChainId = config.chainId;
264
+ const currentChainId = await wallet.getChainId();
265
+ if (currentChainId === targetChainId) {
266
+ return;
267
+ }
268
+ try {
269
+ await wallet.switchNetwork(targetChainId);
270
+ } catch (error) {
271
+ const switchError = error;
272
+ if (autoAdd && switchError.message?.includes("not found")) {
273
+ await wallet.addNetwork({
274
+ chainId: `0x${targetChainId.toString(16)}`,
275
+ chainName: config.name,
276
+ nativeCurrency: config.nativeCurrency,
277
+ rpcUrls: [config.rpcUrl],
278
+ blockExplorerUrls: config.blockExplorer ? [config.blockExplorer] : void 0
279
+ });
280
+ } else {
281
+ throw error;
282
+ }
283
+ }
284
+ }
200
285
 
201
286
  // src/client/payment.ts
202
287
  var ERC20_TRANSFER_SIG = "0xa9059cbb";
@@ -217,9 +302,15 @@ function encodeERC20Transfer(to, amount) {
217
302
  return ERC20_TRANSFER_SIG + toHex + amountHex;
218
303
  }
219
304
  async function processPayment(request, wallet) {
305
+ if (!request.amount || !request.recipient || !request.network) {
306
+ throw new Error("Invalid payment request: missing required fields");
307
+ }
220
308
  const tokenConfig = getTokenConfig(request.token, request.network);
221
309
  const decimals = tokenConfig?.decimals ?? 18;
222
310
  const totalAmount = amountToWei(request.amount, decimals);
311
+ if (totalAmount === 0n) {
312
+ throw new Error("Invalid payment amount: amount must be greater than 0");
313
+ }
223
314
  const { merchantAmount, feeAmount } = calculateSplit(totalAmount);
224
315
  let txHash;
225
316
  if (tokenConfig) {
@@ -230,17 +321,21 @@ async function processPayment(request, wallet) {
230
321
  };
231
322
  txHash = await wallet.sendTransaction(tx);
232
323
  } else {
324
+ const merchantValue = merchantAmount.toString(16);
233
325
  const merchantTx = {
234
326
  to: request.recipient,
235
- value: `0x${merchantAmount.toString(16)}`
327
+ value: `0x${merchantValue}`
236
328
  };
237
329
  txHash = await wallet.sendTransaction(merchantTx);
238
330
  if (feeAmount > 0n) {
331
+ const feeValue = feeAmount.toString(16);
239
332
  const feeTx = {
240
333
  to: TREASURY_ADDRESS,
241
- value: `0x${feeAmount.toString(16)}`
334
+ value: `0x${feeValue}`
242
335
  };
243
- await wallet.sendTransaction(feeTx);
336
+ wallet.sendTransaction(feeTx).catch((err) => {
337
+ console.warn("Fee transaction failed (non-critical):", err);
338
+ });
244
339
  }
245
340
  }
246
341
  return {
@@ -252,6 +347,12 @@ async function processPayment(request, wallet) {
252
347
  // src/client/modal-react.tsx
253
348
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
254
349
  function formatAddress(address) {
350
+ if (!address || typeof address !== "string") {
351
+ return "N/A";
352
+ }
353
+ if (address.length < 10) {
354
+ return address;
355
+ }
255
356
  return `${address.slice(0, 6)}...${address.slice(-4)}`;
256
357
  }
257
358
  function PaymentModal({ request, onComplete, onCancel, isOpen }) {
@@ -260,6 +361,62 @@ function PaymentModal({ request, onComplete, onCancel, isOpen }) {
260
361
  const [isProcessing, setIsProcessing] = useState(false);
261
362
  const [error, setError] = useState(null);
262
363
  const [step, setStep] = useState("connect");
364
+ if (!request || !request.amount || !request.recipient || !request.network) {
365
+ console.error("Invalid payment request:", request);
366
+ if (isOpen) {
367
+ return /* @__PURE__ */ jsx(
368
+ "div",
369
+ {
370
+ style: {
371
+ position: "fixed",
372
+ inset: 0,
373
+ zIndex: 9999,
374
+ display: "flex",
375
+ alignItems: "center",
376
+ justifyContent: "center",
377
+ background: "rgba(0, 0, 0, 0.5)",
378
+ backdropFilter: "blur(4px)"
379
+ },
380
+ onClick: (e) => e.target === e.currentTarget && onCancel(),
381
+ children: /* @__PURE__ */ jsxs(
382
+ "div",
383
+ {
384
+ style: {
385
+ width: "100%",
386
+ maxWidth: "28rem",
387
+ borderRadius: "0.75rem",
388
+ border: "1px solid rgba(239, 68, 68, 0.5)",
389
+ background: "rgba(24, 24, 27, 0.95)",
390
+ padding: "1.5rem",
391
+ color: "#fafafa"
392
+ },
393
+ children: [
394
+ /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 1rem 0", color: "rgba(239, 68, 68, 0.9)" }, children: "Invalid Payment Request" }),
395
+ /* @__PURE__ */ jsx("p", { style: { margin: "0 0 1rem 0", color: "rgba(250, 250, 250, 0.8)" }, children: "The payment request is missing required information. Please try again." }),
396
+ /* @__PURE__ */ jsx(
397
+ "button",
398
+ {
399
+ onClick: onCancel,
400
+ style: {
401
+ width: "100%",
402
+ padding: "0.75rem",
403
+ borderRadius: "0.5rem",
404
+ border: "1px solid rgba(255, 255, 255, 0.2)",
405
+ background: "rgba(255, 255, 255, 0.1)",
406
+ color: "#fafafa",
407
+ cursor: "pointer"
408
+ },
409
+ children: "Close"
410
+ }
411
+ )
412
+ ]
413
+ }
414
+ )
415
+ }
416
+ );
417
+ }
418
+ return null;
419
+ }
263
420
  const checkWalletConnection = useCallback(async () => {
264
421
  const wallet = detectWalletProvider();
265
422
  if (wallet) {
@@ -308,10 +465,27 @@ function PaymentModal({ request, onComplete, onCancel, isOpen }) {
308
465
  if (!wallet) {
309
466
  throw new Error("Wallet not connected");
310
467
  }
468
+ try {
469
+ await ensureNetwork(wallet, request.network, true);
470
+ } catch (networkError) {
471
+ const errorMessage = networkError instanceof Error ? networkError.message : "Network switch failed";
472
+ throw new Error(`Failed to switch network: ${errorMessage}. Please ensure you're on ${request.network}`);
473
+ }
311
474
  const payment = await processPayment(request, wallet);
312
475
  onComplete(payment);
313
476
  } catch (err) {
314
- setError(err instanceof Error ? err.message : "Payment failed");
477
+ let errorMessage = "Payment failed";
478
+ if (err instanceof Error) {
479
+ errorMessage = err.message;
480
+ if (err.message.includes("user rejected") || err.message.includes("User denied")) {
481
+ errorMessage = "Transaction was rejected. Please try again.";
482
+ } else if (err.message.includes("insufficient funds") || err.message.includes("insufficient balance")) {
483
+ errorMessage = "Insufficient funds. Please ensure you have enough MNT in your wallet.";
484
+ } else if (err.message.includes("network")) {
485
+ errorMessage = err.message;
486
+ }
487
+ }
488
+ setError(errorMessage);
315
489
  setStep("confirm");
316
490
  } finally {
317
491
  setIsProcessing(false);
@@ -625,7 +799,1001 @@ function PaymentModal({ request, onComplete, onCancel, isOpen }) {
625
799
  }
626
800
  );
627
801
  }
802
+
803
+ // src/client/payment-modal-enhanced.tsx
804
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
805
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
806
+ function formatAddress2(address) {
807
+ if (!address || typeof address !== "string") {
808
+ return "N/A";
809
+ }
810
+ if (address.length < 10) {
811
+ return address;
812
+ }
813
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
814
+ }
815
+ function getExplorerUrl(txHash, network) {
816
+ const config = getNetworkConfig(network);
817
+ if (config.blockExplorer) {
818
+ return `${config.blockExplorer}/tx/${txHash}`;
819
+ }
820
+ if (network.includes("sepolia") || network.includes("testnet")) {
821
+ return `https://explorer.sepolia.mantle.xyz/tx/${txHash}`;
822
+ }
823
+ return `https://explorer.mantle.xyz/tx/${txHash}`;
824
+ }
825
+ function EnhancedPaymentModal({
826
+ request,
827
+ onComplete,
828
+ onCancel,
829
+ isOpen,
830
+ simulation = false,
831
+ description,
832
+ endpoint
833
+ }) {
834
+ const [walletAddress, setWalletAddress] = useState2(null);
835
+ const [isConnecting, setIsConnecting] = useState2(false);
836
+ const [isProcessing, setIsProcessing] = useState2(false);
837
+ const [error, setError] = useState2(null);
838
+ const [txHash, setTxHash] = useState2(null);
839
+ const [copied, setCopied] = useState2(false);
840
+ useEffect2(() => {
841
+ if (!isOpen) {
842
+ setIsProcessing(false);
843
+ setError(null);
844
+ setTxHash(null);
845
+ setCopied(false);
846
+ setWalletAddress(null);
847
+ }
848
+ }, [isOpen]);
849
+ const handleCopy = useCallback2((text) => {
850
+ navigator.clipboard.writeText(text);
851
+ setCopied(true);
852
+ setTimeout(() => setCopied(false), 2e3);
853
+ }, []);
854
+ const checkWalletConnection = useCallback2(async () => {
855
+ const wallet = detectWalletProvider();
856
+ if (wallet) {
857
+ try {
858
+ const account = await wallet.getAccount();
859
+ if (account) {
860
+ setWalletAddress(account);
861
+ }
862
+ } catch {
863
+ }
864
+ }
865
+ }, []);
866
+ useEffect2(() => {
867
+ if (isOpen) {
868
+ checkWalletConnection();
869
+ }
870
+ }, [isOpen, checkWalletConnection]);
871
+ const handleConnect = async () => {
872
+ setIsConnecting(true);
873
+ setError(null);
874
+ try {
875
+ const wallet = detectWalletProvider();
876
+ if (!wallet) {
877
+ throw new Error("No wallet found. Please install MetaMask.");
878
+ }
879
+ const address = await connectWallet(wallet);
880
+ setWalletAddress(address);
881
+ } catch (err) {
882
+ setError(err instanceof Error ? err.message : "Failed to connect wallet");
883
+ } finally {
884
+ setIsConnecting(false);
885
+ }
886
+ };
887
+ const handlePayment = async () => {
888
+ if (simulation) {
889
+ setIsProcessing(true);
890
+ setError(null);
891
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
892
+ const mockTxHash = `0x${Array.from(
893
+ { length: 64 },
894
+ () => Math.floor(Math.random() * 16).toString(16)
895
+ ).join("")}`;
896
+ setTxHash(mockTxHash);
897
+ setTimeout(() => {
898
+ const paymentResponse = {
899
+ transactionHash: mockTxHash,
900
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
901
+ };
902
+ setIsProcessing(false);
903
+ onComplete(paymentResponse);
904
+ }, 1500);
905
+ return;
906
+ }
907
+ if (!walletAddress) {
908
+ setError("Please connect your wallet first");
909
+ return;
910
+ }
911
+ try {
912
+ setIsProcessing(true);
913
+ setError(null);
914
+ const wallet = detectWalletProvider();
915
+ if (!wallet) {
916
+ throw new Error("Wallet not connected");
917
+ }
918
+ try {
919
+ await ensureNetwork(wallet, request.network, true);
920
+ } catch (networkError) {
921
+ const errorMessage = networkError instanceof Error ? networkError.message : "Network switch failed";
922
+ throw new Error(
923
+ `Failed to switch network: ${errorMessage}. Please ensure you're on ${request.network}`
924
+ );
925
+ }
926
+ const payment = await processPayment(request, wallet);
927
+ setTxHash(payment.transactionHash);
928
+ setTimeout(() => {
929
+ onComplete(payment);
930
+ }, 2e3);
931
+ } catch (err) {
932
+ let errorMessage = "Payment failed";
933
+ if (err instanceof Error) {
934
+ errorMessage = err.message;
935
+ if (err.message.includes("user rejected") || err.message.includes("User denied")) {
936
+ errorMessage = "Transaction was rejected. Please try again.";
937
+ } else if (err.message.includes("insufficient funds") || err.message.includes("insufficient balance")) {
938
+ errorMessage = "Insufficient funds. Please ensure you have enough MNT in your wallet.";
939
+ } else if (err.message.includes("network")) {
940
+ errorMessage = err.message;
941
+ }
942
+ }
943
+ setError(errorMessage);
944
+ setIsProcessing(false);
945
+ }
946
+ };
947
+ if (!request || !request.amount || !request.recipient || !request.network) {
948
+ console.error("Invalid payment request:", request);
949
+ if (isOpen) {
950
+ return /* @__PURE__ */ jsx2(
951
+ "div",
952
+ {
953
+ style: {
954
+ position: "fixed",
955
+ inset: 0,
956
+ zIndex: 9999,
957
+ display: "flex",
958
+ alignItems: "center",
959
+ justifyContent: "center",
960
+ background: "rgba(0, 0, 0, 0.5)",
961
+ backdropFilter: "blur(4px)",
962
+ padding: "1rem"
963
+ },
964
+ onClick: (e) => e.target === e.currentTarget && onCancel(),
965
+ children: /* @__PURE__ */ jsxs2(
966
+ "div",
967
+ {
968
+ style: {
969
+ width: "100%",
970
+ maxWidth: "28rem",
971
+ borderRadius: "0.75rem",
972
+ border: "1px solid rgba(239, 68, 68, 0.5)",
973
+ background: "rgba(24, 24, 27, 0.95)",
974
+ padding: "1.5rem",
975
+ color: "#fafafa"
976
+ },
977
+ children: [
978
+ /* @__PURE__ */ jsx2("h2", { style: { margin: "0 0 1rem 0", color: "rgba(239, 68, 68, 0.9)" }, children: "Invalid Payment Request" }),
979
+ /* @__PURE__ */ jsx2("p", { style: { margin: "0 0 1rem 0", color: "rgba(250, 250, 250, 0.8)" }, children: "The payment request is missing required information. Please try again." }),
980
+ /* @__PURE__ */ jsx2(
981
+ "button",
982
+ {
983
+ onClick: onCancel,
984
+ style: {
985
+ width: "100%",
986
+ padding: "0.75rem",
987
+ borderRadius: "0.5rem",
988
+ border: "1px solid rgba(255, 255, 255, 0.2)",
989
+ background: "rgba(255, 255, 255, 0.1)",
990
+ color: "#fafafa",
991
+ cursor: "pointer"
992
+ },
993
+ children: "Close"
994
+ }
995
+ )
996
+ ]
997
+ }
998
+ )
999
+ }
1000
+ );
1001
+ }
1002
+ return null;
1003
+ }
1004
+ if (!isOpen) return null;
1005
+ return /* @__PURE__ */ jsxs2(
1006
+ "div",
1007
+ {
1008
+ style: {
1009
+ position: "fixed",
1010
+ inset: 0,
1011
+ zIndex: 9999,
1012
+ display: "flex",
1013
+ alignItems: "center",
1014
+ justifyContent: "center",
1015
+ background: "rgba(0, 0, 0, 0.5)",
1016
+ backdropFilter: "blur(4px)",
1017
+ padding: "1rem"
1018
+ },
1019
+ onClick: (e) => e.target === e.currentTarget && onCancel(),
1020
+ children: [
1021
+ /* @__PURE__ */ jsxs2(
1022
+ "div",
1023
+ {
1024
+ style: {
1025
+ width: "100%",
1026
+ maxWidth: "28rem",
1027
+ borderRadius: "0.75rem",
1028
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1029
+ background: "rgba(24, 24, 27, 0.95)",
1030
+ padding: "1.5rem",
1031
+ boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.3)",
1032
+ backdropFilter: "blur(16px)",
1033
+ color: "#fafafa",
1034
+ maxHeight: "90vh",
1035
+ overflowY: "auto"
1036
+ },
1037
+ children: [
1038
+ /* @__PURE__ */ jsxs2(
1039
+ "div",
1040
+ {
1041
+ style: {
1042
+ display: "flex",
1043
+ alignItems: "center",
1044
+ justifyContent: "space-between",
1045
+ marginBottom: "1rem"
1046
+ },
1047
+ children: [
1048
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1049
+ /* @__PURE__ */ jsx2(
1050
+ "h2",
1051
+ {
1052
+ style: {
1053
+ margin: 0,
1054
+ fontSize: "1.25rem",
1055
+ fontWeight: 300,
1056
+ color: "#fafafa"
1057
+ },
1058
+ children: txHash ? "Payment Complete" : "Payment Required"
1059
+ }
1060
+ ),
1061
+ simulation && /* @__PURE__ */ jsx2(
1062
+ "span",
1063
+ {
1064
+ style: {
1065
+ borderRadius: "9999px",
1066
+ border: "1px solid rgba(234, 179, 8, 0.4)",
1067
+ background: "rgba(234, 179, 8, 0.2)",
1068
+ padding: "0.125rem 0.5rem",
1069
+ fontFamily: "monospace",
1070
+ fontSize: "0.75rem",
1071
+ color: "rgba(234, 179, 8, 1)"
1072
+ },
1073
+ children: "SIMULATION"
1074
+ }
1075
+ )
1076
+ ] }),
1077
+ !isProcessing && /* @__PURE__ */ jsx2(
1078
+ "button",
1079
+ {
1080
+ onClick: onCancel,
1081
+ style: {
1082
+ background: "none",
1083
+ border: "none",
1084
+ fontSize: "1.5rem",
1085
+ cursor: "pointer",
1086
+ color: "rgba(250, 250, 250, 0.6)",
1087
+ lineHeight: 1,
1088
+ padding: 0,
1089
+ display: "flex",
1090
+ alignItems: "center",
1091
+ justifyContent: "center"
1092
+ },
1093
+ "aria-label": "Close",
1094
+ children: "\xD7"
1095
+ }
1096
+ )
1097
+ ]
1098
+ }
1099
+ ),
1100
+ txHash ? /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
1101
+ /* @__PURE__ */ jsx2(
1102
+ "div",
1103
+ {
1104
+ style: {
1105
+ display: "flex",
1106
+ alignItems: "center",
1107
+ justifyContent: "center",
1108
+ padding: "0.5rem 0"
1109
+ },
1110
+ children: /* @__PURE__ */ jsx2(
1111
+ "div",
1112
+ {
1113
+ style: {
1114
+ borderRadius: "50%",
1115
+ background: "rgba(34, 197, 94, 0.2)",
1116
+ padding: "0.75rem"
1117
+ },
1118
+ children: /* @__PURE__ */ jsx2(
1119
+ "svg",
1120
+ {
1121
+ width: "32",
1122
+ height: "32",
1123
+ viewBox: "0 0 24 24",
1124
+ fill: "none",
1125
+ stroke: "rgba(34, 197, 94, 1)",
1126
+ strokeWidth: "2",
1127
+ strokeLinecap: "round",
1128
+ strokeLinejoin: "round",
1129
+ children: /* @__PURE__ */ jsx2("path", { d: "M20 6L9 17l-5-5" })
1130
+ }
1131
+ )
1132
+ }
1133
+ )
1134
+ }
1135
+ ),
1136
+ /* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1rem", display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
1137
+ /* @__PURE__ */ jsxs2("div", { children: [
1138
+ /* @__PURE__ */ jsx2(
1139
+ "p",
1140
+ {
1141
+ style: {
1142
+ marginBottom: "0.5rem",
1143
+ fontFamily: "monospace",
1144
+ fontSize: "0.75rem",
1145
+ color: "rgba(250, 250, 250, 0.6)"
1146
+ },
1147
+ children: "Transaction Hash"
1148
+ }
1149
+ ),
1150
+ /* @__PURE__ */ jsxs2(
1151
+ "div",
1152
+ {
1153
+ style: {
1154
+ display: "flex",
1155
+ alignItems: "center",
1156
+ gap: "0.5rem",
1157
+ borderRadius: "0.5rem",
1158
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1159
+ background: "rgba(0, 0, 0, 0.3)",
1160
+ padding: "0.5rem 0.75rem",
1161
+ overflow: "hidden"
1162
+ },
1163
+ children: [
1164
+ /* @__PURE__ */ jsx2(
1165
+ "code",
1166
+ {
1167
+ style: {
1168
+ minWidth: 0,
1169
+ flex: 1,
1170
+ overflow: "hidden",
1171
+ textOverflow: "ellipsis",
1172
+ whiteSpace: "nowrap",
1173
+ fontFamily: "monospace",
1174
+ fontSize: "0.875rem",
1175
+ color: "#fafafa"
1176
+ },
1177
+ children: txHash
1178
+ }
1179
+ ),
1180
+ /* @__PURE__ */ jsxs2(
1181
+ "div",
1182
+ {
1183
+ style: {
1184
+ display: "flex",
1185
+ alignItems: "center",
1186
+ gap: "0.375rem",
1187
+ flexShrink: 0
1188
+ },
1189
+ children: [
1190
+ /* @__PURE__ */ jsx2(
1191
+ "button",
1192
+ {
1193
+ onClick: () => handleCopy(txHash),
1194
+ style: {
1195
+ display: "flex",
1196
+ alignItems: "center",
1197
+ gap: "0.375rem",
1198
+ borderRadius: "0.375rem",
1199
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1200
+ background: "rgba(255, 255, 255, 0.1)",
1201
+ padding: "0.25rem 0.625rem",
1202
+ fontFamily: "monospace",
1203
+ fontSize: "0.75rem",
1204
+ color: "#fafafa",
1205
+ cursor: "pointer",
1206
+ transition: "background 0.2s"
1207
+ },
1208
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)",
1209
+ onMouseLeave: (e) => e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)",
1210
+ title: "Copy transaction hash",
1211
+ children: copied ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
1212
+ /* @__PURE__ */ jsx2(
1213
+ "svg",
1214
+ {
1215
+ width: "14",
1216
+ height: "14",
1217
+ viewBox: "0 0 24 24",
1218
+ fill: "none",
1219
+ stroke: "currentColor",
1220
+ strokeWidth: "2",
1221
+ children: /* @__PURE__ */ jsx2("path", { d: "M20 6L9 17l-5-5" })
1222
+ }
1223
+ ),
1224
+ "Copied"
1225
+ ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
1226
+ /* @__PURE__ */ jsxs2(
1227
+ "svg",
1228
+ {
1229
+ width: "14",
1230
+ height: "14",
1231
+ viewBox: "0 0 24 24",
1232
+ fill: "none",
1233
+ stroke: "currentColor",
1234
+ strokeWidth: "2",
1235
+ children: [
1236
+ /* @__PURE__ */ jsx2("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
1237
+ /* @__PURE__ */ jsx2("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" })
1238
+ ]
1239
+ }
1240
+ ),
1241
+ "Copy"
1242
+ ] })
1243
+ }
1244
+ ),
1245
+ /* @__PURE__ */ jsx2(
1246
+ "a",
1247
+ {
1248
+ href: getExplorerUrl(txHash, request.network),
1249
+ target: "_blank",
1250
+ rel: "noopener noreferrer",
1251
+ style: {
1252
+ display: "flex",
1253
+ alignItems: "center",
1254
+ justifyContent: "center",
1255
+ borderRadius: "0.375rem",
1256
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1257
+ background: "rgba(255, 255, 255, 0.1)",
1258
+ padding: "0.375rem",
1259
+ color: "rgba(250, 250, 250, 0.6)",
1260
+ cursor: "pointer",
1261
+ transition: "all 0.2s",
1262
+ textDecoration: "none"
1263
+ },
1264
+ onMouseEnter: (e) => {
1265
+ e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)";
1266
+ e.currentTarget.style.color = "#fafafa";
1267
+ },
1268
+ onMouseLeave: (e) => {
1269
+ e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)";
1270
+ e.currentTarget.style.color = "rgba(250, 250, 250, 0.6)";
1271
+ },
1272
+ title: "View on explorer",
1273
+ children: /* @__PURE__ */ jsxs2(
1274
+ "svg",
1275
+ {
1276
+ width: "14",
1277
+ height: "14",
1278
+ viewBox: "0 0 24 24",
1279
+ fill: "none",
1280
+ stroke: "currentColor",
1281
+ strokeWidth: "2",
1282
+ children: [
1283
+ /* @__PURE__ */ jsx2("path", { d: "M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" }),
1284
+ /* @__PURE__ */ jsx2("path", { d: "M15 3h6v6" }),
1285
+ /* @__PURE__ */ jsx2("path", { d: "M10 14L21 3" })
1286
+ ]
1287
+ }
1288
+ )
1289
+ }
1290
+ )
1291
+ ]
1292
+ }
1293
+ )
1294
+ ]
1295
+ }
1296
+ )
1297
+ ] }),
1298
+ /* @__PURE__ */ jsxs2("div", { children: [
1299
+ /* @__PURE__ */ jsx2(
1300
+ "p",
1301
+ {
1302
+ style: {
1303
+ marginBottom: "0.5rem",
1304
+ fontFamily: "monospace",
1305
+ fontSize: "0.75rem",
1306
+ color: "rgba(250, 250, 250, 0.6)"
1307
+ },
1308
+ children: "Amount Paid"
1309
+ }
1310
+ ),
1311
+ /* @__PURE__ */ jsxs2(
1312
+ "p",
1313
+ {
1314
+ style: {
1315
+ fontFamily: "sans-serif",
1316
+ fontSize: "1rem",
1317
+ color: "#fafafa",
1318
+ margin: 0
1319
+ },
1320
+ children: [
1321
+ request.amount,
1322
+ " ",
1323
+ request.token
1324
+ ]
1325
+ }
1326
+ )
1327
+ ] })
1328
+ ] }),
1329
+ /* @__PURE__ */ jsx2(
1330
+ "button",
1331
+ {
1332
+ onClick: onCancel,
1333
+ style: {
1334
+ width: "100%",
1335
+ borderRadius: "0.5rem",
1336
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1337
+ background: "rgba(255, 255, 255, 0.15)",
1338
+ padding: "0.625rem 1rem",
1339
+ fontFamily: "sans-serif",
1340
+ fontSize: "0.875rem",
1341
+ color: "#fafafa",
1342
+ cursor: "pointer",
1343
+ transition: "background 0.2s"
1344
+ },
1345
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)",
1346
+ onMouseLeave: (e) => e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)",
1347
+ children: "Done"
1348
+ }
1349
+ )
1350
+ ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
1351
+ /* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1.5rem", display: "flex", flexDirection: "column", gap: "1rem" }, children: [
1352
+ description && /* @__PURE__ */ jsxs2("div", { children: [
1353
+ /* @__PURE__ */ jsx2(
1354
+ "p",
1355
+ {
1356
+ style: {
1357
+ marginBottom: "0.5rem",
1358
+ fontFamily: "monospace",
1359
+ fontSize: "0.75rem",
1360
+ color: "rgba(250, 250, 250, 0.6)"
1361
+ },
1362
+ children: "Description"
1363
+ }
1364
+ ),
1365
+ /* @__PURE__ */ jsx2(
1366
+ "p",
1367
+ {
1368
+ style: {
1369
+ fontFamily: "sans-serif",
1370
+ fontSize: "0.875rem",
1371
+ color: "#fafafa",
1372
+ margin: 0
1373
+ },
1374
+ children: description
1375
+ }
1376
+ )
1377
+ ] }),
1378
+ endpoint && /* @__PURE__ */ jsxs2("div", { children: [
1379
+ /* @__PURE__ */ jsx2(
1380
+ "p",
1381
+ {
1382
+ style: {
1383
+ marginBottom: "0.5rem",
1384
+ fontFamily: "monospace",
1385
+ fontSize: "0.75rem",
1386
+ color: "rgba(250, 250, 250, 0.6)"
1387
+ },
1388
+ children: "Endpoint"
1389
+ }
1390
+ ),
1391
+ /* @__PURE__ */ jsx2(
1392
+ "code",
1393
+ {
1394
+ style: {
1395
+ fontFamily: "monospace",
1396
+ fontSize: "0.75rem",
1397
+ color: "rgba(250, 250, 250, 0.8)",
1398
+ wordBreak: "break-all"
1399
+ },
1400
+ children: endpoint
1401
+ }
1402
+ )
1403
+ ] }),
1404
+ /* @__PURE__ */ jsxs2(
1405
+ "div",
1406
+ {
1407
+ style: {
1408
+ borderRadius: "0.5rem",
1409
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1410
+ background: "rgba(255, 255, 255, 0.05)",
1411
+ padding: "1rem"
1412
+ },
1413
+ children: [
1414
+ /* @__PURE__ */ jsxs2(
1415
+ "div",
1416
+ {
1417
+ style: {
1418
+ marginBottom: "0.75rem",
1419
+ display: "flex",
1420
+ alignItems: "center",
1421
+ justifyContent: "space-between"
1422
+ },
1423
+ children: [
1424
+ /* @__PURE__ */ jsx2(
1425
+ "p",
1426
+ {
1427
+ style: {
1428
+ fontFamily: "monospace",
1429
+ fontSize: "0.75rem",
1430
+ color: "rgba(250, 250, 250, 0.6)",
1431
+ margin: 0
1432
+ },
1433
+ children: "Amount"
1434
+ }
1435
+ ),
1436
+ /* @__PURE__ */ jsxs2(
1437
+ "p",
1438
+ {
1439
+ style: {
1440
+ fontFamily: "sans-serif",
1441
+ fontSize: "1.5rem",
1442
+ fontWeight: 300,
1443
+ color: "#fafafa",
1444
+ margin: 0
1445
+ },
1446
+ children: [
1447
+ request.amount,
1448
+ " ",
1449
+ request.token
1450
+ ]
1451
+ }
1452
+ )
1453
+ ]
1454
+ }
1455
+ ),
1456
+ /* @__PURE__ */ jsxs2(
1457
+ "div",
1458
+ {
1459
+ style: {
1460
+ display: "flex",
1461
+ flexDirection: "column",
1462
+ gap: "0.5rem",
1463
+ borderTop: "1px solid rgba(255, 255, 255, 0.1)",
1464
+ paddingTop: "0.75rem"
1465
+ },
1466
+ children: [
1467
+ /* @__PURE__ */ jsxs2(
1468
+ "div",
1469
+ {
1470
+ style: {
1471
+ display: "flex",
1472
+ alignItems: "center",
1473
+ justifyContent: "space-between"
1474
+ },
1475
+ children: [
1476
+ /* @__PURE__ */ jsx2(
1477
+ "p",
1478
+ {
1479
+ style: {
1480
+ fontFamily: "monospace",
1481
+ fontSize: "0.75rem",
1482
+ color: "rgba(250, 250, 250, 0.6)",
1483
+ margin: 0
1484
+ },
1485
+ children: "Network"
1486
+ }
1487
+ ),
1488
+ /* @__PURE__ */ jsx2(
1489
+ "p",
1490
+ {
1491
+ style: {
1492
+ fontFamily: "monospace",
1493
+ fontSize: "0.75rem",
1494
+ color: "#fafafa",
1495
+ margin: 0
1496
+ },
1497
+ children: request.network
1498
+ }
1499
+ )
1500
+ ]
1501
+ }
1502
+ ),
1503
+ /* @__PURE__ */ jsxs2(
1504
+ "div",
1505
+ {
1506
+ style: {
1507
+ display: "flex",
1508
+ alignItems: "center",
1509
+ justifyContent: "space-between",
1510
+ gap: "0.5rem"
1511
+ },
1512
+ children: [
1513
+ /* @__PURE__ */ jsx2(
1514
+ "p",
1515
+ {
1516
+ style: {
1517
+ fontFamily: "monospace",
1518
+ fontSize: "0.75rem",
1519
+ color: "rgba(250, 250, 250, 0.6)",
1520
+ margin: 0
1521
+ },
1522
+ children: "Recipient"
1523
+ }
1524
+ ),
1525
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1526
+ /* @__PURE__ */ jsx2(
1527
+ "code",
1528
+ {
1529
+ style: {
1530
+ fontFamily: "monospace",
1531
+ fontSize: "0.75rem",
1532
+ color: "#fafafa"
1533
+ },
1534
+ children: formatAddress2(request.recipient)
1535
+ }
1536
+ ),
1537
+ /* @__PURE__ */ jsx2(
1538
+ "button",
1539
+ {
1540
+ onClick: () => handleCopy(request.recipient),
1541
+ style: {
1542
+ background: "none",
1543
+ border: "none",
1544
+ color: "rgba(250, 250, 250, 0.6)",
1545
+ cursor: "pointer",
1546
+ padding: 0,
1547
+ display: "flex",
1548
+ alignItems: "center",
1549
+ justifyContent: "center",
1550
+ transition: "color 0.2s"
1551
+ },
1552
+ onMouseEnter: (e) => e.currentTarget.style.color = "#fafafa",
1553
+ onMouseLeave: (e) => e.currentTarget.style.color = "rgba(250, 250, 250, 0.6)",
1554
+ title: "Copy address",
1555
+ children: copied ? /* @__PURE__ */ jsx2(
1556
+ "svg",
1557
+ {
1558
+ width: "14",
1559
+ height: "14",
1560
+ viewBox: "0 0 24 24",
1561
+ fill: "none",
1562
+ stroke: "rgba(34, 197, 94, 1)",
1563
+ strokeWidth: "2",
1564
+ children: /* @__PURE__ */ jsx2("path", { d: "M20 6L9 17l-5-5" })
1565
+ }
1566
+ ) : /* @__PURE__ */ jsxs2(
1567
+ "svg",
1568
+ {
1569
+ width: "14",
1570
+ height: "14",
1571
+ viewBox: "0 0 24 24",
1572
+ fill: "none",
1573
+ stroke: "currentColor",
1574
+ strokeWidth: "2",
1575
+ children: [
1576
+ /* @__PURE__ */ jsx2("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
1577
+ /* @__PURE__ */ jsx2("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" })
1578
+ ]
1579
+ }
1580
+ )
1581
+ }
1582
+ )
1583
+ ] })
1584
+ ]
1585
+ }
1586
+ ),
1587
+ walletAddress && /* @__PURE__ */ jsxs2(
1588
+ "div",
1589
+ {
1590
+ style: {
1591
+ display: "flex",
1592
+ alignItems: "center",
1593
+ justifyContent: "space-between",
1594
+ gap: "0.5rem"
1595
+ },
1596
+ children: [
1597
+ /* @__PURE__ */ jsx2(
1598
+ "p",
1599
+ {
1600
+ style: {
1601
+ fontFamily: "monospace",
1602
+ fontSize: "0.75rem",
1603
+ color: "rgba(250, 250, 250, 0.6)",
1604
+ margin: 0
1605
+ },
1606
+ children: "From"
1607
+ }
1608
+ ),
1609
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1610
+ /* @__PURE__ */ jsxs2(
1611
+ "svg",
1612
+ {
1613
+ width: "14",
1614
+ height: "14",
1615
+ viewBox: "0 0 24 24",
1616
+ fill: "none",
1617
+ stroke: "rgba(250, 250, 250, 0.6)",
1618
+ strokeWidth: "2",
1619
+ children: [
1620
+ /* @__PURE__ */ jsx2("path", { d: "M21 12V7H5a2 2 0 01 0-4h14v4" }),
1621
+ /* @__PURE__ */ jsx2("path", { d: "M3 5v14a2 2 0 002 2h16v-5" }),
1622
+ /* @__PURE__ */ jsx2("path", { d: "M5 21a2 2 0 110-4h14" })
1623
+ ]
1624
+ }
1625
+ ),
1626
+ /* @__PURE__ */ jsx2(
1627
+ "code",
1628
+ {
1629
+ style: {
1630
+ fontFamily: "monospace",
1631
+ fontSize: "0.75rem",
1632
+ color: "#fafafa"
1633
+ },
1634
+ children: formatAddress2(walletAddress)
1635
+ }
1636
+ )
1637
+ ] })
1638
+ ]
1639
+ }
1640
+ )
1641
+ ]
1642
+ }
1643
+ )
1644
+ ]
1645
+ }
1646
+ )
1647
+ ] }),
1648
+ error && /* @__PURE__ */ jsxs2(
1649
+ "div",
1650
+ {
1651
+ style: {
1652
+ marginBottom: "1rem",
1653
+ display: "flex",
1654
+ alignItems: "start",
1655
+ gap: "0.75rem",
1656
+ borderRadius: "0.5rem",
1657
+ border: "1px solid rgba(239, 68, 68, 0.3)",
1658
+ background: "rgba(239, 68, 68, 0.1)",
1659
+ padding: "0.75rem"
1660
+ },
1661
+ children: [
1662
+ /* @__PURE__ */ jsxs2(
1663
+ "svg",
1664
+ {
1665
+ width: "20",
1666
+ height: "20",
1667
+ viewBox: "0 0 24 24",
1668
+ fill: "none",
1669
+ stroke: "rgba(239, 68, 68, 1)",
1670
+ strokeWidth: "2",
1671
+ style: { flexShrink: 0, marginTop: "0.125rem" },
1672
+ children: [
1673
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
1674
+ /* @__PURE__ */ jsx2("path", { d: "M12 8v4" }),
1675
+ /* @__PURE__ */ jsx2("path", { d: "M12 16h.01" })
1676
+ ]
1677
+ }
1678
+ ),
1679
+ /* @__PURE__ */ jsx2(
1680
+ "p",
1681
+ {
1682
+ style: {
1683
+ flex: 1,
1684
+ fontFamily: "monospace",
1685
+ fontSize: "0.75rem",
1686
+ color: "rgba(239, 68, 68, 1)",
1687
+ wordBreak: "break-word",
1688
+ margin: 0
1689
+ },
1690
+ children: error
1691
+ }
1692
+ )
1693
+ ]
1694
+ }
1695
+ ),
1696
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "0.75rem" }, children: [
1697
+ /* @__PURE__ */ jsx2(
1698
+ "button",
1699
+ {
1700
+ onClick: onCancel,
1701
+ disabled: isProcessing,
1702
+ style: {
1703
+ flex: 1,
1704
+ borderRadius: "0.5rem",
1705
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1706
+ background: "rgba(255, 255, 255, 0.05)",
1707
+ padding: "0.625rem 1rem",
1708
+ fontFamily: "sans-serif",
1709
+ fontSize: "0.875rem",
1710
+ color: "rgba(250, 250, 250, 0.8)",
1711
+ cursor: isProcessing ? "not-allowed" : "pointer",
1712
+ opacity: isProcessing ? 0.5 : 1,
1713
+ transition: "background 0.2s"
1714
+ },
1715
+ onMouseEnter: (e) => {
1716
+ if (!isProcessing) e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)";
1717
+ },
1718
+ onMouseLeave: (e) => {
1719
+ if (!isProcessing) e.currentTarget.style.background = "rgba(255, 255, 255, 0.05)";
1720
+ },
1721
+ children: "Cancel"
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ jsx2(
1725
+ "button",
1726
+ {
1727
+ onClick: walletAddress ? handlePayment : handleConnect,
1728
+ disabled: isProcessing || isConnecting,
1729
+ style: {
1730
+ flex: 1,
1731
+ borderRadius: "0.5rem",
1732
+ border: "1px solid rgba(255, 255, 255, 0.1)",
1733
+ background: "rgba(255, 255, 255, 0.15)",
1734
+ padding: "0.625rem 1rem",
1735
+ fontFamily: "sans-serif",
1736
+ fontSize: "0.875rem",
1737
+ color: "#fafafa",
1738
+ cursor: isProcessing || isConnecting ? "not-allowed" : "pointer",
1739
+ opacity: isProcessing || isConnecting ? 0.5 : 1,
1740
+ transition: "background 0.2s"
1741
+ },
1742
+ onMouseEnter: (e) => {
1743
+ if (!isProcessing && !isConnecting)
1744
+ e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)";
1745
+ },
1746
+ onMouseLeave: (e) => {
1747
+ if (!isProcessing && !isConnecting)
1748
+ e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
1749
+ },
1750
+ children: isProcessing ? /* @__PURE__ */ jsxs2(
1751
+ "span",
1752
+ {
1753
+ style: {
1754
+ display: "flex",
1755
+ alignItems: "center",
1756
+ justifyContent: "center",
1757
+ gap: "0.5rem"
1758
+ },
1759
+ children: [
1760
+ /* @__PURE__ */ jsx2(
1761
+ "svg",
1762
+ {
1763
+ width: "16",
1764
+ height: "16",
1765
+ viewBox: "0 0 24 24",
1766
+ fill: "none",
1767
+ stroke: "currentColor",
1768
+ strokeWidth: "2",
1769
+ style: {
1770
+ animation: "spin 1s linear infinite"
1771
+ },
1772
+ children: /* @__PURE__ */ jsx2("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
1773
+ }
1774
+ ),
1775
+ simulation ? "Simulating..." : "Processing..."
1776
+ ]
1777
+ }
1778
+ ) : isConnecting ? "Connecting..." : !walletAddress ? "Connect Wallet" : simulation ? `Simulate ${request.amount} ${request.token}` : `Pay ${request.amount} ${request.token}`
1779
+ }
1780
+ )
1781
+ ] })
1782
+ ] })
1783
+ ]
1784
+ }
1785
+ ),
1786
+ /* @__PURE__ */ jsx2("style", { children: `
1787
+ @keyframes spin {
1788
+ to { transform: rotate(360deg); }
1789
+ }
1790
+ ` })
1791
+ ]
1792
+ }
1793
+ );
1794
+ }
628
1795
  export {
1796
+ EnhancedPaymentModal,
629
1797
  PaymentModal
630
1798
  };
631
1799
  //# sourceMappingURL=react.js.map