1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-25 20:02:58 +01:00
metamask-extension/ui/ducks/domains.js
amerkadicE dd09245ff6
Fix/use etherjs specific imports (#15461)
* replace ethers with submodules

Co-authored-by: Alex <adonesky@gmail.com>
2023-01-24 08:10:36 -06:00

218 lines
5.8 KiB
JavaScript

import { createSlice } from '@reduxjs/toolkit';
import log from 'loglevel';
import networkMap from 'ethereum-ens-network-map';
import { isConfusing } from 'unicode-confusables';
import { isHexString } from 'ethereumjs-util';
import { Web3Provider } from '@ethersproject/providers';
import { getCurrentChainId } from '../selectors';
import {
CHAIN_ID_TO_NETWORK_ID_MAP,
NETWORK_IDS,
NETWORK_ID_TO_ETHERS_NETWORK_NAME_MAP,
} from '../../shared/constants/network';
import {
CONFUSING_ENS_ERROR,
ENS_ILLEGAL_CHARACTER,
ENS_NOT_FOUND_ON_NETWORK,
ENS_NOT_SUPPORTED_ON_NETWORK,
ENS_NO_ADDRESS_FOR_NAME,
ENS_REGISTRATION_ERROR,
ENS_UNKNOWN_ERROR,
} from '../pages/send/send.constants';
import { isValidDomainName } from '../helpers/utils/util';
import { CHAIN_CHANGED } from '../store/actionConstants';
import {
BURN_ADDRESS,
isBurnAddress,
isValidHexAddress,
} from '../../shared/modules/hexstring-utils';
// Local Constants
const ZERO_X_ERROR_ADDRESS = '0x';
const ENS = 'ENS';
const initialState = {
stage: 'UNINITIALIZED',
resolution: null,
error: null,
warning: null,
network: null,
domainType: null,
domainName: null,
};
export const domainInitialState = initialState;
const name = 'DNS';
let web3Provider = null;
const slice = createSlice({
name,
initialState,
reducers: {
domainLookup: (state, action) => {
// first clear out the previous state
state.resolution = null;
state.error = null;
state.warning = null;
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 {
state.error = ENS_NO_ADDRESS_FOR_NAME;
}
}
},
enableDomainLookup: (state, action) => {
state.stage = 'INITIALIZED';
state.error = null;
state.resolution = null;
state.warning = null;
state.network = action.payload;
},
disableDomainLookup: (state) => {
state.stage = 'NO_NETWORK_SUPPORT';
state.error = null;
state.warning = null;
state.resolution = null;
state.network = null;
},
ensNotSupported: (state) => {
state.resolution = null;
state.warning = null;
state.error = ENS_NOT_SUPPORTED_ON_NETWORK;
},
resetDomainResolution: (state) => {
state.resolution = null;
state.warning = null;
state.error = null;
},
},
extraReducers: (builder) => {
builder.addCase(CHAIN_CHANGED, (state, action) => {
if (action.payload !== state.currentChainId) {
state.stage = 'UNINITIALIZED';
web3Provider = null;
}
});
},
});
const { reducer, actions } = slice;
export default reducer;
const {
disableDomainLookup,
domainLookup,
enableDomainLookup,
ensNotSupported,
resetDomainResolution,
} = actions;
export { resetDomainResolution };
export function initializeDomainSlice() {
return (dispatch, getState) => {
const state = getState();
const chainId = getCurrentChainId(state);
const network = CHAIN_ID_TO_NETWORK_ID_MAP[chainId];
const networkName = NETWORK_ID_TO_ETHERS_NETWORK_NAME_MAP[network];
const ensAddress = networkMap[network];
const networkIsSupported = Boolean(ensAddress);
if (networkIsSupported) {
web3Provider = new Web3Provider(global.ethereumProvider, {
chainId: parseInt(network, 10),
name: networkName,
ensAddress,
});
dispatch(enableDomainLookup(network));
} else {
web3Provider = null;
dispatch(disableDomainLookup());
}
};
}
export function lookupEnsName(domainName) {
return async (dispatch, getState) => {
const trimmedDomainName = domainName.trim();
let state = getState();
if (state[name].stage === 'UNINITIALIZED') {
await dispatch(initializeDomainSlice());
}
state = getState();
if (
state[name].stage === 'NO_NETWORK_SUPPORT' &&
!(
isBurnAddress(trimmedDomainName) === false &&
isValidHexAddress(trimmedDomainName, { mixedCaseUseChecksum: true })
) &&
!isHexString(trimmedDomainName)
) {
await dispatch(ensNotSupported());
} else {
log.info(`ENS attempting to resolve name: ${trimmedDomainName}`);
let address;
let error;
try {
address = await web3Provider.resolveName(trimmedDomainName);
} catch (err) {
error = err;
}
const chainId = getCurrentChainId(state);
const network = CHAIN_ID_TO_NETWORK_ID_MAP[chainId];
await dispatch(
domainLookup({
address,
error,
chainId,
network,
domainType: ENS,
domainName: trimmedDomainName,
}),
);
}
};
}
export function getDomainResolution(state) {
return state[name].resolution;
}
export function getDomainError(state) {
return state[name].error;
}
export function getDomainWarning(state) {
return state[name].warning;
}