Utxo counts #374

Merged
jessopb merged 3 commits from utxoCounts into master 2021-01-05 18:16:05 +01:00
7 changed files with 406 additions and 70 deletions

213
dist/bundle.es.js vendored
View file

@ -100,6 +100,13 @@ const SET_TRANSACTION_LIST_FILTER = 'SET_TRANSACTION_LIST_FILTER';
const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT'; const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT';
const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT'; const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS'; const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
const FETCH_UTXO_COUNT_STARTED = 'FETCH_UTXO_COUNT_STARTED';
const FETCH_UTXO_COUNT_COMPLETED = 'FETCH_UTXO_COUNT_COMPLETED';
const FETCH_UTXO_COUNT_FAILED = 'FETCH_UTXO_COUNT_FAILED';
const DO_UTXO_CONSOLIDATE_STARTED = 'DO_UTXO_CONSOLIDATE_STARTED';
const DO_UTXO_CONSOLIDATE_COMPLETED = 'DO_UTXO_CONSOLIDATE_COMPLETED';
const DO_UTXO_CONSOLIDATE_FAILED = 'DO_UTXO_CONSOLIDATE_FAILED';
const PENDING_CONSOLIDATED_TXOS_UPDATED = 'PENDING_CONSOLIDATED_TXOS_UPDATED';
// Claims // Claims
const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED'; const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED';
@ -367,6 +374,13 @@ var action_types = /*#__PURE__*/Object.freeze({
UPDATE_CURRENT_HEIGHT: UPDATE_CURRENT_HEIGHT, UPDATE_CURRENT_HEIGHT: UPDATE_CURRENT_HEIGHT,
SET_DRAFT_TRANSACTION_AMOUNT: SET_DRAFT_TRANSACTION_AMOUNT, SET_DRAFT_TRANSACTION_AMOUNT: SET_DRAFT_TRANSACTION_AMOUNT,
SET_DRAFT_TRANSACTION_ADDRESS: SET_DRAFT_TRANSACTION_ADDRESS, SET_DRAFT_TRANSACTION_ADDRESS: SET_DRAFT_TRANSACTION_ADDRESS,
FETCH_UTXO_COUNT_STARTED: FETCH_UTXO_COUNT_STARTED,
FETCH_UTXO_COUNT_COMPLETED: FETCH_UTXO_COUNT_COMPLETED,
FETCH_UTXO_COUNT_FAILED: FETCH_UTXO_COUNT_FAILED,
DO_UTXO_CONSOLIDATE_STARTED: DO_UTXO_CONSOLIDATE_STARTED,
DO_UTXO_CONSOLIDATE_COMPLETED: DO_UTXO_CONSOLIDATE_COMPLETED,
DO_UTXO_CONSOLIDATE_FAILED: DO_UTXO_CONSOLIDATE_FAILED,
PENDING_CONSOLIDATED_TXOS_UPDATED: PENDING_CONSOLIDATED_TXOS_UPDATED,
RESOLVE_URIS_STARTED: RESOLVE_URIS_STARTED, RESOLVE_URIS_STARTED: RESOLVE_URIS_STARTED,
RESOLVE_URIS_COMPLETED: RESOLVE_URIS_COMPLETED, RESOLVE_URIS_COMPLETED: RESOLVE_URIS_COMPLETED,
FETCH_CHANNEL_CLAIMS_STARTED: FETCH_CHANNEL_CLAIMS_STARTED, FETCH_CHANNEL_CLAIMS_STARTED: FETCH_CHANNEL_CLAIMS_STARTED,
@ -1909,6 +1923,8 @@ const selectWalletEncryptSucceeded = reselect.createSelector(selectState, state
const selectPendingSupportTransactions = reselect.createSelector(selectState, state => state.pendingSupportTransactions); const selectPendingSupportTransactions = reselect.createSelector(selectState, state => state.pendingSupportTransactions);
const selectPendingOtherTransactions = reselect.createSelector(selectState, state => state.pendingConsolidateTxos);
const selectAbandonClaimSupportError = reselect.createSelector(selectState, state => state.abandonClaimSupportError); const selectAbandonClaimSupportError = reselect.createSelector(selectState, state => state.abandonClaimSupportError);
const makeSelectPendingAmountByUri = uri => reselect.createSelector(selectClaimIdsByUri, selectPendingSupportTransactions, (claimIdsByUri, pendingSupports) => { const makeSelectPendingAmountByUri = uri => reselect.createSelector(selectClaimIdsByUri, selectPendingSupportTransactions, (claimIdsByUri, pendingSupports) => {
@ -2098,6 +2114,12 @@ const selectFilteredTransactionCount = reselect.createSelector(selectFilteredTra
const selectIsWalletReconnecting = reselect.createSelector(selectState, state => state.walletReconnecting); const selectIsWalletReconnecting = reselect.createSelector(selectState, state => state.walletReconnecting);
const selectIsFetchingUtxoCounts = reselect.createSelector(selectState, state => state.fetchingUtxoCounts);
const selectIsConsolidatingUtxos = reselect.createSelector(selectState, state => state.consolidatingUtxos);
const selectUtxoCounts = reselect.createSelector(selectState, state => state.utxoCounts);
var _extends$2 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$2 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties$1(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _objectWithoutProperties$1(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
@ -2685,6 +2707,8 @@ function creditsToString(amount) {
var _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
const FIFTEEN_SECONDS = 15000; const FIFTEEN_SECONDS = 15000;
let walletBalancePromise = null; let walletBalancePromise = null;
function doUpdateBalance() { function doUpdateBalance() {
@ -2799,6 +2823,60 @@ function doFetchSupports(page = 1, pageSize = 99999) {
}; };
} }
function doFetchUtxoCounts() {
return (() => {
var _ref = _asyncToGenerator(function* (dispatch) {
dispatch({
type: FETCH_UTXO_COUNT_STARTED
});
let resultSets = yield Promise.all([lbryProxy.txo_list({ type: 'other', is_not_spent: true }), lbryProxy.txo_list({ type: 'support', is_not_spent: true })]);
const counts = {};
const paymentCount = resultSets[0]['total_items'];
const supportCount = resultSets[1]['total_items'];
counts['other'] = typeof paymentCount === 'number' ? paymentCount : 0;
counts['support'] = typeof supportCount === 'number' ? supportCount : 0;
dispatch({
type: FETCH_UTXO_COUNT_COMPLETED,
data: counts,
debug: { resultSets }
});
});
return function (_x) {
return _ref.apply(this, arguments);
};
})();
}
function doUtxoConsolidate() {
return (() => {
var _ref2 = _asyncToGenerator(function* (dispatch) {
dispatch({
type: DO_UTXO_CONSOLIDATE_STARTED
});
const results = yield lbryProxy.txo_spend({ type: 'other' });
const result = results[0];
dispatch({
type: PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: [result.txid] }
});
dispatch({
type: DO_UTXO_CONSOLIDATE_COMPLETED
});
dispatch(doCheckPendingTxs());
});
return function (_x2) {
return _ref2.apply(this, arguments);
};
})();
}
function doGetNewAddress() { function doGetNewAddress() {
return dispatch => { return dispatch => {
dispatch({ dispatch({
@ -3013,6 +3091,7 @@ function doWalletUnlock(password) {
}; };
} }
// Collect all tips for a claim
function doSupportAbandonForClaim(claimId, claimType, keep, preview) { function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
return dispatch => { return dispatch => {
if (preview) { if (preview) {
@ -3032,7 +3111,7 @@ function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
if (!preview) { if (!preview) {
dispatch({ dispatch({
type: ABANDON_CLAIM_SUPPORT_COMPLETED, type: ABANDON_CLAIM_SUPPORT_COMPLETED,
data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType } // add to pendingSupportTransactions, data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType }
}); });
dispatch(doCheckPendingTxs()); dispatch(doCheckPendingTxs());
} }
@ -3131,33 +3210,48 @@ function doUpdateBlockHeight() {
const doCheckPendingTxs = () => (dispatch, getState) => { const doCheckPendingTxs = () => (dispatch, getState) => {
const state = getState(); const state = getState();
const pendingTxsById = selectPendingSupportTransactions(state); // {} const pendingTxsById = selectPendingSupportTransactions(state); // {}
if (!Object.keys(pendingTxsById).length) { const pendingOtherTxes = selectPendingOtherTransactions(state);
if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) {
return; return;
} }
let txCheckInterval; let txCheckInterval;
const checkTxList = () => { const checkTxList = () => {
const state = getState(); const state = getState();
const pendingTxs = selectPendingSupportTransactions(state); // {} const pendingSupportTxs = selectPendingSupportTransactions(state); // {}
const pendingConsolidateTxes = selectPendingOtherTransactions(state);
const promises = []; const promises = [];
const newPendingTxes = {}; const newPendingTxes = {};
const noLongerPendingConsolidate = [];
const types = new Set([]); const types = new Set([]);
let changed = false; // { claimId: {txid: 123, amount 12.3}, }
Object.entries(pendingTxs).forEach(([claim, data]) => { const entries = Object.entries(pendingSupportTxs);
entries.forEach(([claim, data]) => {
promises.push(lbryProxy.transaction_show({ txid: data.txid })); promises.push(lbryProxy.transaction_show({ txid: data.txid }));
types.add(data.type); types.add(data.type);
}); });
if (pendingConsolidateTxes.length) {
pendingConsolidateTxes.forEach(txid => promises.push(lbryProxy.transaction_show({ txid })));
}
Promise.all(promises).then(txShows => { Promise.all(promises).then(txShows => {
let changed = false;
txShows.forEach(result => { txShows.forEach(result => {
if (result.height <= 0) { if (pendingConsolidateTxes.includes(result.txid)) {
const entries = Object.entries(pendingTxs); if (result.height > 0) {
const match = entries.find(entry => entry[1].txid === result.txid); noLongerPendingConsolidate.push(result.txid);
newPendingTxes[match[0]] = match[1]; }
} else { } else {
changed = true; if (result.height <= 0) {
const match = entries.find(entry => entry[1].txid === result.txid);
newPendingTxes[match[0]] = match[1];
} else {
changed = true;
}
} }
}); });
}).then(() => {
if (changed) { if (changed) {
dispatch({ dispatch({
type: PENDING_SUPPORTS_UPDATED, type: PENDING_SUPPORTS_UPDATED,
@ -3170,12 +3264,17 @@ const doCheckPendingTxs = () => (dispatch, getState) => {
dispatch(doFetchClaimListMine()); dispatch(doFetchClaimListMine());
} }
} }
if (Object.keys(newPendingTxes).length === 0) clearInterval(txCheckInterval); if (noLongerPendingConsolidate.length) {
}); dispatch({
type: PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: noLongerPendingConsolidate, remove: true }
});
}
if (!Object.keys(pendingTxsById).length) { if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) {
clearInterval(txCheckInterval); clearInterval(txCheckInterval);
} }
});
}; };
txCheckInterval = setInterval(() => { txCheckInterval = setInterval(() => {
@ -3193,7 +3292,7 @@ function batchActions(...actions) {
var _extends$5 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$5 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } function _asyncToGenerator$1(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) { function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) {
return (dispatch, getState) => { return (dispatch, getState) => {
@ -3229,7 +3328,7 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true)
const resolveInfo = {}; const resolveInfo = {};
return lbryProxy.resolve(_extends$5({ urls: urisToResolve }, options)).then((() => { return lbryProxy.resolve(_extends$5({ urls: urisToResolve }, options)).then((() => {
var _ref = _asyncToGenerator(function* (result) { var _ref = _asyncToGenerator$1(function* (result) {
let repostedResults = {}; let repostedResults = {};
const repostsToResolve = []; const repostsToResolve = [];
const fallbackResolveInfo = { const fallbackResolveInfo = {
@ -3248,6 +3347,7 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true)
} else { } else {
if (checkReposts) { if (checkReposts) {
if (uriResolveInfo.reposted_claim) { if (uriResolveInfo.reposted_claim) {
// $FlowFixMe
const repostUrl = uriResolveInfo.reposted_claim.permanent_url; const repostUrl = uriResolveInfo.reposted_claim.permanent_url;
if (!resolvingUris.includes(repostUrl)) { if (!resolvingUris.includes(repostUrl)) {
repostsToResolve.push(repostUrl); repostsToResolve.push(repostUrl);
@ -4299,7 +4399,7 @@ const selectTakeOverAmount = reselect.createSelector(selectState$3, selectMyClai
var _extends$7 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$7 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _asyncToGenerator$1(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } function _asyncToGenerator$2(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
const doResetThumbnailStatus = () => dispatch => { const doResetThumbnailStatus = () => dispatch => {
dispatch({ dispatch({
@ -4633,7 +4733,7 @@ const doCheckReflectingFiles = () => (dispatch, getState) => {
let reflectorCheckInterval; let reflectorCheckInterval;
const checkFileList = (() => { const checkFileList = (() => {
var _ref = _asyncToGenerator$1(function* () { var _ref = _asyncToGenerator$2(function* () {
const state = getState(); const state = getState();
const reflectingById = selectReflectingById(state); const reflectingById = selectReflectingById(state);
const ids = Object.keys(reflectingById); const ids = Object.keys(reflectingById);
@ -5818,10 +5918,16 @@ const defaultState$5 = {
transactionListFilter: 'all', transactionListFilter: 'all',
walletReconnecting: false, walletReconnecting: false,
txoFetchParams: {}, txoFetchParams: {},
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: undefined,
consolidatingUtxos: false,
txoPage: {}, txoPage: {},
fetchingTxos: false, fetchingTxos: false,
fetchingTxosError: undefined, fetchingTxosError: undefined,
pendingSupportTransactions: {}, pendingSupportTransactions: {},
pendingConsolidateTxos: [],
abandonClaimSupportError: undefined abandonClaimSupportError: undefined
}; };
@ -5865,6 +5971,57 @@ const walletReducer = handleActions({
fetchingTxosError: action.data fetchingTxosError: action.data
}); });
}, },
[FETCH_UTXO_COUNT_STARTED]: state => {
return _extends$d({}, state, {
fetchingUtxoCounts: true,
fetchingUtxoError: undefined
});
},
[FETCH_UTXO_COUNT_COMPLETED]: (state, action) => {
return _extends$d({}, state, {
utxoCounts: action.data,
fetchingUtxoCounts: false
});
},
[FETCH_UTXO_COUNT_FAILED]: (state, action) => {
return _extends$d({}, state, {
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: action.data
});
},
[DO_UTXO_CONSOLIDATE_STARTED]: state => {
return _extends$d({}, state, {
consolidatingUtxos: true
});
},
[DO_UTXO_CONSOLIDATE_COMPLETED]: (state, action) => {
return _extends$d({}, state, {
consolidatingUtxos: false
});
},
[DO_UTXO_CONSOLIDATE_FAILED]: (state, action) => {
return _extends$d({}, state, {
consolidatingUtxos: false
});
},
[PENDING_CONSOLIDATED_TXOS_UPDATED]: (state, action) => {
const pendingTxos = state.pendingConsolidateTxos;
const { txids, remove } = action.data;
if (remove) {
const newTxos = pendingTxos.filter(txo => !txids.includes(txo));
return _extends$d({}, state, { pendingConsolidateTxos: newTxos });
} else {
const newPendingSet = new Set([...pendingTxos, ...txids]);
return _extends$d({}, state, { pendingConsolidateTxos: Array.from(newPendingSet) });
}
},
[UPDATE_TXO_FETCH_PARAMS]: (state, action) => { [UPDATE_TXO_FETCH_PARAMS]: (state, action) => {
return _extends$d({}, state, { return _extends$d({}, state, {
@ -5909,7 +6066,7 @@ const walletReducer = handleActions({
return _extends$d({}, state, { return _extends$d({}, state, {
supports: byOutpoint, supports: byOutpoint,
abandoningSupportsById: currentlyAbandoning abandoningSupportsByOutpoint: currentlyAbandoning
}); });
}, },
@ -5926,7 +6083,12 @@ const walletReducer = handleActions({
}, },
[ABANDON_CLAIM_SUPPORT_COMPLETED]: (state, action) => { [ABANDON_CLAIM_SUPPORT_COMPLETED]: (state, action) => {
const { claimId, type, txid, effective } = action.data; const {
claimId,
type,
txid,
effective
} = action.data;
const pendingtxs = Object.assign({}, state.pendingSupportTransactions); const pendingtxs = Object.assign({}, state.pendingSupportTransactions);
pendingtxs[claimId] = { txid, type, effective }; pendingtxs[claimId] = { txid, type, effective };
@ -5944,7 +6106,6 @@ const walletReducer = handleActions({
}, },
[PENDING_SUPPORTS_UPDATED]: (state, action) => { [PENDING_SUPPORTS_UPDATED]: (state, action) => {
return _extends$d({}, state, { return _extends$d({}, state, {
pendingSupportTransactions: action.data pendingSupportTransactions: action.data
}); });
@ -6210,6 +6371,7 @@ exports.doFetchFileInfo = doFetchFileInfo;
exports.doFetchFileInfos = doFetchFileInfos; exports.doFetchFileInfos = doFetchFileInfos;
exports.doFetchTransactions = doFetchTransactions; exports.doFetchTransactions = doFetchTransactions;
exports.doFetchTxoPage = doFetchTxoPage; exports.doFetchTxoPage = doFetchTxoPage;
exports.doFetchUtxoCounts = doFetchUtxoCounts;
exports.doFileGet = doFileGet; exports.doFileGet = doFileGet;
exports.doFileList = doFileList; exports.doFileList = doFileList;
exports.doGetNewAddress = doGetNewAddress; exports.doGetNewAddress = doGetNewAddress;
@ -6239,6 +6401,7 @@ exports.doUpdateChannel = doUpdateChannel;
exports.doUpdatePublishForm = doUpdatePublishForm; exports.doUpdatePublishForm = doUpdatePublishForm;
exports.doUpdateTxoPageParams = doUpdateTxoPageParams; exports.doUpdateTxoPageParams = doUpdateTxoPageParams;
exports.doUploadThumbnail = doUploadThumbnail; exports.doUploadThumbnail = doUploadThumbnail;
exports.doUtxoConsolidate = doUtxoConsolidate;
exports.doWalletDecrypt = doWalletDecrypt; exports.doWalletDecrypt = doWalletDecrypt;
exports.doWalletEncrypt = doWalletEncrypt; exports.doWalletEncrypt = doWalletEncrypt;
exports.doWalletReconnect = doWalletReconnect; exports.doWalletReconnect = doWalletReconnect;
@ -6356,12 +6519,14 @@ exports.selectFilteredTransactionCount = selectFilteredTransactionCount;
exports.selectFilteredTransactions = selectFilteredTransactions; exports.selectFilteredTransactions = selectFilteredTransactions;
exports.selectGettingNewAddress = selectGettingNewAddress; exports.selectGettingNewAddress = selectGettingNewAddress;
exports.selectHasTransactions = selectHasTransactions; exports.selectHasTransactions = selectHasTransactions;
exports.selectIsConsolidatingUtxos = selectIsConsolidatingUtxos;
exports.selectIsFetchingClaimListMine = selectIsFetchingClaimListMine; exports.selectIsFetchingClaimListMine = selectIsFetchingClaimListMine;
exports.selectIsFetchingFileList = selectIsFetchingFileList; exports.selectIsFetchingFileList = selectIsFetchingFileList;
exports.selectIsFetchingFileListDownloadedOrPublished = selectIsFetchingFileListDownloadedOrPublished; exports.selectIsFetchingFileListDownloadedOrPublished = selectIsFetchingFileListDownloadedOrPublished;
exports.selectIsFetchingMyPurchases = selectIsFetchingMyPurchases; exports.selectIsFetchingMyPurchases = selectIsFetchingMyPurchases;
exports.selectIsFetchingTransactions = selectIsFetchingTransactions; exports.selectIsFetchingTransactions = selectIsFetchingTransactions;
exports.selectIsFetchingTxos = selectIsFetchingTxos; exports.selectIsFetchingTxos = selectIsFetchingTxos;
exports.selectIsFetchingUtxoCounts = selectIsFetchingUtxoCounts;
exports.selectIsResolvingPublishUris = selectIsResolvingPublishUris; exports.selectIsResolvingPublishUris = selectIsResolvingPublishUris;
exports.selectIsSendingSupport = selectIsSendingSupport; exports.selectIsSendingSupport = selectIsSendingSupport;
exports.selectIsStillEditing = selectIsStillEditing; exports.selectIsStillEditing = selectIsStillEditing;
@ -6382,6 +6547,7 @@ exports.selectMyPurchases = selectMyPurchases;
exports.selectMyPurchasesCount = selectMyPurchasesCount; exports.selectMyPurchasesCount = selectMyPurchasesCount;
exports.selectMyStreamUrlsCount = selectMyStreamUrlsCount; exports.selectMyStreamUrlsCount = selectMyStreamUrlsCount;
exports.selectPendingIds = selectPendingIds; exports.selectPendingIds = selectPendingIds;
exports.selectPendingOtherTransactions = selectPendingOtherTransactions;
exports.selectPendingSupportTransactions = selectPendingSupportTransactions; exports.selectPendingSupportTransactions = selectPendingSupportTransactions;
exports.selectPlayingUri = selectPlayingUri; exports.selectPlayingUri = selectPlayingUri;
exports.selectPublishFormValues = selectPublishFormValues; exports.selectPublishFormValues = selectPublishFormValues;
@ -6411,6 +6577,7 @@ exports.selectTxoPageParams = selectTxoPageParams;
exports.selectUpdateChannelError = selectUpdateChannelError; exports.selectUpdateChannelError = selectUpdateChannelError;
exports.selectUpdatingChannel = selectUpdatingChannel; exports.selectUpdatingChannel = selectUpdatingChannel;
exports.selectUrisLoading = selectUrisLoading; exports.selectUrisLoading = selectUrisLoading;
exports.selectUtxoCounts = selectUtxoCounts;
exports.selectWalletDecryptPending = selectWalletDecryptPending; exports.selectWalletDecryptPending = selectWalletDecryptPending;
exports.selectWalletDecryptResult = selectWalletDecryptResult; exports.selectWalletDecryptResult = selectWalletDecryptResult;
exports.selectWalletDecryptSucceeded = selectWalletDecryptSucceeded; exports.selectWalletDecryptSucceeded = selectWalletDecryptSucceeded;

View file

@ -79,6 +79,13 @@ export const SET_TRANSACTION_LIST_FILTER = 'SET_TRANSACTION_LIST_FILTER';
export const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT'; export const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT';
export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT'; export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS'; export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
export const FETCH_UTXO_COUNT_STARTED = 'FETCH_UTXO_COUNT_STARTED';
export const FETCH_UTXO_COUNT_COMPLETED = 'FETCH_UTXO_COUNT_COMPLETED';
export const FETCH_UTXO_COUNT_FAILED = 'FETCH_UTXO_COUNT_FAILED';
export const DO_UTXO_CONSOLIDATE_STARTED = 'DO_UTXO_CONSOLIDATE_STARTED';
export const DO_UTXO_CONSOLIDATE_COMPLETED = 'DO_UTXO_CONSOLIDATE_COMPLETED';
export const DO_UTXO_CONSOLIDATE_FAILED = 'DO_UTXO_CONSOLIDATE_FAILED';
export const PENDING_CONSOLIDATED_TXOS_UPDATED = 'PENDING_CONSOLIDATED_TXOS_UPDATED';
// Claims // Claims
export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED'; export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED';

View file

@ -120,6 +120,8 @@ export {
doUpdateBlockHeight, doUpdateBlockHeight,
doClearSupport, doClearSupport,
doSupportAbandonForClaim, doSupportAbandonForClaim,
doFetchUtxoCounts,
doUtxoConsolidate,
} from 'redux/actions/wallet'; } from 'redux/actions/wallet';
export { doPopulateSharedUserState, doPreferenceGet, doPreferenceSet } from 'redux/actions/sync'; export { doPopulateSharedUserState, doPreferenceGet, doPreferenceSet } from 'redux/actions/sync';
@ -313,4 +315,8 @@ export {
selectPendingSupportTransactions, selectPendingSupportTransactions,
selectAbandonClaimSupportError, selectAbandonClaimSupportError,
makeSelectPendingAmountByUri, makeSelectPendingAmountByUri,
selectIsFetchingUtxoCounts,
selectIsConsolidatingUtxos,
selectUtxoCounts,
selectPendingOtherTransactions,
} from 'redux/selectors/wallet'; } from 'redux/selectors/wallet';

View file

@ -64,7 +64,7 @@ export function doResolveUris(
} = {}; } = {};
return Lbry.resolve({ urls: urisToResolve, ...options }).then( return Lbry.resolve({ urls: urisToResolve, ...options }).then(
async (result: ResolveResponse) => { async(result: ResolveResponse) => {
let repostedResults = {}; let repostedResults = {};
const repostsToResolve = []; const repostsToResolve = [];
const fallbackResolveInfo = { const fallbackResolveInfo = {
@ -83,6 +83,7 @@ export function doResolveUris(
} else { } else {
if (checkReposts) { if (checkReposts) {
if (uriResolveInfo.reposted_claim) { if (uriResolveInfo.reposted_claim) {
// $FlowFixMe
const repostUrl = uriResolveInfo.reposted_claim.permanent_url; const repostUrl = uriResolveInfo.reposted_claim.permanent_url;
if (!resolvingUris.includes(repostUrl)) { if (!resolvingUris.includes(repostUrl)) {
repostsToResolve.push(repostUrl); repostsToResolve.push(repostUrl);

View file

@ -5,6 +5,7 @@ import {
selectBalance, selectBalance,
selectPendingSupportTransactions, selectPendingSupportTransactions,
selectTxoPageParams, selectTxoPageParams,
selectPendingOtherTransactions,
} from 'redux/selectors/wallet'; } from 'redux/selectors/wallet';
import { creditsToString } from 'util/format-credits'; import { creditsToString } from 'util/format-credits';
import { selectMyClaimsRaw } from 'redux/selectors/claims'; import { selectMyClaimsRaw } from 'redux/selectors/claims';
@ -128,6 +129,51 @@ export function doFetchSupports(page = 1, pageSize = 99999) {
}; };
} }
export function doFetchUtxoCounts() {
return async dispatch => {
dispatch({
type: ACTIONS.FETCH_UTXO_COUNT_STARTED,
});
let resultSets = await Promise.all([
Lbry.txo_list({ type: 'other', is_not_spent: true }),
Lbry.txo_list({ type: 'support', is_not_spent: true }),
]);
const counts = {};
const paymentCount = resultSets[0]['total_items'];
const supportCount = resultSets[1]['total_items'];
counts['other'] = typeof paymentCount === 'number' ? paymentCount : 0;
counts['support'] = typeof supportCount === 'number' ? supportCount : 0;
dispatch({
type: ACTIONS.FETCH_UTXO_COUNT_COMPLETED,
data: counts,
debug: { resultSets },
});
};
}
export function doUtxoConsolidate() {
return async dispatch => {
dispatch({
type: ACTIONS.DO_UTXO_CONSOLIDATE_STARTED,
});
const results = await Lbry.txo_spend({ type: 'other' });
const result = results[0];
dispatch({
type: ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: [result.txid] },
});
dispatch({
type: ACTIONS.DO_UTXO_CONSOLIDATE_COMPLETED,
});
dispatch(doCheckPendingTxs());
};
}
export function doGetNewAddress() { export function doGetNewAddress() {
return dispatch => { return dispatch => {
dispatch({ dispatch({
@ -382,6 +428,7 @@ export function doWalletLock() {
}; };
} }
// Collect all tips for a claim
export function doSupportAbandonForClaim(claimId, claimType, keep, preview) { export function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
return dispatch => { return dispatch => {
if (preview) { if (preview) {
@ -402,7 +449,7 @@ export function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
if (!preview) { if (!preview) {
dispatch({ dispatch({
type: ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED, type: ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED,
data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType }, // add to pendingSupportTransactions, data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType },
}); });
dispatch(doCheckPendingTxs()); dispatch(doCheckPendingTxs());
} }
@ -507,53 +554,71 @@ export function doUpdateBlockHeight() {
export const doCheckPendingTxs = () => (dispatch, getState) => { export const doCheckPendingTxs = () => (dispatch, getState) => {
const state = getState(); const state = getState();
const pendingTxsById = selectPendingSupportTransactions(state); // {} const pendingTxsById = selectPendingSupportTransactions(state); // {}
if (!Object.keys(pendingTxsById).length) { const pendingOtherTxes = selectPendingOtherTransactions(state);
if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) {
return; return;
} }
let txCheckInterval; let txCheckInterval;
const checkTxList = () => { const checkTxList = () => {
const state = getState(); const state = getState();
const pendingTxs = selectPendingSupportTransactions(state); // {} const pendingSupportTxs = selectPendingSupportTransactions(state); // {}
const pendingConsolidateTxes = selectPendingOtherTransactions(state);
const promises = []; const promises = [];
const newPendingTxes = {}; const newPendingTxes = {};
const noLongerPendingConsolidate = [];
const types = new Set([]); const types = new Set([]);
let changed = false; // { claimId: {txid: 123, amount 12.3}, }
Object.entries(pendingTxs).forEach(([claim, data]) => { const entries = Object.entries(pendingSupportTxs);
entries.forEach(([claim, data]) => {
promises.push(Lbry.transaction_show({ txid: data.txid })); promises.push(Lbry.transaction_show({ txid: data.txid }));
types.add(data.type); types.add(data.type);
}); });
if (pendingConsolidateTxes.length) {
pendingConsolidateTxes.forEach(txid => promises.push(Lbry.transaction_show({ txid })));
}
Promise.all(promises) Promise.all(promises).then(txShows => {
.then(txShows => { let changed = false;
txShows.forEach(result => { txShows.forEach(result => {
if (pendingConsolidateTxes.includes(result.txid)) {
if (result.height > 0) {
noLongerPendingConsolidate.push(result.txid);
}
} else {
if (result.height <= 0) { if (result.height <= 0) {
const entries = Object.entries(pendingTxs);
const match = entries.find(entry => entry[1].txid === result.txid); const match = entries.find(entry => entry[1].txid === result.txid);
newPendingTxes[match[0]] = match[1]; newPendingTxes[match[0]] = match[1];
} else { } else {
changed = true; changed = true;
} }
});
})
.then(() => {
if (changed) {
dispatch({
type: ACTIONS.PENDING_SUPPORTS_UPDATED,
data: newPendingTxes,
});
if (types.has('channel')) {
dispatch(doFetchChannelListMine());
}
if (types.has('stream')) {
dispatch(doFetchClaimListMine());
}
} }
if (Object.keys(newPendingTxes).length === 0) clearInterval(txCheckInterval);
}); });
if (!Object.keys(pendingTxsById).length) { if (changed) {
clearInterval(txCheckInterval); dispatch({
} type: ACTIONS.PENDING_SUPPORTS_UPDATED,
data: newPendingTxes,
});
if (types.has('channel')) {
dispatch(doFetchChannelListMine());
}
if (types.has('stream')) {
dispatch(doFetchClaimListMine());
}
}
if (noLongerPendingConsolidate.length) {
dispatch({
type: ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: noLongerPendingConsolidate, remove: true },
});
}
if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) {
clearInterval(txCheckInterval);
}
});
}; };
txCheckInterval = setInterval(() => { txCheckInterval = setInterval(() => {

View file

@ -45,10 +45,12 @@ type WalletState = {
walletLockResult: ?boolean, walletLockResult: ?boolean,
walletReconnecting: boolean, walletReconnecting: boolean,
txoFetchParams: {}, txoFetchParams: {},
utxoCounts: {},
txoPage: any, txoPage: any,
fetchingTxos: boolean, fetchingTxos: boolean,
fetchingTxosError?: string, fetchingTxosError?: string,
pendingSupportTransactions: {}, // { claimId: {txid: 123, amount 12.3}, } pendingSupportTransactions: {}, // { claimId: {txid: 123, amount 12.3}, }
pendingConsolidateTxos: Array<string>,
abandonClaimSupportError?: string, abandonClaimSupportError?: string,
}; };
@ -85,10 +87,16 @@ const defaultState = {
transactionListFilter: 'all', transactionListFilter: 'all',
walletReconnecting: false, walletReconnecting: false,
txoFetchParams: {}, txoFetchParams: {},
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: undefined,
consolidatingUtxos: false,
txoPage: {}, txoPage: {},
fetchingTxos: false, fetchingTxos: false,
fetchingTxosError: undefined, fetchingTxosError: undefined,
pendingSupportTransactions: {}, pendingSupportTransactions: {},
pendingConsolidateTxos: [],
abandonClaimSupportError: undefined, abandonClaimSupportError: undefined,
}; };
@ -138,6 +146,63 @@ export const walletReducer = handleActions(
fetchingTxosError: action.data, fetchingTxosError: action.data,
}; };
}, },
[ACTIONS.FETCH_UTXO_COUNT_STARTED]: (state: WalletState) => {
return {
...state,
fetchingUtxoCounts: true,
fetchingUtxoError: undefined,
};
},
[ACTIONS.FETCH_UTXO_COUNT_COMPLETED]: (state: WalletState, action) => {
return {
...state,
utxoCounts: action.data,
fetchingUtxoCounts: false,
};
},
[ACTIONS.FETCH_UTXO_COUNT_FAILED]: (state: WalletState, action) => {
return {
...state,
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: action.data,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_STARTED]: (state: WalletState) => {
return {
...state,
consolidatingUtxos: true,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_COMPLETED]: (state: WalletState, action) => {
return {
...state,
consolidatingUtxos: false,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_FAILED]: (state: WalletState, action) => {
return {
...state,
consolidatingUtxos: false,
};
},
[ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED]: (state: WalletState, action) => {
const pendingTxos = state.pendingConsolidateTxos;
const { txids, remove } = action.data;
if (remove) {
const newTxos = pendingTxos.filter(txo => !txids.includes(txo));
return { ...state, pendingConsolidateTxos: newTxos };
} else {
const newPendingSet = new Set([...pendingTxos, ...txids]);
return { ...state, pendingConsolidateTxos: Array.from(newPendingSet) };
}
},
[ACTIONS.UPDATE_TXO_FETCH_PARAMS]: (state: WalletState, action) => { [ACTIONS.UPDATE_TXO_FETCH_PARAMS]: (state: WalletState, action) => {
return { return {
@ -186,7 +251,7 @@ export const walletReducer = handleActions(
return { return {
...state, ...state,
supports: byOutpoint, supports: byOutpoint,
abandoningSupportsById: currentlyAbandoning, abandoningSupportsByOutpoint: currentlyAbandoning,
}; };
}, },
@ -205,10 +270,15 @@ export const walletReducer = handleActions(
}, },
[ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED]: (state: WalletState, action: any): WalletState => { [ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED]: (state: WalletState, action: any): WalletState => {
const { claimId, type, txid, effective }: { claimId: string, type: string, txid: string, effective: string } = action.data; const {
claimId,
type,
txid,
effective,
}: { claimId: string, type: string, txid: string, effective: string } = action.data;
const pendingtxs = Object.assign({}, state.pendingSupportTransactions); const pendingtxs = Object.assign({}, state.pendingSupportTransactions);
pendingtxs[claimId] = {txid, type, effective}; pendingtxs[claimId] = { txid, type, effective };
return { return {
...state, ...state,
@ -225,7 +295,6 @@ export const walletReducer = handleActions(
}, },
[ACTIONS.PENDING_SUPPORTS_UPDATED]: (state: WalletState, action: any): WalletState => { [ACTIONS.PENDING_SUPPORTS_UPDATED]: (state: WalletState, action: any): WalletState => {
return { return {
...state, ...state,
pendingSupportTransactions: action.data, pendingSupportTransactions: action.data,

View file

@ -26,21 +26,27 @@ export const selectPendingSupportTransactions = createSelector(
state => state.pendingSupportTransactions state => state.pendingSupportTransactions
); );
export const selectPendingOtherTransactions = createSelector(
selectState,
state => state.pendingConsolidateTxos
);
export const selectAbandonClaimSupportError = createSelector( export const selectAbandonClaimSupportError = createSelector(
selectState, selectState,
state => state.abandonClaimSupportError state => state.abandonClaimSupportError
); );
export const makeSelectPendingAmountByUri = (uri) => createSelector( export const makeSelectPendingAmountByUri = uri =>
selectClaimIdsByUri, createSelector(
selectPendingSupportTransactions, selectClaimIdsByUri,
(claimIdsByUri, pendingSupports) => { selectPendingSupportTransactions,
const uriEntry = Object.entries(claimIdsByUri).find(([u, cid]) => u === uri); (claimIdsByUri, pendingSupports) => {
const claimId = uriEntry && uriEntry[1]; const uriEntry = Object.entries(claimIdsByUri).find(([u, cid]) => u === uri);
const pendingSupport = claimId && pendingSupports[claimId]; const claimId = uriEntry && uriEntry[1];
return pendingSupport ? pendingSupport.effective : undefined; const pendingSupport = claimId && pendingSupports[claimId];
} return pendingSupport ? pendingSupport.effective : undefined;
); }
);
export const selectWalletEncryptResult = createSelector( export const selectWalletEncryptResult = createSelector(
selectState, selectState,
@ -328,27 +334,27 @@ export const selectTxoPageParams = createSelector(
export const selectTxoPage = createSelector( export const selectTxoPage = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.items) || [], state => (state.txoPage && state.txoPage.items) || []
); );
export const selectTxoPageNumber = createSelector( export const selectTxoPageNumber = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.page) || 1, state => (state.txoPage && state.txoPage.page) || 1
); );
export const selectTxoItemCount = createSelector( export const selectTxoItemCount = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.total_items) || 1, state => (state.txoPage && state.txoPage.total_items) || 1
); );
export const selectFetchingTxosError = createSelector( export const selectFetchingTxosError = createSelector(
selectState, selectState,
state => state.fetchingTxosError, state => state.fetchingTxosError
); );
export const selectIsFetchingTxos = createSelector( export const selectIsFetchingTxos = createSelector(
selectState, selectState,
state => state.fetchingTxos, state => state.fetchingTxos
); );
export const makeSelectFilteredTransactionsForPage = (page = 1) => export const makeSelectFilteredTransactionsForPage = (page = 1) =>
@ -379,3 +385,18 @@ export const selectIsWalletReconnecting = createSelector(
selectState, selectState,
state => state.walletReconnecting state => state.walletReconnecting
); );
export const selectIsFetchingUtxoCounts = createSelector(
selectState,
state => state.fetchingUtxoCounts
);
export const selectIsConsolidatingUtxos = createSelector(
selectState,
state => state.consolidatingUtxos
);
export const selectUtxoCounts = createSelector(
selectState,
state => state.utxoCounts
);