@micro-cms/crypto-payments 1.0.9 → 1.0.11
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.css +1 -0
- package/dist/index.js +2 -351
- package/dist/index.mjs +2 -323
- package/package.json +5 -2
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.mcms-mx-auto{margin-left:auto;margin-right:auto}.mcms-mb-3{margin-bottom:.75rem}.mcms-mb-4{margin-bottom:1rem}.mcms-mb-6{margin-bottom:1.5rem}.mcms-mt-1{margin-top:.25rem}.mcms-flex{display:flex}.mcms-h-12{height:3rem}.mcms-h-3{height:.75rem}.mcms-h-4{height:1rem}.mcms-h-5{height:1.25rem}.mcms-h-8{height:2rem}.mcms-w-12{width:3rem}.mcms-w-3{width:.75rem}.mcms-w-4{width:1rem}.mcms-w-5{width:1.25rem}.mcms-w-8{width:2rem}.mcms-w-full{width:100%}.mcms-shrink-0{flex-shrink:0}@keyframes mcms-spin{to{transform:rotate(1turn)}}.mcms-animate-spin{animation:mcms-spin 1s linear infinite}.mcms-flex-col{flex-direction:column}.mcms-items-center{align-items:center}.mcms-justify-center{justify-content:center}.mcms-justify-between{justify-content:space-between}.mcms-gap-1{gap:.25rem}.mcms-gap-2{gap:.5rem}.mcms-gap-3{gap:.75rem}.mcms-space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.mcms-space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.mcms-overflow-hidden{overflow:hidden}.mcms-break-all{word-break:break-all}.mcms-rounded-2xl{border-radius:1rem}.mcms-rounded-lg{border-radius:.5rem}.mcms-rounded-xl{border-radius:.75rem}.mcms-border{border-width:1px}.mcms-border-t{border-top-width:1px}.mcms-border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity,1))}.mcms-border-red-100{--tw-border-opacity:1;border-color:rgb(254 226 226/var(--tw-border-opacity,1))}.mcms-border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.mcms-border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.mcms-bg-\[\#512da8\]{--tw-bg-opacity:1;background-color:rgb(81 45 168/var(--tw-bg-opacity,1))}.mcms-bg-\[\#f6851b\]{--tw-bg-opacity:1;background-color:rgb(246 133 27/var(--tw-bg-opacity,1))}.mcms-bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.mcms-bg-indigo-50{--tw-bg-opacity:1;background-color:rgb(238 242 255/var(--tw-bg-opacity,1))}.mcms-bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity,1))}.mcms-bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.mcms-bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.mcms-bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.mcms-bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.mcms-bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.mcms-p-2{padding:.5rem}.mcms-p-3{padding:.75rem}.mcms-p-4{padding:1rem}.mcms-p-6{padding:1.5rem}.mcms-px-4{padding-left:1rem;padding-right:1rem}.mcms-px-6{padding-left:1.5rem;padding-right:1.5rem}.mcms-py-3{padding-top:.75rem;padding-bottom:.75rem}.mcms-py-8{padding-top:2rem;padding-bottom:2rem}.mcms-text-center{text-align:center}.mcms-font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.mcms-text-lg{font-size:1.125rem;line-height:1.75rem}.mcms-text-sm{font-size:.875rem;line-height:1.25rem}.mcms-text-xs{font-size:.75rem;line-height:1rem}.mcms-font-bold{font-weight:700}.mcms-font-medium{font-weight:500}.mcms-font-semibold{font-weight:600}.mcms-uppercase{text-transform:uppercase}.mcms-tracking-wider{letter-spacing:.05em}.mcms-text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.mcms-text-green-700{--tw-text-opacity:1;color:rgb(21 128 61/var(--tw-text-opacity,1))}.mcms-text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity,1))}.mcms-text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.mcms-text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.mcms-text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.mcms-text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.mcms-text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.mcms-text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.mcms-shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.mcms-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:mcms-bg-\[\#4527a0\]:hover{--tw-bg-opacity:1;background-color:rgb(69 39 160/var(--tw-bg-opacity,1))}.hover\:mcms-bg-\[\#e2761b\]:hover{--tw-bg-opacity:1;background-color:rgb(226 118 27/var(--tw-bg-opacity,1))}.hover\:mcms-bg-black:hover{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.hover\:mcms-bg-indigo-700:hover{--tw-bg-opacity:1;background-color:rgb(67 56 202/var(--tw-bg-opacity,1))}.hover\:mcms-text-indigo-700:hover{--tw-text-opacity:1;color:rgb(67 56 202/var(--tw-text-opacity,1))}
|
package/dist/index.js
CHANGED
|
@@ -1,351 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
PaymentWidget: () => PaymentWidget,
|
|
24
|
-
useEVMWallet: () => useEVMWallet,
|
|
25
|
-
usePayment: () => usePayment,
|
|
26
|
-
useSolanaWallet: () => useSolanaWallet
|
|
27
|
-
});
|
|
28
|
-
module.exports = __toCommonJS(index_exports);
|
|
29
|
-
var import_react = require("react");
|
|
30
|
-
|
|
31
|
-
// src/providers/SolanaProvider.ts
|
|
32
|
-
var useSolanaWallet = () => {
|
|
33
|
-
const getProvider = () => {
|
|
34
|
-
if ("solana" in window) {
|
|
35
|
-
const anyWindow = window;
|
|
36
|
-
if (anyWindow.solana?.isPhantom) {
|
|
37
|
-
return anyWindow.solana;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return void 0;
|
|
41
|
-
};
|
|
42
|
-
const connect = async () => {
|
|
43
|
-
const provider = getProvider();
|
|
44
|
-
if (provider) {
|
|
45
|
-
try {
|
|
46
|
-
const resp = await provider.connect();
|
|
47
|
-
return resp.publicKey.toString();
|
|
48
|
-
} catch (err) {
|
|
49
|
-
throw new Error("User rejected the connection");
|
|
50
|
-
}
|
|
51
|
-
} else {
|
|
52
|
-
throw new Error("Phantom wallet not found");
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const sendPayment = async (intent) => {
|
|
56
|
-
const provider = getProvider();
|
|
57
|
-
if (!provider) throw new Error("Wallet not connected");
|
|
58
|
-
console.log(`Simulating Solana payment to ${intent.paymentAddress} for ${intent.amount} SOL`);
|
|
59
|
-
return "simulated_solana_signature_" + Math.random().toString(36).slice(2);
|
|
60
|
-
};
|
|
61
|
-
return { isAvailable: !!getProvider(), connect, sendPayment };
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// src/providers/EVMProvider.ts
|
|
65
|
-
var useEVMWallet = () => {
|
|
66
|
-
const getProvider = () => {
|
|
67
|
-
if (typeof window !== "undefined" && "ethereum" in window) {
|
|
68
|
-
return window.ethereum;
|
|
69
|
-
}
|
|
70
|
-
return void 0;
|
|
71
|
-
};
|
|
72
|
-
const connect = async () => {
|
|
73
|
-
const provider = getProvider();
|
|
74
|
-
if (provider) {
|
|
75
|
-
try {
|
|
76
|
-
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
77
|
-
return accounts[0];
|
|
78
|
-
} catch (err) {
|
|
79
|
-
throw new Error("User rejected the connection");
|
|
80
|
-
}
|
|
81
|
-
} else {
|
|
82
|
-
throw new Error("MetaMask or EVM wallet not found");
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
const sendPayment = async (intent) => {
|
|
86
|
-
const provider = getProvider();
|
|
87
|
-
if (!provider) throw new Error("Wallet not connected");
|
|
88
|
-
console.log(`Simulating EVM payment to ${intent.paymentAddress} for ${intent.amount} ${intent.currency}`);
|
|
89
|
-
return "simulated_evm_tx_hash_" + Math.random().toString(36).slice(2);
|
|
90
|
-
};
|
|
91
|
-
return { isAvailable: !!getProvider(), connect, sendPayment };
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// src/PaymentWidget.tsx
|
|
95
|
-
var import_lucide_react = require("lucide-react");
|
|
96
|
-
var import_clsx = require("clsx");
|
|
97
|
-
var import_tailwind_merge = require("tailwind-merge");
|
|
98
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
99
|
-
function cn(...inputs) {
|
|
100
|
-
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
101
|
-
}
|
|
102
|
-
var PaymentWidget = ({
|
|
103
|
-
className,
|
|
104
|
-
...props
|
|
105
|
-
}) => {
|
|
106
|
-
const {
|
|
107
|
-
status,
|
|
108
|
-
intent,
|
|
109
|
-
error,
|
|
110
|
-
initiate,
|
|
111
|
-
verify,
|
|
112
|
-
setStatus,
|
|
113
|
-
isSolanaAvailable,
|
|
114
|
-
handleSolanaPay,
|
|
115
|
-
isEVMAvailable,
|
|
116
|
-
handleEVMPay
|
|
117
|
-
} = usePayment(props);
|
|
118
|
-
if (status === "success") {
|
|
119
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("p-6 text-center bg-green-50 rounded-xl border border-green-200", className), children: [
|
|
120
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle, { className: "mx-auto w-12 h-12 text-green-500 mb-4" }),
|
|
121
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "text-lg font-semibold text-green-900", children: "Payment Successful" }),
|
|
122
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-green-700 mt-1", children: "Your order has been confirmed." })
|
|
123
|
-
] });
|
|
124
|
-
}
|
|
125
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("bg-white rounded-2xl border border-slate-200 shadow-sm overflow-hidden", className), children: [
|
|
126
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-6", children: [
|
|
127
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 mb-6", children: [
|
|
128
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-2 bg-indigo-50 rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Wallet, { className: "w-5 h-5 text-indigo-600" }) }),
|
|
129
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
130
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "font-semibold text-slate-900", children: "Crypto Payment" }),
|
|
131
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-slate-500", children: "Pay securely using your wallet" })
|
|
132
|
-
] })
|
|
133
|
-
] }),
|
|
134
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-4 p-3 bg-red-50 border border-red-100 rounded-lg flex gap-3 text-red-700 text-sm", children: [
|
|
135
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircle, { className: "w-4 h-4 shrink-0" }),
|
|
136
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: error })
|
|
137
|
-
] }),
|
|
138
|
-
status === "idle" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
139
|
-
"button",
|
|
140
|
-
{
|
|
141
|
-
onClick: initiate,
|
|
142
|
-
className: "w-full py-3 px-4 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
143
|
-
children: "Start Payment"
|
|
144
|
-
}
|
|
145
|
-
),
|
|
146
|
-
(status === "connecting" || status === "initiating" || status === "verifying") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-8 text-center", children: [
|
|
147
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "w-8 h-8 text-indigo-600 animate-spin mx-auto mb-3" }),
|
|
148
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-slate-600 font-medium", children: status === "connecting" ? "Connecting wallet..." : status === "initiating" ? "Preparing transaction..." : "Verifying on-chain..." })
|
|
149
|
-
] }),
|
|
150
|
-
status === "pending_signature" && intent && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4", children: [
|
|
151
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-4 bg-slate-50 rounded-xl space-y-2", children: [
|
|
152
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-sm", children: [
|
|
153
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-slate-500", children: "Amount to pay" }),
|
|
154
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-mono font-medium text-slate-900", children: [
|
|
155
|
-
intent.amount,
|
|
156
|
-
" ",
|
|
157
|
-
intent.currency
|
|
158
|
-
] })
|
|
159
|
-
] }),
|
|
160
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-sm", children: [
|
|
161
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-slate-500", children: "Network" }),
|
|
162
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-slate-900 font-medium", children: intent.network })
|
|
163
|
-
] })
|
|
164
|
-
] }),
|
|
165
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
|
|
166
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-slate-500 uppercase font-bold tracking-wider", children: "Destination Address" }),
|
|
167
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-3 bg-slate-100 rounded-lg font-mono text-xs break-all text-slate-600 border border-slate-200", children: intent.paymentAddress })
|
|
168
|
-
] }),
|
|
169
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2", children: intent.network.toLowerCase().includes("solana") && isSolanaAvailable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
170
|
-
"button",
|
|
171
|
-
{
|
|
172
|
-
onClick: handleSolanaPay,
|
|
173
|
-
className: "w-full py-3 px-4 bg-[#512da8] hover:bg-[#4527a0] text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
174
|
-
children: [
|
|
175
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Cpu, { className: "w-4 h-4" }),
|
|
176
|
-
"Pay with Phantom"
|
|
177
|
-
]
|
|
178
|
-
}
|
|
179
|
-
) : (intent.network.toLowerCase().includes("ethereum") || intent.network.toLowerCase().includes("evm") || intent.network.toLowerCase().includes("polygon")) && isEVMAvailable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
180
|
-
"button",
|
|
181
|
-
{
|
|
182
|
-
onClick: handleEVMPay,
|
|
183
|
-
className: "w-full py-3 px-4 bg-[#f6851b] hover:bg-[#e2761b] text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
184
|
-
children: [
|
|
185
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: "https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Mirror_Logo.svg", className: "w-4 h-4", alt: "MetaMask" }),
|
|
186
|
-
"Pay with MetaMask"
|
|
187
|
-
]
|
|
188
|
-
}
|
|
189
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
190
|
-
"button",
|
|
191
|
-
{
|
|
192
|
-
onClick: () => {
|
|
193
|
-
setStatus("verifying");
|
|
194
|
-
setTimeout(() => verify("0x_mock_transaction_hash_generic"), 2e3);
|
|
195
|
-
},
|
|
196
|
-
className: "w-full py-3 px-4 bg-slate-900 hover:bg-black text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
197
|
-
children: "Confirm in Wallet"
|
|
198
|
-
}
|
|
199
|
-
) })
|
|
200
|
-
] })
|
|
201
|
-
] }),
|
|
202
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bg-slate-50 px-6 py-3 border-t border-slate-100 flex justify-between items-center", children: [
|
|
203
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-slate-400", children: "Powered by Micro-CMS Crypto" }),
|
|
204
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: "#", className: "text-xs text-indigo-600 hover:text-indigo-700 font-medium flex items-center gap-1", children: [
|
|
205
|
-
"Help ",
|
|
206
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "w-3 h-3" })
|
|
207
|
-
] })
|
|
208
|
-
] })
|
|
209
|
-
] });
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// src/index.ts
|
|
213
|
-
var usePayment = (props) => {
|
|
214
|
-
const [status, setStatus] = (0, import_react.useState)("idle");
|
|
215
|
-
const [error, setError] = (0, import_react.useState)(null);
|
|
216
|
-
const [intent, setIntent] = (0, import_react.useState)(null);
|
|
217
|
-
const initiate = (0, import_react.useCallback)(async () => {
|
|
218
|
-
try {
|
|
219
|
-
setStatus("initiating");
|
|
220
|
-
setError(null);
|
|
221
|
-
if (props.provider) {
|
|
222
|
-
const data2 = await props.provider.initiatePayment(props.orderId, {
|
|
223
|
-
amount: props.amount,
|
|
224
|
-
currency: props.currency
|
|
225
|
-
});
|
|
226
|
-
setIntent(data2);
|
|
227
|
-
setStatus("pending_signature");
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const response = await fetch(props.endpoints?.initiate || "/api/orders/initiate", {
|
|
231
|
-
method: "POST",
|
|
232
|
-
headers: { "Content-Type": "application/json" },
|
|
233
|
-
body: JSON.stringify({
|
|
234
|
-
orderId: props.orderId,
|
|
235
|
-
amount: props.amount,
|
|
236
|
-
currency: props.currency
|
|
237
|
-
})
|
|
238
|
-
});
|
|
239
|
-
if (!response.ok) {
|
|
240
|
-
const errorData = await response.json();
|
|
241
|
-
throw new Error(errorData.error || "Failed to initiate payment intent");
|
|
242
|
-
}
|
|
243
|
-
const data = await response.json();
|
|
244
|
-
setIntent(data);
|
|
245
|
-
setStatus("pending_signature");
|
|
246
|
-
} catch (err) {
|
|
247
|
-
setError(err.message);
|
|
248
|
-
setStatus("error");
|
|
249
|
-
props.onError?.(err);
|
|
250
|
-
}
|
|
251
|
-
}, [props.provider, props.endpoints?.initiate, props.orderId, props.amount, props.currency, props.onError]);
|
|
252
|
-
const verify = (0, import_react.useCallback)(async (txHash) => {
|
|
253
|
-
try {
|
|
254
|
-
setStatus("verifying");
|
|
255
|
-
if (props.provider) {
|
|
256
|
-
const data2 = await props.provider.verifyPayment(txHash, props.orderId);
|
|
257
|
-
if (data2.status === "confirmed") {
|
|
258
|
-
setStatus("success");
|
|
259
|
-
props.onSuccess?.(data2);
|
|
260
|
-
} else {
|
|
261
|
-
throw new Error("Payment not confirmed yet, status: " + data2.status);
|
|
262
|
-
}
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
const response = await fetch(props.endpoints?.verify || "/api/orders/verify-payment", {
|
|
266
|
-
method: "POST",
|
|
267
|
-
headers: { "Content-Type": "application/json" },
|
|
268
|
-
body: JSON.stringify({
|
|
269
|
-
orderId: props.orderId,
|
|
270
|
-
transactionHash: txHash
|
|
271
|
-
})
|
|
272
|
-
});
|
|
273
|
-
if (!response.ok) {
|
|
274
|
-
const errorData = await response.json();
|
|
275
|
-
throw new Error(errorData.error || "Payment verification failed");
|
|
276
|
-
}
|
|
277
|
-
const data = await response.json();
|
|
278
|
-
if (data.status === "confirmed") {
|
|
279
|
-
setStatus("success");
|
|
280
|
-
props.onSuccess?.(data);
|
|
281
|
-
} else {
|
|
282
|
-
throw new Error("Payment not confirmed yet, status: " + data.status);
|
|
283
|
-
}
|
|
284
|
-
} catch (err) {
|
|
285
|
-
setError(err.message);
|
|
286
|
-
setStatus("error");
|
|
287
|
-
props.onError?.(err);
|
|
288
|
-
}
|
|
289
|
-
}, [props.provider, props.endpoints?.verify, props.orderId, props.onSuccess, props.onError]);
|
|
290
|
-
const { isAvailable: isSolanaAvailable, connect: connectSolana, sendPayment: sendSolanaPayment } = useSolanaWallet();
|
|
291
|
-
const handleSolanaPay = async () => {
|
|
292
|
-
try {
|
|
293
|
-
if (!intent) {
|
|
294
|
-
setError("Payment intent not established.");
|
|
295
|
-
setStatus("error");
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
setStatus("connecting");
|
|
299
|
-
const publicKey = await connectSolana();
|
|
300
|
-
console.log("Connected to Solana with public key:", publicKey);
|
|
301
|
-
setStatus("pending_signature");
|
|
302
|
-
const signature = await sendSolanaPayment(intent);
|
|
303
|
-
setStatus("verifying");
|
|
304
|
-
await verify(signature);
|
|
305
|
-
} catch (err) {
|
|
306
|
-
setError(err.message || "Failed to connect to Phantom or sign transaction.");
|
|
307
|
-
setStatus("error");
|
|
308
|
-
props.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
const { isAvailable: isEVMAvailable, connect: connectEVM, sendPayment: sendEVMPayment } = useEVMWallet();
|
|
312
|
-
const handleEVMPay = async () => {
|
|
313
|
-
try {
|
|
314
|
-
if (!intent) {
|
|
315
|
-
setError("Payment intent not established.");
|
|
316
|
-
setStatus("error");
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
setStatus("connecting");
|
|
320
|
-
const account = await connectEVM();
|
|
321
|
-
console.log("Connected to EVM with account:", account);
|
|
322
|
-
setStatus("pending_signature");
|
|
323
|
-
const txHash = await sendEVMPayment(intent);
|
|
324
|
-
setStatus("verifying");
|
|
325
|
-
await verify(txHash);
|
|
326
|
-
} catch (err) {
|
|
327
|
-
setError(err.message || "Failed to connect to MetaMask or sign transaction.");
|
|
328
|
-
setStatus("error");
|
|
329
|
-
props.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
return {
|
|
333
|
-
status,
|
|
334
|
-
intent,
|
|
335
|
-
error,
|
|
336
|
-
initiate,
|
|
337
|
-
verify,
|
|
338
|
-
setStatus,
|
|
339
|
-
isSolanaAvailable,
|
|
340
|
-
handleSolanaPay,
|
|
341
|
-
isEVMAvailable,
|
|
342
|
-
handleEVMPay
|
|
343
|
-
};
|
|
344
|
-
};
|
|
345
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
346
|
-
0 && (module.exports = {
|
|
347
|
-
PaymentWidget,
|
|
348
|
-
useEVMWallet,
|
|
349
|
-
usePayment,
|
|
350
|
-
useSolanaWallet
|
|
351
|
-
});
|
|
1
|
+
"use strict";var v=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var A=(e,r)=>{for(var t in r)v(e,t,{get:r[t],enumerable:!0})},T=(e,r,t,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of V(r))!j.call(e,a)&&a!==t&&v(e,a,{get:()=>r[a],enumerable:!(s=_(r,a))||s.enumerable});return e};var L=e=>T(v({},"__esModule",{value:!0}),e);var O={};A(O,{PaymentWidget:()=>q,useEVMWallet:()=>b,usePayment:()=>N,useSolanaWallet:()=>x});module.exports=L(O);var l=require("react");var x=()=>{let e=()=>{if("solana"in window){let s=window;if(s.solana?.isPhantom)return s.solana}},r=async()=>{let s=e();if(s)try{return(await s.connect()).publicKey.toString()}catch{throw new Error("User rejected the connection")}else throw new Error("Phantom wallet not found")},t=async s=>{if(!e())throw new Error("Wallet not connected");return console.log(`Simulating Solana payment to ${s.paymentAddress} for ${s.amount} SOL`),"simulated_solana_signature_"+Math.random().toString(36).slice(2)};return{isAvailable:!!e(),connect:r,sendPayment:t}};var b=()=>{let e=()=>{if(typeof window<"u"&&"ethereum"in window)return window.ethereum},r=async()=>{let s=e();if(s)try{return(await s.request({method:"eth_requestAccounts"}))[0]}catch{throw new Error("User rejected the connection")}else throw new Error("MetaMask or EVM wallet not found")},t=async s=>{if(!e())throw new Error("Wallet not connected");return console.log(`Simulating EVM payment to ${s.paymentAddress} for ${s.amount} ${s.currency}`),"simulated_evm_tx_hash_"+Math.random().toString(36).slice(2)};return{isAvailable:!!e(),connect:r,sendPayment:t}};function P(e,{insertAt:r}={}){if(!e||typeof document>"u")return;let t=document.head||document.getElementsByTagName("head")[0],s=document.createElement("style");s.type="text/css",r==="top"&&t.firstChild?t.insertBefore(s,t.firstChild):t.appendChild(s),s.styleSheet?s.styleSheet.cssText=e:s.appendChild(document.createTextNode(e))}P(`@tailwind base;@tailwind components;@tailwind utilities;
|
|
2
|
+
`);var c=require("lucide-react"),S=require("clsx"),k=require("tailwind-merge");var n=require("react/jsx-runtime");function E(...e){return(0,k.twMerge)((0,S.clsx)(e))}var q=({className:e,...r})=>{let{status:t,intent:s,error:a,initiate:i,verify:f,setStatus:g,isSolanaAvailable:u,handleSolanaPay:w,isEVMAvailable:h,handleEVMPay:p}=N(r);return t==="success"?(0,n.jsxs)("div",{className:E("mcms-p-6 mcms-text-center mcms-bg-green-50 mcms-rounded-xl mcms-border mcms-border-green-200",e),children:[(0,n.jsx)(c.CheckCircle,{className:"mcms-mx-auto mcms-w-12 mcms-h-12 mcms-text-green-500 mcms-mb-4"}),(0,n.jsx)("h3",{className:"mcms-text-lg mcms-font-semibold mcms-green-900",children:"Payment Successful"}),(0,n.jsx)("p",{className:"mcms-text-green-700 mcms-mt-1",children:"Your order has been confirmed."})]}):(0,n.jsxs)("div",{className:E("mcms-bg-white mcms-rounded-2xl mcms-border mcms-border-slate-200 mcms-shadow-sm mcms-overflow-hidden",e),children:[(0,n.jsxs)("div",{className:"mcms-p-6",children:[(0,n.jsxs)("div",{className:"mcms-flex mcms-items-center mcms-gap-3 mcms-mb-6",children:[(0,n.jsx)("div",{className:"mcms-p-2 mcms-bg-indigo-50 mcms-rounded-lg",children:(0,n.jsx)(c.Wallet,{className:"mcms-w-5 mcms-h-5 mcms-text-indigo-600"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"mcms-font-semibold mcms-text-slate-900",children:"Crypto Payment"}),(0,n.jsx)("p",{className:"mcms-text-sm mcms-text-slate-500",children:"Pay securely using your wallet"})]})]}),a&&(0,n.jsxs)("div",{className:"mcms-mb-4 mcms-p-3 mcms-bg-red-50 mcms-border mcms-border-red-100 mcms-rounded-lg mcms-flex mcms-gap-3 mcms-text-red-700 mcms-text-sm",children:[(0,n.jsx)(c.AlertCircle,{className:"mcms-w-4 mcms-h-4 mcms-shrink-0"}),(0,n.jsx)("p",{children:a})]}),t==="idle"&&(0,n.jsx)("button",{onClick:i,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-indigo-600 hover:mcms-bg-indigo-700 mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:"Start Payment"}),(t==="connecting"||t==="initiating"||t==="verifying")&&(0,n.jsxs)("div",{className:"mcms-py-8 mcms-text-center",children:[(0,n.jsx)(c.Loader2,{className:"mcms-w-8 mcms-h-8 mcms-text-indigo-600 mcms-animate-spin mcms-mx-auto mcms-mb-3"}),(0,n.jsx)("p",{className:"mcms-text-slate-600 mcms-font-medium",children:t==="connecting"?"Connecting wallet...":t==="initiating"?"Preparing transaction...":"Verifying on-chain..."})]}),t==="pending_signature"&&s&&(0,n.jsxs)("div",{className:"mcms-space-y-4",children:[(0,n.jsxs)("div",{className:"mcms-p-4 mcms-bg-slate-50 mcms-rounded-xl mcms-space-y-2",children:[(0,n.jsxs)("div",{className:"mcms-flex mcms-justify-between mcms-text-sm",children:[(0,n.jsx)("span",{className:"mcms-text-slate-500",children:"Amount to pay"}),(0,n.jsxs)("span",{className:"mcms-font-mono mcms-font-medium mcms-text-slate-900",children:[s.amount," ",s.currency]})]}),(0,n.jsxs)("div",{className:"mcms-flex mcms-justify-between mcms-text-sm",children:[(0,n.jsx)("span",{className:"mcms-text-slate-500",children:"Network"}),(0,n.jsx)("span",{className:"mcms-text-slate-900 mcms-font-medium",children:s.network})]})]}),(0,n.jsxs)("div",{className:"mcms-space-y-2",children:[(0,n.jsx)("p",{className:"mcms-text-xs mcms-text-slate-500 mcms-uppercase mcms-font-bold mcms-tracking-wider",children:"Destination Address"}),(0,n.jsx)("div",{className:"mcms-p-3 mcms-bg-slate-100 mcms-rounded-lg mcms-font-mono mcms-text-xs mcms-break-all mcms-text-slate-600 mcms-border mcms-border-slate-200",children:s.paymentAddress})]}),(0,n.jsx)("div",{className:"mcms-flex mcms-flex-col mcms-gap-2",children:s.network.toLowerCase().includes("solana")&&u?(0,n.jsxs)("button",{onClick:w,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-[#512da8] hover:mcms-bg-[#4527a0] mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:[(0,n.jsx)(c.Cpu,{className:"mcms-w-4 mcms-h-4"}),"Pay with Phantom"]}):(s.network.toLowerCase().includes("ethereum")||s.network.toLowerCase().includes("evm")||s.network.toLowerCase().includes("polygon"))&&h?(0,n.jsxs)("button",{onClick:p,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-[#f6851b] hover:mcms-bg-[#e2761b] mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:[(0,n.jsx)("img",{src:"https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Mirror_Logo.svg",className:"mcms-w-4 mcms-h-4",alt:"MetaMask"}),"Pay with MetaMask"]}):(0,n.jsx)("button",{onClick:()=>{g("verifying"),setTimeout(()=>f("0x_mock_transaction_hash_generic"),2e3)},className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-slate-900 hover:mcms-bg-black mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:"Confirm in Wallet"})})]})]}),(0,n.jsxs)("div",{className:"mcms-bg-slate-50 mcms-px-6 mcms-py-3 mcms-border-t mcms-border-slate-100 mcms-flex mcms-justify-between mcms-items-center",children:[(0,n.jsx)("span",{className:"mcms-text-xs mcms-text-slate-400",children:"Powered by Micro-CMS Crypto"}),(0,n.jsxs)("a",{href:"#",className:"mcms-text-xs mcms-text-indigo-600 hover:mcms-text-indigo-700 mcms-font-medium mcms-flex mcms-items-center mcms-gap-1",children:["Help ",(0,n.jsx)(c.ExternalLink,{className:"mcms-w-3 mcms-h-3"})]})]})]})};var N=e=>{let[r,t]=(0,l.useState)("idle"),[s,a]=(0,l.useState)(null),[i,f]=(0,l.useState)(null),g=(0,l.useCallback)(async()=>{try{if(t("initiating"),a(null),e.provider){let d=await e.provider.initiatePayment(e.orderId,{amount:e.amount,currency:e.currency});f(d),t("pending_signature");return}let m=await fetch(e.endpoints?.initiate||"/api/orders/initiate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({orderId:e.orderId,amount:e.amount,currency:e.currency})});if(!m.ok){let d=await m.json();throw new Error(d.error||"Failed to initiate payment intent")}let o=await m.json();f(o),t("pending_signature")}catch(m){a(m.message),t("error"),e.onError?.(m)}},[e.provider,e.endpoints?.initiate,e.orderId,e.amount,e.currency,e.onError]),u=(0,l.useCallback)(async m=>{try{if(t("verifying"),e.provider){let y=await e.provider.verifyPayment(m,e.orderId);if(y.status==="confirmed")t("success"),e.onSuccess?.(y);else throw new Error("Payment not confirmed yet, status: "+y.status);return}let o=await fetch(e.endpoints?.verify||"/api/orders/verify-payment",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({orderId:e.orderId,transactionHash:m})});if(!o.ok){let y=await o.json();throw new Error(y.error||"Payment verification failed")}let d=await o.json();if(d.status==="confirmed")t("success"),e.onSuccess?.(d);else throw new Error("Payment not confirmed yet, status: "+d.status)}catch(o){a(o.message),t("error"),e.onError?.(o)}},[e.provider,e.endpoints?.verify,e.orderId,e.onSuccess,e.onError]),{isAvailable:w,connect:h,sendPayment:p}=x(),C=async()=>{try{if(!i){a("Payment intent not established."),t("error");return}t("connecting");let m=await h();console.log("Connected to Solana with public key:",m),t("pending_signature");let o=await p(i);t("verifying"),await u(o)}catch(m){a(m.message||"Failed to connect to Phantom or sign transaction."),t("error"),e.onError?.(m instanceof Error?m:new Error(String(m)))}},{isAvailable:M,connect:W,sendPayment:I}=b();return{status:r,intent:i,error:s,initiate:g,verify:u,setStatus:t,isSolanaAvailable:w,handleSolanaPay:C,isEVMAvailable:M,handleEVMPay:async()=>{try{if(!i){a("Payment intent not established."),t("error");return}t("connecting");let m=await W();console.log("Connected to EVM with account:",m),t("pending_signature");let o=await I(i);t("verifying"),await u(o)}catch(m){a(m.message||"Failed to connect to MetaMask or sign transaction."),t("error"),e.onError?.(m instanceof Error?m:new Error(String(m)))}}}};0&&(module.exports={PaymentWidget,useEVMWallet,usePayment,useSolanaWallet});
|
package/dist/index.mjs
CHANGED
|
@@ -1,323 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
// src/providers/SolanaProvider.ts
|
|
5
|
-
var useSolanaWallet = () => {
|
|
6
|
-
const getProvider = () => {
|
|
7
|
-
if ("solana" in window) {
|
|
8
|
-
const anyWindow = window;
|
|
9
|
-
if (anyWindow.solana?.isPhantom) {
|
|
10
|
-
return anyWindow.solana;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return void 0;
|
|
14
|
-
};
|
|
15
|
-
const connect = async () => {
|
|
16
|
-
const provider = getProvider();
|
|
17
|
-
if (provider) {
|
|
18
|
-
try {
|
|
19
|
-
const resp = await provider.connect();
|
|
20
|
-
return resp.publicKey.toString();
|
|
21
|
-
} catch (err) {
|
|
22
|
-
throw new Error("User rejected the connection");
|
|
23
|
-
}
|
|
24
|
-
} else {
|
|
25
|
-
throw new Error("Phantom wallet not found");
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const sendPayment = async (intent) => {
|
|
29
|
-
const provider = getProvider();
|
|
30
|
-
if (!provider) throw new Error("Wallet not connected");
|
|
31
|
-
console.log(`Simulating Solana payment to ${intent.paymentAddress} for ${intent.amount} SOL`);
|
|
32
|
-
return "simulated_solana_signature_" + Math.random().toString(36).slice(2);
|
|
33
|
-
};
|
|
34
|
-
return { isAvailable: !!getProvider(), connect, sendPayment };
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// src/providers/EVMProvider.ts
|
|
38
|
-
var useEVMWallet = () => {
|
|
39
|
-
const getProvider = () => {
|
|
40
|
-
if (typeof window !== "undefined" && "ethereum" in window) {
|
|
41
|
-
return window.ethereum;
|
|
42
|
-
}
|
|
43
|
-
return void 0;
|
|
44
|
-
};
|
|
45
|
-
const connect = async () => {
|
|
46
|
-
const provider = getProvider();
|
|
47
|
-
if (provider) {
|
|
48
|
-
try {
|
|
49
|
-
const accounts = await provider.request({ method: "eth_requestAccounts" });
|
|
50
|
-
return accounts[0];
|
|
51
|
-
} catch (err) {
|
|
52
|
-
throw new Error("User rejected the connection");
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
throw new Error("MetaMask or EVM wallet not found");
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const sendPayment = async (intent) => {
|
|
59
|
-
const provider = getProvider();
|
|
60
|
-
if (!provider) throw new Error("Wallet not connected");
|
|
61
|
-
console.log(`Simulating EVM payment to ${intent.paymentAddress} for ${intent.amount} ${intent.currency}`);
|
|
62
|
-
return "simulated_evm_tx_hash_" + Math.random().toString(36).slice(2);
|
|
63
|
-
};
|
|
64
|
-
return { isAvailable: !!getProvider(), connect, sendPayment };
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// src/PaymentWidget.tsx
|
|
68
|
-
import { Wallet, CheckCircle, Loader2, AlertCircle, ExternalLink, Cpu } from "lucide-react";
|
|
69
|
-
import { clsx } from "clsx";
|
|
70
|
-
import { twMerge } from "tailwind-merge";
|
|
71
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
72
|
-
function cn(...inputs) {
|
|
73
|
-
return twMerge(clsx(inputs));
|
|
74
|
-
}
|
|
75
|
-
var PaymentWidget = ({
|
|
76
|
-
className,
|
|
77
|
-
...props
|
|
78
|
-
}) => {
|
|
79
|
-
const {
|
|
80
|
-
status,
|
|
81
|
-
intent,
|
|
82
|
-
error,
|
|
83
|
-
initiate,
|
|
84
|
-
verify,
|
|
85
|
-
setStatus,
|
|
86
|
-
isSolanaAvailable,
|
|
87
|
-
handleSolanaPay,
|
|
88
|
-
isEVMAvailable,
|
|
89
|
-
handleEVMPay
|
|
90
|
-
} = usePayment(props);
|
|
91
|
-
if (status === "success") {
|
|
92
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-center bg-green-50 rounded-xl border border-green-200", className), children: [
|
|
93
|
-
/* @__PURE__ */ jsx(CheckCircle, { className: "mx-auto w-12 h-12 text-green-500 mb-4" }),
|
|
94
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-green-900", children: "Payment Successful" }),
|
|
95
|
-
/* @__PURE__ */ jsx("p", { className: "text-green-700 mt-1", children: "Your order has been confirmed." })
|
|
96
|
-
] });
|
|
97
|
-
}
|
|
98
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("bg-white rounded-2xl border border-slate-200 shadow-sm overflow-hidden", className), children: [
|
|
99
|
-
/* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
100
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-6", children: [
|
|
101
|
-
/* @__PURE__ */ jsx("div", { className: "p-2 bg-indigo-50 rounded-lg", children: /* @__PURE__ */ jsx(Wallet, { className: "w-5 h-5 text-indigo-600" }) }),
|
|
102
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
103
|
-
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-slate-900", children: "Crypto Payment" }),
|
|
104
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Pay securely using your wallet" })
|
|
105
|
-
] })
|
|
106
|
-
] }),
|
|
107
|
-
error && /* @__PURE__ */ jsxs("div", { className: "mb-4 p-3 bg-red-50 border border-red-100 rounded-lg flex gap-3 text-red-700 text-sm", children: [
|
|
108
|
-
/* @__PURE__ */ jsx(AlertCircle, { className: "w-4 h-4 shrink-0" }),
|
|
109
|
-
/* @__PURE__ */ jsx("p", { children: error })
|
|
110
|
-
] }),
|
|
111
|
-
status === "idle" && /* @__PURE__ */ jsx(
|
|
112
|
-
"button",
|
|
113
|
-
{
|
|
114
|
-
onClick: initiate,
|
|
115
|
-
className: "w-full py-3 px-4 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
116
|
-
children: "Start Payment"
|
|
117
|
-
}
|
|
118
|
-
),
|
|
119
|
-
(status === "connecting" || status === "initiating" || status === "verifying") && /* @__PURE__ */ jsxs("div", { className: "py-8 text-center", children: [
|
|
120
|
-
/* @__PURE__ */ jsx(Loader2, { className: "w-8 h-8 text-indigo-600 animate-spin mx-auto mb-3" }),
|
|
121
|
-
/* @__PURE__ */ jsx("p", { className: "text-slate-600 font-medium", children: status === "connecting" ? "Connecting wallet..." : status === "initiating" ? "Preparing transaction..." : "Verifying on-chain..." })
|
|
122
|
-
] }),
|
|
123
|
-
status === "pending_signature" && intent && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
124
|
-
/* @__PURE__ */ jsxs("div", { className: "p-4 bg-slate-50 rounded-xl space-y-2", children: [
|
|
125
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
126
|
-
/* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Amount to pay" }),
|
|
127
|
-
/* @__PURE__ */ jsxs("span", { className: "font-mono font-medium text-slate-900", children: [
|
|
128
|
-
intent.amount,
|
|
129
|
-
" ",
|
|
130
|
-
intent.currency
|
|
131
|
-
] })
|
|
132
|
-
] }),
|
|
133
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
|
|
134
|
-
/* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Network" }),
|
|
135
|
-
/* @__PURE__ */ jsx("span", { className: "text-slate-900 font-medium", children: intent.network })
|
|
136
|
-
] })
|
|
137
|
-
] }),
|
|
138
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
139
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500 uppercase font-bold tracking-wider", children: "Destination Address" }),
|
|
140
|
-
/* @__PURE__ */ jsx("div", { className: "p-3 bg-slate-100 rounded-lg font-mono text-xs break-all text-slate-600 border border-slate-200", children: intent.paymentAddress })
|
|
141
|
-
] }),
|
|
142
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: intent.network.toLowerCase().includes("solana") && isSolanaAvailable ? /* @__PURE__ */ jsxs(
|
|
143
|
-
"button",
|
|
144
|
-
{
|
|
145
|
-
onClick: handleSolanaPay,
|
|
146
|
-
className: "w-full py-3 px-4 bg-[#512da8] hover:bg-[#4527a0] text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
147
|
-
children: [
|
|
148
|
-
/* @__PURE__ */ jsx(Cpu, { className: "w-4 h-4" }),
|
|
149
|
-
"Pay with Phantom"
|
|
150
|
-
]
|
|
151
|
-
}
|
|
152
|
-
) : (intent.network.toLowerCase().includes("ethereum") || intent.network.toLowerCase().includes("evm") || intent.network.toLowerCase().includes("polygon")) && isEVMAvailable ? /* @__PURE__ */ jsxs(
|
|
153
|
-
"button",
|
|
154
|
-
{
|
|
155
|
-
onClick: handleEVMPay,
|
|
156
|
-
className: "w-full py-3 px-4 bg-[#f6851b] hover:bg-[#e2761b] text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
157
|
-
children: [
|
|
158
|
-
/* @__PURE__ */ jsx("img", { src: "https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Mirror_Logo.svg", className: "w-4 h-4", alt: "MetaMask" }),
|
|
159
|
-
"Pay with MetaMask"
|
|
160
|
-
]
|
|
161
|
-
}
|
|
162
|
-
) : /* @__PURE__ */ jsx(
|
|
163
|
-
"button",
|
|
164
|
-
{
|
|
165
|
-
onClick: () => {
|
|
166
|
-
setStatus("verifying");
|
|
167
|
-
setTimeout(() => verify("0x_mock_transaction_hash_generic"), 2e3);
|
|
168
|
-
},
|
|
169
|
-
className: "w-full py-3 px-4 bg-slate-900 hover:bg-black text-white font-medium rounded-xl transition-colors flex items-center justify-center gap-2",
|
|
170
|
-
children: "Confirm in Wallet"
|
|
171
|
-
}
|
|
172
|
-
) })
|
|
173
|
-
] })
|
|
174
|
-
] }),
|
|
175
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-slate-50 px-6 py-3 border-t border-slate-100 flex justify-between items-center", children: [
|
|
176
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-slate-400", children: "Powered by Micro-CMS Crypto" }),
|
|
177
|
-
/* @__PURE__ */ jsxs("a", { href: "#", className: "text-xs text-indigo-600 hover:text-indigo-700 font-medium flex items-center gap-1", children: [
|
|
178
|
-
"Help ",
|
|
179
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "w-3 h-3" })
|
|
180
|
-
] })
|
|
181
|
-
] })
|
|
182
|
-
] });
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
// src/index.ts
|
|
186
|
-
var usePayment = (props) => {
|
|
187
|
-
const [status, setStatus] = useState("idle");
|
|
188
|
-
const [error, setError] = useState(null);
|
|
189
|
-
const [intent, setIntent] = useState(null);
|
|
190
|
-
const initiate = useCallback(async () => {
|
|
191
|
-
try {
|
|
192
|
-
setStatus("initiating");
|
|
193
|
-
setError(null);
|
|
194
|
-
if (props.provider) {
|
|
195
|
-
const data2 = await props.provider.initiatePayment(props.orderId, {
|
|
196
|
-
amount: props.amount,
|
|
197
|
-
currency: props.currency
|
|
198
|
-
});
|
|
199
|
-
setIntent(data2);
|
|
200
|
-
setStatus("pending_signature");
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const response = await fetch(props.endpoints?.initiate || "/api/orders/initiate", {
|
|
204
|
-
method: "POST",
|
|
205
|
-
headers: { "Content-Type": "application/json" },
|
|
206
|
-
body: JSON.stringify({
|
|
207
|
-
orderId: props.orderId,
|
|
208
|
-
amount: props.amount,
|
|
209
|
-
currency: props.currency
|
|
210
|
-
})
|
|
211
|
-
});
|
|
212
|
-
if (!response.ok) {
|
|
213
|
-
const errorData = await response.json();
|
|
214
|
-
throw new Error(errorData.error || "Failed to initiate payment intent");
|
|
215
|
-
}
|
|
216
|
-
const data = await response.json();
|
|
217
|
-
setIntent(data);
|
|
218
|
-
setStatus("pending_signature");
|
|
219
|
-
} catch (err) {
|
|
220
|
-
setError(err.message);
|
|
221
|
-
setStatus("error");
|
|
222
|
-
props.onError?.(err);
|
|
223
|
-
}
|
|
224
|
-
}, [props.provider, props.endpoints?.initiate, props.orderId, props.amount, props.currency, props.onError]);
|
|
225
|
-
const verify = useCallback(async (txHash) => {
|
|
226
|
-
try {
|
|
227
|
-
setStatus("verifying");
|
|
228
|
-
if (props.provider) {
|
|
229
|
-
const data2 = await props.provider.verifyPayment(txHash, props.orderId);
|
|
230
|
-
if (data2.status === "confirmed") {
|
|
231
|
-
setStatus("success");
|
|
232
|
-
props.onSuccess?.(data2);
|
|
233
|
-
} else {
|
|
234
|
-
throw new Error("Payment not confirmed yet, status: " + data2.status);
|
|
235
|
-
}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
const response = await fetch(props.endpoints?.verify || "/api/orders/verify-payment", {
|
|
239
|
-
method: "POST",
|
|
240
|
-
headers: { "Content-Type": "application/json" },
|
|
241
|
-
body: JSON.stringify({
|
|
242
|
-
orderId: props.orderId,
|
|
243
|
-
transactionHash: txHash
|
|
244
|
-
})
|
|
245
|
-
});
|
|
246
|
-
if (!response.ok) {
|
|
247
|
-
const errorData = await response.json();
|
|
248
|
-
throw new Error(errorData.error || "Payment verification failed");
|
|
249
|
-
}
|
|
250
|
-
const data = await response.json();
|
|
251
|
-
if (data.status === "confirmed") {
|
|
252
|
-
setStatus("success");
|
|
253
|
-
props.onSuccess?.(data);
|
|
254
|
-
} else {
|
|
255
|
-
throw new Error("Payment not confirmed yet, status: " + data.status);
|
|
256
|
-
}
|
|
257
|
-
} catch (err) {
|
|
258
|
-
setError(err.message);
|
|
259
|
-
setStatus("error");
|
|
260
|
-
props.onError?.(err);
|
|
261
|
-
}
|
|
262
|
-
}, [props.provider, props.endpoints?.verify, props.orderId, props.onSuccess, props.onError]);
|
|
263
|
-
const { isAvailable: isSolanaAvailable, connect: connectSolana, sendPayment: sendSolanaPayment } = useSolanaWallet();
|
|
264
|
-
const handleSolanaPay = async () => {
|
|
265
|
-
try {
|
|
266
|
-
if (!intent) {
|
|
267
|
-
setError("Payment intent not established.");
|
|
268
|
-
setStatus("error");
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
setStatus("connecting");
|
|
272
|
-
const publicKey = await connectSolana();
|
|
273
|
-
console.log("Connected to Solana with public key:", publicKey);
|
|
274
|
-
setStatus("pending_signature");
|
|
275
|
-
const signature = await sendSolanaPayment(intent);
|
|
276
|
-
setStatus("verifying");
|
|
277
|
-
await verify(signature);
|
|
278
|
-
} catch (err) {
|
|
279
|
-
setError(err.message || "Failed to connect to Phantom or sign transaction.");
|
|
280
|
-
setStatus("error");
|
|
281
|
-
props.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
const { isAvailable: isEVMAvailable, connect: connectEVM, sendPayment: sendEVMPayment } = useEVMWallet();
|
|
285
|
-
const handleEVMPay = async () => {
|
|
286
|
-
try {
|
|
287
|
-
if (!intent) {
|
|
288
|
-
setError("Payment intent not established.");
|
|
289
|
-
setStatus("error");
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
setStatus("connecting");
|
|
293
|
-
const account = await connectEVM();
|
|
294
|
-
console.log("Connected to EVM with account:", account);
|
|
295
|
-
setStatus("pending_signature");
|
|
296
|
-
const txHash = await sendEVMPayment(intent);
|
|
297
|
-
setStatus("verifying");
|
|
298
|
-
await verify(txHash);
|
|
299
|
-
} catch (err) {
|
|
300
|
-
setError(err.message || "Failed to connect to MetaMask or sign transaction.");
|
|
301
|
-
setStatus("error");
|
|
302
|
-
props.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
return {
|
|
306
|
-
status,
|
|
307
|
-
intent,
|
|
308
|
-
error,
|
|
309
|
-
initiate,
|
|
310
|
-
verify,
|
|
311
|
-
setStatus,
|
|
312
|
-
isSolanaAvailable,
|
|
313
|
-
handleSolanaPay,
|
|
314
|
-
isEVMAvailable,
|
|
315
|
-
handleEVMPay
|
|
316
|
-
};
|
|
317
|
-
};
|
|
318
|
-
export {
|
|
319
|
-
PaymentWidget,
|
|
320
|
-
useEVMWallet,
|
|
321
|
-
usePayment,
|
|
322
|
-
useSolanaWallet
|
|
323
|
-
};
|
|
1
|
+
import{useState as v,useCallback as E}from"react";var x=()=>{let e=()=>{if("solana"in window){let n=window;if(n.solana?.isPhantom)return n.solana}},c=async()=>{let n=e();if(n)try{return(await n.connect()).publicKey.toString()}catch{throw new Error("User rejected the connection")}else throw new Error("Phantom wallet not found")},t=async n=>{if(!e())throw new Error("Wallet not connected");return console.log(`Simulating Solana payment to ${n.paymentAddress} for ${n.amount} SOL`),"simulated_solana_signature_"+Math.random().toString(36).slice(2)};return{isAvailable:!!e(),connect:c,sendPayment:t}};var b=()=>{let e=()=>{if(typeof window<"u"&&"ethereum"in window)return window.ethereum},c=async()=>{let n=e();if(n)try{return(await n.request({method:"eth_requestAccounts"}))[0]}catch{throw new Error("User rejected the connection")}else throw new Error("MetaMask or EVM wallet not found")},t=async n=>{if(!e())throw new Error("Wallet not connected");return console.log(`Simulating EVM payment to ${n.paymentAddress} for ${n.amount} ${n.currency}`),"simulated_evm_tx_hash_"+Math.random().toString(36).slice(2)};return{isAvailable:!!e(),connect:c,sendPayment:t}};function p(e,{insertAt:c}={}){if(!e||typeof document>"u")return;let t=document.head||document.getElementsByTagName("head")[0],n=document.createElement("style");n.type="text/css",c==="top"&&t.firstChild?t.insertBefore(n,t.firstChild):t.appendChild(n),n.styleSheet?n.styleSheet.cssText=e:n.appendChild(document.createTextNode(e))}p(`@tailwind base;@tailwind components;@tailwind utilities;
|
|
2
|
+
`);import{Wallet as W,CheckCircle as I,Loader2 as _,AlertCircle as V,ExternalLink as j,Cpu as A}from"lucide-react";import{clsx as T}from"clsx";import{twMerge as L}from"tailwind-merge";import{jsx as m,jsxs as a}from"react/jsx-runtime";function P(...e){return L(T(e))}var U=({className:e,...c})=>{let{status:t,intent:n,error:r,initiate:i,verify:y,setStatus:f,isSolanaAvailable:l,handleSolanaPay:g,isEVMAvailable:w,handleEVMPay:h}=N(c);return t==="success"?a("div",{className:P("mcms-p-6 mcms-text-center mcms-bg-green-50 mcms-rounded-xl mcms-border mcms-border-green-200",e),children:[m(I,{className:"mcms-mx-auto mcms-w-12 mcms-h-12 mcms-text-green-500 mcms-mb-4"}),m("h3",{className:"mcms-text-lg mcms-font-semibold mcms-green-900",children:"Payment Successful"}),m("p",{className:"mcms-text-green-700 mcms-mt-1",children:"Your order has been confirmed."})]}):a("div",{className:P("mcms-bg-white mcms-rounded-2xl mcms-border mcms-border-slate-200 mcms-shadow-sm mcms-overflow-hidden",e),children:[a("div",{className:"mcms-p-6",children:[a("div",{className:"mcms-flex mcms-items-center mcms-gap-3 mcms-mb-6",children:[m("div",{className:"mcms-p-2 mcms-bg-indigo-50 mcms-rounded-lg",children:m(W,{className:"mcms-w-5 mcms-h-5 mcms-text-indigo-600"})}),a("div",{children:[m("h3",{className:"mcms-font-semibold mcms-text-slate-900",children:"Crypto Payment"}),m("p",{className:"mcms-text-sm mcms-text-slate-500",children:"Pay securely using your wallet"})]})]}),r&&a("div",{className:"mcms-mb-4 mcms-p-3 mcms-bg-red-50 mcms-border mcms-border-red-100 mcms-rounded-lg mcms-flex mcms-gap-3 mcms-text-red-700 mcms-text-sm",children:[m(V,{className:"mcms-w-4 mcms-h-4 mcms-shrink-0"}),m("p",{children:r})]}),t==="idle"&&m("button",{onClick:i,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-indigo-600 hover:mcms-bg-indigo-700 mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:"Start Payment"}),(t==="connecting"||t==="initiating"||t==="verifying")&&a("div",{className:"mcms-py-8 mcms-text-center",children:[m(_,{className:"mcms-w-8 mcms-h-8 mcms-text-indigo-600 mcms-animate-spin mcms-mx-auto mcms-mb-3"}),m("p",{className:"mcms-text-slate-600 mcms-font-medium",children:t==="connecting"?"Connecting wallet...":t==="initiating"?"Preparing transaction...":"Verifying on-chain..."})]}),t==="pending_signature"&&n&&a("div",{className:"mcms-space-y-4",children:[a("div",{className:"mcms-p-4 mcms-bg-slate-50 mcms-rounded-xl mcms-space-y-2",children:[a("div",{className:"mcms-flex mcms-justify-between mcms-text-sm",children:[m("span",{className:"mcms-text-slate-500",children:"Amount to pay"}),a("span",{className:"mcms-font-mono mcms-font-medium mcms-text-slate-900",children:[n.amount," ",n.currency]})]}),a("div",{className:"mcms-flex mcms-justify-between mcms-text-sm",children:[m("span",{className:"mcms-text-slate-500",children:"Network"}),m("span",{className:"mcms-text-slate-900 mcms-font-medium",children:n.network})]})]}),a("div",{className:"mcms-space-y-2",children:[m("p",{className:"mcms-text-xs mcms-text-slate-500 mcms-uppercase mcms-font-bold mcms-tracking-wider",children:"Destination Address"}),m("div",{className:"mcms-p-3 mcms-bg-slate-100 mcms-rounded-lg mcms-font-mono mcms-text-xs mcms-break-all mcms-text-slate-600 mcms-border mcms-border-slate-200",children:n.paymentAddress})]}),m("div",{className:"mcms-flex mcms-flex-col mcms-gap-2",children:n.network.toLowerCase().includes("solana")&&l?a("button",{onClick:g,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-[#512da8] hover:mcms-bg-[#4527a0] mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:[m(A,{className:"mcms-w-4 mcms-h-4"}),"Pay with Phantom"]}):(n.network.toLowerCase().includes("ethereum")||n.network.toLowerCase().includes("evm")||n.network.toLowerCase().includes("polygon"))&&w?a("button",{onClick:h,className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-[#f6851b] hover:mcms-bg-[#e2761b] mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:[m("img",{src:"https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Mirror_Logo.svg",className:"mcms-w-4 mcms-h-4",alt:"MetaMask"}),"Pay with MetaMask"]}):m("button",{onClick:()=>{f("verifying"),setTimeout(()=>y("0x_mock_transaction_hash_generic"),2e3)},className:"mcms-w-full mcms-py-3 mcms-px-4 mcms-bg-slate-900 hover:mcms-bg-black mcms-text-white mcms-font-medium mcms-rounded-xl mcms-transition-colors mcms-flex mcms-items-center mcms-justify-center mcms-gap-2",children:"Confirm in Wallet"})})]})]}),a("div",{className:"mcms-bg-slate-50 mcms-px-6 mcms-py-3 mcms-border-t mcms-border-slate-100 mcms-flex mcms-justify-between mcms-items-center",children:[m("span",{className:"mcms-text-xs mcms-text-slate-400",children:"Powered by Micro-CMS Crypto"}),a("a",{href:"#",className:"mcms-text-xs mcms-text-indigo-600 hover:mcms-text-indigo-700 mcms-font-medium mcms-flex mcms-items-center mcms-gap-1",children:["Help ",m(j,{className:"mcms-w-3 mcms-h-3"})]})]})]})};var N=e=>{let[c,t]=v("idle"),[n,r]=v(null),[i,y]=v(null),f=E(async()=>{try{if(t("initiating"),r(null),e.provider){let d=await e.provider.initiatePayment(e.orderId,{amount:e.amount,currency:e.currency});y(d),t("pending_signature");return}let s=await fetch(e.endpoints?.initiate||"/api/orders/initiate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({orderId:e.orderId,amount:e.amount,currency:e.currency})});if(!s.ok){let d=await s.json();throw new Error(d.error||"Failed to initiate payment intent")}let o=await s.json();y(o),t("pending_signature")}catch(s){r(s.message),t("error"),e.onError?.(s)}},[e.provider,e.endpoints?.initiate,e.orderId,e.amount,e.currency,e.onError]),l=E(async s=>{try{if(t("verifying"),e.provider){let u=await e.provider.verifyPayment(s,e.orderId);if(u.status==="confirmed")t("success"),e.onSuccess?.(u);else throw new Error("Payment not confirmed yet, status: "+u.status);return}let o=await fetch(e.endpoints?.verify||"/api/orders/verify-payment",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({orderId:e.orderId,transactionHash:s})});if(!o.ok){let u=await o.json();throw new Error(u.error||"Payment verification failed")}let d=await o.json();if(d.status==="confirmed")t("success"),e.onSuccess?.(d);else throw new Error("Payment not confirmed yet, status: "+d.status)}catch(o){r(o.message),t("error"),e.onError?.(o)}},[e.provider,e.endpoints?.verify,e.orderId,e.onSuccess,e.onError]),{isAvailable:g,connect:w,sendPayment:h}=x(),S=async()=>{try{if(!i){r("Payment intent not established."),t("error");return}t("connecting");let s=await w();console.log("Connected to Solana with public key:",s),t("pending_signature");let o=await h(i);t("verifying"),await l(o)}catch(s){r(s.message||"Failed to connect to Phantom or sign transaction."),t("error"),e.onError?.(s instanceof Error?s:new Error(String(s)))}},{isAvailable:k,connect:C,sendPayment:M}=b();return{status:c,intent:i,error:n,initiate:f,verify:l,setStatus:t,isSolanaAvailable:g,handleSolanaPay:S,isEVMAvailable:k,handleEVMPay:async()=>{try{if(!i){r("Payment intent not established."),t("error");return}t("connecting");let s=await C();console.log("Connected to EVM with account:",s),t("pending_signature");let o=await M(i);t("verifying"),await l(o)}catch(s){r(s.message||"Failed to connect to MetaMask or sign transaction."),t("error"),e.onError?.(s instanceof Error?s:new Error(String(s)))}}}};export{U as PaymentWidget,b as useEVMWallet,N as usePayment,x as useSolanaWallet};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@micro-cms/crypto-payments",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Composable Crypto Payment Widget for Micro-CMS",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
12
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --minify --clean --inject-style && npx tailwindcss -i src/index.css -o dist/index.css --minify",
|
|
13
13
|
"dev": "tsup src/index.ts --format cjs,esm --watch --dts",
|
|
14
14
|
"lint": "eslint src/**/*.ts"
|
|
15
15
|
},
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/react": "^18.2.0",
|
|
28
|
+
"autoprefixer": "^10.4.24",
|
|
29
|
+
"postcss": "^8.5.6",
|
|
30
|
+
"tailwindcss": "^3.4.1",
|
|
28
31
|
"typescript": "^5.3.3",
|
|
29
32
|
"tsup": "^8.0.2"
|
|
30
33
|
}
|