Uses timestamps for dates for Claims and Transactions #136
7 changed files with 140 additions and 142 deletions
1
flow-typed/Claim.js
vendored
1
flow-typed/Claim.js
vendored
|
@ -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
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue