@thenamespace/ens-components 0.0.5-alpha → 0.0.6-alpha

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.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { forwardRef, createElement, useState, useRef, useEffect, useMemo, useCallback, createContext, useContext } from 'react';
3
- import { isAddress as isAddress$1, parseAbi } from 'viem';
2
+ import { forwardRef, createElement, useState, useRef, useEffect, useCallback, useMemo, createContext, useContext } from 'react';
3
+ import { isAddress as isAddress$1, parseAbi, namehash, encodeFunctionData, toHex, ContractFunctionExecutionError } from 'viem';
4
4
  import { mainnet, base as base$1, arbitrum, polygon, optimism, zora } from 'viem/chains';
5
- import { usePublicClient, useWalletClient } from 'wagmi';
5
+ import { usePublicClient, useWalletClient, useAccount, useSwitchChain } from 'wagmi';
6
6
 
7
7
  const sizeToClass = {
8
8
  sm: "ns-btn--sm",
@@ -1116,6 +1116,431 @@ const Tooltip = ({
1116
1116
  );
1117
1117
  };
1118
1118
 
1119
+ var TransactionState = /* @__PURE__ */ ((TransactionState2) => {
1120
+ TransactionState2["InProgress"] = "In Progress";
1121
+ TransactionState2["Completed"] = "Completed";
1122
+ TransactionState2["Failed"] = "Failed";
1123
+ return TransactionState2;
1124
+ })(TransactionState || {});
1125
+ const PendingTransaction = ({
1126
+ state,
1127
+ blockExplorerUrl,
1128
+ transactionHash,
1129
+ className = ""
1130
+ }) => {
1131
+ const getStatusIcon = () => {
1132
+ switch (state) {
1133
+ case "In Progress" /* InProgress */:
1134
+ return /* @__PURE__ */ jsx("div", { className: "ns-pending-tx__spinner" });
1135
+ case "Completed" /* Completed */:
1136
+ return /* @__PURE__ */ jsx(Icon, { name: "check-circle", size: 24 });
1137
+ case "Failed" /* Failed */:
1138
+ return /* @__PURE__ */ jsx(Icon, { name: "x-circle", size: 24 });
1139
+ default:
1140
+ return null;
1141
+ }
1142
+ };
1143
+ const getStatusMessage = () => {
1144
+ switch (state) {
1145
+ case "In Progress" /* InProgress */:
1146
+ return "Transaction is being executed...";
1147
+ case "Completed" /* Completed */:
1148
+ return "Transaction completed successfully!";
1149
+ case "Failed" /* Failed */:
1150
+ return "Transaction failed!";
1151
+ default:
1152
+ return "";
1153
+ }
1154
+ };
1155
+ const getStatusClass = () => {
1156
+ switch (state) {
1157
+ case "In Progress" /* InProgress */:
1158
+ return "ns-pending-tx--in-progress";
1159
+ case "Completed" /* Completed */:
1160
+ return "ns-pending-tx--completed";
1161
+ case "Failed" /* Failed */:
1162
+ return "ns-pending-tx--failed";
1163
+ default:
1164
+ return "";
1165
+ }
1166
+ };
1167
+ const getIconClass = () => {
1168
+ switch (state) {
1169
+ case "In Progress" /* InProgress */:
1170
+ return "ns-pending-tx__icon--in-progress";
1171
+ case "Completed" /* Completed */:
1172
+ return "ns-pending-tx__icon--completed";
1173
+ case "Failed" /* Failed */:
1174
+ return "ns-pending-tx__icon--failed";
1175
+ default:
1176
+ return "";
1177
+ }
1178
+ };
1179
+ return /* @__PURE__ */ jsx("div", { className: `ns-pending-tx ${getStatusClass()} ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "ns-pending-tx__content", children: [
1180
+ /* @__PURE__ */ jsx("div", { className: `ns-pending-tx__icon ${getIconClass()}`, children: getStatusIcon() }),
1181
+ /* @__PURE__ */ jsx("div", { className: "ns-pending-tx__status", children: /* @__PURE__ */ jsx(Text, { children: getStatusMessage() }) }),
1182
+ transactionHash && /* @__PURE__ */ jsxs("p", { className: "ns-pending-tx__message", children: [
1183
+ "Hash: ",
1184
+ transactionHash.slice(0, 10),
1185
+ "...",
1186
+ transactionHash.slice(-8)
1187
+ ] }),
1188
+ /* @__PURE__ */ jsxs(
1189
+ "a",
1190
+ {
1191
+ href: blockExplorerUrl,
1192
+ target: "_blank",
1193
+ rel: "noopener noreferrer",
1194
+ className: "ns-pending-tx__link",
1195
+ children: [
1196
+ /* @__PURE__ */ jsx(Icon, { name: "globe", size: 16, className: "ns-pending-tx__link-icon" }),
1197
+ "View on Block Explorer"
1198
+ ]
1199
+ }
1200
+ )
1201
+ ] }) });
1202
+ };
1203
+
1204
+ const Dropdown = ({
1205
+ trigger,
1206
+ children,
1207
+ placement = "bottom",
1208
+ align = "start",
1209
+ disabled = false,
1210
+ dataTestId
1211
+ }) => {
1212
+ const [isOpen, setIsOpen] = useState(false);
1213
+ const triggerRef = useRef(null);
1214
+ const dropdownRef = useRef(null);
1215
+ const handleToggle = useCallback(() => {
1216
+ if (!disabled) {
1217
+ setIsOpen((prev) => !prev);
1218
+ }
1219
+ }, [disabled]);
1220
+ const handleClickOutside = useCallback((event) => {
1221
+ if (triggerRef.current && !triggerRef.current.contains(event.target) && dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1222
+ setIsOpen(false);
1223
+ }
1224
+ }, []);
1225
+ useEffect(() => {
1226
+ if (isOpen) {
1227
+ document.addEventListener("mousedown", handleClickOutside);
1228
+ document.addEventListener("keydown", (e) => {
1229
+ if (e.key === "Escape") setIsOpen(false);
1230
+ });
1231
+ }
1232
+ return () => {
1233
+ document.removeEventListener("mousedown", handleClickOutside);
1234
+ };
1235
+ }, [isOpen, handleClickOutside]);
1236
+ const getPlacementClasses = () => {
1237
+ const placementClass = `ns-dropdown--${placement}`;
1238
+ const alignClass = `ns-dropdown--align-${align}`;
1239
+ return `${placementClass} ${alignClass}`;
1240
+ };
1241
+ return /* @__PURE__ */ jsxs("div", { className: "ns-dropdown", "data-test-id": dataTestId, children: [
1242
+ /* @__PURE__ */ jsx(
1243
+ "div",
1244
+ {
1245
+ ref: triggerRef,
1246
+ className: "ns-dropdown__trigger",
1247
+ onClick: handleToggle,
1248
+ role: "button",
1249
+ tabIndex: disabled ? -1 : 0,
1250
+ "aria-expanded": isOpen,
1251
+ "aria-haspopup": "true",
1252
+ onKeyDown: (e) => {
1253
+ if (e.key === "Enter" || e.key === " ") {
1254
+ e.preventDefault();
1255
+ handleToggle();
1256
+ }
1257
+ },
1258
+ children: trigger
1259
+ }
1260
+ ),
1261
+ isOpen && /* @__PURE__ */ jsx(
1262
+ "div",
1263
+ {
1264
+ ref: dropdownRef,
1265
+ className: `ns-dropdown__menu ${getPlacementClasses()}`,
1266
+ role: "menu",
1267
+ "aria-orientation": "vertical",
1268
+ children
1269
+ }
1270
+ )
1271
+ ] });
1272
+ };
1273
+
1274
+ var ContenthashProtocol = /* @__PURE__ */ ((ContenthashProtocol2) => {
1275
+ ContenthashProtocol2["Ipfs"] = "ipfs";
1276
+ ContenthashProtocol2["Onion"] = "onion3";
1277
+ ContenthashProtocol2["Arweave"] = "arweave";
1278
+ ContenthashProtocol2["Skynet"] = "skynet";
1279
+ ContenthashProtocol2["Swarm"] = "swarm";
1280
+ return ContenthashProtocol2;
1281
+ })(ContenthashProtocol || {});
1282
+
1283
+ const IpfsIcon = ({ size = 20 }) => {
1284
+ return /* @__PURE__ */ jsxs(
1285
+ "svg",
1286
+ {
1287
+ xmlns: "http://www.w3.org/2000/svg",
1288
+ width: size,
1289
+ height: size,
1290
+ viewBox: "0 0 20 22",
1291
+ fill: "none",
1292
+ children: [
1293
+ /* @__PURE__ */ jsx(
1294
+ "path",
1295
+ {
1296
+ fill: "#469EA2",
1297
+ d: "m0 16.44 9.56 5.48 9.559-5.48V5.48L9.559 0 0 5.48z"
1298
+ }
1299
+ ),
1300
+ /* @__PURE__ */ jsx(
1301
+ "path",
1302
+ {
1303
+ fill: "#6ACAD1",
1304
+ d: "M8.58 1.31 1.64 5.289a2 2 0 0 1 0 .373l6.93 3.977a1.66 1.66 0 0 1 1.97 0l6.93-3.977a2 2 0 0 1 0-.373l-6.92-3.977a1.66 1.66 0 0 1-1.968 0m9.56 5.447-6.942 4.023c.038.348-.036.7-.212 1.005a1.67 1.67 0 0 1-.766.69l.011 7.91q.17.073.319.18l6.93-3.978c-.037-.348.037-.7.213-1.005s.444-.545.766-.69V6.939a2.3 2.3 0 0 1-.319-.181M.98 6.802q-.15.107-.319.181v7.955c.326.139.598.38.775.685.176.306.248.66.204 1.01l6.93 3.977q.15-.107.32-.18v-7.955a1.63 1.63 0 0 1-.775-.686 1.6 1.6 0 0 1-.205-1.01z"
1305
+ }
1306
+ ),
1307
+ /* @__PURE__ */ jsx(
1308
+ "path",
1309
+ {
1310
+ fill: "#469EA2",
1311
+ d: "m9.56 1.186 8.546 4.904v9.797L9.56 20.791l-8.547-4.904V6.079zm0-1.163L0 5.503v10.96l9.56 5.48 9.559-5.48V5.503z"
1312
+ }
1313
+ ),
1314
+ /* @__PURE__ */ jsx(
1315
+ "path",
1316
+ {
1317
+ fill: "#469EA2",
1318
+ d: "M9.628 12.825H9.49a1.8 1.8 0 0 1-1.264-.518 1.77 1.77 0 0 1-.522-1.256v-.136a1.76 1.76 0 0 1 .521-1.255 1.78 1.78 0 0 1 1.265-.519h.137a1.8 1.8 0 0 1 1.265.519 1.77 1.77 0 0 1 .521 1.255v.136a1.76 1.76 0 0 1-.521 1.256 1.78 1.78 0 0 1-1.265.518m0 7.288H9.49a1.79 1.79 0 0 0-1.559.904l1.628.927 1.627-.927a1.79 1.79 0 0 0-1.56-.904m9.502-5.48h-.068a1.8 1.8 0 0 0-1.265.518 1.77 1.77 0 0 0-.522 1.256v.135a1.7 1.7 0 0 0 .228.86l1.627-.939zM17.503 4.576a1.73 1.73 0 0 0-.228.859v.136a1.76 1.76 0 0 0 .522 1.255 1.78 1.78 0 0 0 1.265.519h.068V5.503zM9.56.023 7.932.949a1.78 1.78 0 0 0 1.56.915h.136A1.79 1.79 0 0 0 11.187.96zM1.627 4.565 0 5.503v1.842h.068a1.8 1.8 0 0 0 1.265-.519 1.77 1.77 0 0 0 .522-1.255v-.136a1.9 1.9 0 0 0-.228-.87M.068 14.633H0v1.83l1.627.938a1.73 1.73 0 0 0 .228-.859v-.135a1.76 1.76 0 0 0-.522-1.256 1.78 1.78 0 0 0-1.265-.518"
1319
+ }
1320
+ ),
1321
+ /* @__PURE__ */ jsx(
1322
+ "path",
1323
+ {
1324
+ fill: "#083B54",
1325
+ fillOpacity: "0.15",
1326
+ d: "M9.56 22V11.028L0 5.548V16.52z"
1327
+ }
1328
+ ),
1329
+ /* @__PURE__ */ jsx(
1330
+ "path",
1331
+ {
1332
+ fill: "#083B54",
1333
+ fillOpacity: "0.05",
1334
+ d: "M19.13 16.418V5.458l-9.56 5.48V21.91z"
1335
+ }
1336
+ )
1337
+ ]
1338
+ }
1339
+ );
1340
+ };
1341
+
1342
+ const OnionIcon = ({ size = 20 }) => {
1343
+ return /* @__PURE__ */ jsx(
1344
+ "svg",
1345
+ {
1346
+ xmlns: "http://www.w3.org/2000/svg",
1347
+ width: size,
1348
+ height: size * 1.18,
1349
+ "data-name": "Layer 1",
1350
+ viewBox: "0 0 161 190",
1351
+ children: /* @__PURE__ */ jsx(
1352
+ "path",
1353
+ {
1354
+ fill: "#7D50CF",
1355
+ d: "M141.67 74.68c-16.3-17.8-41.29-40.85-44-52.41S102.17 0 102.17 0C90.76-.21 84.29 5.54 80.56 12.07 76.9 5.54 70.36-.21 59 0c0 0 7.25 10.62 4.52 22.26s-27.77 34.62-44 52.43c-45.45 49.76-6 115.82 61 115.82s106.53-66.06 61.15-115.83M80.56 175.29c-27 0-57.73-14.51-64.55-43.81-7.76-34.25 25.77-55.29 45.59-75.9l3.23 3.24c1.73 1.65 3.45 3.37 5.25 5-1.44 1.44-2.88 2.8-4.17 4.09C49.47 84 21 102.33 27.21 128.68c5.53 23.63 31.81 34.69 53.35 34.69s47.82-11.06 53.35-34.69c6.18-26.35-22.26-44.73-38.7-60.75C87.45 60.32 79.7 52.57 72 44.81a95 95 0 0 0 8.41-10.05l.14-.14.14.14c20.76 30.09 74.25 54.57 64.49 96.72-6.89 29.3-37.55 43.81-64.62 43.81m20.54-66.14a48 48 0 0 0-4.46-4.67l8.36-8.76c12.07 12.35 23.56 27.79 5.82 42.87-7.68 6.54-19.24 9.48-30.37 9.48s-22.62-2.94-30.31-9.48c-17.8-15.15-6.1-30.66 6-43.08l8.33 8.83a37.3 37.3 0 0 0-4.67 4.81c-13.14 16.3 6.1 26.43 20.61 26.43s33.83-10.13 20.69-26.43m-10.7 10.63a19.71 19.71 0 0 1-19.61-.07l4.1-23.41a11.62 11.62 0 1 1 17.3-10.13 11.44 11.44 0 0 1-6 10.13z"
1356
+ }
1357
+ )
1358
+ }
1359
+ );
1360
+ };
1361
+
1362
+ const ArweaveIcon = ({ size = 20 }) => {
1363
+ return /* @__PURE__ */ jsxs(
1364
+ "svg",
1365
+ {
1366
+ xmlns: "http://www.w3.org/2000/svg",
1367
+ xmlSpace: "preserve",
1368
+ width: size,
1369
+ height: size,
1370
+ viewBox: "0 0 31.8 31.8",
1371
+ children: [
1372
+ /* @__PURE__ */ jsx(
1373
+ "circle",
1374
+ {
1375
+ cx: "15.9",
1376
+ cy: "15.9",
1377
+ r: "14.7",
1378
+ fill: "none",
1379
+ stroke: "currentColor",
1380
+ strokeWidth: "2.5",
1381
+ className: "arweave_svg__st0"
1382
+ }
1383
+ ),
1384
+ /* @__PURE__ */ jsx(
1385
+ "path",
1386
+ {
1387
+ fill: "currentColor",
1388
+ d: "M18.7 21.2c-.1-.1-.1-.3-.2-.5 0-.2-.1-.4-.1-.6-.2.2-.4.3-.6.5s-.5.3-.7.4c-.3.1-.5.2-.9.3-.3.1-.7.1-1 .1-.6 0-1.1-.1-1.6-.3s-.9-.4-1.3-.7-.6-.7-.8-1.1-.3-.9-.3-1.4c0-1.2.5-2.2 1.4-2.8.9-.7 2.3-1 4.1-1h1.7v-.7c0-.6-.2-1-.5-1.3-.4-.3-.9-.5-1.6-.5-.6 0-1 .1-1.3.4s-.4.6-.4 1h-3c0-.5.1-1 .3-1.4s.5-.8 1-1.2c.4-.3.9-.6 1.5-.8q.9-.3 2.1-.3c.7 0 1.3.1 1.9.3s1.1.4 1.6.8c.4.3.8.8 1 1.3s.4 1.1.4 1.8v5c0 .6 0 1.1.1 1.5s.2.8.3 1v.2zm-2.9-2.1c.3 0 .6 0 .8-.1.3-.1.5-.2.7-.3s.4-.2.5-.4l.4-.4v-2h-1.5c-.5 0-.9 0-1.2.1s-.6.2-.8.4-.4.3-.5.6c-.1.2-.1.5-.1.7 0 .4.1.7.4 1s.8.4 1.3.4",
1389
+ className: "arweave_svg__st1"
1390
+ }
1391
+ )
1392
+ ]
1393
+ }
1394
+ );
1395
+ };
1396
+
1397
+ const SkynetIcon = ({ size = 20 }) => {
1398
+ return /* @__PURE__ */ jsx(
1399
+ "svg",
1400
+ {
1401
+ xmlns: "http://www.w3.org/2000/svg",
1402
+ width: size,
1403
+ height: size,
1404
+ viewBox: "0 0 24 24",
1405
+ style: { color: "rgb(0, 198, 94)" },
1406
+ children: /* @__PURE__ */ jsx(
1407
+ "path",
1408
+ {
1409
+ fill: "#00c65e",
1410
+ d: "m0 6.46 21.389 11.297a.917.917 0 0 1 .2 1.485h-.011a10 10 0 0 1-2.234 1.53c-6.912 3.474-14.991-1.837-14.543-9.56l2.86 1.975c.856 4.508 5.618 7.11 9.874 5.393zm8.647 3.151 14.366 5.679a.87.87 0 0 1 .52 1.046v.018a.872.872 0 0 1-1.257.526zm5.29-7.437c2.71-.233 6.095.787 8.111 3.387 1.7 2.195 2.05 4.877 1.93 7.646V13.2a.878.878 0 0 1-1.197.745l-9.765-3.86 9.065 2.432a7.3 7.3 0 0 0-1.068-4.563c-2.968-4.768-9.984-4.535-12.63.42a8 8 0 0 0-.397.883L5.555 7.961q.104-.15.214-.296c.116-.241.242-.487.38-.727 1.612-2.79 4.31-4.433 7.156-4.697.21-.018.421-.049.632-.067z"
1411
+ }
1412
+ )
1413
+ }
1414
+ );
1415
+ };
1416
+
1417
+ const SwarmIcon = ({ size = 20 }) => {
1418
+ return /* @__PURE__ */ jsx(
1419
+ "svg",
1420
+ {
1421
+ xmlns: "http://www.w3.org/2000/svg",
1422
+ width: size,
1423
+ height: size * 1.03,
1424
+ fill: "none",
1425
+ children: /* @__PURE__ */ jsxs("g", { fill: "#FF8A00", children: [
1426
+ /* @__PURE__ */ jsx("path", { d: "m0 30.47 8.02 4.502 8.022-4.502v-8.986L8.02 16.977 0 21.484zM26.516.03l-4.24 2.381-.006.036v4.758l4.246 2.382.036.017 4.24-2.376V2.43zM34.4 21.484l-8.02-4.507-8.022 4.507v8.986l8.021 4.502L34.4 30.47z" }),
1427
+ /* @__PURE__ */ jsx("path", { d: "m17.137 1.285-8.01 4.502v8.986l8.022 4.501 8.02-4.501v-3.58l-3.905-2.19-1.054-.59V3.119z" })
1428
+ ] })
1429
+ }
1430
+ );
1431
+ };
1432
+
1433
+ const icons = {
1434
+ [ContenthashProtocol.Ipfs]: IpfsIcon,
1435
+ [ContenthashProtocol.Onion]: OnionIcon,
1436
+ [ContenthashProtocol.Arweave]: ArweaveIcon,
1437
+ [ContenthashProtocol.Skynet]: SkynetIcon,
1438
+ [ContenthashProtocol.Swarm]: SwarmIcon
1439
+ };
1440
+ const ContenthashIcon = (props) => {
1441
+ const { className, size, protocol, ...restProps } = props;
1442
+ const _size = size || 20;
1443
+ const IconComponent = icons[protocol];
1444
+ if (!IconComponent) {
1445
+ console.warn(`No icon found for protocol: ${protocol}`);
1446
+ return null;
1447
+ }
1448
+ return /* @__PURE__ */ jsx("div", { className: `ns-chain-icon ${className || ""}`, children: /* @__PURE__ */ jsx(IconComponent, { size: _size }) });
1449
+ };
1450
+
1451
+ const variantConfig = {
1452
+ error: { icon: "x-circle", colorClass: "ns-alert-error" },
1453
+ warning: { icon: "alert-triangle", colorClass: "ns-alert-warning" },
1454
+ info: { icon: "info", colorClass: "ns-alert-info" },
1455
+ success: { icon: "check-circle", colorClass: "ns-alert-success" }
1456
+ };
1457
+ const Alert = ({
1458
+ variant = "info",
1459
+ children,
1460
+ className = "",
1461
+ onClose,
1462
+ dismissible = false,
1463
+ title
1464
+ }) => {
1465
+ const config = variantConfig[variant];
1466
+ return /* @__PURE__ */ jsx("div", { className: `ns-alert ${config.colorClass} ${className}`, role: "alert", children: /* @__PURE__ */ jsxs("div", { className: "ns-alert-content", children: [
1467
+ /* @__PURE__ */ jsx("div", { className: "ns-alert-icon", children: /* @__PURE__ */ jsx(Icon, { name: config.icon, size: 20 }) }),
1468
+ /* @__PURE__ */ jsxs("div", { className: "ns-alert-message", children: [
1469
+ title && /* @__PURE__ */ jsx("div", { className: "ns-alert-title", children: title }),
1470
+ /* @__PURE__ */ jsx("div", { className: "ns-alert-description", children })
1471
+ ] }),
1472
+ dismissible && onClose && /* @__PURE__ */ jsx(
1473
+ "button",
1474
+ {
1475
+ className: "ns-alert-close",
1476
+ onClick: onClose,
1477
+ "aria-label": "Close alert",
1478
+ type: "button",
1479
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 16 })
1480
+ }
1481
+ )
1482
+ ] }) });
1483
+ };
1484
+
1485
+ const Modal = ({
1486
+ isOpen,
1487
+ onClose,
1488
+ title,
1489
+ children,
1490
+ footer,
1491
+ size = "md",
1492
+ isDismissDisabled,
1493
+ titleId,
1494
+ className = "",
1495
+ style
1496
+ }) => {
1497
+ const overlayRef = useRef(null);
1498
+ const dialogRef = useRef(null);
1499
+ useEffect(() => {
1500
+ if (!isOpen || isDismissDisabled) return;
1501
+ const handleKeyDown = (e) => {
1502
+ if (e.key === "Escape") onClose();
1503
+ };
1504
+ window.addEventListener("keydown", handleKeyDown);
1505
+ return () => window.removeEventListener("keydown", handleKeyDown);
1506
+ }, [isOpen, isDismissDisabled, onClose]);
1507
+ const handleOverlayClick = (e) => {
1508
+ if (isDismissDisabled) return;
1509
+ if (e.target === overlayRef.current) onClose();
1510
+ };
1511
+ if (!isOpen) return null;
1512
+ const sizeClass = `ns-modal--${size}`;
1513
+ const classes = ["ns-modal", className, sizeClass].filter(Boolean).join(" ");
1514
+ return /* @__PURE__ */ jsx(
1515
+ "div",
1516
+ {
1517
+ ref: overlayRef,
1518
+ className: "ns-modal-overlay",
1519
+ onMouseDown: handleOverlayClick,
1520
+ "aria-hidden": !isOpen,
1521
+ children: /* @__PURE__ */ jsxs(
1522
+ "div",
1523
+ {
1524
+ ref: dialogRef,
1525
+ className: classes,
1526
+ role: "dialog",
1527
+ "aria-modal": "true",
1528
+ "aria-labelledby": title ? titleId || "ns-modal-title" : void 0,
1529
+ style,
1530
+ children: [
1531
+ (title || !isDismissDisabled) && /* @__PURE__ */ jsxs("div", { className: "ns-modal__header", children: [
1532
+ title && /* @__PURE__ */ jsx("div", { className: "ns-modal__title", id: titleId || "ns-modal-title", children: typeof title === "string" ? /* @__PURE__ */ jsx(Text, { size: "lg", weight: "medium", children: title }) : title }),
1533
+ !isDismissDisabled && /* @__PURE__ */ jsx("button", { className: "ns-modal__close", "aria-label": "Close", onClick: onClose, children: "\xD7" })
1534
+ ] }),
1535
+ /* @__PURE__ */ jsx("div", { className: "ns-modal__body", children }),
1536
+ /* @__PURE__ */ jsx("div", { className: "ns-modal__footer", children: footer !== void 0 ? footer : /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, children: "Close" }) })
1537
+ ]
1538
+ }
1539
+ )
1540
+ }
1541
+ );
1542
+ };
1543
+
1119
1544
  const capitalize = (value) => {
1120
1545
  return value.charAt(0).toLocaleUpperCase() + value.substring(1);
1121
1546
  };
@@ -9302,7 +9727,7 @@ const nonEvmCoinTypeToNameMap = Object.freeze({
9302
9727
  "5718350": ["wan", "Wanchain"],
9303
9728
  "5741564": ["waves", "Waves"],
9304
9729
  });
9305
- Object.freeze({
9730
+ const coinTypeToNameMap = Object.freeze({
9306
9731
  ...nonEvmCoinTypeToNameMap,
9307
9732
  ...evmCoinTypeToNameMap,
9308
9733
  });
@@ -9341,6 +9766,31 @@ const getCoderByCoinName = (name) => {
9341
9766
  }
9342
9767
  return format;
9343
9768
  };
9769
+ const getCoderByCoinType = (coinType) => {
9770
+ const names = coinTypeToNameMap[String(coinType)];
9771
+ // https://docs.ens.domains/ens-improvement-proposals/ensip-11-evmchain-address-resolution
9772
+ if (coinType >= SLIP44_MSB) {
9773
+ // EVM coin
9774
+ const evmChainId = coinTypeToEvmChainId(coinType);
9775
+ const isUnknownChain = !names;
9776
+ const name = isUnknownChain ? `Unknown Chain (${evmChainId})` : names[0]; // name is derivable
9777
+ const ethFormat = eth;
9778
+ return {
9779
+ name,
9780
+ coinType: coinType,
9781
+ evmChainId,
9782
+ isUnknownChain,
9783
+ encode: ethFormat.encode,
9784
+ decode: ethFormat.decode,
9785
+ };
9786
+ }
9787
+ if (!names) {
9788
+ throw new Error(`Unsupported coin type: ${coinType}`);
9789
+ }
9790
+ const [name] = names;
9791
+ const format = formats[name];
9792
+ return format;
9793
+ };
9344
9794
 
9345
9795
  const isValidEmvAddress = (value) => {
9346
9796
  return isAddress$1(value);
@@ -9449,15 +9899,6 @@ const getSupportedAddressByName = (name) => {
9449
9899
  return supportedAddresses.find((addr) => addr.chainName === name);
9450
9900
  };
9451
9901
 
9452
- var ContenthashProtocol = /* @__PURE__ */ ((ContenthashProtocol2) => {
9453
- ContenthashProtocol2["Ipfs"] = "ipfs";
9454
- ContenthashProtocol2["Onion"] = "onion3";
9455
- ContenthashProtocol2["Arweave"] = "arweave";
9456
- ContenthashProtocol2["Skynet"] = "skynet";
9457
- ContenthashProtocol2["Swarm"] = "swarm";
9458
- return ContenthashProtocol2;
9459
- })(ContenthashProtocol || {});
9460
-
9461
9902
  /**
9462
9903
  * @param {Uint8Array} aa
9463
9904
  * @param {Uint8Array} bb
@@ -11212,567 +11653,236 @@ const TextRecords = ({
11212
11653
  behavior: "smooth",
11213
11654
  block: "center"
11214
11655
  });
11215
- inputRefs.current[lastAddedKey]?.focus();
11216
- setLastAddedKey(null);
11217
- }
11218
- }, [texts, lastAddedKey]);
11219
- const handleTextChanged = (key, value) => {
11220
- const _texts = [...texts];
11221
- for (const text of _texts) {
11222
- if (text.key === key) {
11223
- text.value = value;
11224
- }
11225
- }
11226
- onTextsChanged(_texts);
11227
- };
11228
- const handleTextAdded = (key) => {
11229
- const initialText = initialTexts.find((txt) => txt.key === key);
11230
- onTextsChanged([...texts, { key, value: initialText?.value || "" }]);
11231
- setLastAddedKey(key);
11232
- };
11233
- const handleRemoveText = (key) => {
11234
- onTextsChanged(texts.filter((text) => text.key !== key));
11235
- };
11236
- const filterSuggestions = (record) => {
11237
- if (searchFilter && searchFilter.length > 0) {
11238
- const lowercase = searchFilter.toLocaleLowerCase();
11239
- const label = record.label || "";
11240
- return record.key.toLocaleLowerCase().includes(lowercase) || label.toLocaleLowerCase().includes(lowercase);
11241
- }
11242
- return true;
11243
- };
11244
- const filteredItems = useMemo(() => {
11245
- const shownTextCategory = [category];
11246
- if (category === TextRecordCategory.General) {
11247
- shownTextCategory.push(TextRecordCategory.Image);
11248
- }
11249
- return supportedTexts.filter((record) => filterSuggestions(record) && shownTextCategory.includes(record.category));
11250
- }, [searchFilter]);
11251
- if (filteredItems.length === 0) {
11252
- return /* @__PURE__ */ jsx(Fragment, {});
11253
- }
11254
- return /* @__PURE__ */ jsxs("div", { className: "ns-text-records", children: [
11255
- /* @__PURE__ */ jsx(Text, { className: "ns-mb-2", weight: "bold", children: capitalize(category) }),
11256
- filteredItems.filter((record) => existingTextsMap[record.key] !== void 0).map((record) => {
11257
- const current = existingTextsMap[record.key];
11258
- return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 10 }, children: [
11259
- /* @__PURE__ */ jsx(
11260
- Text,
11261
- {
11262
- style: { marginBottom: "4px" },
11263
- color: "grey",
11264
- size: "xs",
11265
- weight: "medium",
11266
- children: record.label
11267
- }
11268
- ),
11269
- /* @__PURE__ */ jsxs(
11270
- "div",
11271
- {
11272
- style: { width: "100%" },
11273
- className: "d-flex align-items-center",
11274
- children: [
11275
- /* @__PURE__ */ jsx(
11276
- Input,
11277
- {
11278
- ref: (el) => {
11279
- inputRefs.current[record.key] = el;
11280
- },
11281
- style: { width: "100%" },
11282
- onChange: (e) => handleTextChanged(record.key, e.target.value),
11283
- prefix: /* @__PURE__ */ jsx(Icon, { name: record.icon, size: 18, color: "grey" }),
11284
- value: current.value,
11285
- placeholder: record.placeholder
11286
- }
11287
- ),
11288
- /* @__PURE__ */ jsx(
11289
- "div",
11290
- {
11291
- onClick: () => handleRemoveText(record.key),
11292
- className: "ns-close-icon ns-ms-1",
11293
- children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 18 })
11294
- }
11295
- )
11296
- ]
11297
- }
11298
- )
11299
- ] }, record.key);
11300
- }),
11301
- /* @__PURE__ */ jsx("div", { className: "row g-2", children: filteredItems.filter(
11302
- (record) => existingTextsMap[record.key] === void 0 && record.category !== TextRecordCategory.Image && filterSuggestions(record)
11303
- ).map((record) => /* @__PURE__ */ jsx("div", { className: "col col-lg-3 col-sm-6", children: /* @__PURE__ */ jsxs(
11304
- "div",
11305
- {
11306
- className: "ns-text-suggestion",
11307
- onClick: () => handleTextAdded(record.key),
11308
- children: [
11309
- /* @__PURE__ */ jsx(Icon, { size: 18, color: "grey", name: record.icon }),
11310
- /* @__PURE__ */ jsx(Text, { className: "ns-mt-1", size: "xs", weight: "medium", children: record.label })
11311
- ]
11312
- }
11313
- ) }, record.key)) })
11314
- ] });
11315
- };
11316
-
11317
- const AddressRecords = ({
11318
- addresses,
11319
- onAddressesChanged,
11320
- initialAddresses,
11321
- searchFilter
11322
- }) => {
11323
- const existingAddressMap = useMemo(() => {
11324
- const map = {};
11325
- addresses.forEach((addr) => {
11326
- map[addr.coinType] = addr;
11327
- });
11328
- return map;
11329
- }, [addresses]);
11330
- const [lastAddedKey, setLastAddedKey] = useState(null);
11331
- const inputRefs = useRef({});
11332
- useEffect(() => {
11333
- if (lastAddedKey && inputRefs.current[lastAddedKey]) {
11334
- inputRefs.current[lastAddedKey]?.scrollIntoView({
11335
- behavior: "smooth",
11336
- block: "center"
11337
- });
11338
- inputRefs.current[lastAddedKey]?.focus();
11339
- setLastAddedKey(null);
11340
- }
11341
- }, [addresses, lastAddedKey]);
11342
- const handleAddressChanged = (coin, value) => {
11343
- const _addresses = [...addresses];
11344
- for (const addr of _addresses) {
11345
- if (addr.coinType === coin) {
11346
- addr.value = value;
11656
+ inputRefs.current[lastAddedKey]?.focus();
11657
+ setLastAddedKey(null);
11658
+ }
11659
+ }, [texts, lastAddedKey]);
11660
+ const handleTextChanged = (key, value) => {
11661
+ const _texts = [...texts];
11662
+ for (const text of _texts) {
11663
+ if (text.key === key) {
11664
+ text.value = value;
11347
11665
  }
11348
11666
  }
11349
- onAddressesChanged(_addresses);
11667
+ onTextsChanged(_texts);
11350
11668
  };
11351
- const handleAddressAdded = (coin) => {
11352
- const initialAddress = initialAddresses.find((i) => i.coinType === coin);
11353
- onAddressesChanged([
11354
- ...addresses,
11355
- { coinType: coin, value: initialAddress?.value || "" }
11356
- ]);
11357
- setLastAddedKey(`${coin}`);
11669
+ const handleTextAdded = (key) => {
11670
+ const initialText = initialTexts.find((txt) => txt.key === key);
11671
+ onTextsChanged([...texts, { key, value: initialText?.value || "" }]);
11672
+ setLastAddedKey(key);
11358
11673
  };
11359
- const handleRemoveAddress = (coin) => {
11360
- onAddressesChanged(addresses.filter((addr) => addr.coinType !== coin));
11674
+ const handleRemoveText = (key) => {
11675
+ onTextsChanged(texts.filter((text) => text.key !== key));
11361
11676
  };
11362
- const filterAddress = (address) => {
11677
+ const filterSuggestions = (record) => {
11363
11678
  if (searchFilter && searchFilter.length > 0) {
11364
11679
  const lowercase = searchFilter.toLocaleLowerCase();
11365
- return address.chainName.includes(lowercase) || address.label.toLocaleLowerCase().includes(lowercase);
11680
+ const label = record.label || "";
11681
+ return record.key.toLocaleLowerCase().includes(lowercase) || label.toLocaleLowerCase().includes(lowercase);
11366
11682
  }
11367
11683
  return true;
11368
11684
  };
11369
- const filteredAddresses = useMemo(() => {
11370
- return supportedAddresses.filter((record) => filterAddress(record));
11371
- }, [searchFilter]);
11372
- if (filteredAddresses.length === 0) {
11373
- return /* @__PURE__ */ jsx(Fragment, {});
11374
- }
11375
- return /* @__PURE__ */ jsxs("div", { className: "ns-text-records", children: [
11376
- /* @__PURE__ */ jsx(Text, { className: "ns-mb-2", weight: "bold", children: "Addresses" }),
11377
- filteredAddresses.filter((record) => existingAddressMap[record.coinType] !== void 0).map((record) => {
11378
- const current = existingAddressMap[record.coinType];
11379
- const isInvalidAddress = current.value.length > 0 && !record.validateFunc?.(current.value);
11380
- return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 10 }, children: [
11381
- /* @__PURE__ */ jsx(
11382
- Text,
11383
- {
11384
- style: { marginBottom: "4px" },
11385
- color: "grey",
11386
- size: "xs",
11387
- weight: "medium",
11388
- children: record.label
11389
- }
11390
- ),
11391
- /* @__PURE__ */ jsxs(
11392
- "div",
11393
- {
11394
- style: { width: "100%" },
11395
- className: "d-flex align-items-center",
11396
- children: [
11397
- /* @__PURE__ */ jsx(
11398
- Input,
11399
- {
11400
- ref: (el) => {
11401
- inputRefs.current[record.coinType] = el;
11402
- },
11403
- error: isInvalidAddress,
11404
- style: { width: "100%" },
11405
- onChange: (e) => handleAddressChanged(record.coinType, e.target.value),
11406
- prefix: /* @__PURE__ */ jsx(ChainIcon, { chain: record.chainName, size: 18 }),
11407
- value: current.value,
11408
- placeholder: record.placeholder
11409
- }
11410
- ),
11411
- /* @__PURE__ */ jsx(
11412
- "div",
11413
- {
11414
- onClick: () => handleRemoveAddress(record.coinType),
11415
- className: "ns-close-icon ns-ms-1",
11416
- children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 18 })
11417
- }
11418
- )
11419
- ]
11420
- }
11421
- ),
11422
- isInvalidAddress && /* @__PURE__ */ jsx(
11423
- Text,
11424
- {
11425
- size: "xs",
11426
- color: "danger",
11427
- className: "ns-mt-1",
11428
- children: `${record.label} address is not valid`
11429
- }
11430
- )
11431
- ] }, record.chainName);
11432
- }),
11433
- /* @__PURE__ */ jsx("div", { className: "row g-2", children: filteredAddresses.filter((record) => existingAddressMap[record.coinType] === void 0).map((record) => /* @__PURE__ */ jsx("div", { className: "col col-lg-3 col-sm-6", children: /* @__PURE__ */ jsxs(
11434
- "div",
11435
- {
11436
- className: "ns-text-suggestion",
11437
- onClick: () => handleAddressAdded(record.coinType),
11438
- children: [
11439
- /* @__PURE__ */ jsx(ChainIcon, { size: 20, chain: record.chainName }),
11440
- /* @__PURE__ */ jsx(Text, { className: "ns-mt-1", size: "xs", weight: "medium", children: record.label })
11441
- ]
11442
- }
11443
- ) }, record.coinType)) })
11444
- ] });
11445
- };
11446
-
11447
- const Dropdown = ({
11448
- trigger,
11449
- children,
11450
- placement = "bottom",
11451
- align = "start",
11452
- disabled = false,
11453
- dataTestId
11454
- }) => {
11455
- const [isOpen, setIsOpen] = useState(false);
11456
- const triggerRef = useRef(null);
11457
- const dropdownRef = useRef(null);
11458
- const handleToggle = useCallback(() => {
11459
- if (!disabled) {
11460
- setIsOpen((prev) => !prev);
11461
- }
11462
- }, [disabled]);
11463
- const handleClickOutside = useCallback((event) => {
11464
- if (triggerRef.current && !triggerRef.current.contains(event.target) && dropdownRef.current && !dropdownRef.current.contains(event.target)) {
11465
- setIsOpen(false);
11466
- }
11467
- }, []);
11468
- useEffect(() => {
11469
- if (isOpen) {
11470
- document.addEventListener("mousedown", handleClickOutside);
11471
- document.addEventListener("keydown", (e) => {
11472
- if (e.key === "Escape") setIsOpen(false);
11473
- });
11474
- }
11475
- return () => {
11476
- document.removeEventListener("mousedown", handleClickOutside);
11477
- };
11478
- }, [isOpen, handleClickOutside]);
11479
- const getPlacementClasses = () => {
11480
- const placementClass = `ns-dropdown--${placement}`;
11481
- const alignClass = `ns-dropdown--align-${align}`;
11482
- return `${placementClass} ${alignClass}`;
11483
- };
11484
- return /* @__PURE__ */ jsxs("div", { className: "ns-dropdown", "data-test-id": dataTestId, children: [
11485
- /* @__PURE__ */ jsx(
11486
- "div",
11487
- {
11488
- ref: triggerRef,
11489
- className: "ns-dropdown__trigger",
11490
- onClick: handleToggle,
11491
- role: "button",
11492
- tabIndex: disabled ? -1 : 0,
11493
- "aria-expanded": isOpen,
11494
- "aria-haspopup": "true",
11495
- onKeyDown: (e) => {
11496
- if (e.key === "Enter" || e.key === " ") {
11497
- e.preventDefault();
11498
- handleToggle();
11499
- }
11500
- },
11501
- children: trigger
11502
- }
11503
- ),
11504
- isOpen && /* @__PURE__ */ jsx(
11505
- "div",
11506
- {
11507
- ref: dropdownRef,
11508
- className: `ns-dropdown__menu ${getPlacementClasses()}`,
11509
- role: "menu",
11510
- "aria-orientation": "vertical",
11511
- children
11512
- }
11513
- )
11514
- ] });
11515
- };
11516
-
11517
- const IpfsIcon = ({ size = 20 }) => {
11518
- return /* @__PURE__ */ jsxs(
11519
- "svg",
11520
- {
11521
- xmlns: "http://www.w3.org/2000/svg",
11522
- width: size,
11523
- height: size,
11524
- viewBox: "0 0 20 22",
11525
- fill: "none",
11526
- children: [
11527
- /* @__PURE__ */ jsx(
11528
- "path",
11529
- {
11530
- fill: "#469EA2",
11531
- d: "m0 16.44 9.56 5.48 9.559-5.48V5.48L9.559 0 0 5.48z"
11532
- }
11533
- ),
11534
- /* @__PURE__ */ jsx(
11535
- "path",
11536
- {
11537
- fill: "#6ACAD1",
11538
- d: "M8.58 1.31 1.64 5.289a2 2 0 0 1 0 .373l6.93 3.977a1.66 1.66 0 0 1 1.97 0l6.93-3.977a2 2 0 0 1 0-.373l-6.92-3.977a1.66 1.66 0 0 1-1.968 0m9.56 5.447-6.942 4.023c.038.348-.036.7-.212 1.005a1.67 1.67 0 0 1-.766.69l.011 7.91q.17.073.319.18l6.93-3.978c-.037-.348.037-.7.213-1.005s.444-.545.766-.69V6.939a2.3 2.3 0 0 1-.319-.181M.98 6.802q-.15.107-.319.181v7.955c.326.139.598.38.775.685.176.306.248.66.204 1.01l6.93 3.977q.15-.107.32-.18v-7.955a1.63 1.63 0 0 1-.775-.686 1.6 1.6 0 0 1-.205-1.01z"
11539
- }
11540
- ),
11541
- /* @__PURE__ */ jsx(
11542
- "path",
11543
- {
11544
- fill: "#469EA2",
11545
- d: "m9.56 1.186 8.546 4.904v9.797L9.56 20.791l-8.547-4.904V6.079zm0-1.163L0 5.503v10.96l9.56 5.48 9.559-5.48V5.503z"
11546
- }
11547
- ),
11548
- /* @__PURE__ */ jsx(
11549
- "path",
11550
- {
11551
- fill: "#469EA2",
11552
- d: "M9.628 12.825H9.49a1.8 1.8 0 0 1-1.264-.518 1.77 1.77 0 0 1-.522-1.256v-.136a1.76 1.76 0 0 1 .521-1.255 1.78 1.78 0 0 1 1.265-.519h.137a1.8 1.8 0 0 1 1.265.519 1.77 1.77 0 0 1 .521 1.255v.136a1.76 1.76 0 0 1-.521 1.256 1.78 1.78 0 0 1-1.265.518m0 7.288H9.49a1.79 1.79 0 0 0-1.559.904l1.628.927 1.627-.927a1.79 1.79 0 0 0-1.56-.904m9.502-5.48h-.068a1.8 1.8 0 0 0-1.265.518 1.77 1.77 0 0 0-.522 1.256v.135a1.7 1.7 0 0 0 .228.86l1.627-.939zM17.503 4.576a1.73 1.73 0 0 0-.228.859v.136a1.76 1.76 0 0 0 .522 1.255 1.78 1.78 0 0 0 1.265.519h.068V5.503zM9.56.023 7.932.949a1.78 1.78 0 0 0 1.56.915h.136A1.79 1.79 0 0 0 11.187.96zM1.627 4.565 0 5.503v1.842h.068a1.8 1.8 0 0 0 1.265-.519 1.77 1.77 0 0 0 .522-1.255v-.136a1.9 1.9 0 0 0-.228-.87M.068 14.633H0v1.83l1.627.938a1.73 1.73 0 0 0 .228-.859v-.135a1.76 1.76 0 0 0-.522-1.256 1.78 1.78 0 0 0-1.265-.518"
11553
- }
11554
- ),
11555
- /* @__PURE__ */ jsx(
11556
- "path",
11557
- {
11558
- fill: "#083B54",
11559
- fillOpacity: "0.15",
11560
- d: "M9.56 22V11.028L0 5.548V16.52z"
11561
- }
11562
- ),
11563
- /* @__PURE__ */ jsx(
11564
- "path",
11565
- {
11566
- fill: "#083B54",
11567
- fillOpacity: "0.05",
11568
- d: "M19.13 16.418V5.458l-9.56 5.48V21.91z"
11569
- }
11570
- )
11571
- ]
11572
- }
11573
- );
11574
- };
11575
-
11576
- const OnionIcon = ({ size = 20 }) => {
11577
- return /* @__PURE__ */ jsx(
11578
- "svg",
11579
- {
11580
- xmlns: "http://www.w3.org/2000/svg",
11581
- width: size,
11582
- height: size * 1.18,
11583
- "data-name": "Layer 1",
11584
- viewBox: "0 0 161 190",
11585
- children: /* @__PURE__ */ jsx(
11586
- "path",
11587
- {
11588
- fill: "#7D50CF",
11589
- d: "M141.67 74.68c-16.3-17.8-41.29-40.85-44-52.41S102.17 0 102.17 0C90.76-.21 84.29 5.54 80.56 12.07 76.9 5.54 70.36-.21 59 0c0 0 7.25 10.62 4.52 22.26s-27.77 34.62-44 52.43c-45.45 49.76-6 115.82 61 115.82s106.53-66.06 61.15-115.83M80.56 175.29c-27 0-57.73-14.51-64.55-43.81-7.76-34.25 25.77-55.29 45.59-75.9l3.23 3.24c1.73 1.65 3.45 3.37 5.25 5-1.44 1.44-2.88 2.8-4.17 4.09C49.47 84 21 102.33 27.21 128.68c5.53 23.63 31.81 34.69 53.35 34.69s47.82-11.06 53.35-34.69c6.18-26.35-22.26-44.73-38.7-60.75C87.45 60.32 79.7 52.57 72 44.81a95 95 0 0 0 8.41-10.05l.14-.14.14.14c20.76 30.09 74.25 54.57 64.49 96.72-6.89 29.3-37.55 43.81-64.62 43.81m20.54-66.14a48 48 0 0 0-4.46-4.67l8.36-8.76c12.07 12.35 23.56 27.79 5.82 42.87-7.68 6.54-19.24 9.48-30.37 9.48s-22.62-2.94-30.31-9.48c-17.8-15.15-6.1-30.66 6-43.08l8.33 8.83a37.3 37.3 0 0 0-4.67 4.81c-13.14 16.3 6.1 26.43 20.61 26.43s33.83-10.13 20.69-26.43m-10.7 10.63a19.71 19.71 0 0 1-19.61-.07l4.1-23.41a11.62 11.62 0 1 1 17.3-10.13 11.44 11.44 0 0 1-6 10.13z"
11590
- }
11591
- )
11685
+ const filteredItems = useMemo(() => {
11686
+ const shownTextCategory = [category];
11687
+ if (category === TextRecordCategory.General) {
11688
+ shownTextCategory.push(TextRecordCategory.Image);
11592
11689
  }
11593
- );
11594
- };
11595
-
11596
- const ArweaveIcon = ({ size = 20 }) => {
11597
- return /* @__PURE__ */ jsxs(
11598
- "svg",
11599
- {
11600
- xmlns: "http://www.w3.org/2000/svg",
11601
- xmlSpace: "preserve",
11602
- width: size,
11603
- height: size,
11604
- viewBox: "0 0 31.8 31.8",
11605
- children: [
11690
+ return supportedTexts.filter((record) => filterSuggestions(record) && shownTextCategory.includes(record.category));
11691
+ }, [searchFilter]);
11692
+ if (filteredItems.length === 0) {
11693
+ return /* @__PURE__ */ jsx(Fragment, {});
11694
+ }
11695
+ return /* @__PURE__ */ jsxs("div", { className: "ns-text-records", children: [
11696
+ /* @__PURE__ */ jsx(Text, { className: "ns-mb-2", weight: "bold", children: capitalize(category) }),
11697
+ filteredItems.filter((record) => existingTextsMap[record.key] !== void 0).map((record) => {
11698
+ const current = existingTextsMap[record.key];
11699
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 10 }, children: [
11606
11700
  /* @__PURE__ */ jsx(
11607
- "circle",
11701
+ Text,
11608
11702
  {
11609
- cx: "15.9",
11610
- cy: "15.9",
11611
- r: "14.7",
11612
- fill: "none",
11613
- stroke: "currentColor",
11614
- strokeWidth: "2.5",
11615
- className: "arweave_svg__st0"
11703
+ style: { marginBottom: "4px" },
11704
+ color: "grey",
11705
+ size: "xs",
11706
+ weight: "medium",
11707
+ children: record.label
11616
11708
  }
11617
11709
  ),
11618
- /* @__PURE__ */ jsx(
11619
- "path",
11710
+ /* @__PURE__ */ jsxs(
11711
+ "div",
11620
11712
  {
11621
- fill: "currentColor",
11622
- d: "M18.7 21.2c-.1-.1-.1-.3-.2-.5 0-.2-.1-.4-.1-.6-.2.2-.4.3-.6.5s-.5.3-.7.4c-.3.1-.5.2-.9.3-.3.1-.7.1-1 .1-.6 0-1.1-.1-1.6-.3s-.9-.4-1.3-.7-.6-.7-.8-1.1-.3-.9-.3-1.4c0-1.2.5-2.2 1.4-2.8.9-.7 2.3-1 4.1-1h1.7v-.7c0-.6-.2-1-.5-1.3-.4-.3-.9-.5-1.6-.5-.6 0-1 .1-1.3.4s-.4.6-.4 1h-3c0-.5.1-1 .3-1.4s.5-.8 1-1.2c.4-.3.9-.6 1.5-.8q.9-.3 2.1-.3c.7 0 1.3.1 1.9.3s1.1.4 1.6.8c.4.3.8.8 1 1.3s.4 1.1.4 1.8v5c0 .6 0 1.1.1 1.5s.2.8.3 1v.2zm-2.9-2.1c.3 0 .6 0 .8-.1.3-.1.5-.2.7-.3s.4-.2.5-.4l.4-.4v-2h-1.5c-.5 0-.9 0-1.2.1s-.6.2-.8.4-.4.3-.5.6c-.1.2-.1.5-.1.7 0 .4.1.7.4 1s.8.4 1.3.4",
11623
- className: "arweave_svg__st1"
11713
+ style: { width: "100%" },
11714
+ className: "d-flex align-items-center",
11715
+ children: [
11716
+ /* @__PURE__ */ jsx(
11717
+ Input,
11718
+ {
11719
+ ref: (el) => {
11720
+ inputRefs.current[record.key] = el;
11721
+ },
11722
+ style: { width: "100%" },
11723
+ onChange: (e) => handleTextChanged(record.key, e.target.value),
11724
+ prefix: /* @__PURE__ */ jsx(Icon, { name: record.icon, size: 18, color: "grey" }),
11725
+ value: current.value,
11726
+ placeholder: record.placeholder
11727
+ }
11728
+ ),
11729
+ /* @__PURE__ */ jsx(
11730
+ "div",
11731
+ {
11732
+ onClick: () => handleRemoveText(record.key),
11733
+ className: "ns-close-icon ns-ms-1",
11734
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 18 })
11735
+ }
11736
+ )
11737
+ ]
11624
11738
  }
11625
11739
  )
11626
- ]
11627
- }
11628
- );
11740
+ ] }, record.key);
11741
+ }),
11742
+ /* @__PURE__ */ jsx("div", { className: "row g-2", children: filteredItems.filter(
11743
+ (record) => existingTextsMap[record.key] === void 0 && record.category !== TextRecordCategory.Image && filterSuggestions(record)
11744
+ ).map((record) => /* @__PURE__ */ jsx("div", { className: "col col-lg-3 col-sm-6", children: /* @__PURE__ */ jsxs(
11745
+ "div",
11746
+ {
11747
+ className: "ns-text-suggestion",
11748
+ onClick: () => handleTextAdded(record.key),
11749
+ children: [
11750
+ /* @__PURE__ */ jsx(Icon, { size: 18, color: "grey", name: record.icon }),
11751
+ /* @__PURE__ */ jsx(Text, { className: "ns-mt-1", size: "xs", weight: "medium", children: record.label })
11752
+ ]
11753
+ }
11754
+ ) }, record.key)) })
11755
+ ] });
11629
11756
  };
11630
11757
 
11631
- const SkynetIcon = ({ size = 20 }) => {
11632
- return /* @__PURE__ */ jsx(
11633
- "svg",
11634
- {
11635
- xmlns: "http://www.w3.org/2000/svg",
11636
- width: size,
11637
- height: size,
11638
- viewBox: "0 0 24 24",
11639
- style: { color: "rgb(0, 198, 94)" },
11640
- children: /* @__PURE__ */ jsx(
11641
- "path",
11642
- {
11643
- fill: "#00c65e",
11644
- d: "m0 6.46 21.389 11.297a.917.917 0 0 1 .2 1.485h-.011a10 10 0 0 1-2.234 1.53c-6.912 3.474-14.991-1.837-14.543-9.56l2.86 1.975c.856 4.508 5.618 7.11 9.874 5.393zm8.647 3.151 14.366 5.679a.87.87 0 0 1 .52 1.046v.018a.872.872 0 0 1-1.257.526zm5.29-7.437c2.71-.233 6.095.787 8.111 3.387 1.7 2.195 2.05 4.877 1.93 7.646V13.2a.878.878 0 0 1-1.197.745l-9.765-3.86 9.065 2.432a7.3 7.3 0 0 0-1.068-4.563c-2.968-4.768-9.984-4.535-12.63.42a8 8 0 0 0-.397.883L5.555 7.961q.104-.15.214-.296c.116-.241.242-.487.38-.727 1.612-2.79 4.31-4.433 7.156-4.697.21-.018.421-.049.632-.067z"
11645
- }
11646
- )
11758
+ const AddressRecords = ({
11759
+ addresses,
11760
+ onAddressesChanged,
11761
+ initialAddresses,
11762
+ searchFilter
11763
+ }) => {
11764
+ const existingAddressMap = useMemo(() => {
11765
+ const map = {};
11766
+ addresses.forEach((addr) => {
11767
+ map[addr.coinType] = addr;
11768
+ });
11769
+ return map;
11770
+ }, [addresses]);
11771
+ const [lastAddedKey, setLastAddedKey] = useState(null);
11772
+ const inputRefs = useRef({});
11773
+ useEffect(() => {
11774
+ if (lastAddedKey && inputRefs.current[lastAddedKey]) {
11775
+ inputRefs.current[lastAddedKey]?.scrollIntoView({
11776
+ behavior: "smooth",
11777
+ block: "center"
11778
+ });
11779
+ inputRefs.current[lastAddedKey]?.focus();
11780
+ setLastAddedKey(null);
11647
11781
  }
11648
- );
11649
- };
11650
-
11651
- const SwarmIcon = ({ size = 20 }) => {
11652
- return /* @__PURE__ */ jsx(
11653
- "svg",
11654
- {
11655
- xmlns: "http://www.w3.org/2000/svg",
11656
- width: size,
11657
- height: size * 1.03,
11658
- fill: "none",
11659
- children: /* @__PURE__ */ jsxs("g", { fill: "#FF8A00", children: [
11660
- /* @__PURE__ */ jsx("path", { d: "m0 30.47 8.02 4.502 8.022-4.502v-8.986L8.02 16.977 0 21.484zM26.516.03l-4.24 2.381-.006.036v4.758l4.246 2.382.036.017 4.24-2.376V2.43zM34.4 21.484l-8.02-4.507-8.022 4.507v8.986l8.021 4.502L34.4 30.47z" }),
11661
- /* @__PURE__ */ jsx("path", { d: "m17.137 1.285-8.01 4.502v8.986l8.022 4.501 8.02-4.501v-3.58l-3.905-2.19-1.054-.59V3.119z" })
11662
- ] })
11782
+ }, [addresses, lastAddedKey]);
11783
+ const handleAddressChanged = (coin, value) => {
11784
+ const _addresses = [...addresses];
11785
+ for (const addr of _addresses) {
11786
+ if (addr.coinType === coin) {
11787
+ addr.value = value;
11788
+ }
11663
11789
  }
11664
- );
11665
- };
11666
-
11667
- const icons = {
11668
- [ContenthashProtocol.Ipfs]: IpfsIcon,
11669
- [ContenthashProtocol.Onion]: OnionIcon,
11670
- [ContenthashProtocol.Arweave]: ArweaveIcon,
11671
- [ContenthashProtocol.Skynet]: SkynetIcon,
11672
- [ContenthashProtocol.Swarm]: SwarmIcon
11673
- };
11674
- const ContenthashIcon = (props) => {
11675
- const { className, size, protocol, ...restProps } = props;
11676
- const _size = size || 20;
11677
- const IconComponent = icons[protocol];
11678
- if (!IconComponent) {
11679
- console.warn(`No icon found for protocol: ${protocol}`);
11680
- return null;
11790
+ onAddressesChanged(_addresses);
11791
+ };
11792
+ const handleAddressAdded = (coin) => {
11793
+ const initialAddress = initialAddresses.find((i) => i.coinType === coin);
11794
+ onAddressesChanged([
11795
+ ...addresses,
11796
+ { coinType: coin, value: initialAddress?.value || "" }
11797
+ ]);
11798
+ setLastAddedKey(`${coin}`);
11799
+ };
11800
+ const handleRemoveAddress = (coin) => {
11801
+ onAddressesChanged(addresses.filter((addr) => addr.coinType !== coin));
11802
+ };
11803
+ const filterAddress = (address) => {
11804
+ if (searchFilter && searchFilter.length > 0) {
11805
+ const lowercase = searchFilter.toLocaleLowerCase();
11806
+ return address.chainName.includes(lowercase) || address.label.toLocaleLowerCase().includes(lowercase);
11807
+ }
11808
+ return true;
11809
+ };
11810
+ const filteredAddresses = useMemo(() => {
11811
+ return supportedAddresses.filter((record) => filterAddress(record));
11812
+ }, [searchFilter]);
11813
+ if (filteredAddresses.length === 0) {
11814
+ return /* @__PURE__ */ jsx(Fragment, {});
11681
11815
  }
11682
- return /* @__PURE__ */ jsx("div", { className: `ns-chain-icon ${className || ""}`, children: /* @__PURE__ */ jsx(IconComponent, { size: _size }) });
11683
- };
11684
-
11685
- const variantConfig = {
11686
- error: { icon: "x-circle", colorClass: "ns-alert-error" },
11687
- warning: { icon: "alert-triangle", colorClass: "ns-alert-warning" },
11688
- info: { icon: "info", colorClass: "ns-alert-info" },
11689
- success: { icon: "check-circle", colorClass: "ns-alert-success" }
11690
- };
11691
- const Alert = ({
11692
- variant = "info",
11693
- children,
11694
- className = "",
11695
- onClose,
11696
- dismissible = false,
11697
- title
11698
- }) => {
11699
- const config = variantConfig[variant];
11700
- return /* @__PURE__ */ jsx("div", { className: `ns-alert ${config.colorClass} ${className}`, role: "alert", children: /* @__PURE__ */ jsxs("div", { className: "ns-alert-content", children: [
11701
- /* @__PURE__ */ jsx("div", { className: "ns-alert-icon", children: /* @__PURE__ */ jsx(Icon, { name: config.icon, size: 20 }) }),
11702
- /* @__PURE__ */ jsxs("div", { className: "ns-alert-message", children: [
11703
- title && /* @__PURE__ */ jsx("div", { className: "ns-alert-title", children: title }),
11704
- /* @__PURE__ */ jsx("div", { className: "ns-alert-description", children })
11705
- ] }),
11706
- dismissible && onClose && /* @__PURE__ */ jsx(
11707
- "button",
11816
+ return /* @__PURE__ */ jsxs("div", { className: "ns-text-records", children: [
11817
+ /* @__PURE__ */ jsx(Text, { className: "ns-mb-2", weight: "bold", children: "Addresses" }),
11818
+ filteredAddresses.filter((record) => existingAddressMap[record.coinType] !== void 0).map((record) => {
11819
+ const current = existingAddressMap[record.coinType];
11820
+ const isInvalidAddress = current.value.length > 0 && !record.validateFunc?.(current.value);
11821
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: 10 }, children: [
11822
+ /* @__PURE__ */ jsx(
11823
+ Text,
11824
+ {
11825
+ style: { marginBottom: "4px" },
11826
+ color: "grey",
11827
+ size: "xs",
11828
+ weight: "medium",
11829
+ children: record.label
11830
+ }
11831
+ ),
11832
+ /* @__PURE__ */ jsxs(
11833
+ "div",
11834
+ {
11835
+ style: { width: "100%" },
11836
+ className: "d-flex align-items-center",
11837
+ children: [
11838
+ /* @__PURE__ */ jsx(
11839
+ Input,
11840
+ {
11841
+ ref: (el) => {
11842
+ inputRefs.current[record.coinType] = el;
11843
+ },
11844
+ error: isInvalidAddress,
11845
+ style: { width: "100%" },
11846
+ onChange: (e) => handleAddressChanged(record.coinType, e.target.value),
11847
+ prefix: /* @__PURE__ */ jsx(ChainIcon, { chain: record.chainName, size: 18 }),
11848
+ value: current.value,
11849
+ placeholder: record.placeholder
11850
+ }
11851
+ ),
11852
+ /* @__PURE__ */ jsx(
11853
+ "div",
11854
+ {
11855
+ onClick: () => handleRemoveAddress(record.coinType),
11856
+ className: "ns-close-icon ns-ms-1",
11857
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 18 })
11858
+ }
11859
+ )
11860
+ ]
11861
+ }
11862
+ ),
11863
+ isInvalidAddress && /* @__PURE__ */ jsx(
11864
+ Text,
11865
+ {
11866
+ size: "xs",
11867
+ color: "danger",
11868
+ className: "ns-mt-1",
11869
+ children: `${record.label} address is not valid`
11870
+ }
11871
+ )
11872
+ ] }, record.chainName);
11873
+ }),
11874
+ /* @__PURE__ */ jsx("div", { className: "row g-2", children: filteredAddresses.filter((record) => existingAddressMap[record.coinType] === void 0).map((record) => /* @__PURE__ */ jsx("div", { className: "col col-lg-3 col-sm-6", children: /* @__PURE__ */ jsxs(
11875
+ "div",
11708
11876
  {
11709
- className: "ns-alert-close",
11710
- onClick: onClose,
11711
- "aria-label": "Close alert",
11712
- type: "button",
11713
- children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 16 })
11877
+ className: "ns-text-suggestion",
11878
+ onClick: () => handleAddressAdded(record.coinType),
11879
+ children: [
11880
+ /* @__PURE__ */ jsx(ChainIcon, { size: 20, chain: record.chainName }),
11881
+ /* @__PURE__ */ jsx(Text, { className: "ns-mt-1", size: "xs", weight: "medium", children: record.label })
11882
+ ]
11714
11883
  }
11715
- )
11716
- ] }) });
11717
- };
11718
-
11719
- const Modal = ({
11720
- isOpen,
11721
- onClose,
11722
- title,
11723
- children,
11724
- footer,
11725
- size = "md",
11726
- isDismissDisabled,
11727
- titleId,
11728
- className = "",
11729
- style
11730
- }) => {
11731
- const overlayRef = useRef(null);
11732
- const dialogRef = useRef(null);
11733
- useEffect(() => {
11734
- if (!isOpen || isDismissDisabled) return;
11735
- const handleKeyDown = (e) => {
11736
- if (e.key === "Escape") onClose();
11737
- };
11738
- window.addEventListener("keydown", handleKeyDown);
11739
- return () => window.removeEventListener("keydown", handleKeyDown);
11740
- }, [isOpen, isDismissDisabled, onClose]);
11741
- const handleOverlayClick = (e) => {
11742
- if (isDismissDisabled) return;
11743
- if (e.target === overlayRef.current) onClose();
11744
- };
11745
- if (!isOpen) return null;
11746
- const sizeClass = `ns-modal--${size}`;
11747
- const classes = ["ns-modal", className, sizeClass].filter(Boolean).join(" ");
11748
- return /* @__PURE__ */ jsx(
11749
- "div",
11750
- {
11751
- ref: overlayRef,
11752
- className: "ns-modal-overlay",
11753
- onMouseDown: handleOverlayClick,
11754
- "aria-hidden": !isOpen,
11755
- children: /* @__PURE__ */ jsxs(
11756
- "div",
11757
- {
11758
- ref: dialogRef,
11759
- className: classes,
11760
- role: "dialog",
11761
- "aria-modal": "true",
11762
- "aria-labelledby": title ? titleId || "ns-modal-title" : void 0,
11763
- style,
11764
- children: [
11765
- (title || !isDismissDisabled) && /* @__PURE__ */ jsxs("div", { className: "ns-modal__header", children: [
11766
- title && /* @__PURE__ */ jsx("div", { className: "ns-modal__title", id: titleId || "ns-modal-title", children: typeof title === "string" ? /* @__PURE__ */ jsx(Text, { size: "lg", weight: "medium", children: title }) : title }),
11767
- !isDismissDisabled && /* @__PURE__ */ jsx("button", { className: "ns-modal__close", "aria-label": "Close", onClick: onClose, children: "\xD7" })
11768
- ] }),
11769
- /* @__PURE__ */ jsx("div", { className: "ns-modal__body", children }),
11770
- /* @__PURE__ */ jsx("div", { className: "ns-modal__footer", children: footer !== void 0 ? footer : /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, children: "Close" }) })
11771
- ]
11772
- }
11773
- )
11774
- }
11775
- );
11884
+ ) }, record.coinType)) })
11885
+ ] });
11776
11886
  };
11777
11887
 
11778
11888
  const ContenthashRecord = ({
@@ -12094,89 +12204,284 @@ const SelectRecordsForm = ({
12094
12204
  ] });
12095
12205
  };
12096
12206
 
12097
- var TransactionState = /* @__PURE__ */ ((TransactionState2) => {
12098
- TransactionState2["InProgress"] = "In Progress";
12099
- TransactionState2["Completed"] = "Completed";
12100
- TransactionState2["Failed"] = "Failed";
12101
- return TransactionState2;
12102
- })(TransactionState || {});
12103
- const PendingTransaction = ({
12104
- state,
12105
- blockExplorerUrl,
12106
- transactionHash,
12107
- className = ""
12207
+ const SET_TEXT_FUNC = "function setText(bytes32 node, string key, string value)";
12208
+ const SET_ADDRESS_FUNC = "function setAddr(bytes32 node, uint256 coin, bytes value)";
12209
+ const SET_CONTENTHASH_FUNC = "function setContenthash(bytes32 node, bytes value)";
12210
+ const MULTICALL = "function multicall(bytes[] data)";
12211
+ const ENS_RESOLVER_ABI = parseAbi([
12212
+ SET_TEXT_FUNC,
12213
+ SET_ADDRESS_FUNC,
12214
+ SET_CONTENTHASH_FUNC,
12215
+ MULTICALL
12216
+ ]);
12217
+
12218
+ const convertToMulticallResolverData = (name, recordsDiff) => {
12219
+ const node = namehash(name);
12220
+ const resolverMulticallData = [];
12221
+ convertTextData(node, resolverMulticallData, recordsDiff);
12222
+ convertAddressData(node, resolverMulticallData, recordsDiff);
12223
+ convertContenthashData(node, resolverMulticallData, recordsDiff);
12224
+ return resolverMulticallData;
12225
+ };
12226
+ const convertTextData = (node, resolverData, diff) => {
12227
+ const modifiedTexts = [
12228
+ ...diff.textsAdded,
12229
+ ...diff.textsModified
12230
+ ];
12231
+ modifiedTexts.forEach((text) => {
12232
+ const data = encodeFunctionData({
12233
+ functionName: "setText",
12234
+ abi: parseAbi([SET_TEXT_FUNC]),
12235
+ args: [node, text.key, text.value]
12236
+ });
12237
+ resolverData.push(data);
12238
+ });
12239
+ diff.textsModified.forEach((text) => {
12240
+ const data = encodeFunctionData({
12241
+ functionName: "setText",
12242
+ abi: parseAbi([SET_TEXT_FUNC]),
12243
+ args: [node, text.key, ""]
12244
+ });
12245
+ resolverData.push(data);
12246
+ });
12247
+ };
12248
+ const convertAddressData = (node, resolverData, diff) => {
12249
+ const modifiedAddressMap = {};
12250
+ diff.addressesAdded.forEach((addr) => {
12251
+ modifiedAddressMap[addr.coinType] = addr;
12252
+ });
12253
+ diff.addressesModified.forEach((addr) => {
12254
+ modifiedAddressMap[addr.coinType] = addr;
12255
+ });
12256
+ const modifiedAddresses = Object.values(modifiedAddressMap);
12257
+ modifiedAddresses.forEach((addr) => {
12258
+ const coinEncoder = getCoderByCoinType(addr.coinType);
12259
+ if (!coinEncoder) {
12260
+ throw Error(
12261
+ `Coin type is not supported: ${addr.coinType}. Cannot get an encoder`
12262
+ );
12263
+ }
12264
+ const decode = coinEncoder.decode(addr.value);
12265
+ const hexValue = toHex(decode);
12266
+ const data = encodeFunctionData({
12267
+ functionName: "setAddr",
12268
+ abi: parseAbi([SET_ADDRESS_FUNC]),
12269
+ args: [node, BigInt(addr.coinType), hexValue]
12270
+ });
12271
+ resolverData.push(data);
12272
+ });
12273
+ diff.addressesRemoved.forEach((addr) => {
12274
+ const data = encodeFunctionData({
12275
+ functionName: "setAddr",
12276
+ abi: parseAbi([SET_ADDRESS_FUNC]),
12277
+ args: [node, BigInt(addr.coinType), "0x"]
12278
+ });
12279
+ resolverData.push(data);
12280
+ });
12281
+ };
12282
+ const convertContenthashData = (node, resolverData, diff) => {
12283
+ if (diff.contenthashRemoved) {
12284
+ const data = encodeFunctionData({
12285
+ functionName: "setContenthash",
12286
+ abi: parseAbi([SET_CONTENTHASH_FUNC]),
12287
+ args: [node, "0x"]
12288
+ });
12289
+ resolverData.push(data);
12290
+ return;
12291
+ }
12292
+ let contenthash = void 0;
12293
+ if (diff.contenthashModified !== void 0) {
12294
+ contenthash = diff.contenthashModified;
12295
+ } else if (diff.contenthashAdded !== void 0) {
12296
+ contenthash = diff.contenthashAdded;
12297
+ }
12298
+ if (contenthash !== void 0) {
12299
+ const { protocol, value } = contenthash;
12300
+ const encodedValue = `0x${encode(protocol, value)}`;
12301
+ const data = encodeFunctionData({
12302
+ functionName: "setContenthash",
12303
+ abi: parseAbi([SET_CONTENTHASH_FUNC]),
12304
+ args: [node, encodedValue]
12305
+ });
12306
+ resolverData.push(data);
12307
+ }
12308
+ };
12309
+
12310
+ const addressMapByCoin = getSupportedAddressMap();
12311
+ const EnsRecordsForm = ({
12312
+ name,
12313
+ initialRecords,
12314
+ chainId,
12315
+ resolverAddress,
12316
+ onCancel,
12317
+ onSuccess
12108
12318
  }) => {
12109
- const getStatusIcon = () => {
12110
- switch (state) {
12111
- case "In Progress" /* InProgress */:
12112
- return /* @__PURE__ */ jsx("div", { className: "ns-pending-tx__spinner" });
12113
- case "Completed" /* Completed */:
12114
- return /* @__PURE__ */ jsx(Icon, { name: "check-circle", size: 24 });
12115
- case "Failed" /* Failed */:
12116
- return /* @__PURE__ */ jsx(Icon, { name: "x-circle", size: 24 });
12117
- default:
12118
- return null;
12319
+ const [records, setRecords] = useState(
12320
+ initialRecords ? deepCopy(initialRecords) : { texts: [], addresses: [] }
12321
+ );
12322
+ const currentChainId = chainId || mainnet.id;
12323
+ const publicClient = usePublicClient({ chainId: currentChainId });
12324
+ const { data: walletClient } = useWalletClient({ chainId: currentChainId });
12325
+ const { address, chain, isConnected } = useAccount();
12326
+ const { switchChain } = useSwitchChain();
12327
+ const [contractError, setContractError] = useState(null);
12328
+ const [generalError, setGeneralError] = useState(null);
12329
+ const [txIndicator, setTxIndicator] = useState({
12330
+ isWaitingForTx: false,
12331
+ isWaitingForWallet: false
12332
+ });
12333
+ const shouldSwitchNetwork = chain && chain.id !== currentChainId;
12334
+ useEffect(() => {
12335
+ if (!address) {
12336
+ setGeneralError({
12337
+ title: "Not connected",
12338
+ subtitle: "Connect wallet to continue"
12339
+ });
12340
+ } else {
12341
+ setGeneralError(null);
12342
+ }
12343
+ }, [address, publicClient, walletClient]);
12344
+ const areValidAddresses = useMemo(() => {
12345
+ for (const addr of records.addresses) {
12346
+ const validateFuc = addressMapByCoin[addr.coinType].validateFunc;
12347
+ if (!validateFuc) {
12348
+ throw Error("Validate function not present for coin:" + addr.coinType);
12349
+ }
12350
+ if (addr.value?.length === 0 || !validateFuc(addr.value)) {
12351
+ return false;
12352
+ }
12119
12353
  }
12120
- };
12121
- const getStatusMessage = () => {
12122
- switch (state) {
12123
- case "In Progress" /* InProgress */:
12124
- return "Transaction is being executed...";
12125
- case "Completed" /* Completed */:
12126
- return "Transaction completed successfully!";
12127
- case "Failed" /* Failed */:
12128
- return "Transaction failed!";
12129
- default:
12130
- return "";
12354
+ return true;
12355
+ }, [records.addresses]);
12356
+ const areValidTexts = useMemo(() => {
12357
+ for (const text of records.texts) {
12358
+ if (text.value.length === 0) {
12359
+ return false;
12360
+ }
12361
+ }
12362
+ return true;
12363
+ }, [records.texts]);
12364
+ useMemo(() => {
12365
+ if (!records.contenthash) {
12366
+ return true;
12131
12367
  }
12368
+ return isContenthashValid(
12369
+ records.contenthash.protocol,
12370
+ records.contenthash.value
12371
+ );
12372
+ }, [records.contenthash]);
12373
+ const getInitalRecords = () => {
12374
+ return initialRecords ? initialRecords : { texts: [], addresses: [] };
12132
12375
  };
12133
- const getStatusClass = () => {
12134
- switch (state) {
12135
- case "In Progress" /* InProgress */:
12136
- return "ns-pending-tx--in-progress";
12137
- case "Completed" /* Completed */:
12138
- return "ns-pending-tx--completed";
12139
- case "Failed" /* Failed */:
12140
- return "ns-pending-tx--failed";
12141
- default:
12142
- return "";
12376
+ const isDiffPresent = useMemo(() => {
12377
+ const diff = getEnsRecordsDiff(getInitalRecords(), records);
12378
+ const {
12379
+ addressesAdded,
12380
+ addressesModified,
12381
+ addressesRemoved,
12382
+ textsAdded,
12383
+ textsModified,
12384
+ textsRemoved,
12385
+ contenthashRemoved,
12386
+ contenthashAdded,
12387
+ contenthashModified
12388
+ } = diff;
12389
+ return addressesAdded.length > 0 || addressesModified.length > 0 || addressesRemoved.length || textsAdded.length > 0 || textsRemoved.length > 0 || textsModified.length > 0 || contenthashRemoved === true || contenthashModified !== void 0 || contenthashAdded !== void 0;
12390
+ }, [records, initialRecords]);
12391
+ const handleUpdateRecords = async () => {
12392
+ try {
12393
+ const old = initialRecords ? initialRecords : { texts: [], addresses: [] };
12394
+ const diff = getEnsRecordsDiff(old, records);
12395
+ const resolverData = convertToMulticallResolverData(name, diff);
12396
+ setTxIndicator({ ...txIndicator, isWaitingForWallet: true });
12397
+ const { request } = await publicClient.simulateContract({
12398
+ abi: ENS_RESOLVER_ABI,
12399
+ args: [resolverData],
12400
+ functionName: "multicall",
12401
+ address: resolverAddress,
12402
+ account: address
12403
+ });
12404
+ const tx = await walletClient.writeContract(request);
12405
+ setTxIndicator({ isWaitingForTx: true, isWaitingForWallet: false });
12406
+ await publicClient.waitForTransactionReceipt({ hash: tx });
12407
+ onSuccess?.(tx);
12408
+ } catch (err) {
12409
+ console.error(err);
12410
+ if (err instanceof ContractFunctionExecutionError) {
12411
+ const _err = err;
12412
+ setContractError(_err.details);
12413
+ } else {
12414
+ setContractError("Transaction failed for unknown reason!");
12415
+ }
12416
+ } finally {
12417
+ setTxIndicator({ isWaitingForTx: false, isWaitingForWallet: false });
12143
12418
  }
12144
12419
  };
12145
- const getIconClass = () => {
12146
- switch (state) {
12147
- case "In Progress" /* InProgress */:
12148
- return "ns-pending-tx__icon--in-progress";
12149
- case "Completed" /* Completed */:
12150
- return "ns-pending-tx__icon--completed";
12151
- case "Failed" /* Failed */:
12152
- return "ns-pending-tx__icon--failed";
12153
- default:
12154
- return "";
12420
+ const getActionButton = () => {
12421
+ const areInputsValue = areValidAddresses && areValidTexts && isContenthashValid;
12422
+ const style = { width: "100%" };
12423
+ if (!isConnected) {
12424
+ return /* @__PURE__ */ jsx(
12425
+ Button,
12426
+ {
12427
+ style,
12428
+ size: "lg",
12429
+ disabled: true,
12430
+ prefix: /* @__PURE__ */ jsx(Icon, { name: "alert-triangle" }),
12431
+ children: "Connect Wallet"
12432
+ }
12433
+ );
12434
+ } else if (shouldSwitchNetwork) {
12435
+ return /* @__PURE__ */ jsx(
12436
+ Button,
12437
+ {
12438
+ style,
12439
+ size: "lg",
12440
+ onClick: () => switchChain({ chainId: currentChainId }),
12441
+ children: "Switch Network"
12442
+ }
12443
+ );
12444
+ } else if (!areInputsValue) {
12445
+ return /* @__PURE__ */ jsx(Tooltip, { content: "Invalid inputs", position: "top", children: /* @__PURE__ */ jsx(Button, { style, size: "lg", disabled: true, children: "Update" }) });
12446
+ } else if (!isDiffPresent) {
12447
+ return /* @__PURE__ */ jsx(Tooltip, { content: "No Records updated", position: "top", children: /* @__PURE__ */ jsx(Button, { style, size: "lg", disabled: true, children: "Update" }) });
12448
+ } else {
12449
+ const updateBtnLoading = txIndicator.isWaitingForTx || txIndicator.isWaitingForWallet;
12450
+ return /* @__PURE__ */ jsx(
12451
+ Button,
12452
+ {
12453
+ style,
12454
+ size: "lg",
12455
+ disabled: updateBtnLoading,
12456
+ loading: updateBtnLoading,
12457
+ onClick: () => handleUpdateRecords(),
12458
+ children: "Update"
12459
+ }
12460
+ );
12155
12461
  }
12156
12462
  };
12157
- return /* @__PURE__ */ jsx("div", { className: `ns-pending-tx ${getStatusClass()} ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "ns-pending-tx__content", children: [
12158
- /* @__PURE__ */ jsx("div", { className: `ns-pending-tx__icon ${getIconClass()}`, children: getStatusIcon() }),
12159
- /* @__PURE__ */ jsx("div", { className: "ns-pending-tx__status", children: /* @__PURE__ */ jsx(Text, { children: getStatusMessage() }) }),
12160
- transactionHash && /* @__PURE__ */ jsxs("p", { className: "ns-pending-tx__message", children: [
12161
- "Hash: ",
12162
- transactionHash.slice(0, 10),
12163
- "...",
12164
- transactionHash.slice(-8)
12165
- ] }),
12166
- /* @__PURE__ */ jsxs(
12167
- "a",
12463
+ return /* @__PURE__ */ jsxs("div", { className: "ns-edit-records-form", children: [
12464
+ /* @__PURE__ */ jsx(
12465
+ SelectRecordsForm,
12168
12466
  {
12169
- href: blockExplorerUrl,
12170
- target: "_blank",
12171
- rel: "noopener noreferrer",
12172
- className: "ns-pending-tx__link",
12173
- children: [
12174
- /* @__PURE__ */ jsx(Icon, { name: "globe", size: 16, className: "ns-pending-tx__link-icon" }),
12175
- "View on Block Explorer"
12176
- ]
12467
+ records,
12468
+ onRecordsUpdated: (records2) => setRecords(records2)
12177
12469
  }
12178
- )
12179
- ] }) });
12470
+ ),
12471
+ /* @__PURE__ */ jsx("div", { style: { padding: 15, paddingTop: 0 }, children: /* @__PURE__ */ jsxs("div", { className: "d-flex align-items-center", style: { gap: "8px" }, children: [
12472
+ /* @__PURE__ */ jsx(
12473
+ Button,
12474
+ {
12475
+ onClick: () => onCancel?.(),
12476
+ size: "lg",
12477
+ style: { width: "100%" },
12478
+ variant: "outline",
12479
+ children: "Cancel"
12480
+ }
12481
+ ),
12482
+ getActionButton()
12483
+ ] }) })
12484
+ ] });
12180
12485
  };
12181
12486
 
12182
12487
  const useWaitForTransaction = ({ chainId: number }) => {
@@ -12191,17 +12496,6 @@ const useWeb3Client = ({ chainId }) => {
12191
12496
  };
12192
12497
  };
12193
12498
 
12194
- const SET_TEXT_FUNC = "function setText(bytes32 node, string key, string value)";
12195
- const SET_ADDRESS_FUNC = "function setAddr(bytes32 node, uint256 coin, bytes value)";
12196
- const SET_CONTENTHASH_FUNC = "function setContenthash(bytes32 node, bytes value)";
12197
- const MULTICALL = "function multicall(bytes[] data)";
12198
- const ENS_RESOLVER_ABI = parseAbi([
12199
- SET_TEXT_FUNC,
12200
- SET_ADDRESS_FUNC,
12201
- SET_CONTENTHASH_FUNC,
12202
- MULTICALL
12203
- ]);
12204
-
12205
12499
  const ThemeContext = createContext(void 0);
12206
12500
  const ThemeProvider = ({
12207
12501
  initialTheme = "light",
@@ -12237,5 +12531,5 @@ const useTheme = () => {
12237
12531
  return ctx;
12238
12532
  };
12239
12533
 
12240
- export { Alert, Button, ChainIcon, ContenthashIcon, ContenthashProtocol, Dropdown, ENS_RESOLVER_ABI, Icon, Input, MULTICALL, Modal, PendingTransaction, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, Text, TextRecordCategory, ThemeProvider, Tooltip, TransactionState, capitalize, convertEVMChainIdToCoinType, deepCopy, equalsIgnoreCase, getEnsRecordsDiff, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, getSupportedTextMap, isContenthashValid, supportedAddresses, supportedContenthashRecords, supportedTexts, useTheme, useWaitForTransaction, useWeb3Client };
12534
+ export { Alert, Button, ChainIcon, ContenthashIcon, ContenthashProtocol, Dropdown, ENS_RESOLVER_ABI, EnsRecordsForm, Icon, Input, MULTICALL, Modal, PendingTransaction, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, Text, TextRecordCategory, ThemeProvider, Tooltip, TransactionState, capitalize, convertEVMChainIdToCoinType, deepCopy, equalsIgnoreCase, getEnsRecordsDiff, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, getSupportedTextMap, isContenthashValid, supportedAddresses, supportedContenthashRecords, supportedTexts, useTheme, useWaitForTransaction, useWeb3Client };
12241
12535
  //# sourceMappingURL=index.js.map