diff --git a/flow-typed/Claim.js b/flow-typed/Claim.js index 548000e..8bdd33c 100644 --- a/flow-typed/Claim.js +++ b/flow-typed/Claim.js @@ -31,6 +31,7 @@ declare type GenericClaim = { decoded_claim: boolean, // claim made in accordance with sdk protobuf types depth: number, // confirmations since tx effective_amount: number, // bid amount + supports + timestamp?: number, // date of transaction has_signature: boolean, height: number, // block height the tx was confirmed hex: string, // `value` hex encoded diff --git a/src/constants/action_types.js b/src/constants/action_types.js index a01c6ef..37a94cc 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -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_COMPLETED = 'SEND_TRANSACTION_COMPLETED'; 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_COMPLETED = 'SUPPORT_TRANSACTION_COMPLETED'; export const SUPPORT_TRANSACTION_FAILED = 'SUPPORT_TRANSACTION_FAILED'; diff --git a/src/index.js b/src/index.js index a378626..90989d0 100644 --- a/src/index.js +++ b/src/index.js @@ -71,7 +71,6 @@ export { doUpdateTotalBalance, doTotalBalanceSubscribe, doFetchTransactions, - doFetchBlock, doGetNewAddress, doCheckAddressIsMine, doSendDraftTransaction, @@ -111,6 +110,7 @@ export { makeSelectClaimsInChannelForPage, makeSelectMetadataForUri, makeSelectTitleForUri, + makeSelectDateForUri, makeSelectContentTypeForUri, makeSelectIsUriResolving, makeSelectTotalItemsForChannel, @@ -178,7 +178,6 @@ export { } from 'redux/selectors/search'; export { - makeSelectBlockDate, selectBalance, selectTotalBalance, selectTransactionsById, diff --git a/src/redux/actions/wallet.js b/src/redux/actions/wallet.js index 74aa062..cdcd816 100644 --- a/src/redux/actions/wallet.js +++ b/src/redux/actions/wallet.js @@ -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() { return dispatch => { dispatch({ diff --git a/src/redux/reducers/wallet.js b/src/redux/reducers/wallet.js index 308c5e7..5e9061b 100644 --- a/src/redux/reducers/wallet.js +++ b/src/redux/reducers/wallet.js @@ -183,18 +183,6 @@ reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = (state: WalletState, action) => 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) => Object.assign({}, state, { walletIsEncrypted: action.result, diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 5686127..7fcfed1 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -178,6 +178,19 @@ export const makeSelectTitleForUri = (uri: string) => 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) => createSelector( makeSelectClaimForUri(uri), diff --git a/src/redux/selectors/wallet.js b/src/redux/selectors/wallet.js index af5d340..a79bfc4 100644 --- a/src/redux/selectors/wallet.js +++ b/src/redux/selectors/wallet.js @@ -65,112 +65,130 @@ export const selectWalletLockSucceeded = createSelector( 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 => { - const items = []; +export const selectTransactionItems = createSelector( + selectTransactionsById, + byId => { + const items = []; - Object.keys(byId).forEach(txid => { - const tx = byId[txid]; + Object.keys(byId).forEach(txid => { + const tx = byId[txid]; - // ignore dust/fees - // it is fee only txn if all infos are also empty - if ( - Math.abs(tx.value) === Math.abs(tx.fee) && - tx.claim_info.length === 0 && - tx.support_info.length === 0 && - tx.update_info.length === 0 && - tx.abandon_info.length === 0 - ) { - return; - } + // ignore dust/fees + // it is fee only txn if all infos are also empty + if ( + Math.abs(tx.value) === Math.abs(tx.fee) && + tx.claim_info.length === 0 && + tx.support_info.length === 0 && + tx.update_info.length === 0 && + tx.abandon_info.length === 0 + ) { + 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( - Object.assign({}, tx, { - type: tx.value < 0 ? TRANSACTIONS.SPEND : TRANSACTIONS.RECEIVE, + ...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( + 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( - ...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 items.sort((tx1, tx2) => { + if (!tx1.timestamp && !tx2.timestamp) { + return 0; + } else if (!tx1.timestamp && tx2.timestamp) { + return -1; + } else if (tx1.timestamp && !tx2.timestamp) { + return 1; + } - 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, - }; - }) - ); - }); + return tx2.timestamp - tx1.timestamp; + }); + } +); - return items.sort((tx1, tx2) => { - if (!tx1.timestamp && !tx2.timestamp) { - return 0; - } else if (!tx1.timestamp && tx2.timestamp) { - return -1; - } else if (tx1.timestamp && !tx2.timestamp) { - return 1; - } +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 tx2.timestamp - tx1.timestamp; - }); -}); - -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; - }); -}); + return transaction.date > threshold; + }); + } +); export const selectHasTransactions = createSelector( selectTransactionItems, @@ -182,9 +200,15 @@ export const selectIsFetchingTransactions = createSelector( 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( selectState, @@ -211,30 +235,15 @@ export const selectDraftTransactionError = createSelector( 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 makeSelectBlockDate = block => - 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 selectCurrentHeight = createSelector( + selectState, + state => state.latestBlock +); export const selectTransactionListFilter = createSelector( selectState,