mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Make ENS named elements domain generic (#16166)
Co-authored-by: Olaf Tomalka <olaf.tomalka@gmail.com> Co-authored-by: Vincent Shadbolt <vince.shadbolt@gmail.com> Co-authored-by: Brad Decker <bhdecker84@gmail.com> Co-authored-by: Brad Decker <git@braddecker.dev>
This commit is contained in:
parent
b675a12dbf
commit
086003555c
@ -517,8 +517,8 @@ const state = {
|
||||
maxModeOn: false,
|
||||
editingTransactionId: null,
|
||||
toNickname: 'Account 2',
|
||||
ensResolution: null,
|
||||
ensResolutionError: '',
|
||||
domainResolution: null,
|
||||
domainResolutionError: '',
|
||||
token: {
|
||||
address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D',
|
||||
symbol: 'DAI',
|
||||
|
@ -30,6 +30,7 @@ import {
|
||||
|
||||
// Local Constants
|
||||
const ZERO_X_ERROR_ADDRESS = '0x';
|
||||
const ENS = 'ENS';
|
||||
|
||||
const initialState = {
|
||||
stage: 'UNINITIALIZED',
|
||||
@ -37,11 +38,13 @@ const initialState = {
|
||||
error: null,
|
||||
warning: null,
|
||||
network: null,
|
||||
domainType: null,
|
||||
domainName: null,
|
||||
};
|
||||
|
||||
export const ensInitialState = initialState;
|
||||
export const domainInitialState = initialState;
|
||||
|
||||
const name = 'ENS';
|
||||
const name = 'DNS';
|
||||
|
||||
let web3Provider = null;
|
||||
|
||||
@ -49,51 +52,54 @@ const slice = createSlice({
|
||||
name,
|
||||
initialState,
|
||||
reducers: {
|
||||
ensLookup: (state, action) => {
|
||||
domainLookup: (state, action) => {
|
||||
// first clear out the previous state
|
||||
state.resolution = null;
|
||||
state.error = null;
|
||||
state.warning = null;
|
||||
const { address, ensName, error, network } = action.payload;
|
||||
|
||||
if (error) {
|
||||
if (
|
||||
isValidDomainName(ensName) &&
|
||||
error.message === 'ENS name not defined.'
|
||||
) {
|
||||
state.error =
|
||||
network === NETWORK_IDS.MAINNET
|
||||
? ENS_NO_ADDRESS_FOR_NAME
|
||||
: ENS_NOT_FOUND_ON_NETWORK;
|
||||
} else if (error.message === 'Illegal character for ENS.') {
|
||||
state.error = ENS_ILLEGAL_CHARACTER;
|
||||
const { address, error, network, domainType, domainName } =
|
||||
action.payload;
|
||||
state.domainType = domainType;
|
||||
if (state.domainType === ENS) {
|
||||
if (error) {
|
||||
if (
|
||||
isValidDomainName(domainName) &&
|
||||
error.message === 'ENS name not defined.'
|
||||
) {
|
||||
state.error =
|
||||
network === NETWORK_IDS.MAINNET
|
||||
? ENS_NO_ADDRESS_FOR_NAME
|
||||
: ENS_NOT_FOUND_ON_NETWORK;
|
||||
} else if (error.message === 'Illegal character for ENS.') {
|
||||
state.error = ENS_ILLEGAL_CHARACTER;
|
||||
} else {
|
||||
log.error(error);
|
||||
state.error = ENS_UNKNOWN_ERROR;
|
||||
}
|
||||
} else if (address) {
|
||||
if (address === BURN_ADDRESS) {
|
||||
state.error = ENS_NO_ADDRESS_FOR_NAME;
|
||||
} else if (address === ZERO_X_ERROR_ADDRESS) {
|
||||
state.error = ENS_REGISTRATION_ERROR;
|
||||
} else {
|
||||
state.resolution = address;
|
||||
}
|
||||
if (isValidDomainName(address) && isConfusing(address)) {
|
||||
state.warning = CONFUSING_ENS_ERROR;
|
||||
}
|
||||
} else {
|
||||
log.error(error);
|
||||
state.error = ENS_UNKNOWN_ERROR;
|
||||
}
|
||||
} else if (address) {
|
||||
if (address === BURN_ADDRESS) {
|
||||
state.error = ENS_NO_ADDRESS_FOR_NAME;
|
||||
} else if (address === ZERO_X_ERROR_ADDRESS) {
|
||||
state.error = ENS_REGISTRATION_ERROR;
|
||||
} else {
|
||||
state.resolution = address;
|
||||
}
|
||||
if (isValidDomainName(address) && isConfusing(address)) {
|
||||
state.warning = CONFUSING_ENS_ERROR;
|
||||
}
|
||||
} else {
|
||||
state.error = ENS_NO_ADDRESS_FOR_NAME;
|
||||
}
|
||||
},
|
||||
enableEnsLookup: (state, action) => {
|
||||
enableDomainLookup: (state, action) => {
|
||||
state.stage = 'INITIALIZED';
|
||||
state.error = null;
|
||||
state.resolution = null;
|
||||
state.warning = null;
|
||||
state.network = action.payload;
|
||||
},
|
||||
disableEnsLookup: (state) => {
|
||||
disableDomainLookup: (state) => {
|
||||
state.stage = 'NO_NETWORK_SUPPORT';
|
||||
state.error = null;
|
||||
state.warning = null;
|
||||
@ -105,7 +111,7 @@ const slice = createSlice({
|
||||
state.warning = null;
|
||||
state.error = ENS_NOT_SUPPORTED_ON_NETWORK;
|
||||
},
|
||||
resetEnsResolution: (state) => {
|
||||
resetDomainResolution: (state) => {
|
||||
state.resolution = null;
|
||||
state.warning = null;
|
||||
state.error = null;
|
||||
@ -125,15 +131,15 @@ const { reducer, actions } = slice;
|
||||
export default reducer;
|
||||
|
||||
const {
|
||||
disableEnsLookup,
|
||||
ensLookup,
|
||||
enableEnsLookup,
|
||||
disableDomainLookup,
|
||||
domainLookup,
|
||||
enableDomainLookup,
|
||||
ensNotSupported,
|
||||
resetEnsResolution,
|
||||
resetDomainResolution,
|
||||
} = actions;
|
||||
export { resetEnsResolution };
|
||||
export { resetDomainResolution };
|
||||
|
||||
export function initializeEnsSlice() {
|
||||
export function initializeDomainSlice() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const chainId = getCurrentChainId(state);
|
||||
@ -150,69 +156,65 @@ export function initializeEnsSlice() {
|
||||
ensAddress,
|
||||
},
|
||||
);
|
||||
dispatch(enableEnsLookup(network));
|
||||
dispatch(enableDomainLookup(network));
|
||||
} else {
|
||||
web3Provider = null;
|
||||
dispatch(disableEnsLookup());
|
||||
dispatch(disableDomainLookup());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function lookupEnsName(ensName) {
|
||||
export function lookupEnsName(domainName) {
|
||||
return async (dispatch, getState) => {
|
||||
const trimmedEnsName = ensName.trim();
|
||||
const trimmedDomainName = domainName.trim();
|
||||
let state = getState();
|
||||
if (state[name].stage === 'UNINITIALIZED') {
|
||||
await dispatch(initializeEnsSlice());
|
||||
await dispatch(initializeDomainSlice());
|
||||
}
|
||||
state = getState();
|
||||
if (
|
||||
state[name].stage === 'NO_NETWORK_SUPPORT' &&
|
||||
!(
|
||||
isBurnAddress(trimmedEnsName) === false &&
|
||||
isValidHexAddress(trimmedEnsName, { mixedCaseUseChecksum: true })
|
||||
isBurnAddress(trimmedDomainName) === false &&
|
||||
isValidHexAddress(trimmedDomainName, { mixedCaseUseChecksum: true })
|
||||
) &&
|
||||
!isHexString(trimmedEnsName)
|
||||
!isHexString(trimmedDomainName)
|
||||
) {
|
||||
await dispatch(ensNotSupported());
|
||||
} else {
|
||||
log.info(`ENS attempting to resolve name: ${trimmedEnsName}`);
|
||||
log.info(`ENS attempting to resolve name: ${trimmedDomainName}`);
|
||||
let address;
|
||||
let error;
|
||||
try {
|
||||
// the writable property on the 'provider' object on the 'web3Provider' flips to false when stale
|
||||
// This helps handle the case where the provider is becomes unresponsive if/when, in MV3, the service worker dies after the ENS slice is instantiated
|
||||
const isProviderActive = web3Provider.provider?.writable;
|
||||
if (!isProviderActive) {
|
||||
await dispatch(initializeEnsSlice());
|
||||
}
|
||||
address = await web3Provider.resolveName(trimmedEnsName);
|
||||
address = await web3Provider.resolveName(trimmedDomainName);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
const chainId = getCurrentChainId(state);
|
||||
const network = CHAIN_ID_TO_NETWORK_ID_MAP[chainId];
|
||||
|
||||
await dispatch(
|
||||
ensLookup({
|
||||
ensName: trimmedEnsName,
|
||||
domainLookup({
|
||||
address,
|
||||
error,
|
||||
chainId,
|
||||
network,
|
||||
domainType: ENS,
|
||||
domainName: trimmedDomainName,
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getEnsResolution(state) {
|
||||
export function getDomainResolution(state) {
|
||||
return state[name].resolution;
|
||||
}
|
||||
|
||||
export function getEnsError(state) {
|
||||
export function getDomainError(state) {
|
||||
return state[name].error;
|
||||
}
|
||||
|
||||
export function getEnsWarning(state) {
|
||||
export function getDomainWarning(state) {
|
||||
return state[name].warning;
|
||||
}
|
@ -3,7 +3,7 @@ import { ALERT_TYPES } from '../../shared/constants/alerts';
|
||||
import metamaskReducer from './metamask/metamask';
|
||||
import localeMessagesReducer from './locale/locale';
|
||||
import sendReducer from './send/send';
|
||||
import ensReducer from './ens';
|
||||
import domainReducer from './domains';
|
||||
import appStateReducer from './app/app';
|
||||
import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck';
|
||||
import gasReducer from './gas/gas.duck';
|
||||
@ -17,7 +17,7 @@ export default combineReducers({
|
||||
activeTab: (s) => (s === undefined ? null : s),
|
||||
metamask: metamaskReducer,
|
||||
appState: appStateReducer,
|
||||
ENS: ensReducer,
|
||||
DNS: domainReducer,
|
||||
history: historyReducer,
|
||||
send: sendReducer,
|
||||
confirmTransaction: confirmTransactionReducer,
|
||||
|
@ -82,7 +82,7 @@ import {
|
||||
getUnapprovedTxs,
|
||||
} from '../metamask/metamask';
|
||||
|
||||
import { resetEnsResolution } from '../ens';
|
||||
import { resetDomainResolution } from '../domains';
|
||||
import {
|
||||
isBurnAddress,
|
||||
isValidHexAddress,
|
||||
@ -2199,7 +2199,7 @@ export function resetRecipientInput() {
|
||||
await dispatch(addHistoryEntry(`sendFlow - user cleared recipient input`));
|
||||
await dispatch(updateRecipientUserInput(''));
|
||||
await dispatch(updateRecipient({ address: '', nickname: '' }));
|
||||
await dispatch(resetEnsResolution());
|
||||
await dispatch(resetDomainResolution());
|
||||
await dispatch(validateRecipientUserInput({ chainId }));
|
||||
};
|
||||
}
|
||||
|
@ -2108,7 +2108,7 @@ describe('Send Slice', () => {
|
||||
expect(actionResult[8].type).toStrictEqual(
|
||||
'send/computeEstimatedGasLimit/rejected',
|
||||
);
|
||||
expect(actionResult[9].type).toStrictEqual('ENS/resetEnsResolution');
|
||||
expect(actionResult[9].type).toStrictEqual('DNS/resetDomainResolution');
|
||||
expect(actionResult[10].type).toStrictEqual(
|
||||
'send/validateRecipientUserInput',
|
||||
);
|
||||
|
@ -16,9 +16,9 @@ export default class AddRecipient extends Component {
|
||||
ownedAccounts: PropTypes.array,
|
||||
addressBook: PropTypes.array,
|
||||
updateRecipient: PropTypes.func,
|
||||
ensResolution: PropTypes.string,
|
||||
ensError: PropTypes.string,
|
||||
ensWarning: PropTypes.string,
|
||||
domainResolution: PropTypes.string,
|
||||
domainError: PropTypes.string,
|
||||
domainWarning: PropTypes.string,
|
||||
addressBookEntryName: PropTypes.string,
|
||||
contacts: PropTypes.array,
|
||||
nonContacts: PropTypes.array,
|
||||
@ -102,7 +102,7 @@ export default class AddRecipient extends Component {
|
||||
|
||||
render() {
|
||||
const {
|
||||
ensResolution,
|
||||
domainResolution,
|
||||
recipient,
|
||||
userInput,
|
||||
addressBookEntryName,
|
||||
@ -117,9 +117,9 @@ export default class AddRecipient extends Component {
|
||||
recipient.nickname,
|
||||
'validated user input',
|
||||
);
|
||||
} else if (ensResolution && !recipient.error) {
|
||||
} else if (domainResolution && !recipient.error) {
|
||||
content = this.renderExplicitAddress(
|
||||
ensResolution,
|
||||
domainResolution,
|
||||
addressBookEntryName || userInput,
|
||||
'ENS resolution',
|
||||
);
|
||||
@ -233,19 +233,19 @@ export default class AddRecipient extends Component {
|
||||
}
|
||||
|
||||
renderDialogs() {
|
||||
const { ensError, recipient, ensWarning } = this.props;
|
||||
const { domainError, recipient, domainWarning } = this.props;
|
||||
const { t } = this.context;
|
||||
|
||||
if (ensError || (recipient.error && recipient.error !== 'required')) {
|
||||
if (domainError || (recipient.error && recipient.error !== 'required')) {
|
||||
return (
|
||||
<Dialog type="error" className="send__error-dialog">
|
||||
{t(ensError ?? recipient.error)}
|
||||
{t(domainError ?? recipient.error)}
|
||||
</Dialog>
|
||||
);
|
||||
} else if (ensWarning || recipient.warning) {
|
||||
} else if (domainWarning || recipient.warning) {
|
||||
return (
|
||||
<Dialog type="warning" className="send__error-dialog">
|
||||
{t(ensWarning ?? recipient.warning)}
|
||||
{t(domainWarning ?? recipient.warning)}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ describe('AddRecipient Component', () => {
|
||||
it('should render error when query has no results', () => {
|
||||
wrapper.setProps({
|
||||
addressBook: [],
|
||||
ensError: 'bad',
|
||||
domainError: 'bad',
|
||||
contacts: [],
|
||||
nonContacts: [],
|
||||
});
|
||||
@ -151,7 +151,7 @@ describe('AddRecipient Component', () => {
|
||||
it('should render error when query has ens does not resolve', () => {
|
||||
wrapper.setProps({
|
||||
addressBook: [],
|
||||
ensError: 'very bad',
|
||||
domainError: 'very bad',
|
||||
contacts: [],
|
||||
nonContacts: [],
|
||||
});
|
||||
@ -166,8 +166,8 @@ describe('AddRecipient Component', () => {
|
||||
it('should render error when ens resolved but ens error exists', () => {
|
||||
wrapper.setProps({
|
||||
addressBook: [],
|
||||
ensError: 'bad',
|
||||
ensResolution: '0x128',
|
||||
domainError: 'bad',
|
||||
domainResolution: '0x128',
|
||||
});
|
||||
|
||||
const dialog = wrapper.find(Dialog);
|
||||
|
@ -16,20 +16,20 @@ import {
|
||||
addHistoryEntry,
|
||||
} from '../../../../ducks/send';
|
||||
import {
|
||||
getEnsResolution,
|
||||
getEnsError,
|
||||
getEnsWarning,
|
||||
} from '../../../../ducks/ens';
|
||||
getDomainResolution,
|
||||
getDomainError,
|
||||
getDomainWarning,
|
||||
} from '../../../../ducks/domains';
|
||||
import AddRecipient from './add-recipient.component';
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddRecipient);
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const ensResolution = getEnsResolution(state);
|
||||
const domainResolution = getDomainResolution(state);
|
||||
|
||||
let addressBookEntryName = '';
|
||||
if (ensResolution) {
|
||||
const addressBookEntry = getAddressBookEntry(state, ensResolution) || {};
|
||||
if (domainResolution) {
|
||||
const addressBookEntry = getAddressBookEntry(state, domainResolution) || {};
|
||||
addressBookEntryName = addressBookEntry.name;
|
||||
}
|
||||
|
||||
@ -41,9 +41,9 @@ function mapStateToProps(state) {
|
||||
addressBook,
|
||||
addressBookEntryName,
|
||||
contacts: addressBook.filter(({ name }) => Boolean(name)),
|
||||
ensResolution,
|
||||
ensError: getEnsError(state),
|
||||
ensWarning: getEnsWarning(state),
|
||||
domainResolution,
|
||||
domainError: getDomainError(state),
|
||||
domainWarning: getDomainWarning(state),
|
||||
nonContacts: addressBook.filter(({ name }) => !name),
|
||||
ownedAccounts,
|
||||
isUsingMyAccountsForRecipientSearch:
|
||||
|
@ -18,10 +18,10 @@ jest.mock('../../../../selectors', () => ({
|
||||
],
|
||||
}));
|
||||
|
||||
jest.mock('../../../../ducks/ens', () => ({
|
||||
getEnsResolution: (s) => `mockSendEnsResolution:${s}`,
|
||||
getEnsError: (s) => `mockSendEnsResolutionError:${s}`,
|
||||
getEnsWarning: (s) => `mockSendEnsResolutionWarning:${s}`,
|
||||
jest.mock('../../../../ducks/domains', () => ({
|
||||
getDomainResolution: (s) => `mockSendDomainResolution:${s}`,
|
||||
getDomainError: (s) => `mockSendDomainResolutionError:${s}`,
|
||||
getDomainWarning: (s) => `mockSendDomainResolutionWarning:${s}`,
|
||||
useMyAccountsForRecipientSearch: (s) =>
|
||||
`useMyAccountsForRecipientSearch:${s}`,
|
||||
}));
|
||||
@ -49,9 +49,9 @@ describe('add-recipient container', () => {
|
||||
addressBook: [{ name: 'mockAddressBook:mockState' }],
|
||||
addressBookEntryName: undefined,
|
||||
contacts: [{ name: 'mockAddressBook:mockState' }],
|
||||
ensResolution: 'mockSendEnsResolution:mockState',
|
||||
ensError: 'mockSendEnsResolutionError:mockState',
|
||||
ensWarning: 'mockSendEnsResolutionWarning:mockState',
|
||||
domainResolution: 'mockSendDomainResolution:mockState',
|
||||
domainError: 'mockSendDomainResolutionError:mockState',
|
||||
domainWarning: 'mockSendDomainResolutionWarning:mockState',
|
||||
nonContacts: [],
|
||||
ownedAccounts: [
|
||||
{ name: 'account1:mockState' },
|
||||
|
@ -29,13 +29,13 @@ export default {
|
||||
updateRecipient: {
|
||||
action: 'updateRecipient',
|
||||
},
|
||||
ensResolution: {
|
||||
domainResolution: {
|
||||
control: 'text',
|
||||
},
|
||||
ensError: {
|
||||
domainError: {
|
||||
control: 'text',
|
||||
},
|
||||
ensWarning: {
|
||||
domainWarning: {
|
||||
control: 'text',
|
||||
},
|
||||
addressBookEntryName: {
|
||||
@ -96,8 +96,8 @@ export const ErrorStory = (args) => {
|
||||
};
|
||||
|
||||
ErrorStory.argTypes = {
|
||||
// ensError must be the key for a translation
|
||||
ensError: { type: 'text', defaultValue: 'loading' },
|
||||
// domainError must be the key for a translation
|
||||
domainError: { type: 'text', defaultValue: 'loading' },
|
||||
};
|
||||
|
||||
ErrorStory.storyName = 'Error';
|
||||
@ -115,8 +115,8 @@ export const WarningStory = (args) => {
|
||||
};
|
||||
|
||||
WarningStory.argTypes = {
|
||||
// ensWarning must be the key for a translation
|
||||
ensWarning: { type: 'text', defaultValue: 'loading' },
|
||||
// domainWarning must be the key for a translation
|
||||
domainWarning: { type: 'text', defaultValue: 'loading' },
|
||||
};
|
||||
|
||||
WarningStory.storyName = 'Warning';
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
isValidHexAddress,
|
||||
} from '../../../../../shared/modules/hexstring-utils';
|
||||
|
||||
export default class EnsInput extends Component {
|
||||
export default class DomainInput extends Component {
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
metricsEvent: PropTypes.func,
|
||||
@ -27,12 +27,12 @@ export default class EnsInput extends Component {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
lookupEnsName: PropTypes.func.isRequired,
|
||||
initializeEnsSlice: PropTypes.func.isRequired,
|
||||
resetEnsResolution: PropTypes.func.isRequired,
|
||||
initializeDomainSlice: PropTypes.func.isRequired,
|
||||
resetDomainResolution: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.initializeEnsSlice();
|
||||
this.props.initializeDomainSlice();
|
||||
}
|
||||
|
||||
onPaste = (event) => {
|
||||
@ -56,7 +56,7 @@ export default class EnsInput extends Component {
|
||||
internalSearch,
|
||||
onChange,
|
||||
lookupEnsName,
|
||||
resetEnsResolution,
|
||||
resetDomainResolution,
|
||||
} = this.props;
|
||||
const input = value.trim();
|
||||
|
||||
@ -69,7 +69,7 @@ export default class EnsInput extends Component {
|
||||
if (isValidDomainName(input)) {
|
||||
lookupEnsName(input);
|
||||
} else {
|
||||
resetEnsResolution();
|
||||
resetDomainResolution();
|
||||
if (
|
||||
onValidAddressTyped &&
|
||||
!isBurnAddress(input) &&
|
@ -0,0 +1,24 @@
|
||||
import { debounce } from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
lookupEnsName,
|
||||
initializeDomainSlice,
|
||||
resetDomainResolution,
|
||||
} from '../../../../ducks/domains';
|
||||
import DomainInput from './domain-input.component';
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
lookupEnsName: debounce(
|
||||
(domainName) => dispatch(lookupEnsName(domainName)),
|
||||
150,
|
||||
),
|
||||
initializeDomainSlice: () => dispatch(initializeDomainSlice()),
|
||||
resetDomainResolution: debounce(
|
||||
() => dispatch(resetDomainResolution()),
|
||||
300,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(DomainInput);
|
1
ui/pages/send/send-content/add-recipient/domain-input.js
Normal file
1
ui/pages/send/send-content/add-recipient/domain-input.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './domain-input.container';
|
@ -1,18 +0,0 @@
|
||||
import { debounce } from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
lookupEnsName,
|
||||
initializeEnsSlice,
|
||||
resetEnsResolution,
|
||||
} from '../../../../ducks/ens';
|
||||
import EnsInput from './ens-input.component';
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
lookupEnsName: debounce((ensName) => dispatch(lookupEnsName(ensName)), 150),
|
||||
initializeEnsSlice: () => dispatch(initializeEnsSlice()),
|
||||
resetEnsResolution: debounce(() => dispatch(resetEnsResolution()), 300),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(EnsInput);
|
@ -1 +0,0 @@
|
||||
export { default } from './ens-input.container';
|
@ -25,7 +25,7 @@ import SendHeader from './send-header';
|
||||
import AddRecipient from './send-content/add-recipient';
|
||||
import SendContent from './send-content';
|
||||
import SendFooter from './send-footer';
|
||||
import EnsInput from './send-content/add-recipient/ens-input';
|
||||
import DomainInput from './send-content/add-recipient/domain-input';
|
||||
|
||||
const sendSliceIsCustomPriceExcessive = (state) =>
|
||||
isCustomPriceExcessive(state, true);
|
||||
@ -112,7 +112,7 @@ export default function SendTransactionScreen() {
|
||||
return (
|
||||
<div className="page-container">
|
||||
<SendHeader history={history} />
|
||||
<EnsInput
|
||||
<DomainInput
|
||||
userInput={userInput}
|
||||
className="send__to-row"
|
||||
onChange={(address) => dispatch(updateRecipientUserInput(address))}
|
||||
|
@ -3,7 +3,7 @@ import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { SEND_STAGES, startNewDraftTransaction } from '../../ducks/send';
|
||||
import { ensInitialState } from '../../ducks/ens';
|
||||
import { domainInitialState } from '../../ducks/domains';
|
||||
import { renderWithProvider } from '../../../test/jest';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../shared/constants/gas';
|
||||
@ -54,7 +54,7 @@ jest.mock('ethers', () => {
|
||||
});
|
||||
const baseStore = {
|
||||
send: INITIAL_SEND_STATE_FOR_EXISTING_DRAFT,
|
||||
ENS: ensInitialState,
|
||||
DNS: domainInitialState,
|
||||
gas: {
|
||||
customData: { limit: null, price: null },
|
||||
},
|
||||
@ -132,7 +132,7 @@ describe('Send Page', () => {
|
||||
expect(actions).toStrictEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'ENS/enableEnsLookup',
|
||||
type: 'DNS/enableDomainLookup',
|
||||
}),
|
||||
]),
|
||||
);
|
||||
@ -146,7 +146,7 @@ describe('Send Page', () => {
|
||||
expect(actions).toStrictEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
type: 'ENS/enableEnsLookup',
|
||||
type: 'DNS/enableDomainLookup',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
type: 'UI_MODAL_OPEN',
|
||||
@ -165,7 +165,7 @@ describe('Send Page', () => {
|
||||
expect(getByText('Send to')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the EnsInput field', () => {
|
||||
it('should render the DomainInput field', () => {
|
||||
const store = configureMockStore(middleware)(baseStore);
|
||||
const { getByPlaceholderText } = renderWithProvider(<Send />, store);
|
||||
expect(
|
||||
@ -209,7 +209,7 @@ describe('Send Page', () => {
|
||||
expect(getByText('Send')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the EnsInput field', () => {
|
||||
it('should render the DomainInput field', () => {
|
||||
const store = configureMockStore(middleware)(baseStore);
|
||||
const { getByPlaceholderText } = renderWithProvider(<Send />, store);
|
||||
expect(
|
||||
|
@ -5,7 +5,7 @@ import Identicon from '../../../../components/ui/identicon';
|
||||
import TextField from '../../../../components/ui/text-field';
|
||||
import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes';
|
||||
import { isValidDomainName } from '../../../../helpers/utils/util';
|
||||
import EnsInput from '../../../send/send-content/add-recipient/ens-input';
|
||||
import DomainInput from '../../../send/send-content/add-recipient/domain-input';
|
||||
import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer';
|
||||
import {
|
||||
isBurnAddress,
|
||||
@ -25,9 +25,9 @@ export default class AddContact extends PureComponent {
|
||||
qrCodeData:
|
||||
PropTypes.object /* eslint-disable-line react/no-unused-prop-types */,
|
||||
qrCodeDetected: PropTypes.func,
|
||||
ensResolution: PropTypes.string,
|
||||
ensError: PropTypes.string,
|
||||
resetEnsResolution: PropTypes.func,
|
||||
domainResolution: PropTypes.string,
|
||||
domainError: PropTypes.string,
|
||||
resetDomainResolution: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
@ -45,10 +45,10 @@ export default class AddContact extends PureComponent {
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.qrCodeData) {
|
||||
if (nextProps.qrCodeData.type === 'address') {
|
||||
const { ensResolution } = this.props;
|
||||
const { domainResolution } = this.props;
|
||||
const scannedAddress =
|
||||
nextProps.qrCodeData.values.address.toLowerCase();
|
||||
const currentAddress = ensResolution || this.state.ethAddress;
|
||||
const currentAddress = domainResolution || this.state.ethAddress;
|
||||
if (currentAddress.toLowerCase() !== scannedAddress) {
|
||||
this.setState({ input: scannedAddress });
|
||||
this.validate(scannedAddress);
|
||||
@ -79,7 +79,7 @@ export default class AddContact extends PureComponent {
|
||||
|
||||
renderInput() {
|
||||
return (
|
||||
<EnsInput
|
||||
<DomainInput
|
||||
scanQrCode={(_) => {
|
||||
this.props.scanQrCode();
|
||||
}}
|
||||
@ -89,7 +89,7 @@ export default class AddContact extends PureComponent {
|
||||
this.validate(text);
|
||||
}}
|
||||
onReset={() => {
|
||||
this.props.resetEnsResolution();
|
||||
this.props.resetDomainResolution();
|
||||
this.setState({ ethAddress: '', input: '' });
|
||||
}}
|
||||
userInput={this.state.input}
|
||||
@ -99,17 +99,18 @@ export default class AddContact extends PureComponent {
|
||||
|
||||
render() {
|
||||
const { t } = this.context;
|
||||
const { history, addToAddressBook, ensError, ensResolution } = this.props;
|
||||
const { history, addToAddressBook, domainError, domainResolution } =
|
||||
this.props;
|
||||
|
||||
const errorToRender = ensError || this.state.error;
|
||||
const errorToRender = domainError || this.state.error;
|
||||
|
||||
return (
|
||||
<div className="settings-page__content-row address-book__add-contact">
|
||||
{ensResolution && (
|
||||
{domainResolution && (
|
||||
<div className="address-book__view-contact__group">
|
||||
<Identicon address={ensResolution} diameter={60} />
|
||||
<Identicon address={domainResolution} diameter={60} />
|
||||
<div className="address-book__view-contact__group__value">
|
||||
{ensResolution}
|
||||
{domainResolution}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -145,7 +146,7 @@ export default class AddContact extends PureComponent {
|
||||
disabled={Boolean(this.state.error)}
|
||||
onSubmit={async () => {
|
||||
await addToAddressBook(
|
||||
ensResolution || this.state.ethAddress,
|
||||
domainResolution || this.state.ethAddress,
|
||||
this.state.newName,
|
||||
);
|
||||
history.push(CONTACT_LIST_ROUTE);
|
||||
|
@ -8,17 +8,17 @@ import {
|
||||
} from '../../../../store/actions';
|
||||
import { getQrCodeData } from '../../../../ducks/app/app';
|
||||
import {
|
||||
getEnsError,
|
||||
getEnsResolution,
|
||||
resetEnsResolution,
|
||||
} from '../../../../ducks/ens';
|
||||
getDomainError,
|
||||
getDomainResolution,
|
||||
resetDomainResolution,
|
||||
} from '../../../../ducks/domains';
|
||||
import AddContact from './add-contact.component';
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
qrCodeData: getQrCodeData(state),
|
||||
ensError: getEnsError(state),
|
||||
ensResolution: getEnsResolution(state),
|
||||
domainError: getDomainError(state),
|
||||
domainResolution: getDomainResolution(state),
|
||||
};
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
dispatch(addToAddressBook(recipient, nickname)),
|
||||
scanQrCode: () => dispatch(showQrScanner()),
|
||||
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)),
|
||||
resetEnsResolution: () => dispatch(resetEnsResolution()),
|
||||
resetDomainResolution: () => dispatch(resetDomainResolution()),
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user