lbry-redux/src/redux/selectors/wallet.js
jessop 1e505184dc add txo list by params
fix set.slice() error

add txopage reducer

move txo constants to redux

abandon bug

abandon callback
2020-04-14 16:35:27 -04:00

381 lines
9.5 KiB
JavaScript

import { createSelector } from 'reselect';
import * as TRANSACTIONS from 'constants/transaction_types';
import { PAGE_SIZE, LATEST_PAGE_SIZE } from 'constants/transaction_list';
import { selectClaimIdsByUri } from 'redux/selectors/claims';
export const selectState = state => state.wallet || {};
export const selectWalletState = selectState;
export const selectWalletIsEncrypted = createSelector(
selectState,
state => state.walletIsEncrypted
);
export const selectWalletEncryptPending = createSelector(
selectState,
state => state.walletEncryptPending
);
export const selectWalletEncryptSucceeded = createSelector(
selectState,
state => state.walletEncryptSucceded
);
export const selectPendingSupportTransactions = createSelector(
selectState,
state => state.pendingSupportTransactions
);
export const selectAbandonClaimSupportError = createSelector(
selectState,
state => state.abandonClaimSupportError
);
export const makeSelectPendingAmountByUri = (uri) => createSelector(
selectClaimIdsByUri,
selectPendingSupportTransactions,
(claimIdsByUri, pendingSupports) => {
const uriEntry = Object.entries(claimIdsByUri).find(([u, cid]) => u === uri);
const claimId = uriEntry && uriEntry[1];
const pendingSupport = claimId && pendingSupports[claimId];
return pendingSupport ? pendingSupport.effective : undefined;
}
);
export const selectWalletEncryptResult = createSelector(
selectState,
state => state.walletEncryptResult
);
export const selectWalletDecryptPending = createSelector(
selectState,
state => state.walletDecryptPending
);
export const selectWalletDecryptSucceeded = createSelector(
selectState,
state => state.walletDecryptSucceded
);
export const selectWalletDecryptResult = createSelector(
selectState,
state => state.walletDecryptResult
);
export const selectWalletUnlockPending = createSelector(
selectState,
state => state.walletUnlockPending
);
export const selectWalletUnlockSucceeded = createSelector(
selectState,
state => state.walletUnlockSucceded
);
export const selectWalletUnlockResult = createSelector(
selectState,
state => state.walletUnlockResult
);
export const selectWalletLockPending = createSelector(
selectState,
state => state.walletLockPending
);
export const selectWalletLockSucceeded = createSelector(
selectState,
state => state.walletLockSucceded
);
export const selectWalletLockResult = createSelector(
selectState,
state => state.walletLockResult
);
export const selectBalance = createSelector(
selectState,
state => state.balance
);
export const selectTotalBalance = createSelector(
selectState,
state => state.totalBalance
);
export const selectReservedBalance = createSelector(
selectState,
state => state.reservedBalance
);
export const selectClaimsBalance = createSelector(
selectState,
state => state.claimsBalance
);
export const selectSupportsBalance = createSelector(
selectState,
state => state.supportsBalance
);
export const selectTipsBalance = createSelector(
selectState,
state => state.tipsBalance
);
export const selectTransactionsById = createSelector(
selectState,
state => state.transactions || {}
);
export const selectSupportsByOutpoint = createSelector(
selectState,
state => state.supports || {}
);
export const selectTotalSupports = createSelector(
selectSupportsByOutpoint,
byOutpoint => {
let total = parseFloat('0.0');
Object.values(byOutpoint).forEach(support => {
const { amount } = support;
total = amount ? total + parseFloat(amount) : total;
});
return total;
}
);
export const selectTransactionItems = createSelector(
selectTransactionsById,
byId => {
const items = [];
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;
}
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,
})
);
}
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,
};
})
);
});
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 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;
});
}
);
export const selectHasTransactions = createSelector(
selectTransactionItems,
transactions => transactions && transactions.length > 0
);
export const selectIsFetchingTransactions = createSelector(
selectState,
state => state.fetchingTransactions
);
export const selectIsSendingSupport = createSelector(
selectState,
state => state.sendingSupport
);
export const selectReceiveAddress = createSelector(
selectState,
state => state.receiveAddress
);
export const selectGettingNewAddress = createSelector(
selectState,
state => state.gettingNewAddress
);
export const selectDraftTransaction = createSelector(
selectState,
state => state.draftTransaction || {}
);
export const selectDraftTransactionAmount = createSelector(
selectDraftTransaction,
draft => draft.amount
);
export const selectDraftTransactionAddress = createSelector(
selectDraftTransaction,
draft => draft.address
);
export const selectDraftTransactionError = createSelector(
selectDraftTransaction,
draft => draft.error
);
export const selectBlocks = createSelector(
selectState,
state => state.blocks
);
export const selectCurrentHeight = createSelector(
selectState,
state => state.latestBlock
);
export const selectTransactionListFilter = createSelector(
selectState,
state => state.transactionListFilter || ''
);
export const selectFilteredTransactions = createSelector(
selectTransactionItems,
selectTransactionListFilter,
(transactions, filter) => {
return transactions.filter(transaction => {
return filter === TRANSACTIONS.ALL || filter === transaction.type;
});
}
);
export const selectTxoPageParams = createSelector(
selectState,
state => state.txoFetchParams
);
export const selectTxoPage = createSelector(
selectState,
state => (state.txoPage && state.txoPage.items) || [],
);
export const selectTxoPageNumber = createSelector(
selectState,
state => (state.txoPage && state.txoPage.page) || 1,
);
export const selectTxoItemCount = createSelector(
selectState,
state => (state.txoPage && state.txoPage.total_items) || 1,
);
export const selectFetchingTxosError = createSelector(
selectState,
state => state.fetchingTxosError,
);
export const selectIsFetchingTxos = createSelector(
selectState,
state => state.fetchingTxos,
);
export const makeSelectFilteredTransactionsForPage = (page = 1) =>
createSelector(
selectFilteredTransactions,
filteredTransactions => {
const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(PAGE_SIZE);
return filteredTransactions && filteredTransactions.length
? filteredTransactions.slice(start, end)
: [];
}
);
export const makeSelectLatestTransactions = createSelector(
selectTransactionItems,
transactions => {
return transactions && transactions.length ? transactions.slice(0, LATEST_PAGE_SIZE) : [];
}
);
export const selectFilteredTransactionCount = createSelector(
selectFilteredTransactions,
filteredTransactions => filteredTransactions.length
);
export const selectIsWalletReconnecting = createSelector(
selectState,
state => state.walletReconnecting
);