diff --git a/package.json b/package.json index d5c5f9123..6c86fe2ab 100644 --- a/package.json +++ b/package.json @@ -87,14 +87,15 @@ "dependencies": { "@apollo/react-hooks": "^3.1.3", "@confio/relayer": "^0.4.0", - "@cosmjs/crypto": "^0.28.4", - "@cosmjs/encoding": "^0.28.4", - "@cosmjs/launchpad": "^0.27.1", - "@cosmjs/math": "^0.28.4", - "@cosmjs/proto-signing": "^0.28.4", - "@cosmjs/stargate": "^0.28.4", - "@cosmjs/tendermint-rpc": "^0.28.4", - "@cybercongress/cyber-js": "0.3.0", + "@cosmjs/amino": "0.28.4", + "@cosmjs/crypto": "0.28.4", + "@cosmjs/encoding": "0.28.4", + "@cosmjs/launchpad": "0.27.1", + "@cosmjs/math": "0.28.4", + "@cosmjs/proto-signing": "0.28.4", + "@cosmjs/stargate": "0.28.4", + "@cosmjs/tendermint-rpc": "0.28.4", + "@cybercongress/cyber-js": "0.3.1", "@cybercongress/gravity": "0.0.15", "@ledgerhq/hw-transport-u2f": "^4.72.1", "@ledgerhq/hw-transport-webusb": "5.53.0", diff --git a/src/components/ledger/stageActionBar.jsx b/src/components/ledger/stageActionBar.jsx index 703bc42ab..4d4537129 100644 --- a/src/components/ledger/stageActionBar.jsx +++ b/src/components/ledger/stageActionBar.jsx @@ -93,6 +93,14 @@ const imgRead = require('../../image/duplicate-outline.svg'); const imgEth = require('../../image/Ethereum_logo_2014.svg'); const imgCyber = require('../../image/large-green.png'); const imgCosmos = require('../../image/cosmos-2.svg'); +const imgCyberSigner = require('../../image/wallet-outline.svg'); + +const imgData = { + ledger: imgLedger, + keplr: imgKeplr, + cyber: imgCyber, + cyberSigner: imgCyberSigner, +}; const T = new LocalizedStrings(i18n); const ledger = require('../../image/select-pin-nano2.svg'); @@ -303,6 +311,7 @@ export const StartStageSearchActionBar = ({ textBtn = 'Cyberlink', placeholder = 'add keywords, hash or file', keys = 'ledger', + node, }) => { return ( @@ -378,9 +387,9 @@ export const StartStageSearchActionBar = ({ /> } - disabled={!contentHash.length} + disabled={node === null && !contentHash.length} onClick={onClickBtn} - img={keys === 'ledger' ? imgLedger : imgKeplr} + img={imgData[keys]} /> @@ -1432,6 +1441,12 @@ export const ConnectAddress = ({ )} + selectMethodFunc('cyberSigner')} + active={selectMethod === 'cyberSigner'} + img={imgCyberSigner} + text="cyberSigner" + /> )} {web3 && web3 !== null && ethNetwork && ( diff --git a/src/components/tabBtn/index.jsx b/src/components/tabBtn/index.jsx index 3b262da47..50dcdf993 100644 --- a/src/components/tabBtn/index.jsx +++ b/src/components/tabBtn/index.jsx @@ -2,8 +2,31 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Tab } from '@cybercongress/gravity'; -const TabBtn = ({ key, text, isSelected, onSelect, to, ...props }) => ( - +const TabBtn = ({ key, text, isSelected, onSelect, to, ...props }) => { + if (to) { + return ( + + + {text} + + + ); + } + return ( ( > {text} - -); + ); +}; export default TabBtn; diff --git a/src/containers/Search/ActionBar.jsx b/src/containers/Search/ActionBar.jsx new file mode 100644 index 000000000..df15d0b40 --- /dev/null +++ b/src/containers/Search/ActionBar.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import InnerActionBarContainer from './ActionBarContainer'; +import { AppContext, AppContextSigner } from '../../context'; + +const ActionBarContainer = (props) => { + return ( + + {(valueAppContext) => ( + + {(valueAppContextSigner) => ( + + )} + + )} + + ); +}; + +export default ActionBarContainer; diff --git a/src/containers/Search/ActionBarContainer.jsx b/src/containers/Search/ActionBarContainer.jsx index 99c324f1e..451541acb 100644 --- a/src/containers/Search/ActionBarContainer.jsx +++ b/src/containers/Search/ActionBarContainer.jsx @@ -35,11 +35,19 @@ import { DEFAULT_GAS_LIMITS, } from '../../utils/config'; import { trimString } from '../../utils/utils'; -import { AppContext } from '../../context'; +import Msgs from '../../utils/msgs'; const imgKeplr = require('../../image/keplr-icon.svg'); const imgLedger = require('../../image/ledger.svg'); const imgCyber = require('../../image/blue-circle.png'); +const imgCyberSigner = require('../../image/wallet-outline.svg'); + +const imgData = { + ledger: imgLedger, + keplr: imgKeplr, + cyber: imgCyber, + cyberSigner: imgCyberSigner, +}; const { MEMO, @@ -62,8 +70,9 @@ const ADD_ADDRESS = 11; const LEDGER_TX_ACOUNT_INFO = 12; const STAGE_IPFS_HASH = 3.1; const STAGE_KEPLR_APPROVE = 3.2; +const STAGE_CHECK_TYPE_SIGNER = 8.1; -class ActionBarContainer extends Component { +class InnerActionBarContainer extends Component { constructor(props) { super(props); this.state = { @@ -116,7 +125,9 @@ class ActionBarContainer extends Component { if ( address !== null && addressInfo !== null && + toCid && toCid !== null && + fromCid && fromCid !== null ) { this.stageReady(); @@ -124,8 +135,8 @@ class ActionBarContainer extends Component { } if (stage === STAGE_IPFS_HASH) { - if (toCid !== null && fromCid !== null) { - this.generateTx(); + if (toCid && toCid !== null && fromCid && fromCid !== null) { + this.checkTypeSigner(); } } if (prevProps.defaultAccount.name !== defaultAccount.name) { @@ -282,9 +293,25 @@ class ActionBarContainer extends Component { }); }; + checkTypeSigner = () => { + const { addressLocalStor } = this.state; + + this.setState({ + stage: STAGE_CHECK_TYPE_SIGNER, + }); + + if (addressLocalStor.keys === 'keplr') { + this.generateTx(); + } + if (addressLocalStor.keys === 'cyberSigner') { + this.sendTxSigner(); + } + }; + generateTx = async () => { try { - const { keplr } = this.context; + const { valueAppContext } = this.props; + const { keplr } = valueAppContext; const { fromCid, toCid, addressLocalStor } = this.state; this.setState({ @@ -514,6 +541,50 @@ class ActionBarContainer extends Component { }); }; + updateCallbackFnc = (result) => { + const { valueAppContextSigner } = this.props; + const { updateCallbackSigner } = valueAppContextSigner; + + if (result.code === 0) { + const hash = result.transactionHash; + updateCallbackSigner(null); + console.log('hash :>> ', hash); + this.setState({ stage: STAGE_SUBMITTED, txHash: hash }); + this.timeOut = setTimeout(this.confirmTx, 1500); + } else { + this.setState({ + txHash: null, + stage: STAGE_ERROR, + errorMessage: result.rawLog.toString(), + }); + } + }; + + sendTxSigner = async () => { + const { valueAppContextSigner } = this.props; + const { fromCid, toCid, addressLocalStor } = this.state; + const { cyberSigner, updateValueTxs, updateCallbackSigner } = + valueAppContextSigner; + if (cyberSigner !== null) { + const [{ address }] = await cyberSigner.signer.getAccounts(); + // const fee = { + // amount: [], + // gas: DEFAULT_GAS_LIMITS.toString(), + // }; + // const result = await cyberSigner.cyberlink(address, fromCid, toCid, fee); + // console.log('result', result); + + const objMsgs = new Msgs(); + const msgs = objMsgs.cyberlink(address, fromCid, toCid); + + updateCallbackSigner(this.updateCallbackFnc); + updateValueTxs([msgs]); + this.setState({ + stage: STAGE_KEPLR_APPROVE, + }); + } + }; + onClickBtnRank = async () => { const { addressLocalStor } = this.state; const { rankLink } = this.props; @@ -538,6 +609,9 @@ class ActionBarContainer extends Component { if (addressLocalStor.keys === 'keplr') { this.onClickInitKeplr(); } + if (addressLocalStor.keys === 'cyberSigner') { + this.onClickInitKeplr(); + } }; render() { @@ -558,7 +632,7 @@ class ActionBarContainer extends Component { addressLocalStor, } = this.state; - const { textBtn, placeholder, rankLink } = this.props; + const { textBtn, placeholder, rankLink, node } = this.props; if (stage === STAGE_INIT && addressLocalStor === null) { return ( @@ -606,7 +680,7 @@ class ActionBarContainer extends Component { } onClick={() => this.onClickBtnRank()} - img={keys === 'ledger' ? imgLedger : imgKeplr} + img={imgData[keys]} /> @@ -629,6 +703,7 @@ class ActionBarContainer extends Component { onClickClear={this.onClickClear} file={file} placeholder={placeholder} + node={node} /> ); } @@ -676,6 +751,16 @@ class ActionBarContainer extends Component { ); } + if (stage === STAGE_CHECK_TYPE_SIGNER) { + return ( + + + + + + ); + } + if (stage === STAGE_WAIT) { return ( { }; }; -ActionBarContainer.contextType = AppContext; +// ActionBarContainer.contextType = AppContext; +// ActionBarContainer.contextType = AppContextSigner; -export default connect(mapStateToProps)(ActionBarContainer); +export default connect(mapStateToProps)(InnerActionBarContainer); diff --git a/src/containers/Search/SearchResults.jsx b/src/containers/Search/SearchResults.jsx index 59bff88ea..69f49e2dd 100644 --- a/src/containers/Search/SearchResults.jsx +++ b/src/containers/Search/SearchResults.jsx @@ -24,7 +24,7 @@ import { NoItems, Dots, } from '../../components'; -import ActionBarContainer from './ActionBarContainer'; +import ActionBarContainer from './ActionBar'; import { PATTERN, PATTERN_CYBER, diff --git a/src/containers/Validators/ActionBarContainer.jsx b/src/containers/Validators/ActionBarContainer.jsx index fca9f78c9..42546d54b 100644 --- a/src/containers/Validators/ActionBarContainer.jsx +++ b/src/containers/Validators/ActionBarContainer.jsx @@ -1,4 +1,10 @@ -import React, { useState, useEffect, useContext, useMemo } from 'react'; +import React, { + useState, + useEffect, + useContext, + useMemo, + useCallback, +} from 'react'; import { Pane, Text, ActionBar, Button } from '@cybercongress/gravity'; import { coins, coin } from '@cosmjs/launchpad'; import { useHistory } from 'react-router-dom'; @@ -18,9 +24,10 @@ import { } from '../../components'; import { trimString, formatNumber } from '../../utils/utils'; +import Msgs from '../../utils/msgs'; import { LEDGER, CYBER, DEFAULT_GAS_LIMITS } from '../../utils/config'; -import { AppContext } from '../../context'; +import { AppContext, AppContextSigner } from '../../context'; const { MEMO, @@ -190,6 +197,13 @@ function ActionBarContainer({ updateFnc, }) { const { keplr, jsCyber } = useContext(AppContext); + const { + cyberSigner, + updateValueTxs, + updateValueIsVisible, + updateCallbackSigner, + updateStageSigner, + } = useContext(AppContextSigner); const history = useHistory(); const [stage, setStage] = useState(STAGE_INIT); const [txType, setTxType] = useState(null); @@ -219,6 +233,97 @@ function ActionBarContainer({ setStage(STAGE_INIT); }; + const getTxsMsgs = useCallback( + async (address) => { + const validatorAddres = getValidatorAddres(validators); + const msgs = []; + const dataMsgs = new Msgs(); + if (txType === TXTYPE_DELEGATE) { + const tempMsg = await dataMsgs.delegateTokens( + address, + validatorAddres, + coin(parseFloat(amount), CYBER.DENOM_CYBER) + ); + msgs.push(tempMsg); + } + if (txType === TXTYPE_UNDELEGATE) { + const tempMsg = await dataMsgs.undelegateTokens( + address, + validatorAddres, + coin(parseFloat(amount), CYBER.DENOM_CYBER) + ); + msgs.push(tempMsg); + } + if (txType === TXTYPE_REDELEGATE) { + const tempMsg = await dataMsgs.redelegateTokens( + address, + validatorAddres, + valueSelect, + coin(parseFloat(amount), CYBER.DENOM_CYBER) + ); + msgs.push(tempMsg); + } + + return msgs; + }, + [txType, valueSelect, amount] + ); + + const updateCallbackFnc = (response) => { + checkTxs(response, { setTxHash, setErrorMessage, setStage }); + }; + + const generateTxCyberSigner = useCallback(async () => { + if (cyberSigner !== null) { + const [{ address }] = await cyberSigner.signer.getAccounts(); + if (addressPocket !== null && addressPocket.bech32 === address) { + const msgs = await getTxsMsgs(address); + console.log('msgs', msgs); + updateCallbackSigner(updateCallbackFnc); + updateValueTxs(msgs); + setStage(LEDGER_GENERATION); + } else { + setStage(STAGE_ERROR); + setErrorMessage( + `Add address ${trimString( + address, + 9, + 5 + )} to your pocket or make active ` + ); + } + } + }, [cyberSigner, amount, valueSelect]); + + const generateTxKeplr = useCallback(async () => { + if (keplr !== null) { + const [{ address }] = await keplr.signer.getAccounts(); + if (addressPocket !== null && addressPocket.bech32 === address) { + const msgs = await getTxsMsgs(address); + + console.log('msgs', msgs); + + const result = await keplr.signAndBroadcast( + address, + msgs, + fee, + CYBER.MEMO_KEPLR + ); + console.log('result: ', result); + checkTxs(result, { setTxHash, setErrorMessage, setStage }); + } else { + setStage(STAGE_ERROR); + setErrorMessage( + `Add address ${trimString( + address, + 9, + 5 + )} to your pocket or make active ` + ); + } + } + }, [keplr, addressPocket, amount, valueSelect]); + const delegateTokens = async () => { console.log('delegateTokens', delegateTokens); try { @@ -343,6 +448,16 @@ function ActionBarContainer({ setStage(STAGE_READY); }; + const initDevice = () => { + if (addressPocket !== null && addressPocket.keys === 'keplr') { + generateTxKeplr(); + } + + if (addressPocket !== null && addressPocket.keys === 'cyberSigner') { + generateTxCyberSigner(); + } + }; + // console.log('addressPocket', addressPocket); // console.log('loadingBalanceInfo', loadingBalanceInfo); // console.log('balance', balance); @@ -412,7 +527,7 @@ function ActionBarContainer({ if ( Object.keys(validators).length === 0 && stage === STAGE_INIT && - balance.delegation && + balance.delegation && balance.delegation === 0 ) { return ( @@ -532,9 +647,10 @@ function ActionBarContainer({ onChangeInputAmount={(e) => setAmount(e.target.value)} toSend={amount} disabledBtn={amount.length === 0} - generateTx={ - txType === TXTYPE_DELEGATE ? delegateTokens : undelegateTokens - } + generateTx={() => initDevice()} + // generateTx={ + // txType === TXTYPE_DELEGATE ? delegateTokens : undelegateTokens + // } delegate={txType === TXTYPE_DELEGATE} /> ); @@ -543,7 +659,8 @@ function ActionBarContainer({ if (stage === STAGE_READY && txType === TXTYPE_REDELEGATE) { return ( redelegateTokens()} + generateTx={() => initDevice()} + // generateTx={() => redelegateTokens()} onChangeInputAmount={(e) => setAmount(e.target.value)} toSend={amount} disabledBtn={!validRestakeBtn} diff --git a/src/containers/Wallet/actionBar.jsx b/src/containers/Wallet/actionBar.jsx index a85b194e1..8846f5718 100644 --- a/src/containers/Wallet/actionBar.jsx +++ b/src/containers/Wallet/actionBar.jsx @@ -11,18 +11,21 @@ import ActionBarWeb3 from './actionBarWeb3'; import ActionBarUser from './actionBarUser'; import ActionBarLedger from './actionBarLedger'; import ActionBarConnect from './actionBarConnect'; +import ActionBarCyberSigner from './actionBarCyberSigner'; import waitForWeb3 from '../../components/web3/waitForWeb3'; import { NETWORKSIDS } from '../../utils/config'; const imgLedger = require('../../image/ledger.svg'); const imgKeplr = require('../../image/keplr-icon.svg'); const imgRead = require('../../image/duplicate-outline.svg'); +const imgCyberSigner = require('../../image/wallet-outline.svg'); const STAGE_INIT = 1; const STAGE_CONNECT = 2; const STAGE_SEND_LEDGER = 3.1; const STAGE_SEND_KEPLR = 4.1; const STAGE_SEND_READ_ONLY = 5.1; +const STAGE_SEND_CYBER_SIGNER = 6.1; const ButtonImgText = ({ img, text = 'Send', ...props }) => ( + )} + setStage(STAGE_SEND_CYBER_SIGNER)} + /> + {makeActive && ( + + )} + + + ); + } + if (typeActionBar === 'tweet' && stage === STAGE_INIT) { if (defaultAccounts !== null && defaultAccounts.cyber) { return ( @@ -311,6 +337,16 @@ function ActionBar({ ); } + if (stage === STAGE_SEND_CYBER_SIGNER) { + return ( + + ); + } + if (stage === STAGE_SEND_LEDGER) { return ( { + console.log(`callbackSigner`, signerCyber); + const [{ address, pubkey }] = await signerCyber.signer.getAccounts(); + const pk = Buffer.from(pubkey).toString('hex'); + console.log(`callbackSigner address`, address); + console.log(`callbackSigner pk`, pk); + updateCallbackSigner(null); + const accounts = {}; + let key = 'Account 1'; + let dataPocketAccount = null; + let valueObj = {}; + let pocketAccount = {}; + let count = 1; + + const localStorageStory = await localStorage.getItem('pocketAccount'); + const localStoragePocket = await localStorage.getItem('pocket'); + const localStorageCount = await localStorage.getItem('count'); + if (localStorageCount !== null) { + const dataCount = JSON.parse(localStorageCount); + count = parseFloat(dataCount); + key = `Account ${count}`; + } + localStorage.setItem('count', JSON.stringify(count + 1)); + if (localStorageStory !== null) { + dataPocketAccount = JSON.parse(localStorageStory); + valueObj = Object.values(dataPocketAccount); + if (selectAccount !== null) { + key = selectAccount.key; + } + } + if (selectNetwork === 'cyber' || addCyberAddress) { + const cyberBech32 = address; + if ( + selectAccount !== null || + !checkAddress(valueObj, 'cyber', cyberBech32) + ) { + const seedBase64 = btoa(signerCyber.signer.secret.data); + accounts.cyber = { + bech32: cyberBech32, + keys: 'cyberSigner', + pk, + path: HDPATH, + secret: seedBase64, + }; + } + } + if (selectNetwork === 'cosmos') { + const cosmosAddress = fromBech32(address, 'cosmos'); + const cosmosBech32 = cosmosAddress; + if ( + selectAccount !== null || + !checkAddress(valueObj, 'cosmos', cosmosBech32) + ) { + accounts.cosmos = { + bech32: cosmosBech32, + keys: 'cyberSigner', + pk, + path: HDPATH, + }; + } + } + setStage(STAGE_ADD_ADDRESS_OK); + if (selectAccount === null) { + if (localStorageStory !== null) { + if (Object.keys(accounts).length > 0) { + pocketAccount = { [key]: accounts, ...dataPocketAccount }; + } + } else { + pocketAccount = { [key]: accounts }; + } + if (Object.keys(pocketAccount).length > 0) { + localStorage.setItem('pocketAccount', JSON.stringify(pocketAccount)); + } + } else { + dataPocketAccount[selectAccount.key][selectNetwork] = + accounts[selectNetwork]; + console.log('dataPocketAccount', dataPocketAccount); + if (Object.keys(dataPocketAccount).length > 0) { + localStorage.setItem( + 'pocketAccount', + JSON.stringify(dataPocketAccount) + ); + } + if (localStoragePocket !== null) { + const localStoragePocketData = JSON.parse(localStoragePocket); + const keyPocket = Object.keys(localStoragePocketData)[0]; + localStoragePocketData[keyPocket][selectNetwork] = + accounts[selectNetwork]; + if (keyPocket === selectAccount.key) { + localStorage.setItem( + 'pocket', + JSON.stringify(localStoragePocketData) + ); + } + } + } + cleatState(); + if (updateAddress) { + updateAddress(); + } + if (updateFuncActionBar) { + updateFuncActionBar(); + } + }; + + const onClickConnectCyberSigner = () => { + updateCallbackSigner(callbackSigner); + updateValueIsVisible(true); + updateStageSigner(CYBER_SIGNER.STAGE_INIT_ACC); + }; + const connectKeplr = async () => { const accounts = {}; let key = 'Account 1'; diff --git a/src/containers/Wallet/actionBarCyberSigner.jsx b/src/containers/Wallet/actionBarCyberSigner.jsx new file mode 100644 index 000000000..c450673d1 --- /dev/null +++ b/src/containers/Wallet/actionBarCyberSigner.jsx @@ -0,0 +1,221 @@ +import React, { useEffect, useState, useContext } from 'react'; +import TransportWebUSB from '@ledgerhq/hw-transport-webusb'; +import { Link } from 'react-router-dom'; +import { Pane, Text, ActionBar, Button, Input } from '@cybercongress/gravity'; +import { coins } from '@cosmjs/launchpad'; +import { CosmosDelegateTool } from '../../utils/ledger'; +import { AppContextSigner } from '../../context'; +import { + ConnectLadger, + Dots, + ActionBarContentText, + TransactionSubmitted, + Confirmed, + TransactionError, +} from '../../components'; +import { + LEDGER, + CYBER, + PATTERN_COSMOS, + PATTERN_CYBER, + POCKET, +} from '../../utils/config'; +import { getTxs } from '../../utils/search/utils'; +import { deletPubkey } from './utils'; +import Msgs from '../../utils/msgs'; + +const imgKeplr = require('../../image/keplr-icon.svg'); + +const { + STAGE_INIT, + STAGE_ERROR, + STAGE_SUBMITTED, + STAGE_CONFIRMING, + STAGE_CONFIRMED, +} = LEDGER; + +const STAGE_SEND = 1.1; + +function ActionBarCyberSigner({ updateAddress, updateBalance, selectAccount }) { + const { cyberSigner, updateValueTxs, updateCallbackSigner } = useContext( + AppContextSigner + ); + const [stage, setStage] = useState(STAGE_SEND); + const [amountSend, setAmountSend] = useState(''); + const [recipient, setRecipient] = useState(''); + const [recipientInputValid, setRecipientInputValid] = useState(null); + const [amountSendInputValid, setAmountSendInputValid] = useState(null); + const [txHash, setTxHash] = useState(null); + const [txHeight, setTxHeight] = useState(null); + const [errorMessage, setErrorMessage] = useState(null); + const [disabledGenerate, setDisabledGenerate] = useState(true); + + const generateTxSend = async () => { + const amount = parseFloat(amountSend); + if (cyberSigner !== null) { + setStage(STAGE_SUBMITTED); + const [{ address }] = await cyberSigner.signer.getAccounts(); + const dataMsgs = new Msgs(); + const msgs = dataMsgs.sendTokens( + address, + recipient, + coins(amount, CYBER.DENOM_CYBER) + ); + + updateCallbackSigner(updateCallbackFnc); + updateValueTxs([msgs]); + } + }; + + const updateCallbackFnc = (result) => { + const hash = result.transactionHash; + updateCallbackSigner(null); + console.log('hash :>> ', hash); + setTxHash(hash); + }; + + const cleatState = () => { + setStage(STAGE_SEND); + setRecipientInputValid(null); + setAmountSendInputValid(null); + setRecipient(''); + setAmountSend(''); + setErrorMessage(null); + setTxHeight(null); + setTxHash(null); + if (updateAddress) { + updateAddress(); + } + }; + + useEffect(() => { + const confirmTx = async () => { + console.log('txHash :>> ', txHash); + if (txHash && txHash !== null) { + setStage(STAGE_CONFIRMING); + const response = await getTxs(txHash); + console.log('response :>> ', response); + if (response && response !== null) { + if (response.logs) { + setStage(STAGE_CONFIRMED); + setTxHeight(response.height); + if (updateBalance) { + updateBalance(); + } + return; + } + if (response.code) { + setStage(STAGE_ERROR); + setTxHeight(response.height); + setErrorMessage(response.raw_log); + return; + } + } + setTimeout(confirmTx, 1500); + } + }; + confirmTx(); + }, [txHash]); + + useEffect(() => { + if (parseFloat(amountSend) === 0) { + setAmountSendInputValid('Invalid amount'); + } else { + setAmountSendInputValid(null); + } + }, [amountSend]); + + useEffect(() => { + if (recipient !== '') { + if (!recipient.match(PATTERN_CYBER)) { + setRecipientInputValid('Invalid bech32 address'); + } else { + setRecipientInputValid(null); + } + } + }, [recipient]); + + useEffect(() => { + if (recipient.match(PATTERN_CYBER) && parseFloat(amountSend) > 0) { + setDisabledGenerate(false); + } else { + setDisabledGenerate(true); + } + }, [recipient, amountSend]); + + if (stage === STAGE_SEND) { + return ( + + + + setRecipient(e.target.value)} + placeholder="cyber address To" + isInvalid={recipientInputValid !== null} + message={recipientInputValid} + /> + + setAmountSend(e.target.value)} + placeholder="BOOT" + isInvalid={amountSendInputValid !== null} + message={amountSendInputValid} + /> + + + + + + ); + } + if (stage === STAGE_SUBMITTED) { + return ( + + + check the transaction + + + ); + } + + if (stage === STAGE_CONFIRMING) { + return ; + } + + if (stage === STAGE_CONFIRMED) { + return ( + cleatState()} + /> + ); + } + + if (stage === STAGE_ERROR && errorMessage !== null) { + return ( + cleatState()} + /> + ); + } + + return null; +} + +export default ActionBarCyberSigner; diff --git a/src/containers/Wallet/components/pocketCard.jsx b/src/containers/Wallet/components/pocketCard.jsx index faa89b591..b10097c48 100644 --- a/src/containers/Wallet/components/pocketCard.jsx +++ b/src/containers/Wallet/components/pocketCard.jsx @@ -14,6 +14,7 @@ const deleteIcon = require('../../../image/trash-outline.svg'); const imgEth = require('../../../image/Ethereum_logo_2014.svg'); const imgCyber = require('../../../image/large-green.png'); const imgCosmos = require('../../../image/cosmos-2.svg'); +const imgCyberSigner = require('../../../image/wallet-outline.svg'); const imgData = { ledger: imgLedger, @@ -23,6 +24,7 @@ const imgData = { cyber: imgCyber, cosmos: imgCosmos, eth: imgEth, + cyberSigner: imgCyberSigner, }; export const FormatNumber = ({ diff --git a/src/containers/account/ActionBarContainer.jsx b/src/containers/account/ActionBarContainer.jsx new file mode 100644 index 000000000..f1dd656ed --- /dev/null +++ b/src/containers/account/ActionBarContainer.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import InnerActionBarContainer from './actionBar'; +import { AppContext, AppContextSigner } from '../../context'; + +const ActionBarContainer = (props) => { + return ( + + {(valueAppContext) => ( + + {(valueAppContextSigner) => ( + + )} + + )} + + ); +}; + +export default ActionBarContainer; diff --git a/src/containers/account/actionBar.jsx b/src/containers/account/actionBar.jsx index 35d79ba5c..711adb926 100644 --- a/src/containers/account/actionBar.jsx +++ b/src/containers/account/actionBar.jsx @@ -35,8 +35,6 @@ import { getPin, } from '../../utils/search/utils'; -import { AppContext } from '../../context'; - const { DIVISOR_CYBER_G } = CYBER; const { @@ -66,7 +64,7 @@ const groupLink = (linkArr) => { return link; }; -class ActionBarContainer extends Component { +class InnerActionBarContainer extends Component { constructor(props) { super(props); this.state = { @@ -442,6 +440,36 @@ class ActionBarContainer extends Component { this.timeOut = setTimeout(this.confirmTx, 1500); }; + generateTxCyberSigner = async () => { + const { valueAppContextSigner } = this.props; + const { + cyberSigner, + updateValueTxs, + updateCallbackSigner, + } = valueAppContextSigner; + + if (cyberSigner !== null) { + await window.keplr.enable(CYBER.CHAIN_ID); + const [{ address }] = await cyberSigner.getAccounts(); + const msg = await this.getTxs(address); + console.log(`msg`, msg); + if (msg.length > 0) { + updateCallbackSigner(this.updateCallbackFnc); + updateValueTxs(msg); + } + } + }; + + updateCallbackFnc = (result) => { + const { valueAppContextSigner } = this.props; + const { updateCallbackSigner } = valueAppContextSigner; + const hash = result.transactionHash; + updateCallbackSigner(null); + console.log('hash :>> ', hash); + this.setState({ stage: STAGE_SUBMITTED, txHash: hash }); + this.timeOut = setTimeout(this.confirmTx, 1500); + }; + onChangeInputAmount = (e) => { this.setState({ toSend: e.target.value, @@ -465,6 +493,9 @@ class ActionBarContainer extends Component { if (defaultAccount.keys === 'keplr') { this.generateTxSendKplr(); } + if (defaultAccount.keys === 'cyberSigner') { + this.generateTxCyberSigner(); + } }; cleatState = () => { @@ -596,7 +627,7 @@ class ActionBarContainer extends Component { stage === STAGE_INIT && type === 'heroes' && defaultAccount !== null && - defaultAccount.keys === 'keplr' + defaultAccount.keys !== 'ledger' ) { return ( @@ -722,6 +753,4 @@ const mapStateToProps = (store) => { }; }; -ActionBarContainer.contextType = AppContext; - -export default connect(mapStateToProps)(ActionBarContainer); +export default connect(mapStateToProps)(InnerActionBarContainer); diff --git a/src/containers/brain/brain.jsx b/src/containers/brain/brain.jsx index 07054cf7b..b7acf31fb 100644 --- a/src/containers/brain/brain.jsx +++ b/src/containers/brain/brain.jsx @@ -14,7 +14,7 @@ import { TabBtn } from '../../components'; import { CYBER, TAKEOFF } from '../../utils/config'; -import ActionBarContainer from './actionBarContainer'; +import ActionBarContainer from '../Search/ActionBar'; import { GovernmentTab, MainTab, @@ -311,7 +311,11 @@ function Brain({ node, mobile, defaultAccount }) { selected !== 'government' && selected !== 'halloffame' && (addressActive.keys !== 'read-only' ? ( - + ) : ( diff --git a/src/containers/governance/actionBar.jsx b/src/containers/governance/actionBar.jsx index 79788fe12..0895dc0ed 100644 --- a/src/containers/governance/actionBar.jsx +++ b/src/containers/governance/actionBar.jsx @@ -50,7 +50,7 @@ const { const LEDGER_TX_ACOUNT_INFO = 10; -class ActionBar extends Component { +class InnerActionBarContainer extends Component { constructor(props) { super(props); this.state = { @@ -142,7 +142,7 @@ class ActionBar extends Component { } }; - generateTxKeplr = async () => { + getTxsMsgs = async (address) => { const { valueSelect, valueDescription, @@ -169,13 +169,13 @@ class ActionBar extends Component { }; const [{ address }] = await keplr.signer.getAccounts(); - // if (valueDeposit > 0) { - // deposit = coins(valueDeposit, CYBER.DENOM_CYBER); - // } + // if (valueDeposit > 0) { + // deposit = coins(valueDeposit, CYBER.DENOM_CYBER); + // } - // if (valueAmountRecipient > 0) { - // amount = coins(valueAmountRecipient, CYBER.DENOM_CYBER); - // } + // if (valueAmountRecipient > 0) { + // amount = coins(valueAmountRecipient, CYBER.DENOM_CYBER); + // } try { const deposit = coins(parseFloat(valueDeposit), CYBER.DENOM_CYBER); @@ -445,6 +445,9 @@ class ActionBar extends Component { if (account.keys === 'keplr') { this.generateTxKeplr(); } + if (account.keys === 'cyberSigner') { + this.generateTxCyberSigner(); + } } }; @@ -766,6 +769,4 @@ class ActionBar extends Component { } } -ActionBar.contextType = AppContext; - -export default ActionBar; +export default InnerActionBarContainer; diff --git a/src/containers/governance/actionBarContainer.jsx b/src/containers/governance/actionBarContainer.jsx new file mode 100644 index 000000000..f1dd656ed --- /dev/null +++ b/src/containers/governance/actionBarContainer.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import InnerActionBarContainer from './actionBar'; +import { AppContext, AppContextSigner } from '../../context'; + +const ActionBarContainer = (props) => { + return ( + + {(valueAppContext) => ( + + {(valueAppContextSigner) => ( + + )} + + )} + + ); +}; + +export default ActionBarContainer; diff --git a/src/containers/governance/actionBarDetailsContainer.jsx b/src/containers/governance/actionBarDetailsContainer.jsx new file mode 100644 index 000000000..5f71ed4e1 --- /dev/null +++ b/src/containers/governance/actionBarDetailsContainer.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import InnerActionBarContainerDetail from './actionBarDatail'; +import { AppContext, AppContextSigner } from '../../context'; + +const ActionBarContainer = (props) => { + return ( + + {(valueAppContext) => ( + + {(valueAppContextSigner) => ( + + )} + + )} + + ); +}; + +export default ActionBarContainer; diff --git a/src/containers/governance/governance.jsx b/src/containers/governance/governance.jsx index adb4e73b4..ded3f2c9a 100644 --- a/src/containers/governance/governance.jsx +++ b/src/containers/governance/governance.jsx @@ -1,8 +1,8 @@ import React, { useState, useEffect, useContext } from 'react'; import { Link } from 'react-router-dom'; -import { Pane } from '@cybercongress/gravity'; +import { Pane, ActionBar } from '@cybercongress/gravity'; import { connect } from 'react-redux'; -import ActionBar from './actionBar'; +import ActionBarContainer from './actionBarContainer'; import { getProposals, getMinDeposit } from '../../utils/governance'; import Columns from './components/columns'; import { AcceptedCard, ActiveCard, RejectedCard } from './components/card'; @@ -200,7 +200,25 @@ function Governance({ defaultAccount }) { {rejected} - + {account !== null ? ( + + ) : ( + + + + add address to your pocket + + + + )} ); } diff --git a/src/containers/governance/proposalsDetail.jsx b/src/containers/governance/proposalsDetail.jsx index 87206996f..dc324e19d 100644 --- a/src/containers/governance/proposalsDetail.jsx +++ b/src/containers/governance/proposalsDetail.jsx @@ -33,7 +33,7 @@ import { getTableVoters, getTallyingProposals, } from '../../utils/governance'; -import ActionBarDetail from './actionBarDatail'; +import ActionBarContainer from './actionBarDetailsContainer'; import { formatNumber } from '../../utils/utils'; diff --git a/src/containers/mint/actionBar.jsx b/src/containers/mint/actionBar.jsx index c612544c7..15294174a 100644 --- a/src/containers/mint/actionBar.jsx +++ b/src/containers/mint/actionBar.jsx @@ -13,10 +13,11 @@ import { TransactionError, Account, } from '../../components'; -import { AppContext } from '../../context'; +import { AppContext, AppContextSigner } from '../../context'; import { CYBER, LEDGER, DEFAULT_GAS_LIMITS } from '../../utils/config'; import { getTxs } from '../../utils/search/utils'; import { trimString } from '../../utils/utils'; +import Msgs from '../../utils/msgs'; const { STAGE_INIT, @@ -29,6 +30,21 @@ const { const VESTING_TIME_HOURS = 3601; const BASE_VESTING_TIME = 86401; +const checkTxs = (response, updateState) => { + console.log('response', response); + const { setStage, setTxHash, setErrorMessage } = updateState; + if (response.code === 0) { + const hash = response.transactionHash; + console.log('hash :>> ', hash); + setStage(STAGE_SUBMITTED); + setTxHash(hash); + } else { + setStage(STAGE_ERROR); + setTxHash(null); + setErrorMessage(response.rawLog.toString()); + } +}; + function ActionBar({ value, selected, @@ -38,6 +54,13 @@ function ActionBar({ addressActive, }) { const { keplr, jsCyber } = useContext(AppContext); + const { + cyberSigner, + updateValueTxs, + updateValueIsVisible, + updateCallbackSigner, + updateStageSigner, + } = useContext(AppContextSigner); const [stage, setStage] = useState(STAGE_INIT); const [txHash, setTxHash] = useState(null); const [txHeight, setTxHeight] = useState(null); @@ -72,14 +95,13 @@ function ActionBar({ }, [jsCyber, txHash]); const investmint = async () => { - if (keplr !== null) { - setStage(STAGE_SUBMITTED); + if (keplr !== null && addressActive !== null) { const [{ address }] = await keplr.signer.getAccounts(); const fee = { amount: [], gas: DEFAULT_GAS_LIMITS.toString(), }; - if (addressActive === address) { + if (addressActive.bech32 === address) { const response = await keplr.investmint( address, coin(parseFloat(value), 'hydrogen'), @@ -88,19 +110,7 @@ function ActionBar({ fee ); console.log(`response`, response); - if (response.code === 0) { - setTxHash(response.transactionHash); - } else if (response.code === 4) { - setTxHash(null); - setErrorMessage( - 'Cyberlinking and investmint is not working. Wait for updates.' - ); - setStage(STAGE_ERROR); - } else { - setTxHash(null); - setErrorMessage(response.rawLog.toString()); - setStage(STAGE_ERROR); - } + checkTxs(response, { setTxHash, setErrorMessage, setStage }); } else { setErrorMessage( @@ -113,6 +123,38 @@ function ActionBar({ } }; + const updateCallbackFnc = (response) => { + checkTxs(response, { setTxHash, setErrorMessage, setStage }); + }; + + const investmintCyberCigner = async () => { + if (cyberSigner !== null) { + const dataMsgs = new Msgs(); + const [{ address }] = await cyberSigner.signer.getAccounts(); + const msgs = await dataMsgs.investmint( + address, + coin(parseFloat(value), 'hydrogen'), + selected, + parseFloat(BASE_VESTING_TIME * valueDays) + ); + console.log('msgs', msgs) + updateValueTxs([msgs]); + updateCallbackSigner(updateCallbackFnc); + } + }; + + const chooseSigner = () => { + if (addressActive !== null) { + if (addressActive.keys === 'keplr') { + investmint(); + } + + if (addressActive.keys === 'cyberSigner') { + investmintCyberCigner(); + } + } + }; + const cleatState = () => { setStage(STAGE_INIT); setTxHash(null); @@ -134,7 +176,7 @@ function ActionBar({ ); } - if (jsCyber === null || keplr === null) { + if (jsCyber === null) { return ( @@ -145,7 +187,7 @@ function ActionBar({ if (stage === STAGE_INIT) { return ( - diff --git a/src/containers/mint/index.jsx b/src/containers/mint/index.jsx index ae6ecf6fb..69b022616 100644 --- a/src/containers/mint/index.jsx +++ b/src/containers/mint/index.jsx @@ -24,6 +24,7 @@ import useGetSlots from './useGetSlots'; import { TableSlots } from '../energy/ui'; import TabBtnList from './tabLinsBtn'; import ActionBar from './actionBar'; +import useSetActiveAddress from '../../hooks/useSetActiveAddress'; const INIT_STAGE = 0; const TSX_SEND = 1; @@ -75,15 +76,12 @@ const returnColorDot = (marks) => { function Mint({ defaultAccount }) { const { jsCyber } = useContext(AppContext); - const [addressActive, setAddressActive] = useState(null); + const { addressActive } = useSetActiveAddress(defaultAccount); + // const [addressActive, setAddressActive] = useState(null); const [updateAddress, setUpdateAddress] = useState(0); // const { balance } = useGetBalance(addressActive, updateAddress); - const { - slotsData, - vested, - loadingAuthAccounts, - originalVesting, - } = useGetSlots(addressActive, updateAddress); + const { slotsData, vested, loadingAuthAccounts, originalVesting } = + useGetSlots(addressActive, updateAddress); const [selected, setSelected] = useState('millivolt'); const [value, setValue] = useState(0); const [valueDays, setValueDays] = useState(1); @@ -100,7 +98,7 @@ function Mint({ defaultAccount }) { let amountHydrogen = 0; if (jsCyber !== null && addressActive !== null) { const responseBalance = await jsCyber.getBalance( - addressActive, + addressActive.bech32, 'hydrogen' ); if (responseBalance.amount) { @@ -114,39 +112,26 @@ function Mint({ defaultAccount }) { useEffect(() => { const getParam = async () => { - const responseResourcesParams = await jsCyber.resourcesParams(); - if ( - responseResourcesParams.params && - Object.keys(responseResourcesParams.params).length > 0 - ) { - console.log(`responseResourcesParams`, responseResourcesParams); - const { params } = responseResourcesParams; - setResourcesParams((item) => ({ ...item, ...params })); - } + if (jsCyber !== null) { + const responseResourcesParams = await jsCyber.resourcesParams(); + if ( + responseResourcesParams.params && + Object.keys(responseResourcesParams.params).length > 0 + ) { + console.log(`responseResourcesParams`, responseResourcesParams); + const { params } = responseResourcesParams; + setResourcesParams((item) => ({ ...item, ...params })); + } - const responseGetHeight = await jsCyber.getHeight(); - if (responseGetHeight > 0) { - setHeight(responseGetHeight); + const responseGetHeight = await jsCyber.getHeight(); + if (responseGetHeight > 0) { + setHeight(responseGetHeight); + } } }; getParam(); }, [jsCyber]); - useEffect(() => { - const { account } = defaultAccount; - let addressPocket = null; - if ( - account !== null && - Object.prototype.hasOwnProperty.call(account, 'cyber') - ) { - const { keys, bech32 } = account.cyber; - if (keys === 'keplr') { - addressPocket = bech32; - } - } - setAddressActive(addressPocket); - }, [defaultAccount.name]); - useEffect(() => { let vestedTokens = 0; let maxValue = 0; @@ -394,10 +379,10 @@ function Mint({ defaultAccount }) { }} > You’re freezing {formatNumber(value)} H for {valueDays} days. It - will release {resourceToken} {} for - you. At the end of the period, {selected} becomes liquid - automatically, but you can use it to boost ranking during the - freeze. You can have only 8 slots for investmint at a time. + will release {resourceToken} for you. + At the end of the period, {selected} becomes liquid automatically, + but you can use it to boost ranking during the freeze. You can + have only 8 slots for investmint at a time. )} diff --git a/src/containers/mint/useGetSlots.jsx b/src/containers/mint/useGetSlots.jsx index 1050089a9..cf3ab5717 100644 --- a/src/containers/mint/useGetSlots.jsx +++ b/src/containers/mint/useGetSlots.jsx @@ -47,14 +47,25 @@ function timeSince(timeMS) { return `${Math.floor(seconds)} seconds`; } -function useGetSlots(addressActive, updateAddress) { +function useGetSlots(address, updateAddress) { const { jsCyber } = useContext(AppContext); + const [addressActive, setAddressActive] = useState(null); const [slotsData, setSlotsData] = useState([]); const [loadingAuthAccounts, setLoadingAuthAccounts] = useState(true); const [originalVesting, setOriginalVesting] = useState(initStateVested); const [balacesResource, setBalacesResource] = useState(initBalacesResource); const [vested, setVested] = useState(initStateVested); + useEffect(() => { + if (address !== null) { + if (address.bech32) { + setAddressActive(address.bech32); + } else { + setAddressActive(address); + } + } + }, [address]); + useEffect(() => { const getAuth = async () => { setLoadingAuthAccounts(true); @@ -71,9 +82,8 @@ function useGetSlots(addressActive, updateAddress) { const getAccount = await authAccounts(addressActive); if (getAccount !== null && getAccount.result.value.vesting_periods) { const { vesting_periods: vestingPeriods } = getAccount.result.value; - const { - original_vesting: originalVestingAmount, - } = getAccount.result.value.base_vesting_account; + const { original_vesting: originalVestingAmount } = + getAccount.result.value.base_vesting_account; const { start_time: startTime } = getAccount.result.value; const balances = getCalculationBalance(originalVestingAmount); diff --git a/src/containers/signer/app.jsx b/src/containers/signer/app.jsx new file mode 100644 index 000000000..604461b4e --- /dev/null +++ b/src/containers/signer/app.jsx @@ -0,0 +1,158 @@ +import React, { useEffect, useState, useContext } from 'react'; +import { useLocation } from 'react-router-dom'; +import { connect } from 'react-redux'; +import Signer from './index'; +import { AppContextSigner } from '../../context'; +import { + StateSign, + StateBroadcast, + StateConfirmed, + StateInitAccount, + StateCreateNew, + StateRestore, +} from './component/ui'; +import { CYBER_SIGNER } from '../../utils/config'; + +const { + STAGE_INIT, + STAGE_SIGN, + STAGE_INIT_ACC, + STAGE_CREATE_NEW_ACCOUNT, + STAGE_RESTORE_PHARSE, +} = CYBER_SIGNER; + +const signerObj = new Signer(); + +function AppSign({ defaultAccount }) { + const { + tx, + stage, + isVisible, + cyberSigner, + callbackFnc, + updateValueIsVisible, + updateValueTxs, + updateCyberSigner, + updateStageSigner, + } = useContext(AppContextSigner); + const location = useLocation(); + const [msgData, setMsgData] = useState(null); + const [cyberSignerTemp, SetCyberSignerTemp] = useState(null); + const [valuePhrase, setValuePhrase] = useState(''); + + useEffect(() => { + rejectStage(); + }, [location.pathname]); + + useEffect(() => { + const getSigner = async () => { + const signerCyber = await signerObj.initSigner(defaultAccount); + console.log('clientCyber', signerCyber); + + console.log(`signerCyber`, signerCyber); + updateCyberSigner(signerCyber); + }; + getSigner(); + }, [defaultAccount.name]); + + useEffect(() => { + if (tx !== null) { + setMsgData(tx); + updateStageSigner(STAGE_SIGN); + updateValueIsVisible(true); + } + }, [tx]); + + const restorePhrase = async () => { + const signerCyber = await signerObj.restorePhrase(valuePhrase, callbackFnc); + console.log('signerCyber', signerCyber) + updateCyberSigner(signerCyber); + setValuePhrase(''); + updateStageSigner(STAGE_INIT); + }; + + const createNewAcc = async () => { + updateStageSigner(CYBER_SIGNER.STAGE_CREATE_NEW_ACCOUNT); + const signerCyber = await signerObj.getVanityAccount(); + // updateCyberSigner(signerCyber); + SetCyberSignerTemp(signerCyber); + setValuePhrase(signerCyber.signer.secret.data); + }; + + const signTx = async () => { + console.log(`signer`, cyberSigner); + console.log(`msgData`, msgData); + if (cyberSigner !== null && msgData !== null) { + const response = await signerObj.sendTxs(msgData, callbackFnc); + console.log(`response Txs`, response); + updateValueTxs(null); + setMsgData(null); + rejectStage(); + } + }; + + const rejectStage = () => { + updateStageSigner(STAGE_INIT); + setMsgData(null); + updateValueTxs(null); + updateValueIsVisible(false); + }; + + if (isVisible && stage === STAGE_SIGN) { + return ( + + ); + } + + const fuckGoogleCreateAcc = async () => { + updateStageSigner(STAGE_INIT); + setValuePhrase(''); + if (callbackFnc !== null) { + callbackFnc(cyberSignerTemp); + } + }; + + if (isVisible && stage === STAGE_INIT_ACC) { + return ( + createNewAcc()} + onClickRestore={() => + updateStageSigner(CYBER_SIGNER.STAGE_RESTORE_PHARSE) + } + /> + ); + } + + if (isVisible && stage === STAGE_CREATE_NEW_ACCOUNT) { + return ( + fuckGoogleCreateAcc()} + /> + ); + } + + if (isVisible && stage === STAGE_RESTORE_PHARSE) { + return ( + setValuePhrase(e.target.value)} + onClick={() => restorePhrase()} + /> + ); + } + + return null; +} + +const mapStateToProps = (store) => { + return { + defaultAccount: store.pocket.defaultAccount, + }; +}; + +export default connect(mapStateToProps)(AppSign); diff --git a/src/containers/signer/component/MsgsSigner.jsx b/src/containers/signer/component/MsgsSigner.jsx new file mode 100644 index 000000000..15537b945 --- /dev/null +++ b/src/containers/signer/component/MsgsSigner.jsx @@ -0,0 +1,151 @@ +import React from 'react'; +import { Pane } from '@cybercongress/gravity'; + +import { trimString, formatNumber } from '../../../utils/utils'; +import MsgType from '../../txs/msgType'; + +const CT = ({ children }) => ( + {children} +); + +function MsgsSigner({ msgData }) { + if (msgData.typeUrl === '/cosmos.bank.v1beta1.MsgSend') { + let recipient; + let amount; + if (msgData.value.toAddress && msgData.value.amount) { + recipient = trimString(msgData.value.toAddress, 8, 4); + amount = msgData.value.amount.map((coin, j) => { + return ( + + {' '} + {formatNumber(coin.amount)} {coin.denom.toUpperCase()} + + ); + }); + } + return ( +
+ + + {recipient} will receive {amount} + +
+ ); + } + + if (msgData.type === 'cosmos-sdk/MsgDelegate') { + let amount; + let validator; + if (msgData.value.validator_address && msgData.value.amount) { + amount = `${formatNumber( + msgData.value.amount.amount + )} ${msgData.value.amount.denom.toUpperCase()}`; + validator = trimString(msgData.value.validator_address, 16); + } + + return ( +
+ + Delegate Delegate {amount} to {validator} +
+ ); + } + + if (msgData.type === 'cosmos-sdk/MsgUndelegate') { + let amount; + let validator; + if (msgData.value.validator_address && msgData.value.amount) { + amount = `${formatNumber( + msgData.value.amount.amount + )} ${msgData.value.amount.denom.toUpperCase()}`; + validator = trimString(msgData.value.validator_address, 16, 4); + } + return ( +
+ + Undelegate Undelegate {amount} from {validator} +
+ Asset will be liquid after unbonding period +
+ ); + } + + if (msgData.type === 'cosmos-sdk/MsgBeginRedelegate') { + let amount; + let fromValidator; + let toValidator; + if ( + msgData.value.validator_dst_address && + msgData.value.validator_src_address && + msgData.value.amount + ) { + amount = `${formatNumber( + msgData.value.amount.amount + )} ${msgData.value.amount.denom.toUpperCase()}`; + fromValidator = trimString(msgData.value.validator_src_address, 16, 4); + toValidator = trimString(msgData.value.validator_dst_address, 16, 4); + } + + return ( +
+ + Redelegate Redelegate {amount} from {fromValidator} to{' '} + {toValidator} +
+ ); + } + + if (msgData.type === 'cosmos-sdk/MsgWithdrawDelegatorReward') { + let validator; + if (msgData.value.validator_address) { + validator = trimString(msgData.value.validator_address, 16, 4); + } + return ( +
+ + Claim Staking Reward Claim pending staking reward from{' '} + {validator} +
+ ); + } + + if (msgData.type === 'cyber/Link') { + let links; + let address; + const cyberlinks = []; + if (msgData.value.address) { + address = trimString(msgData.value.address, 8, 4); + } + if (msgData.value.links) { + msgData.value.links.forEach((link) => { + cyberlinks.push({ + from: link.from, + to: link.to, + }); + }); + } + if (cyberlinks.length > 0) { + links = cyberlinks + .map((link) => { + return `${trimString(link.from, 4, 4)} → ${trimString( + link.to, + 4, + 4 + )}`; + }) + .join(', '); + } + + return ( +
+ + {address} create link
+ {links} +
+ ); + } + + return
{msgData.type}
; +} + +export default MsgsSigner; diff --git a/src/containers/signer/component/ui.jsx b/src/containers/signer/component/ui.jsx new file mode 100644 index 000000000..dc6119ad3 --- /dev/null +++ b/src/containers/signer/component/ui.jsx @@ -0,0 +1,237 @@ +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; +import { Pane, Button, Tablist } from '@cybercongress/gravity'; +import MsgType from '../../txs/msgType'; +import { PillNumber, TabBtn, Dots } from '../../../components'; +import { trimString } from '../../../utils/utils'; +import MsgsSigner from './MsgsSigner'; +import { JsonView } from '../../wasm/ui/ui'; + +const HeaderSigner = ({ children }) => ( + + {children} + +); + +const ContainerSigner = ({ children }) => ( + + {children} + +); + +function StateSign({ msgData, onClick, onClickReject }) { + let content; + + if (msgData !== null) { + content = ( + + + Messages{' '} + + {Object.keys(msgData).length} + {' '} + + + + {/* {Object.keys(msgData).map((key) => ( + + + + + ))} */} + + + ); + } + + return ( + + sign tx + + {content} + + + + + + + ); +} + +function StateBroadcast() { + return ( + + Broadcast txs + + + Please wait while we confirm the transaction on the blockchain{' '} + + + + + ); +} + +function StateConfirmed({ txHash, onClick }) { + return ( + + Confirmed + + + Transaction hash:{' '} + + {trimString(txHash, 6, 6)} + + + + + + + + ); +} + +function StateInitAccount({ onClickCreateNew, onClickRestore }) { + return ( + + Init Account + + + + + + + + ); +} + +function StateRestore({ valuePhrase, onChangeInputPhrase, onClick }) { + return ( + + Restore phrase + + + Input your seed : +