import React, { Fragment, PureComponent } from 'react';
import web3 from 'web3';
import EmbarkJS from 'Embark/EmbarkJS';
import { connect } from 'react-redux';
import { actions as accountActions, getDefaultAccount } from '../../reducers/accounts';
import { checkAndDispatchStatusContactCode } from '../../actions/accounts';
import { hash } from 'eth-ens-namehash';
import { isNil } from 'lodash';
import Hidden from '@material-ui/core/Hidden';
import Typography from '@material-ui/core/Typography';
import UsernameRegistrar from 'Embark/contracts/UsernameRegistrar';
import ENSRegistry from 'Embark/contracts/ENSRegistry';
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';
import Warning from '../../ui/components/Warning';
const { getPrice, getExpirationTime, getCreationTime, release } = UsernameRegistrar.methods;
import NotInterested from '@material-ui/icons/NotInterested';
import Face from '@material-ui/icons/Face';
import Copy from './copy';
import IDNANormalizer from 'idna-normalize';
import { nullAddress, getResolver } from './utils/domain';
import { YOUR_CONTACT_CODE } from './constants';
import DisplayBox from './DisplayBox';
import styled from "styled-components";
import { Route } from "react-router-dom";
const normalizer = new IDNANormalizer();
const invalidSuffix = '0000000000000000000000000000000000000000'
const validAddress = address => address !== nullAddress;
const validStatusAddress = address => !address.includes(invalidSuffix);
const formatName = domainName => domainName.includes('.') ? normalizer.normalize(domainName) : normalizer.normalize(`${domainName}.stateofus.eth`);
const getDomain = fullDomain => formatName(fullDomain).split('.').slice(1).join('.');
const hashedDomain = domainName => hash(getDomain(domainName));
const registryIsOwner = address => address === UsernameRegistrar._address;
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 validTimestamp = timestamp => Number(timestamp) > 99999999;
const generatePrettyDate = timestamp => new Date(timestamp * 1000).toDateString();
const pastReleaseDate = timestamp => new Date > new Date(timestamp * 1000);
const MobileAddressDisplay = ({ domainName, address, statusAccount, expirationTime, creationTime, defaultAccount, isOwner, edit, onSubmit, handleChange, values, handleSubmit }) => (
{isOwner ? : }
{formatName(domainName)}
{isOwner
? edit ? 'Edit Contact Code' : 'You own this ENS name'
: 'unavailable'}
Registered {validTimestamp(creationTime) && generatePrettyDate(creationTime)}
{edit
? 'The contact code connects the domain with a unique Status account'
: validAddress(address) ? 'to the addresses below' : 'Click \'Edit\' to add a valid address and contact code'}
{edit && }
{!edit && }
{!edit && validStatusAddress(statusAccount) && }
)
class RenderAddresses extends PureComponent {
state = { copied: false, editMenu: false, editAction: false }
render() {
const { domainName, address, statusAccount, expirationTime, defaultAccount, ownerAddress, setStatus, registryOwnsDomain } = this.props;
const { copied, editMenu, editAction, submitted } = this.state
const markCopied = (v) => { this.setState({ copied: v }) }
const isCopied = address => address === copied;
const renderCopied = address => isCopied(address) && Copied!;
const onClose = value => { this.setState({ editAction: value, editMenu: false }) }
const onClickEdit = () => { validAddress(address) ? this.setState({ editMenu: true }) : this.setState({ editAction: 'edit' }) }
const isOwner = defaultAccount === ownerAddress;
const canBeReleased = validTimestamp(expirationTime) && pastReleaseDate(expirationTime);
const closeReleaseAlert = value => {
if (!isNil(value)) {
this.setState({ submitted: true });
release(
soliditySha3(domainName)
)
.send()
} else {
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}
}
{submitted ? : { this.setState({ submitted: true}) }}/>}
{isOwner && !editAction && }
)
}
}
const InfoHeading = styled.h2`
line-height: 26px;
font-size: 22px;
text-align: center;
letter-spacing: -0.275px;
margin: 0 0 12px 0;
color: #FFFFFF;
`;
const RegisterInfoCard = ({ formattedDomain, domainPrice, registryOwnsDomain }) => (
{formattedDomain.toLowerCase()} can be registered for {!!domainPrice && formatPrice(fromWei(domainPrice))} SNT
{formattedDomain.toLowerCase()}
available
{!!domainPrice && formatPrice(fromWei(domainPrice))} SNT to register
{registryOwnsDomain ?
Add your contact code to use
your name in Status chat.
:
This domain is not owned by the registry'}
);
const TransactionComplete = ({ type, setStatus }) => (
{Copy[type]['title']['sub']}
{Copy[type]['title']['body']}
{Copy[type]['subheading']}
{ setStatus(null) } } />
);
class Register extends PureComponent {
state = { domainPrice: null };
componentDidMount() {
const { domainName } = this.props;
getPrice()
.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, registryOwnsDomain, ownerAddress, defaultAccount } = this.props;
const { domainPrice, registered, submitted } = this.state;
const formattedDomain = formatName(domainName);
const formattedDomainArray = formattedDomain.split('.');
const isOwner = defaultAccount === ownerAddress;
return (
{!registered && !submitted ?
{registryOwnsDomain &&
{ this.setState({ submitted: true }) }}
registeredCallbackFn={this.onRegistered} />}
:
submitted && !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.defaultAccount === props.ownerAddress ?
:
{props.domainName}
}
));
class LookupForm extends React.Component {
render() {
const { handleSubmit, values, handleChange, isWarningDisplayed } = this.props;
return (
);
}
}
const isValidDomainName = val => /^([a-z0-9]+)$/.test(val.toLowerCase());
class SearchResultsPage extends React.Component {
async loadDomainInformation({setStatus, domainName}) {
if (isValidDomainName(domainName)) {
const { methods: { owner, resolver } } = ENSRegistry;
const lookupHash = hash(formatName(domainName));
const subdomainHash = soliditySha3(domainName);
const resolverContract = await getResolver(lookupHash);
const { addr, pubkey } = resolverContract.methods;
const address = addr(lookupHash).call();
const keys = pubkey(lookupHash).call();
const ownerAddress = owner(lookupHash).call();
const suffixOwner = owner(hash(getDomain(domainName))).call();
const expirationTime = getExpirationTime(subdomainHash).call();
const creationTime = getCreationTime(subdomainHash).call();
Promise.all([address, keys, ownerAddress, expirationTime, creationTime,suffixOwner])
.then(([ address, keys, ownerAddress, expirationTime, creationTime, suffixOwner ]) => {
const statusAccount = keyFromXY(keys[0], keys[1]);
const registryOwnsDomain = registryIsOwner(suffixOwner);
setStatus({
address,
statusAccount,
expirationTime,
creationTime,
ownerAddress,
registryOwnsDomain,
domainName
});
});
} else {
setStatus({isInvalidDomain: true });
}
}
componentDidMount() {
const { setValues } = this.props;
const domainName = this.props.match.params.domainName;
setValues({domainName: domainName});
this.loadDomainInformation({
setStatus: this.props.setStatus,
domainName: domainName
});
}
componentWillReceiveProps(nextProps) {
const { setValues, match } = this.props;
const oldDomainName = match.params.domainName;
const newDomainName = nextProps.match.params.domainName;
if (oldDomainName !== newDomainName) {
setValues({domainName: newDomainName});
this.loadDomainInformation({
setStatus: this.props.setStatus,
domainName: newDomainName
});
}
}
render() {
const {
values,
handleChange,
handleSubmit,
status,
setStatus,
defaultAccount
} = this.props;
return (
{!status || !status.address ?
:
validAddress(status.address) || defaultAccount === status.ownerAddress ?
:
}
);
}
}
class NameLookupContainer extends React.Component {
render() {
const {match, status} = this.props;
return (
{match &&
}/>
}/>
}
)
}
}
const NameLookupContainerWrapped = withFormik({
mapPropsToValues: () => ({ domainName: '' }),
async handleSubmit(values, { props }) {
const { domainName } = values;
props.history.push(`${props.match.url}/${domainName}`);
}
})(NameLookupContainer);
export default connect(mapStateToProps)(NameLookupContainerWrapped);