@dipansrimany/mlink-sdk 0.4.1 → 0.4.2

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.
@@ -16,6 +16,8 @@ var MANTLE_SEPOLIA = {
16
16
  };
17
17
  var DEFAULT_CHAIN = MANTLE_SEPOLIA;
18
18
  var ACTION_QUERY_PARAM = "action";
19
+ var REGISTRY_URL = "https://mlinks-fe.vercel.app";
20
+ var REGISTRY_VALIDATE_ENDPOINT = "/api/registry/validate";
19
21
 
20
22
  // src/utils.ts
21
23
  function parseBlinkUrl(blinkUrl) {
@@ -180,22 +182,73 @@ function validateActionMetadata(data) {
180
182
  // src/react/useMlink.ts
181
183
  var DEFAULT_REFRESH_INTERVAL = 10 * 60 * 1e3;
182
184
  function useMlink(url, options = {}) {
183
- const { refreshInterval = DEFAULT_REFRESH_INTERVAL, enabled = true } = options;
185
+ const {
186
+ refreshInterval = DEFAULT_REFRESH_INTERVAL,
187
+ enabled = true,
188
+ registryUrl = REGISTRY_URL,
189
+ requireRegistration = true,
190
+ allowPending = true,
191
+ allowBlocked = false
192
+ } = options;
184
193
  const [status, setStatus] = useState("idle");
185
194
  const [metadata, setMetadata] = useState(null);
186
195
  const [error, setError] = useState(null);
196
+ const [registration, setRegistration] = useState(null);
187
197
  const abortControllerRef = useRef(null);
188
198
  const intervalRef = useRef(null);
189
199
  const actionUrl = parseBlinkUrl(url) || url;
200
+ const validateRegistration = useCallback(async () => {
201
+ if (!actionUrl || !requireRegistration) return null;
202
+ try {
203
+ const validateUrl = `${registryUrl}${REGISTRY_VALIDATE_ENDPOINT}?url=${encodeURIComponent(actionUrl)}`;
204
+ const response = await fetch(validateUrl, {
205
+ method: "GET",
206
+ headers: {
207
+ Accept: "application/json"
208
+ }
209
+ });
210
+ const data = await response.json();
211
+ return data;
212
+ } catch (err) {
213
+ console.error("Registry validation error:", err);
214
+ return {
215
+ isRegistered: false,
216
+ status: null,
217
+ error: "Unable to validate against registry. Please try again later."
218
+ };
219
+ }
220
+ }, [actionUrl, registryUrl, requireRegistration]);
190
221
  const fetchMetadata = useCallback(async () => {
191
222
  if (!actionUrl || !enabled) return;
192
223
  if (abortControllerRef.current) {
193
224
  abortControllerRef.current.abort();
194
225
  }
195
226
  abortControllerRef.current = new AbortController();
196
- setStatus("loading");
227
+ setStatus("validating");
197
228
  setError(null);
198
229
  try {
230
+ if (requireRegistration) {
231
+ const registrationResult = await validateRegistration();
232
+ setRegistration(registrationResult);
233
+ if (registrationResult) {
234
+ if (!registrationResult.isRegistered) {
235
+ setError(registrationResult.error || "This MLink is not registered.");
236
+ setStatus("unregistered");
237
+ return;
238
+ }
239
+ if (registrationResult.status === "blocked" && !allowBlocked) {
240
+ setError("This MLink has been blocked for policy violations.");
241
+ setStatus("blocked");
242
+ return;
243
+ }
244
+ if (registrationResult.status === "pending" && !allowPending) {
245
+ setError("This MLink is pending review and not yet available.");
246
+ setStatus("error");
247
+ return;
248
+ }
249
+ }
250
+ }
251
+ setStatus("loading");
199
252
  const response = await fetch(actionUrl, {
200
253
  method: "GET",
201
254
  headers: {
@@ -221,7 +274,7 @@ function useMlink(url, options = {}) {
221
274
  setError(errorMessage);
222
275
  setStatus("error");
223
276
  }
224
- }, [actionUrl, enabled]);
277
+ }, [actionUrl, enabled, requireRegistration, validateRegistration, allowBlocked, allowPending]);
225
278
  useEffect(() => {
226
279
  if (enabled) {
227
280
  fetchMetadata();
@@ -248,7 +301,9 @@ function useMlink(url, options = {}) {
248
301
  metadata,
249
302
  error,
250
303
  url: actionUrl,
251
- refresh: fetchMetadata
304
+ refresh: fetchMetadata,
305
+ registration,
306
+ isRegistered: registration?.isRegistered ?? false
252
307
  };
253
308
  }
254
309
  function useExecuteMlink(options) {
@@ -475,11 +530,20 @@ function Mlink({
475
530
  onSuccess,
476
531
  onError,
477
532
  className = "",
478
- stylePreset = "default"
533
+ stylePreset = "default",
534
+ registryUrl,
535
+ requireRegistration = true,
536
+ allowPending = true,
537
+ allowBlocked = false
479
538
  }) {
480
539
  const context = useMlinkContext();
481
540
  const resolvedTheme = themeProp ? resolveTheme(themeProp) : context.theme;
482
- const { status: fetchStatus, metadata, error: fetchError } = useMlink(url);
541
+ const { status: fetchStatus, metadata, error: fetchError, registration } = useMlink(url, {
542
+ registryUrl,
543
+ requireRegistration,
544
+ allowPending,
545
+ allowBlocked
546
+ });
483
547
  const {
484
548
  execute,
485
549
  status: execStatus,
@@ -542,9 +606,21 @@ function Mlink({
542
606
  const hasLinkedActions = useMemo(() => {
543
607
  return metadata?.links?.actions && metadata.links.actions.length > 0;
544
608
  }, [metadata]);
545
- if (fetchStatus === "loading") {
609
+ if (fetchStatus === "loading" || fetchStatus === "validating") {
546
610
  return /* @__PURE__ */ jsx(MlinkContainer, { theme: resolvedTheme, className, preset: stylePreset, children: /* @__PURE__ */ jsx(MlinkSkeleton, {}) });
547
611
  }
612
+ if (fetchStatus === "unregistered") {
613
+ return /* @__PURE__ */ jsx(MlinkContainer, { theme: resolvedTheme, className, preset: stylePreset, children: /* @__PURE__ */ jsx(
614
+ MlinkUnregistered,
615
+ {
616
+ message: fetchError || "This MLink is not registered.",
617
+ registryUrl
618
+ }
619
+ ) });
620
+ }
621
+ if (fetchStatus === "blocked") {
622
+ return /* @__PURE__ */ jsx(MlinkContainer, { theme: resolvedTheme, className, preset: stylePreset, children: /* @__PURE__ */ jsx(MlinkBlocked, { message: fetchError || "This MLink has been blocked." }) });
623
+ }
548
624
  if (fetchStatus === "error" || !metadata) {
549
625
  return /* @__PURE__ */ jsx(MlinkContainer, { theme: resolvedTheme, className, preset: stylePreset, children: /* @__PURE__ */ jsx(MlinkError, { message: fetchError || "Failed to load action" }) });
550
626
  }
@@ -821,6 +897,38 @@ function MlinkError({ message }) {
821
897
  /* @__PURE__ */ jsx("p", { className: "mlink-error-message", children: message })
822
898
  ] });
823
899
  }
900
+ function MlinkUnregistered({ message, registryUrl }) {
901
+ const registerUrl = registryUrl ? `${registryUrl}/dashboard/register` : "https://mlinks-fe.vercel.app/dashboard/register";
902
+ return /* @__PURE__ */ jsxs("div", { className: "mlink-unregistered", children: [
903
+ /* @__PURE__ */ jsx("div", { className: "mlink-unregistered-icon", children: /* @__PURE__ */ jsxs("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
904
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
905
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
906
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
907
+ ] }) }),
908
+ /* @__PURE__ */ jsx("h3", { className: "mlink-unregistered-title", children: "Unregistered MLink" }),
909
+ /* @__PURE__ */ jsx("p", { className: "mlink-unregistered-message", children: message }),
910
+ /* @__PURE__ */ jsx(
911
+ "a",
912
+ {
913
+ href: registerUrl,
914
+ target: "_blank",
915
+ rel: "noopener noreferrer",
916
+ className: "mlink-button",
917
+ children: "Register MLink"
918
+ }
919
+ )
920
+ ] });
921
+ }
922
+ function MlinkBlocked({ message }) {
923
+ return /* @__PURE__ */ jsxs("div", { className: "mlink-blocked", children: [
924
+ /* @__PURE__ */ jsx("div", { className: "mlink-blocked-icon", children: /* @__PURE__ */ jsxs("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
925
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
926
+ /* @__PURE__ */ jsx("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
927
+ ] }) }),
928
+ /* @__PURE__ */ jsx("h3", { className: "mlink-blocked-title", children: "Blocked MLink" }),
929
+ /* @__PURE__ */ jsx("p", { className: "mlink-blocked-message", children: message })
930
+ ] });
931
+ }
824
932
  function MlinkSuccess({ message, txHash, onReset }) {
825
933
  const shortHash = `${txHash.slice(0, 10)}...${txHash.slice(-8)}`;
826
934
  return /* @__PURE__ */ jsxs("div", { className: "mlink-success", children: [