Uses timestamps for dates for Claims and Transactions #136

Merged
jessopb merged 1 commit from removeBlockShowForDates into master 2019-05-07 06:19:28 +02:00
7 changed files with 140 additions and 142 deletions

1
flow-typed/Claim.js vendored
View file

@ -31,6 +31,7 @@ declare type GenericClaim = {
decoded_claim: boolean, // claim made in accordance with sdk protobuf types decoded_claim: boolean, // claim made in accordance with sdk protobuf types
depth: number, // confirmations since tx depth: number, // confirmations since tx
effective_amount: number, // bid amount + supports effective_amount: number, // bid amount + supports
timestamp?: number, // date of transaction
has_signature: boolean, has_signature: boolean,
height: number, // block height the tx was confirmed height: number, // block height the tx was confirmed
hex: string, // `value` hex encoded hex: string, // `value` hex encoded

View file

@ -40,7 +40,6 @@ export const CHECK_ADDRESS_IS_MINE_COMPLETED = 'CHECK_ADDRESS_IS_MINE_COMPLETED'
export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED'; export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED';
export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED'; export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED';
export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED'; export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED';
export const FETCH_BLOCK_SUCCESS = 'FETCH_BLOCK_SUCCESS';
export const SUPPORT_TRANSACTION_STARTED = 'SUPPORT_TRANSACTION_STARTED'; export const SUPPORT_TRANSACTION_STARTED = 'SUPPORT_TRANSACTION_STARTED';
export const SUPPORT_TRANSACTION_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED'; export const SUPPORT_TRANSACTION_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED';
export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED'; export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED';

View file

@ -71,7 +71,6 @@ export {
doUpdateTotalBalance, doUpdateTotalBalance,
doTotalBalanceSubscribe, doTotalBalanceSubscribe,
doFetchTransactions, doFetchTransactions,
doFetchBlock,
doGetNewAddress, doGetNewAddress,
doCheckAddressIsMine, doCheckAddressIsMine,
doSendDraftTransaction, doSendDraftTransaction,
@ -111,6 +110,7 @@ export {
makeSelectClaimsInChannelForPage, makeSelectClaimsInChannelForPage,
makeSelectMetadataForUri, makeSelectMetadataForUri,
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectDateForUri,
makeSelectContentTypeForUri, makeSelectContentTypeForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectTotalItemsForChannel, makeSelectTotalItemsForChannel,
@ -177,7 +177,6 @@ export {
} from 'redux/selectors/search'; } from 'redux/selectors/search';
export { export {
makeSelectBlockDate,
selectBalance, selectBalance,
selectTotalBalance, selectTotalBalance,
selectTransactionsById, selectTransactionsById,

View file

@ -80,17 +80,6 @@ export function doFetchTransactions() {
}; };
} }
export function doFetchBlock(height) {
return dispatch => {
Lbry.block_show({ height }).then(block => {
dispatch({
type: ACTIONS.FETCH_BLOCK_SUCCESS,
data: { block },
});
});
};
}
export function doGetNewAddress() { export function doGetNewAddress() {
return dispatch => { return dispatch => {
dispatch({ dispatch({

View file

@ -183,18 +183,6 @@ reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = (state: WalletState, action) =>
sendingSupport: false, sendingSupport: false,
}); });
reducers[ACTIONS.FETCH_BLOCK_SUCCESS] = (state: WalletState, action) => {
const {
block,
block: { height },
} = action.data;
const blocks = Object.assign({}, state.blocks);
blocks[height] = block;
return Object.assign({}, state, { blocks });
};
reducers[ACTIONS.WALLET_STATUS_COMPLETED] = (state: WalletState, action) => reducers[ACTIONS.WALLET_STATUS_COMPLETED] = (state: WalletState, action) =>
Object.assign({}, state, { Object.assign({}, state, {
walletIsEncrypted: action.result, walletIsEncrypted: action.result,

View file

@ -178,6 +178,19 @@ export const makeSelectTitleForUri = (uri: string) =>
metadata => metadata && metadata.title metadata => metadata && metadata.title
); );
export const makeSelectDateForUri = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
const timestamp = claim && claim.timestamp ? claim.timestamp * 1000 : undefined;
if (!timestamp) {
return undefined;
}
const dateObj = new Date(timestamp);
return dateObj;
}
);
export const makeSelectContentTypeForUri = (uri: string) => export const makeSelectContentTypeForUri = (uri: string) =>
createSelector( createSelector(
makeSelectClaimForUri(uri), makeSelectClaimForUri(uri),

View file

@ -65,112 +65,130 @@ export const selectWalletLockSucceeded = createSelector(
state => state.walletLockSucceded state => state.walletLockSucceded
); );
export const selectWalletLockResult = createSelector(selectState, state => state.walletLockResult); export const selectWalletLockResult = createSelector(
selectState,
state => state.walletLockResult
);
export const selectBalance = createSelector(selectState, state => state.balance); export const selectBalance = createSelector(
selectState,
state => state.balance
);
export const selectTotalBalance = createSelector(selectState, state => state.totalBalance); export const selectTotalBalance = createSelector(
selectState,
state => state.totalBalance
);
export const selectTransactionsById = createSelector(selectState, state => state.transactions); export const selectTransactionsById = createSelector(
selectState,
state => state.transactions
);
export const selectTransactionItems = createSelector(selectTransactionsById, byId => { export const selectTransactionItems = createSelector(
const items = []; selectTransactionsById,
byId => {
const items = [];
Object.keys(byId).forEach(txid => { Object.keys(byId).forEach(txid => {
const tx = byId[txid]; const tx = byId[txid];
// ignore dust/fees // ignore dust/fees
// it is fee only txn if all infos are also empty // it is fee only txn if all infos are also empty
if ( if (
Math.abs(tx.value) === Math.abs(tx.fee) && Math.abs(tx.value) === Math.abs(tx.fee) &&
tx.claim_info.length === 0 && tx.claim_info.length === 0 &&
tx.support_info.length === 0 && tx.support_info.length === 0 &&
tx.update_info.length === 0 && tx.update_info.length === 0 &&
tx.abandon_info.length === 0 tx.abandon_info.length === 0
) { ) {
return; return;
} }
const append = []; const append = [];
append.push(
...tx.claim_info.map(item =>
Object.assign({}, tx, item, {
type: item.claim_name[0] === '@' ? TRANSACTIONS.CHANNEL : TRANSACTIONS.PUBLISH,
})
)
);
append.push(
...tx.support_info.map(item =>
Object.assign({}, tx, item, {
type: !item.is_tip ? TRANSACTIONS.SUPPORT : TRANSACTIONS.TIP,
})
)
);
append.push(
...tx.update_info.map(item => Object.assign({}, tx, item, { type: TRANSACTIONS.UPDATE }))
);
append.push(
...tx.abandon_info.map(item => Object.assign({}, tx, item, { type: TRANSACTIONS.ABANDON }))
);
if (!append.length) {
append.push( append.push(
Object.assign({}, tx, { ...tx.claim_info.map(item =>
type: tx.value < 0 ? TRANSACTIONS.SPEND : TRANSACTIONS.RECEIVE, Object.assign({}, tx, item, {
type: item.claim_name[0] === '@' ? TRANSACTIONS.CHANNEL : TRANSACTIONS.PUBLISH,
})
)
);
append.push(
...tx.support_info.map(item =>
Object.assign({}, tx, item, {
type: !item.is_tip ? TRANSACTIONS.SUPPORT : TRANSACTIONS.TIP,
})
)
);
append.push(
...tx.update_info.map(item => Object.assign({}, tx, item, { type: TRANSACTIONS.UPDATE }))
);
append.push(
...tx.abandon_info.map(item => Object.assign({}, tx, item, { type: TRANSACTIONS.ABANDON }))
);
if (!append.length) {
append.push(
Object.assign({}, tx, {
type: tx.value < 0 ? TRANSACTIONS.SPEND : TRANSACTIONS.RECEIVE,
})
);
}
items.push(
...append.map(item => {
// value on transaction, amount on outpoint
// amount is always positive, but should match sign of value
const balanceDelta = parseFloat(item.balance_delta);
const value = parseFloat(item.value);
const amount = balanceDelta || value;
const fee = parseFloat(tx.fee);
return {
txid,
timestamp: tx.timestamp,
date: tx.timestamp ? new Date(Number(tx.timestamp) * 1000) : null,
amount,
fee,
claim_id: item.claim_id,
claim_name: item.claim_name,
type: item.type || TRANSACTIONS.SPEND,
nout: item.nout,
confirmations: tx.confirmations,
};
}) })
); );
} });
items.push( return items.sort((tx1, tx2) => {
...append.map(item => { if (!tx1.timestamp && !tx2.timestamp) {
// value on transaction, amount on outpoint return 0;
// amount is always positive, but should match sign of value } else if (!tx1.timestamp && tx2.timestamp) {
const balanceDelta = parseFloat(item.balance_delta); return -1;
const value = parseFloat(item.value); } else if (tx1.timestamp && !tx2.timestamp) {
const amount = balanceDelta || value; return 1;
const fee = parseFloat(tx.fee); }
return { return tx2.timestamp - tx1.timestamp;
txid, });
timestamp: tx.timestamp, }
date: tx.timestamp ? new Date(Number(tx.timestamp) * 1000) : null, );
amount,
fee,
claim_id: item.claim_id,
claim_name: item.claim_name,
type: item.type || TRANSACTIONS.SPEND,
nout: item.nout,
confirmations: tx.confirmations,
};
})
);
});
return items.sort((tx1, tx2) => { export const selectRecentTransactions = createSelector(
if (!tx1.timestamp && !tx2.timestamp) { selectTransactionItems,
return 0; transactions => {
} else if (!tx1.timestamp && tx2.timestamp) { const threshold = new Date();
return -1; threshold.setDate(threshold.getDate() - 7);
} else if (tx1.timestamp && !tx2.timestamp) { return transactions.filter(transaction => {
return 1; if (!transaction.date) {
} return true; // pending transaction
}
return tx2.timestamp - tx1.timestamp; return transaction.date > threshold;
}); });
}); }
);
export const selectRecentTransactions = createSelector(selectTransactionItems, transactions => {
const threshold = new Date();
threshold.setDate(threshold.getDate() - 7);
return transactions.filter(transaction => {
if (!transaction.date) {
return true; // pending transaction
}
return transaction.date > threshold;
});
});
export const selectHasTransactions = createSelector( export const selectHasTransactions = createSelector(
selectTransactionItems, selectTransactionItems,
@ -182,9 +200,15 @@ export const selectIsFetchingTransactions = createSelector(
state => state.fetchingTransactions state => state.fetchingTransactions
); );
export const selectIsSendingSupport = createSelector(selectState, state => state.sendingSupport); export const selectIsSendingSupport = createSelector(
selectState,
state => state.sendingSupport
);
export const selectReceiveAddress = createSelector(selectState, state => state.receiveAddress); export const selectReceiveAddress = createSelector(
selectState,
state => state.receiveAddress
);
export const selectGettingNewAddress = createSelector( export const selectGettingNewAddress = createSelector(
selectState, selectState,
@ -211,30 +235,15 @@ export const selectDraftTransactionError = createSelector(
draft => draft.error draft => draft.error
); );
export const selectBlocks = createSelector(selectState, state => state.blocks); export const selectBlocks = createSelector(
selectState,
state => state.blocks
);
export const selectCurrentHeight = createSelector(selectState, state => state.latestBlock); export const selectCurrentHeight = createSelector(
selectState,
export const makeSelectBlockDate = block => state => state.latestBlock
createSelector(selectBlocks, selectCurrentHeight, (blocks, latestBlock) => { );
// If we have the block data, look at the actual date,
// If not, try to simulate it based on 2.5 minute blocks
// Adding this on 11/7/2018 because caling block_show for every claim is causing
// performance issues.
if (blocks && blocks[block]) {
return new Date(blocks[block].time * 1000);
}
// Pending claim
if (block < 1) {
return null;
}
const difference = latestBlock - block;
const msSincePublish = difference * 2.5 * 60 * 1000; // Number of blocks * 2.5 minutes in ms
const publishDate = Date.now() - msSincePublish;
return new Date(publishDate);
});
export const selectTransactionListFilter = createSelector( export const selectTransactionListFilter = createSelector(
selectState, selectState,