diff --git a/README.md b/README.md index 5ba91d6..231ae29 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,12 @@ npx cap sync npx cap update ``` -two last commands are synced code for android and ios. +two last commands are synced code for android and ios. if you want to build for desktop you must enter these two commands to sync code + +``` +npx cap sync electron +npx cap sync update electron +``` ### Android @@ -63,10 +68,12 @@ IOS users can open ios project in code, open it in xcode and build any version t ### Desktop systems -for desktop systems you can use electron use command below +To build desktop version of project you must enter to electron directory and build project ``` -npm run build:electron: +npm run build +npm run electron:pack +npm run electron:make ``` diff --git a/electron/src/index.ts b/electron/src/index.ts index 69784d8..404aea4 100644 --- a/electron/src/index.ts +++ b/electron/src/index.ts @@ -4,7 +4,7 @@ import type { MenuItemConstructorOptions } from 'electron'; import { app, MenuItem } from 'electron'; import electronIsDev from 'electron-is-dev'; import unhandled from 'electron-unhandled'; -import { autoUpdater } from 'electron-updater'; +// import { autoUpdater } from 'electron-updater'; import { ElectronCapacitorApp, setupContentSecurityPolicy, setupReloadWatcher } from './setup'; @@ -46,7 +46,7 @@ if (electronIsDev) { // Initialize our app, build windows, and load content. await myCapacitorApp.init(); // Check for updates if we are in a packaged app. - autoUpdater.checkForUpdatesAndNotify(); + // autoUpdater.checkForUpdatesAndNotify(); })(); // Handle when all of our windows are close (platforms have their own expectations). diff --git a/electron/src/setup.ts b/electron/src/setup.ts index e6dabe9..91469a6 100644 --- a/electron/src/setup.ts +++ b/electron/src/setup.ts @@ -212,9 +212,9 @@ export class ElectronCapacitorApp { this.MainWindow.show(); } setTimeout(() => { - // if (electronIsDev) { + if (electronIsDev) { this.MainWindow.webContents.openDevTools(); - // } + } CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', ''); }, 400); }); diff --git a/src/api/wallet-add/WalletCreate.tsx b/src/api/wallet-add/WalletCreate.tsx index 7c00974..02a4a8a 100644 --- a/src/api/wallet-add/WalletCreate.tsx +++ b/src/api/wallet-add/WalletCreate.tsx @@ -5,7 +5,7 @@ import * as walletActions from "../../action/wallet"; import Stepper from "@material-ui/core/Stepper"; import Step from "@material-ui/core/Step"; import StepLabel from "@material-ui/core/StepLabel"; -import WalletName from "./WalletName"; +import WalletName from "./elements/WalletName"; import WalletTypeSelect from "./elements/WalletTypeSelect"; import { NETWORK_TYPES } from "../../config/network_type"; import WalletPassword from "./WalletPassword"; @@ -17,7 +17,7 @@ interface PropsType extends RouteComponentProps { interface StateType { mnemonic: string; - mnemonicPassPhrase: string; + mnemonic_passphrase: string; step: number; name: string; type: WalletType; @@ -29,7 +29,7 @@ interface StateType { class WalletCreate extends React.Component { state: StateType = { mnemonic: "", - mnemonicPassPhrase: "", + mnemonic_passphrase: "", step: 0, name: "", type: WalletType.Normal, @@ -43,8 +43,8 @@ class WalletCreate extends React.Component { "Password" ]; - gotoMnemonic = (name: string, password: string) => { - this.setState({ name: name, mnemonicPassPhrase: password, step: 1 }); + gotoMnemonic = (name: string) => { + this.setState({ name: name, step: 1 }); }; goPassword = () => { @@ -55,8 +55,8 @@ class WalletCreate extends React.Component { this.setState({ step: 0 }); }; - goConfirm = (mnemonic: string, network: string) => { - this.setState({ mnemonic: mnemonic, step: 2, network_type: network }); + goConfirm = (mnemonic: string, network: string, mnemonic_passphrase: string) => { + this.setState({ mnemonic: mnemonic, step: 2, network_type: network, mnemonic_passphrase: mnemonic_passphrase }); }; saveWallet = (password: string) => { @@ -66,7 +66,7 @@ class WalletCreate extends React.Component { this.state.name, this.state.type, this.state.mnemonic, - this.state.mnemonicPassPhrase, + this.state.mnemonic_passphrase, this.state.network_type, password ).then(() => { @@ -81,10 +81,8 @@ class WalletCreate extends React.Component { renderName = () => ( this.gotoMnemonic(name, password)}> + goForward={(name) => this.gotoMnemonic(name)}> <>

Enter wallet name and password.

this.setState({ type: value })} /> @@ -95,7 +93,7 @@ class WalletCreate extends React.Component { renderPassword = () => ( this.saveWallet(password)} - goBack={() => this.goConfirm(this.state.mnemonic, this.state.network_type)} + goBack={() => this.goConfirm(this.state.mnemonic, this.state.network_type, this.state.mnemonic_passphrase)} />) renderMnemonic = (): ReactNode | null => null; diff --git a/src/api/wallet-add/elements/MnemonicPassword.tsx b/src/api/wallet-add/elements/MnemonicPassword.tsx new file mode 100644 index 0000000..fcdc640 --- /dev/null +++ b/src/api/wallet-add/elements/MnemonicPassword.tsx @@ -0,0 +1,68 @@ +import React, { useEffect, useState } from "react"; +import { Checkbox, Container, FormControlLabel, Grid } from "@material-ui/core"; +import PasswordInput from "../../../components/PasswordInput"; + +interface PropsType { + password: string; + valid: boolean; + confirm?: boolean; + goBack?: () => any; + setPassword: (password: string, valid: boolean) => any; +} + +const MnemonicPassword = (props: PropsType) => { + const [usePassword, setUsePassword] = useState(!!props.password); + const [password, setPassword] = useState(props.password ? props.password : ""); + const [passwordConfirm, setPasswordConfirm] = useState(props.password ? props.password : ""); + + const validatePasswordConfirm = () => { + if (!props.confirm || !usePassword) return ""; + return (passwordConfirm !== password) ? "Passwords are not same" : ""; + }; + useEffect(() => { + const valid = validatePasswordConfirm() === ''; + const aggregated_password = usePassword ? password : "" + if(props.password !== aggregated_password || valid !== props.valid){ + props.setPassword(aggregated_password, valid) + } + }) + return ( + + + setUsePassword(event.target.checked)} + name="use Password" + color="primary" + /> + } + label="Extend Mnemonic using extra password" + /> + + {usePassword ? ( + + + { + props.confirm ? ( + + ) : null + } + + ) : null} + + ); + +}; + + +export default MnemonicPassword; diff --git a/src/api/wallet-add/WalletName.tsx b/src/api/wallet-add/elements/WalletName.tsx similarity index 50% rename from src/api/wallet-add/WalletName.tsx rename to src/api/wallet-add/elements/WalletName.tsx index 9a37e4b..a32dfcc 100644 --- a/src/api/wallet-add/WalletName.tsx +++ b/src/api/wallet-add/elements/WalletName.tsx @@ -1,34 +1,22 @@ import React, { useState } from "react"; import { Button, Container, Grid } from "@material-ui/core"; -import PasswordInput from "../../components/PasswordInput"; -import TextInput from "../../components/TextInput"; +import TextInput from "../../../components/TextInput"; interface PropsType { name: string; - password?: string; - hidePassword?: boolean; - hideDbPassword?: boolean; - confirm?: boolean; goBack?: () => any; - goForward: (name: string, password: string) => any; + goForward: (name: string) => any; children: React.ReactElement; } const WalletName = (props: PropsType) => { const [name, setName] = useState(props.name); - const [password, setPassword] = useState(props.password ? props.password : ""); - const [passwordConfirm, setPasswordConfirm] = useState(props.password ? props.password : ""); - - const validatePasswordConfirm = () => { - if (props.hidePassword || !props.confirm) return ""; - return (passwordConfirm !== password) ? "Passwords are not same" : ""; - }; const validateName = () => { return (name === "") ? "Name must entered" : ""; }; const formValid = () => { - return validatePasswordConfirm() + validateName() === ""; + return validateName() === ""; }; return ( @@ -44,22 +32,6 @@ const WalletName = (props: PropsType) => { error={validateName()} value={name} setValue={setName} /> - {props.hidePassword ? null : ( - - - {props.confirm ? ( - - ) : null} - - )} @@ -74,7 +46,7 @@ const WalletName = (props: PropsType) => { diff --git a/src/api/wallet-add/insert/InsertWallet.tsx b/src/api/wallet-add/insert/InsertWallet.tsx index 6056828..8c5ec3e 100644 --- a/src/api/wallet-add/insert/InsertWallet.tsx +++ b/src/api/wallet-add/insert/InsertWallet.tsx @@ -1,5 +1,5 @@ import React from "react"; -import WalletName from "../WalletName"; +import WalletName from "../elements/WalletName"; import Mnemonic from "./Mnemonic"; import MnemonicConfirm from "./MnemonicConfirm"; import { withRouter } from "react-router-dom"; @@ -10,10 +10,8 @@ class InsertWallet extends WalletCreate { renderName = () => ( this.gotoMnemonic(name, password)}> + goForward={(name) => this.gotoMnemonic(name)}> <> Enter new wallet name and password.

@@ -27,10 +25,10 @@ class InsertWallet extends WalletCreate { renderMnemonic = () => ( this.goBackName()} network={this.state.network_type} - goForward={(mnemonic: string, network: string) => this.goConfirm(mnemonic, network)} /> - + goForward={(mnemonic: string, network: string, mnemonic_passphrase: string) => this.goConfirm(mnemonic, network, mnemonic_passphrase)} /> ); renderConfirm = () => ( diff --git a/src/api/wallet-add/insert/Mnemonic.tsx b/src/api/wallet-add/insert/Mnemonic.tsx index 01da60e..19f434e 100644 --- a/src/api/wallet-add/insert/Mnemonic.tsx +++ b/src/api/wallet-add/insert/Mnemonic.tsx @@ -3,11 +3,13 @@ import { generateMnemonic } from "bip39"; import { Container, Grid, Button } from "@material-ui/core"; import MnemonicView from "../elements/MnemonicView"; import WalletNetworkSelect from "../elements/WalletNetworkSelect"; +import MnemonicPassword from "../elements/MnemonicPassword"; interface PropsType { mnemonic?: string; + mnemonic_passphrase: string; goBack: () => any; - goForward: (mnemonic: string, network: string) => any; + goForward: (mnemonic: string, network: string, mnemonic_passphrase: string) => any; network: string; } @@ -15,11 +17,15 @@ const Mnemonic = (props: PropsType) => { const initialMnemonic = props.mnemonic ? props.mnemonic : generateMnemonic(160); const [mnemonic] = useState(initialMnemonic); const [network, setNetwork] = useState(props.network); + const [mnemonic_passphrase, set_mnemonic_passphrase] = useState<{ password: string, valid: boolean }>({ + password: props.mnemonic_passphrase, + valid: true + }); return ( - setNetwork(newNetwork)}/> + setNetwork(newNetwork)} />

Create Wallet

@@ -33,6 +39,18 @@ const Mnemonic = (props: PropsType) => {
+ + + set_mnemonic_passphrase({ + password, + valid + })} /> + + - diff --git a/src/api/wallet-add/readonly/ReadOnlyWallet.tsx b/src/api/wallet-add/readonly/ReadOnlyWallet.tsx index d565319..0df9242 100644 --- a/src/api/wallet-add/readonly/ReadOnlyWallet.tsx +++ b/src/api/wallet-add/readonly/ReadOnlyWallet.tsx @@ -1,6 +1,6 @@ import React from "react"; import WalletCreate from "../WalletCreate"; -import WalletName from "../WalletName"; +import WalletName from "../elements/WalletName"; import { withRouter } from "react-router-dom"; import ReadOnlyWalletAddress from "./ReadOnlyWalletAddress"; import * as walletActions from '../../../action/wallet'; @@ -13,11 +13,9 @@ class ReadOnlyWallet extends WalletCreate { ]; renderName = () => ( this.gotoMnemonic(name, password)}> + goForward={(name) => this.gotoMnemonic(name)}> <> Enter new wallet name.

diff --git a/src/api/wallet-add/restore/Mnemonic.tsx b/src/api/wallet-add/restore/Mnemonic.tsx index c1d1e69..2843e6b 100644 --- a/src/api/wallet-add/restore/Mnemonic.tsx +++ b/src/api/wallet-add/restore/Mnemonic.tsx @@ -4,11 +4,13 @@ import MnemonicView from "../elements/MnemonicView"; import { wordlists, getDefaultWordlist, mnemonicToEntropy } from "bip39"; import { Autocomplete } from "@material-ui/lab"; import WalletNetworkSelect from "../elements/WalletNetworkSelect"; +import MnemonicPassword from "../elements/MnemonicPassword"; interface PropsType { mnemonic?: string; goBack: () => any; - goForward: (mnemonic: string, network: string) => any; + mnemonic_passphrase: string; + goForward: (mnemonic: string, network: string, mnemonic_passphrase: string) => any; network: string; } @@ -19,6 +21,10 @@ const Mnemonic = (props: PropsType) => { const [mnemonicValid, setMnemonicValid] = useState(true); const [selected, setSelected] = useState(""); const [network, setNetwork] = useState(props.network); + const [mnemonic_passphrase, set_mnemonic_passphrase] = useState<{ password: string, valid: boolean }>({ + password: props.mnemonic_passphrase, + valid: true + }); const selectElement = (element: string) => { if (words.indexOf(element) !== -1) { setMnemonic(mnemonic ? mnemonic + " " + element : element); @@ -106,6 +112,13 @@ const Mnemonic = (props: PropsType) => { ) : null} + + set_mnemonic_passphrase({ password, valid })} /> + @@ -117,8 +130,8 @@ const Mnemonic = (props: PropsType) => { diff --git a/src/api/wallet-add/restore/RestoreWallet.tsx b/src/api/wallet-add/restore/RestoreWallet.tsx index 3502517..35c0b9d 100644 --- a/src/api/wallet-add/restore/RestoreWallet.tsx +++ b/src/api/wallet-add/restore/RestoreWallet.tsx @@ -14,15 +14,16 @@ class RestoreWallet extends WalletCreate { renderMnemonic = () => ( this.goBackName()} - goForward={(mnemonic: string, network: string) => this.goConfirm(mnemonic, network)} /> + goForward={(mnemonic: string, network: string, mnemonic_passphrase: string) => this.goConfirm(mnemonic, network, mnemonic_passphrase)} /> ); renderConfirm = () => ( this.setState({ step: 1 })} goForward={this.goPassword} /> ); diff --git a/src/api/wallet/dapps/DAppList.tsx b/src/api/wallet/dapps/DAppList.tsx index 6565778..3176173 100644 --- a/src/api/wallet/dapps/DAppList.tsx +++ b/src/api/wallet/dapps/DAppList.tsx @@ -4,11 +4,8 @@ import DAppListElement from "./DAppListElement"; import { RouteComponentProps, withRouter } from "react-router-dom"; import { RouteMap, getRoute } from "../../../router/routerMap"; import { WalletPagePropsType } from "../../../utils/interface"; +import { apps } from "./dapps"; -export const apps = [ - { name: "Issue Token", description: "Issue new token using EIP-004", id: "issueToken" }, - { name: "SigmaUSD", description: "Buy or sell SigmaUSD and SigmaRSV", id: "sigmaUsd" } -]; interface DAppListPropsTypes extends WalletPagePropsType, RouteComponentProps<{ id: string }> { diff --git a/src/api/wallet/dapps/DAppView.tsx b/src/api/wallet/dapps/DAppView.tsx index 31e4ad3..b51cb42 100644 --- a/src/api/wallet/dapps/DAppView.tsx +++ b/src/api/wallet/dapps/DAppView.tsx @@ -12,13 +12,18 @@ import { GlobalStateType } from "../../../store/reducer"; import { connect } from "react-redux"; import WithAppBar from "../../../layout/WithAppBar"; import AppHeader from "../../../header/AppHeader"; -import { apps } from "./DAppList"; +import { apps } from "./dapps"; import Loading from "../../../components/Loading"; import GenerateTransactionBottomSheet from "../../../components/GenerateTransactionBottomSheet"; import { UnsignedGeneratedTx } from "../../../utils/interface"; import { getNetworkType } from "../../../config/network_type"; import SigmaUSD from "./apps/sigmausd/SigmaUSD"; import { getSingleTokenWithAddressForWallet } from "../../../db/action/boxContent"; +import IconButton from "@material-ui/core/IconButton"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faInfoCircle } from "@fortawesome/free-solid-svg-icons"; +import BottomSheet from "../../../components/bottom-sheet/BottomSheet"; +import { Container } from "@material-ui/core"; interface PropsType extends RouteComponentProps<{ id: string, dAppId: string }> { wallets_valid: boolean; @@ -31,12 +36,14 @@ interface StateType { display: boolean; transaction?: UnsignedGeneratedTx; title?: string; + show_description: boolean; } class DAppView extends React.Component { state: StateType = { display: false, - wallet_loading: false + wallet_loading: false, + show_description: false, }; loadContent = () => { @@ -108,11 +115,23 @@ class DAppView extends React.Component { }; }; + descriptionIcon = () => { + const dApp = this.getDApp(); + if(dApp && dApp.readme) { + return ( + this.setState({show_description: true})}> + + + ) + } + return null + } + render = () => { const dApp = this.getDApp(); if (dApp && this.state.wallet) { return ( - }> + }> {dApp.id === "issueToken" ? ( ) : null} @@ -126,6 +145,16 @@ class DAppView extends React.Component { wallet={this.state.wallet} transaction={this.state.transaction} /> ) : null} + {dApp && dApp.readme ? ( + this.setState({show_description: false})}> + + {dApp.readme} +
+
+
+
+
+ ) : null}
); } else { diff --git a/src/api/wallet/dapps/apps/sigmausd/SigmaUSD.tsx b/src/api/wallet/dapps/apps/sigmausd/SigmaUSD.tsx index 2b95fd1..c286311 100644 --- a/src/api/wallet/dapps/apps/sigmausd/SigmaUSD.tsx +++ b/src/api/wallet/dapps/apps/sigmausd/SigmaUSD.tsx @@ -377,14 +377,14 @@ class SigmaUSD extends React.Component { Sell SigmaRSV diff --git a/src/api/wallet/dapps/dapps.tsx b/src/api/wallet/dapps/dapps.tsx new file mode 100644 index 0000000..d5cfc67 --- /dev/null +++ b/src/api/wallet/dapps/dapps.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { Browser } from "@capacitor/browser"; + +const SigmaUSDReadme = () => ( +

+

What is SigmaUSD

+ SigmaUSD is an instance of AgeUSD protocol for Ergo blockchain. +
+
+ AgeUSD is a novel crypto-backed algorithmic stablecoin protocol + that has been created in joint partnership by the Ergo Foundation, + EMURGO, and IOG on top of the Ergo Blockchain. +
+
+ AgeUSD does not rely on CDPs (collateralized debt positions) + as is the current popular crypto-backed stablecoin design pattern. + This was a conscious design decision made due to the fragility of + CDP-based protocols in the face of sharp volatility and/or blockchain + congestion. +
+
+ This was epitomized during Black Thursday where MakerDAO CDPs were + triggered for liquidation due to volatility, + and then sold off for $0 due to blockchain congestion + which prevented others from bidding. +
+
+ Please note that this dApp itself is not the instance; + it only interacts with the deployed contracts on Ergo blockchain + which has been deployed by other anonymous community + members not connected with Emurgo or EF. +
+

Fees

+ The SigmaUSD protocol fee parameter are: +
+
    +
  1. 1% Protocol Fee
  2. +
  3. 0.2% Frontend Implementor Fee
  4. +
+ The protocol fee is charged on all minting/redeeming actions in the protocol (for both AgeUSD & ReserveCoins). + The Ergs from this fee go back to the protocol reserves, and as such profit the ReserveCoin holders directly. In + other words, if you hold ReserveCoins, you are not only rewarded in the scenario that the price of Erg goes up, + but also if a lot of people use the AgeUSD protocol. This provides further incentives for Reserve Providers to + ensure sufficient liquidity is always available so AgeUSD users can always mint AgeUSD. +
+
+ The frontend implementor fee is the fee that gets paid out to the frontend implementor who built a GUI on top of + the AgeUSD headless dApp. This fee payout is performed automatically as a part of every mint/redeem action. +
+
+ Browser.open({ url: `https://github.com/Emurgo/age-usd/blob/main/README.md` })}> + Read more about AgeUSD protocol here + +
+); +export const apps = [ + { name: "Issue Token", description: "Issue new token using EIP-004", id: "issueToken" }, + { name: "SigmaUSD", description: "Buy or sell SigmaUSD and SigmaRSV", readme: SigmaUSDReadme(), id: "sigmaUsd" } +]; diff --git a/src/app/Database/Database.tsx b/src/app/Database/Database.tsx index 7a9edd7..4c8302e 100644 --- a/src/app/Database/Database.tsx +++ b/src/app/Database/Database.tsx @@ -64,6 +64,9 @@ const Database = (props: PropsType) => { setConnected(true); setConnecting(false); }, 100); + }).catch(exp => { + setConnected(true); + setConnecting(false) }); }, 300); } diff --git a/src/components/SendConfirm.tsx b/src/components/SendConfirm.tsx index 14002b3..7b8e638 100644 --- a/src/components/SendConfirm.tsx +++ b/src/components/SendConfirm.tsx @@ -31,6 +31,7 @@ const SendConfirm = (props: PropsType) => { }).catch(exp => { show_notification(exp); }); + setPassword(""); }).catch(error => { show_notification(error); }); diff --git a/src/header/AppHeader.tsx b/src/header/AppHeader.tsx index 4d197ef..1767321 100644 --- a/src/header/AppHeader.tsx +++ b/src/header/AppHeader.tsx @@ -27,6 +27,7 @@ interface propTypes extends RouteComponentProps { back?: () => any; hideQrCode?: boolean; openQrCode: () => any; + extraIcons?: React.ReactNode | Array, } const WalletHeader = (props: propTypes) => { @@ -46,6 +47,7 @@ const WalletHeader = (props: propTypes) => { {props.title} + {props.extraIcons ? props.extraIcons : null} {props.hideQrCode ? null : (