Feat txo paginate #299
12 changed files with 577 additions and 36 deletions
276
dist/bundle.es.js
vendored
276
dist/bundle.es.js
vendored
|
@ -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
24
dist/flow-typed/Txo.js
vendored
Normal 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
24
flow-typed/Txo.js
vendored
Normal 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,
|
||||
}
|
4
src/constants/abandon_txo_states.js
Normal file
4
src/constants/abandon_txo_states.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
export const PENDING = 'pending';
|
||||
export const DONE = 'done';
|
||||
export const READY = 'ready';
|
||||
export const ERROR = 'error';
|
|
@ -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';
|
||||
![]() Desktop still has access to the original transaction list. Desktop still has access to the original transaction list.
![]() 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
35
src/constants/txo_list.js
Normal 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;
|
||||
|
13
src/index.js
13
src/index.js
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
} = {
|
||||
![]() can we call txo_list for page 1 here? can we call txo_list for page 1 here?
![]() Considered it. 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...
![]() 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 = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue
Do you need these old actions still?