Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
fix: flashing state handling
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Dec 2, 2020
1 parent 0353cd3 commit 0d1cf22
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 52 deletions.
5 changes: 1 addition & 4 deletions app/components/home/stacking-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ import {

type StackingCardProps = any;

export const StackingCard: FC<StackingCardProps> = props => {
const {} = props;

export const StackingCard: FC<StackingCardProps> = () => {
const { stackingDetails, stackerInfo, nextCycleInfo } = useSelector((state: RootState) => ({
stackingDetails: selectPoxInfo(state),
stackerInfo: selectStackerInfo(state),
nextCycleInfo: selectNextCycleInfo(state),
}));

// if (stackingDetails && stackerInfo && !stackingError && !nextCycleInfo?.isStackingCallPending)
return (
<Flex
flexDirection="column"
Expand Down
11 changes: 7 additions & 4 deletions app/modals/stacking/stacking-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import {
decryptSoftwareWallet,
selectWalletType,
} from '@store/keys';
import { selectCoreNodeInfo, selectPoxInfo } from '@store/stacking';
import { activeStackingTx, selectCoreNodeInfo, selectPoxInfo } from '@store/stacking';
import {
makeUnsignedContractCall,
StacksTransaction,
makeContractCall,
TransactionSigner,
createStacksPrivateKey,
} from '@stacks/transactions';
import { broadcastTransaction } from '@store/transaction';
import { broadcastTransaction, BroadcastTransactionArgs } from '@store/transaction';
import { selectActiveNodeApi } from '@store/stacks-node';
import { selectAddressBalance } from '@store/address';
import { LedgerConnectStep } from '@hooks/use-ledger';
Expand Down Expand Up @@ -170,10 +170,13 @@ export const StackingModal: FC<StackingModalProps> = ({ onClose, numCycles, poxA
const broadcastTx = async () => {
if (balance === null) return;

const broadcastActions = {
const broadcastActions: Omit<BroadcastTransactionArgs, 'transaction'> = {
amount: new BigNumber(balance),
isStackingCall: true,
onBroadcastSuccess: () => history.push(routes.HOME),
onBroadcastSuccess: txId => {
dispatch(activeStackingTx({ txId }));
history.push(routes.HOME);
},
onBroadcastFail: () => setStep(StackingModalStep.FailedContractCall),
};

Expand Down
27 changes: 11 additions & 16 deletions app/pages/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@ import {
fetchCoreDetails,
fetchStackerInfo,
fetchStackingInfo,
removeStackingTx,
selectActiveStackingTxId,
} from '@store/stacking';

export const App: FC = ({ children }) => {
const dispatch = useDispatch();

const { address, activeNode, pendingTxs } = useSelector((state: RootState) => ({
const { address, activeNode, pendingTxs, activeStackingTx } = useSelector((state: RootState) => ({
address: selectAddress(state),
activeNode: selectActiveNodeApi(state),
pendingTxs: selectPendingTransactions(state),
activeStackingTx: selectActiveStackingTxId(state),
}));

const initAppWithStxAddressInfo = useCallback(() => {
Expand Down Expand Up @@ -69,6 +72,7 @@ export const App: FC = ({ children }) => {
dispatch(fetchStackingInfo());
dispatch(fetchCoreDetails());
dispatch(fetchBlockTimeInfo());
dispatch(fetchStackerInfo(address));
}
}, [address, activeNode, initAppWithStxAddressInfo, dispatch]);

Expand All @@ -80,28 +84,19 @@ export const App: FC = ({ children }) => {
dispatch(fetchCoreDetails());
}, 5_000);

useEffect(() => {
if (address) dispatch(fetchStackerInfo(address));
}, [dispatch, address]);

useEffect(() => {
async function run() {
console.log('new stacking call');
const [firstTxId] = pendingTxs.filter(tx => tx.isStackingCall);
if (!firstTxId) return;
console.log({ firstTxId });
const result = await watchContractExecution({
if (!activeStackingTx || !address) return;
await watchContractExecution({
nodeUrl: activeNode.url,
txId: firstTxId.tx_id,
txId: activeStackingTx,
});
dispatch(fetchStackingInfo());
dispatch(fetchCoreDetails());
dispatch(fetchBlockTimeInfo());
console.log(result);
dispatch(fetchStackerInfo(address));
setTimeout(() => dispatch(removeStackingTx()), 2000);
}
void run();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pendingTxs]);
}, [activeStackingTx]);

useEffect(() => {
const wsUrl = new URL(activeNode.url);
Expand Down
13 changes: 10 additions & 3 deletions app/store/home/home.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { createSlice, createSelector } from '@reduxjs/toolkit';
import { selectAddressBalance } from '@store/address';
import { selectIsStackingCallPending } from '@store/pending-transaction';
import { selectLoadingStacking, selectPoxInfo, selectStackerInfo } from '@store/stacking';
import {
selectActiveStackingTxId,
selectLoadingStacking,
selectPoxInfo,
selectStackerInfo,
} from '@store/stacking';
import BigNumber from 'bignumber.js';

import { RootState } from '..';
Expand Down Expand Up @@ -64,13 +69,15 @@ const selectMeetsMinStackingThreshold = createSelector(

export const selectHomeCardState = createSelector(
selectLoadingCardResources,
selectActiveStackingTxId,
selectMeetsMinStackingThreshold,
selectIsStackingCallPending,
selectStackerInfo,
(loadingResources, meetsMinThreshold, stackingCallPending, stackerInfo) => {
(loadingResources, activeStackingTxId, meetsMinThreshold, stackingCallPending, stackerInfo) => {
if (loadingResources) return HomeCardState.LoadingResources;
if (!meetsMinThreshold) return HomeCardState.NotEnoughStx;
if (stackingCallPending) return HomeCardState.StackingPendingContactCall;
if (stackingCallPending || typeof activeStackingTxId === 'string')
return HomeCardState.StackingPendingContactCall;
if (stackerInfo?.isPreStackingPeriodStart) return HomeCardState.StackingPreCycle;
if (stackerInfo?.isCurrentlyStacking) return HomeCardState.StackingActive;
if (meetsMinThreshold) return HomeCardState.EligibleToParticipate;
Expand Down
8 changes: 7 additions & 1 deletion app/store/stacking/stacking.actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { createAsyncThunk, createAction } from '@reduxjs/toolkit';

import { selectActiveNodeApi } from '@store/stacks-node/stacks-node.reducer';
import { RootState } from '@store/index';
Expand Down Expand Up @@ -43,3 +43,9 @@ export const fetchStackerInfo = createAsyncThunk(
throw new Error();
}
);

export const activeStackingTx = createAction<{ txId: string }>(
'stacking/call-stacking-contract-tx'
);

export const removeStackingTx = createAction('stacking/remove-active-tx');
74 changes: 52 additions & 22 deletions app/store/stacking/stacking.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { createSlice, PayloadAction, createSelector } from '@reduxjs/toolkit';
import { RootState } from '..';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import { NETWORK } from '@constants/index';
import { StackerInfo, StackerInfoSuccess } from '@utils/stacking/pox';
import { selectIsStackingCallPending } from '@store/pending-transaction';
import {
fetchStackingInfo,
fetchCoreDetails,
fetchBlockTimeInfo,
fetchStackerInfo,
activeStackingTx,
removeStackingTx,
} from './stacking.actions';
import { NETWORK } from '@constants/index';
import { StackerInfo, StackerInfoSuccess } from '@utils/stacking/pox';
import { selectIsStackingCallPending } from '@store/pending-transaction';

export enum StackingStatus {
NotStacking = 'NotStacking',
Expand All @@ -26,15 +28,27 @@ export enum StackingStatus {
}

export interface StackingState {
initialRequestsComplete: Record<
'poxInfo' | 'coreNodeInfo' | 'blockTimeInfo' | 'stackerInfo',
boolean
>;
error: string | null;
contractCallTx: string | null;
poxInfo: CoreNodePoxResponse | null;
coreNodeInfo: CoreNodeInfoResponse | null;
blockTimeInfo: NetworkBlockTimesResponse | null;
stackerInfo: StackerInfoSuccess | null;
}

const initialState: StackingState = {
initialRequestsComplete: {
poxInfo: false,
coreNodeInfo: false,
blockTimeInfo: false,
stackerInfo: false,
},
error: null,
contractCallTx: null,
poxInfo: null,
coreNodeInfo: null,
blockTimeInfo: null,
Expand All @@ -46,27 +60,42 @@ export const stackingSlice = createSlice({
initialState,
reducers: {},
extraReducers: {
[fetchStackingInfo.fulfilled.toString()]: (state, a: PayloadAction<CoreNodePoxResponse>) => {
state.poxInfo = a.payload;
[fetchStackingInfo.fulfilled.toString()]: (
state,
action: PayloadAction<CoreNodePoxResponse>
) => {
state.initialRequestsComplete.poxInfo = true;
state.poxInfo = action.payload;
},
[fetchCoreDetails.fulfilled.toString()]: (state, a: PayloadAction<CoreNodeInfoResponse>) => {
state.coreNodeInfo = a.payload;
[fetchCoreDetails.fulfilled.toString()]: (
state,
action: PayloadAction<CoreNodeInfoResponse>
) => {
state.initialRequestsComplete.coreNodeInfo = true;
state.coreNodeInfo = action.payload;
},
[fetchBlockTimeInfo.fulfilled.toString()]: (
state,
a: PayloadAction<NetworkBlockTimesResponse>
action: PayloadAction<NetworkBlockTimesResponse>
) => {
state.blockTimeInfo = a.payload;
state.initialRequestsComplete.blockTimeInfo = true;
state.blockTimeInfo = action.payload;
},
[fetchStackerInfo.fulfilled.toString()]: (state, a: PayloadAction<StackerInfo>) => {
// if (a.payload === )
if ('error' in a.payload) {
state.error = a.payload.error;
[fetchStackerInfo.fulfilled.toString()]: (state, action: PayloadAction<StackerInfo>) => {
state.initialRequestsComplete.stackerInfo = true;
if ('error' in action.payload) {
state.error = action.payload.error;
return;
}
state.stackerInfo = a.payload;
state.stackerInfo = action.payload;
state.error = null;
},
[activeStackingTx.toString()]: (state, action: PayloadAction<{ txId: string }>) => {
state.contractCallTx = action.payload.txId;
},
[removeStackingTx.toString()]: state => {
state.contractCallTx = null;
},
},
});

Expand All @@ -81,14 +110,15 @@ export const selectBlockTimeInfo = createSelector(

export const selectStackingError = createSelector(selectStackingState, state => state.error);

export const selectLoadingStacking = createSelector(selectStackingState, state => {
return (
state.coreNodeInfo === null &&
state.poxInfo === null &&
state.error === null &&
state.stackerInfo === null
);
});
export const selectLoadingStacking = createSelector(
selectStackingState,
state => !Object.values(state.initialRequestsComplete).every(value => value === true)
);

export const selectActiveStackingTxId = createSelector(
selectStackingState,
state => state.contractCallTx
);

export const selectPoxInfo = createSelector(selectStackingState, state => state.poxInfo);

Expand Down
3 changes: 1 addition & 2 deletions app/store/transaction/transaction.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { safelyFormatHexTxid } from '@utils/safe-handle-txid';
import { addPendingTransaction } from '@store/pending-transaction';
import { Dispatch, GetState } from '@store/index';
import { selectActiveNodeApi } from '@store/stacks-node';
import { isStackingTx } from '../../utils/tx-utils';

export const pendingTransactionSuccessful = createAction<Transaction>(
'transactions/pending-transaction-successful'
Expand Down Expand Up @@ -54,7 +53,7 @@ export const broadcastTxFail = createAction<BroadcastTxFail>(
'transactions/broadcast-transactions-fail'
);

interface BroadcastTransactionArgs {
export interface BroadcastTransactionArgs {
transaction: StacksTransaction;
amount: BigNumber;
isStackingCall?: boolean;
Expand Down

0 comments on commit 0d1cf22

Please sign in to comment.