@thenamespace/ens-components 0.20.0 → 0.22.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/index.js CHANGED
@@ -1476,12 +1476,24 @@ function convertEVMChainIdToCoinType(chainId) {
1476
1476
  }
1477
1477
 
1478
1478
  const getEnsRecordsDiff = (oldRecords, newRecords) => {
1479
- const { textsAdded, textsModified, textsRemoved } = getEnsTextDiff(
1480
- oldRecords.texts,
1481
- newRecords.texts
1482
- );
1483
- const { addressesAdded, addressesModified, addressesRemoved } = getEnsAddressDiff(oldRecords.addresses, newRecords.addresses);
1484
- const { contenthashAdded, contenthashModified, contenthashRemoved } = getEnsContenthashDiff(oldRecords.contenthash, newRecords.contenthash);
1479
+ const {
1480
+ textsAdded,
1481
+ textsModified,
1482
+ textsRemoved,
1483
+ isDifferent: isTxtDifferent
1484
+ } = getEnsTextDiff(oldRecords.texts, newRecords.texts);
1485
+ const {
1486
+ addressesAdded,
1487
+ addressesModified,
1488
+ addressesRemoved,
1489
+ isDifferent: isAddrDifferent
1490
+ } = getEnsAddressDiff(oldRecords.addresses, newRecords.addresses);
1491
+ const {
1492
+ contenthashAdded,
1493
+ contenthashModified,
1494
+ contenthashRemoved,
1495
+ isDifferent: isChashDifferent
1496
+ } = getEnsContenthashDiff(oldRecords.contenthash, newRecords.contenthash);
1485
1497
  return {
1486
1498
  addressesAdded,
1487
1499
  addressesModified,
@@ -1491,7 +1503,8 @@ const getEnsRecordsDiff = (oldRecords, newRecords) => {
1491
1503
  textsRemoved,
1492
1504
  contenthashAdded,
1493
1505
  contenthashModified,
1494
- contenthashRemoved
1506
+ contenthashRemoved,
1507
+ isDifferent: isTxtDifferent || isAddrDifferent || isChashDifferent
1495
1508
  };
1496
1509
  };
1497
1510
  const getEnsTextDiff = (oldTexts, newTexts) => {
@@ -1499,15 +1512,18 @@ const getEnsTextDiff = (oldTexts, newTexts) => {
1499
1512
  return {
1500
1513
  textsAdded: newTexts,
1501
1514
  textsModified: [],
1502
- textsRemoved: []
1515
+ textsRemoved: [],
1516
+ isDifferent: newTexts.length > 0
1503
1517
  };
1504
1518
  }
1519
+ let hasDifferences = false;
1505
1520
  const oldTextMap = {};
1506
1521
  const textsRemoved = [];
1507
1522
  oldTexts.forEach((text) => {
1508
1523
  oldTextMap[text.key] = text;
1509
1524
  const existsInNew = newTexts.find((newText) => newText.key === text.key);
1510
1525
  if (!existsInNew) {
1526
+ hasDifferences = true;
1511
1527
  textsRemoved.push(text);
1512
1528
  }
1513
1529
  });
@@ -1516,15 +1532,18 @@ const getEnsTextDiff = (oldTexts, newTexts) => {
1516
1532
  newTexts.forEach((newText) => {
1517
1533
  const matchingOldText = oldTextMap[newText.key];
1518
1534
  if (!matchingOldText) {
1535
+ hasDifferences = true;
1519
1536
  textsAdded.push(newText);
1520
1537
  } else if (matchingOldText.value !== newText.value) {
1538
+ hasDifferences = true;
1521
1539
  textsModified.push(newText);
1522
1540
  }
1523
1541
  });
1524
1542
  return {
1525
1543
  textsAdded,
1526
1544
  textsModified,
1527
- textsRemoved
1545
+ textsRemoved,
1546
+ isDifferent: hasDifferences
1528
1547
  };
1529
1548
  };
1530
1549
  const getEnsAddressDiff = (oldAddresses, newAddresses) => {
@@ -1532,9 +1551,11 @@ const getEnsAddressDiff = (oldAddresses, newAddresses) => {
1532
1551
  return {
1533
1552
  addressesAdded: newAddresses,
1534
1553
  addressesModified: [],
1535
- addressesRemoved: []
1554
+ addressesRemoved: [],
1555
+ isDifferent: newAddresses.length > 0
1536
1556
  };
1537
1557
  }
1558
+ let hasDifference = false;
1538
1559
  const oldAddressMap = {};
1539
1560
  const addressesRemoved = [];
1540
1561
  oldAddresses.forEach((address) => {
@@ -1543,6 +1564,7 @@ const getEnsAddressDiff = (oldAddresses, newAddresses) => {
1543
1564
  (newAddress) => newAddress.coinType === address.coinType
1544
1565
  );
1545
1566
  if (!existsInNew) {
1567
+ hasDifference = true;
1546
1568
  addressesRemoved.push(address);
1547
1569
  }
1548
1570
  });
@@ -1551,15 +1573,18 @@ const getEnsAddressDiff = (oldAddresses, newAddresses) => {
1551
1573
  newAddresses.forEach((newAddress) => {
1552
1574
  const matchinOldAddress = oldAddressMap[newAddress.coinType];
1553
1575
  if (!matchinOldAddress) {
1576
+ hasDifference = true;
1554
1577
  addressesAdded.push(newAddress);
1555
1578
  } else if (matchinOldAddress.value !== newAddress.value) {
1579
+ hasDifference = true;
1556
1580
  addressesModified.push(newAddress);
1557
1581
  }
1558
1582
  });
1559
1583
  return {
1560
1584
  addressesAdded,
1561
1585
  addressesModified,
1562
- addressesRemoved
1586
+ addressesRemoved,
1587
+ isDifferent: hasDifference
1563
1588
  };
1564
1589
  };
1565
1590
  const getEnsContenthashDiff = (oldRecord, newRecord) => {
@@ -1567,21 +1592,78 @@ const getEnsContenthashDiff = (oldRecord, newRecord) => {
1567
1592
  return {
1568
1593
  contenthashRemoved: false,
1569
1594
  contenthashAdded: void 0,
1570
- contenthashModified: void 0
1595
+ contenthashModified: void 0,
1596
+ isDifferent: false
1571
1597
  };
1572
1598
  }
1573
1599
  if (!oldRecord && newRecord) {
1574
1600
  return {
1575
1601
  contenthashRemoved: false,
1576
1602
  contenthashAdded: newRecord,
1577
- contenthashModified: void 0
1603
+ contenthashModified: void 0,
1604
+ isDifferent: true
1578
1605
  };
1579
1606
  }
1580
1607
  const isSame = oldRecord?.protocol === newRecord?.protocol && oldRecord?.value === newRecord?.value;
1581
1608
  return {
1582
1609
  contenthashAdded: void 0,
1583
1610
  contenthashModified: isSame ? void 0 : newRecord,
1584
- contenthashRemoved: false
1611
+ contenthashRemoved: false,
1612
+ isDifferent: !isSame
1613
+ };
1614
+ };
1615
+ const validateEnsRecords = (ensRecords) => {
1616
+ const { texts, addresses, contenthash } = ensRecords;
1617
+ let validationErrs = [];
1618
+ let validationFailed = false;
1619
+ if (addresses && addresses.length > 0) {
1620
+ addresses.forEach((addr) => {
1621
+ const validator = getSupportedAddressByCoin(addr.coinType);
1622
+ if (addr.value.length === 0) {
1623
+ validationFailed = true;
1624
+ validationErrs.push({
1625
+ type: "address",
1626
+ reason: `${validator ? validator.label : addr.coinType} address cannot be blank.`
1627
+ });
1628
+ return;
1629
+ }
1630
+ if (validator) {
1631
+ if (!validator.validateFunc?.(addr.value)) {
1632
+ validationFailed = true;
1633
+ validationErrs.push({
1634
+ type: "address",
1635
+ reason: `${validator.label} address value is not valid.`
1636
+ });
1637
+ return;
1638
+ }
1639
+ }
1640
+ });
1641
+ }
1642
+ if (texts && texts.length > 0) {
1643
+ texts.forEach((txt) => {
1644
+ if (!txt.value || txt.value.length === 0) {
1645
+ validationFailed = true;
1646
+ validationErrs.push({
1647
+ type: "text",
1648
+ reason: `Text -> '${txt.key}' cannot be blank.`
1649
+ });
1650
+ }
1651
+ });
1652
+ }
1653
+ if (contenthash) {
1654
+ const { value, protocol } = contenthash;
1655
+ const validator = getSupportedChashByProtocol(protocol);
1656
+ if (value?.trim?.().length == 0 || !isContenthashValid(protocol, value)) {
1657
+ validationFailed = true;
1658
+ validationErrs.push({
1659
+ type: "contenthash",
1660
+ reason: `Contenthash value is invalid for ${validator ? validator.label : protocol} protocol`
1661
+ });
1662
+ }
1663
+ }
1664
+ return {
1665
+ validationFailed,
1666
+ errors: validationErrs
1585
1667
  };
1586
1668
  };
1587
1669
 
@@ -22292,8 +22374,7 @@ const convertToResolverData = (name, records) => {
22292
22374
  addressesModified: [],
22293
22375
  addressesRemoved: [],
22294
22376
  contenthashRemoved: false,
22295
- contenthashAdded: records.contenthash
22296
- });
22377
+ contenthashAdded: records.contenthash});
22297
22378
  };
22298
22379
  const convertToMulticallResolverData = (name, recordsDiff) => {
22299
22380
  const node = namehash(name);
@@ -23968,7 +24049,7 @@ function requireAddresses () {
23968
24049
  nameWrapperProxy: "0x25ADB7e69390FbfeEe26F3C8053955d4D4428Afd",
23969
24050
  hybridResolver: "0xe5A0277018879679d18cCDb66B52BD06f7fE95FD",
23970
24051
  oldHybridResolver: "0x0dcD506D1Be162E50A2b434028A9a148F2686444",
23971
- bulkEnsRegistrar: "0x99393f6ceb39a6fdefdfeed1606669b16c49c453"
24052
+ bulkEnsRegistrar: "0x99393f6ceb39a6fdefdfeed1606669b16c49c453",
23972
24053
  },
23973
24054
  [sepoliaId]: {
23974
24055
  mintController: "0x313442ba3A0b12193787BD162f99Ed3C415F2886",
@@ -24003,15 +24084,17 @@ function requireAddresses () {
24003
24084
  ensRegistry: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
24004
24085
  nameWrapper: "0xd4416b13d2b3a9abae7acd5d6c2bbdbe25686401",
24005
24086
  ethRegistrarController: "0x59E16fcCd424Cc24e280Be16E11Bcd56fb0CE547",
24006
- publicResolver: "0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63",
24007
- universalResolver: "0xce01f8eee7E479C928F8919abD53E553a36CeF67"
24087
+ publicResolver: "0xF29100983E058B709F3D539b0c765937B804AC15",
24088
+ universalResolver: "0xce01f8eee7E479C928F8919abD53E553a36CeF67",
24089
+ unwrappedRegistrarController: "0x59E16fcCd424Cc24e280Be16E11Bcd56fb0CE547"
24008
24090
  },
24009
24091
  [sepoliaId]: {
24010
24092
  ensRegistry: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
24011
24093
  nameWrapper: "0x0635513f179D50A207757E05759CbD106d7dFcE8",
24012
24094
  ethRegistrarController: "0xfb3cE5D01e0f33f41DbB39035dB9745962F1f968",
24013
- publicResolver: "0x8FADE66B79cC9f707aB26799354482EB93a5B7dD",
24014
- universalResolver: "0xc8af999e38273d658be1b921b88a9ddf005769cc"
24095
+ publicResolver: "0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5",
24096
+ universalResolver: "0xc8af999e38273d658be1b921b88a9ddf005769cc",
24097
+ unwrappedRegistrarController: "0xfb3cE5D01e0f33f41DbB39035dB9745962F1f968"
24015
24098
  }
24016
24099
  };
24017
24100
  const getEnsContracts = (isTestnet = false) => {
@@ -24832,7 +24915,6 @@ const useRegisterENS = ({ isTestnet }) => {
24832
24915
  }
24833
24916
  const fullName = `${request.label}.eth`;
24834
24917
  const resolverData = convertToResolverData(fullName, request.records);
24835
- console.log("Generating resolver data for name: " + fullName, resolverData);
24836
24918
  const registration = {
24837
24919
  label: request.label,
24838
24920
  owner: request.owner,
@@ -24855,7 +24937,11 @@ const useRegisterENS = ({ isTestnet }) => {
24855
24937
  account: walletClient.account,
24856
24938
  value: price.wei
24857
24939
  });
24858
- return walletClient.writeContract(contractRequest);
24940
+ const tx = await walletClient.writeContract(contractRequest);
24941
+ return {
24942
+ txHash: tx,
24943
+ price
24944
+ };
24859
24945
  };
24860
24946
  const getEthController = () => {
24861
24947
  return distExports.getEnsContracts(isTestnet).ethRegistrarController;
@@ -24925,6 +25011,7 @@ const RegistrationSummary = ({
24925
25011
  years,
24926
25012
  price,
24927
25013
  nameValidation,
25014
+ transactionFees,
24928
25015
  isTestnet = false,
24929
25016
  onLabelChange,
24930
25017
  onYearsChange,
@@ -24936,6 +25023,24 @@ const RegistrationSummary = ({
24936
25023
  const { isEnsAvailable, getRegistrationPrice } = useRegisterENS({
24937
25024
  isTestnet
24938
25025
  });
25026
+ const { regPrice, regFees, regTotal } = useMemo(() => {
25027
+ let regPrice2 = 0;
25028
+ let regFees2 = 0;
25029
+ let total = 0;
25030
+ if (price) {
25031
+ regPrice2 += price.eth;
25032
+ total += price.eth;
25033
+ }
25034
+ if (transactionFees) {
25035
+ regFees2 += transactionFees.price.eth;
25036
+ total += transactionFees.price.eth;
25037
+ }
25038
+ return {
25039
+ regFees: regFees2,
25040
+ regPrice: regPrice2,
25041
+ regTotal: formatFloat(total, 5)
25042
+ };
25043
+ }, [price, transactionFees]);
24939
25044
  const checkAvailability = async (labelToCheck) => {
24940
25045
  let _available = false;
24941
25046
  try {
@@ -25008,6 +25113,8 @@ const RegistrationSummary = ({
25008
25113
  return label.length >= MIN_ENS_LEN && !nameValidation.isChecking && !nameValidation.isTaken;
25009
25114
  }, [label.length, nameValidation.isChecking, nameValidation.isTaken]);
25010
25115
  const nextBtnDisabled = label.length < MIN_ENS_LEN || nameValidation.isChecking || nameValidation.isTaken;
25116
+ const totalPriceLoading = transactionFees?.isChecking || price.isChecking;
25117
+ const transactionFeesLoading = transactionFees?.isChecking || false;
25011
25118
  return /* @__PURE__ */ jsxs("div", { className: "ens-registration-summary", children: [
25012
25119
  /* @__PURE__ */ jsx("div", { className: "d-flex justify-content-center", children: /* @__PURE__ */ jsx(
25013
25120
  "img",
@@ -25069,17 +25176,23 @@ const RegistrationSummary = ({
25069
25176
  /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mb-1", children: [
25070
25177
  /* @__PURE__ */ jsx(Text$1, { size: "sm", color: "grey", children: "Registration Fee" }),
25071
25178
  price.isChecking ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 16 }) : /* @__PURE__ */ jsxs(Text$1, { size: "sm", color: "grey", children: [
25072
- price.eth,
25179
+ regPrice,
25073
25180
  " ETH"
25074
25181
  ] })
25075
25182
  ] }),
25076
25183
  /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mb-1", children: [
25077
- /* @__PURE__ */ jsx(Text$1, { size: "sm", color: "grey", children: "Est. network fee" }),
25078
- /* @__PURE__ */ jsx(Text$1, { size: "sm", color: "grey", children: "0.04 ETH" })
25184
+ /* @__PURE__ */ jsx(Text$1, { size: "sm", color: "grey", children: "Est. network fees" }),
25185
+ transactionFeesLoading ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 16 }) : /* @__PURE__ */ jsxs(Text$1, { size: "sm", color: "grey", children: [
25186
+ regFees,
25187
+ " ETH"
25188
+ ] })
25079
25189
  ] }),
25080
25190
  /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mt-2 total-fee", children: [
25081
25191
  /* @__PURE__ */ jsx(Text$1, { size: "lg", weight: "bold", children: "Total" }),
25082
- /* @__PURE__ */ jsx(Text$1, { size: "lg", weight: "bold", children: "0.08 ETH" })
25192
+ totalPriceLoading ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 20 }) : /* @__PURE__ */ jsxs(Text$1, { size: "lg", weight: "bold", children: [
25193
+ regTotal,
25194
+ " ETH"
25195
+ ] })
25083
25196
  ] })
25084
25197
  ] }),
25085
25198
  /* @__PURE__ */ jsx(
@@ -25127,26 +25240,43 @@ const SetNameRecords = ({
25127
25240
  records,
25128
25241
  onRecordsChange,
25129
25242
  onCancel,
25130
- onSave
25243
+ onSave,
25244
+ hasChanges
25131
25245
  }) => {
25246
+ const [error, setError] = useState();
25247
+ const handleSave = () => {
25248
+ setError(null);
25249
+ const validation = validateEnsRecords(records);
25250
+ if (validation.validationFailed) {
25251
+ setError(validation.errors?.length > 0 ? validation.errors[0].reason : "Something went wrong");
25252
+ return;
25253
+ }
25254
+ onSave();
25255
+ };
25132
25256
  return /* @__PURE__ */ jsx(
25133
25257
  SelectRecordsForm,
25134
25258
  {
25135
25259
  records,
25136
25260
  onRecordsUpdated: onRecordsChange,
25137
- actionButtons: /* @__PURE__ */ jsx("div", { style: { padding: 15, paddingTop: 0 }, children: /* @__PURE__ */ jsxs("div", { className: "d-flex", style: { gap: "8px", width: "100%" }, children: [
25138
- /* @__PURE__ */ jsx(
25139
- Button,
25140
- {
25141
- variant: "outline",
25142
- size: "lg",
25143
- style: { flex: 1 },
25144
- onClick: onCancel,
25145
- children: "Cancel"
25146
- }
25147
- ),
25148
- /* @__PURE__ */ jsx(Button, { size: "lg", style: { flex: 1 }, onClick: onSave, children: "Save" })
25149
- ] }) })
25261
+ actionButtons: /* @__PURE__ */ jsxs("div", { style: { padding: 15, paddingTop: 0 }, children: [
25262
+ error && /* @__PURE__ */ jsx(Alert, { variant: "error", children: error }),
25263
+ /* @__PURE__ */ jsxs("div", { className: "d-flex", style: { gap: "8px", width: "100%" }, children: [
25264
+ /* @__PURE__ */ jsx(
25265
+ Button,
25266
+ {
25267
+ variant: "outline",
25268
+ size: "lg",
25269
+ style: { flex: 1 },
25270
+ onClick: () => {
25271
+ setError(null);
25272
+ onCancel?.();
25273
+ },
25274
+ children: "Cancel"
25275
+ }
25276
+ ),
25277
+ /* @__PURE__ */ jsx(Button, { disabled: !hasChanges, size: "lg", style: { flex: 1 }, onClick: handleSave, children: "Save" })
25278
+ ] })
25279
+ ] })
25150
25280
  }
25151
25281
  );
25152
25282
  };
@@ -25222,8 +25352,7 @@ const TransactionPendingScreen = ({
25222
25352
  const CommitmentStep = ({
25223
25353
  state,
25224
25354
  isTestnet,
25225
- onStateUpdated,
25226
- referrer
25355
+ onStateUpdated
25227
25356
  }) => {
25228
25357
  const { sendCommitmentTx } = useRegisterENS({ isTestnet });
25229
25358
  const { waitTx } = useWaitTransaction({ isTestnet });
@@ -25250,17 +25379,17 @@ const CommitmentStep = ({
25250
25379
  const handleCommitment = async () => {
25251
25380
  setError(null);
25252
25381
  let tx = null;
25253
- console.log("MAking commitment with records", state.records);
25254
25382
  try {
25255
25383
  setBtnState({ ...btnState, waitingWallet: true });
25256
- tx = await sendCommitmentTx({
25384
+ const request = {
25257
25385
  label: state.label,
25258
25386
  owner: address,
25259
25387
  expiryInYears: state.expiryInYears,
25260
25388
  secret: state.secret,
25261
25389
  records: state.records,
25262
- referrer
25263
- });
25390
+ referrer: state.referrer
25391
+ };
25392
+ tx = await sendCommitmentTx(request);
25264
25393
  setCommitTxStatus({ sent: true, completed: false, hash: tx });
25265
25394
  onStateUpdated({
25266
25395
  ...state,
@@ -25425,15 +25554,19 @@ const TimerStep = ({
25425
25554
  }
25426
25555
  const int = setInterval(() => {
25427
25556
  setSecondsToWait((prev) => {
25428
- if (prev <= 0) {
25429
- onTimerCompleted?.();
25557
+ if (prev <= 1) {
25430
25558
  return 0;
25431
25559
  }
25432
25560
  return prev - 1;
25433
25561
  });
25434
25562
  }, 1e3);
25435
25563
  return () => clearInterval(int);
25436
- }, [onTimerCompleted, shouldStartTimer]);
25564
+ }, [shouldStartTimer]);
25565
+ useEffect(() => {
25566
+ if (secondsToWait === 0 && shouldStartTimer) {
25567
+ onTimerCompleted?.();
25568
+ }
25569
+ }, [secondsToWait, shouldStartTimer, onTimerCompleted]);
25437
25570
  const progress = Math.ceil(
25438
25571
  (INITIAL_SECONDS - secondsToWait) / INITIAL_SECONDS * 100
25439
25572
  );
@@ -25475,20 +25608,26 @@ const RegistrationStep = ({
25475
25608
  completed: false,
25476
25609
  hash: ""
25477
25610
  });
25478
- const { sendRegisterTx, getRegistrationPrice } = useRegisterENS({ isTestnet });
25611
+ const { sendRegisterTx, getRegistrationPrice } = useRegisterENS({
25612
+ isTestnet
25613
+ });
25479
25614
  const handleRegistration = async () => {
25480
25615
  setError(null);
25481
25616
  let tx = null;
25617
+ let registrationPrice = 0;
25482
25618
  try {
25483
25619
  setBtnState({ ...btnState, waitingWallet: true });
25484
- console.log("Sending tx with records", state.records);
25485
- tx = await sendRegisterTx({
25620
+ const request = {
25486
25621
  label: state.label,
25487
25622
  owner: address,
25488
25623
  expiryInYears: state.expiryInYears,
25489
25624
  secret: state.secret,
25490
- records: state.records
25491
- });
25625
+ records: state.records,
25626
+ referrer: state.referrer
25627
+ };
25628
+ const regData = await sendRegisterTx(request);
25629
+ tx = regData.txHash;
25630
+ registrationPrice = formatFloat(regData.price.eth, 5);
25492
25631
  setCommitTxStatus({ sent: true, completed: false, hash: tx });
25493
25632
  onStateUpdated({
25494
25633
  ...state,
@@ -25515,15 +25654,11 @@ const RegistrationStep = ({
25515
25654
  try {
25516
25655
  const receipt = await waitTx({ hash: tx });
25517
25656
  setCommitTxStatus({ sent: true, completed: true, hash: tx });
25518
- const registrationPrice = await getRegistrationPrice(
25519
- state.label,
25520
- state.expiryInYears
25521
- );
25522
25657
  const gasUsed = receipt.gasUsed;
25523
25658
  const gasPrice = receipt.effectiveGasPrice || BigInt(0);
25524
25659
  const transactionFees = gasUsed * gasPrice;
25525
25660
  const transactionFeesEth = formatEther(transactionFees);
25526
- const totalCost = (registrationPrice.eth + parseFloat(transactionFeesEth)).toString();
25661
+ const totalCost = (registrationPrice + parseFloat(transactionFeesEth)).toString();
25527
25662
  const expiryDate = /* @__PURE__ */ new Date();
25528
25663
  expiryDate.setFullYear(expiryDate.getFullYear() + state.expiryInYears);
25529
25664
  const formattedExpiryDate = expiryDate.toLocaleDateString("en-US", {
@@ -25531,11 +25666,6 @@ const RegistrationStep = ({
25531
25666
  month: "long",
25532
25667
  day: "numeric"
25533
25668
  });
25534
- console.log("=== Registration Completed ===");
25535
- console.log("1. Expiration Years:", state.expiryInYears);
25536
- console.log("2. Transaction Value:", registrationPrice.eth, "ETH");
25537
- console.log("3. Transaction Fees:", transactionFeesEth, "ETH");
25538
- console.log("==============================");
25539
25669
  setTimeout(() => {
25540
25670
  onStateUpdated({
25541
25671
  ...state,
@@ -25545,10 +25675,13 @@ const RegistrationStep = ({
25545
25675
  setCommitTxStatus({ sent: false, completed: false, hash: "" });
25546
25676
  onSuccess?.({
25547
25677
  expiryInYears: state.expiryInYears,
25548
- registrationCost: registrationPrice.eth.toString(),
25678
+ registrationCost: registrationPrice.toString(),
25549
25679
  transactionFees: transactionFeesEth,
25550
25680
  total: totalCost,
25551
- expiryDate: formattedExpiryDate
25681
+ expiryDate: formattedExpiryDate,
25682
+ thHash: tx,
25683
+ name: `${state.label}.eth`,
25684
+ records: state.records
25552
25685
  });
25553
25686
  }, 1e3);
25554
25687
  } catch (err) {
@@ -26272,7 +26405,7 @@ const SuccessScreen = ({
26272
26405
  total,
26273
26406
  expiryDate,
26274
26407
  isTestnet = false,
26275
- onClose,
26408
+ onGreat,
26276
26409
  onRegisterAnother,
26277
26410
  onViewName
26278
26411
  }) => {
@@ -26323,8 +26456,8 @@ const SuccessScreen = ({
26323
26456
  /* @__PURE__ */ jsxs("div", { className: "ens-registration-success-card", style: { position: "relative", zIndex: 1 }, children: [
26324
26457
  /* @__PURE__ */ jsx("div", { className: "ens-registration-success-illustration", children: /* @__PURE__ */ jsx("img", { src: img, alt: "Success Illustration" }) }),
26325
26458
  /* @__PURE__ */ jsxs("div", { className: "ens-registration-success-title-section", children: [
26326
- /* @__PURE__ */ jsx(Text$1, { size: "lg", weight: "bold", className: "ens-registration-success-message", children: "Hooray! You've registered" }),
26327
- /* @__PURE__ */ jsxs(Text$1, { size: "lg", weight: "bold", className: "ens-registration-success-name", children: [
26459
+ /* @__PURE__ */ jsx(Text$1, { size: "sm", color: "grey", className: "mb-2", children: "Hooray! You've registered" }),
26460
+ /* @__PURE__ */ jsxs(Text$1, { size: "lg", weight: "bold", children: [
26328
26461
  ensName,
26329
26462
  ".eth"
26330
26463
  ] })
@@ -26364,7 +26497,6 @@ const SuccessScreen = ({
26364
26497
  Button,
26365
26498
  {
26366
26499
  variant: "outline",
26367
- size: "lg",
26368
26500
  onClick: onRegisterAnother,
26369
26501
  className: "ens-registration-success-register-another-btn",
26370
26502
  children: "Register another"
@@ -26373,8 +26505,7 @@ const SuccessScreen = ({
26373
26505
  /* @__PURE__ */ jsx(
26374
26506
  Button,
26375
26507
  {
26376
- variant: "solid",
26377
- size: "lg",
26508
+ variant: "outline",
26378
26509
  onClick: () => {
26379
26510
  if (onViewName) {
26380
26511
  onViewName();
@@ -26386,20 +26517,41 @@ const SuccessScreen = ({
26386
26517
  children: "View Name"
26387
26518
  }
26388
26519
  )
26389
- ] })
26520
+ ] }),
26521
+ /* @__PURE__ */ jsx(Button, { onClick: () => onGreat?.(), size: "lg", className: "ns-wd-100 mt-2", children: "Great!" })
26390
26522
  ] })
26391
26523
  ]
26392
26524
  }
26393
26525
  );
26394
26526
  };
26395
26527
 
26528
+ const generateEnsRegistrationSecret = () => {
26529
+ return toHex(Math.floor(Math.random() * 1e9));
26530
+ };
26531
+
26532
+ const getBlankRegistrationState = (label, exiryInYears, records, isTestnet, referrer) => {
26533
+ const blankRegistrationState = {
26534
+ step: ProcessSteps.Start,
26535
+ label,
26536
+ commitment: { completed: false, time: 0 },
26537
+ registration: { completed: false },
26538
+ timerStartedAt: 0,
26539
+ expiryInYears: exiryInYears,
26540
+ secret: generateEnsRegistrationSecret(),
26541
+ records,
26542
+ isTestnet,
26543
+ referrer
26544
+ };
26545
+ return blankRegistrationState;
26546
+ };
26396
26547
  const RegistrationProcess = ({
26397
26548
  label,
26398
26549
  expiryInYears,
26399
26550
  isTestnet = false,
26400
26551
  records,
26401
26552
  onBack,
26402
- onSuccess
26553
+ onSuccess,
26554
+ referrer
26403
26555
  }) => {
26404
26556
  const { chain } = useAccount();
26405
26557
  const { switchChain } = useSwitchChain();
@@ -26407,18 +26559,15 @@ const RegistrationProcess = ({
26407
26559
  const isOnCorrectNetwork = chain?.id === expectedChainId;
26408
26560
  const shouldSwitchNetwork = chain && !isOnCorrectNetwork;
26409
26561
  const [registrationState, setRegistrationState] = useState(
26410
- {
26411
- step: ProcessSteps.Start,
26562
+ getBlankRegistrationState(
26412
26563
  label,
26413
- commitment: { completed: false, time: 0 },
26414
- registration: { completed: false },
26415
- timerStartedAt: 0,
26416
26564
  expiryInYears,
26417
- secret: "0x0",
26418
26565
  records,
26419
- isTestnet
26420
- }
26566
+ isTestnet,
26567
+ referrer
26568
+ )
26421
26569
  );
26570
+ const [showConfirmClose, setShowConfirmClose] = useState(false);
26422
26571
  useEffect(() => {
26423
26572
  setRegistrationState({ ...registrationState, records });
26424
26573
  }, [records]);
@@ -26428,18 +26577,33 @@ const RegistrationProcess = ({
26428
26577
  }
26429
26578
  };
26430
26579
  const handleTimerPassed = () => {
26431
- setRegistrationState({
26580
+ const newState = {
26432
26581
  ...registrationState,
26433
26582
  step: ProcessSteps.TimerCompleted
26434
- });
26583
+ };
26584
+ setRegistrationState(newState);
26435
26585
  };
26436
26586
  const networkName = isTestnet ? "Sepolia" : "Mainnet";
26587
+ const handleCloseClick = () => {
26588
+ if (registrationState.step > ProcessSteps.Start && registrationState.step < ProcessSteps.RegistrationCompleted) {
26589
+ setShowConfirmClose(true);
26590
+ } else {
26591
+ onBack?.();
26592
+ }
26593
+ };
26594
+ const handleConfirmClose = () => {
26595
+ setShowConfirmClose(false);
26596
+ onBack?.(true);
26597
+ };
26598
+ const handleCancelClose = () => {
26599
+ setShowConfirmClose(false);
26600
+ };
26437
26601
  return /* @__PURE__ */ jsxs("div", { className: "ens-registration-progress", children: [
26438
26602
  /* @__PURE__ */ jsx(
26439
26603
  "button",
26440
26604
  {
26441
26605
  className: "ens-registration-close-btn",
26442
- onClick: () => onBack?.(),
26606
+ onClick: handleCloseClick,
26443
26607
  type: "button",
26444
26608
  "aria-label": "Close",
26445
26609
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 16 })
@@ -26474,14 +26638,18 @@ const RegistrationProcess = ({
26474
26638
  {
26475
26639
  state: registrationState,
26476
26640
  isTestnet,
26477
- onStateUpdated: (state) => setRegistrationState(state)
26641
+ onStateUpdated: (state) => {
26642
+ setRegistrationState(state);
26643
+ }
26478
26644
  }
26479
26645
  ) }),
26480
26646
  /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
26481
26647
  TimerStep,
26482
26648
  {
26483
26649
  state: registrationState,
26484
- onTimerCompleted: handleTimerPassed
26650
+ onTimerCompleted: () => {
26651
+ handleTimerPassed();
26652
+ }
26485
26653
  }
26486
26654
  ) }),
26487
26655
  /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
@@ -26489,20 +26657,69 @@ const RegistrationProcess = ({
26489
26657
  {
26490
26658
  state: registrationState,
26491
26659
  isTestnet,
26492
- onStateUpdated: (state) => setRegistrationState(state),
26660
+ onStateUpdated: (state) => {
26661
+ setRegistrationState(state);
26662
+ },
26493
26663
  onSuccess
26494
26664
  }
26495
26665
  ) })
26496
- ] })
26666
+ ] }),
26667
+ /* @__PURE__ */ jsx(
26668
+ Modal,
26669
+ {
26670
+ isOpen: showConfirmClose,
26671
+ onClose: handleCancelClose,
26672
+ title: "Leave Registration?",
26673
+ size: "sm",
26674
+ footer: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, width: "100%" }, children: [
26675
+ /* @__PURE__ */ jsx(
26676
+ Button,
26677
+ {
26678
+ variant: "outline",
26679
+ onClick: handleCancelClose,
26680
+ style: { flex: 1 },
26681
+ children: "Cancel"
26682
+ }
26683
+ ),
26684
+ /* @__PURE__ */ jsx(
26685
+ Button,
26686
+ {
26687
+ variant: "destructive",
26688
+ onClick: handleConfirmClose,
26689
+ style: { flex: 1 },
26690
+ children: "Leave"
26691
+ }
26692
+ )
26693
+ ] }),
26694
+ children: /* @__PURE__ */ jsx(Text$1, { size: "sm", children: "If you leave now, you will lose all your registration progress. Are you sure you want to continue?" })
26695
+ }
26696
+ )
26497
26697
  ] });
26498
26698
  };
26499
26699
 
26700
+ const getLabel = (name) => {
26701
+ if (!name) {
26702
+ return "";
26703
+ }
26704
+ if (name.split(".").length !== 1) {
26705
+ return name.split(".")[0];
26706
+ }
26707
+ return name;
26708
+ };
26500
26709
  const EnsNameRegistrationForm = (props) => {
26501
- const [label, setLabel] = useState(props.name || "");
26710
+ const [label, setLabel] = useState(getLabel(props.name));
26502
26711
  const [step, setStep] = useState(
26503
26712
  0 /* Summary */
26504
26713
  );
26505
26714
  const [years, setYears] = useState(1);
26715
+ const [regTxFees, setRegTxFees] = useState({
26716
+ estimatedGas: 0,
26717
+ isChecking: false,
26718
+ price: {
26719
+ wei: 0n,
26720
+ eth: 1e-4
26721
+ }
26722
+ });
26506
26723
  const [price, setPrice] = useState({
26507
26724
  isChecking: false,
26508
26725
  wei: 0n,
@@ -26522,6 +26739,9 @@ const EnsNameRegistrationForm = (props) => {
26522
26739
  addresses: [],
26523
26740
  texts: []
26524
26741
  });
26742
+ const hasRecordsDifference = useMemo(() => {
26743
+ return getEnsRecordsDiff(ensRecords, ensRecordTemplate).isDifferent;
26744
+ }, [ensRecords, ensRecordTemplate]);
26525
26745
  const [successData, setSuccessData] = useState(null);
26526
26746
  const handleSaveRecords = () => {
26527
26747
  setEnsRecords(deepCopy(ensRecordTemplate));
@@ -26533,77 +26753,87 @@ const EnsNameRegistrationForm = (props) => {
26533
26753
  };
26534
26754
  const clearInputState = () => {
26535
26755
  setLabel("");
26536
- setYears(0);
26756
+ setYears(1);
26537
26757
  setEnsRecords({ addresses: [], texts: [] });
26538
26758
  setEnsRecordsTemplate({ addresses: [], texts: [] });
26539
26759
  setNameValidation({ isChecking: false, isTaken: false });
26540
26760
  setPrice({ isChecking: false, wei: 0n, eth: 0 });
26541
26761
  };
26542
- return /* @__PURE__ */ jsxs("div", { className: `ens-registration-form-container ${props.className || ""} ${props.noBorder ? "no-boder" : ""}`, children: [
26543
- step === 0 /* Summary */ && /* @__PURE__ */ jsxs(Fragment, { children: [
26544
- showProfile && /* @__PURE__ */ jsx(
26545
- SetNameRecords,
26546
- {
26547
- records: ensRecordTemplate,
26548
- onRecordsChange: setEnsRecordsTemplate,
26549
- onCancel: handleCancelRecords,
26550
- onSave: handleSaveRecords
26551
- }
26552
- ),
26553
- !showProfile && /* @__PURE__ */ jsx(
26554
- RegistrationSummary,
26555
- {
26556
- label,
26557
- years,
26558
- price,
26559
- nameValidation,
26560
- isTestnet: props.isTestnet || false,
26561
- onLabelChange: setLabel,
26562
- onYearsChange: setYears,
26563
- onPriceChange: setPrice,
26564
- onNameValidationChange: setNameValidation,
26565
- onSetProfile: () => setShowProfile(true),
26566
- onStart: () => setStep(1 /* Progress */)
26567
- }
26568
- )
26569
- ] }),
26570
- step === 1 /* Progress */ && /* @__PURE__ */ jsx(
26571
- RegistrationProcess,
26572
- {
26573
- isTestnet: props.isTestnet || false,
26574
- label,
26575
- expiryInYears: years,
26576
- records: ensRecords,
26577
- onBack: (clearState) => {
26578
- if (clearState) {
26579
- clearInputState();
26762
+ return /* @__PURE__ */ jsxs(
26763
+ "div",
26764
+ {
26765
+ className: `ens-registration-form-container ${props.className || ""} ${props.noBorder ? "no-boder" : ""}`,
26766
+ children: [
26767
+ step === 0 /* Summary */ && /* @__PURE__ */ jsxs(Fragment, { children: [
26768
+ showProfile && /* @__PURE__ */ jsx(
26769
+ SetNameRecords,
26770
+ {
26771
+ records: ensRecordTemplate,
26772
+ onRecordsChange: setEnsRecordsTemplate,
26773
+ onCancel: handleCancelRecords,
26774
+ onSave: handleSaveRecords,
26775
+ hasChanges: hasRecordsDifference
26776
+ }
26777
+ ),
26778
+ !showProfile && /* @__PURE__ */ jsx(
26779
+ RegistrationSummary,
26780
+ {
26781
+ label,
26782
+ years,
26783
+ price,
26784
+ nameValidation,
26785
+ isTestnet: props.isTestnet || false,
26786
+ transactionFees: regTxFees,
26787
+ onLabelChange: setLabel,
26788
+ onYearsChange: setYears,
26789
+ onPriceChange: setPrice,
26790
+ onNameValidationChange: setNameValidation,
26791
+ onSetProfile: () => setShowProfile(true),
26792
+ onStart: () => setStep(1 /* Progress */)
26793
+ }
26794
+ )
26795
+ ] }),
26796
+ step === 1 /* Progress */ && /* @__PURE__ */ jsx(
26797
+ RegistrationProcess,
26798
+ {
26799
+ isTestnet: props.isTestnet || false,
26800
+ label,
26801
+ expiryInYears: years,
26802
+ records: ensRecords,
26803
+ onBack: (clearState) => {
26804
+ if (clearState) {
26805
+ clearInputState();
26806
+ }
26807
+ setStep(0 /* Summary */);
26808
+ },
26809
+ onSuccess: (data) => {
26810
+ setSuccessData(data);
26811
+ props.onRegistrationSuccess?.(data);
26812
+ setStep(2 /* Success */);
26813
+ }
26580
26814
  }
26581
- setStep(0 /* Summary */);
26582
- },
26583
- onSuccess: (data) => {
26584
- setSuccessData(data);
26585
- setStep(2 /* Success */);
26586
- }
26587
- }
26588
- ),
26589
- step === 2 /* Success */ && successData && /* @__PURE__ */ jsx(
26590
- SuccessScreen,
26591
- {
26592
- ensName: label,
26593
- expiryInYears: successData.expiryInYears,
26594
- registrationCost: successData.registrationCost,
26595
- transactionFees: successData.transactionFees,
26596
- total: successData.total,
26597
- expiryDate: successData.expiryDate,
26598
- isTestnet: props.isTestnet || false,
26599
- onRegisterAnother: () => {
26600
- clearInputState();
26601
- setSuccessData(null);
26602
- setStep(0 /* Summary */);
26603
- }
26604
- }
26605
- )
26606
- ] });
26815
+ ),
26816
+ step === 2 /* Success */ && successData && /* @__PURE__ */ jsx(
26817
+ SuccessScreen,
26818
+ {
26819
+ ensName: label,
26820
+ expiryInYears: successData.expiryInYears,
26821
+ registrationCost: successData.registrationCost,
26822
+ transactionFees: successData.transactionFees,
26823
+ total: successData.total,
26824
+ expiryDate: successData.expiryDate,
26825
+ isTestnet: props.isTestnet || false,
26826
+ onGreat: () => props.onClose?.(true),
26827
+ onRegisterAnother: () => {
26828
+ clearInputState();
26829
+ setSuccessData(null);
26830
+ setStep(0 /* Summary */);
26831
+ }
26832
+ }
26833
+ )
26834
+ ]
26835
+ }
26836
+ );
26607
26837
  };
26608
26838
 
26609
26839
  const ThemeContext = createContext(void 0);
@@ -34360,5 +34590,5 @@ var walletConnectWalletYHWKVTDY = /*#__PURE__*/Object.freeze({
34360
34590
  default: walletConnectWallet_default
34361
34591
  });
34362
34592
 
34363
- export { Accordion, Alert, Button, Card, ChainIcon, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, ENS_RESOLVER_ABI, EnsNameRegistrationForm, Icon, Input, MULTICALL, Modal, PendingTransaction, ProfileHeader, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, Text$1 as Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionState, WalletConnectProvider, capitalize, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce$1 as debounce, deepCopy, ensureFloatInput, equalsIgnoreCase, formatFloat, getEnsRecordsDiff, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isUserDeniedError, supportedAddresses, supportedContenthashRecords, supportedTexts, useRegisterENS, useTheme, useWaitTransaction };
34593
+ export { Accordion, Alert, Button, Card, ChainIcon, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, ENS_RESOLVER_ABI, EnsNameRegistrationForm, Icon, Input, MULTICALL, Modal, PendingTransaction, ProfileHeader, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, Text$1 as Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionState, WalletConnectProvider, capitalize, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce$1 as debounce, deepCopy, ensureFloatInput, equalsIgnoreCase, formatFloat, getEnsRecordsDiff, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isUserDeniedError, supportedAddresses, supportedContenthashRecords, supportedTexts, useRegisterENS, useTheme, useWaitTransaction, validateEnsRecords };
34364
34594
  //# sourceMappingURL=index.js.map