aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts/redux/reducer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website/ts/redux/reducer.ts')
-rw-r--r--packages/website/ts/redux/reducer.ts363
1 files changed, 363 insertions, 0 deletions
diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts
new file mode 100644
index 000000000..7723597cd
--- /dev/null
+++ b/packages/website/ts/redux/reducer.ts
@@ -0,0 +1,363 @@
+import * as _ from 'lodash';
+import {ZeroEx} from '0x.js';
+import BigNumber from 'bignumber.js';
+import {utils} from 'ts/utils/utils';
+import {
+ GenerateOrderSteps,
+ Side,
+ SideToAssetToken,
+ Direction,
+ BlockchainErrs,
+ SignatureData,
+ TokenByAddress,
+ TokenStateByAddress,
+ Order,
+ Action,
+ ActionTypes,
+ ScreenWidths,
+ ProviderType,
+ TokenState,
+} from 'ts/types';
+
+// Instead of defaulting the docs version to an empty string, we pre-populate it with
+// a valid version value. This does not need to be updated however, since onLoad, it
+// is always replaced with a value retrieved from our S3 bucket.
+const DEFAULT_DOCS_VERSION = '0.0.0';
+
+export interface State {
+ // Portal
+ blockchainErr: BlockchainErrs;
+ blockchainIsLoaded: boolean;
+ generateOrderStep: GenerateOrderSteps;
+ networkId: number;
+ orderExpiryTimestamp: BigNumber;
+ orderFillAmount: BigNumber;
+ orderTakerAddress: string;
+ orderSignatureData: SignatureData;
+ orderSalt: BigNumber;
+ nodeVersion: string;
+ screenWidth: ScreenWidths;
+ shouldBlockchainErrDialogBeOpen: boolean;
+ sideToAssetToken: SideToAssetToken;
+ tokenByAddress: TokenByAddress;
+ tokenStateByAddress: TokenStateByAddress;
+ userAddress: string;
+ userEtherBalance: BigNumber;
+ // Note: cache of supplied orderJSON in fill order step. Do not use for anything else.
+ userSuppliedOrderCache: Order;
+
+ // Docs
+ docsVersion: string;
+ availableDocVersions: string[];
+
+ // Shared
+ flashMessage: string|React.ReactNode;
+ providerType: ProviderType;
+ injectedProviderName: string;
+};
+
+const INITIAL_STATE: State = {
+ // Portal
+ blockchainErr: '',
+ blockchainIsLoaded: false,
+ generateOrderStep: GenerateOrderSteps.ChooseAssets,
+ networkId: undefined,
+ orderExpiryTimestamp: utils.initialOrderExpiryUnixTimestampSec(),
+ orderFillAmount: undefined,
+ orderSignatureData: {
+ hash: '',
+ r: '',
+ s: '',
+ v: 27,
+ },
+ orderTakerAddress: '',
+ orderSalt: ZeroEx.generatePseudoRandomSalt(),
+ nodeVersion: undefined,
+ screenWidth: utils.getScreenWidth(),
+ shouldBlockchainErrDialogBeOpen: false,
+ sideToAssetToken: {
+ [Side.deposit]: {},
+ [Side.receive]: {},
+ },
+ tokenByAddress: {},
+ tokenStateByAddress: {},
+ userAddress: '',
+ userEtherBalance: new BigNumber(0),
+ userSuppliedOrderCache: undefined,
+
+ // Docs
+ docsVersion: DEFAULT_DOCS_VERSION,
+ availableDocVersions: [DEFAULT_DOCS_VERSION],
+
+ // Shared
+ flashMessage: undefined,
+ providerType: ProviderType.INJECTED,
+ injectedProviderName: '',
+};
+
+export function reducer(state: State = INITIAL_STATE, action: Action) {
+ switch (action.type) {
+ // Portal
+ case ActionTypes.RESET_STATE:
+ return INITIAL_STATE;
+
+ case ActionTypes.UPDATE_ORDER_SALT: {
+ return _.assign({}, state, {
+ orderSalt: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_NODE_VERSION: {
+ return _.assign({}, state, {
+ nodeVersion: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_ORDER_FILL_AMOUNT: {
+ return _.assign({}, state, {
+ orderFillAmount: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN: {
+ return _.assign({}, state, {
+ shouldBlockchainErrDialogBeOpen: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_USER_ETHER_BALANCE: {
+ return _.assign({}, state, {
+ userEtherBalance: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_USER_SUPPLIED_ORDER_CACHE: {
+ return _.assign({}, state, {
+ userSuppliedOrderCache: action.data,
+ });
+ }
+
+ case ActionTypes.CLEAR_TOKEN_BY_ADDRESS: {
+ return _.assign({}, state, {
+ tokenByAddress: {},
+ });
+ }
+
+ case ActionTypes.ADD_TOKEN_TO_TOKEN_BY_ADDRESS: {
+ const newTokenByAddress = state.tokenByAddress;
+ newTokenByAddress[action.data.address] = action.data;
+ return _.assign({}, state, {
+ tokenByAddress: newTokenByAddress,
+ });
+ }
+
+ case ActionTypes.REMOVE_TOKEN_TO_TOKEN_BY_ADDRESS: {
+ const newTokenByAddress = state.tokenByAddress;
+ delete newTokenByAddress[action.data.address];
+ return _.assign({}, state, {
+ tokenByAddress: newTokenByAddress,
+ });
+ }
+
+ case ActionTypes.UPDATE_TOKEN_BY_ADDRESS: {
+ const tokenByAddress = state.tokenByAddress;
+ const tokens = action.data;
+ _.each(tokens, token => {
+ const updatedToken = _.assign({}, tokenByAddress[token.address], token);
+ tokenByAddress[token.address] = updatedToken;
+ });
+ return _.assign({}, state, {
+ tokenByAddress,
+ });
+ }
+
+ case ActionTypes.UPDATE_TOKEN_STATE_BY_ADDRESS: {
+ const tokenStateByAddress = state.tokenStateByAddress;
+ const updatedTokenStateByAddress = action.data;
+ _.each(updatedTokenStateByAddress, (tokenState: TokenState, address: string) => {
+ const updatedTokenState = _.assign({}, tokenStateByAddress[address], tokenState);
+ tokenStateByAddress[address] = updatedTokenState;
+ });
+ return _.assign({}, state, {
+ tokenStateByAddress,
+ });
+ }
+
+ case ActionTypes.REMOVE_FROM_TOKEN_STATE_BY_ADDRESS: {
+ const tokenStateByAddress = state.tokenStateByAddress;
+ const tokenAddress = action.data;
+ delete tokenStateByAddress[tokenAddress];
+ return _.assign({}, state, {
+ tokenStateByAddress,
+ });
+ }
+
+ case ActionTypes.REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS: {
+ const tokenStateByAddress = state.tokenStateByAddress;
+ const allowance = action.data.allowance;
+ const tokenAddress = action.data.address;
+ tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], {
+ allowance,
+ });
+ return _.assign({}, state, {
+ tokenStateByAddress,
+ });
+ }
+
+ case ActionTypes.REPLACE_TOKEN_BALANCE_BY_ADDRESS: {
+ const tokenStateByAddress = state.tokenStateByAddress;
+ const balance = action.data.balance;
+ const tokenAddress = action.data.address;
+ tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], {
+ balance,
+ });
+ return _.assign({}, state, {
+ tokenStateByAddress,
+ });
+ }
+
+ case ActionTypes.UPDATE_TOKEN_BALANCE_BY_ADDRESS: {
+ const tokenStateByAddress = state.tokenStateByAddress;
+ const balanceDelta = action.data.balanceDelta;
+ const tokenAddress = action.data.address;
+ const currBalance = tokenStateByAddress[tokenAddress].balance;
+ tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], {
+ balance: currBalance.plus(balanceDelta),
+ });
+ return _.assign({}, state, {
+ tokenStateByAddress,
+ });
+ }
+
+ case ActionTypes.UPDATE_ORDER_SIGNATURE_DATA: {
+ return _.assign({}, state, {
+ orderSignatureData: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_SCREEN_WIDTH: {
+ return _.assign({}, state, {
+ screenWidth: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_BLOCKCHAIN_IS_LOADED: {
+ return _.assign({}, state, {
+ blockchainIsLoaded: action.data,
+ });
+ }
+
+ case ActionTypes.BLOCKCHAIN_ERR_ENCOUNTERED: {
+ return _.assign({}, state, {
+ blockchainErr: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_NETWORK_ID: {
+ return _.assign({}, state, {
+ networkId: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_GENERATE_ORDER_STEP: {
+ const direction = action.data;
+ let nextGenerateOrderStep = state.generateOrderStep;
+ if (direction === Direction.forward) {
+ nextGenerateOrderStep += 1;
+ } else if (state.generateOrderStep !== 0) {
+ nextGenerateOrderStep -= 1;
+ }
+ return _.assign({}, state, {
+ generateOrderStep: nextGenerateOrderStep,
+ });
+ }
+
+ case ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN: {
+ const newSideToAssetToken = _.assign({}, state.sideToAssetToken, {
+ [action.data.side]: action.data.token,
+ });
+ return _.assign({}, state, {
+ sideToAssetToken: newSideToAssetToken,
+ });
+ }
+
+ case ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS: {
+ const newAssetToken = state.sideToAssetToken[action.data.side];
+ newAssetToken.address = action.data.address;
+ const newSideToAssetToken = _.assign({}, state.sideToAssetToken, {
+ [action.data.side]: newAssetToken,
+ });
+ return _.assign({}, state, {
+ sideToAssetToken: newSideToAssetToken,
+ });
+ }
+
+ case ActionTypes.SWAP_ASSET_TOKENS: {
+ const newSideToAssetToken = _.assign({}, state.sideToAssetToken, {
+ [Side.deposit]: state.sideToAssetToken[Side.receive],
+ [Side.receive]: state.sideToAssetToken[Side.deposit],
+ });
+ return _.assign({}, state, {
+ sideToAssetToken: newSideToAssetToken,
+ });
+ }
+
+ case ActionTypes.UPDATE_ORDER_EXPIRY: {
+ return _.assign({}, state, {
+ orderExpiryTimestamp: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_ORDER_TAKER_ADDRESS: {
+ return _.assign({}, state, {
+ orderTakerAddress: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_USER_ADDRESS: {
+ return _.assign({}, state, {
+ userAddress: action.data,
+ });
+ }
+
+ // Docs
+ case ActionTypes.UPDATE_LIBRARY_VERSION: {
+ return _.assign({}, state, {
+ docsVersion: action.data,
+ });
+ }
+ case ActionTypes.UPDATE_AVAILABLE_LIBRARY_VERSIONS: {
+ return _.assign({}, state, {
+ availableDocVersions: action.data,
+ });
+ }
+
+ // Shared
+ case ActionTypes.SHOW_FLASH_MESSAGE: {
+ return _.assign({}, state, {
+ flashMessage: action.data,
+ });
+ }
+
+ case ActionTypes.HIDE_FLASH_MESSAGE: {
+ return _.assign({}, state, {
+ flashMessage: undefined,
+ });
+ }
+
+ case ActionTypes.UPDATE_PROVIDER_TYPE: {
+ return _.assign({}, state, {
+ providerType: action.data,
+ });
+ }
+
+ case ActionTypes.UPDATE_INJECTED_PROVIDER_NAME: {
+ return _.assign({}, state, {
+ injectedProviderName: action.data,
+ });
+ }
+
+ default:
+ return state;
+ }
+}