mirror of
https://github.com/trezor/trezor-wallet
synced 2025-01-03 21:00:55 +00:00
add fees to Ripple
This commit is contained in:
parent
025e7856cd
commit
be9cd4fef0
@ -1,7 +1,7 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import TrezorConnect from 'trezor-connect';
|
import TrezorConnect from 'trezor-connect';
|
||||||
// import * as BLOCKCHAIN from 'actions/constants/blockchain';
|
import * as BLOCKCHAIN from 'actions/constants/blockchain';
|
||||||
import * as PENDING from 'actions/constants/pendingTx';
|
import * as PENDING from 'actions/constants/pendingTx';
|
||||||
import * as AccountsActions from 'actions/AccountsActions';
|
import * as AccountsActions from 'actions/AccountsActions';
|
||||||
import { toDecimalAmount } from 'utils/formatUtils';
|
import { toDecimalAmount } from 'utils/formatUtils';
|
||||||
@ -11,6 +11,9 @@ import type {
|
|||||||
Dispatch,
|
Dispatch,
|
||||||
GetState,
|
GetState,
|
||||||
PromiseAction,
|
PromiseAction,
|
||||||
|
PayloadAction,
|
||||||
|
Network,
|
||||||
|
BlockchainFeeLevel,
|
||||||
} from 'flowtype';
|
} from 'flowtype';
|
||||||
|
|
||||||
const DECIMALS: number = 6;
|
const DECIMALS: number = 6;
|
||||||
@ -23,22 +26,40 @@ export const subscribe = (network: string): PromiseAction<void> => async (dispat
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get current known fee
|
||||||
|
// Use default values from appConfig.json if it wasn't downloaded from blockchain yet
|
||||||
|
// update them later, after onBlockMined event
|
||||||
|
export const getFeeLevels = (network: Network): PayloadAction<Array<BlockchainFeeLevel>> => (dispatch: Dispatch, getState: GetState): Array<BlockchainFeeLevel> => {
|
||||||
|
const blockchain = getState().blockchain.find(b => b.shortcut === network.shortcut);
|
||||||
|
if (!blockchain || blockchain.feeLevels.length < 1) {
|
||||||
|
return network.fee.levels.map(level => ({
|
||||||
|
name: level.name,
|
||||||
|
value: level.value,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return blockchain.feeLevels;
|
||||||
|
};
|
||||||
|
|
||||||
export const onBlockMined = (network: string): PromiseAction<void> => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
export const onBlockMined = (network: string): PromiseAction<void> => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||||
const blockchain = getState().blockchain.find(b => b.shortcut === network);
|
const blockchain = getState().blockchain.find(b => b.shortcut === network);
|
||||||
if (!blockchain) return;
|
if (!blockchain) return; // flowtype fallback
|
||||||
|
|
||||||
// const fee = await TrezorConnect.blockchainGetFee({
|
// if last update was more than 5 minutes ago
|
||||||
// coin: network,
|
const now = new Date().getTime();
|
||||||
// });
|
if (blockchain.feeTimestamp < now - 300000) {
|
||||||
// if (!fee.success) return;
|
const feeRequest = await TrezorConnect.blockchainEstimateFee({
|
||||||
|
coin: network,
|
||||||
|
});
|
||||||
|
if (feeRequest.success) {
|
||||||
|
dispatch({
|
||||||
|
type: BLOCKCHAIN.UPDATE_FEE,
|
||||||
|
shortcut: network,
|
||||||
|
feeLevels: feeRequest.payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if (fee.payload !== blockchain.fee) {
|
// TODO: check for blockchain rollbacks here!
|
||||||
// dispatch({
|
|
||||||
// type: BLOCKCHAIN.UPDATE_FEE,
|
|
||||||
// shortcut: network,
|
|
||||||
// fee: fee.payload,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
const accounts: Array<any> = getState().accounts.filter(a => a.network === network);
|
const accounts: Array<any> = getState().accounts.filter(a => a.network === network);
|
||||||
// console.warn('ACCOUNTS', accounts);
|
// console.warn('ACCOUNTS', accounts);
|
||||||
|
@ -16,9 +16,10 @@ import type {
|
|||||||
AsyncAction,
|
AsyncAction,
|
||||||
TrezorDevice,
|
TrezorDevice,
|
||||||
} from 'flowtype';
|
} from 'flowtype';
|
||||||
import type { State } from 'reducers/SendFormRippleReducer';
|
import type { State, FeeLevel } from 'reducers/SendFormRippleReducer';
|
||||||
import * as SessionStorageActions from '../SessionStorageActions';
|
import * as SessionStorageActions from '../SessionStorageActions';
|
||||||
|
|
||||||
|
import * as BlockchainActions from './BlockchainActions';
|
||||||
import * as ValidationActions from './SendFormValidationActions';
|
import * as ValidationActions from './SendFormValidationActions';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -43,14 +44,14 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction =
|
|||||||
// handle gasPrice update from backend
|
// handle gasPrice update from backend
|
||||||
// recalculate fee levels if needed
|
// recalculate fee levels if needed
|
||||||
if (action.type === BLOCKCHAIN.UPDATE_FEE) {
|
if (action.type === BLOCKCHAIN.UPDATE_FEE) {
|
||||||
dispatch(ValidationActions.onFeeUpdated(action.shortcut, action.fee));
|
dispatch(ValidationActions.onFeeUpdated(action.shortcut, action.feeLevels));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let shouldUpdate: boolean = false;
|
let shouldUpdate: boolean = false;
|
||||||
// check if "selectedAccount" reducer changed
|
// check if "selectedAccount" reducer changed
|
||||||
shouldUpdate = reducerUtils.observeChanges(prevState.selectedAccount, currentState.selectedAccount, {
|
shouldUpdate = reducerUtils.observeChanges(prevState.selectedAccount, currentState.selectedAccount, {
|
||||||
account: ['balance', 'nonce'],
|
account: ['balance', 'sequence'],
|
||||||
});
|
});
|
||||||
|
|
||||||
// check if "sendForm" reducer changed
|
// check if "sendForm" reducer changed
|
||||||
@ -79,7 +80,7 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
|
|||||||
network,
|
network,
|
||||||
} = getState().selectedAccount;
|
} = getState().selectedAccount;
|
||||||
|
|
||||||
if (!account || !network) return;
|
if (!account || account.networkType !== 'ripple' || !network) return;
|
||||||
|
|
||||||
const stateFromStorage = dispatch(SessionStorageActions.loadRippleDraftTransaction());
|
const stateFromStorage = dispatch(SessionStorageActions.loadRippleDraftTransaction());
|
||||||
if (stateFromStorage) {
|
if (stateFromStorage) {
|
||||||
@ -91,7 +92,8 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const feeLevels = dispatch(ValidationActions.getFeeLevels(network.symbol));
|
const blockchainFeeLevels = dispatch(BlockchainActions.getFeeLevels(network));
|
||||||
|
const feeLevels = dispatch(ValidationActions.getFeeLevels(blockchainFeeLevels));
|
||||||
const selectedFeeLevel = ValidationActions.getSelectedFeeLevel(feeLevels, initialState.selectedFeeLevel);
|
const selectedFeeLevel = ValidationActions.getSelectedFeeLevel(feeLevels, initialState.selectedFeeLevel);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -103,11 +105,20 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS
|
|||||||
networkSymbol: network.symbol,
|
networkSymbol: network.symbol,
|
||||||
feeLevels,
|
feeLevels,
|
||||||
selectedFeeLevel,
|
selectedFeeLevel,
|
||||||
|
fee: network.fee.defaultFee,
|
||||||
sequence: '1',
|
sequence: '1',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI from "advanced" button
|
||||||
|
*/
|
||||||
|
export const toggleAdvanced = (): Action => ({
|
||||||
|
type: SEND.TOGGLE_ADVANCED,
|
||||||
|
networkType: 'ripple',
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called from UI on "address" field change
|
* Called from UI on "address" field change
|
||||||
*/
|
*/
|
||||||
@ -160,6 +171,78 @@ export const onSetMax = (): ThunkAction => (dispatch: Dispatch, getState: GetSta
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI on "fee" selection change
|
||||||
|
*/
|
||||||
|
export const onFeeLevelChange = (feeLevel: FeeLevel): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
|
const state = getState().sendFormRipple;
|
||||||
|
|
||||||
|
const isCustom = feeLevel.value === 'Custom';
|
||||||
|
const advanced = isCustom ? true : state.advanced;
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: SEND.CHANGE,
|
||||||
|
networkType: 'ripple',
|
||||||
|
state: {
|
||||||
|
...state,
|
||||||
|
advanced,
|
||||||
|
selectedFeeLevel: feeLevel,
|
||||||
|
fee: isCustom ? state.selectedFeeLevel.fee : feeLevel.fee,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI from "update recommended fees" button
|
||||||
|
*/
|
||||||
|
export const updateFeeLevels = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
network,
|
||||||
|
} = getState().selectedAccount;
|
||||||
|
if (!account || !network) return;
|
||||||
|
|
||||||
|
const blockchainFeeLevels = dispatch(BlockchainActions.getFeeLevels(network));
|
||||||
|
const state: State = getState().sendFormRipple;
|
||||||
|
const feeLevels = dispatch(ValidationActions.getFeeLevels(blockchainFeeLevels, state.selectedFeeLevel));
|
||||||
|
const selectedFeeLevel = ValidationActions.getSelectedFeeLevel(feeLevels, state.selectedFeeLevel);
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: SEND.CHANGE,
|
||||||
|
networkType: 'ripple',
|
||||||
|
state: {
|
||||||
|
...state,
|
||||||
|
feeLevels,
|
||||||
|
selectedFeeLevel,
|
||||||
|
feeNeedsUpdate: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI on "advanced / fee" field change
|
||||||
|
*/
|
||||||
|
export const onFeeChange = (fee: string): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
|
const { network } = getState().selectedAccount;
|
||||||
|
if (!network) return;
|
||||||
|
const state: State = getState().sendFormRipple;
|
||||||
|
|
||||||
|
// switch to custom fee level
|
||||||
|
let newSelectedFeeLevel = state.selectedFeeLevel;
|
||||||
|
if (state.selectedFeeLevel.value !== 'Custom') newSelectedFeeLevel = state.feeLevels.find(f => f.value === 'Custom');
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: SEND.CHANGE,
|
||||||
|
networkType: 'ripple',
|
||||||
|
state: {
|
||||||
|
...state,
|
||||||
|
untouched: false,
|
||||||
|
touched: { ...state.touched, fee: true },
|
||||||
|
selectedFeeLevel: newSelectedFeeLevel,
|
||||||
|
fee,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called from UI from "send" button
|
* Called from UI from "send" button
|
||||||
@ -190,7 +273,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
|
|||||||
useEmptyPassphrase: selected.useEmptyPassphrase,
|
useEmptyPassphrase: selected.useEmptyPassphrase,
|
||||||
path: account.accountPath,
|
path: account.accountPath,
|
||||||
transaction: {
|
transaction: {
|
||||||
fee: blockchain.fee, // Fee must be in the range of 10 to 10,000 drops
|
fee: currentState.selectedFeeLevel.fee, // Fee must be in the range of 10 to 10,000 drops
|
||||||
flags: 0x80000000,
|
flags: 0x80000000,
|
||||||
sequence: account.sequence,
|
sequence: account.sequence,
|
||||||
payment: {
|
payment: {
|
||||||
@ -256,8 +339,12 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
toggleAdvanced,
|
||||||
onAddressChange,
|
onAddressChange,
|
||||||
onAmountChange,
|
onAmountChange,
|
||||||
onSetMax,
|
onSetMax,
|
||||||
|
onFeeLevelChange,
|
||||||
|
updateFeeLevels,
|
||||||
|
onFeeChange,
|
||||||
onSend,
|
onSend,
|
||||||
};
|
};
|
@ -9,11 +9,13 @@ import type {
|
|||||||
Dispatch,
|
Dispatch,
|
||||||
GetState,
|
GetState,
|
||||||
PayloadAction,
|
PayloadAction,
|
||||||
|
BlockchainFeeLevel,
|
||||||
} from 'flowtype';
|
} from 'flowtype';
|
||||||
import type { State, FeeLevel } from 'reducers/SendFormRippleReducer';
|
import type { State, FeeLevel } from 'reducers/SendFormRippleReducer';
|
||||||
|
|
||||||
import AddressValidator from 'wallet-address-validator';
|
import AddressValidator from 'wallet-address-validator';
|
||||||
// general regular expressions
|
// general regular expressions
|
||||||
|
const ABS_RE = new RegExp('^[0-9]+$');
|
||||||
const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)?|\\.[0-9]+)$');
|
const NUMBER_RE: RegExp = new RegExp('^(0|0\\.([0-9]+)?|[1-9][0-9]*\\.?([0-9]+)?|\\.[0-9]+)$');
|
||||||
const XRP_6_RE = new RegExp('^(0|0\\.([0-9]{0,6})?|[1-9][0-9]*\\.?([0-9]{0,6})?|\\.[0-9]{0,6})$');
|
const XRP_6_RE = new RegExp('^(0|0\\.([0-9]{0,6})?|[1-9][0-9]*\\.?([0-9]{0,6})?|\\.[0-9]{0,6})$');
|
||||||
|
|
||||||
@ -21,11 +23,10 @@ const XRP_6_RE = new RegExp('^(0|0\\.([0-9]{0,6})?|[1-9][0-9]*\\.?([0-9]{0,6})?|
|
|||||||
* Called from SendFormActions.observe
|
* Called from SendFormActions.observe
|
||||||
* Reaction for BLOCKCHAIN.FEE_UPDATED action
|
* Reaction for BLOCKCHAIN.FEE_UPDATED action
|
||||||
*/
|
*/
|
||||||
export const onFeeUpdated = (network: string, fee: string): PayloadAction<void> => (dispatch: Dispatch, getState: GetState): void => {
|
export const onFeeUpdated = (network: string, feeLevels: Array<BlockchainFeeLevel>): PayloadAction<void> => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
const state = getState().sendFormRipple;
|
const state = getState().sendFormRipple;
|
||||||
if (network === state.networkSymbol) return;
|
if (network === state.networkSymbol) return;
|
||||||
|
|
||||||
|
|
||||||
if (!state.untouched) {
|
if (!state.untouched) {
|
||||||
// if there is a transaction draft let the user know
|
// if there is a transaction draft let the user know
|
||||||
// and let him update manually
|
// and let him update manually
|
||||||
@ -35,24 +36,21 @@ export const onFeeUpdated = (network: string, fee: string): PayloadAction<void>
|
|||||||
state: {
|
state: {
|
||||||
...state,
|
...state,
|
||||||
feeNeedsUpdate: true,
|
feeNeedsUpdate: true,
|
||||||
recommendedFee: fee,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// automatically update feeLevels and gasPrice
|
// automatically update feeLevels
|
||||||
const feeLevels = dispatch(getFeeLevels(state.networkSymbol));
|
const newFeeLevels = dispatch(getFeeLevels(feeLevels));
|
||||||
const selectedFeeLevel = getSelectedFeeLevel(feeLevels, state.selectedFeeLevel);
|
const selectedFeeLevel = getSelectedFeeLevel(newFeeLevels, state.selectedFeeLevel);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SEND.CHANGE,
|
type: SEND.CHANGE,
|
||||||
networkType: 'ripple',
|
networkType: 'ripple',
|
||||||
state: {
|
state: {
|
||||||
...state,
|
...state,
|
||||||
feeNeedsUpdate: false,
|
feeNeedsUpdate: false,
|
||||||
recommendedFee: fee,
|
feeLevels: newFeeLevels,
|
||||||
gasPrice: selectedFeeLevel.gasPrice,
|
|
||||||
feeLevels,
|
|
||||||
selectedFeeLevel,
|
selectedFeeLevel,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -70,9 +68,11 @@ export const validation = (): PayloadAction<State> => (dispatch: Dispatch, getSt
|
|||||||
state.warnings = {};
|
state.warnings = {};
|
||||||
state.infos = {};
|
state.infos = {};
|
||||||
state = dispatch(recalculateTotalAmount(state));
|
state = dispatch(recalculateTotalAmount(state));
|
||||||
|
state = dispatch(updateCustomFeeLabel(state));
|
||||||
state = dispatch(addressValidation(state));
|
state = dispatch(addressValidation(state));
|
||||||
state = dispatch(addressLabel(state));
|
state = dispatch(addressLabel(state));
|
||||||
state = dispatch(amountValidation(state));
|
state = dispatch(amountValidation(state));
|
||||||
|
state = dispatch(feeValidation(state));
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,19 +83,27 @@ const recalculateTotalAmount = ($state: State): PayloadAction<State> => (dispatc
|
|||||||
} = getState().selectedAccount;
|
} = getState().selectedAccount;
|
||||||
if (!account) return $state;
|
if (!account) return $state;
|
||||||
|
|
||||||
const blockchain = getState().blockchain.find(b => b.shortcut === account.network);
|
|
||||||
if (!blockchain) return $state;
|
|
||||||
const fee = toDecimalAmount(blockchain.fee, 6);
|
|
||||||
|
|
||||||
const state = { ...$state };
|
const state = { ...$state };
|
||||||
|
|
||||||
if (state.setMax) {
|
if (state.setMax) {
|
||||||
const pendingAmount = getPendingAmount(pending, state.networkSymbol, false);
|
const pendingAmount = getPendingAmount(pending, state.networkSymbol, false);
|
||||||
const b = new BigNumber(account.balance).minus(pendingAmount);
|
const availableBalance = new BigNumber(account.balance).minus(pendingAmount);
|
||||||
state.amount = calculateMaxAmount(b, fee);
|
state.amount = calculateMaxAmount(availableBalance, state.selectedFeeLevel.fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.total = calculateTotal(state.amount, fee);
|
state.total = calculateTotal(state.amount, state.selectedFeeLevel.fee);
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateCustomFeeLabel = ($state: State): PayloadAction<State> => (): State => {
|
||||||
|
const state = { ...$state };
|
||||||
|
if ($state.selectedFeeLevel.value === 'Custom') {
|
||||||
|
state.selectedFeeLevel = {
|
||||||
|
...state.selectedFeeLevel,
|
||||||
|
fee: state.fee,
|
||||||
|
label: `${toDecimalAmount(state.fee, 6)} ${state.networkSymbol}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,6 +197,33 @@ const amountValidation = ($state: State): PayloadAction<State> => (dispatch: Dis
|
|||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fee value validation
|
||||||
|
*/
|
||||||
|
export const feeValidation = ($state: State): PayloadAction<State> => (dispatch: Dispatch, getState: GetState): State => {
|
||||||
|
const state = { ...$state };
|
||||||
|
if (!state.touched.fee) return state;
|
||||||
|
|
||||||
|
const {
|
||||||
|
network,
|
||||||
|
} = getState().selectedAccount;
|
||||||
|
if (!network) return state;
|
||||||
|
|
||||||
|
const { fee } = state;
|
||||||
|
if (fee.length < 1) {
|
||||||
|
state.errors.fee = 'Fee is not set';
|
||||||
|
} else if (fee.length > 0 && !fee.match(ABS_RE)) {
|
||||||
|
state.errors.fee = 'Fee must be an absolute number';
|
||||||
|
} else {
|
||||||
|
const gl: BigNumber = new BigNumber(fee);
|
||||||
|
if (gl.lessThan(10)) {
|
||||||
|
state.errors.fee = 'Fee is below recommended';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UTILITIES
|
* UTILITIES
|
||||||
*/
|
*/
|
||||||
@ -212,36 +247,32 @@ const calculateMaxAmount = (balance: BigNumber, fee: string): string => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFeeLevels = (symbol: string): PayloadAction<Array<FeeLevel>> => (dispatch: Dispatch, getState: GetState): Array<FeeLevel> => {
|
// Generate FeeLevel dataset for "fee" select
|
||||||
const blockchain = getState().blockchain.find(b => b.shortcut === symbol.toLowerCase());
|
export const getFeeLevels = (feeLevels: Array<BlockchainFeeLevel>, selected?: FeeLevel): PayloadAction<Array<FeeLevel>> => (dispatch: Dispatch, getState: GetState): Array<FeeLevel> => {
|
||||||
if (!blockchain) {
|
const { network } = getState().selectedAccount;
|
||||||
// return default fee levels (TODO: get them from config)
|
if (!network) return []; // flowtype fallback
|
||||||
return [{
|
|
||||||
value: 'Normal',
|
|
||||||
gasPrice: '0.000012',
|
|
||||||
label: `0.000012 ${symbol}`,
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
const xrpDrops = toDecimalAmount(blockchain.fee, 6);
|
// map BlockchainFeeLevel to SendFormReducer FeeLevel
|
||||||
|
const levels = feeLevels.map(level => ({
|
||||||
|
value: level.name,
|
||||||
|
fee: level.value,
|
||||||
|
label: `${toDecimalAmount(level.value, network.decimals)} ${network.symbol}`,
|
||||||
|
}));
|
||||||
|
|
||||||
// TODO: calc fee levels
|
// add "Custom" level
|
||||||
return [{
|
const customLevel = selected && selected.value === 'Custom' ? {
|
||||||
value: 'Normal',
|
value: 'Custom',
|
||||||
gasPrice: xrpDrops,
|
fee: selected.fee,
|
||||||
label: `${xrpDrops} ${symbol}`,
|
label: `${toDecimalAmount(selected.fee, network.decimals)} ${network.symbol}`,
|
||||||
}];
|
} : {
|
||||||
|
value: 'Custom',
|
||||||
|
fee: '0',
|
||||||
|
label: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
return levels.concat([customLevel]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// export const getFeeLevels = (shortcut: string): Array<FeeLevel> => ([
|
|
||||||
// {
|
|
||||||
// value: 'Normal',
|
|
||||||
// gasPrice: '1',
|
|
||||||
// label: `1 ${shortcut}`,
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
|
|
||||||
export const getSelectedFeeLevel = (feeLevels: Array<FeeLevel>, selected: FeeLevel): FeeLevel => {
|
export const getSelectedFeeLevel = (feeLevels: Array<FeeLevel>, selected: FeeLevel): FeeLevel => {
|
||||||
const { value } = selected;
|
const { value } = selected;
|
||||||
let selectedFeeLevel: ?FeeLevel;
|
let selectedFeeLevel: ?FeeLevel;
|
||||||
|
@ -7,7 +7,7 @@ import type { Action } from 'flowtype';
|
|||||||
|
|
||||||
export type FeeLevel = {
|
export type FeeLevel = {
|
||||||
label: string;
|
label: string;
|
||||||
gasPrice: string;
|
fee: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export type State = {
|
|||||||
setMax: boolean;
|
setMax: boolean;
|
||||||
feeLevels: Array<FeeLevel>;
|
feeLevels: Array<FeeLevel>;
|
||||||
selectedFeeLevel: FeeLevel;
|
selectedFeeLevel: FeeLevel;
|
||||||
recommendedFee: string;
|
fee: string;
|
||||||
feeNeedsUpdate: boolean;
|
feeNeedsUpdate: boolean;
|
||||||
sequence: string;
|
sequence: string;
|
||||||
total: string;
|
total: string;
|
||||||
@ -49,11 +49,11 @@ export const initialState: State = {
|
|||||||
setMax: false,
|
setMax: false,
|
||||||
feeLevels: [],
|
feeLevels: [],
|
||||||
selectedFeeLevel: {
|
selectedFeeLevel: {
|
||||||
label: 'Normal',
|
|
||||||
gasPrice: '0',
|
|
||||||
value: 'Normal',
|
value: 'Normal',
|
||||||
|
label: '',
|
||||||
|
fee: '0',
|
||||||
},
|
},
|
||||||
recommendedFee: '0',
|
fee: '0',
|
||||||
feeNeedsUpdate: false,
|
feeNeedsUpdate: false,
|
||||||
sequence: '0',
|
sequence: '0',
|
||||||
total: '0',
|
total: '0',
|
||||||
|
Loading…
Reference in New Issue
Block a user