2021-06-10 19:53:15 +02:00
|
|
|
import log from 'loglevel';
|
|
|
|
import { estimateGas } from '../../store/actions';
|
|
|
|
import { setCustomGasLimit } from '../gas/gas.duck';
|
|
|
|
import {
|
|
|
|
estimateGasForSend,
|
|
|
|
calcTokenBalance,
|
|
|
|
} from '../../pages/send/send.utils';
|
|
|
|
|
2018-04-07 00:29:51 +02:00
|
|
|
// Actions
|
2021-02-04 19:15:23 +01:00
|
|
|
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN';
|
|
|
|
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN';
|
|
|
|
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS';
|
|
|
|
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE';
|
|
|
|
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP';
|
|
|
|
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP';
|
2021-06-10 19:53:15 +02:00
|
|
|
const UPDATE_GAS_LIMIT = 'UPDATE_GAS_LIMIT';
|
|
|
|
const UPDATE_GAS_PRICE = 'UPDATE_GAS_PRICE';
|
|
|
|
const UPDATE_GAS_TOTAL = 'UPDATE_GAS_TOTAL';
|
|
|
|
const UPDATE_SEND_HEX_DATA = 'UPDATE_SEND_HEX_DATA';
|
|
|
|
const UPDATE_SEND_TOKEN_BALANCE = 'UPDATE_SEND_TOKEN_BALANCE';
|
|
|
|
const UPDATE_SEND_TO = 'UPDATE_SEND_TO';
|
|
|
|
const UPDATE_SEND_AMOUNT = 'UPDATE_SEND_AMOUNT';
|
|
|
|
const UPDATE_MAX_MODE = 'UPDATE_MAX_MODE';
|
|
|
|
const UPDATE_SEND = 'UPDATE_SEND';
|
|
|
|
const UPDATE_SEND_TOKEN = 'UPDATE_SEND_TOKEN';
|
|
|
|
const CLEAR_SEND = 'CLEAR_SEND';
|
|
|
|
const GAS_LOADING_STARTED = 'GAS_LOADING_STARTED';
|
|
|
|
const GAS_LOADING_FINISHED = 'GAS_LOADING_FINISHED';
|
|
|
|
const UPDATE_SEND_ENS_RESOLUTION = 'UPDATE_SEND_ENS_RESOLUTION';
|
|
|
|
const UPDATE_SEND_ENS_RESOLUTION_ERROR = 'UPDATE_SEND_ENS_RESOLUTION_ERROR';
|
2018-04-07 00:29:51 +02:00
|
|
|
|
|
|
|
const initState = {
|
|
|
|
toDropdownOpen: false,
|
2018-09-13 14:35:17 +02:00
|
|
|
gasButtonGroupShown: true,
|
2018-04-26 18:38:38 +02:00
|
|
|
errors: {},
|
2021-06-10 19:53:15 +02:00
|
|
|
gasLimit: null,
|
|
|
|
gasPrice: null,
|
|
|
|
gasTotal: null,
|
|
|
|
tokenBalance: '0x0',
|
|
|
|
from: '',
|
|
|
|
to: '',
|
|
|
|
amount: '0',
|
|
|
|
memo: '',
|
|
|
|
maxModeOn: false,
|
|
|
|
editingTransactionId: null,
|
|
|
|
toNickname: '',
|
|
|
|
ensResolution: null,
|
|
|
|
ensResolutionError: '',
|
|
|
|
gasIsLoading: false,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-04-07 00:29:51 +02:00
|
|
|
|
|
|
|
// Reducer
|
2020-11-03 00:41:28 +01:00
|
|
|
export default function reducer(state = initState, action) {
|
2018-04-07 00:29:51 +02:00
|
|
|
switch (action.type) {
|
|
|
|
case OPEN_TO_DROPDOWN:
|
2020-01-13 17:29:21 +01:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-04-07 00:29:51 +02:00
|
|
|
toDropdownOpen: true,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-04-07 00:29:51 +02:00
|
|
|
case CLOSE_TO_DROPDOWN:
|
2020-01-13 17:29:21 +01:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-04-07 00:29:51 +02:00
|
|
|
toDropdownOpen: false,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-04-27 21:03:00 +02:00
|
|
|
case UPDATE_SEND_ERRORS:
|
2020-01-13 17:29:21 +01:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-04-27 21:03:00 +02:00
|
|
|
errors: {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state.errors,
|
2018-04-27 21:03:00 +02:00
|
|
|
...action.value,
|
|
|
|
},
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-09-13 14:35:17 +02:00
|
|
|
case SHOW_GAS_BUTTON_GROUP:
|
2020-01-13 17:29:21 +01:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-09-13 14:35:17 +02:00
|
|
|
gasButtonGroupShown: true,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-09-13 14:35:17 +02:00
|
|
|
case HIDE_GAS_BUTTON_GROUP:
|
2020-01-13 17:29:21 +01:00
|
|
|
return {
|
2020-02-06 17:38:14 +01:00
|
|
|
...state,
|
2018-09-13 14:35:17 +02:00
|
|
|
gasButtonGroupShown: false,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2021-06-10 19:53:15 +02:00
|
|
|
case UPDATE_GAS_LIMIT:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasLimit: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_GAS_PRICE:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasPrice: action.value,
|
|
|
|
};
|
2018-06-29 19:19:40 +02:00
|
|
|
case RESET_SEND_STATE:
|
2021-02-04 19:15:23 +01:00
|
|
|
return { ...initState };
|
2021-06-10 19:53:15 +02:00
|
|
|
case UPDATE_GAS_TOTAL:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasTotal: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_SEND_TOKEN_BALANCE:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
tokenBalance: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_SEND_HEX_DATA:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
data: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_SEND_TO:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
to: action.value.to,
|
|
|
|
toNickname: action.value.nickname,
|
|
|
|
};
|
|
|
|
case UPDATE_SEND_AMOUNT:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
amount: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_MAX_MODE:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
maxModeOn: action.value,
|
|
|
|
};
|
|
|
|
case UPDATE_SEND:
|
|
|
|
return Object.assign(state, action.value);
|
|
|
|
case UPDATE_SEND_TOKEN: {
|
|
|
|
const newSend = {
|
|
|
|
...state,
|
|
|
|
token: action.value,
|
|
|
|
};
|
|
|
|
// erase token-related state when switching back to native currency
|
|
|
|
if (newSend.editingTransactionId && !newSend.token) {
|
|
|
|
const unapprovedTx =
|
|
|
|
newSend?.unapprovedTxs?.[newSend.editingTransactionId] || {};
|
|
|
|
const txParams = unapprovedTx.txParams || {};
|
|
|
|
Object.assign(newSend, {
|
|
|
|
tokenBalance: null,
|
|
|
|
balance: '0',
|
|
|
|
from: unapprovedTx.from || '',
|
|
|
|
unapprovedTxs: {
|
|
|
|
...newSend.unapprovedTxs,
|
|
|
|
[newSend.editingTransactionId]: {
|
|
|
|
...unapprovedTx,
|
|
|
|
txParams: {
|
|
|
|
...txParams,
|
|
|
|
data: '',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return Object.assign(state, newSend);
|
|
|
|
}
|
|
|
|
case UPDATE_SEND_ENS_RESOLUTION:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
ensResolution: action.payload,
|
|
|
|
ensResolutionError: '',
|
|
|
|
};
|
|
|
|
case UPDATE_SEND_ENS_RESOLUTION_ERROR:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
ensResolution: null,
|
|
|
|
ensResolutionError: action.payload,
|
|
|
|
};
|
|
|
|
case CLEAR_SEND:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasLimit: null,
|
|
|
|
gasPrice: null,
|
|
|
|
gasTotal: null,
|
|
|
|
tokenBalance: null,
|
|
|
|
from: '',
|
|
|
|
to: '',
|
|
|
|
amount: '0x0',
|
|
|
|
memo: '',
|
|
|
|
errors: {},
|
|
|
|
maxModeOn: false,
|
|
|
|
editingTransactionId: null,
|
|
|
|
toNickname: '',
|
|
|
|
};
|
|
|
|
case GAS_LOADING_STARTED:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasIsLoading: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
case GAS_LOADING_FINISHED:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
gasIsLoading: false,
|
|
|
|
};
|
2018-04-07 00:29:51 +02:00
|
|
|
default:
|
2021-02-04 19:15:23 +01:00
|
|
|
return state;
|
2018-04-07 00:29:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Action Creators
|
2020-11-03 00:41:28 +01:00
|
|
|
export function openToDropdown() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: OPEN_TO_DROPDOWN };
|
2018-04-07 00:29:51 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function closeToDropdown() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: CLOSE_TO_DROPDOWN };
|
2018-04-27 02:38:14 +02:00
|
|
|
}
|
2018-04-27 21:03:00 +02:00
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function showGasButtonGroup() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: SHOW_GAS_BUTTON_GROUP };
|
2018-09-13 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function hideGasButtonGroup() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: HIDE_GAS_BUTTON_GROUP };
|
2018-09-13 14:35:17 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function updateSendErrors(errorObject) {
|
2018-04-27 21:03:00 +02:00
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_ERRORS,
|
|
|
|
value: errorObject,
|
2021-02-04 19:15:23 +01:00
|
|
|
};
|
2018-04-27 21:03:00 +02:00
|
|
|
}
|
2018-06-29 19:19:40 +02:00
|
|
|
|
2020-11-03 00:41:28 +01:00
|
|
|
export function resetSendState() {
|
2021-02-04 19:15:23 +01:00
|
|
|
return { type: RESET_SEND_STATE };
|
2018-06-29 19:19:40 +02:00
|
|
|
}
|
2021-06-10 19:53:15 +02:00
|
|
|
|
|
|
|
export function setGasLimit(gasLimit) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_GAS_LIMIT,
|
|
|
|
value: gasLimit,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setGasPrice(gasPrice) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_GAS_PRICE,
|
|
|
|
value: gasPrice,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setGasTotal(gasTotal) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_GAS_TOTAL,
|
|
|
|
value: gasTotal,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateGasData({
|
|
|
|
gasPrice,
|
|
|
|
blockGasLimit,
|
|
|
|
selectedAddress,
|
|
|
|
sendToken,
|
|
|
|
to,
|
|
|
|
value,
|
|
|
|
data,
|
|
|
|
}) {
|
|
|
|
return (dispatch) => {
|
|
|
|
dispatch(gasLoadingStarted());
|
|
|
|
return estimateGasForSend({
|
|
|
|
estimateGasMethod: estimateGas,
|
|
|
|
blockGasLimit,
|
|
|
|
selectedAddress,
|
|
|
|
sendToken,
|
|
|
|
to,
|
|
|
|
value,
|
|
|
|
estimateGasPrice: gasPrice,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
.then((gas) => {
|
|
|
|
dispatch(setGasLimit(gas));
|
|
|
|
dispatch(setCustomGasLimit(gas));
|
|
|
|
dispatch(updateSendErrors({ gasLoadingError: null }));
|
|
|
|
dispatch(gasLoadingFinished());
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
log.error(err);
|
|
|
|
dispatch(updateSendErrors({ gasLoadingError: 'gasLoadingError' }));
|
|
|
|
dispatch(gasLoadingFinished());
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function gasLoadingStarted() {
|
|
|
|
return {
|
|
|
|
type: GAS_LOADING_STARTED,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function gasLoadingFinished() {
|
|
|
|
return {
|
|
|
|
type: GAS_LOADING_FINISHED,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendTokenBalance({ sendToken, tokenContract, address }) {
|
|
|
|
return (dispatch) => {
|
|
|
|
const tokenBalancePromise = tokenContract
|
|
|
|
? tokenContract.balanceOf(address)
|
|
|
|
: Promise.resolve();
|
|
|
|
return tokenBalancePromise
|
|
|
|
.then((usersToken) => {
|
|
|
|
if (usersToken) {
|
|
|
|
const newTokenBalance = calcTokenBalance({ sendToken, usersToken });
|
|
|
|
dispatch(setSendTokenBalance(newTokenBalance));
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
log.error(err);
|
|
|
|
updateSendErrors({ tokenBalance: 'tokenBalanceError' });
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setSendTokenBalance(tokenBalance) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_TOKEN_BALANCE,
|
|
|
|
value: tokenBalance,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendHexData(value) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_HEX_DATA,
|
|
|
|
value,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendTo(to, nickname = '') {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_TO,
|
|
|
|
value: { to, nickname },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendAmount(amount) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_AMOUNT,
|
|
|
|
value: amount,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setMaxModeTo(bool) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_MAX_MODE,
|
|
|
|
value: bool,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSend(newSend) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND,
|
|
|
|
value: newSend,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendToken(token) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_TOKEN,
|
|
|
|
value: token,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function clearSend() {
|
|
|
|
return {
|
|
|
|
type: CLEAR_SEND,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendEnsResolution(ensResolution) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_ENS_RESOLUTION,
|
|
|
|
payload: ensResolution,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSendEnsResolutionError(errorMessage) {
|
|
|
|
return {
|
|
|
|
type: UPDATE_SEND_ENS_RESOLUTION_ERROR,
|
|
|
|
payload: errorMessage,
|
|
|
|
};
|
|
|
|
}
|