Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local Development Environment For Wallet #615

Merged
merged 3 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/default.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function configureAWSBucket() {
const bucket = 'nightfallv3';
const mode = process.env.MODE; // options are 'local', 'internal', 'preprod', 'production', 'staging', and 'testnet'
const mode = process.env.REACT_APP_MODE; // options are 'local', 'internal', 'preprod', 'production', 'staging', and 'testnet'
if (mode === 'local') return bucket;
return `${bucket}-${mode}`;
}
Expand Down
56 changes: 32 additions & 24 deletions wallet/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
# Wallet

## Testing ERC Contracts
For testing purposes, account `0x9C8B2276D490141Ae1440Da660E470E7C0349C63` with privateKey `0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e` has been setup in testnet wit some Ether and some ERC tokens.

## How is nightfall's mnemonic stored?
When connecting with Metamask to your nightfall account for the first time, you will be prompted to enter a twelve word
mnemonic. This mnemonic is used by nightfall to generate your personal set of keys that will allow you to operate on nighrfall.
You need to save this 12 word seed in a safe place, as it is the only way to recover your nightfall account.
This wallet offers a backup, but this backup is only a convenient way to log in to your account without entering the mnemonic, and
must no be relied to provide a permanent backup.
If you select to backup your nightfall mnemonic, it will be encrypted in local storage using as a key the result of hashing as signed message via Metamask. When logging back, you will be request to sign a message to decript the mnemonic and unlock your metamask account.

## How to generate different keys from a single mnemonic?
When you login to nightfall, you will be using account index 0. You can select a different index in `Account Settings` to use a different set of keys.

## Tests
*Updates : E2E test is not working, not maintained currently*
To launch test, set these `NETWORK_NAME`, `RPC_URL`, `CHAIN_ID`, and `PRIVATE_KEY` environment variable in local machine and then run
```sh
npm run e2e-test
```
### For example
If launching test (e2e test) locally with Ganache.
1. Follow instruction [here](https://github.com/EYBlockchain/nightfall_3#wallet) to start wallet app with ganache.
2. Run `e2e-test` npm script in wallet director `NETWORK_NAME=ganache-nightfall RPC_URL=http://localhost:8546 CHAIN_ID=1337 PRIVATE_KEY=0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e npm run e2e-test`
### Running the Wallet locally
1. Install dependencies
`npm ci`

2. Local development uses the ERC20Mock token deployed by `nightfall-deployer`.
To make changes to the tokens used in the wallet for local development, look at `src/static/supported-token-list/supported-tokens-testnet.ts`

3. Start nightfall in development mode
`cd ..`
`./start-nightfall -g -d -s`

4. Start the wallet in local development mode.
`npm run start`

5. Ensure that your account used in metamask has the same tokens as supported by the wallet (See 2);

6. It is usually good practice to reset your local browser state between runs.

### Resetting Local Browser State

#### **Reset Browser DBs**
The browser db is persistent between runs and not clearing them will cause untold issues.
- Open developer console in the browser.
- Navigate to the Application tab
- In the left hand column, under storage, select IndexedDB.
- Click on Nightfall Commitments and delete the database.
- Click on local storage in the same column.
- Right click on the localhost:3000 entry and click on Clear.

#### **Reset Metamask**
Metamask nonces will be persistent between runs not resetting them will cause untold issues.
- Go to Metamask > Settings > Advanced > Reset Account.
8 changes: 7 additions & 1 deletion wallet/craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ BigInt.prototype.toJSON = function () {
return this.toString();
};

const path = require(`path`);

module.exports = {
webpack: {
alias: {},
alias: {
'@TokenList': path.resolve(__dirname, `src/static/supported-token-lists/`),
'@Nightfall': path.resolve(__dirname, `src/nightfall-browser/`),
'@Components': path.resolve(__dirname, `src/components/`),
},
plugins: {
add: [
new WebpackManifestPlugin({
Expand Down
8 changes: 7 additions & 1 deletion wallet/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
"zokrates-js": "^1.0.39"
},
"scripts": {
"start": "LOCAL_PROPOSER=true USE_STUBS=true craco start",
"start": "LOCAL_PROPOSER=true USE_STUBS=true REACT_APP_MODE=local craco start",
"start:docker": "REACT_APP_ENVIRONMENT=Docker PORT=3010 craco start",
"start:ropsten": "REACT_APP_ENVIRONMENT=Ropsten craco start",
"build": "LOCAL_PROPOSER=false USE_STUBS=true craco build",
"build": "LOCAL_PROPOSER=false USE_STUBS=false REACT_APP_MODE=test craco build",
"deploy": "npm run build && aws s3 sync build s3://pnf-dev-browser --cache-control max-age=172800 --delete && aws configure set preview.cloudfront true && aws cloudfront create-invalidation --distribution-id ENV3X13MLR5YT --paths \"/*\"",
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'tests/**/*.ts'",
"eject": "craco eject",
Expand Down
26 changes: 11 additions & 15 deletions wallet/src/components/BridgeComponent/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { MdArrowForwardIos } from 'react-icons/md';
import { toast } from 'react-toastify';
import { useLocation } from 'react-router-dom';
import axios from 'axios';
import importTokens from '@TokenList/index';
import deposit from '@Nightfall/services/deposit';
import withdraw from '@Nightfall/services/withdraw';
import { getWalletBalance } from '@Nightfall/services/commitment-storage';
import { decompressKey } from '@Nightfall/services/keys';
import { saveTransaction } from '@Nightfall/services/database';
import styles from '../../styles/bridge.module.scss';
import stylesModal from '../../styles/modal.module.scss';
import ethChainImage from '../../assets/img/ethereum-chain.svg';
Expand All @@ -12,27 +18,23 @@ import discloserBottomImage from '../../assets/img/discloser-bottom.svg';
import lightArrowImage from '../../assets/img/light-arrow.svg';
import { approve, getContractAddress, submitTransaction } from '../../common-files/utils/contract';
import Web3 from '../../common-files/utils/web3';
import deposit from '../../nightfall-browser/services/deposit';
import withdraw from '../../nightfall-browser/services/withdraw';
import approveImg from '../../assets/img/modalImages/adeposit_approve1.png';
import depositConfirmed from '../../assets/img/modalImages/adeposit_confirmed.png';
import successHand from '../../assets/img/modalImages/success-hand.png';
import transferCompletedImg from '../../assets/img/modalImages/tranferCompleted.png';
import { UserContext } from '../../hooks/User/index.jsx';
import './styles.scss';
import Input from '../Input/index.tsx';
import TokensList from '../Modals/Bridge/TokensList/index.tsx';
import TokensList from '../Modals/Bridge/index.tsx';
import { useAccount } from '../../hooks/Account/index.tsx';
import { getWalletBalance } from '../../nightfall-browser/services/commitment-storage';
import './toast.css';
import ERC20 from '../../contract-abis/ERC20.json';
import tokensList from '../Modals/Bridge/TokensList/tokensList';
import { APPROVE_AMOUNT } from '../../constants';
import { retrieveAndDecrypt } from '../../utils/lib/key-storage';
import { decompressKey } from '../../nightfall-browser/services/keys';
import { saveTransaction } from '../../nightfall-browser/services/database';
import BigFloat from '../../common-files/classes/bigFloat';

const supportedTokens = importTokens();

const { proposerUrl } = global.config;

// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -47,11 +49,10 @@ const BridgeComponent = () => {
const [l2Balance, setL2Balance] = useState(0n);
const [shieldContractAddress, setShieldAddress] = useState('');
const location = useLocation();

const initialTx = location?.tokenState?.initialTxType ?? 'deposit';
const initialToken =
tokensList.tokens.find(t => t.address.toLowerCase() === location?.tokenState?.tokenAddress) ??
tokensList.tokens[0];
supportedTokens.find(t => t.address.toLowerCase() === location?.tokenState?.tokenAddress) ??
supportedTokens[0];

const [token, setToken] = useState(initialToken);
const [txType, setTxType] = useState(initialTx);
Expand Down Expand Up @@ -146,8 +147,6 @@ const BridgeComponent = () => {
async function triggerTx() {
if (shieldContractAddress === '')
setShieldAddress((await getContractAddress('Shield')).data.address);
// const { address } = (await getContractAddress('ERC20Mock')).data; // TODO Only for testing now
// const ercAddress = address; // TODO Location to be removed later
const ercAddress = token.address;
console.log('ercAddress', ercAddress);
const zkpKeys = await retrieveAndDecrypt(state.compressedPkd);
Expand Down Expand Up @@ -228,8 +227,6 @@ const BridgeComponent = () => {
async function updateL1Balance() {
console.log('L1 Balance');
if (token && token?.address) {
// const { address } = (await getContractAddress('ERC20Mock')).data; // TODO REMOVE THIS WHEN OFFICIAL ADDRESSES
// console.log('ERC20', defaultTokenAddress);
const contract = new window.web3.eth.Contract(ERC20, token.address);
const result = await contract.methods.balanceOf(accountInstance.address).call(); // 29803630997051883414242659
setL1Balance(result);
Expand All @@ -240,7 +237,6 @@ const BridgeComponent = () => {

async function updateL2Balance() {
if (token && token.address) {
// const { address } = (await getContractAddress('ERC20Mock')).data; // TODO REMOVE THIS WHEN OFFICIAL ADDRESSES
const l2bal = await getWalletBalance(state.compressedPkd);
if (Object.hasOwnProperty.call(l2bal, state.compressedPkd))
setL2Balance(l2bal[state.compressedPkd][token.address.toLowerCase()] ?? 0n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ import React, { useState, Dispatch, SetStateAction, ChangeEvent } from 'react';
import './styles.scss';
import { FiSearch } from 'react-icons/fi';
import Modal from 'react-bootstrap/Modal';
import tokensList from './tokensList';
import TokenType from './TokenType';
import importTokens from '@TokenList/index';
import TokenType from '@TokenList/TokenType';

const supportedTokens = importTokens();

type TokenListType = {
handleClose: Dispatch<SetStateAction<boolean>>;
setToken: Dispatch<SetStateAction<TokenType>>;
};

const TokensList = ({ handleClose, setToken }: TokenListType): JSX.Element => {
const [filteredTokens, setFilteredTokens] = useState(tokensList.tokens);
const [filteredTokens, setFilteredTokens] = useState(supportedTokens);

const filterTokens = (e: ChangeEvent<HTMLInputElement>) => {
setFilteredTokens(
tokensList.tokens.filter(token =>
supportedTokens.filter((token: any) =>
token.name.toLowerCase().includes(e.target.value.toLocaleLowerCase()),
),
);
Expand Down
4 changes: 2 additions & 2 deletions wallet/src/components/Modals/instantWithdrawal.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useState } from 'react';
import { Button, Col, FormControl, InputGroup, Modal, ProgressBar, Row } from 'react-bootstrap';
import { markWithdrawState } from '@Nightfall/services/database';
import setInstantWithdrawl from '@Nightfall/services/instant-withdrawal';
import { getContractAddress, submitTransaction } from '../../common-files/utils/contract';
import { markWithdrawState } from '../../nightfall-browser/services/database';
import setInstantWithdrawl from '../../nightfall-browser/services/instant-withdrawal';
import './index.scss';

interface InstantWithdrawProps {
Expand Down
21 changes: 12 additions & 9 deletions wallet/src/components/Modals/sendModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import Modal from 'react-bootstrap/Modal';
import { AiOutlineDown } from 'react-icons/ai';
import { FiSearch } from 'react-icons/fi';
import axios from 'axios';
import tokensList from './Bridge/TokensList/tokensList';
import importTokens from '@TokenList/index';
import TokenType from '@TokenList/TokenType';
import transfer from '@Nightfall/services/transfer';
import { getWalletBalance } from '@Nightfall/services/commitment-storage';
import { saveTransaction } from '@Nightfall/services/database';
import stylesModal from '../../styles/modal.module.scss';
import { UserContext } from '../../hooks/User';
import maticImg from '../../assets/img/polygon-chain.svg';
import transfer from '../../nightfall-browser/services/transfer';
import { retrieveAndDecrypt } from '../../utils/lib/key-storage';
import { getContractAddress } from '../../common-files/utils/contract';
import { getWalletBalance } from '../../nightfall-browser/services/commitment-storage';
import styles from '../../styles/bridge.module.scss';
import approveImg from '../../assets/img/modalImages/adeposit_approve1.png';
import depositConfirmed from '../../assets/img/modalImages/adeposit_confirmed.png';
import successHand from '../../assets/img/modalImages/success-hand.png';
import transferCompletedImg from '../../assets/img/modalImages/tranferCompleted.png';
import { saveTransaction } from '../../nightfall-browser/services/database';
import BigFloat from '../../common-files/classes/bigFloat';

const supportedTokens = importTokens();

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { proposerUrl } = global.config;
Expand All @@ -43,7 +47,7 @@ const SendModal = (props: SendModalProps): JSX.Element => {
const { onHide, show, ...initialSendToken } = props;
const [sendToken, setSendToken] = useState(initialSendToken);
const [filteredTokens, setFilteredTokens] = useState(
tokensList.tokens.map(({ name, symbol, address, logoURI, decimals }) => {
supportedTokens.map(({ name, symbol, address, logoURI, decimals }) => {
return {
name,
symbol,
Expand All @@ -58,9 +62,9 @@ const SendModal = (props: SendModalProps): JSX.Element => {
const [l2Balance, setL2Balance] = useState(0n);
const [showTokensListModal, setShowTokensListModal] = useState(false);

const filterTxs = (criteria: string) =>
tokensList.tokens
.filter(t => t.name.toLowerCase().includes(criteria))
const filterTxs = (criteria: string): any[] =>
supportedTokens
.filter((t: TokenType) => t.name.toLowerCase().includes(criteria))
.map(({ name, symbol, address, logoURI, decimals }) => {
return {
name,
Expand Down Expand Up @@ -154,7 +158,6 @@ const SendModal = (props: SendModalProps): JSX.Element => {
await timeout(2000);
setShowModalTransferInProgress(false);
setShowModalTransferEnRoute(true);
// const { address } = (await getContractAddress('ERC20Mock')).data; // TODO Only for testing now
const { transaction, rawTransaction } = await transfer(
{
offchain: true,
Expand Down
6 changes: 3 additions & 3 deletions wallet/src/components/Modals/txInfoModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { Button, Col, Modal, Row } from 'react-bootstrap';
import { markWithdrawState } from '@Nightfall/services/database';
import { finaliseWithdrawal } from '@Nightfall/services/finalise-withdrawal';
import { isValidWithdrawal } from '@Nightfall/services/valid-withdrawal';
import { getContractAddress, submitTransaction } from '../../common-files/utils/contract';
import { markWithdrawState } from '../../nightfall-browser/services/database';
import { finaliseWithdrawal } from '../../nightfall-browser/services/finalise-withdrawal';
import { isValidWithdrawal } from '../../nightfall-browser/services/valid-withdrawal';
import stylesModal from '../../styles/modal.module.scss';

interface TxModalProps {
Expand Down
8 changes: 5 additions & 3 deletions wallet/src/components/TokenItem/index.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import importTokens from '@TokenList/index';
import { getWalletBalance } from '@Nightfall/services/commitment-storage';
import styles from '../../styles/tokenItem.module.scss';
import metamaskIcon from '../../assets/svg/metamask.svg';
import { UserContext } from '../../hooks/User/index.jsx';
import tokensList from '../Modals/Bridge/TokensList/tokensList';
import { getWalletBalance } from '../../nightfall-browser/services/commitment-storage';
import SendModal from '../Modals/sendModal';

const supportedTokens = importTokens();

export default function TokenItem(props) {
const [showSendModal, setShowSendModal] = useState(false);
const [state] = React.useContext(UserContext);
const [filteredTokens, setFilteredTokens] = useState(tokensList.tokens);
const [filteredTokens, setFilteredTokens] = useState(supportedTokens);

useEffect(async () => {
const l2bal = await getWalletBalance(state.compressedPkd);
Expand Down
Loading