mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-01-19 07:32:34 +00:00
985ea0fb89
* [FEATURE] Initial EAC integration. * Title and explanation * [FEATURE] Move the Schedule Payment to the main tab. * [FEATURE] TimeBounty slider. * [FEATURE] Move to main menu. * [FEATURE] Redirection to the DApp for details. * [FEATURE] Timestamp scheduling * Scheduling: Basic date and time widget * Linting fixes * Moved the datetime field to new tab * Fixed push errors * Added missing specs * Undid unintentional UI change * Fixed some failing tests * Ignore datetime parameter when checking if a transaction is full * Added a date selector widget and renamed ScheduleTimestamp to ScheduleDate * Marked componentDidMount * Initialized Pikaday * Revert "Initialized Pikaday" This reverts commit 4e5bf5b2b882f236f5977400abf9b7092cbd1592. * Revert "Marked componentDidMount" This reverts commit 85d52192ac58f4b6ca9219e702f7390cd27e582f. * Revert "Added a date selector widget and renamed ScheduleTimestamp to ScheduleDate" This reverts commit aaad0ac9b565a78d1bfc631754160919fd38a59b. * Converted the date picker into a datetime picker * Added decent styling to the datetimepicker * Added validation to the datetime picker * Fixed prepush errors for scheduling timestamp * Adjusted validation logic scheduling timestamp * [FEATURE] Move scheduling to main tab. * [FEATURE] Timezone selector * [FEATURE] Scheduling: Timezone selector * Removed zombie files * [FEATURE] Reimplement Time Bounty. * [FEATURE] Time/block selector * [FEATURE] Add Window Size field. * [FEATURE] Time/block switch functionality * Implemented time/block switcher fuctionality * [FEATURE] Add Schedule Gas Price field. * [FEATURE] Scheduling toggle * [FEATURE] Add basic styling and network check. * [FEATURE] Add Schedule Gas Limit field * [FEATURE] "Scheduled" button styling * Reordered, renamed and centered scheduling elements * Added the toggle button styling * Class -> ClassName * [FEATURE] Add Deposit field * [FEATURE] Move scheduling code into one directory * [FIX] Scheduling responsiveness * [FIX] Datetime picker not working on md screens * [FEATURE] Timestamp Scheduling basic functionality * [FIX] Fix data serialization. * [FEATURE] Timezone inclusion * [FEATURE] Add ChronoLogic logo. * [FEATURE] Add link to image. * [FIX] Update CSS of logo. * [FEATURE] Default Window Size * [FEATURE] Modified Help component to enable acting as a tooltip * [FEATURE] Call contract to validate scheduling params * [FIX] Change moment import to fix tests * [FEATURE] Gas estimation for scheduling * [FEATURE] Additional validation * [FEATURE] UI changes and descriptions * [FEATURE] Add tooltip to window and fix fee display. * [FIX] Fix ethereumjs-abi dependency. * [FEATURE] Hide scheduling when sending tokens. * [FIX] Improved styling datetime picker * [FEATURE] Add Redux state for scheduling * [FEATURE] Create Toggle component, Share code between components * [FEATURE] Use Tooltip component for help. * [FEATURE] Better datetime picker * [FEATURE] Remove fee * Trigger mycryptobuild * [FIX] Timestamp scheduling - Validation match * [FIX] EAC integration touchups * [FIX] Code review fixes * [FIX] Window Size type * [FIX] Type fixes. * [FIX] Make tooltips only show on icons + resposiveness fixes * [FIX] Break tooltips into more lines * [FIX] Remove unnecessary code. * [FIX] Remove unnecessary code. * [FIX] Remove unnecessary types declaration. * [FIX] Fee class names
307 lines
8.6 KiB
TypeScript
307 lines
8.6 KiB
TypeScript
import { buffers, delay } from 'redux-saga';
|
|
import { apply, put, select, take, actionChannel, call, race } from 'redux-saga/effects';
|
|
import BN from 'bn.js';
|
|
import { getNodeLib, getOffline, getAutoGasLimitEnabled } from 'selectors/config';
|
|
import { getWalletInst } from 'selectors/wallet';
|
|
import { getTransaction, getCurrentToAddressMessage } from 'selectors/transaction';
|
|
import {
|
|
setGasLimitField,
|
|
estimateGasFailed,
|
|
estimateGasSucceeded,
|
|
TypeKeys,
|
|
estimateGasRequested,
|
|
estimateGasTimedout
|
|
} from 'actions/transaction';
|
|
import { makeTransaction, getTransactionFields } from 'libs/transaction';
|
|
import {
|
|
shouldEstimateGas,
|
|
estimateGas,
|
|
localGasEstimation,
|
|
setAddressMessageGasLimit
|
|
} from 'sagas/transaction/network/gas';
|
|
import { cloneableGenerator, SagaIteratorClone } from 'redux-saga/utils';
|
|
import { Wei } from 'libs/units';
|
|
import { TypeKeys as ConfigTypeKeys } from 'actions/config';
|
|
import { isSchedulingEnabled } from 'selectors/schedule/fields';
|
|
import { setScheduleGasLimitField } from 'actions/schedule';
|
|
|
|
describe('shouldEstimateGas*', () => {
|
|
const offline = false;
|
|
const autoGasLimitEnabled = true;
|
|
const addressMessage = undefined;
|
|
const transaction: any = 'transaction';
|
|
const tx = { transaction };
|
|
const rest: any = {
|
|
mock1: 'mock1',
|
|
mock2: 'mock2'
|
|
};
|
|
const transactionFields = {
|
|
gasLimit: 'gasLimit',
|
|
gasPrice: 'gasPrice',
|
|
nonce: 'nonce',
|
|
chainId: 'chainId',
|
|
...rest
|
|
};
|
|
const action: any = {
|
|
type: TypeKeys.TO_FIELD_SET,
|
|
payload: {
|
|
value: 'value',
|
|
raw: 'raw'
|
|
}
|
|
};
|
|
|
|
const gen = shouldEstimateGas();
|
|
|
|
it('should take expected types', () => {
|
|
expect(gen.next().value).toEqual(
|
|
take([
|
|
TypeKeys.TO_FIELD_SET,
|
|
TypeKeys.DATA_FIELD_SET,
|
|
TypeKeys.ETHER_TO_TOKEN_SWAP,
|
|
TypeKeys.TOKEN_TO_TOKEN_SWAP,
|
|
TypeKeys.TOKEN_TO_ETHER_SWAP,
|
|
ConfigTypeKeys.CONFIG_TOGGLE_AUTO_GAS_LIMIT
|
|
])
|
|
);
|
|
});
|
|
|
|
it('should select getOffline', () => {
|
|
expect(gen.next(action).value).toEqual(select(getOffline));
|
|
});
|
|
|
|
it('should select autoGasLimitEnabled', () => {
|
|
expect(gen.next(offline).value).toEqual(select(getAutoGasLimitEnabled));
|
|
});
|
|
|
|
it('should select getCurrentToAddressMessage', () => {
|
|
expect(gen.next(autoGasLimitEnabled).value).toEqual(select(getCurrentToAddressMessage));
|
|
});
|
|
|
|
it('should select getTransaction', () => {
|
|
expect(gen.next(addressMessage).value).toEqual(select(getTransaction));
|
|
});
|
|
|
|
it('should call getTransactionFields with transaction', () => {
|
|
expect(gen.next(tx).value).toEqual(call(getTransactionFields, transaction));
|
|
});
|
|
|
|
it('should put estimatedGasRequested with rest', () => {
|
|
expect(gen.next(transactionFields).value).toEqual(put(estimateGasRequested(rest)));
|
|
});
|
|
});
|
|
|
|
describe('estimateGas*', () => {
|
|
const offline = false;
|
|
const autoGasLimitEnabled = true;
|
|
const requestChan = 'requestChan';
|
|
const payload: any = {
|
|
mock1: 'mock1',
|
|
mock2: 'mock2'
|
|
};
|
|
const action = { payload };
|
|
const node: any = {
|
|
estimateGas: jest.fn()
|
|
};
|
|
const walletInst: any = {
|
|
getAddressString: jest.fn()
|
|
};
|
|
const from = '0xa';
|
|
const txObj = { ...payload, from };
|
|
const gasLimit = Wei('100');
|
|
const successfulGasEstimationResult = {
|
|
gasLimit
|
|
};
|
|
|
|
const unsuccessfulGasEstimationResult = {
|
|
gasLimit: null
|
|
};
|
|
const gasSetOptions = {
|
|
raw: gasLimit.toString(),
|
|
value: gasLimit
|
|
};
|
|
|
|
const gens: { [name: string]: any } = {};
|
|
gens.successCase = cloneableGenerator(estimateGas)();
|
|
|
|
let random: () => number;
|
|
beforeAll(() => {
|
|
random = Math.random;
|
|
Math.random = () => 0.001;
|
|
});
|
|
|
|
afterAll(() => {
|
|
Math.random = random;
|
|
});
|
|
|
|
it('should yield actionChannel', () => {
|
|
const expected = JSON.stringify(
|
|
actionChannel(TypeKeys.ESTIMATE_GAS_REQUESTED, buffers.sliding(1))
|
|
);
|
|
const result = JSON.stringify(gens.successCase.next().value);
|
|
expect(expected).toEqual(result);
|
|
});
|
|
|
|
it('should select autoGasLimit', () => {
|
|
expect(gens.successCase.next(requestChan).value).toEqual(select(getAutoGasLimitEnabled));
|
|
});
|
|
|
|
it('should select getOffline', () => {
|
|
expect(gens.successCase.next(autoGasLimitEnabled).value).toEqual(select(getOffline));
|
|
});
|
|
|
|
it('should take requestChan', () => {
|
|
expect(gens.successCase.next(offline).value).toEqual(take(requestChan));
|
|
});
|
|
|
|
it('should call delay', () => {
|
|
expect(gens.successCase.next(action).value).toEqual(call(delay, 250));
|
|
});
|
|
|
|
it('should select getNodeLib', () => {
|
|
expect(gens.successCase.next().value).toEqual(select(getNodeLib));
|
|
});
|
|
|
|
it('should select getWalletInst', () => {
|
|
expect(gens.successCase.next(node).value).toEqual(select(getWalletInst));
|
|
});
|
|
|
|
it('should apply walletInst', () => {
|
|
expect(gens.successCase.next(walletInst).value).toEqual(
|
|
apply(walletInst, walletInst.getAddressString)
|
|
);
|
|
});
|
|
|
|
it('should race between node.estimate gas and a 10 second timeout', () => {
|
|
gens.failCase = gens.successCase.clone();
|
|
expect(gens.successCase.next(from).value).toEqual(
|
|
race({
|
|
gasLimit: apply(node, node.estimateGas, [txObj]),
|
|
timeout: call(delay, 10000)
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should select isSchedulingEnabled', () => {
|
|
gens.timeOutCase = gens.successCase.clone();
|
|
expect(gens.successCase.next(successfulGasEstimationResult).value).toEqual(
|
|
select(isSchedulingEnabled)
|
|
);
|
|
});
|
|
|
|
it('should put setGasLimitField', () => {
|
|
gens.scheduleCase = gens.successCase.clone();
|
|
const notScheduling = null as any;
|
|
expect(gens.successCase.next(notScheduling).value).toEqual(
|
|
put(setGasLimitField(gasSetOptions))
|
|
);
|
|
});
|
|
|
|
it('should put setScheduleGasLimitField', () => {
|
|
const scheduling = { value: true } as any;
|
|
expect(gens.scheduleCase.next(scheduling).value).toEqual(
|
|
put(setScheduleGasLimitField(gasSetOptions))
|
|
);
|
|
});
|
|
|
|
it('should put estimateGasSucceeded', () => {
|
|
expect(gens.successCase.next().value).toEqual(put(estimateGasSucceeded()));
|
|
});
|
|
|
|
describe('when it times out', () => {
|
|
it('should put estimateGasTimedout ', () => {
|
|
expect(gens.timeOutCase.next(unsuccessfulGasEstimationResult).value).toEqual(
|
|
put(estimateGasTimedout())
|
|
);
|
|
});
|
|
it('should call localGasEstimation', () => {
|
|
expect(gens.timeOutCase.next(estimateGasFailed()).value).toEqual(
|
|
call(localGasEstimation, payload)
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('when it throws', () => {
|
|
it('should catch and put estimateGasFailed', () => {
|
|
expect(gens.failCase.throw().value).toEqual(put(estimateGasFailed()));
|
|
});
|
|
|
|
it('should call localGasEstimation', () => {
|
|
expect(gens.failCase.next(estimateGasFailed()).value).toEqual(
|
|
call(localGasEstimation, payload)
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('localGasEstimation', () => {
|
|
const payload: any = {
|
|
mock1: 'mock1',
|
|
mock2: 'mock2'
|
|
};
|
|
const tx = {
|
|
getBaseFee: jest.fn()
|
|
};
|
|
const gasLimit = Wei('100');
|
|
|
|
const gen = localGasEstimation(payload);
|
|
it('should call makeTransaction with payload', () => {
|
|
expect(gen.next().value).toEqual(call(makeTransaction, payload));
|
|
});
|
|
|
|
it('should apply tx.getBaseFee', () => {
|
|
expect(gen.next(tx).value).toEqual(apply(tx, tx.getBaseFee));
|
|
});
|
|
|
|
it('should put setGasLimitField', () => {
|
|
expect(gen.next(gasLimit).value).toEqual(
|
|
put(
|
|
setGasLimitField({
|
|
raw: gasLimit.toString(),
|
|
value: gasLimit
|
|
})
|
|
)
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('setAddressMessageGasLimit*', () => {
|
|
const gens = cloneableGenerator(setAddressMessageGasLimit)();
|
|
const gen = gens.clone();
|
|
let noAutoGen: SagaIteratorClone;
|
|
let noMessageGen: SagaIteratorClone;
|
|
const addressMessage = {
|
|
gasLimit: 123456,
|
|
msg: 'Thanks for donating, er, investing in SCAM'
|
|
};
|
|
|
|
it('should select getAutoGasLimitEnabled', () => {
|
|
expect(gen.next().value).toEqual(select(getAutoGasLimitEnabled));
|
|
});
|
|
|
|
it('should select getCurrentToAddressMessage', () => {
|
|
noAutoGen = gen.clone();
|
|
expect(gen.next(true).value).toEqual(select(getCurrentToAddressMessage));
|
|
});
|
|
|
|
it('should put setGasLimitField', () => {
|
|
noMessageGen = gen.clone();
|
|
expect(gen.next(addressMessage).value).toEqual(
|
|
put(
|
|
setGasLimitField({
|
|
raw: addressMessage.gasLimit.toString(),
|
|
value: new BN(addressMessage.gasLimit)
|
|
})
|
|
)
|
|
);
|
|
});
|
|
|
|
it('should do nothing if getAutoGasLimitEnabled is false', () => {
|
|
noAutoGen.next(false);
|
|
expect(noAutoGen.next(addressMessage).done).toBeTruthy();
|
|
});
|
|
|
|
it('should do nothing if getCurrentToAddressMessage is undefined', () => {
|
|
expect(noMessageGen.next(undefined).done).toBeTruthy();
|
|
});
|
|
});
|