mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-01-24 18:09:10 +00:00
[FEATURE] Call contract to validate scheduling params
This commit is contained in:
parent
1630e9fee9
commit
2cf2cc5b26
@ -20,7 +20,8 @@ import {
|
||||
SetScheduleTimezoneAction,
|
||||
SetScheduleGasPriceFieldAction,
|
||||
SetScheduleGasLimitFieldAction,
|
||||
SetScheduleDepositFieldAction
|
||||
SetScheduleDepositFieldAction,
|
||||
SetScheduleParamsValidityAction
|
||||
} from '../actionTypes';
|
||||
import { TypeKeys } from 'actions/transaction/constants';
|
||||
|
||||
@ -162,6 +163,12 @@ const setScheduleDepositField = (payload: SetScheduleDepositFieldAction['payload
|
||||
payload
|
||||
});
|
||||
|
||||
type TSetScheduleParamsValidity = typeof setScheduleParamsValidity;
|
||||
const setScheduleParamsValidity = (payload: SetScheduleParamsValidityAction['payload']) => ({
|
||||
type: TypeKeys.SCHEDULE_PARAMS_VALIDITY_SET,
|
||||
payload
|
||||
});
|
||||
|
||||
type TReset = typeof reset;
|
||||
const reset = (payload: ResetAction['payload'] = { include: {}, exclude: {} }): ResetAction => ({
|
||||
type: TypeKeys.RESET,
|
||||
@ -190,6 +197,7 @@ export {
|
||||
TSetScheduleGasPriceField,
|
||||
TSetScheduleGasLimitField,
|
||||
TSetScheduleDepositField,
|
||||
TSetScheduleParamsValidity,
|
||||
TReset,
|
||||
inputGasLimit,
|
||||
inputGasPrice,
|
||||
@ -212,5 +220,6 @@ export {
|
||||
setScheduleGasPriceField,
|
||||
setScheduleGasLimitField,
|
||||
setScheduleDepositField,
|
||||
setScheduleParamsValidity,
|
||||
reset
|
||||
};
|
||||
|
@ -163,6 +163,14 @@ interface SetScheduleDepositFieldAction {
|
||||
};
|
||||
}
|
||||
|
||||
interface SetScheduleParamsValidityAction {
|
||||
type: TypeKeys.SCHEDULE_PARAMS_VALIDITY_SET;
|
||||
payload: {
|
||||
raw: boolean;
|
||||
value: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
type InputFieldAction = InputNonceAction | InputGasLimitAction | InputDataAction;
|
||||
|
||||
type FieldAction =
|
||||
@ -181,7 +189,8 @@ type FieldAction =
|
||||
| SetScheduleGasPriceFieldAction
|
||||
| SetScheduleGasLimitFieldAction
|
||||
| SetScheduleDepositFieldAction
|
||||
| SetScheduleTimezoneAction;
|
||||
| SetScheduleTimezoneAction
|
||||
| SetScheduleParamsValidityAction;
|
||||
|
||||
export {
|
||||
InputGasLimitAction,
|
||||
@ -208,5 +217,6 @@ export {
|
||||
SetScheduleGasPriceFieldAction,
|
||||
SetScheduleGasLimitFieldAction,
|
||||
SetScheduleDepositFieldAction,
|
||||
SetScheduleTimezoneAction
|
||||
SetScheduleTimezoneAction,
|
||||
SetScheduleParamsValidityAction
|
||||
};
|
||||
|
@ -57,6 +57,7 @@ export enum TypeKeys {
|
||||
SCHEDULE_TYPE_SET = 'SCHEDULE_TYPE_SET',
|
||||
SCHEDULING_TOGGLE_SET = 'SCHEDULING_TOGGLE_SET',
|
||||
SCHEDULE_DEPOSIT_FIELD_SET = 'SCHEDULE_DEPOSIT_FIELD_SET',
|
||||
SCHEDULE_PARAMS_VALIDITY_SET = 'SCHEDULE_PARAMS_VALIDITY_SET',
|
||||
|
||||
TOKEN_TO_META_SET = 'TOKEN_TO_META_SET',
|
||||
UNIT_META_SET = 'UNIT_META_SET',
|
||||
|
@ -1,32 +1,48 @@
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import translate from 'translations';
|
||||
import { ConfirmationModal } from 'components/ConfirmationModal';
|
||||
import { SigningStatus } from 'components';
|
||||
import { SendScheduleTransactionButtonFactory } from 'containers/Tabs/ScheduleTransaction/components/SendScheduleTransactionButtonFactory';
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from 'reducers';
|
||||
import { getScheduleParamsValidity } from 'selectors/transaction';
|
||||
|
||||
export const SendScheduleTransactionButton: React.SFC<{
|
||||
interface Props {
|
||||
className?: string;
|
||||
signing?: boolean;
|
||||
customModal?: typeof ConfirmationModal;
|
||||
}> = ({ signing, customModal, className }) => (
|
||||
<React.Fragment>
|
||||
<SendScheduleTransactionButtonFactory
|
||||
signing={signing}
|
||||
Modal={customModal ? customModal : ConfirmationModal}
|
||||
withProps={({ disabled, openModal, signTx }) => (
|
||||
<React.Fragment>
|
||||
<button
|
||||
disabled={disabled}
|
||||
className={`SendButton btn btn-primary btn-block ${className}`}
|
||||
onClick={() => {
|
||||
!!signing ? (signTx(), openModal()) : openModal();
|
||||
}}
|
||||
>
|
||||
{translate('SCHEDULE_SCHEDULE')}
|
||||
</button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
/>
|
||||
<SigningStatus />
|
||||
</React.Fragment>
|
||||
);
|
||||
paramsValidity: boolean;
|
||||
}
|
||||
|
||||
class SendScheduleTransactionButtonClass extends Component<Props> {
|
||||
public render() {
|
||||
const { className, customModal, paramsValidity, signing } = this.props;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SendScheduleTransactionButtonFactory
|
||||
signing={signing}
|
||||
Modal={customModal ? customModal : ConfirmationModal}
|
||||
withProps={({ disabled, openModal, signTx }) => (
|
||||
<React.Fragment>
|
||||
<button
|
||||
disabled={disabled || !paramsValidity}
|
||||
className={`SendButton btn btn-primary btn-block ${className}`}
|
||||
onClick={() => {
|
||||
!!signing ? (signTx(), openModal()) : openModal();
|
||||
}}
|
||||
>
|
||||
{translate('SCHEDULE_SCHEDULE')}
|
||||
</button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
/>
|
||||
<SigningStatus />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const SendScheduleTransactionButton = connect((state: AppState) => ({
|
||||
paramsValidity: getScheduleParamsValidity(state).value
|
||||
}))(SendScheduleTransactionButtonClass);
|
||||
|
@ -0,0 +1,3 @@
|
||||
import { schedulingParamsValidity } from './paramsValidity';
|
||||
|
||||
export const schedulingTransactionNetworkSagas = [schedulingParamsValidity];
|
@ -0,0 +1,149 @@
|
||||
import { SagaIterator, delay } from 'redux-saga';
|
||||
import { select, fork, call, take, apply, put } from 'redux-saga/effects';
|
||||
import { getOffline, getNodeLib } from 'selectors/config';
|
||||
import {
|
||||
ICurrentSchedulingToggle,
|
||||
ICurrentWindowSize
|
||||
} from 'containers/Tabs/ScheduleTransaction/selectors';
|
||||
import {
|
||||
getSchedulingToggle,
|
||||
getScheduleTimestamp,
|
||||
getScheduleTimezone
|
||||
} from '../../../selectors/fields';
|
||||
import {
|
||||
TypeKeys,
|
||||
SetScheduleParamsValidityAction,
|
||||
setScheduleParamsValidity
|
||||
} from 'actions/transaction';
|
||||
import {
|
||||
getCurrentTo,
|
||||
getCurrentValue,
|
||||
getData,
|
||||
getScheduleType,
|
||||
getWindowStart,
|
||||
getWindowSize,
|
||||
getTimeBounty,
|
||||
getScheduleGasPrice,
|
||||
getScheduleGasLimit,
|
||||
getScheduleDeposit
|
||||
} from 'selectors/transaction';
|
||||
import { getWalletInst } from 'selectors/wallet';
|
||||
import {
|
||||
EAC_SCHEDULING_CONFIG,
|
||||
calcEACEndowment,
|
||||
getValidateRequestParamsData,
|
||||
EAC_ADDRESSES,
|
||||
parseSchedulingParametersValidity
|
||||
} from 'libs/scheduling';
|
||||
import { gasPriceToBase } from 'libs/units';
|
||||
import BN from 'bn.js';
|
||||
import { bufferToHex } from 'ethereumjs-util';
|
||||
import RequestFactory from 'libs/scheduling/contracts/RequestFactory';
|
||||
import { dateTimeToUnixTimestamp, windowSizeBlockToMin } from 'selectors/transaction/helpers';
|
||||
|
||||
export function* shouldValidateParams(): SagaIterator {
|
||||
while (true) {
|
||||
yield take([
|
||||
TypeKeys.TO_FIELD_SET,
|
||||
TypeKeys.DATA_FIELD_SET,
|
||||
TypeKeys.CURRENT_TIME_BOUNTY_SET,
|
||||
TypeKeys.WINDOW_SIZE_FIELD_SET,
|
||||
TypeKeys.WINDOW_START_FIELD_SET,
|
||||
TypeKeys.SCHEDULE_TIMESTAMP_FIELD_SET,
|
||||
TypeKeys.TIME_BOUNTY_FIELD_SET,
|
||||
TypeKeys.SCHEDULE_TYPE_SET,
|
||||
TypeKeys.SCHEDULING_TOGGLE_SET,
|
||||
TypeKeys.SCHEDULE_TIMEZONE_SET
|
||||
]);
|
||||
|
||||
yield call(delay, 250);
|
||||
|
||||
const isOffline: boolean = yield select(getOffline);
|
||||
const schedulingToggle: ICurrentSchedulingToggle = yield select(getSchedulingToggle);
|
||||
const scheduling = Boolean(schedulingToggle && schedulingToggle.value);
|
||||
|
||||
if (isOffline || !scheduling) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield call(checkSchedulingParametersValidity);
|
||||
}
|
||||
}
|
||||
|
||||
function* checkSchedulingParametersValidity() {
|
||||
const currentTo = yield select(getCurrentTo);
|
||||
const currentValue = yield select(getCurrentValue);
|
||||
const callData = yield select(getData);
|
||||
const scheduleType = yield select(getScheduleType);
|
||||
const windowStart = yield select(getWindowStart);
|
||||
const windowSize: ICurrentWindowSize = yield select(getWindowSize);
|
||||
const timeBounty = yield select(getTimeBounty);
|
||||
const scheduleGasPrice = yield select(getScheduleGasPrice);
|
||||
const scheduleGasLimit = yield select(getScheduleGasLimit);
|
||||
const deposit = yield select(getScheduleDeposit);
|
||||
const node = yield select(getNodeLib);
|
||||
const wallet = yield select(getWalletInst);
|
||||
const scheduleTimestamp = yield select(getScheduleTimestamp);
|
||||
const scheduleTimezone = yield select(getScheduleTimezone);
|
||||
|
||||
if (
|
||||
!currentValue.value ||
|
||||
!currentTo.value ||
|
||||
!scheduleGasPrice.value ||
|
||||
!wallet ||
|
||||
!windowSize.value
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const callGasLimit = scheduleGasLimit.value || EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_LIMIT_FALLBACK;
|
||||
|
||||
const endowment = calcEACEndowment(
|
||||
callGasLimit,
|
||||
currentValue.value || new BN(0),
|
||||
scheduleGasPrice.value || gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK),
|
||||
timeBounty.value
|
||||
);
|
||||
|
||||
const fromAddress = yield apply(wallet, wallet.getAddressString);
|
||||
|
||||
const data = getValidateRequestParamsData(
|
||||
bufferToHex(currentTo.value),
|
||||
callData.value ? bufferToHex(callData.value) : '',
|
||||
callGasLimit,
|
||||
currentValue.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value) || 0,
|
||||
scheduleType.value === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone.value)
|
||||
: windowStart.value,
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value,
|
||||
deposit.value || new BN(0),
|
||||
scheduleType.value === 'time',
|
||||
endowment,
|
||||
fromAddress
|
||||
);
|
||||
|
||||
const callResult: string = yield apply(node, node.sendCallRequest, [
|
||||
{
|
||||
to: EAC_ADDRESSES.KOVAN.requestFactory,
|
||||
data
|
||||
}
|
||||
]);
|
||||
|
||||
const { paramsValidity } = RequestFactory.validateRequestParams.decodeOutput(callResult);
|
||||
|
||||
const errors = parseSchedulingParametersValidity(paramsValidity);
|
||||
const paramsValid = errors.length === 0;
|
||||
|
||||
yield call(setField, {
|
||||
raw: paramsValid,
|
||||
value: paramsValid
|
||||
});
|
||||
}
|
||||
|
||||
export function* setField(payload: SetScheduleParamsValidityAction['payload']) {
|
||||
yield put(setScheduleParamsValidity(payload));
|
||||
}
|
||||
|
||||
export const schedulingParamsValidity = fork(shouldValidateParams);
|
@ -11,6 +11,7 @@ const getSchedulingToggle = (state: AppState) => getFields(state).schedulingTogg
|
||||
const getScheduleGasLimit = (state: AppState) => getFields(state).scheduleGasLimit;
|
||||
const getScheduleGasPrice = (state: AppState) => getFields(state).scheduleGasPrice;
|
||||
const getScheduleDeposit = (state: AppState) => getFields(state).scheduleDeposit;
|
||||
const getScheduleParamsValidity = (state: AppState) => getFields(state).scheduleParamsValidity;
|
||||
|
||||
const schedulingFields = [
|
||||
'windowStart',
|
||||
@ -20,7 +21,8 @@ const schedulingFields = [
|
||||
'schedulingToggle',
|
||||
'scheduleDeposit',
|
||||
'scheduleGasLimit',
|
||||
'scheduleGasPrice'
|
||||
'scheduleGasPrice',
|
||||
'scheduleParamsValidity'
|
||||
];
|
||||
|
||||
export {
|
||||
@ -34,5 +36,6 @@ export {
|
||||
getScheduleGasLimit,
|
||||
getScheduleGasPrice,
|
||||
getScheduleDeposit,
|
||||
schedulingFields
|
||||
schedulingFields,
|
||||
getScheduleParamsValidity
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { AppState } from 'reducers';
|
||||
import {
|
||||
IGetTransaction,
|
||||
getCurrentTo,
|
||||
getCurrentValue,
|
||||
getFields,
|
||||
@ -21,7 +20,8 @@ import {
|
||||
isValidScheduleDeposit,
|
||||
getScheduleDeposit,
|
||||
getScheduleTimestamp,
|
||||
getScheduleTimezone
|
||||
getScheduleTimezone,
|
||||
IGetTransaction
|
||||
} from 'selectors/transaction';
|
||||
import { Address, gasPriceToBase } from 'libs/units';
|
||||
import {
|
||||
@ -43,7 +43,7 @@ import {
|
||||
import EthTx from 'ethereumjs-tx';
|
||||
import { getLatestBlock } from 'selectors/config';
|
||||
|
||||
const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
export const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
const currentTo = getCurrentTo(state);
|
||||
const currentValue = getCurrentValue(state);
|
||||
const transactionFields = getFields(state);
|
||||
@ -69,6 +69,13 @@ const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
const depositValid = isValidScheduleDeposit(state);
|
||||
const deposit = getScheduleDeposit(state);
|
||||
|
||||
const endowment = calcEACEndowment(
|
||||
scheduleGasLimit.value || EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_LIMIT_FALLBACK,
|
||||
currentValue.value || new BN(0),
|
||||
scheduleGasPrice.value || gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK),
|
||||
timeBounty.value
|
||||
);
|
||||
|
||||
const isFullTransaction =
|
||||
isFullTx(state, transactionFields, currentTo, currentValue, dataExists, validGasCost, unit) &&
|
||||
(windowStartValid || scheduleTimestampValid) &&
|
||||
@ -77,26 +84,23 @@ const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
scheduleGasLimitValid &&
|
||||
depositValid;
|
||||
|
||||
const transactionData = getScheduleData(
|
||||
currentTo.raw,
|
||||
callData.raw,
|
||||
scheduleGasLimit.value,
|
||||
currentValue.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value),
|
||||
scheduleType.value === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone.value)
|
||||
: windowStart.value,
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value,
|
||||
deposit.value
|
||||
);
|
||||
let transactionData = null;
|
||||
|
||||
const endowment = calcEACEndowment(
|
||||
scheduleGasLimit.value || EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_LIMIT_FALLBACK,
|
||||
currentValue.value || new BN(0),
|
||||
scheduleGasPrice.value || gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK),
|
||||
timeBounty.value
|
||||
);
|
||||
if (isFullTransaction) {
|
||||
transactionData = getScheduleData(
|
||||
currentTo.raw,
|
||||
callData.raw,
|
||||
scheduleGasLimit.value,
|
||||
currentValue.value,
|
||||
windowSizeBlockToMin(windowSize.value, scheduleType.value),
|
||||
scheduleType.value === 'time'
|
||||
? dateTimeToUnixTimestamp(scheduleTimestamp, scheduleTimezone.value)
|
||||
: windowStart.value,
|
||||
scheduleGasPrice.value,
|
||||
timeBounty.value,
|
||||
deposit.value
|
||||
);
|
||||
}
|
||||
|
||||
const transactionOptions = {
|
||||
to: Address(
|
||||
@ -122,5 +126,3 @@ const getSchedulingTransaction = (state: AppState): IGetTransaction => {
|
||||
isFullTransaction
|
||||
};
|
||||
};
|
||||
|
||||
export { getSchedulingTransaction };
|
||||
|
@ -120,7 +120,7 @@ export default class AbiFunction {
|
||||
this.inputNames.map(name => {
|
||||
const type = this.funcParams[name].type;
|
||||
//TODO: parse args based on type
|
||||
if (!suppliedArgs[name]) {
|
||||
if (typeof suppliedArgs[name] === 'undefined') {
|
||||
throw Error(
|
||||
`Expected argument "${name}" of type "${type}" missing, suppliedArgs: ${JSON.stringify(
|
||||
suppliedArgs,
|
||||
|
58
common/libs/scheduling/contracts/RequestFactory.ts
Normal file
58
common/libs/scheduling/contracts/RequestFactory.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import Contract from 'libs/contracts';
|
||||
|
||||
interface ABIFunc<T, K = void> {
|
||||
encodeInput(x: T): string;
|
||||
decodeInput(argStr: string): T;
|
||||
decodeOutput(argStr: string): K;
|
||||
}
|
||||
|
||||
type address = any;
|
||||
type uint256 = any;
|
||||
type bytes = any;
|
||||
|
||||
interface IRequestFactory {
|
||||
validateRequestParams: ABIFunc<
|
||||
{ _addressArgs: address[]; _uintArgs: uint256[]; _callData: bytes; _endowment: uint256 },
|
||||
{ paramsValidity: boolean[] }
|
||||
>;
|
||||
}
|
||||
|
||||
const requestFactoryAbi = [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '_addressArgs',
|
||||
type: 'address[3]'
|
||||
},
|
||||
{
|
||||
name: '_uintArgs',
|
||||
type: 'uint256[12]'
|
||||
},
|
||||
{
|
||||
name: '_callData',
|
||||
type: 'bytes'
|
||||
},
|
||||
{
|
||||
name: '_endowment',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'validateRequestParams',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool[6]'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
];
|
||||
|
||||
const outputMappings = {
|
||||
validateRequestParams: ['paramsValidity']
|
||||
};
|
||||
|
||||
export default (new Contract(requestFactoryAbi, outputMappings) as any) as IRequestFactory;
|
@ -1,7 +1,8 @@
|
||||
import BN from 'bn.js';
|
||||
import abi from 'ethereumjs-abi';
|
||||
import { toWei, Units } from './units';
|
||||
import { toWei, Units } from '../units';
|
||||
import { toBuffer } from 'ethereumjs-util';
|
||||
import RequestFactory from './contracts/RequestFactory';
|
||||
|
||||
const TIME_BOUNTY_MIN = new BN('1');
|
||||
|
||||
@ -25,6 +26,7 @@ export const EAC_SCHEDULING_CONFIG = {
|
||||
export const EAC_ADDRESSES = {
|
||||
KOVAN: {
|
||||
blockScheduler: '0x1afc19a7e642761ba2b55d2a45b32c7ef08269d1',
|
||||
requestFactory: '0x496e2b6089bde77293a994469b08e9f266d87adb',
|
||||
timestampScheduler: '0xc6370807f0164bdf10a66c08d0dab1028dbe80a3'
|
||||
}
|
||||
};
|
||||
@ -106,6 +108,67 @@ export const getScheduleData = (
|
||||
]);
|
||||
};
|
||||
|
||||
export const parseSchedulingParametersValidity = (isValid: boolean[]) => {
|
||||
const Errors = [
|
||||
'InsufficientEndowment',
|
||||
'ReservedWindowBiggerThanExecutionWindow',
|
||||
'InvalidTemporalUnit',
|
||||
'ExecutionWindowTooSoon',
|
||||
'CallGasTooHigh',
|
||||
'EmptyToAddress'
|
||||
];
|
||||
const errors: string[] = [];
|
||||
|
||||
isValid.forEach((boolIsTrue, index) => {
|
||||
if (!boolIsTrue) {
|
||||
errors.push(Errors[index]);
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export const getValidateRequestParamsData = (
|
||||
toAddress: string,
|
||||
callData = '',
|
||||
callGas: BN,
|
||||
callValue: any,
|
||||
windowSize: number,
|
||||
windowStart: BN,
|
||||
gasPrice: BN,
|
||||
timeBounty: BN,
|
||||
requiredDeposit: BN,
|
||||
isTimestamp: boolean,
|
||||
endowment: BN,
|
||||
fromAddress: string
|
||||
): string => {
|
||||
const temporalUnit = isTimestamp ? 2 : 1;
|
||||
const freezePeriod = isTimestamp ? 3 * 60 : 10; // 3 minutes or 10 blocks
|
||||
const reservedWindowSize = isTimestamp ? 5 * 60 : 16; // 5 minutes or 16 blocks
|
||||
const claimWindowSize = isTimestamp ? 60 * 60 : 255; // 60 minutes or 255 blocks
|
||||
const feeRecipient = '0x0'; // stub
|
||||
|
||||
return RequestFactory.validateRequestParams.encodeInput({
|
||||
_addressArgs: [fromAddress, feeRecipient, toAddress],
|
||||
_uintArgs: [
|
||||
EAC_SCHEDULING_CONFIG.FEE,
|
||||
timeBounty,
|
||||
claimWindowSize,
|
||||
freezePeriod,
|
||||
reservedWindowSize,
|
||||
temporalUnit,
|
||||
windowSize,
|
||||
windowStart,
|
||||
callGas,
|
||||
callValue,
|
||||
gasPrice,
|
||||
requiredDeposit
|
||||
],
|
||||
_callData: callData,
|
||||
_endowment: endowment
|
||||
});
|
||||
};
|
||||
|
||||
export const getTXDetailsCheckURL = (txHash: string) => {
|
||||
return `${EAC_SCHEDULING_CONFIG.DAPP_ADDRESS}/awaiting/scheduler/${txHash}`;
|
||||
};
|
@ -44,7 +44,8 @@ const INITIAL_STATE: State = {
|
||||
raw: EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK.toString(),
|
||||
value: gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK)
|
||||
},
|
||||
scheduleDeposit: { raw: '', value: null }
|
||||
scheduleDeposit: { raw: '', value: null },
|
||||
scheduleParamsValidity: { raw: true, value: true }
|
||||
};
|
||||
|
||||
const updateField = (key: keyof State): Reducer<State> => (state: State, action: FieldAction) => ({
|
||||
@ -114,6 +115,8 @@ export const fields = (
|
||||
return updateField('scheduleGasPrice')(state, action);
|
||||
case TK.SCHEDULE_DEPOSIT_FIELD_SET:
|
||||
return updateField('scheduleDeposit')(state, action);
|
||||
case TK.SCHEDULE_PARAMS_VALIDITY_SET:
|
||||
return updateField('scheduleParamsValidity')(state, action);
|
||||
case TK.TOKEN_TO_ETHER_SWAP:
|
||||
return tokenToEther(state, action);
|
||||
case TK.ETHER_TO_TOKEN_SWAP:
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
SetScheduleGasPriceFieldAction,
|
||||
SetScheduleGasLimitFieldAction,
|
||||
SetScheduleDepositFieldAction,
|
||||
SetScheduleTimezoneAction
|
||||
SetScheduleTimezoneAction,
|
||||
SetScheduleParamsValidityAction
|
||||
} from 'actions/transaction';
|
||||
import { Wei } from 'libs/units';
|
||||
|
||||
@ -32,4 +33,5 @@ export interface State {
|
||||
scheduleGasLimit: SetScheduleGasLimitFieldAction['payload'];
|
||||
scheduleGasPrice: SetScheduleGasPriceFieldAction['payload'];
|
||||
scheduleDeposit: SetScheduleDepositFieldAction['payload'];
|
||||
scheduleParamsValidity: SetScheduleParamsValidityAction['payload'];
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { from } from './from';
|
||||
import { gas } from './gas';
|
||||
import { nonce } from './nonce';
|
||||
export const network = [from, ...gas, nonce];
|
||||
import { schedulingTransactionNetworkSagas } from '../../../containers/Tabs/ScheduleTransaction/sagas/transaction/network';
|
||||
|
||||
export const network = [from, ...gas, nonce, ...schedulingTransactionNetworkSagas];
|
||||
|
@ -33,7 +33,8 @@ describe('fields reducer', () => {
|
||||
value: gasPriceToBase(EAC_SCHEDULING_CONFIG.SCHEDULE_GAS_PRICE_FALLBACK)
|
||||
},
|
||||
scheduleGasLimit: { raw: '21000', value: new BN(21000) },
|
||||
scheduleDeposit: { raw: '', value: null }
|
||||
scheduleDeposit: { raw: '', value: null },
|
||||
scheduleParamsValidity: { raw: true, value: true }
|
||||
};
|
||||
const testPayload = { raw: 'test', value: null };
|
||||
|
||||
|
@ -81,6 +81,10 @@ describe('fields selector', () => {
|
||||
scheduleDeposit: {
|
||||
raw: '1000000000',
|
||||
value: Wei('1000000000')
|
||||
},
|
||||
scheduleParamsValidity: {
|
||||
raw: false,
|
||||
value: false
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -85,6 +85,10 @@ describe('helpers selector', () => {
|
||||
scheduleDeposit: {
|
||||
raw: '1000000000',
|
||||
value: Wei('1000000000')
|
||||
},
|
||||
scheduleParamsValidity: {
|
||||
raw: false,
|
||||
value: false
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -106,7 +110,8 @@ describe('helpers selector', () => {
|
||||
scheduleTimezone: moment.tz.guess(),
|
||||
scheduleGasPrice: Wei('1500'),
|
||||
scheduleGasLimit: Wei('21000'),
|
||||
scheduleDeposit: Wei('1000000000')
|
||||
scheduleDeposit: Wei('1000000000'),
|
||||
scheduleParamsValidity: false
|
||||
};
|
||||
expect(reduceToValues(state.transaction.fields)).toEqual(values);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user