import React, { Fragment, PureComponent } from 'react'; import web3 from 'web3'; import { connect } from 'react-redux'; import { actions as accountActions, getDefaultAccount } from '../../reducers/accounts'; import { hash } from 'eth-ens-namehash'; import Hidden from '@material-ui/core/Hidden'; import Typography from '@material-ui/core/Typography'; import ENSSubdomainRegistry from 'Embark/contracts/ENSSubdomainRegistry'; import { Button, Field, TextInput, MobileSearch, MobileButton, Card, Info, Text } from '../../ui/components' import { IconCheck } from '../../ui/icons' import { keyFromXY } from '../../utils/ecdsa'; import EditOptions from './EditOptions'; import ReleaseDomainAlert from './ReleaseDomain'; import theme from '../../ui/theme' import { withFormik } from 'formik'; import PublicResolver from 'Embark/contracts/PublicResolver'; import { CopyToClipboard } from 'react-copy-to-clipboard'; import RegisterSubDomain from '../ens/registerSubDomain'; import StatusLogo from '../../ui/icons/components/StatusLogo' import EnsLogo from '../../ui/icons/logos/ens.png'; import { formatPrice } from '../ens/utils'; import CheckCircle from '../../ui/icons/components/baseline_check_circle_outline.png'; const { getPrice, getExpirationTime, release } = ENSSubdomainRegistry.methods; import NotInterested from '@material-ui/icons/NotInterested'; import Face from '@material-ui/icons/Face'; const invalidSuffix = '0000000000000000000000000000000000000000' const nullAddress = '0x0000000000000000000000000000000000000000' const validAddress = address => address != nullAddress; const validStatusAddress = address => !address.includes(invalidSuffix); const formatName = domainName => domainName.includes('.') ? domainName : `${domainName}.stateofus.eth`; const getDomain = fullDomain => formatName(fullDomain).split('.').slice(1).join('.'); const hashedDomain = domainName => hash(getDomain(domainName)); const { soliditySha3, fromWei } = web3.utils; const cardStyle = { width: '100%', padding: '30px', height: '425px' } const addressStyle = { fontSize: '18px', fontWeight: 400, cursor: 'copy', wordWrap: 'break-word', } const backButton = { fontSize: '40px', color: theme.accent, cursor: 'pointer' } const generatePrettyDate = (timestamp) => new Date(timestamp * 1000).toDateString(); const DisplayBox = ({ displayType, pubKey }) => (
{displayType}
{pubKey}
); const MobileAddressDisplay = ({ domainName, address, statusAccount, expirationTime, defaultAccount, isOwner }) => ( {isOwner ? : } {formatName(domainName)}
{expirationTime && Locked until {generatePrettyDate(expirationTime)}}
{isOwner ? 'You\'re the owner of this name' : 'Name is unavailable'} registered to the addresses below {validStatusAddress(statusAccount) && }
) class RenderAddresses extends PureComponent { state = { copied: false, editMenu: false } render() { const { domainName, address, statusAccount, expirationTime, defaultAccount } = this.props const { copied, editMenu, editAction } = this.state const markCopied = (v) => { this.setState({ copied: v }) } const isCopied = address => address == copied; const renderCopied = address => isCopied(address) && Copied!; const isOwner = defaultAccount === address; const onClose = value => { this.setState({ editAction: value, editMenu: false }) } const closeReleaseAlert = value => { if (value) { release( soliditySha3(domainName), hash('stateofus.eth'), ) .send() } this.setState({ editAction: null }) } return (
{formatName(domainName)}{expirationTime && (Expires {generatePrettyDate(expirationTime)})} Resolves To: {address && Ethereum Address {renderCopied(address)}}
{address}
{validStatusAddress(statusAccount) && Status Address {renderCopied(statusAccount)}} {validStatusAddress(statusAccount) &&
{statusAccount}
}
{isOwner && { this.setState({ editMenu: true }) } }/>} {editMenu && }
) } } const RegisterInfoCard = ({ formattedDomain, domainPrice }) => ( {formattedDomain.toLowerCase()} can be registered for {!!domainPrice && formatPrice(fromWei(domainPrice))} SNT {formattedDomain.toLowerCase()}
{!!domainPrice && formatPrice(fromWei(domainPrice))} SNT / 1 year
This name will be pointed to the wallet address and contact code below
) class Register extends PureComponent { state = { domainPrice: null }; componentDidMount() { const { domainName } = this.props; getPrice(hashedDomain(domainName)) .call() .then((res) => { this.setState({ domainPrice: res })}); } onRegistered = (address, statusAccount) => { const { domainPrice } = this.state; const { subtractFromBalance } = this.props; subtractFromBalance(domainPrice); this.setState({ registered: { address, statusAccount } }); } render() { const { domainName, setStatus, style } = this.props; const { domainPrice, registered } = this.state; const formattedDomain = formatName(domainName); const formattedDomainArray = formattedDomain.split('.') return (
{!registered ? : }
) } } const mapDispatchToProps = dispatch => ({ subtractFromBalance(amount) { dispatch(accountActions.subtractfromSntTokenBalance(amount)); }, }); const mapStateToProps = state => ({ defaultAccount: getDefaultAccount(state) }) const ConnectedRegister = connect(mapStateToProps, mapDispatchToProps)(Register); const DisplayAddress = connect(mapStateToProps)((props) => ( {validAddress(props.address) ? : {props.domainName} } )) const LookupForm = ({ handleSubmit, values, handleChange, justSearch }) => (
{!justSearch && Symbols * /
are not supported
}
) const InnerForm = ({ values, errors, touched, handleChange, handleBlur, handleSubmit, isSubmitting, status, setStatus }) => (
Ens Logo {!status ? : validAddress(status.address) ? :
}
) const NameLookup = withFormik({ mapPropsToValues: props => ({ domainName: '' }), async handleSubmit(values, { status, setSubmitting, setStatus }) { const { domainName } = values; const { addr, pubkey } = PublicResolver.methods; const lookupHash = hash(formatName(domainName)); const address = await addr(lookupHash).call(); const keys = await pubkey(lookupHash).call(); const statusAccount = keyFromXY(keys[0], keys[1]); const expirationTime = await getExpirationTime(lookupHash).call(); setStatus({ address, statusAccount, expirationTime }); } })(InnerForm) export default NameLookup;