aitrean cf9887f21f Outstanding tasks to Productionize Tx (#1194)
* Verify and complete all branching saga logic tests for transaction stack.

* Write reducer tests for refactored transaction stack.

* Add selector tests. Some files still need to be debugged.

* Add snapshot test for fields, additional seelector testing.

* Remove fields snapshots.

* Remove ABIs from the TestState json

* Use redux state instead of raw json in selector testing.

* Fix merge issues.

* Remove log

* Fix state values.

* Change test value to wei.

* Last touchup.

* Fix buffer shape, change Wei typo, use reasonable wei values.

* Last touch up.
2018-03-08 12:03:45 -06:00

98 lines
3.2 KiB
TypeScript

import { AppState } from 'reducers';
import { getCurrentTo, getCurrentValue } from './current';
import { getFields } from './fields';
import { makeTransaction, IHexStrTransaction } from 'libs/transaction';
import EthTx from 'ethereumjs-tx';
import { getUnit } from 'selectors/transaction/meta';
import { reduceToValues, isFullTx } from 'selectors/transaction/helpers';
import {
getGasPrice,
getGasLimit,
getDataExists,
getSerializedTransaction,
getValidGasCost,
isEtherTransaction
} from 'selectors/transaction';
import { Wei } from 'libs/units';
import { getTransactionFields } from 'libs/transaction/utils/ether';
import { getNetworkConfig } from 'selectors/config';
const getTransactionState = (state: AppState) => state.transaction;
export interface IGetTransaction {
transaction: EthTx;
isFullTransaction: boolean; //if the user has filled all the fields
}
const getTransaction = (state: AppState): IGetTransaction => {
const currentTo = getCurrentTo(state);
const currentValue = getCurrentValue(state);
const transactionFields = getFields(state);
const unit = getUnit(state);
const reducedValues = reduceToValues(transactionFields);
const transaction: EthTx = makeTransaction(reducedValues);
const dataExists = getDataExists(state);
const validGasCost = getValidGasCost(state);
const isFullTransaction = isFullTx(
state,
transactionFields,
currentTo,
currentValue,
dataExists,
validGasCost,
unit
);
return { transaction, isFullTransaction };
};
const nonStandardTransaction = (state: AppState): boolean => {
const etherTransaction = isEtherTransaction(state);
const { isFullTransaction } = getTransaction(state);
const dataExists = getDataExists(state);
return isFullTransaction && dataExists && etherTransaction;
};
const getGasCost = (state: AppState) => {
const gasPrice = getGasPrice(state);
const gasLimit = getGasLimit(state);
return gasLimit.value ? gasPrice.value.mul(gasLimit.value) : Wei('0');
};
const serializedAndTransactionFieldsMatch = (state: AppState, isLocallySigned: boolean) => {
const serialzedTransaction = getSerializedTransaction(state);
const { transaction, isFullTransaction } = getTransaction(state);
if (!isFullTransaction || !serialzedTransaction) {
return false;
}
const t1 = getTransactionFields(transaction);
// inject chainId into t1 as it wont have it from the fields
const networkConfig = getNetworkConfig(state);
if (!networkConfig) {
return false;
}
const { chainId } = networkConfig;
t1.chainId = chainId;
const t2 = getTransactionFields(makeTransaction(serialzedTransaction));
const checkValidity = (tx: IHexStrTransaction) =>
Object.keys(tx).reduce(
(match, currField: keyof IHexStrTransaction) => match && t1[currField] === t2[currField],
true
);
//reduce both ways to make sure both are exact same
const transactionsMatch = checkValidity(t1) && checkValidity(t2);
// if its signed then verify the signature too
return transactionsMatch && isLocallySigned
? makeTransaction(serialzedTransaction).verifySignature()
: true;
};
export {
getTransaction,
getTransactionState,
getGasCost,
nonStandardTransaction,
serializedAndTransactionFieldsMatch
};