@medialane/ui 0.165.0 → 0.167.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/utils/describe-error.cjs +41 -72
- package/dist/utils/describe-error.cjs.map +1 -1
- package/dist/utils/describe-error.d.cts +3 -4
- package/dist/utils/describe-error.d.ts +3 -4
- package/dist/utils/describe-error.js +41 -77
- package/dist/utils/describe-error.js.map +1 -1
- package/package.json +3 -3
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "ghost" | "link" | "default" | "destructive" | "outline" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "icon" | "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "ghost" | "link" | "default" | "destructive" | "outline" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "icon" | "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
package/dist/index.d.cts
CHANGED
|
@@ -8,7 +8,7 @@ export { useIntersectionActive } from './utils/use-intersection-active.cjs';
|
|
|
8
8
|
export { getReadIds, markRead } from './utils/notification-storage.cjs';
|
|
9
9
|
export { licenseSummary } from './utils/license-summary.cjs';
|
|
10
10
|
export { WrongNetworkError, assertCorrectNetwork, isBareExecuteFailure, isUserRejectedRequest, isWrongNetwork } from './utils/wallet-error.cjs';
|
|
11
|
-
export { ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED,
|
|
11
|
+
export { ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED, describeError } from './utils/describe-error.cjs';
|
|
12
12
|
export { IP_TYPE_DATA, IP_TYPE_DATA_MAP, IpTypeData } from './data/ip-types.cjs';
|
|
13
13
|
export { AI_POLICIES, DERIVATIVES_OPTIONS, GEOGRAPHIC_SCOPES, IPType, IP_TYPES, LICENSE_TRAIT_TYPES, LICENSE_TYPES, LicenseType } from './data/ip.cjs';
|
|
14
14
|
export { DOC_UPLOAD, DocUploadConfig, EMBED_PLATFORM_META, EmbedPlatform, IPTemplate, IP_TEMPLATES, SOCIAL_PLATFORM_META, SocialPlatform, TEMPLATE_TRAIT_TYPES, TraitSuggestion } from './data/ip-templates.cjs';
|
|
@@ -175,8 +175,8 @@ export { CreatorAnalytics } from './components/creator-analytics.cjs';
|
|
|
175
175
|
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/dialog.cjs';
|
|
176
176
|
export { SelfFundConsentDialog, feeLabelFor } from './components/wallet/self-fund-consent-dialog.cjs';
|
|
177
177
|
export { ExportKeySection, ExportKeySectionProps } from './components/wallet/export-key-section.cjs';
|
|
178
|
+
export { UserFacingError } from '@medialane/sdk';
|
|
178
179
|
import 'clsx';
|
|
179
|
-
import '@medialane/sdk';
|
|
180
180
|
import 'react';
|
|
181
181
|
import 'lucide-react';
|
|
182
182
|
import 'react/jsx-runtime';
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { useIntersectionActive } from './utils/use-intersection-active.js';
|
|
|
8
8
|
export { getReadIds, markRead } from './utils/notification-storage.js';
|
|
9
9
|
export { licenseSummary } from './utils/license-summary.js';
|
|
10
10
|
export { WrongNetworkError, assertCorrectNetwork, isBareExecuteFailure, isUserRejectedRequest, isWrongNetwork } from './utils/wallet-error.js';
|
|
11
|
-
export { ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED,
|
|
11
|
+
export { ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED, describeError } from './utils/describe-error.js';
|
|
12
12
|
export { IP_TYPE_DATA, IP_TYPE_DATA_MAP, IpTypeData } from './data/ip-types.js';
|
|
13
13
|
export { AI_POLICIES, DERIVATIVES_OPTIONS, GEOGRAPHIC_SCOPES, IPType, IP_TYPES, LICENSE_TRAIT_TYPES, LICENSE_TYPES, LicenseType } from './data/ip.js';
|
|
14
14
|
export { DOC_UPLOAD, DocUploadConfig, EMBED_PLATFORM_META, EmbedPlatform, IPTemplate, IP_TEMPLATES, SOCIAL_PLATFORM_META, SocialPlatform, TEMPLATE_TRAIT_TYPES, TraitSuggestion } from './data/ip-templates.js';
|
|
@@ -175,8 +175,8 @@ export { CreatorAnalytics } from './components/creator-analytics.js';
|
|
|
175
175
|
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/dialog.js';
|
|
176
176
|
export { SelfFundConsentDialog, feeLabelFor } from './components/wallet/self-fund-consent-dialog.js';
|
|
177
177
|
export { ExportKeySection, ExportKeySectionProps } from './components/wallet/export-key-section.js';
|
|
178
|
+
export { UserFacingError } from '@medialane/sdk';
|
|
178
179
|
import 'clsx';
|
|
179
|
-
import '@medialane/sdk';
|
|
180
180
|
import 'react';
|
|
181
181
|
import 'lucide-react';
|
|
182
182
|
import 'react/jsx-runtime';
|
|
@@ -21,7 +21,7 @@ __export(describe_error_exports, {
|
|
|
21
21
|
GENERIC: () => GENERIC,
|
|
22
22
|
NETWORK_BUSY: () => NETWORK_BUSY,
|
|
23
23
|
NOT_SUBMITTED: () => NOT_SUBMITTED,
|
|
24
|
-
UserFacingError: () => UserFacingError,
|
|
24
|
+
UserFacingError: () => import_sdk.UserFacingError,
|
|
25
25
|
describeError: () => describeError
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(describe_error_exports);
|
|
@@ -30,94 +30,63 @@ var import_wallet_error = require("./wallet-error.js");
|
|
|
30
30
|
const NOT_SUBMITTED = "Request not completed. Nothing was submitted.";
|
|
31
31
|
const GENERIC = "Something went wrong. Please try again.";
|
|
32
32
|
const NETWORK_BUSY = "The network is busy right now. Nothing was submitted. Please try again in a moment.";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const notice = (title, message, description) => ({
|
|
34
|
+
title,
|
|
35
|
+
message,
|
|
36
|
+
description,
|
|
37
|
+
isUserRejection: false
|
|
38
|
+
});
|
|
39
|
+
function isTransient(error) {
|
|
40
|
+
if (error instanceof import_sdk.MedialaneApiError) {
|
|
41
|
+
return error.status === 408 || error.status === 429 || error.status >= 500;
|
|
37
42
|
}
|
|
38
|
-
}
|
|
39
|
-
function isTransientStatus(status) {
|
|
40
|
-
return status === 408 || status === 429 || status >= 500;
|
|
41
|
-
}
|
|
42
|
-
function isTransientNetworkError(text) {
|
|
43
43
|
return /-32001|unable to complete request|service unavailable|temporarily unavailable|rate.?limit|too many requests|gateway time-?out|bad gateway|failed to fetch|fetch failed|network ?error|load failed/i.test(
|
|
44
|
-
|
|
44
|
+
(0, import_wallet_error.collectErrorText)(error)
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
description: "Your device did not confirm this request. Nothing was submitted. Try again when you are ready.",
|
|
53
|
-
isUserRejection: true
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
if ((0, import_wallet_error.isBareExecuteFailure)(error)) {
|
|
57
|
-
return {
|
|
58
|
-
title: "Request not completed",
|
|
59
|
-
message: NOT_SUBMITTED,
|
|
60
|
-
description: "Your wallet didn't complete this request. This usually means you closed or declined it, your wallet needs extra verification (like 2FA) before it can sign, or your wallet hit a temporary network hiccup. Nothing was submitted. Try again in a moment.",
|
|
61
|
-
isUserRejection: true
|
|
62
|
-
};
|
|
47
|
+
function apiReason(error) {
|
|
48
|
+
const body = error.details;
|
|
49
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
50
|
+
const reason = body.error;
|
|
51
|
+
if (typeof reason === "string" && reason.trim() !== "") return reason;
|
|
63
52
|
}
|
|
64
|
-
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
function describeError(error, fallback) {
|
|
56
|
+
if (error instanceof import_sdk.PasskeyCancelledError || (0, import_wallet_error.isUserRejectedRequest)(error)) {
|
|
57
|
+
const unclear = (0, import_wallet_error.isBareExecuteFailure)(error) || error instanceof import_sdk.PasskeyCancelledError;
|
|
65
58
|
return {
|
|
66
59
|
title: "Request not completed",
|
|
67
60
|
message: NOT_SUBMITTED,
|
|
68
|
-
description: "Your wallet didn't complete this request. You may have closed or declined it,
|
|
61
|
+
description: unclear ? "Your wallet didn't complete this request. You may have closed or declined it, it may need extra verification such as 2FA before it can sign, or it may have hit a temporary network hiccup. Try again in a moment." : "Your wallet didn't complete this request. You may have closed or declined it, or it may need extra verification before it can sign.",
|
|
69
62
|
isUserRejection: true
|
|
70
63
|
};
|
|
71
64
|
}
|
|
72
65
|
if (error instanceof import_wallet_error.WrongNetworkError) {
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
if (error instanceof UserFacingError) {
|
|
81
|
-
return { title: "Something went wrong", message: error.message, isUserRejection: false };
|
|
66
|
+
return notice(
|
|
67
|
+
"Wrong network",
|
|
68
|
+
"Your wallet is connected to the wrong network. Nothing was submitted.",
|
|
69
|
+
"Switch your wallet to Starknet Mainnet, then try again."
|
|
70
|
+
);
|
|
82
71
|
}
|
|
83
|
-
if (error
|
|
84
|
-
|
|
85
|
-
return { title: "Something went wrong", message: error.message, isUserRejection: false };
|
|
86
|
-
}
|
|
87
|
-
if (isTransientStatus(error.status)) {
|
|
88
|
-
return { title: "Network busy", message: NETWORK_BUSY, isUserRejection: false };
|
|
89
|
-
}
|
|
90
|
-
return { title: "Something went wrong", message: fallback ?? GENERIC, isUserRejection: false };
|
|
72
|
+
if (isTransient(error)) {
|
|
73
|
+
return notice("Network busy", NETWORK_BUSY);
|
|
91
74
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return { title: "Network busy", message: NETWORK_BUSY, isUserRejection: false };
|
|
75
|
+
if (error instanceof import_sdk.UserFacingError) {
|
|
76
|
+
return notice("Something went wrong", error.message);
|
|
95
77
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
title: "Insufficient balance",
|
|
100
|
-
message: "You don't have enough balance to complete this transaction.",
|
|
101
|
-
isUserRejection: false
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
const stack = error instanceof Error && typeof error.stack === "string" ? error.stack.toLowerCase() : "";
|
|
105
|
-
if (lower.includes("validation failure") && (lower.includes("jscontrollererror") || stack.includes("jscontrollererror"))) {
|
|
106
|
-
return {
|
|
107
|
-
title: "Not enough gas",
|
|
108
|
-
message: "Your wallet doesn't have enough STRK (or ETH) to pay for this transaction's gas fee.",
|
|
109
|
-
description: "Add funds to your wallet, then try again.",
|
|
110
|
-
isUserRejection: false
|
|
111
|
-
};
|
|
78
|
+
if (error instanceof import_sdk.MedialaneApiError) {
|
|
79
|
+
return notice("Something went wrong", apiReason(error) ?? fallback ?? GENERIC);
|
|
112
80
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
81
|
+
const text = (0, import_wallet_error.collectErrorText)(error).toLowerCase();
|
|
82
|
+
if (text.includes("insufficient") && /balance|allowance|funds/.test(text)) {
|
|
83
|
+
return notice(
|
|
84
|
+
"Insufficient balance",
|
|
85
|
+
"You don't have enough balance to complete this transaction.",
|
|
86
|
+
"Add funds to your wallet, then try again."
|
|
87
|
+
);
|
|
119
88
|
}
|
|
120
|
-
return
|
|
89
|
+
return notice("Something went wrong", fallback ?? GENERIC);
|
|
121
90
|
}
|
|
122
91
|
// Annotate the CommonJS export names for ESM import in node:
|
|
123
92
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/describe-error.ts"],"sourcesContent":["import { MedialaneApiError, PasskeyCancelledError } from \"@medialane/sdk\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/utils/describe-error.ts"],"sourcesContent":["import { MedialaneApiError, PasskeyCancelledError, UserFacingError } from \"@medialane/sdk\";\nimport { WrongNetworkError, isBareExecuteFailure, isUserRejectedRequest, collectErrorText } from \"./wallet-error.js\";\n\nexport const NOT_SUBMITTED = \"Request not completed. Nothing was submitted.\";\nexport const GENERIC = \"Something went wrong. Please try again.\";\nexport const NETWORK_BUSY =\n \"The network is busy right now. Nothing was submitted. Please try again in a moment.\";\n\nexport interface ErrorNotice {\n title: string;\n message: string;\n description?: string;\n isUserRejection: boolean;\n}\n\nconst notice = (title: string, message: string, description?: string): ErrorNotice => ({\n title,\n message,\n description,\n isUserRejection: false,\n});\n\nfunction isTransient(error: unknown): boolean {\n if (error instanceof MedialaneApiError) {\n return error.status === 408 || error.status === 429 || error.status >= 500;\n }\n return /-32001|unable to complete request|service unavailable|temporarily unavailable|rate.?limit|too many requests|gateway time-?out|bad gateway|failed to fetch|fetch failed|network ?error|load failed/i.test(\n collectErrorText(error),\n );\n}\n\nfunction apiReason(error: MedialaneApiError): string | undefined {\n const body = error.details;\n if (body && typeof body === \"object\" && \"error\" in body) {\n const reason = (body as { error?: unknown }).error;\n if (typeof reason === \"string\" && reason.trim() !== \"\") return reason;\n }\n return undefined;\n}\n\nexport function describeError(error: unknown, fallback?: string): ErrorNotice {\n if (error instanceof PasskeyCancelledError || isUserRejectedRequest(error)) {\n const unclear = isBareExecuteFailure(error) || error instanceof PasskeyCancelledError;\n return {\n title: \"Request not completed\",\n message: NOT_SUBMITTED,\n description: unclear\n ? \"Your wallet didn't complete this request. You may have closed or declined it, it may need extra verification such as 2FA before it can sign, or it may have hit a temporary network hiccup. Try again in a moment.\"\n : \"Your wallet didn't complete this request. You may have closed or declined it, or it may need extra verification before it can sign.\",\n isUserRejection: true,\n };\n }\n\n if (error instanceof WrongNetworkError) {\n return notice(\n \"Wrong network\",\n \"Your wallet is connected to the wrong network. Nothing was submitted.\",\n \"Switch your wallet to Starknet Mainnet, then try again.\",\n );\n }\n\n if (isTransient(error)) {\n return notice(\"Network busy\", NETWORK_BUSY);\n }\n\n if (error instanceof UserFacingError) {\n return notice(\"Something went wrong\", error.message);\n }\n\n if (error instanceof MedialaneApiError) {\n return notice(\"Something went wrong\", apiReason(error) ?? fallback ?? GENERIC);\n }\n\n const text = collectErrorText(error).toLowerCase();\n if (text.includes(\"insufficient\") && /balance|allowance|funds/.test(text)) {\n return notice(\n \"Insufficient balance\",\n \"You don't have enough balance to complete this transaction.\",\n \"Add funds to your wallet, then try again.\",\n );\n }\n\n return notice(\"Something went wrong\", fallback ?? GENERIC);\n}\n\nexport { UserFacingError };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA0E;AAC1E,0BAAiG;AAE1F,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAChB,MAAM,eACX;AASF,MAAM,SAAS,CAAC,OAAe,SAAiB,iBAAuC;AAAA,EACrF;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB;AAEA,SAAS,YAAY,OAAyB;AAC5C,MAAI,iBAAiB,8BAAmB;AACtC,WAAO,MAAM,WAAW,OAAO,MAAM,WAAW,OAAO,MAAM,UAAU;AAAA,EACzE;AACA,SAAO,qMAAqM;AAAA,QAC1M,sCAAiB,KAAK;AAAA,EACxB;AACF;AAEA,SAAS,UAAU,OAA8C;AAC/D,QAAM,OAAO,MAAM;AACnB,MAAI,QAAQ,OAAO,SAAS,YAAY,WAAW,MAAM;AACvD,UAAM,SAAU,KAA6B;AAC7C,QAAI,OAAO,WAAW,YAAY,OAAO,KAAK,MAAM,GAAI,QAAO;AAAA,EACjE;AACA,SAAO;AACT;AAEO,SAAS,cAAc,OAAgB,UAAgC;AAC5E,MAAI,iBAAiB,wCAAyB,2CAAsB,KAAK,GAAG;AAC1E,UAAM,cAAU,0CAAqB,KAAK,KAAK,iBAAiB;AAChE,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,aAAa,UACT,uNACA;AAAA,MACJ,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,iBAAiB,uCAAmB;AACtC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO,OAAO,gBAAgB,YAAY;AAAA,EAC5C;AAEA,MAAI,iBAAiB,4BAAiB;AACpC,WAAO,OAAO,wBAAwB,MAAM,OAAO;AAAA,EACrD;AAEA,MAAI,iBAAiB,8BAAmB;AACtC,WAAO,OAAO,wBAAwB,UAAU,KAAK,KAAK,YAAY,OAAO;AAAA,EAC/E;AAEA,QAAM,WAAO,sCAAiB,KAAK,EAAE,YAAY;AACjD,MAAI,KAAK,SAAS,cAAc,KAAK,0BAA0B,KAAK,IAAI,GAAG;AACzE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,wBAAwB,YAAY,OAAO;AAC3D;","names":[]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { UserFacingError } from '@medialane/sdk';
|
|
2
|
+
|
|
1
3
|
declare const NOT_SUBMITTED = "Request not completed. Nothing was submitted.";
|
|
2
4
|
declare const GENERIC = "Something went wrong. Please try again.";
|
|
3
5
|
declare const NETWORK_BUSY = "The network is busy right now. Nothing was submitted. Please try again in a moment.";
|
|
@@ -7,9 +9,6 @@ interface ErrorNotice {
|
|
|
7
9
|
description?: string;
|
|
8
10
|
isUserRejection: boolean;
|
|
9
11
|
}
|
|
10
|
-
declare class UserFacingError extends Error {
|
|
11
|
-
constructor(message: string);
|
|
12
|
-
}
|
|
13
12
|
declare function describeError(error: unknown, fallback?: string): ErrorNotice;
|
|
14
13
|
|
|
15
|
-
export { type ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED,
|
|
14
|
+
export { type ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED, describeError };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { UserFacingError } from '@medialane/sdk';
|
|
2
|
+
|
|
1
3
|
declare const NOT_SUBMITTED = "Request not completed. Nothing was submitted.";
|
|
2
4
|
declare const GENERIC = "Something went wrong. Please try again.";
|
|
3
5
|
declare const NETWORK_BUSY = "The network is busy right now. Nothing was submitted. Please try again in a moment.";
|
|
@@ -7,9 +9,6 @@ interface ErrorNotice {
|
|
|
7
9
|
description?: string;
|
|
8
10
|
isUserRejection: boolean;
|
|
9
11
|
}
|
|
10
|
-
declare class UserFacingError extends Error {
|
|
11
|
-
constructor(message: string);
|
|
12
|
-
}
|
|
13
12
|
declare function describeError(error: unknown, fallback?: string): ErrorNotice;
|
|
14
13
|
|
|
15
|
-
export { type ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED,
|
|
14
|
+
export { type ErrorNotice, GENERIC, NETWORK_BUSY, NOT_SUBMITTED, describeError };
|
|
@@ -1,101 +1,65 @@
|
|
|
1
|
-
import { MedialaneApiError, PasskeyCancelledError } from "@medialane/sdk";
|
|
2
|
-
import {
|
|
3
|
-
WrongNetworkError,
|
|
4
|
-
isBareExecuteFailure,
|
|
5
|
-
isUserRejectedRequest,
|
|
6
|
-
collectErrorText
|
|
7
|
-
} from "./wallet-error.js";
|
|
1
|
+
import { MedialaneApiError, PasskeyCancelledError, UserFacingError } from "@medialane/sdk";
|
|
2
|
+
import { WrongNetworkError, isBareExecuteFailure, isUserRejectedRequest, collectErrorText } from "./wallet-error.js";
|
|
8
3
|
const NOT_SUBMITTED = "Request not completed. Nothing was submitted.";
|
|
9
4
|
const GENERIC = "Something went wrong. Please try again.";
|
|
10
5
|
const NETWORK_BUSY = "The network is busy right now. Nothing was submitted. Please try again in a moment.";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
const notice = (title, message, description) => ({
|
|
7
|
+
title,
|
|
8
|
+
message,
|
|
9
|
+
description,
|
|
10
|
+
isUserRejection: false
|
|
11
|
+
});
|
|
12
|
+
function isTransient(error) {
|
|
13
|
+
if (error instanceof MedialaneApiError) {
|
|
14
|
+
return error.status === 408 || error.status === 429 || error.status >= 500;
|
|
15
15
|
}
|
|
16
|
-
}
|
|
17
|
-
function isTransientStatus(status) {
|
|
18
|
-
return status === 408 || status === 429 || status >= 500;
|
|
19
|
-
}
|
|
20
|
-
function isTransientNetworkError(text) {
|
|
21
16
|
return /-32001|unable to complete request|service unavailable|temporarily unavailable|rate.?limit|too many requests|gateway time-?out|bad gateway|failed to fetch|fetch failed|network ?error|load failed/i.test(
|
|
22
|
-
|
|
17
|
+
collectErrorText(error)
|
|
23
18
|
);
|
|
24
19
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
description: "Your device did not confirm this request. Nothing was submitted. Try again when you are ready.",
|
|
31
|
-
isUserRejection: true
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
if (isBareExecuteFailure(error)) {
|
|
35
|
-
return {
|
|
36
|
-
title: "Request not completed",
|
|
37
|
-
message: NOT_SUBMITTED,
|
|
38
|
-
description: "Your wallet didn't complete this request. This usually means you closed or declined it, your wallet needs extra verification (like 2FA) before it can sign, or your wallet hit a temporary network hiccup. Nothing was submitted. Try again in a moment.",
|
|
39
|
-
isUserRejection: true
|
|
40
|
-
};
|
|
20
|
+
function apiReason(error) {
|
|
21
|
+
const body = error.details;
|
|
22
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
23
|
+
const reason = body.error;
|
|
24
|
+
if (typeof reason === "string" && reason.trim() !== "") return reason;
|
|
41
25
|
}
|
|
42
|
-
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
function describeError(error, fallback) {
|
|
29
|
+
if (error instanceof PasskeyCancelledError || isUserRejectedRequest(error)) {
|
|
30
|
+
const unclear = isBareExecuteFailure(error) || error instanceof PasskeyCancelledError;
|
|
43
31
|
return {
|
|
44
32
|
title: "Request not completed",
|
|
45
33
|
message: NOT_SUBMITTED,
|
|
46
|
-
description: "Your wallet didn't complete this request. You may have closed or declined it,
|
|
34
|
+
description: unclear ? "Your wallet didn't complete this request. You may have closed or declined it, it may need extra verification such as 2FA before it can sign, or it may have hit a temporary network hiccup. Try again in a moment." : "Your wallet didn't complete this request. You may have closed or declined it, or it may need extra verification before it can sign.",
|
|
47
35
|
isUserRejection: true
|
|
48
36
|
};
|
|
49
37
|
}
|
|
50
38
|
if (error instanceof WrongNetworkError) {
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
39
|
+
return notice(
|
|
40
|
+
"Wrong network",
|
|
41
|
+
"Your wallet is connected to the wrong network. Nothing was submitted.",
|
|
42
|
+
"Switch your wallet to Starknet Mainnet, then try again."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (isTransient(error)) {
|
|
46
|
+
return notice("Network busy", NETWORK_BUSY);
|
|
57
47
|
}
|
|
58
48
|
if (error instanceof UserFacingError) {
|
|
59
|
-
return
|
|
49
|
+
return notice("Something went wrong", error.message);
|
|
60
50
|
}
|
|
61
51
|
if (error instanceof MedialaneApiError) {
|
|
62
|
-
|
|
63
|
-
return { title: "Something went wrong", message: error.message, isUserRejection: false };
|
|
64
|
-
}
|
|
65
|
-
if (isTransientStatus(error.status)) {
|
|
66
|
-
return { title: "Network busy", message: NETWORK_BUSY, isUserRejection: false };
|
|
67
|
-
}
|
|
68
|
-
return { title: "Something went wrong", message: fallback ?? GENERIC, isUserRejection: false };
|
|
69
|
-
}
|
|
70
|
-
const raw = collectErrorText(error);
|
|
71
|
-
if (isTransientNetworkError(raw)) {
|
|
72
|
-
return { title: "Network busy", message: NETWORK_BUSY, isUserRejection: false };
|
|
73
|
-
}
|
|
74
|
-
const lower = raw.toLowerCase();
|
|
75
|
-
if (lower.includes("insufficient") && /balance|allowance|funds/.test(lower)) {
|
|
76
|
-
return {
|
|
77
|
-
title: "Insufficient balance",
|
|
78
|
-
message: "You don't have enough balance to complete this transaction.",
|
|
79
|
-
isUserRejection: false
|
|
80
|
-
};
|
|
52
|
+
return notice("Something went wrong", apiReason(error) ?? fallback ?? GENERIC);
|
|
81
53
|
}
|
|
82
|
-
const
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
if (/unknown_error/i.test(raw) || typeof error === "object" && error !== null && error.code === 163) {
|
|
92
|
-
return {
|
|
93
|
-
title: "Something went wrong",
|
|
94
|
-
message: "Your wallet couldn't complete this transaction. Nothing was submitted. Try again, or try a different wallet or device if it keeps happening.",
|
|
95
|
-
isUserRejection: false
|
|
96
|
-
};
|
|
54
|
+
const text = collectErrorText(error).toLowerCase();
|
|
55
|
+
if (text.includes("insufficient") && /balance|allowance|funds/.test(text)) {
|
|
56
|
+
return notice(
|
|
57
|
+
"Insufficient balance",
|
|
58
|
+
"You don't have enough balance to complete this transaction.",
|
|
59
|
+
"Add funds to your wallet, then try again."
|
|
60
|
+
);
|
|
97
61
|
}
|
|
98
|
-
return
|
|
62
|
+
return notice("Something went wrong", fallback ?? GENERIC);
|
|
99
63
|
}
|
|
100
64
|
export {
|
|
101
65
|
GENERIC,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/describe-error.ts"],"sourcesContent":["import { MedialaneApiError, PasskeyCancelledError } from \"@medialane/sdk\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/utils/describe-error.ts"],"sourcesContent":["import { MedialaneApiError, PasskeyCancelledError, UserFacingError } from \"@medialane/sdk\";\nimport { WrongNetworkError, isBareExecuteFailure, isUserRejectedRequest, collectErrorText } from \"./wallet-error.js\";\n\nexport const NOT_SUBMITTED = \"Request not completed. Nothing was submitted.\";\nexport const GENERIC = \"Something went wrong. Please try again.\";\nexport const NETWORK_BUSY =\n \"The network is busy right now. Nothing was submitted. Please try again in a moment.\";\n\nexport interface ErrorNotice {\n title: string;\n message: string;\n description?: string;\n isUserRejection: boolean;\n}\n\nconst notice = (title: string, message: string, description?: string): ErrorNotice => ({\n title,\n message,\n description,\n isUserRejection: false,\n});\n\nfunction isTransient(error: unknown): boolean {\n if (error instanceof MedialaneApiError) {\n return error.status === 408 || error.status === 429 || error.status >= 500;\n }\n return /-32001|unable to complete request|service unavailable|temporarily unavailable|rate.?limit|too many requests|gateway time-?out|bad gateway|failed to fetch|fetch failed|network ?error|load failed/i.test(\n collectErrorText(error),\n );\n}\n\nfunction apiReason(error: MedialaneApiError): string | undefined {\n const body = error.details;\n if (body && typeof body === \"object\" && \"error\" in body) {\n const reason = (body as { error?: unknown }).error;\n if (typeof reason === \"string\" && reason.trim() !== \"\") return reason;\n }\n return undefined;\n}\n\nexport function describeError(error: unknown, fallback?: string): ErrorNotice {\n if (error instanceof PasskeyCancelledError || isUserRejectedRequest(error)) {\n const unclear = isBareExecuteFailure(error) || error instanceof PasskeyCancelledError;\n return {\n title: \"Request not completed\",\n message: NOT_SUBMITTED,\n description: unclear\n ? \"Your wallet didn't complete this request. You may have closed or declined it, it may need extra verification such as 2FA before it can sign, or it may have hit a temporary network hiccup. Try again in a moment.\"\n : \"Your wallet didn't complete this request. You may have closed or declined it, or it may need extra verification before it can sign.\",\n isUserRejection: true,\n };\n }\n\n if (error instanceof WrongNetworkError) {\n return notice(\n \"Wrong network\",\n \"Your wallet is connected to the wrong network. Nothing was submitted.\",\n \"Switch your wallet to Starknet Mainnet, then try again.\",\n );\n }\n\n if (isTransient(error)) {\n return notice(\"Network busy\", NETWORK_BUSY);\n }\n\n if (error instanceof UserFacingError) {\n return notice(\"Something went wrong\", error.message);\n }\n\n if (error instanceof MedialaneApiError) {\n return notice(\"Something went wrong\", apiReason(error) ?? fallback ?? GENERIC);\n }\n\n const text = collectErrorText(error).toLowerCase();\n if (text.includes(\"insufficient\") && /balance|allowance|funds/.test(text)) {\n return notice(\n \"Insufficient balance\",\n \"You don't have enough balance to complete this transaction.\",\n \"Add funds to your wallet, then try again.\",\n );\n }\n\n return notice(\"Something went wrong\", fallback ?? GENERIC);\n}\n\nexport { UserFacingError };\n"],"mappings":"AAAA,SAAS,mBAAmB,uBAAuB,uBAAuB;AAC1E,SAAS,mBAAmB,sBAAsB,uBAAuB,wBAAwB;AAE1F,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAChB,MAAM,eACX;AASF,MAAM,SAAS,CAAC,OAAe,SAAiB,iBAAuC;AAAA,EACrF;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB;AAEA,SAAS,YAAY,OAAyB;AAC5C,MAAI,iBAAiB,mBAAmB;AACtC,WAAO,MAAM,WAAW,OAAO,MAAM,WAAW,OAAO,MAAM,UAAU;AAAA,EACzE;AACA,SAAO,qMAAqM;AAAA,IAC1M,iBAAiB,KAAK;AAAA,EACxB;AACF;AAEA,SAAS,UAAU,OAA8C;AAC/D,QAAM,OAAO,MAAM;AACnB,MAAI,QAAQ,OAAO,SAAS,YAAY,WAAW,MAAM;AACvD,UAAM,SAAU,KAA6B;AAC7C,QAAI,OAAO,WAAW,YAAY,OAAO,KAAK,MAAM,GAAI,QAAO;AAAA,EACjE;AACA,SAAO;AACT;AAEO,SAAS,cAAc,OAAgB,UAAgC;AAC5E,MAAI,iBAAiB,yBAAyB,sBAAsB,KAAK,GAAG;AAC1E,UAAM,UAAU,qBAAqB,KAAK,KAAK,iBAAiB;AAChE,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,aAAa,UACT,uNACA;AAAA,MACJ,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,iBAAiB,mBAAmB;AACtC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO,OAAO,gBAAgB,YAAY;AAAA,EAC5C;AAEA,MAAI,iBAAiB,iBAAiB;AACpC,WAAO,OAAO,wBAAwB,MAAM,OAAO;AAAA,EACrD;AAEA,MAAI,iBAAiB,mBAAmB;AACtC,WAAO,OAAO,wBAAwB,UAAU,KAAK,KAAK,YAAY,OAAO;AAAA,EAC/E;AAEA,QAAM,OAAO,iBAAiB,KAAK,EAAE,YAAY;AACjD,MAAI,KAAK,SAAS,cAAc,KAAK,0BAA0B,KAAK,IAAI,GAAG;AACzE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,wBAAwB,YAAY,OAAO;AAC3D;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@medialane/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.167.0",
|
|
4
4
|
"description": "Shared UI components for Medialane apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"preview": "vite --config preview/vite.config.ts"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@medialane/sdk": ">=0.
|
|
54
|
+
"@medialane/sdk": ">=0.129.0",
|
|
55
55
|
"@radix-ui/react-checkbox": ">=1.1.0",
|
|
56
56
|
"@radix-ui/react-collapsible": ">=1.1.0",
|
|
57
57
|
"@radix-ui/react-dialog": ">=1.1.0",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"zod": "^3.25.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@medialane/sdk": "0.
|
|
82
|
+
"@medialane/sdk": "0.129.0",
|
|
83
83
|
"@radix-ui/react-checkbox": "^1.3.8",
|
|
84
84
|
"@radix-ui/react-collapsible": "^1.1.17",
|
|
85
85
|
"@radix-ui/react-dialog": "^1.1.20",
|