import React from 'react'
import { Box, Text } from 'ink'
import type { Address } from 'viem'
import { Surface } from '../../../ui/Surface.js'
import { TextInput } from '../../../ui/TextInput.js'
import { theme } from '../../../ui/theme.js'
import {
isEthDomain,
sanitizeSubdomainPrefix,
} from '../../ens/ensLookup.js'
import {
displayCustodyMode,
readIdentityStateString,
type CustodyMode,
} from '../custody/state.js'
import { ensValidationReasonText } from './state.js'
import { shortAddress } from '../shared/model/format.js'
import { FieldRow } from '../shared/components/FieldRow.js'
import { readValidationFromState } from './editCopy.js'
import type { EnsEditProps } from './types.js'
export const footerHint = (hint: string) => {hint}
import { abbreviateRecordValue } from './editCopy.js'
export const renderRecordValue = (value: string) =>
value
? {abbreviateRecordValue(value)}
: Unset
export function rootErrorMessage(
reason: 'invalid-root' | 'missing-token-id' | 'root-not-owned' | 'wrapped-parent' | 'root-owner-mismatch' | 'token-owner-mismatch' | 'token-owner-lookup-failed' | 'lookup-failed',
detail: string,
rootName: string,
): string {
switch (reason) {
case 'invalid-root':
return 'Enter the parent .eth name, e.g. name.eth'
case 'missing-token-id':
return 'This identity is missing an ERC-8004 token id'
case 'root-not-owned':
return `${rootName} does not have an ENS manager on Ethereum mainnet. Switch wallets or pick a different parent name.`
case 'wrapped-parent':
return `${rootName} ENS NameWrapper ownership could not be verified: ${detail}`
case 'root-owner-mismatch':
return `Connected wallet does not manage ${rootName}. ${detail}`
case 'token-owner-mismatch':
return `Connected wallet manages ${rootName} but does not own this ERC-8004 token. ${detail}. Move the token to this wallet, then submit again.`
case 'token-owner-lookup-failed':
return `Could not verify ERC-8004 token owner: ${detail}`
case 'lookup-failed':
return `ENS lookup failed: ${detail}`
}
}
export const EnsSetupRow: React.FC<{ label: string; value: string; muted?: boolean }> = ({ label, value, muted }) => (
{label}
{value}
)
export const EnsStatusBanner: React.FC<{ identity: EnsEditProps['identity']; noRootEnsName?: boolean }> = ({ identity, noRootEnsName }) => {
const ensName = readIdentityStateString(identity.state, 'ensName')
if (!ensName) {
const status = noRootEnsName
? 'Not Linked. This wallet does not own a root .eth ENS name.'
: 'Not Linked. Choose a setup below.'
return {status}} />
}
const validation = readValidationFromState(identity.state)
if (validation?.ok) {
return linked, {ensName}} />
}
return (
issue, {ensName} ({ensValidationReasonText(validation?.reason)})}
/>
)
}
type AssignEnsCurrentSetupProps = {
currentEnsName: string
currentMode: CustodyMode | undefined
ownerAddress: string
operatorAddress: string
tokenNetworkLabel: string
}
export const AssignEnsCurrentSetup: React.FC = ({
currentEnsName,
currentMode,
ownerAddress,
operatorAddress,
tokenNetworkLabel,
}) => {
const modeLabel = displayCustodyMode(currentMode)
return (
Current Setup
{currentMode === 'advanced'
? (
<>
{ownerAddress ? : null}
{operatorAddress ? : null}
>
)
: null}
)
}
type SubdomainEntryProps = {
parent: string
ownerAddress: Address
initialValue?: string
placeholder?: string
error?: string
onConfirm: (fullName: string) => void
onBack: () => void
}
export const SubdomainEntry: React.FC = ({ parent, ownerAddress, initialValue, placeholder, error, onConfirm, onBack }) => (
{error ? {error} : null}
{
const v = sanitizeSubdomainPrefix(value)
if (!v) return 'Subdomain name cannot be empty'
if (value.includes('.')) return 'Enter only the subdomain name, not the full ENS name'
if (!isEthDomain(`${v}.${parent}`)) return 'Invalid characters in subdomain name'
return null
}}
onSubmit={value => {
const prefix = sanitizeSubdomainPrefix(value)
if (!prefix) return
onConfirm(`${prefix}.${parent}`)
}}
onCancel={onBack}
/>
Wallet: {shortAddress(ownerAddress)}
)