Feat txo paginate #299

Merged
jessopb merged 3 commits from feat-txo-paginate into master 2020-04-15 16:21:38 +02:00
12 changed files with 577 additions and 36 deletions

276
dist/bundle.es.js vendored
View file

@ -58,6 +58,10 @@ const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED';
const GET_NEW_ADDRESS_COMPLETED = 'GET_NEW_ADDRESS_COMPLETED';
const FETCH_TRANSACTIONS_STARTED = 'FETCH_TRANSACTIONS_STARTED';
const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED';
const FETCH_TXO_PAGE_STARTED = 'FETCH_TXO_PAGE_STARTED';
const FETCH_TXO_PAGE_COMPLETED = 'FETCH_TXO_PAGE_COMPLETED';
const FETCH_TXO_PAGE_FAILED = 'FETCH_TXO_PAGE_FAILED';
const UPDATE_TXO_FETCH_PARAMS = 'UPDATE_TXO_FETCH_PARAMS';
const FETCH_SUPPORTS_STARTED = 'FETCH_SUPPORTS_STARTED';
const FETCH_SUPPORTS_COMPLETED = 'FETCH_SUPPORTS_COMPLETED';
const ABANDON_SUPPORT_STARTED = 'ABANDON_SUPPORT_STARTED';
@ -328,6 +332,10 @@ var action_types = /*#__PURE__*/Object.freeze({
GET_NEW_ADDRESS_COMPLETED: GET_NEW_ADDRESS_COMPLETED,
FETCH_TRANSACTIONS_STARTED: FETCH_TRANSACTIONS_STARTED,
FETCH_TRANSACTIONS_COMPLETED: FETCH_TRANSACTIONS_COMPLETED,
FETCH_TXO_PAGE_STARTED: FETCH_TXO_PAGE_STARTED,
FETCH_TXO_PAGE_COMPLETED: FETCH_TXO_PAGE_COMPLETED,
FETCH_TXO_PAGE_FAILED: FETCH_TXO_PAGE_FAILED,
UPDATE_TXO_FETCH_PARAMS: UPDATE_TXO_FETCH_PARAMS,
FETCH_SUPPORTS_STARTED: FETCH_SUPPORTS_STARTED,
FETCH_SUPPORTS_COMPLETED: FETCH_SUPPORTS_COMPLETED,
ABANDON_SUPPORT_STARTED: ABANDON_SUPPORT_STARTED,
@ -749,6 +757,83 @@ var transaction_list = /*#__PURE__*/Object.freeze({
LATEST_PAGE_SIZE: LATEST_PAGE_SIZE
});
const PENDING = 'pending';
const DONE = 'done';
const READY$1 = 'ready';
const ERROR = 'error';
var abandon_txo_states = /*#__PURE__*/Object.freeze({
PENDING: PENDING,
DONE: DONE,
READY: READY$1,
ERROR: ERROR
});
const ACTIVE = 'active'; // spent, active, all
const TYPE = 'type'; // all, payment, support, channel, stream, repost
const SUB_TYPE = 'subtype'; // other, purchase, tip
const PAGE_SIZE$2 = 'page_size';
const PAGE = 'page';
const ALL$1 = 'all';
// dropdown types
const SENT = 'sent';
const RECEIVED = 'received';
const SUPPORT$1 = 'support';
const CHANNEL$2 = 'channel';
const PUBLISH$2 = 'publish';
const REPOST = 'repost';
const DROPDOWN_TYPES = [ALL$1, SENT, RECEIVED, SUPPORT$1, CHANNEL$2, PUBLISH$2, REPOST];
// dropdown subtypes
const TIP$1 = 'tip';
const PURCHASE = 'purchase';
const PAYMENT = 'payment';
const DROPDOWN_SUBTYPES = [ALL$1, TIP$1, PURCHASE, PAYMENT];
// rpc params
const TX_TYPE = 'type'; // = other, stream, repost, channel, support, purchase
const IS_SPENT = 'is_spent';
const IS_NOT_SPENT = 'is_not_spent';
const IS_MY_INPUT = 'is_my_input';
const IS_MY_OUTPUT = 'is_my_output';
const IS_NOT_MY_INPUT = 'is_not_my_input';
const IS_NOT_MY_OUTPUT = 'is_not_my_output'; // use to further distinguish payments to self / from self.
// sdk unique types
const OTHER$1 = 'other';
const STREAM = 'stream';
const PAGE_SIZE_DEFAULT = 20;
var txo_list = /*#__PURE__*/Object.freeze({
ACTIVE: ACTIVE,
TYPE: TYPE,
SUB_TYPE: SUB_TYPE,
PAGE_SIZE: PAGE_SIZE$2,
PAGE: PAGE,
ALL: ALL$1,
SENT: SENT,
RECEIVED: RECEIVED,
SUPPORT: SUPPORT$1,
CHANNEL: CHANNEL$2,
PUBLISH: PUBLISH$2,
REPOST: REPOST,
DROPDOWN_TYPES: DROPDOWN_TYPES,
TIP: TIP$1,
PURCHASE: PURCHASE,
PAYMENT: PAYMENT,
DROPDOWN_SUBTYPES: DROPDOWN_SUBTYPES,
TX_TYPE: TX_TYPE,
IS_SPENT: IS_SPENT,
IS_NOT_SPENT: IS_NOT_SPENT,
IS_MY_INPUT: IS_MY_INPUT,
IS_MY_OUTPUT: IS_MY_OUTPUT,
IS_NOT_MY_INPUT: IS_NOT_MY_INPUT,
IS_NOT_MY_OUTPUT: IS_NOT_MY_OUTPUT,
OTHER: OTHER$1,
STREAM: STREAM,
PAGE_SIZE_DEFAULT: PAGE_SIZE_DEFAULT
});
const SPEECH_STATUS = 'https://spee.ch/api/config/site/publishing';
const SPEECH_PUBLISH = 'https://spee.ch/api/claim/publish';
@ -1966,6 +2051,18 @@ const selectFilteredTransactions = reselect.createSelector(selectTransactionItem
});
});
const selectTxoPageParams = reselect.createSelector(selectState$1, state => state.txoFetchParams);
const selectTxoPage = reselect.createSelector(selectState$1, state => state.txoPage && state.txoPage.items || []);
const selectTxoPageNumber = reselect.createSelector(selectState$1, state => state.txoPage && state.txoPage.page || 1);
const selectTxoItemCount = reselect.createSelector(selectState$1, state => state.txoPage && state.txoPage.total_items || 1);
const selectFetchingTxosError = reselect.createSelector(selectState$1, state => state.fetchingTxosError);
const selectIsFetchingTxos = reselect.createSelector(selectState$1, state => state.fetchingTxos);
const makeSelectFilteredTransactionsForPage = (page = 1) => reselect.createSelector(selectFilteredTransactions, filteredTransactions => {
const start = (Number(page) - 1) * Number(PAGE_SIZE$1);
const end = Number(page) * Number(PAGE_SIZE$1);
@ -2591,6 +2688,40 @@ function doFetchTransactions(page = 1, pageSize = 99999) {
};
}
function doFetchTxoPage() {
return (dispatch, getState) => {
dispatch({
type: FETCH_TXO_PAGE_STARTED
});
const state = getState();
const queryParams = selectTxoPageParams(state);
lbryProxy.txo_list(queryParams).then(res => {
dispatch({
type: FETCH_TXO_PAGE_COMPLETED,
data: res
});
}).catch(e => {
dispatch({
type: FETCH_TXO_PAGE_COMPLETED,
data: e.message
});
});
};
}
function doUpdateTxoPageParams(params) {
return dispatch => {
dispatch({
type: UPDATE_TXO_FETCH_PARAMS,
data: params
});
dispatch(doFetchTxoPage());
};
}
function doFetchSupports(page = 1, pageSize = 99999) {
return dispatch => {
dispatch({
@ -3081,6 +3212,79 @@ function doFetchClaimListMine(page = 1, pageSize = 99999, resolve = true) {
};
}
function doAbandonTxo(txo, cb) {
return dispatch => {
if (cb) cb(PENDING);
const isClaim = txo.type === 'claim';
const isSupport = txo.type === 'support' && txo.is_my_input === true;
const isTip = txo.type === 'support' && txo.is_my_input === false;
const data = isClaim ? { claimId: txo.claim_id } : { outpoint: `${txo.txid}:${txo.nout}` };
const startedActionType = isClaim ? ABANDON_CLAIM_STARTED : ABANDON_SUPPORT_STARTED;
const completedActionType = isClaim ? ABANDON_CLAIM_SUCCEEDED : ABANDON_SUPPORT_COMPLETED;
dispatch({
type: startedActionType,
data
});
const errorCallback = () => {
if (cb) cb(ERROR);
dispatch(doToast({
message: isClaim ? 'Error abandoning your claim/support' : 'Error unlocking your tip',
isError: true
}));
};
const successCallback = () => {
dispatch({
type: completedActionType,
data
});
let abandonMessage;
if (isClaim) {
abandonMessage = __('Successfully abandoned your claim.');
} else if (isSupport) {
abandonMessage = __('Successfully abandoned your support.');
} else {
abandonMessage = __('Successfully unlocked your tip!');
}
if (cb) cb(DONE);
dispatch(doToast({
message: abandonMessage
}));
};
const abandonParams = {
blocking: true
};
if (isClaim) {
abandonParams['claim_id'] = txo.claim_id;
} else {
abandonParams['txid'] = txo.txid;
abandonParams['nout'] = txo.nout;
}
let method;
if (isSupport || isTip) {
method = 'support_abandon';
} else if (isClaim) {
const { normalized_name: claimName } = txo;
method = claimName.startsWith('@') ? 'channel_abandon' : 'stream_abandon';
}
if (!method) {
console.error('No "method" chosen for claim or support abandon');
return;
}
lbryProxy[method](abandonParams).then(successCallback, errorCallback);
};
}
function doAbandonClaim(txid, nout) {
const outpoint = `${txid}:${nout}`;
@ -3124,23 +3328,17 @@ function doAbandonClaim(txid, nout) {
let abandonMessage;
if (isClaim) {
abandonMessage = 'Successfully abandoned your claim.';
abandonMessage = __('Successfully abandoned your claim.');
} else if (supportToAbandon) {
abandonMessage = 'Successfully abandoned your support.';
abandonMessage = __('Successfully abandoned your support.');
} else {
abandonMessage = 'Successfully unlocked your tip!';
abandonMessage = __('Successfully unlocked your tip!');
}
dispatch(doToast({
message: abandonMessage
}));
// After abandoning, fetch transactions to show the new abandon transaction
// Only fetch the latest few transactions since we don't care about old ones
// Not very robust, but better than calling the entire list for large wallets
const page = 1;
const pageSize = 10;
dispatch(doFetchTransactions(page, pageSize));
dispatch(doFetchTxoPage());
};
const abandonParams = {
@ -4825,7 +5023,7 @@ reducers[FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => {
return Object.assign({}, state, {
isFetchingClaimListMine: false,
myClaims: myClaimIds,
myClaims: Array.from(myClaimIds),
byId,
claimsByUri: byUri,
pendingById
@ -4880,8 +5078,8 @@ reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => {
claimsByUri: byUri,
channelClaimCounts,
fetchingMyChannels: false,
myChannelClaims,
myClaims: myClaimIds
myChannelClaims: Array.from(myChannelClaims),
myClaims: Array.from(myClaimIds)
});
};
@ -4960,6 +5158,7 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => {
const { claimId } = action.data;
const byId = Object.assign({}, state.byId);
const newMyClaims = state.myClaims ? state.myClaims.slice() : [];
const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : [];
const claimsByUri = Object.assign({}, state.claimsByUri);
Object.keys(claimsByUri).forEach(uri => {
@ -4967,11 +5166,14 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => {
delete claimsByUri[uri];
}
});
const myClaims = newMyClaims.filter(i => i.claim_id && i.claim_id !== claimId);
const myClaims = newMyClaims.filter(i => i !== claimId);
const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId);
delete byId[claimId];
return Object.assign({}, state, {
myClaims,
myChannelClaims,
byId,
claimsByUri
});
@ -4995,7 +5197,7 @@ reducers[CREATE_CHANNEL_COMPLETED] = (state, action) => {
return Object.assign({}, state, {
byId,
pendingById,
myChannelClaims,
myChannelClaims: Array.from(myChannelClaims),
creatingChannel: false
});
};
@ -5907,6 +6109,7 @@ const defaultState$a = {
latestBlock: undefined,
transactions: {},
fetchingTransactions: false,
fetchingTransactionsError: undefined,
supports: {},
fetchingSupports: false,
abandoningSupportsByOutpoint: {},
@ -5928,6 +6131,10 @@ const defaultState$a = {
walletLockResult: null,
transactionListFilter: 'all',
walletReconnecting: false,
txoFetchParams: {},
txoPage: {},
fetchingTxos: false,
fetchingTxosError: undefined,
pendingSupportTransactions: {},
abandonClaimSupportError: undefined
};
@ -5951,6 +6158,34 @@ const walletReducer = handleActions({
});
},
[FETCH_TXO_PAGE_STARTED]: state => {
return _extends$i({}, state, {
fetchingTxos: true,
fetchingTxosError: undefined
});
},
[FETCH_TXO_PAGE_COMPLETED]: (state, action) => {
return _extends$i({}, state, {
txoPage: action.data,
fetchingTxos: false
});
},
[FETCH_TXO_PAGE_FAILED]: (state, action) => {
return _extends$i({}, state, {
txoPage: {},
fetchingTxos: false,
fetchingTxosError: action.data
});
},
[UPDATE_TXO_FETCH_PARAMS]: (state, action) => {
return _extends$i({}, state, {
txoFetchParams: action.data
});
},
[FETCH_SUPPORTS_STARTED]: state => _extends$i({}, state, {
fetchingSupports: true
}),
@ -6344,6 +6579,8 @@ exports.SORT_OPTIONS = sort_options;
exports.SPEECH_URLS = speech_urls;
exports.THUMBNAIL_STATUSES = thumbnail_upload_statuses;
exports.TRANSACTIONS = transaction_types;
exports.TXO_ABANDON_STATES = abandon_txo_states;
exports.TXO_LIST = txo_list;
exports.TX_LIST = transaction_list;
exports.apiCall = apiCall;
exports.batchActions = batchActions;
@ -6357,6 +6594,7 @@ exports.convertToShareLink = convertToShareLink;
exports.createNormalizedClaimSearchKey = createNormalizedClaimSearchKey;
exports.creditsToString = creditsToString;
exports.doAbandonClaim = doAbandonClaim;
exports.doAbandonTxo = doAbandonTxo;
exports.doAddTag = doAddTag;
exports.doBalanceSubscribe = doBalanceSubscribe;
exports.doBlurSearchInput = doBlurSearchInput;
@ -6383,6 +6621,7 @@ exports.doFetchClaimsByChannel = doFetchClaimsByChannel;
exports.doFetchFileInfo = doFetchFileInfo;
exports.doFetchFileInfosAndPublishedClaims = doFetchFileInfosAndPublishedClaims;
exports.doFetchTransactions = doFetchTransactions;
exports.doFetchTxoPage = doFetchTxoPage;
exports.doFileGet = doFileGet;
exports.doFileList = doFileList;
exports.doFocusSearchInput = doFocusSearchInput;
@ -6416,6 +6655,7 @@ exports.doUpdateChannel = doUpdateChannel;
exports.doUpdatePublishForm = doUpdatePublishForm;
exports.doUpdateSearchOptions = doUpdateSearchOptions;
exports.doUpdateSearchQuery = doUpdateSearchQuery;
exports.doUpdateTxoPageParams = doUpdateTxoPageParams;
exports.doUploadThumbnail = doUploadThumbnail;
exports.doWalletDecrypt = doWalletDecrypt;
exports.doWalletEncrypt = doWalletEncrypt;
@ -6529,6 +6769,7 @@ exports.selectFailedPurchaseUris = selectFailedPurchaseUris;
exports.selectFetchingClaimSearch = selectFetchingClaimSearch;
exports.selectFetchingClaimSearchByQuery = selectFetchingClaimSearchByQuery;
exports.selectFetchingMyChannels = selectFetchingMyChannels;
exports.selectFetchingTxosError = selectFetchingTxosError;
exports.selectFileInfosByOutpoint = selectFileInfosByOutpoint;
exports.selectFileInfosDownloaded = selectFileInfosDownloaded;
exports.selectFileListDownloadedSort = selectFileListDownloadedSort;
@ -6543,6 +6784,7 @@ exports.selectIsFetchingClaimListMine = selectIsFetchingClaimListMine;
exports.selectIsFetchingFileList = selectIsFetchingFileList;
exports.selectIsFetchingFileListDownloadedOrPublished = selectIsFetchingFileListDownloadedOrPublished;
exports.selectIsFetchingTransactions = selectIsFetchingTransactions;
exports.selectIsFetchingTxos = selectIsFetchingTxos;
exports.selectIsResolvingPublishUris = selectIsResolvingPublishUris;
exports.selectIsSearching = selectIsSearching;
exports.selectIsSendingSupport = selectIsSendingSupport;
@ -6590,6 +6832,10 @@ exports.selectTotalSupports = selectTotalSupports;
exports.selectTransactionItems = selectTransactionItems;
exports.selectTransactionListFilter = selectTransactionListFilter;
exports.selectTransactionsById = selectTransactionsById;
exports.selectTxoItemCount = selectTxoItemCount;
exports.selectTxoPage = selectTxoPage;
exports.selectTxoPageNumber = selectTxoPageNumber;
exports.selectTxoPageParams = selectTxoPageParams;
exports.selectUnfollowedTags = selectUnfollowedTags;
exports.selectUpdateChannelError = selectUpdateChannelError;
exports.selectUpdatingChannel = selectUpdatingChannel;

24
dist/flow-typed/Txo.js vendored Normal file
View file

@ -0,0 +1,24 @@
declare type Txo = {
amount: number,
claim_id: string,
normalized_name: string,
nout: number,
txid: string,
type: string,
value_type: string,
timestamp: number,
is_my_output: boolean,
is_my_input: boolean,
is_spent: boolean,
};
declare type TxoListParams = {
page: number,
page_size: number,
type: string,
is_my_input?: boolean,
is_my_output?: boolean,
is_not_my_input?: boolean,
is_not_my_output?: boolean,
is_spent?: boolean,
}

24
flow-typed/Txo.js vendored Normal file
View file

@ -0,0 +1,24 @@
declare type Txo = {
amount: number,
claim_id: string,
normalized_name: string,
nout: number,
txid: string,
type: string,
value_type: string,
timestamp: number,
is_my_output: boolean,
is_my_input: boolean,
is_spent: boolean,
};
declare type TxoListParams = {
page: number,
page_size: number,
type: string,
is_my_input?: boolean,
is_my_output?: boolean,
is_not_my_input?: boolean,
is_not_my_output?: boolean,
is_spent?: boolean,
}

View file

@ -0,0 +1,4 @@
export const PENDING = 'pending';
export const DONE = 'done';
export const READY = 'ready';
export const ERROR = 'error';

View file

@ -35,6 +35,10 @@ export const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED';
export const GET_NEW_ADDRESS_COMPLETED = 'GET_NEW_ADDRESS_COMPLETED';
export const FETCH_TRANSACTIONS_STARTED = 'FETCH_TRANSACTIONS_STARTED';
export const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED';
neb-b commented 2020-04-10 20:47:11 +02:00 (Migrated from github.com)
Review

Do you need these old actions still?

Do you need these old actions still?
jessopb commented 2020-04-10 21:01:39 +02:00 (Migrated from github.com)
Review

Desktop still has access to the original transaction list.

Desktop still has access to the original transaction list.
jessopb commented 2020-04-10 21:10:34 +02:00 (Migrated from github.com)
Review

The old page brings only the file export of the list. EVentually I figure that would be a modal.

The old page brings only the file export of the list. EVentually I figure that would be a modal.
export const FETCH_TXO_PAGE_STARTED = 'FETCH_TXO_PAGE_STARTED';
export const FETCH_TXO_PAGE_COMPLETED = 'FETCH_TXO_PAGE_COMPLETED';
export const FETCH_TXO_PAGE_FAILED = 'FETCH_TXO_PAGE_FAILED';
export const UPDATE_TXO_FETCH_PARAMS = 'UPDATE_TXO_FETCH_PARAMS';
export const FETCH_SUPPORTS_STARTED = 'FETCH_SUPPORTS_STARTED';
export const FETCH_SUPPORTS_COMPLETED = 'FETCH_SUPPORTS_COMPLETED';
export const ABANDON_SUPPORT_STARTED = 'ABANDON_SUPPORT_STARTED';

35
src/constants/txo_list.js Normal file
View file

@ -0,0 +1,35 @@
export const ACTIVE = 'active'; // spent, active, all
export const TYPE = 'type'; // all, payment, support, channel, stream, repost
export const SUB_TYPE = 'subtype'; // other, purchase, tip
export const PAGE_SIZE = 'page_size';
export const PAGE = 'page';
export const ALL = 'all';
// dropdown types
export const SENT = 'sent';
export const RECEIVED = 'received';
export const SUPPORT = 'support';
export const CHANNEL = 'channel';
export const PUBLISH = 'publish';
export const REPOST = 'repost';
export const DROPDOWN_TYPES = [ALL, SENT, RECEIVED, SUPPORT, CHANNEL, PUBLISH, REPOST];
// dropdown subtypes
export const TIP = 'tip';
export const PURCHASE = 'purchase';
export const PAYMENT = 'payment';
export const DROPDOWN_SUBTYPES = [ALL, TIP, PURCHASE, PAYMENT];
// rpc params
export const TX_TYPE = 'type'; // = other, stream, repost, channel, support, purchase
export const IS_SPENT = 'is_spent';
export const IS_NOT_SPENT = 'is_not_spent';
export const IS_MY_INPUT = 'is_my_input';
export const IS_MY_OUTPUT = 'is_my_output';
export const IS_NOT_MY_INPUT = 'is_not_my_input';
export const IS_NOT_MY_OUTPUT = 'is_not_my_output'; // use to further distinguish payments to self / from self.
// sdk unique types
export const OTHER = 'other';
export const STREAM = 'stream';
export const PAGE_SIZE_DEFAULT = 20;

View file

@ -7,6 +7,8 @@ import * as SORT_OPTIONS from 'constants/sort_options';
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
import * as TRANSACTIONS from 'constants/transaction_types';
import * as TX_LIST from 'constants/transaction_list';
import * as TXO_ABANDON_STATES from 'constants/abandon_txo_states';
import * as TXO_LIST from 'constants/txo_list';
import * as SPEECH_URLS from 'constants/speech_urls';
import * as DAEMON_SETTINGS from 'constants/daemon_settings';
import * as SHARED_PREFERENCES from 'constants/shared_preferences';
@ -27,6 +29,8 @@ export {
DAEMON_SETTINGS,
TRANSACTIONS,
TX_LIST,
TXO_LIST,
TXO_ABANDON_STATES,
SORT_OPTIONS,
PAGES,
DEFAULT_KNOWN_TAGS,
@ -60,6 +64,7 @@ export {
doFetchClaimsByChannel,
doFetchClaimListMine,
doAbandonClaim,
doAbandonTxo,
doResolveUris,
doResolveUri,
doFetchChannelListMine,
@ -106,6 +111,8 @@ export {
doUpdateBalance,
doBalanceSubscribe,
doFetchTransactions,
doFetchTxoPage,
doUpdateTxoPageParams,
doGetNewAddress,
doCheckAddressIsMine,
doSendDraftTransaction,
@ -327,6 +334,12 @@ export {
selectWalletUnlockResult,
selectTransactionListFilter,
selectFilteredTransactions,
selectTxoPageParams,
selectTxoPage,
selectTxoPageNumber,
selectTxoItemCount,
selectIsFetchingTxos,
selectFetchingTxosError,
makeSelectLatestTransactions,
makeSelectFilteredTransactionsForPage,
selectFilteredTransactionCount,

View file

@ -1,5 +1,6 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import * as TXO_STATES from 'constants/abandon_txo_states';
import Lbry from 'lbry';
import { normalizeURI } from 'lbryURI';
import { doToast } from 'redux/actions/notifications';
@ -9,7 +10,7 @@ import {
selectClaimsByUri,
selectMyChannelClaims,
} from 'redux/selectors/claims';
import { doFetchTransactions } from 'redux/actions/wallet';
import { doFetchTxoPage } from 'redux/actions/wallet';
import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
import { creditsToString } from 'util/format-credits';
import { batchActions } from 'util/batch-actions';
@ -120,6 +121,91 @@ export function doFetchClaimListMine(
};
}
export function doAbandonTxo(txo: Txo, cb: string => void) {
return (dispatch: Dispatch) => {
if (cb) cb(TXO_STATES.PENDING);
const isClaim = txo.type === 'claim';
const isSupport = txo.type === 'support' && txo.is_my_input === true;
const isTip = txo.type === 'support' && txo.is_my_input === false;
const data = isClaim ? { claimId: txo.claim_id } : { outpoint: `${txo.txid}:${txo.nout}` };
const startedActionType = isClaim
? ACTIONS.ABANDON_CLAIM_STARTED
: ACTIONS.ABANDON_SUPPORT_STARTED;
const completedActionType = isClaim
? ACTIONS.ABANDON_CLAIM_SUCCEEDED
: ACTIONS.ABANDON_SUPPORT_COMPLETED;
dispatch({
type: startedActionType,
data,
});
const errorCallback = () => {
if (cb) cb(TXO_STATES.ERROR);
dispatch(
doToast({
message: isClaim ? 'Error abandoning your claim/support' : 'Error unlocking your tip',
isError: true,
})
);
};
const successCallback = () => {
dispatch({
type: completedActionType,
data,
});
let abandonMessage;
if (isClaim) {
abandonMessage = __('Successfully abandoned your claim.');
} else if (isSupport) {
abandonMessage = __('Successfully abandoned your support.');
} else {
abandonMessage = __('Successfully unlocked your tip!');
}
if (cb) cb(TXO_STATES.DONE);
dispatch(
doToast({
message: abandonMessage,
})
);
};
const abandonParams: {
claim_id?: string,
txid?: string,
nout?: number,
} = {
neb-b commented 2020-04-10 20:48:15 +02:00 (Migrated from github.com)
Review

can we call txo_list for page 1 here?

can we call txo_list for page 1 here?
jessopb commented 2020-04-10 21:08:58 +02:00 (Migrated from github.com)
Review

Considered it.
Currently the component parses the params locally and feeds them to fetchTransactoins(p).
Instead, we would have to parse the params locally and update redux with the params, 'dot then' fetch given the params.
Then we could ask redux to refetch current params at any time...

Considered it. Currently the component parses the params locally and feeds them to fetchTransactoins(p). Instead, we would have to parse the params locally and update redux with the params, 'dot then' fetch given the params. Then we could ask redux to refetch current params at any time...
jessopb commented 2020-04-13 19:31:02 +02:00 (Migrated from github.com)
Review

Changed to updating params which calls fetchTxos on success.

Changed to updating params which calls fetchTxos on success.
blocking: true,
};
if (isClaim) {
abandonParams['claim_id'] = txo.claim_id;
} else {
abandonParams['txid'] = txo.txid;
abandonParams['nout'] = txo.nout;
}
let method;
if (isSupport || isTip) {
method = 'support_abandon';
} else if (isClaim) {
const { normalized_name: claimName } = txo;
method = claimName.startsWith('@') ? 'channel_abandon' : 'stream_abandon';
}
if (!method) {
console.error('No "method" chosen for claim or support abandon');
return;
}
Lbry[method](abandonParams).then(successCallback, errorCallback);
};
}
export function doAbandonClaim(txid: string, nout: number) {
const outpoint = `${txid}:${nout}`;
@ -171,11 +257,11 @@ export function doAbandonClaim(txid: string, nout: number) {
let abandonMessage;
if (isClaim) {
abandonMessage = 'Successfully abandoned your claim.';
abandonMessage = __('Successfully abandoned your claim.');
} else if (supportToAbandon) {
abandonMessage = 'Successfully abandoned your support.';
abandonMessage = __('Successfully abandoned your support.');
} else {
abandonMessage = 'Successfully unlocked your tip!';
abandonMessage = __('Successfully unlocked your tip!');
}
dispatch(
@ -183,13 +269,7 @@ export function doAbandonClaim(txid: string, nout: number) {
message: abandonMessage,
})
);
// After abandoning, fetch transactions to show the new abandon transaction
// Only fetch the latest few transactions since we don't care about old ones
// Not very robust, but better than calling the entire list for large wallets
const page = 1;
const pageSize = 10;
dispatch(doFetchTransactions(page, pageSize));
dispatch(doFetchTxoPage());
};
const abandonParams = {

View file

@ -1,7 +1,7 @@
import * as ACTIONS from 'constants/action_types';
import Lbry from 'lbry';
import { doToast } from 'redux/actions/notifications';
import { selectBalance, selectPendingSupportTransactions } from 'redux/selectors/wallet';
import { selectBalance, selectPendingSupportTransactions, selectTxoPageParams } from 'redux/selectors/wallet';
import { creditsToString } from 'util/format-credits';
import { selectMyClaimsRaw } from 'redux/selectors/claims';
import { doFetchChannelListMine, doFetchClaimListMine } from 'redux/actions/claims';
@ -72,6 +72,42 @@ export function doFetchTransactions(page = 1, pageSize = 99999) {
};
}
export function doFetchTxoPage() {
return (dispatch, getState) => {
dispatch({
type: ACTIONS.FETCH_TXO_PAGE_STARTED,
});
const state = getState();
const queryParams = selectTxoPageParams(state);
Lbry.txo_list(queryParams)
.then(res => {
dispatch({
type: ACTIONS.FETCH_TXO_PAGE_COMPLETED,
data: res,
});
})
.catch(e => {
dispatch({
type: ACTIONS.FETCH_TXO_PAGE_COMPLETED,
data: e.message,
});
});
};
}
export function doUpdateTxoPageParams(params: TxoListParams) {
return dispatch => {
dispatch({
type: ACTIONS.UPDATE_TXO_FETCH_PARAMS,
data: params,
});
dispatch(doFetchTxoPage());
};
}
export function doFetchSupports(page = 1, pageSize = 99999) {
return dispatch => {
dispatch({
@ -432,6 +468,7 @@ export function doWalletStatus() {
};
}
export function doSetTransactionListFilter(filterOption) {
return {
type: ACTIONS.SET_TRANSACTION_LIST_FILTER,

View file

@ -18,8 +18,8 @@ type State = {
byId: { [string]: Claim },
resolvingUris: Array<string>,
pendingById: { [string]: Claim },
myClaims: ?Array<Claim>,
myChannelClaims: ?Set<string>,
myClaims: ?Array<string>,
myChannelClaims: ?Array<string>,
abandoningById: { [string]: boolean },
fetchingChannelClaims: { [string]: number },
fetchingMyChannels: boolean,
@ -198,7 +198,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
return Object.assign({}, state, {
isFetchingClaimListMine: false,
myClaims: myClaimIds,
myClaims: Array.from(myClaimIds),
byId,
claimsByUri: byUri,
pendingById,
@ -255,8 +255,8 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
claimsByUri: byUri,
channelClaimCounts,
fetchingMyChannels: false,
myChannelClaims,
myClaims: myClaimIds,
myChannelClaims: Array.from(myChannelClaims),
myClaims: Array.from(myClaimIds),
});
};
@ -342,6 +342,7 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State =
const { claimId }: { claimId: string } = action.data;
const byId = Object.assign({}, state.byId);
const newMyClaims = state.myClaims ? state.myClaims.slice() : [];
const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : [];
const claimsByUri = Object.assign({}, state.claimsByUri);
Object.keys(claimsByUri).forEach(uri => {
@ -349,11 +350,14 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State =
delete claimsByUri[uri];
}
});
const myClaims = newMyClaims.filter(i => i.claim_id && i.claim_id !== claimId);
const myClaims = newMyClaims.filter(i => i !== claimId);
const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId);
delete byId[claimId];
return Object.assign({}, state, {
myClaims,
myChannelClaims,
byId,
claimsByUri,
});
@ -378,7 +382,7 @@ reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = (state: State, action: any): State
return Object.assign({}, state, {
byId,
pendingById,
myChannelClaims,
myChannelClaims: Array.from(myChannelClaims),
creatingChannel: false,
});
};

View file

@ -14,8 +14,6 @@ type ActionResult = {
result: any,
};
type WalletState = {
balance: any,
totalBalance: any,
@ -28,6 +26,7 @@ type WalletState = {
supports: { [string]: Support },
abandoningSupportsByOutpoint: { [string]: boolean },
fetchingTransactions: boolean,
fetchingTransactionsError: string,
gettingNewAddress: boolean,
draftTransaction: any,
sendingSupport: boolean,
@ -45,6 +44,10 @@ type WalletState = {
walletLockSucceded: ?boolean,
walletLockResult: ?boolean,
walletReconnecting: boolean,
txoFetchParams: {},
txoPage: any,
fetchingTxos: boolean,
fetchingTxosError?: string,
pendingSupportTransactions: {}, // { claimId: {txid: 123, amount 12.3}, }
abandonClaimSupportError?: string,
};
@ -59,6 +62,7 @@ const defaultState = {
latestBlock: undefined,
transactions: {},
fetchingTransactions: false,
fetchingTransactionsError: undefined,
supports: {},
fetchingSupports: false,
abandoningSupportsByOutpoint: {},
@ -80,6 +84,10 @@ const defaultState = {
walletLockResult: null,
transactionListFilter: 'all',
walletReconnecting: false,
txoFetchParams: {},
txoPage: {},
fetchingTxos: false,
fetchingTxosError: undefined,
pendingSupportTransactions: {},
abandonClaimSupportError: undefined,
};
@ -106,6 +114,38 @@ export const walletReducer = handleActions(
};
},
[ACTIONS.FETCH_TXO_PAGE_STARTED]: (state: WalletState) => {
return {
...state,
fetchingTxos: true,
fetchingTxosError: undefined,
};
},
[ACTIONS.FETCH_TXO_PAGE_COMPLETED]: (state: WalletState, action) => {
return {
...state,
txoPage: action.data,
fetchingTxos: false,
};
},
[ACTIONS.FETCH_TXO_PAGE_FAILED]: (state: WalletState, action) => {
return {
...state,
txoPage: {},
fetchingTxos: false,
fetchingTxosError: action.data,
};
},
[ACTIONS.UPDATE_TXO_FETCH_PARAMS]: (state: WalletState, action) => {
return {
...state,
txoFetchParams: action.data,
};
},
[ACTIONS.FETCH_SUPPORTS_STARTED]: (state: WalletState) => ({
...state,
fetchingSupports: true,

View file

@ -321,6 +321,36 @@ export const selectFilteredTransactions = createSelector(
}
);
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,