Merge pull request #69 from andrerfneves/feature/list-shielded-transactions
Feature/list shielded transactions
This commit is contained in:
commit
3019f0182c
|
@ -0,0 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import 'jest-dom/extend-expect';
|
||||
|
||||
import { sortByDescend } from '../../app/utils/sort-by-descend';
|
||||
|
||||
describe('truncateAddress', () => {
|
||||
test('should truncate ZEC address', () => {
|
||||
expect(
|
||||
sortByDescend('id')([{ id: 5 }, { id: 2 }, { id: 1 }, { id: 0 }, { id: 1 }, { id: 1 }]),
|
||||
).toEqual([{ id: 5 }, { id: 2 }, { id: 1 }, { id: 1 }, { id: 1 }, { id: 0 }]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import 'jest-dom/extend-expect';
|
||||
|
||||
import { sortBy } from '../../app/utils/sort-by';
|
||||
|
||||
describe('truncateAddress', () => {
|
||||
test('should truncate ZEC address', () => {
|
||||
expect(
|
||||
sortBy('id')([{ id: 5 }, { id: 2 }, { id: 1 }, { id: 0 }, { id: 1 }, { id: 1 }]),
|
||||
).toEqual([{ id: 0 }, { id: 1 }, { id: 1 }, { id: 1 }, { id: 2 }, { id: 5 }]);
|
||||
});
|
||||
});
|
|
@ -32,7 +32,7 @@ const StyledLink = styled.a`
|
|||
display: flex;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
border-right: ${(props: StyledLinkProps) => (props.isActive ? `3px solid ${props.theme.colors.sidebarItemActive}` : 'none')};
|
||||
border-right: ${(props: StyledLinkProps) => (props.isActive ? `3px solid ${props.theme.colors.sidebarItemActive(props)}` : 'none')};
|
||||
cursor: pointer;
|
||||
transition: all 0.03s ${(props: StyledLinkProps) => props.theme.transitionEase};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ const AddressWrapper = styled.div`
|
|||
background-color: #000;
|
||||
border-radius: 6px;
|
||||
padding: 7px 13px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
|
@ -41,7 +42,7 @@ const QRCodeWrapper = styled.div`
|
|||
background-color: #000;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@ import dateFns from 'date-fns';
|
|||
import { BigNumber } from 'bignumber.js';
|
||||
import { DashboardView } from '../views/dashboard';
|
||||
import rpc from '../../services/api';
|
||||
import { listShieldedTransactions } from '../../services/shielded-transactions';
|
||||
import store from '../../config/electron-store';
|
||||
import {
|
||||
loadWalletSummary,
|
||||
loadWalletSummarySuccess,
|
||||
loadWalletSummaryError,
|
||||
} from '../redux/modules/wallet';
|
||||
import { sortBy } from '../utils/sort-by';
|
||||
import { sortByDescend } from '../utils/sort-by-descend';
|
||||
|
||||
import type { AppState } from '../types/app-state';
|
||||
import type { Dispatch } from '../types/redux';
|
||||
|
@ -47,7 +48,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
);
|
||||
}
|
||||
|
||||
const formattedTransactions = flow([
|
||||
const formattedTransactions: Array<Object> = flow([
|
||||
arr => arr.map(transaction => ({
|
||||
transactionId: transaction.txid,
|
||||
type: transaction.category,
|
||||
|
@ -58,10 +59,11 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
arr => groupBy(arr, obj => dateFns.format(obj.date, 'MMM DD, YYYY')),
|
||||
obj => Object.keys(obj).map(day => ({
|
||||
day,
|
||||
list: sortBy('date')(obj[day]),
|
||||
jsDay: new Date(day),
|
||||
list: sortByDescend('date')(obj[day]),
|
||||
})),
|
||||
sortBy('day'),
|
||||
])(transactions);
|
||||
sortByDescend('jsDay'),
|
||||
])([...transactions, ...listShieldedTransactions()]);
|
||||
|
||||
if (!zAddresses.length) {
|
||||
const [, newZAddress] = await eres(rpc.z_getnewaddress());
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
} from '../redux/modules/send';
|
||||
|
||||
import { filterObjectNullKeys } from '../utils/filter-object-null-keys';
|
||||
import { saveShieldedTransaction } from '../../services/shielded-transactions';
|
||||
|
||||
import type { AppState } from '../types/app-state';
|
||||
import type { Dispatch } from '../types/redux';
|
||||
|
@ -92,6 +93,15 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
|
||||
if (operationStatus && operationStatus.status === 'success') {
|
||||
clearInterval(interval);
|
||||
if (from.startsWith('z')) {
|
||||
saveShieldedTransaction({
|
||||
category: 'send',
|
||||
time: Date.now() / 1000,
|
||||
address: '(Shielded)',
|
||||
amount: new BigNumber(amount).toNumber(),
|
||||
memo,
|
||||
});
|
||||
}
|
||||
dispatch(sendTransactionSuccess({ operationId: operationStatus.result.txid }));
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@ import {
|
|||
loadTransactionsError,
|
||||
} from '../redux/modules/transactions';
|
||||
import rpc from '../../services/api';
|
||||
import { listShieldedTransactions } from '../../services/shielded-transactions';
|
||||
import store from '../../config/electron-store';
|
||||
|
||||
import { sortBy } from '../utils/sort-by';
|
||||
import { sortByDescend } from '../utils/sort-by-descend';
|
||||
|
||||
import type { AppState } from '../types/app-state';
|
||||
import type { Dispatch } from '../types/redux';
|
||||
|
@ -32,7 +33,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
getTransactions: async () => {
|
||||
dispatch(loadTransactions());
|
||||
|
||||
const [transactionsErr, transactions = []] = await eres(rpc.listtransactions());
|
||||
const [transactionsErr, transactions = []] = await eres(rpc.listtransactions('', 200));
|
||||
|
||||
if (transactionsErr) {
|
||||
return dispatch(loadTransactionsError({ error: transactionsErr.message }));
|
||||
|
@ -49,10 +50,11 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
arr => groupBy(arr, obj => dateFns.format(obj.date, 'MMM DD, YYYY')),
|
||||
obj => Object.keys(obj).map(day => ({
|
||||
day,
|
||||
list: sortBy('date')(obj[day]),
|
||||
jsDay: new Date(day),
|
||||
list: sortByDescend('date')(obj[day]),
|
||||
})),
|
||||
sortBy('day'),
|
||||
])(transactions);
|
||||
sortByDescend('jsDay'),
|
||||
])([...transactions, ...listShieldedTransactions()]);
|
||||
|
||||
dispatch(
|
||||
loadTransactionsSuccess({
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// @flow
|
||||
/* eslint-disable max-len */
|
||||
|
||||
// $FlowFixMe
|
||||
export const sortByDescend = <T>(field: string) => (arr: T[]): T[] => arr.sort((a, b) => (a[field] < b[field] ? 1 : -1));
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
// $FlowFixMe
|
||||
export const sortBy = <T>(field: string) => (arr: T[]): T[] => arr.sort((a, b) => (a[field] < b[field] ? 1 : -1));
|
||||
export const sortBy = <T>(field: string) => (arr: T[]): T[] => arr.sort((a, b) => (a[field] > b[field] ? 1 : -1));
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// @flow
|
||||
|
||||
export const truncateAddress = (address: string = '') => `${address.substr(0, 20)}...${address.substr(
|
||||
address.length - 10,
|
||||
address.length,
|
||||
)}`;
|
||||
export const truncateAddress = (address: string = '') => (address.length < 20
|
||||
? address
|
||||
: `${address.substr(0, 20)}...${address.substr(address.length - 10, address.length)}`);
|
||||
|
|
|
@ -159,11 +159,9 @@ const ConfirmItemWrapper = styled(RowComponent)`
|
|||
width: 100%;
|
||||
`;
|
||||
|
||||
type ItemLabelProps =
|
||||
| {
|
||||
color: string,
|
||||
}
|
||||
| Object;
|
||||
type ItemLabelProps = {
|
||||
color: string,
|
||||
};
|
||||
/* eslint-disable max-len */
|
||||
const ItemLabel = styled(TextComponent)`
|
||||
font-weight: ${(props: PropsWithTheme<ItemLabelProps>) => String(props.theme.fontWeight.bold)};
|
||||
|
@ -227,7 +225,7 @@ const MaxAvailableAmount = styled.button`
|
|||
background: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-left: ${props => `1px solid ${props.theme.colors.background}`};
|
||||
border-left: ${props => `1px solid ${props.theme.colors.background(props)}`};
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -10,9 +10,9 @@ declare module 'electron-store' {
|
|||
fileExtension?: string,
|
||||
}): ElectronStore;
|
||||
|
||||
set(key: string, value: string): void;
|
||||
set(key: string, value: any): void;
|
||||
set(payload: Object): void;
|
||||
get(key: string): string;
|
||||
get(key: string): any;
|
||||
has(key: string): boolean;
|
||||
delete(key: string): void;
|
||||
clear(): void;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// @flow
|
||||
import electronStore from '../config/electron-store';
|
||||
|
||||
const STORE_KEY = 'SHIELDED_TRANSACTIONS';
|
||||
|
||||
type ShieldedTransaction = {|
|
||||
category: 'send' | 'receive',
|
||||
time: number,
|
||||
address: string,
|
||||
amount: number,
|
||||
memo: ?string,
|
||||
|};
|
||||
|
||||
// eslint-disable-next-line
|
||||
export const listShieldedTransactions = (): Array<ShieldedTransaction> => electronStore.has(STORE_KEY) ? electronStore.get(STORE_KEY) : [];
|
||||
|
||||
export const saveShieldedTransaction = ({
|
||||
category,
|
||||
time,
|
||||
address,
|
||||
amount,
|
||||
memo,
|
||||
}: ShieldedTransaction): void => {
|
||||
electronStore.set(
|
||||
STORE_KEY,
|
||||
listShieldedTransactions().concat({
|
||||
category,
|
||||
time,
|
||||
address,
|
||||
amount,
|
||||
memo: memo || '',
|
||||
}),
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue