@thenamespace/ens-components 1.3.0 → 1.4.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.d.ts +62 -13
- package/dist/index.js +233 -47
- package/dist/index.js.map +1 -1
- package/dist/types/components/ens-name-registration/RegistrationSummary.d.ts +2 -0
- package/dist/types/components/ens-name-registration/registration/types.d.ts +1 -0
- package/dist/types/components/molecules/pricing-display/PricingDisplay.d.ts +11 -11
- package/dist/types/hooks/useRegisterENS.d.ts +10 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/pricing.d.ts +38 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -172,6 +172,45 @@ declare const yearsFromSeconds: (seconds: number) => number;
|
|
|
172
172
|
*/
|
|
173
173
|
declare const formatDurationSummary: (durationSeconds: number) => string;
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Pure helpers for formatting ETH/USD pricing in the registration UI.
|
|
177
|
+
*
|
|
178
|
+
* Display rules:
|
|
179
|
+
* - ETH is rendered at a fixed 4 decimals.
|
|
180
|
+
* - Non-zero values smaller than 0.0001 ETH render as the literal "<0.0001"
|
|
181
|
+
* so cheap-gas rows stay informative without claiming a misleading exact
|
|
182
|
+
* figure. The USD subtitle is derived from wei (when available) so it
|
|
183
|
+
* stays numerically honest even when the ETH cell is rounded.
|
|
184
|
+
* - "Free" and "N/A" are sentinel strings — they bypass formatting and
|
|
185
|
+
* suppress the USD subtitle.
|
|
186
|
+
*/
|
|
187
|
+
declare const ETH_SENTINELS: readonly ["Free", "N/A"];
|
|
188
|
+
type EthSentinel = (typeof ETH_SENTINELS)[number];
|
|
189
|
+
declare const isSentinel: (amount: number | string) => amount is EthSentinel;
|
|
190
|
+
/**
|
|
191
|
+
* Format an ETH amount for display at a fixed 4 decimals.
|
|
192
|
+
*
|
|
193
|
+
* Any positive value below the 4-decimal threshold renders as the literal
|
|
194
|
+
* "<0.0001" — honest about the rounding direction, and (crucially) avoids
|
|
195
|
+
* the misleading 1:1 read against the wei-derived USD subtitle when the
|
|
196
|
+
* true amount is much smaller than 0.0001 ETH.
|
|
197
|
+
*/
|
|
198
|
+
declare const formatEth: (eth: number) => string;
|
|
199
|
+
/**
|
|
200
|
+
* Convert wei → USD. Note the `Number(bigint)` cast loses exactness above
|
|
201
|
+
* 2^53 wei (~0.009 ETH); the resulting error is < 1e-7 relative, which is
|
|
202
|
+
* invisible after `.toFixed(2)` for any realistic ENS registration total.
|
|
203
|
+
*/
|
|
204
|
+
declare const usdFromWei: (wei: bigint, rate: number) => number;
|
|
205
|
+
/**
|
|
206
|
+
* Compute the `≈ $X.XX` subtitle for a fee row.
|
|
207
|
+
*
|
|
208
|
+
* Prefers `weiAmount` (precise) over the displayed string (which may have
|
|
209
|
+
* been rounded by `formatEth`). Returns `null` when the row is loading,
|
|
210
|
+
* unpriced, a sentinel ("Free"/"N/A"), or otherwise unparseable.
|
|
211
|
+
*/
|
|
212
|
+
declare const computeUsd: (amount: number | string, weiAmount: bigint | undefined, ethUsdRate: number | null | undefined, isChecking: boolean) => string | null;
|
|
213
|
+
|
|
175
214
|
interface EnsRecordsFormProps {
|
|
176
215
|
resolverChainId?: number;
|
|
177
216
|
resolverAddress?: Address;
|
|
@@ -459,20 +498,20 @@ interface ProgressBarProps {
|
|
|
459
498
|
}
|
|
460
499
|
declare function ProgressBar({ progress }: ProgressBarProps): react_jsx_runtime.JSX.Element;
|
|
461
500
|
|
|
501
|
+
interface FeeRow {
|
|
502
|
+
amount: number | string;
|
|
503
|
+
isChecking: boolean;
|
|
504
|
+
/** Optional precise wei value. When provided, USD is computed from wei
|
|
505
|
+
* rather than from the (possibly rounded) display string. See
|
|
506
|
+
* `usdFromWei` for the precision bound. */
|
|
507
|
+
weiAmount?: bigint;
|
|
508
|
+
}
|
|
462
509
|
interface PricingDisplayProps {
|
|
463
|
-
primaryFee: {
|
|
510
|
+
primaryFee: FeeRow & {
|
|
464
511
|
label: string;
|
|
465
|
-
amount: number | string;
|
|
466
|
-
isChecking: boolean;
|
|
467
|
-
};
|
|
468
|
-
networkFees?: {
|
|
469
|
-
amount: number | string;
|
|
470
|
-
isChecking: boolean;
|
|
471
|
-
};
|
|
472
|
-
total: {
|
|
473
|
-
amount: number | string;
|
|
474
|
-
isChecking: boolean;
|
|
475
512
|
};
|
|
513
|
+
networkFees?: FeeRow;
|
|
514
|
+
total: FeeRow;
|
|
476
515
|
expiryPicker?: {
|
|
477
516
|
durationSeconds: number;
|
|
478
517
|
onDurationChange: (seconds: number) => void;
|
|
@@ -628,6 +667,15 @@ interface RentPriceResponse {
|
|
|
628
667
|
wei: bigint;
|
|
629
668
|
eth: number;
|
|
630
669
|
}
|
|
670
|
+
interface RegistrationFeeEstimate {
|
|
671
|
+
wei: bigint;
|
|
672
|
+
eth: number;
|
|
673
|
+
gasEstimate: bigint;
|
|
674
|
+
gasPrice: bigint;
|
|
675
|
+
/** True when the precise eth_estimateGas+stateOverride path failed and we
|
|
676
|
+
* fell back to a heuristic. UI can mark the value as approximate. */
|
|
677
|
+
isHeuristic: boolean;
|
|
678
|
+
}
|
|
631
679
|
interface RegistrationRequest {
|
|
632
680
|
label: string;
|
|
633
681
|
owner: Address;
|
|
@@ -641,6 +689,7 @@ declare const useRegisterENS: ({ isTestnet }: {
|
|
|
641
689
|
}) => {
|
|
642
690
|
isEnsAvailable: (label: string) => Promise<boolean>;
|
|
643
691
|
getRegistrationPrice: (label: string, durationInSeconds?: number) => Promise<RentPriceResponse>;
|
|
692
|
+
estimateRegistrationFees: (request: RegistrationRequest) => Promise<RegistrationFeeEstimate>;
|
|
644
693
|
sendCommitmentTx: (request: RegistrationRequest) => Promise<Hash>;
|
|
645
694
|
sendRegisterTx: (request: RegistrationRequest) => Promise<{
|
|
646
695
|
txHash: Hash;
|
|
@@ -879,5 +928,5 @@ declare const useAvatarClient: ({ isTestnet, domain }: UseAvatarClientParams) =>
|
|
|
879
928
|
getErrorMessage: (err: unknown, imageType?: UploadImageType) => string;
|
|
880
929
|
};
|
|
881
930
|
|
|
882
|
-
export { Accordion, Alert, Button, Card, ChainIcon, ConnectAndSetChain, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, DurationPicker, ENS_RESOLVER_ABI, EnsNameRegistrationForm, EnsRecordsForm, Icon, Input, ListingNetwork, ListingType, MIN_REGISTRATION_SECONDS, MULTICALL, Modal, ONE_DAY, ONE_YEAR, OffchainSubnameForm, PricingDisplay, ProfileHeader, ProgressBar, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, SubnameMintForm, Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionPendingScreen, TxProgress, capitalize, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce, deepCopy, diffToEnsRecords, ensureFloatInput, equalsIgnoreCase, formatDurationSummary, formatFloat, getAvatarUploadErrorMessage, getBlockExplorer, getBlockExplorerAddressUrl, getBlockExplorerName, getBlockExplorerTransactionUrl, getChainIdForListingNetwork, getEnsAppUrl, getEnsRecordsDiff, getImageUploadErrorMessage, getSupportedAddressByChainId, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isUserDeniedError, roundDurationWithDay, secondsFromYears, secondsToDateInput, supportedAddresses, supportedContenthashRecords, supportedTexts, useAvatarClient, useENSResolver, useEthDollarValue, useMintManager, useMintSubname, useOffchainManager, useRegisterENS, useTheme, useWaitTransaction, validateEnsRecords, wait, yearsFromSeconds };
|
|
883
|
-
export type { AccordionProps, AlertPosition, AlertProps, AlertVariant, ButtonProps, ButtonSize, ButtonVariant, ChainName$1 as ChainName, ConnectAndSetChainProps, ContractErrorLabelProps, DropdownProps, DurationPickerProps, EnsAddressRecord$1 as EnsAddressRecord, EnsContenthashRecord, EnsRecords$1 as EnsRecords, EnsRecordsDiff, EnsTextRecord$1 as EnsTextRecord, EstimatedFees, IconName, IconProps, InputProps, InputSize, InputType, ModalPresentation, ModalProps, ModalResponsivePresentation, ModalSize, NameListing, OffchainSubnameCreatedData, PricingDisplayProps, ProfileHeaderProps, RecordValidationError, RegistrationRequest, ShurikenSpinnerProps, SupportedContenthashRecord, SupportedEnsAddress, SupportedText, SupportedTextRecord, TextCategory, TextColor, TextProps, TextSize, TextWeight, TextareaProps, TextareaSize, ThemeContextValue, ThemeName, ThemeProviderProps, TooltipPosition, TooltipProps, UploadAvatarParams, UploadImageType };
|
|
931
|
+
export { Accordion, Alert, Button, Card, ChainIcon, ConnectAndSetChain, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, DurationPicker, ENS_RESOLVER_ABI, ETH_SENTINELS, EnsNameRegistrationForm, EnsRecordsForm, Icon, Input, ListingNetwork, ListingType, MIN_REGISTRATION_SECONDS, MULTICALL, Modal, ONE_DAY, ONE_YEAR, OffchainSubnameForm, PricingDisplay, ProfileHeader, ProgressBar, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, SubnameMintForm, Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionPendingScreen, TxProgress, capitalize, computeUsd, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce, deepCopy, diffToEnsRecords, ensureFloatInput, equalsIgnoreCase, formatDurationSummary, formatEth, formatFloat, getAvatarUploadErrorMessage, getBlockExplorer, getBlockExplorerAddressUrl, getBlockExplorerName, getBlockExplorerTransactionUrl, getChainIdForListingNetwork, getEnsAppUrl, getEnsRecordsDiff, getImageUploadErrorMessage, getSupportedAddressByChainId, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isSentinel, isUserDeniedError, roundDurationWithDay, secondsFromYears, secondsToDateInput, supportedAddresses, supportedContenthashRecords, supportedTexts, usdFromWei, useAvatarClient, useENSResolver, useEthDollarValue, useMintManager, useMintSubname, useOffchainManager, useRegisterENS, useTheme, useWaitTransaction, validateEnsRecords, wait, yearsFromSeconds };
|
|
932
|
+
export type { AccordionProps, AlertPosition, AlertProps, AlertVariant, ButtonProps, ButtonSize, ButtonVariant, ChainName$1 as ChainName, ConnectAndSetChainProps, ContractErrorLabelProps, DropdownProps, DurationPickerProps, EnsAddressRecord$1 as EnsAddressRecord, EnsContenthashRecord, EnsRecords$1 as EnsRecords, EnsRecordsDiff, EnsTextRecord$1 as EnsTextRecord, EstimatedFees, EthSentinel, IconName, IconProps, InputProps, InputSize, InputType, ModalPresentation, ModalProps, ModalResponsivePresentation, ModalSize, NameListing, OffchainSubnameCreatedData, PricingDisplayProps, ProfileHeaderProps, RecordValidationError, RegistrationFeeEstimate, RegistrationRequest, ShurikenSpinnerProps, SupportedContenthashRecord, SupportedEnsAddress, SupportedText, SupportedTextRecord, TextCategory, TextColor, TextProps, TextSize, TextWeight, TextareaProps, TextareaSize, ThemeContextValue, ThemeName, ThemeProviderProps, TooltipPosition, TooltipProps, UploadAvatarParams, UploadImageType };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as zlib from 'zlib';
|
|
|
4
4
|
import * as crypto$5 from 'crypto';
|
|
5
5
|
import * as net from 'net';
|
|
6
6
|
import * as viem from 'viem';
|
|
7
|
-
import { ContractFunctionExecutionError, parseAbi, namehash as namehash$1, encodeFunctionData, toHex, toBytes as toBytes$1, pad, isAddress as isAddress$1, keccak256, formatEther, zeroAddress, zeroHash } from 'viem';
|
|
7
|
+
import { ContractFunctionExecutionError, parseAbi, namehash as namehash$1, encodeFunctionData, toHex, toBytes as toBytes$1, pad, isAddress as isAddress$1, keccak256, parseEther, padHex, formatEther, zeroAddress, concatHex, zeroHash } from 'viem';
|
|
8
8
|
import * as chains$1 from 'viem/chains';
|
|
9
9
|
import { baseSepolia, sepolia, mainnet, optimism, base as base$3, zoraSepolia, zora, celoAlfajores, celo, polygonMumbai, polygon, arbitrumSepolia, arbitrum, optimismSepolia } from 'viem/chains';
|
|
10
10
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -11686,6 +11686,24 @@ const formatDurationSummary = (durationSeconds) => {
|
|
|
11686
11686
|
return parts.slice(0, 2).join(", ") || "0 days";
|
|
11687
11687
|
};
|
|
11688
11688
|
|
|
11689
|
+
const ETH_SENTINELS = ["Free", "N/A"];
|
|
11690
|
+
const isSentinel = (amount) => amount === "Free" || amount === "N/A";
|
|
11691
|
+
const formatEth = (eth) => {
|
|
11692
|
+
if (!isFinite(eth) || eth <= 0) return "0.0000";
|
|
11693
|
+
if (eth < 1e-4) return "<0.0001";
|
|
11694
|
+
return eth.toFixed(4);
|
|
11695
|
+
};
|
|
11696
|
+
const usdFromWei = (wei, rate) => Number(wei) * rate / 1e18;
|
|
11697
|
+
const computeUsd = (amount, weiAmount, ethUsdRate, isChecking) => {
|
|
11698
|
+
if (!ethUsdRate || isChecking || isSentinel(amount)) return null;
|
|
11699
|
+
if (weiAmount !== void 0 && weiAmount > 0n) {
|
|
11700
|
+
return usdFromWei(weiAmount, ethUsdRate).toFixed(2);
|
|
11701
|
+
}
|
|
11702
|
+
const eth = parseFloat(String(amount).replace(/^~/, ""));
|
|
11703
|
+
if (isNaN(eth) || eth <= 0) return null;
|
|
11704
|
+
return (eth * ethUsdRate).toFixed(2);
|
|
11705
|
+
};
|
|
11706
|
+
|
|
11689
11707
|
const isValidEmvAddress = (value) => {
|
|
11690
11708
|
return isAddress$1(value);
|
|
11691
11709
|
};
|
|
@@ -12017,6 +12035,7 @@ const DurationPicker = ({
|
|
|
12017
12035
|
] });
|
|
12018
12036
|
};
|
|
12019
12037
|
|
|
12038
|
+
const NBSP = "\xA0";
|
|
12020
12039
|
const PricingDisplay = ({
|
|
12021
12040
|
primaryFee,
|
|
12022
12041
|
networkFees,
|
|
@@ -12026,14 +12045,10 @@ const PricingDisplay = ({
|
|
|
12026
12045
|
className = ""
|
|
12027
12046
|
}) => {
|
|
12028
12047
|
const totalLoading = total.isChecking || primaryFee.isChecking || networkFees?.isChecking;
|
|
12029
|
-
const totalUsd = React__default.useMemo(
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
const eth = parseFloat(String(total.amount));
|
|
12034
|
-
if (isNaN(eth) || eth <= 0) return null;
|
|
12035
|
-
return (eth * ethUsdRate).toFixed(2);
|
|
12036
|
-
}, [ethUsdRate, total.amount, totalLoading]);
|
|
12048
|
+
const totalUsd = React__default.useMemo(
|
|
12049
|
+
() => computeUsd(total.amount, total.weiAmount, ethUsdRate, !!totalLoading),
|
|
12050
|
+
[ethUsdRate, total.amount, total.weiAmount, totalLoading]
|
|
12051
|
+
);
|
|
12037
12052
|
return /* @__PURE__ */ jsxs("div", { className: `ens-registration-pricing ${className}`, children: [
|
|
12038
12053
|
expiryPicker && /* @__PURE__ */ jsx("div", { className: "ens-expiry-picker mb-2", children: /* @__PURE__ */ jsx(
|
|
12039
12054
|
DurationPicker,
|
|
@@ -12045,23 +12060,17 @@ const PricingDisplay = ({
|
|
|
12045
12060
|
) }),
|
|
12046
12061
|
/* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mb-1", children: [
|
|
12047
12062
|
/* @__PURE__ */ jsx(Text, { size: "sm", color: "grey", children: primaryFee.label }),
|
|
12048
|
-
|
|
12063
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", color: "grey", children: primaryFee.isChecking ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 14 }) : isSentinel(primaryFee.amount) ? primaryFee.amount : `${primaryFee.amount} ETH` })
|
|
12049
12064
|
] }),
|
|
12050
12065
|
networkFees && /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mb-1", children: [
|
|
12051
12066
|
/* @__PURE__ */ jsx(Text, { size: "sm", color: "grey", children: "Est. network fees" }),
|
|
12052
|
-
|
|
12053
|
-
networkFees.amount,
|
|
12054
|
-
" ETH"
|
|
12055
|
-
] })
|
|
12067
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", color: "grey", children: networkFees.isChecking ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 14 }) : networkFees.amount === "N/A" ? "N/A" : `${networkFees.amount} ETH` })
|
|
12056
12068
|
] }),
|
|
12057
12069
|
/* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between align-items-center mt-2 total-fee", children: [
|
|
12058
12070
|
/* @__PURE__ */ jsx(Text, { size: "lg", weight: "bold", children: "Total" }),
|
|
12059
|
-
|
|
12060
|
-
/* @__PURE__ */ jsx(Text, { size: "lg", weight: "bold", children: total.amount
|
|
12061
|
-
|
|
12062
|
-
"\u2248 $",
|
|
12063
|
-
totalUsd
|
|
12064
|
-
] })
|
|
12071
|
+
/* @__PURE__ */ jsxs("div", { style: { textAlign: "right" }, children: [
|
|
12072
|
+
/* @__PURE__ */ jsx(Text, { size: "lg", weight: "bold", children: totalLoading ? /* @__PURE__ */ jsx(ShurikenSpinner, { size: 18 }) : isSentinel(total.amount) ? total.amount : `${total.amount} ETH` }),
|
|
12073
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", color: "grey", children: totalUsd ? `\u2248 $${totalUsd}` : NBSP })
|
|
12065
12074
|
] })
|
|
12066
12075
|
] })
|
|
12067
12076
|
] });
|
|
@@ -64136,6 +64145,18 @@ const ABIS = {
|
|
|
64136
64145
|
RESOLVER
|
|
64137
64146
|
};
|
|
64138
64147
|
|
|
64148
|
+
const COMMITMENTS_SLOT = 1n;
|
|
64149
|
+
const FIVE_MINUTES_SECONDS = 5 * 60;
|
|
64150
|
+
const HEURISTIC_COMMIT_GAS = 50000n;
|
|
64151
|
+
const HEURISTIC_REGISTER_BASE_GAS = 240000n;
|
|
64152
|
+
const HEURISTIC_GAS_PER_RECORD = 50000n;
|
|
64153
|
+
const isStateOverrideRejection = (err) => {
|
|
64154
|
+
const e = err;
|
|
64155
|
+
const code = e?.code ?? e?.cause?.code;
|
|
64156
|
+
if (code === -32602 || code === -32601 || code === -32e3) return true;
|
|
64157
|
+
const msg = `${e?.shortMessage ?? ""} ${e?.message ?? ""}`.toLowerCase();
|
|
64158
|
+
return msg.includes("state override") || msg.includes("stateoverride") || msg.includes("too many arguments") || msg.includes("invalid argument 2") || msg.includes("3rd parameter") || msg.includes("does not support");
|
|
64159
|
+
};
|
|
64139
64160
|
const NAMESPACE_REFERRER_ADDRESS = "0xb7B18611b8C51B4B3F400BaF09DB49E61e0aF044";
|
|
64140
64161
|
const ENS_REGISTRY_ABI = parseAbi([
|
|
64141
64162
|
"function owner(bytes32) view returns (address)"
|
|
@@ -64160,7 +64181,7 @@ const useRegisterENS = ({ isTestnet }) => {
|
|
|
64160
64181
|
const totalPrice = price.base + price.premium;
|
|
64161
64182
|
return {
|
|
64162
64183
|
wei: totalPrice,
|
|
64163
|
-
eth:
|
|
64184
|
+
eth: parseFloat(formatEther(totalPrice))
|
|
64164
64185
|
};
|
|
64165
64186
|
};
|
|
64166
64187
|
const isEnsAvailable = async (label) => {
|
|
@@ -64234,6 +64255,87 @@ const useRegisterENS = ({ isTestnet }) => {
|
|
|
64234
64255
|
const tx = await walletClient.writeContract(contractRequest);
|
|
64235
64256
|
return { txHash: tx, price };
|
|
64236
64257
|
};
|
|
64258
|
+
const getEffectiveGasPrice = () => publicClient.getGasPrice();
|
|
64259
|
+
const commitmentStorageSlot = (commitment) => keccak256(
|
|
64260
|
+
concatHex([padHex(commitment, { size: 32 }), padHex(toHex(COMMITMENTS_SLOT), { size: 32 })])
|
|
64261
|
+
);
|
|
64262
|
+
const estimateRegistrationFees = async (request) => {
|
|
64263
|
+
const fullName = `${request.label}.eth`;
|
|
64264
|
+
const resolverData = convertToResolverData(fullName, request.records);
|
|
64265
|
+
const controller = getEthController();
|
|
64266
|
+
const commitmentParams = {
|
|
64267
|
+
label: request.label,
|
|
64268
|
+
owner: request.owner,
|
|
64269
|
+
duration: BigInt(request.durationInSeconds),
|
|
64270
|
+
secret: keccak256(toBytes$1(request.secret)),
|
|
64271
|
+
resolver: getPublicResolver(),
|
|
64272
|
+
data: resolverData,
|
|
64273
|
+
reverseRecord: 0,
|
|
64274
|
+
referrer: getRegReferrer(request)
|
|
64275
|
+
};
|
|
64276
|
+
const commitment = await publicClient.readContract({
|
|
64277
|
+
functionName: "makeCommitment",
|
|
64278
|
+
abi: ABIS.ETH_REGISTRAR_CONTOLLER,
|
|
64279
|
+
address: controller,
|
|
64280
|
+
args: [commitmentParams]
|
|
64281
|
+
});
|
|
64282
|
+
const price = await getRegistrationPrice(request.label, request.durationInSeconds);
|
|
64283
|
+
const fiveMinAgo = BigInt(Math.floor(Date.now() / 1e3) - FIVE_MINUTES_SECONDS);
|
|
64284
|
+
const balanceOverride = price.wei * 2n + parseEther("1000000");
|
|
64285
|
+
const gasPricePromise = getEffectiveGasPrice();
|
|
64286
|
+
const commitGasPromise = publicClient.estimateContractGas({
|
|
64287
|
+
address: controller,
|
|
64288
|
+
abi: ABIS.ETH_REGISTRAR_CONTOLLER,
|
|
64289
|
+
functionName: "commit",
|
|
64290
|
+
args: [commitment],
|
|
64291
|
+
account: request.owner
|
|
64292
|
+
}).catch(() => HEURISTIC_COMMIT_GAS);
|
|
64293
|
+
const registerGasPromise = publicClient.estimateContractGas({
|
|
64294
|
+
address: controller,
|
|
64295
|
+
abi: ABIS.ETH_REGISTRAR_CONTOLLER,
|
|
64296
|
+
functionName: "register",
|
|
64297
|
+
args: [commitmentParams],
|
|
64298
|
+
account: request.owner,
|
|
64299
|
+
value: price.wei,
|
|
64300
|
+
stateOverride: [
|
|
64301
|
+
{
|
|
64302
|
+
address: controller,
|
|
64303
|
+
stateDiff: [
|
|
64304
|
+
{
|
|
64305
|
+
slot: commitmentStorageSlot(commitment),
|
|
64306
|
+
value: padHex(toHex(fiveMinAgo), { size: 32 })
|
|
64307
|
+
}
|
|
64308
|
+
]
|
|
64309
|
+
},
|
|
64310
|
+
{ address: request.owner, balance: balanceOverride }
|
|
64311
|
+
]
|
|
64312
|
+
}).then((g) => ({ gas: g, isHeuristic: false })).catch((err) => {
|
|
64313
|
+
if (typeof console !== "undefined") {
|
|
64314
|
+
console.warn(
|
|
64315
|
+
"[useRegisterENS] register-gas estimation failed; using heuristic.",
|
|
64316
|
+
isStateOverrideRejection(err) ? "(state override unsupported)" : "",
|
|
64317
|
+
err
|
|
64318
|
+
);
|
|
64319
|
+
}
|
|
64320
|
+
const recordCount = (request.records.addresses?.length ?? 0) + (request.records.texts?.length ?? 0);
|
|
64321
|
+
const heuristic = HEURISTIC_REGISTER_BASE_GAS + BigInt(recordCount) * HEURISTIC_GAS_PER_RECORD;
|
|
64322
|
+
return { gas: heuristic, isHeuristic: true };
|
|
64323
|
+
});
|
|
64324
|
+
const [commitGas, registerResult, gasPrice] = await Promise.all([
|
|
64325
|
+
commitGasPromise,
|
|
64326
|
+
registerGasPromise,
|
|
64327
|
+
gasPricePromise
|
|
64328
|
+
]);
|
|
64329
|
+
const totalGas = commitGas + registerResult.gas;
|
|
64330
|
+
const totalWei = totalGas * gasPrice;
|
|
64331
|
+
return {
|
|
64332
|
+
wei: totalWei,
|
|
64333
|
+
eth: parseFloat(formatEther(totalWei)),
|
|
64334
|
+
gasEstimate: totalGas,
|
|
64335
|
+
gasPrice,
|
|
64336
|
+
isHeuristic: registerResult.isHeuristic
|
|
64337
|
+
};
|
|
64338
|
+
};
|
|
64237
64339
|
const getEthController = () => distExports$1.getEnsContracts(isTestnet).ethRegistrarController;
|
|
64238
64340
|
const getEnsRegistry = () => distExports$1.getEnsContracts(isTestnet).ensRegistry;
|
|
64239
64341
|
const getPublicResolver = () => distExports$1.getEnsContracts(isTestnet).publicResolver;
|
|
@@ -64244,6 +64346,7 @@ const useRegisterENS = ({ isTestnet }) => {
|
|
|
64244
64346
|
return {
|
|
64245
64347
|
isEnsAvailable,
|
|
64246
64348
|
getRegistrationPrice,
|
|
64349
|
+
estimateRegistrationFees,
|
|
64247
64350
|
sendCommitmentTx,
|
|
64248
64351
|
sendRegisterTx
|
|
64249
64352
|
};
|
|
@@ -89487,19 +89590,15 @@ const RegistrationSummary = ({
|
|
|
89487
89590
|
const { isConnected } = useAccount();
|
|
89488
89591
|
const { ethUsdRate } = useEthDollarValue();
|
|
89489
89592
|
const { isEnsAvailable, getRegistrationPrice } = useRegisterENS({ isTestnet });
|
|
89490
|
-
const { regPrice, regFees, regTotal } = useMemo(() => {
|
|
89491
|
-
|
|
89492
|
-
|
|
89493
|
-
|
|
89494
|
-
|
|
89495
|
-
|
|
89496
|
-
|
|
89497
|
-
|
|
89498
|
-
|
|
89499
|
-
regFees2 += transactionFees.price.eth;
|
|
89500
|
-
total += transactionFees.price.eth;
|
|
89501
|
-
}
|
|
89502
|
-
return { regFees: regFees2, regPrice: regPrice2, regTotal: formatFloat(total, 5) };
|
|
89593
|
+
const { regPrice, regFees, regTotal, regTotalWei } = useMemo(() => {
|
|
89594
|
+
const priceEth = price?.eth ?? 0;
|
|
89595
|
+
const feesEth = transactionFees?.price.eth ?? 0;
|
|
89596
|
+
const heuristicPrefix = transactionFees?.isHeuristic ? "~" : "";
|
|
89597
|
+
const regPrice2 = priceEth > 0 ? formatEth(priceEth) : "0.0000";
|
|
89598
|
+
const regFees2 = transactionFees?.failed ? "N/A" : `${heuristicPrefix}${formatEth(feesEth)}`;
|
|
89599
|
+
const regTotal2 = transactionFees?.failed ? "N/A" : `${heuristicPrefix}${formatEth(priceEth + feesEth)}`;
|
|
89600
|
+
const regTotalWei2 = (price?.wei ?? 0n) + (transactionFees?.price.wei ?? 0n);
|
|
89601
|
+
return { regPrice: regPrice2, regFees: regFees2, regTotal: regTotal2, regTotalWei: regTotalWei2 };
|
|
89503
89602
|
}, [price, transactionFees]);
|
|
89504
89603
|
const checkAvailability = async (labelToCheck) => {
|
|
89505
89604
|
try {
|
|
@@ -89521,6 +89620,14 @@ const RegistrationSummary = ({
|
|
|
89521
89620
|
onPriceChange({ isChecking: false, eth: -1, wei: 0n });
|
|
89522
89621
|
}
|
|
89523
89622
|
};
|
|
89623
|
+
useEffect(() => {
|
|
89624
|
+
if (label.length >= MIN_ENS_LEN$2) {
|
|
89625
|
+
onNameValidationChange({ isChecking: true, isTaken: false });
|
|
89626
|
+
onPriceChange({ isChecking: true, eth: 0, wei: 0n });
|
|
89627
|
+
checkAvailability(label);
|
|
89628
|
+
checkRegistrationPrice(label, durationSeconds);
|
|
89629
|
+
}
|
|
89630
|
+
}, []);
|
|
89524
89631
|
const debouncedCheckAvailability = useCallback(
|
|
89525
89632
|
debounce((labelToCheck) => checkAvailability(labelToCheck), 500),
|
|
89526
89633
|
[]
|
|
@@ -89562,7 +89669,7 @@ const RegistrationSummary = ({
|
|
|
89562
89669
|
);
|
|
89563
89670
|
const nextBtnDisabled = label.length < MIN_ENS_LEN$2 || nameValidation.isChecking || nameValidation.isTaken;
|
|
89564
89671
|
const totalPriceLoading = transactionFees?.isChecking || price.isChecking;
|
|
89565
|
-
const transactionFeesLoading = transactionFees?.isChecking ||
|
|
89672
|
+
const transactionFeesLoading = transactionFees?.isChecking || price.isChecking;
|
|
89566
89673
|
return /* @__PURE__ */ jsxs("div", { className: "ens-registration-summary", children: [
|
|
89567
89674
|
!hideBanner && /* @__PURE__ */ jsx("div", { className: "d-flex justify-content-center", children: /* @__PURE__ */ jsx(
|
|
89568
89675
|
"img",
|
|
@@ -89613,13 +89720,11 @@ const RegistrationSummary = ({
|
|
|
89613
89720
|
amount: regPrice,
|
|
89614
89721
|
isChecking: price.isChecking
|
|
89615
89722
|
},
|
|
89616
|
-
networkFees: {
|
|
89617
|
-
amount: regFees,
|
|
89618
|
-
isChecking: transactionFeesLoading
|
|
89619
|
-
},
|
|
89723
|
+
networkFees: transactionFees ? { amount: regFees, isChecking: transactionFeesLoading } : void 0,
|
|
89620
89724
|
total: {
|
|
89621
89725
|
amount: regTotal,
|
|
89622
|
-
isChecking: totalPriceLoading
|
|
89726
|
+
isChecking: totalPriceLoading,
|
|
89727
|
+
weiAmount: regTotalWei
|
|
89623
89728
|
},
|
|
89624
89729
|
expiryPicker: {
|
|
89625
89730
|
durationSeconds,
|
|
@@ -89846,13 +89951,19 @@ const CommitmentStep = ({
|
|
|
89846
89951
|
return;
|
|
89847
89952
|
}
|
|
89848
89953
|
try {
|
|
89849
|
-
await waitTx({ hash: tx });
|
|
89954
|
+
const receipt = await waitTx({ hash: tx });
|
|
89955
|
+
const commitFeeWei = receipt.gasUsed * (receipt.effectiveGasPrice || 0n);
|
|
89850
89956
|
setCommitTxStatus({ sent: true, completed: true, hash: tx });
|
|
89851
89957
|
setTimeout(() => {
|
|
89852
89958
|
onStateUpdated({
|
|
89853
89959
|
...state,
|
|
89854
89960
|
step: ProcessSteps.TimerStarted,
|
|
89855
|
-
commitment: {
|
|
89961
|
+
commitment: {
|
|
89962
|
+
tx,
|
|
89963
|
+
completed: true,
|
|
89964
|
+
time: (/* @__PURE__ */ new Date()).getTime(),
|
|
89965
|
+
feeWei: commitFeeWei
|
|
89966
|
+
}
|
|
89856
89967
|
});
|
|
89857
89968
|
setCommitTxStatus({ sent: false, completed: false, hash: "" });
|
|
89858
89969
|
}, 1e3);
|
|
@@ -90072,9 +90183,10 @@ const RegistrationStep = ({
|
|
|
90072
90183
|
try {
|
|
90073
90184
|
const receipt = await waitTx({ hash: tx });
|
|
90074
90185
|
setCommitTxStatus({ sent: true, completed: true, hash: tx });
|
|
90075
|
-
const
|
|
90076
|
-
const
|
|
90077
|
-
const
|
|
90186
|
+
const registerFeeWei = receipt.gasUsed * (receipt.effectiveGasPrice || 0n);
|
|
90187
|
+
const commitFeeWei = state.commitment?.feeWei ?? 0n;
|
|
90188
|
+
const totalFeeWei = registerFeeWei + commitFeeWei;
|
|
90189
|
+
const transactionFeesEth = formatEther(totalFeeWei);
|
|
90078
90190
|
const totalCost = (registrationPrice + parseFloat(transactionFeesEth)).toString();
|
|
90079
90191
|
const expiryDate = new Date(Date.now() + state.durationInSeconds * 1e3);
|
|
90080
90192
|
const formattedExpiryDate = expiryDate.toLocaleDateString("en-US", {
|
|
@@ -91062,19 +91174,25 @@ const RegistrationProcess = ({
|
|
|
91062
91174
|
] });
|
|
91063
91175
|
};
|
|
91064
91176
|
|
|
91177
|
+
const REG_SECRET_PLACEHOLDER = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
91178
|
+
const FEE_ESTIMATE_OWNER_PLACEHOLDER = "0x0000000000000000000000000000000000000001";
|
|
91065
91179
|
const getLabel = (name) => {
|
|
91066
91180
|
if (!name) return "";
|
|
91067
91181
|
if (name.split(".").length !== 1) return name.split(".")[0];
|
|
91068
91182
|
return name;
|
|
91069
91183
|
};
|
|
91070
91184
|
const EnsNameRegistrationForm = (props) => {
|
|
91185
|
+
const { address: connectedAddress } = useAccount();
|
|
91186
|
+
const { estimateRegistrationFees } = useRegisterENS({ isTestnet: props.isTestnet });
|
|
91071
91187
|
const [label, setLabel] = useState(getLabel(props.name));
|
|
91072
91188
|
const [step, setStep] = useState(0 /* Summary */);
|
|
91073
91189
|
const [durationSeconds, setDurationSeconds] = useState(() => secondsFromYears(/* @__PURE__ */ new Date(), 1));
|
|
91074
91190
|
const [regTxFees, setRegTxFees] = useState({
|
|
91075
91191
|
estimatedGas: 0,
|
|
91076
91192
|
isChecking: false,
|
|
91077
|
-
|
|
91193
|
+
failed: false,
|
|
91194
|
+
isHeuristic: false,
|
|
91195
|
+
price: { wei: 0n, eth: 0 }
|
|
91078
91196
|
});
|
|
91079
91197
|
const [price, setPrice] = useState({ isChecking: false, wei: 0n, eth: 0 });
|
|
91080
91198
|
const [nameValidation, setNameValidation] = useState({ isChecking: false, isTaken: false });
|
|
@@ -91092,6 +91210,74 @@ const EnsNameRegistrationForm = (props) => {
|
|
|
91092
91210
|
[ensRecords, ensRecordTemplate]
|
|
91093
91211
|
);
|
|
91094
91212
|
const [successData, setSuccessData] = useState();
|
|
91213
|
+
const feeRequestRef = useRef(0);
|
|
91214
|
+
const estimateFnRef = useRef(estimateRegistrationFees);
|
|
91215
|
+
const referrerRef = useRef(props.referrer);
|
|
91216
|
+
estimateFnRef.current = estimateRegistrationFees;
|
|
91217
|
+
referrerRef.current = props.referrer;
|
|
91218
|
+
const debouncedEstimate = useMemo(
|
|
91219
|
+
() => debounce(
|
|
91220
|
+
(requestId, params) => {
|
|
91221
|
+
estimateFnRef.current({
|
|
91222
|
+
label: params.label,
|
|
91223
|
+
owner: params.owner,
|
|
91224
|
+
durationInSeconds: params.durationInSeconds,
|
|
91225
|
+
secret: REG_SECRET_PLACEHOLDER,
|
|
91226
|
+
records: params.records,
|
|
91227
|
+
referrer: referrerRef.current
|
|
91228
|
+
}).then((result) => {
|
|
91229
|
+
if (feeRequestRef.current !== requestId) return;
|
|
91230
|
+
setRegTxFees({
|
|
91231
|
+
isChecking: false,
|
|
91232
|
+
failed: false,
|
|
91233
|
+
isHeuristic: result.isHeuristic,
|
|
91234
|
+
estimatedGas: Number(result.gasEstimate),
|
|
91235
|
+
price: { wei: result.wei, eth: result.eth }
|
|
91236
|
+
});
|
|
91237
|
+
}).catch(() => {
|
|
91238
|
+
if (feeRequestRef.current !== requestId) return;
|
|
91239
|
+
setRegTxFees({
|
|
91240
|
+
isChecking: false,
|
|
91241
|
+
failed: true,
|
|
91242
|
+
isHeuristic: false,
|
|
91243
|
+
estimatedGas: 0,
|
|
91244
|
+
price: { wei: 0n, eth: 0 }
|
|
91245
|
+
});
|
|
91246
|
+
});
|
|
91247
|
+
},
|
|
91248
|
+
500
|
|
91249
|
+
),
|
|
91250
|
+
[]
|
|
91251
|
+
);
|
|
91252
|
+
useEffect(() => {
|
|
91253
|
+
if (!label || label.length < 3 || nameValidation.isChecking || nameValidation.isTaken || price.isChecking || price.eth <= 0) {
|
|
91254
|
+
feeRequestRef.current += 1;
|
|
91255
|
+
setRegTxFees((prev) => prev.isChecking ? { ...prev, isChecking: false } : prev);
|
|
91256
|
+
return;
|
|
91257
|
+
}
|
|
91258
|
+
const requestId = feeRequestRef.current + 1;
|
|
91259
|
+
feeRequestRef.current = requestId;
|
|
91260
|
+
setRegTxFees(
|
|
91261
|
+
(prev) => prev.isChecking && !prev.failed ? prev : { ...prev, isChecking: true, failed: false }
|
|
91262
|
+
);
|
|
91263
|
+
debouncedEstimate(requestId, {
|
|
91264
|
+
label,
|
|
91265
|
+
// Estimation works without a wallet — gas price comes from the network
|
|
91266
|
+
// and the owner's balance is state-overridden in the estimator.
|
|
91267
|
+
owner: connectedAddress ?? FEE_ESTIMATE_OWNER_PLACEHOLDER,
|
|
91268
|
+
durationInSeconds: durationSeconds,
|
|
91269
|
+
records: ensRecords
|
|
91270
|
+
});
|
|
91271
|
+
}, [
|
|
91272
|
+
connectedAddress,
|
|
91273
|
+
label,
|
|
91274
|
+
durationSeconds,
|
|
91275
|
+
ensRecords,
|
|
91276
|
+
nameValidation.isChecking,
|
|
91277
|
+
nameValidation.isTaken,
|
|
91278
|
+
price.isChecking,
|
|
91279
|
+
price.eth
|
|
91280
|
+
]);
|
|
91095
91281
|
const handleSaveRecords = () => {
|
|
91096
91282
|
setEnsRecords(deepCopy(ensRecordTemplate));
|
|
91097
91283
|
setShowProfile(false);
|
|
@@ -93646,5 +93832,5 @@ const useTheme = () => {
|
|
|
93646
93832
|
return ctx;
|
|
93647
93833
|
};
|
|
93648
93834
|
|
|
93649
|
-
export { Accordion, Alert, Button, Card, ChainIcon, ConnectAndSetChain, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, DurationPicker, ENS_RESOLVER_ABI, EnsNameRegistrationForm, EnsRecordsForm, Icon, Input, ListingNetwork, ListingType, MIN_REGISTRATION_SECONDS, MULTICALL, Modal, ONE_DAY, ONE_YEAR, OffchainSubnameForm, PricingDisplay, ProfileHeader, ProgressBar, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, SubnameMintForm, Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionPendingScreen, TxProgress, capitalize, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce, deepCopy, diffToEnsRecords, ensureFloatInput, equalsIgnoreCase, formatDurationSummary, formatFloat, getAvatarUploadErrorMessage, getBlockExplorer, getBlockExplorerAddressUrl, getBlockExplorerName, getBlockExplorerTransactionUrl, getChainIdForListingNetwork, getEnsAppUrl, getEnsRecordsDiff, getImageUploadErrorMessage, getSupportedAddressByChainId, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isUserDeniedError, roundDurationWithDay, secondsFromYears, secondsToDateInput, supportedAddresses, supportedContenthashRecords, supportedTexts, useAvatarClient, useENSResolver, useEthDollarValue, useMintManager, useMintSubname, useOffchainManager, useRegisterENS, useTheme, useWaitTransaction, validateEnsRecords, wait, yearsFromSeconds };
|
|
93835
|
+
export { Accordion, Alert, Button, Card, ChainIcon, ConnectAndSetChain, ContenthashIcon, ContenthashProtocol, ContractErrorLabel, Dropdown, DurationPicker, ENS_RESOLVER_ABI, ETH_SENTINELS, EnsNameRegistrationForm, EnsRecordsForm, Icon, Input, ListingNetwork, ListingType, MIN_REGISTRATION_SECONDS, MULTICALL, Modal, ONE_DAY, ONE_YEAR, OffchainSubnameForm, PricingDisplay, ProfileHeader, ProgressBar, SET_ADDRESS_FUNC, SET_CONTENTHASH_FUNC, SET_TEXT_FUNC, SelectRecordsForm, ShurikenSpinner, SubnameMintForm, Text, TextRecordCategory, Textarea, ThemeProvider, Tooltip, TransactionPendingScreen, TxProgress, capitalize, computeUsd, convertEVMChainIdToCoinType, convertToMulticallResolverData, convertToResolverData, createEnsReferer, debounce, deepCopy, diffToEnsRecords, ensureFloatInput, equalsIgnoreCase, formatDurationSummary, formatEth, formatFloat, getAvatarUploadErrorMessage, getBlockExplorer, getBlockExplorerAddressUrl, getBlockExplorerName, getBlockExplorerTransactionUrl, getChainIdForListingNetwork, getEnsAppUrl, getEnsRecordsDiff, getImageUploadErrorMessage, getSupportedAddressByChainId, getSupportedAddressByCoin, getSupportedAddressByName, getSupportedAddressMap, getSupportedChashByProtocol, getSupportedText, isCommitmentToNewErr, isContenthashValid, isSentinel, isUserDeniedError, roundDurationWithDay, secondsFromYears, secondsToDateInput, supportedAddresses, supportedContenthashRecords, supportedTexts, usdFromWei, useAvatarClient, useENSResolver, useEthDollarValue, useMintManager, useMintSubname, useOffchainManager, useRegisterENS, useTheme, useWaitTransaction, validateEnsRecords, wait, yearsFromSeconds };
|
|
93650
93836
|
//# sourceMappingURL=index.js.map
|