commit
a7cbf682ec
|
@ -1,6 +1,6 @@
|
|||
# Development Workflow
|
||||
|
||||
This repository follow the GitFlow paradigm. If you are unfamiliar with GitFlow, please read [Atlassian's GitFlow documentation](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) illustrating the concepts and its advantages.
|
||||
This repository aims to follow the GitFlow paradigm. If you are unfamiliar with GitFlow, please read [Atlassian's GitFlow documentation](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) illustrating the concepts and its advantages.
|
||||
|
||||
# Branching
|
||||
|
||||
|
@ -43,18 +43,8 @@ docs: commit messages doc
|
|||
|
||||
## Pull Requests
|
||||
|
||||
When it comes time to open a PR, make sure that the PR covers all development in the current ticket being worked on. Do your due diligence and make sure everything is working to the best of your knowledge, on every operating system you can test on. If everything is good to go a PR may be opened.
|
||||
### Title
|
||||
|
||||
#### Title
|
||||
The title of the PR should have the type shown (feature, hotfix, chore, etc..) as well as a brief description of the PR's purpose. Example
|
||||
|
||||
The title of the PR should have the type shown (feature, hotfix, chore, etc..) as well as a brief description of the PR's purpose. If this PR relates directly to a ticket (as they ideally should), add the ticket number in as well. Example
|
||||
|
||||
`[feature] [ZC-12] Add Infinite Scroll`
|
||||
|
||||
In some cases there may be a reason that a PR should be opened for discussion among all engineers. If this is the case you should prefix your PR's with [WIP] Example
|
||||
|
||||
`[WIP] [feature] [ZC-12] Add Infinite Scroll`
|
||||
|
||||
## Linting
|
||||
|
||||
All prjects containing Javascript must be linted. This helps us deliver clean and uniform code. ESLint will be the linter used on all projects, and `.eslintrc` file will provide the linting rules to follow.
|
||||
`[feature] Add Infinite Scroll`
|
||||
|
|
88
NODE.md
88
NODE.md
|
@ -1,88 +0,0 @@
|
|||
# Zcash Node Setup
|
||||
|
||||
The original `zcashd` daemon built by the Zcash Company, is built entirely in for Linux systems. If you're running a Linux distro, you should look [here](https://github.com/zcash/zcash) for instructions on how to install it.
|
||||
|
||||
For macOS users, please follow [this guide](https://github.com/kozyilmaz/zcash-apple) to build the binaries locally on your machine and then install it. After downloading the tarball and the hash, use the steps below to kickstart your node and connect it to the network.
|
||||
|
||||
## Installing
|
||||
|
||||
Download the attached files from Zcash Apple repository, verify the checksum of the archive and then extract its contents:
|
||||
|
||||
```bash
|
||||
shasum -a 256 -c zcash-macos-v2.0.1a.tar.bz2.hash
|
||||
tar -xvf zcash-macos-v2.0.1a.tar.bz2
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
When launching Zcash on macOS for the first time, certain initialization steps should be completed. Please run the commands below once for the first time
|
||||
|
||||
```
|
||||
cd zcash-macos-v2.0.1a/usr/local/bin
|
||||
./zcash-fetch-params
|
||||
./zcash-init
|
||||
```
|
||||
|
||||
You can just run Zcash by launching the daemon afterwards:
|
||||
|
||||
```
|
||||
./zcashd
|
||||
```
|
||||
|
||||
## Basic Commands
|
||||
|
||||
Along with `zcashd`, the daemon provides the `zcash-cli` utility which allows you to run RPC commands to your node, and receive the output data.
|
||||
|
||||
Some useful commands can be found below:
|
||||
|
||||
### General
|
||||
|
||||
> List information for a command
|
||||
```bash
|
||||
./zcash-cli help <command>
|
||||
```
|
||||
|
||||
> List all shielded addresses
|
||||
```bash
|
||||
./zcash-cli z_listaddresses
|
||||
```
|
||||
|
||||
> Create new shielded address
|
||||
```bash
|
||||
./zcash-cli z_getnewaddress
|
||||
```
|
||||
|
||||
> Get total balance
|
||||
```bash
|
||||
./zcash-cli z_gettotalbalance
|
||||
```
|
||||
|
||||
### Sending Funds
|
||||
```bash
|
||||
export ZADDR='zcNeXiyD3JkhKTrU38xM9C6HQGy9aP5qqVFH25qFzQGnmdwYZ2Dr53Jy7iRp64D4CzkMZdmKagN6mmtu3jVKHuZ8xZp8fw3'
|
||||
export FRIEND='zcfZJW3qLHpSc7q7W1SXRGdVjgM6Q6kRwdkz1DHW5sP2EqcMHf5RCp3Frpf2qnb81j9K6upzRN4HoVxfboVwLTRaZ7bKn8b'
|
||||
```
|
||||
|
||||
> Send from shielded address to shielded address (with memo and fee)
|
||||
```bash
|
||||
./zcash-cli z_sendmany "$ZADDR" "[{\"address\": \"$FRIEND\", \"amount\": 0.05, \"memo\": \"9876543210\"}]" 1 0.002
|
||||
```
|
||||
|
||||
> Get send result
|
||||
```bash
|
||||
./zcash-cli z_getoperationresult [\"$OPID\"]
|
||||
```
|
||||
|
||||
> List amounts received by shielded address
|
||||
```bash
|
||||
./zcash-cli z_listreceivedbyaddress "$ZADDR"
|
||||
```
|
||||
|
||||
## Helpful Resources
|
||||
|
||||
* [Zcash Documentation (ReadTheDocs)](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html)
|
||||
* [Zcash Apple Daemon](https://github.com/kozyilmaz/zcash-apple)
|
||||
* [Zcash Community Forum](https://forum.zcashcommunity.com/)
|
||||
* [Zcash Foundation](https://z.cash.foundation/)
|
||||
* [Zcash Daemon](https://github.com/zcash/zcash)
|
||||
* [Zcash Payment API Docs](https://github.com/zcash/zcash/blob/master/doc/payment-api.md)
|
10
README.md
10
README.md
|
@ -1,6 +1,6 @@
|
|||
# Zcash Reference Wallet
|
||||
# Zepio | ZEC Wallet
|
||||
|
||||
Reference Wallet for the Zcash Network
|
||||
Zepio is a modern cross-platform full-node desktop wallet for the Zcash Network.
|
||||
|
||||
[![CircleCI](https://circleci.com/gh/andrerfneves/zec-react-wallet.svg?style=svg&circle-token=abde48de664026a5d03d4b806c904c8ce5e45aa0)](https://circleci.com/gh/andrerfneves/zec-react-wallet) ![Flow Coverage](./public/flow-coverage-badge.svg)
|
||||
|
||||
|
@ -32,10 +32,6 @@ yarn start
|
|||
|
||||
This will kickstart the webpack development server and serve the app on port 8080, as well as launch the Electron wrapper for the application, which houses the `zcashd` daemon process.
|
||||
|
||||
## Buiding & Distribution
|
||||
|
||||
TBD
|
||||
|
||||
## License
|
||||
|
||||
© Zcash Foundation 2018
|
||||
MIT © Zcash Foundation 2019
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 304 KiB |
|
@ -13,8 +13,17 @@ const Wrapper = styled.div`
|
|||
padding: 30px 0;
|
||||
`;
|
||||
|
||||
const Text = styled(TextComponent)`
|
||||
margin: 0 8.5px 0;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: ${props => props.theme.colors.transactionLabelText};
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
`;
|
||||
|
||||
export const EmptyTransactionsComponent = () => (
|
||||
<Wrapper data-testid='NoTransactions'>
|
||||
<TextComponent value='No transactions!' />
|
||||
<Text value='No transactions!' />
|
||||
</Wrapper>
|
||||
);
|
||||
|
|
|
@ -36,7 +36,7 @@ const ChildrenWrapper = styled.div`
|
|||
`;
|
||||
|
||||
const Message = styled(TextComponent)`
|
||||
margin: 15px 0;
|
||||
margin: 35px 0;
|
||||
`;
|
||||
|
||||
const ErrorImage = styled.img`
|
||||
|
@ -86,7 +86,7 @@ export class ErrorModalComponent extends PureComponent<Props> {
|
|||
<ChildrenWrapper>
|
||||
<ErrorImage src={ErrorIcon} alt='Error Icon' />
|
||||
<Message value={message} />
|
||||
<Button label='Ok!' onClick={onRequestClose} />
|
||||
<Button label='Ok' onClick={onRequestClose} />
|
||||
</ChildrenWrapper>
|
||||
</ModalWrapper>,
|
||||
this.element,
|
||||
|
|
|
@ -7,6 +7,7 @@ import { ColumnComponent } from './column';
|
|||
import { TextComponent } from './text';
|
||||
import { QRCode } from './qrcode';
|
||||
import { CopyToClipboard } from './copy-to-clipboard';
|
||||
import { Button } from './button';
|
||||
|
||||
import CopyIconDark from '../assets/images/copy_icon_dark.svg';
|
||||
import CopyIconLight from '../assets/images/copy_icon_light.svg';
|
||||
|
@ -164,7 +165,38 @@ const AddressDetailsLabel = styled.div`
|
|||
const AddressDetailsWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px 20px;
|
||||
padding: 10px 20px 0 20px;
|
||||
`;
|
||||
|
||||
const FormButton = styled(Button)`
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const Column = styled.div`
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
`;
|
||||
|
||||
const SecondaryColumn = styled(Column)`
|
||||
padding-bottom: 0;
|
||||
`;
|
||||
|
||||
const Row = styled(Column)`
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
`;
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
max-width: 200px;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
|
@ -175,6 +207,7 @@ type Props = {
|
|||
|
||||
type State = {
|
||||
showCopiedTooltip: boolean,
|
||||
isSecondaryCopied: boolean,
|
||||
showQRCode: boolean,
|
||||
};
|
||||
|
||||
|
@ -182,6 +215,7 @@ class Component extends PureComponent<Props, State> {
|
|||
state = {
|
||||
showQRCode: false,
|
||||
showCopiedTooltip: false,
|
||||
isSecondaryCopied: false,
|
||||
};
|
||||
|
||||
showMoreInfo = () => this.setState(() => ({ showQRCode: true }));
|
||||
|
@ -192,14 +226,21 @@ class Component extends PureComponent<Props, State> {
|
|||
|
||||
hideTooltip = () => this.setState(() => ({ showCopiedTooltip: false }));
|
||||
|
||||
unCopySecondary = () => this.setState(() => ({ isSecondaryCopied: false }));
|
||||
|
||||
copyAddress = () => this.setState(
|
||||
() => ({ showCopiedTooltip: true }),
|
||||
() => setTimeout(() => this.hideTooltip(), 1500),
|
||||
);
|
||||
|
||||
copySecondaryAddress = () => this.setState(
|
||||
() => ({ isSecondaryCopied: true }),
|
||||
() => setTimeout(() => this.unCopySecondary(), 1500),
|
||||
);
|
||||
|
||||
render() {
|
||||
const { address, balance, theme } = this.props;
|
||||
const { showQRCode, showCopiedTooltip } = this.state;
|
||||
const { showQRCode, showCopiedTooltip, isSecondaryCopied } = this.state;
|
||||
|
||||
const qrCodeIcon = theme.mode === DARK ? ScanIconDark : ScanIconLight;
|
||||
|
||||
|
@ -244,12 +285,29 @@ class Component extends PureComponent<Props, State> {
|
|||
<QRCode value={address} />
|
||||
</QRCodeWrapper>
|
||||
<AddressDetailsWrapper>
|
||||
<AddressDetailsLabel>Address</AddressDetailsLabel>
|
||||
<AddressDetailsValue value={address} />
|
||||
<AddressDetailsLabel>Funds</AddressDetailsLabel>
|
||||
<AddressDetailsValue
|
||||
value={formatNumber({ append: `${coinName} `, value: balance })}
|
||||
/>
|
||||
<Column>
|
||||
<AddressDetailsLabel>Address</AddressDetailsLabel>
|
||||
<AddressDetailsValue value={address} />
|
||||
</Column>
|
||||
<Row>
|
||||
<SecondaryColumn>
|
||||
<AddressDetailsLabel>Funds</AddressDetailsLabel>
|
||||
<AddressDetailsValue
|
||||
value={formatNumber({ append: `${coinName} `, value: balance })}
|
||||
/>
|
||||
</SecondaryColumn>
|
||||
<ButtonWrapper>
|
||||
<CopyToClipboard text={address} onCopy={this.copySecondaryAddress}>
|
||||
<FormButton
|
||||
id='send-submit-button'
|
||||
label={isSecondaryCopied ? 'Copied!' : 'Copy Address'}
|
||||
variant='primary'
|
||||
focused
|
||||
isFluid
|
||||
/>
|
||||
</CopyToClipboard>
|
||||
</ButtonWrapper>
|
||||
</Row>
|
||||
</AddressDetailsWrapper>
|
||||
</QRCodeContainer>
|
||||
)}
|
||||
|
|
|
@ -4,4 +4,4 @@ import isDev from 'electron-is-dev';
|
|||
|
||||
export const ZCASH_EXPLORER_BASE_URL = isDev
|
||||
? 'https://chain.so/tx/ZECTEST/'
|
||||
: 'https://zcash.blockexplorer.com/tx/';
|
||||
: 'https://zcha.in/transactions/';
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
// @flow
|
||||
|
||||
export const ZCASH_NETWORK = 'ZCASH_NETWORK';
|
||||
export const EMBEDDED_DAEMON = 'EMBEDDED_DAEMON';
|
||||
|
||||
export const MAINNET = 'MAINNET';
|
||||
export const TESTNET = 'TESTNET';
|
||||
|
||||
export const SPROUT = 'sprout';
|
||||
export const SAPLING = 'sapling';
|
||||
|
|
|
@ -11,6 +11,7 @@ import { DashboardView } from '../views/dashboard';
|
|||
|
||||
import rpc from '../../services/api';
|
||||
import store from '../../config/electron-store';
|
||||
import { SAPLING } from '../constants/zcash-network';
|
||||
import { listShieldedTransactions } from '../../services/shielded-transactions';
|
||||
import { sortByDescend } from '../utils/sort-by-descend';
|
||||
|
||||
|
@ -70,7 +71,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|||
])([...transactions, ...listShieldedTransactions()]);
|
||||
|
||||
if (!zAddresses.length) {
|
||||
const [, newZAddress] = await eres(rpc.z_getnewaddress());
|
||||
const [, newZAddress] = await eres(rpc.z_getnewaddress(SAPLING));
|
||||
|
||||
if (newZAddress) zAddresses.push(newZAddress);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
|||
import { BigNumber } from 'bignumber.js';
|
||||
|
||||
import { ReceiveView } from '../views/receive';
|
||||
import { SAPLING } from '../constants/zcash-network';
|
||||
|
||||
import {
|
||||
loadAddressesSuccess,
|
||||
|
@ -74,7 +75,7 @@ const mapDispatchToProps = (dispatch: Dispatch): MapDispatchToProps => ({
|
|||
},
|
||||
getNewAddress: async ({ type }) => {
|
||||
const [error, address] = await eres(
|
||||
type === 'shielded' ? rpc.z_getnewaddress() : rpc.getnewaddress(''),
|
||||
type === 'shielded' ? rpc.z_getnewaddress(SAPLING) : rpc.getnewaddress(''),
|
||||
);
|
||||
|
||||
if (error || !address) return dispatch(getNewAddressError({ error: 'Unable to generate a new address' }));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import electronStore from '../../../config/electron-store';
|
||||
|
||||
import { ZCASH_NETWORK, EMBEDDED_DAEMON } from '../../constants/zcash-network';
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import type { Action } from '../../types/redux';
|
||||
|
||||
export const SEND_TRANSACTION = 'SEND_TRANSACTION';
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import uniqBy from 'lodash.uniqby';
|
||||
import type { Action } from '../../types/redux';
|
||||
import type { Transaction } from '../../components/transaction-item';
|
||||
|
|
|
@ -72,7 +72,7 @@ const AmountWrapper = styled.div`
|
|||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: ${getCoinName()};
|
||||
content: '${getCoinName()}';
|
||||
font-family: ${props => props.theme.fontFamily};
|
||||
position: absolute;
|
||||
margin-top: 16px;
|
||||
|
@ -286,6 +286,15 @@ const HexadecimalText = styled(TextComponent)`
|
|||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const MemoValidationText = styled(TextComponent)`
|
||||
padding: 10px 5px;
|
||||
margin: 0px 0 8.5px 0;
|
||||
text-transform: uppercase;
|
||||
color: ${props => props.theme.colors.transactionSent};
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
`;
|
||||
|
||||
const SimpleTooltip = styled.div`
|
||||
background: ${props => props.theme.colors.walletAddressTooltipBg};
|
||||
position: absolute;
|
||||
|
@ -810,7 +819,7 @@ class Component extends PureComponent<Props, State> {
|
|||
/>
|
||||
</>
|
||||
)}
|
||||
{!isValidMemo && <TextComponent value='Please enter a valid hexadecimal memo' />}
|
||||
{!isValidMemo && <MemoValidationText value='Please enter a valid hexadecimal memo' />}
|
||||
<ActionsWrapper>
|
||||
<ShowFeeButton
|
||||
id='send-show-additional-options-button'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import eres from 'eres';
|
||||
import processExists from 'process-exists';
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import type { ChildProcess } from 'child_process';
|
|||
import eres from 'eres';
|
||||
import uuid from 'uuid/v4';
|
||||
import findProcess from 'find-process';
|
||||
|
||||
/* eslint-disable-next-line import/named */
|
||||
import { mainWindow } from '../electron';
|
||||
import waitForDaemonClose from './wait-for-daemon-close';
|
||||
|
|
|
@ -54,6 +54,8 @@ const createWindow = () => {
|
|||
});
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
minWidth: 700,
|
||||
minHeight: 600,
|
||||
width: 1000,
|
||||
height: 660,
|
||||
transparent: false,
|
||||
|
@ -61,7 +63,8 @@ const createWindow = () => {
|
|||
resizable: true,
|
||||
webPreferences: {
|
||||
devTools: true,
|
||||
webSecurity: false,
|
||||
// devTools: false,
|
||||
webSecurity: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { typeof app as ElectronApp, type electron$BrowserWindow, remote } from 'electron'; // eslint-disable-line
|
||||
import store from './electron-store';
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import electronStore from './electron-store';
|
||||
import { ZCASH_NETWORK, MAINNET } from '../app/constants/zcash-network';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "zepio",
|
||||
"version": "0.4.6",
|
||||
"version": "0.5.0",
|
||||
"description": "Zepio",
|
||||
"main": "config/main.js",
|
||||
"license": "MIT",
|
||||
|
|
Loading…
Reference in New Issue