diff --git a/lerna.json b/lerna.json
index 56eecf45f7..110180cdb8 100644
--- a/lerna.json
+++ b/lerna.json
@@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
- "version": "0.24.1",
+ "version": "0.24.2",
"npmClient": "yarn",
"useWorkspaces": true
}
diff --git a/package.json b/package.json
index f9a65aa48b..845830554b 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "neuron",
"productName": "Neuron",
"description": "CKB Neuron Wallet",
- "version": "0.24.1",
+ "version": "0.24.2",
"private": true,
"author": {
"name": "Nervos Core Dev",
diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json
index 2247d22eda..9353a6280d 100644
--- a/packages/neuron-ui/package.json
+++ b/packages/neuron-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "neuron-ui",
- "version": "0.24.1",
+ "version": "0.24.2",
"private": true,
"author": {
"name": "Nervos Core Dev",
@@ -53,7 +53,7 @@
"qr.js": "0.0.0",
"react": "16.9.0",
"react-dom": "16.9.0",
- "react-i18next": "10.12.2",
+ "react-i18next": "11.0.1",
"react-router-dom": "5.0.1",
"react-scripts": "3.2.0",
"styled-components": "5.0.0-beta.0"
diff --git a/packages/neuron-ui/src/components/CustomRows/DAORecordRow.tsx b/packages/neuron-ui/src/components/CustomRows/DAORecordRow.tsx
new file mode 100644
index 0000000000..640ce7a0ad
--- /dev/null
+++ b/packages/neuron-ui/src/components/CustomRows/DAORecordRow.tsx
@@ -0,0 +1,143 @@
+import React, { useEffect, useState } from 'react'
+import { DefaultButton } from 'office-ui-fabric-react'
+import { useTranslation } from 'react-i18next'
+import { ckbCore, getBlockByNumber } from 'services/chain'
+import calculateAPY from 'utils/calculateAPY'
+import { shannonToCKBFormatter, uniformTimeFormatter, localNumberFormatter } from 'utils/formatters'
+import calculateClaimEpochNumber from 'utils/calculateClaimEpochNumber'
+import { epochParser } from 'utils/parsers'
+
+import * as styles from './daoRecordRow.module.scss'
+
+const DAORecord = ({
+ daoData,
+ blockNumber,
+ blockHash,
+ outPoint: { txHash, index },
+ tipBlockNumber,
+ tipBlockHash,
+ capacity,
+ actionLabel,
+ onClick,
+ timestamp,
+ depositOutPoint,
+ epoch,
+}: State.NervosDAORecord & {
+ actionLabel: string
+ onClick: any
+ tipBlockNumber: string
+ tipBlockHash: string
+ epoch: string
+}) => {
+ const [t] = useTranslation()
+ const [withdrawValue, setWithdrawValue] = useState('')
+ const [depositEpoch, setDepositEpoch] = useState('')
+
+ useEffect(() => {
+ const withdrawBlockHash = depositOutPoint ? blockHash : tipBlockHash
+ if (!withdrawBlockHash) {
+ return
+ }
+ const formattedDepositOutPoint = depositOutPoint
+ ? {
+ txHash: depositOutPoint.txHash,
+ index: BigInt(depositOutPoint.index),
+ }
+ : {
+ txHash,
+ index: BigInt(index),
+ }
+ ;(ckbCore.rpc as any)
+ .calculateDaoMaximumWithdraw(formattedDepositOutPoint, withdrawBlockHash)
+ .then((res: string) => {
+ setWithdrawValue(BigInt(res).toString())
+ })
+ .catch((err: Error) => {
+ console.error(err)
+ })
+ }, [txHash, index, tipBlockHash, depositOutPoint, blockHash])
+
+ useEffect(() => {
+ if (!depositOutPoint) {
+ return
+ }
+ const depositBlockNumber = ckbCore.utils.bytesToHex(ckbCore.utils.hexToBytes(daoData).reverse())
+ getBlockByNumber(BigInt(depositBlockNumber))
+ .then(b => {
+ setDepositEpoch(b.header.epoch)
+ })
+ .catch((err: Error) => {
+ console.error(err)
+ })
+ }, [daoData, depositOutPoint])
+
+ const interest = BigInt(withdrawValue) - BigInt(capacity)
+
+ let ready = false
+ let metaInfo = 'Ready'
+ if (!depositOutPoint) {
+ const duration = BigInt(tipBlockNumber) - BigInt(blockNumber)
+ metaInfo = t('nervos-dao.interest-accumulated', {
+ blockNumber: localNumberFormatter(duration >= BigInt(0) ? duration : 0),
+ })
+ } else {
+ const depositEpochInfo = epochParser(depositEpoch)
+ const currentEpochInfo = epochParser(epoch)
+ const targetEpochNumber = calculateClaimEpochNumber(depositEpochInfo, currentEpochInfo)
+ if (targetEpochNumber < currentEpochInfo.number + BigInt(1) && targetEpochNumber >= currentEpochInfo.number) {
+ metaInfo = 'Ready'
+ ready = true
+ } else {
+ const epochs = targetEpochNumber - currentEpochInfo.number - BigInt(1)
+ metaInfo = t('nervos-dao.blocks-left', {
+ epochs: localNumberFormatter(epochs),
+ blocks: localNumberFormatter(currentEpochInfo.length - currentEpochInfo.index),
+ days: localNumberFormatter(epochs / BigInt(6)),
+ })
+ }
+ }
+
+ return (
+
+
+
{interest >= BigInt(0) ? `${shannonToCKBFormatter(interest.toString()).toString()} CKB` : ''}
+
{`${shannonToCKBFormatter(capacity)} CKB`}
+
+
+
+
+
+
+ {`APY: ~${calculateAPY(
+ interest >= BigInt(0) ? interest.toString() : '0',
+ capacity,
+ `${Date.now() - +timestamp}`
+ )}%`}
+
+ {uniformTimeFormatter(+timestamp)}
+ {metaInfo}
+
+
+ )
+}
+
+DAORecord.displayName = 'DAORecord'
+
+export default DAORecord
diff --git a/packages/neuron-ui/src/components/CustomRows/daoRecordRow.module.scss b/packages/neuron-ui/src/components/CustomRows/daoRecordRow.module.scss
new file mode 100644
index 0000000000..7a2bede64c
--- /dev/null
+++ b/packages/neuron-ui/src/components/CustomRows/daoRecordRow.module.scss
@@ -0,0 +1,35 @@
+.daoRecord {
+ display: flex;
+ flex-direction: column;
+ border: 1px solid #000;
+ border-radius: 5px;
+ margin: 10px 0;
+ padding: 5px 15px;
+
+ .primaryInfo,
+ .secondaryInfo {
+ display: flex;
+ justify-content: space-between;
+
+ &>div,
+ &>span {
+ flex: 1;
+ text-align: center;
+
+ &:first-child {
+ text-align: left;
+ }
+
+ &:last-child {
+ text-align: right;
+ }
+ }
+
+ }
+
+ .secondaryInfo {
+ font-size: 12px;
+ color: #666;
+ }
+
+}
diff --git a/packages/neuron-ui/src/components/NervosDAO/DepositDialog.tsx b/packages/neuron-ui/src/components/NervosDAO/DepositDialog.tsx
new file mode 100644
index 0000000000..43e1d8a8b6
--- /dev/null
+++ b/packages/neuron-ui/src/components/NervosDAO/DepositDialog.tsx
@@ -0,0 +1,86 @@
+import React from 'react'
+import {
+ Stack,
+ Dialog,
+ TextField,
+ Slider,
+ Text,
+ DefaultButton,
+ PrimaryButton,
+ DialogType,
+ DialogFooter,
+ Spinner,
+ SpinnerSize,
+} from 'office-ui-fabric-react'
+import { useTranslation } from 'react-i18next'
+import { SHANNON_CKB_RATIO } from 'utils/const'
+
+const DepositDialog = ({
+ show,
+ value,
+ fee,
+ balance,
+ onChange,
+ onSlide,
+ onSubmit,
+ onDismiss,
+ isDepositing,
+ errorMessage,
+}: any) => {
+ const [t] = useTranslation()
+ const maxValue = +(BigInt(balance) / BigInt(SHANNON_CKB_RATIO)).toString()
+
+ if (!show) {
+ return null
+ }
+
+ return (
+
+ )
+}
+
+DepositDialog.displayName = 'DepositDialog'
+
+export default DepositDialog
diff --git a/packages/neuron-ui/src/components/NervosDAO/WithdrawDialog.tsx b/packages/neuron-ui/src/components/NervosDAO/WithdrawDialog.tsx
new file mode 100644
index 0000000000..77c77b2760
--- /dev/null
+++ b/packages/neuron-ui/src/components/NervosDAO/WithdrawDialog.tsx
@@ -0,0 +1,107 @@
+import React, { useState, useEffect } from 'react'
+import { Dialog, DialogFooter, DefaultButton, PrimaryButton, DialogType } from 'office-ui-fabric-react'
+import { useTranslation } from 'react-i18next'
+import { shannonToCKBFormatter, localNumberFormatter } from 'utils/formatters'
+import { ckbCore } from 'services/chain'
+import calculateTargetEpochNumber from 'utils/calculateClaimEpochNumber'
+import { epochParser } from 'utils/parsers'
+
+const WithdrawDialog = ({
+ onDismiss,
+ onSubmit,
+ record,
+ tipBlockHash,
+ currentEpoch,
+}: {
+ onDismiss: any
+ onSubmit: any
+ record: State.NervosDAORecord
+ tipBlockHash: string
+ currentEpoch: string
+}) => {
+ const [t] = useTranslation()
+ const [depositEpoch, setDepositEpoch] = useState('')
+ const [withdrawValue, setWithdrawValue] = useState('')
+ useEffect(() => {
+ if (!record) {
+ return
+ }
+ ckbCore.rpc
+ .getBlock(record.blockHash)
+ .then(b => {
+ setDepositEpoch(b.header.epoch)
+ })
+ .catch((err: Error) => {
+ console.error(err)
+ })
+ }, [record])
+ useEffect(() => {
+ if (!record || !tipBlockHash) {
+ return
+ }
+
+ ;(ckbCore.rpc as any)
+ .calculateDaoMaximumWithdraw(
+ {
+ txHash: record.outPoint.txHash,
+ index: `0x${BigInt(record.outPoint.index).toString(16)}`,
+ },
+ tipBlockHash
+ )
+ .then((res: string) => {
+ setWithdrawValue(res)
+ })
+ .catch((err: Error) => {
+ console.error(err)
+ })
+ }, [record, tipBlockHash])
+
+ const depositEpochInfo = epochParser(depositEpoch)
+ const currentEpochInfo = epochParser(currentEpoch)
+ const targetEpochNumber = calculateTargetEpochNumber(depositEpochInfo, currentEpochInfo)
+ const epochs = targetEpochNumber - currentEpochInfo.number - BigInt(1)
+ const message = t('nervos-dao.notice-wait-time', {
+ epochs: localNumberFormatter(epochs),
+ blocks: localNumberFormatter(currentEpochInfo.length - currentEpochInfo.index),
+ days: localNumberFormatter(epochs / BigInt(6)),
+ })
+ return (
+
+ )
+}
+
+WithdrawDialog.displayName = 'WithdrawDialog'
+
+export default WithdrawDialog
diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx
new file mode 100644
index 0000000000..738fcec07a
--- /dev/null
+++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx
@@ -0,0 +1,294 @@
+import React, { useState, useEffect, useCallback, useMemo } from 'react'
+import { RouteComponentProps } from 'react-router-dom'
+import { useTranslation } from 'react-i18next'
+import { Stack, Text, DefaultButton, Icon, TooltipHost, Spinner } from 'office-ui-fabric-react'
+
+import appState from 'states/initStates/app'
+import { AppActions, StateWithDispatch } from 'states/stateProvider/reducer'
+import { updateNervosDaoData, clearNervosDaoData } from 'states/stateProvider/actionCreators'
+
+import calculateFee from 'utils/calculateFee'
+import { shannonToCKBFormatter } from 'utils/formatters'
+import { MIN_DEPOSIT_AMOUNT, MEDIUM_FEE_RATE, SHANNON_CKB_RATIO } from 'utils/const'
+
+import { generateDepositTx, generateWithdrawTx, generateClaimTx } from 'services/remote'
+import { epochParser } from 'utils/parsers'
+
+import DAORecord from 'components/CustomRows/DAORecordRow'
+
+import DepositDialog from './DepositDialog'
+import WithdrawDialog from './WithdrawDialog'
+
+let timer: NodeJS.Timeout
+
+const NervosDAO = ({
+ app: {
+ send = appState.send,
+ loadings: { sending = false },
+ tipBlockNumber,
+ tipBlockHash,
+ epoch,
+ },
+ wallet,
+ dispatch,
+ nervosDAO: { records },
+}: React.PropsWithoutRef) => {
+ const [t] = useTranslation()
+ const [depositValue, setDepositValue] = useState(`${MIN_DEPOSIT_AMOUNT}`)
+ const [showDepositDialog, setShowDepositDialog] = useState(false)
+ const [activeRecord, setActiveRecord] = useState(null)
+ const [errorMessage, setErrorMessage] = useState('')
+
+ const clearGeneratedTx = useCallback(() => {
+ dispatch({
+ type: AppActions.ClearSendState,
+ payload: null,
+ })
+ }, [dispatch])
+
+ const updateDepositValue = useCallback(
+ (value: string) => {
+ if (Number.isNaN(+value) || /[^\d.]/.test(value) || +value < 0) {
+ return
+ }
+ clearTimeout(timer)
+ timer = setTimeout(() => {
+ if (+value < MIN_DEPOSIT_AMOUNT) {
+ setErrorMessage(t('nervos-dao.minimal-fee-required', { minimal: MIN_DEPOSIT_AMOUNT }))
+ clearGeneratedTx()
+ } else {
+ setErrorMessage('')
+ generateDepositTx({
+ feeRate: `${MEDIUM_FEE_RATE}`,
+ capacity: (BigInt(value) * BigInt(SHANNON_CKB_RATIO)).toString(),
+ walletID: wallet.id,
+ }).then(res => {
+ if (res.status === 1) {
+ dispatch({
+ type: AppActions.UpdateGeneratedTx,
+ payload: res.result,
+ })
+ } else {
+ clearGeneratedTx()
+ setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`)
+ }
+ })
+ }
+ }, 500)
+ setDepositValue(value)
+ },
+ [clearGeneratedTx, dispatch, wallet.id, t]
+ )
+
+ useEffect(() => {
+ updateNervosDaoData({ walletID: wallet.id })(dispatch)
+ updateDepositValue(`${MIN_DEPOSIT_AMOUNT}`)
+ return () => {
+ clearNervosDaoData()(dispatch)
+ clearGeneratedTx()
+ }
+ }, [clearGeneratedTx, dispatch, updateDepositValue, wallet.id])
+
+ const onDepositDialogDismiss = () => {
+ setShowDepositDialog(false)
+ setDepositValue(`${MIN_DEPOSIT_AMOUNT}`)
+ setErrorMessage('')
+ }
+
+ const onDepositDialogSubmit = () => {
+ setShowDepositDialog(false)
+ setDepositValue(`${MIN_DEPOSIT_AMOUNT}`)
+ dispatch({
+ type: AppActions.RequestPassword,
+ payload: {
+ walletID: wallet.id,
+ actionType: 'send',
+ },
+ })
+ }
+
+ const onWithdrawDialogDismiss = () => {
+ setActiveRecord(null)
+ }
+
+ const onWithdrawDialogSubmit = () => {
+ setErrorMessage('')
+ if (activeRecord) {
+ ;(activeRecord.depositOutPoint
+ ? generateClaimTx({
+ walletID: wallet.id,
+ withdrawingOutPoint: activeRecord.outPoint,
+ depositOutPoint: activeRecord.depositOutPoint,
+ feeRate: `${MEDIUM_FEE_RATE}`,
+ })
+ : generateWithdrawTx({
+ walletID: wallet.id,
+ outPoint: activeRecord.outPoint,
+ feeRate: `${MEDIUM_FEE_RATE}`,
+ })
+ )
+ .then((res: any) => {
+ if (res.status === 1) {
+ dispatch({
+ type: AppActions.UpdateGeneratedTx,
+ payload: res.result,
+ })
+ dispatch({
+ type: AppActions.RequestPassword,
+ payload: {
+ walletID: wallet.id,
+ actionType: 'send',
+ },
+ })
+ } else {
+ clearGeneratedTx()
+ setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`)
+ }
+ })
+ .catch((err: Error) => {
+ dispatch({
+ type: AppActions.AddNotification,
+ payload: {
+ type: 'alert',
+ timestamp: +new Date(),
+ content: err.message,
+ },
+ })
+ })
+ }
+ setActiveRecord(null)
+ }
+
+ const onActionClick = useCallback(
+ (e: any) => {
+ const { dataset } = e.target
+ const outPoint = {
+ txHash: dataset.txHash,
+ index: dataset.index,
+ }
+ const record = records.find(r => r.outPoint.txHash === outPoint.txHash && r.outPoint.index === outPoint.index)
+ if (record) {
+ setActiveRecord(record)
+ }
+ },
+ [records]
+ )
+
+ const fee = `${shannonToCKBFormatter(
+ send.generatedTx ? send.generatedTx.fee || calculateFee(send.generatedTx) : '0'
+ )} CKB`
+
+ const Records = useMemo(() => {
+ return (
+ <>
+
+ {t('nervos-dao.deposit-records')}
+
+
+ {records.map(record => {
+ let stage = 'deposited'
+ if (record.depositOutPoint) {
+ stage = 'withdrawing'
+ }
+ return (
+
+ )
+ })}
+
+ >
+ )
+ }, [records, t, tipBlockHash, onActionClick, tipBlockNumber, epoch])
+
+ let free = BigInt(0)
+ let locked = BigInt(0)
+ records.forEach(r => {
+ if (!r.depositOutPoint) {
+ locked += BigInt(r.capacity)
+ } else {
+ free += BigInt(r.capacity)
+ }
+ })
+
+ const EpochInfo = useMemo(() => {
+ if (!epoch) {
+ return
+ }
+ const epochInfo = epochParser(epoch)
+ return (
+
+ {`Epoch number: ${epochInfo.number}`}
+ {`Epoch index: ${epochInfo.index}`}
+ {`Epoch length: ${epochInfo.length}`}
+
+ )
+ }, [epoch])
+
+ return (
+ <>
+
+
+ {wallet.name}
+
+
+
+
+ {`${t('nervos-dao.free')}: `}
+ {`${shannonToCKBFormatter(`${free}`)} CKB`}
+
+
+ {`${t('nervos-dao.locked')}: `}
+ {`${shannonToCKBFormatter(`${locked}`)} CKB`}
+
+
+
+ setShowDepositDialog(true)}
+ />
+
+
+
+
+
+ {Records}
+
+ updateDepositValue(value)}
+ onDismiss={onDepositDialogDismiss}
+ onSubmit={onDepositDialogSubmit}
+ onSlide={(value: number) => updateDepositValue(`${value}`)}
+ balance={wallet.balance}
+ isDepositing={sending}
+ errorMessage={errorMessage}
+ />
+ {activeRecord ? (
+
+ ) : null}
+ >
+ )
+}
+
+NervosDAO.displayName = 'NervosDAOao'
+
+export default NervosDAO
diff --git a/packages/neuron-ui/src/components/Overview/index.tsx b/packages/neuron-ui/src/components/Overview/index.tsx
index bfe23b7900..0dedc52dcf 100644
--- a/packages/neuron-ui/src/components/Overview/index.tsx
+++ b/packages/neuron-ui/src/components/Overview/index.tsx
@@ -100,7 +100,7 @@ const Overview = ({
},
{
label: t('overview.epoch'),
- value: epochParser(epoch).index,
+ value: epochParser(epoch).number.toString(),
},
{
label: t('overview.difficulty'),
diff --git a/packages/neuron-ui/src/components/Receive/index.tsx b/packages/neuron-ui/src/components/Receive/index.tsx
index 9c99c7cd8b..4ff1032878 100644
--- a/packages/neuron-ui/src/components/Receive/index.tsx
+++ b/packages/neuron-ui/src/components/Receive/index.tsx
@@ -1,7 +1,7 @@
import React, { useState, useCallback, useMemo } from 'react'
import { RouteComponentProps } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
-import { Stack, Text, TextField, TooltipHost, Modal, FontSizes, IconButton } from 'office-ui-fabric-react'
+import { Stack, Text, TextField, TooltipHost, Modal, IconButton } from 'office-ui-fabric-react'
import { StateWithDispatch } from 'states/stateProvider/reducer'
import QRCode from 'widgets/QRCode'
@@ -28,35 +28,43 @@ const Receive = ({
addPopup('addr-copied')(dispatch)
}, [accountAddress, dispatch])
+ const Address = useMemo(
+ () => (
+
+
+
+
+
+
+
+
+ ),
+ [copyAddress, accountAddress, t]
+ )
+
if (!accountAddress) {
return {t('receive.address-not-found')}
}
return (
<>
-
-
-
-
-
-
-
-
-
-
+
+
+ {`${t('receive.address', { network: accountAddress.startsWith('ckb') ? 'CKB Mainnet' : 'CKB Testnet' })}`}
+
+
+ {t('receive.prompt')}
+
setShowLargeQRCode(false)}>
diff --git a/packages/neuron-ui/src/containers/Main/hooks.ts b/packages/neuron-ui/src/containers/Main/hooks.ts
index 1216c6ca25..7bea9fe347 100644
--- a/packages/neuron-ui/src/containers/Main/hooks.ts
+++ b/packages/neuron-ui/src/containers/Main/hooks.ts
@@ -19,7 +19,7 @@ import {
SyncedBlockNumber as SyncedBlockNumberSubject,
Command as CommandSubject,
} from 'services/subjects'
-import { ckbCore, getTipBlockNumber, getBlockchainInfo } from 'services/chain'
+import { ckbCore, getBlockchainInfo, getTipHeader } from 'services/chain'
import { ConnectionStatus, ErrorCode } from 'utils/const'
import {
networks as networksCache,
@@ -32,47 +32,25 @@ const SYNC_INTERVAL_TIME = 10000
export const useSyncChainData = ({ chainURL, dispatch }: { chainURL: string; dispatch: StateDispatch }) => {
useEffect(() => {
- const syncTipNumber = () =>
- getTipBlockNumber()
- .then(tipBlockNumber => {
+ const syncBlockchainInfo = () => {
+ Promise.all([getTipHeader(), getBlockchainInfo()])
+ .then(([header, chainInfo]) => {
dispatch({
- type: AppActions.UpdateTipBlockNumber,
- payload: BigInt(tipBlockNumber).toString(),
+ type: AppActions.UpdateChainInfo,
+ payload: {
+ tipBlockNumber: `${BigInt(header.number)}`,
+ tipBlockHash: header.hash,
+ chain: chainInfo.chain,
+ difficulty: `${BigInt(chainInfo.difficulty)}`,
+ epoch: chainInfo.epoch,
+ },
})
+
dispatch({
type: AppActions.ClearNotificationsOfCode,
payload: ErrorCode.NodeDisconnected,
})
})
- .catch((err: Error) => {
- if (process.env.NODE_ENV === 'development') {
- console.error(err)
- }
- })
-
- const syncBlockchainInfo = () => {
- getBlockchainInfo()
- .then(info => {
- if (info) {
- const { chain = '', difficulty: difficultyHex = '', epoch: epochHex = '', alerts = [] } = info
- const difficulty = BigInt(difficultyHex).toString()
- const epoch = BigInt(epochHex).toString()
- if (alerts.length) {
- alerts.forEach(a => {
- // TODO: display alerts in Notification
- console.info(a)
- })
- }
- dispatch({
- type: AppActions.UpdateChainInfo,
- payload: {
- chain,
- difficulty,
- epoch,
- },
- })
- }
- })
.catch((err: Error) => {
if (process.env.NODE_ENV === 'development') {
console.warn(err)
@@ -82,10 +60,8 @@ export const useSyncChainData = ({ chainURL, dispatch }: { chainURL: string; dis
clearInterval(timer)
if (chainURL) {
ckbCore.setNode(chainURL)
- syncTipNumber()
syncBlockchainInfo()
timer = setInterval(() => {
- syncTipNumber()
syncBlockchainInfo()
}, SYNC_INTERVAL_TIME)
} else {
diff --git a/packages/neuron-ui/src/containers/Main/index.tsx b/packages/neuron-ui/src/containers/Main/index.tsx
index be2ba32dde..a065e52df6 100644
--- a/packages/neuron-ui/src/containers/Main/index.tsx
+++ b/packages/neuron-ui/src/containers/Main/index.tsx
@@ -18,6 +18,7 @@ import NetworkEditor from 'components/NetworkEditor'
import WalletEditor from 'components/WalletEditor'
import LaunchScreen from 'components/LaunchScreen'
import PasswordRequest from 'components/PasswordRequest'
+import NervosDAO from 'components/NervosDAO'
import { Routes } from 'utils/const'
@@ -107,6 +108,12 @@ export const mainContents: CustomRouter.Route[] = [
exact: false,
comp: PasswordRequest,
},
+ {
+ name: `NervosDAO`,
+ path: Routes.NervosDAO,
+ exact: true,
+ comp: NervosDAO,
+ },
]
const MainContent = ({
diff --git a/packages/neuron-ui/src/containers/Navbar/index.tsx b/packages/neuron-ui/src/containers/Navbar/index.tsx
index 2d6068681d..9e39018fe8 100644
--- a/packages/neuron-ui/src/containers/Navbar/index.tsx
+++ b/packages/neuron-ui/src/containers/Navbar/index.tsx
@@ -13,6 +13,7 @@ const menuItems = [
{ name: 'navbar.send', key: Routes.Send.slice(1), url: Routes.Send },
{ name: 'navbar.receive', key: Routes.Receive.slice(1), url: Routes.Receive },
{ name: 'navbar.history', key: Routes.History.slice(1), url: Routes.History },
+ { name: 'navbar.nervos-dao', key: Routes.NervosDAO.slice(1), url: Routes.NervosDAO },
{ name: 'navbar.addresses', key: Routes.Addresses.slice(1), url: Routes.Addresses },
]
diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json
index 4dbcb0152f..1258eca584 100644
--- a/packages/neuron-ui/src/locales/en.json
+++ b/packages/neuron-ui/src/locales/en.json
@@ -10,7 +10,8 @@
"receive": "Receive",
"history": "History",
"addresses": "Addresses",
- "settings": "Settings"
+ "settings": "Settings",
+ "nervos-dao": "Nervos DAO"
},
"overview": {
"balance": "Balance",
@@ -106,7 +107,8 @@
"click-to-copy": "Click to copy the address",
"address-not-found": "Address not found",
"prompt": "Neuron picks a new receiving address for better privacy. Please go to the Address Book if you want to use a previously used receiving address.",
- "address-qrcode": "Address QR Code"
+ "address-qrcode": "Address QR Code",
+ "address": "{{network}} Address"
},
"history": {
"meta": "Meta",
@@ -304,6 +306,32 @@
"last-page": "Last page",
"page": "Page",
"selected": "Current page"
+ },
+ "nervos-dao": {
+ "free": "Free",
+ "locked": "Locked",
+ "deposit": "Deposit",
+ "deposit-records": "Deposit Records",
+ "apy": "APY",
+ "deposit-at": "Deposit at {{time}}",
+ "claim": "Claim",
+ "withdraw": "Withdraw",
+ "fee": "Transaction fee",
+ "deposit-to-nervos-dao": "Deposit to Nervos DAO",
+ "withdraw-from-nervos-dao": "Withdraw from Nervos DAO",
+ "notice": "Notice",
+ "cancel": "Cancel",
+ "proceed": "Proceed",
+ "deposit-value": "Deposit",
+ "interest": "Interest",
+ "yield": "Yield",
+ "notice-wait-time": "Notice: You need to wait {{epochs}} epochs {{blocks}} blocks(~{{days}} days) to claim the saving.",
+ "deposit-terms": "Nervos DAO is a system layer decentralized infrastructure. Your saving here is secure.\nAccording to the Nervos DAO protocol, you need at least 180 epochs to withdraw your deposit",
+ "deposited-action-label": "Withdraw",
+ "withdrawing-action-label": "Claim",
+ "minimal-fee-required": "The minimum deposit capacity is {{minimal}} CKB",
+ "interest-accumulated": "{{blockNumber}} blocks interest accumulated",
+ "blocks-left": "{{epochs}} epochs {{blocks}} blocks left(~{{days}} days)"
}
}
}
diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json
index c8dd4d46f7..e01e5e5d4b 100644
--- a/packages/neuron-ui/src/locales/zh.json
+++ b/packages/neuron-ui/src/locales/zh.json
@@ -10,7 +10,8 @@
"receive": "收款",
"history": "交易历史",
"addresses": "地址管理",
- "settings": "设置"
+ "settings": "设置",
+ "nervos-dao": "Nervos DAO"
},
"overview": {
"balance": "余额",
@@ -106,7 +107,8 @@
"click-to-copy": "点击复制地址",
"address-not-found": "未找到地址",
"prompt": "为了保护隐私,Neuron 会自动选择一个新收款地址。如果您想使用旧的收款地址,请访问地址管理页面。",
- "address-qrcode": "地址二维码"
+ "address-qrcode": "地址二维码",
+ "address": "{{network}} 地址"
},
"history": {
"meta": "元信息",
@@ -304,6 +306,32 @@
"last-page": "尾页",
"page": "页码",
"selected": "当前页"
+ },
+ "nervos-dao": {
+ "free": "当前可用",
+ "locked": "已锁定",
+ "deposit": "存入",
+ "deposit-records": "存款记录",
+ "apy": "预期年化利率",
+ "deposit-at": "存入于{{time}}",
+ "claim": "Claim",
+ "withdraw": "Withdraw",
+ "fee": "手续费",
+ "deposit-to-nervos-dao": "存入 Nervos DAO",
+ "withdraw-from-nervos-dao": "从 Nervos DAO 取出",
+ "notice": "注意",
+ "cancel": "取消",
+ "proceed": "继续",
+ "deposit-value": "存款",
+ "interest": "利息",
+ "yield": "Yield",
+ "notice-wait-time": "注意: 您需要等待 {{epochs}} epochs {{blocks}} 区块(~{{days}}天)完成最终取款。",
+ "deposit-terms": "Nervos DAO is a system layer decentralized infrastructure. Your saving here is secure.\nAccording to the Nervos DAO protocol, you need at least 180 epochs to withdraw your deposit",
+ "deposited-action-label": "Withdraw",
+ "withdrawing-action-label": "Claim",
+ "minimal-fee-required": "存入金额应不少于 {{minimal}} CKB",
+ "interest-accumulated": "已累计 {{blockNumber}} 个块的利息",
+ "blocks-left": " 还需等待 {{epochs}} epochs {{blocks}} 个块(~{{days}} 天)"
}
}
}
diff --git a/packages/neuron-ui/src/services/chain.ts b/packages/neuron-ui/src/services/chain.ts
index 71aa296ecf..be8bd723b9 100644
--- a/packages/neuron-ui/src/services/chain.ts
+++ b/packages/neuron-ui/src/services/chain.ts
@@ -2,10 +2,17 @@ import CKBCore from '@nervosnetwork/ckb-sdk-core'
export const ckbCore = new CKBCore('')
-export const { getTipBlockNumber, getBlockchainInfo } = ckbCore.rpc
+ckbCore.rpc.addMethod({
+ name: 'calculateDaoMaximumWithdraw',
+ method: 'calculate_dao_maximum_withdraw',
+ paramsFormatters: [ckbCore.rpc.paramsFormatter.toOutPoint, ckbCore.rpc.paramsFormatter.toHash],
+})
+
+export const { getBlockchainInfo, getTipHeader, getBlockByNumber } = ckbCore.rpc
export default {
ckbCore,
- getTipBlockNumber,
getBlockchainInfo,
+ getTipHeader,
+ getBlockByNumber,
}
diff --git a/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts b/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
index d21f8db749..3d09cebaf5 100644
--- a/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
+++ b/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
@@ -47,8 +47,9 @@ export const apiMethodWrapper = (
}))
if (process.env.NODE_ENV === 'development' && window.localStorage.getItem('log-response')) {
- console.group('api controller')
- console.info(JSON.stringify(res, null, 2))
+ console.group(callControllerMethod)
+ console.info(`params: ${JSON.stringify(realParams, null, 2)}`)
+ console.info(`res: ${JSON.stringify(res, null, 2)}`)
console.groupEnd()
}
diff --git a/packages/neuron-ui/src/services/remote/wallets.ts b/packages/neuron-ui/src/services/remote/wallets.ts
index 2ab31713d1..0b807ec406 100644
--- a/packages/neuron-ui/src/services/remote/wallets.ts
+++ b/packages/neuron-ui/src/services/remote/wallets.ts
@@ -38,6 +38,20 @@ export const updateAddressDescription = apiMethodWrapper(api => (params: Control
api.updateAddressDescription(params)
)
+export const getNervosDaoData = apiMethodWrapper(api => (params: Controller.GetNervosDaoDataParams) =>
+ api.getDaoCells(params)
+)
+
+export const generateDepositTx = apiMethodWrapper(api => (params: Controller.DepositParams) =>
+ api.generateDepositTx(params)
+)
+
+export const generateWithdrawTx = apiMethodWrapper(api => (params: Controller.WithdrawParams) =>
+ api.startWithdrawFromDao(params)
+)
+
+export const generateClaimTx = apiMethodWrapper(api => (params: Controller.ClaimParams) => api.withdrawFromDao(params))
+
export default {
updateWallet,
getWalletList,
@@ -51,4 +65,8 @@ export default {
sendTx,
getAddressesByWalletID,
updateAddressDescription,
+ getNervosDaoData,
+ generateDepositTx,
+ generateWithdrawTx,
+ generateClaimTx,
}
diff --git a/packages/neuron-ui/src/states/initStates/app.ts b/packages/neuron-ui/src/states/initStates/app.ts
index c4532a26db..690b1e9b43 100644
--- a/packages/neuron-ui/src/states/initStates/app.ts
+++ b/packages/neuron-ui/src/states/initStates/app.ts
@@ -2,6 +2,7 @@ import { CapacityUnit } from 'utils/const'
const appState: State.App = {
tipBlockNumber: '',
+ tipBlockHash: '',
chain: '',
difficulty: '',
epoch: '',
diff --git a/packages/neuron-ui/src/states/initStates/index.ts b/packages/neuron-ui/src/states/initStates/index.ts
index 456175eb1d..9cac8f7eee 100644
--- a/packages/neuron-ui/src/states/initStates/index.ts
+++ b/packages/neuron-ui/src/states/initStates/index.ts
@@ -2,17 +2,20 @@ import app from './app'
import chain from './chain'
import wallet from './wallet'
import settings from './settings'
+import nervosDAO from './nervosDAO'
export * from './app'
export * from './chain'
export * from './wallet'
export * from './settings'
+export * from './nervosDAO'
const initStates = {
app,
chain,
wallet,
settings,
+ nervosDAO,
}
export default initStates
diff --git a/packages/neuron-ui/src/states/initStates/nervosDAO.ts b/packages/neuron-ui/src/states/initStates/nervosDAO.ts
new file mode 100644
index 0000000000..da0414c1e3
--- /dev/null
+++ b/packages/neuron-ui/src/states/initStates/nervosDAO.ts
@@ -0,0 +1,5 @@
+export const emptyNervosDaoData: State.NervosDAO = {
+ records: [],
+}
+
+export default emptyNervosDaoData
diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
index 4e59511fbf..1a44e0961e 100644
--- a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
+++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
@@ -7,6 +7,7 @@ import {
getCurrentWallet,
updateWallet,
setCurrentWallet as setRemoteCurrentWallet,
+ getNervosDaoData,
sendTx,
getAddressesByWalletID,
updateAddressDescription as updateRemoteAddressDescription,
@@ -15,6 +16,7 @@ import {
showErrorMessage,
} from 'services/remote'
import { emptyWallet } from 'states/initStates/wallet'
+import { emptyNervosDaoData } from 'states/initStates/nervosDAO'
import { WalletWizardPath } from 'components/WalletWizard'
import i18n from 'utils/i18n'
import { wallets as walletsCache, currentWallet as currentWalletCache } from 'services/localCache'
@@ -265,6 +267,27 @@ export const backupWallet = (params: Controller.BackupWalletParams) => (dispatch
}
})
}
+
+export const updateNervosDaoData = (walletID: Controller.GetNervosDaoDataParams) => (dispatch: StateDispatch) => {
+ getNervosDaoData(walletID).then(res => {
+ if (res.status === 1) {
+ dispatch({
+ type: NeuronWalletActions.UpdateNervosDaoData,
+ payload: { records: res.result },
+ })
+ } else {
+ addNotification(failureResToNotification(res))(dispatch)
+ }
+ })
+}
+
+export const clearNervosDaoData = () => (dispatch: StateDispatch) => {
+ dispatch({
+ type: NeuronWalletActions.UpdateNervosDaoData,
+ payload: emptyNervosDaoData,
+ })
+}
+
export default {
createWalletWithMnemonic,
importWalletWithMnemonic,
@@ -277,4 +300,5 @@ export default {
updateAddressDescription,
deleteWallet,
backupWallet,
+ updateNervosDaoData,
}
diff --git a/packages/neuron-ui/src/states/stateProvider/reducer.ts b/packages/neuron-ui/src/states/stateProvider/reducer.ts
index 84beb07297..c464867d10 100644
--- a/packages/neuron-ui/src/states/stateProvider/reducer.ts
+++ b/packages/neuron-ui/src/states/stateProvider/reducer.ts
@@ -18,6 +18,8 @@ export enum NeuronWalletActions {
// Connection
UpdateConnectionStatus = 'updateConnectionStatus',
UpdateSyncedBlockNumber = 'updateSyncedBlockNumber',
+ // dao
+ UpdateNervosDaoData = 'updateNervosDaoData',
}
export enum AppActions {
UpdateTransactionID = 'updateTransactionID',
@@ -38,7 +40,6 @@ export enum AppActions {
RequestPassword = 'requestPassword',
DismissPasswordRequest = 'dismissPasswordRequest',
UpdatePassword = 'updatePassword',
- UpdateTipBlockNumber = 'updateTipBlockNumber',
UpdateChainInfo = 'updateChainInfo',
UpdateLoadings = 'updateLoadings',
@@ -223,19 +224,13 @@ export const reducer = (
},
}
}
- // Actions of App
- case AppActions.UpdateTipBlockNumber: {
- /**
- * paylaod: tipBlockNumber
- */
+ case NeuronWalletActions.UpdateNervosDaoData: {
return {
...state,
- app: {
- ...state.app,
- tipBlockNumber: payload,
- },
+ nervosDAO: payload,
}
}
+ // Actions of App
case AppActions.UpdateChainInfo: {
return {
...state,
diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts
index 377191480b..e214ee89dd 100644
--- a/packages/neuron-ui/src/types/App/index.d.ts
+++ b/packages/neuron-ui/src/types/App/index.d.ts
@@ -74,6 +74,7 @@ declare namespace State {
interface App {
tipBlockNumber: string
+ tipBlockHash: string
chain: string
difficulty: string
epoch: string
@@ -148,11 +149,45 @@ declare namespace State {
wallets: WalletIdentity[]
}
+ interface NervosDAORecord {
+ blockNumber: string
+ blockHash: string
+ capacity: string
+ lock: {
+ codeHash: string
+ hashType: string
+ args: string
+ }
+ lockHash: string
+ outPoint: {
+ txHash: string
+ index: string
+ }
+ depositOutPoint?: {
+ txHash: string
+ index: string
+ }
+ status: 'live' | 'dead'
+ type: {
+ codeHash: string
+ hashType: string
+ args: string
+ }
+ typeHash: string | null
+ daoData: string
+ timestamp: string
+ }
+
+ interface NervosDAO {
+ records: NervosDAORecord[]
+ }
+
interface AppWithNeuronWallet {
app: App
chain: Chain
settings: Settings
wallet: Wallet
+ nervosDAO: NervosDAO
}
}
diff --git a/packages/neuron-ui/src/types/Controller/index.d.ts b/packages/neuron-ui/src/types/Controller/index.d.ts
index b7d56a6a98..d111975962 100644
--- a/packages/neuron-ui/src/types/Controller/index.d.ts
+++ b/packages/neuron-ui/src/types/Controller/index.d.ts
@@ -76,4 +76,39 @@ declare namespace Controller {
description: string
}
type SetSkipAndTypeParam = boolean
+
+ type GetNervosDaoDataParams = {
+ walletID: string
+ }
+
+ // the generate deposit tx method in neuron wallet
+ interface DepositParams {
+ walletID: string
+ capacity: string
+ feeRate: string
+ }
+
+ // the start withdraw from dao method in neuron wallet
+ interface WithdrawParams {
+ walletID: string
+ outPoint: {
+ txHash: string
+ index: string
+ }
+ feeRate: string
+ }
+
+ // the withdraw from dao method in neuron wallet
+ interface ClaimParams {
+ walletID: string
+ depositOutPoint: {
+ txHash: string
+ index: string
+ }
+ withdrawingOutPoint: {
+ txHash: string
+ index: string
+ }
+ feeRate: string
+ }
}
diff --git a/packages/neuron-ui/src/utils/calculateAPY.ts b/packages/neuron-ui/src/utils/calculateAPY.ts
new file mode 100644
index 0000000000..4d08701d29
--- /dev/null
+++ b/packages/neuron-ui/src/utils/calculateAPY.ts
@@ -0,0 +1,7 @@
+const YEAR = 365 * 30 * 24 * 60 * 60 * 1000
+
+export default (interest: string, amount: string, duration: string) => {
+ const BASE = 10000
+ const v = Math.floor(+((BigInt(interest) * BigInt(BASE)) / BigInt(amount)).toString()) * (YEAR / +duration)
+ return `${(v / BASE).toFixed(2)}`
+}
diff --git a/packages/neuron-ui/src/utils/calculateClaimEpochNumber.ts b/packages/neuron-ui/src/utils/calculateClaimEpochNumber.ts
new file mode 100644
index 0000000000..5ebadb8e7c
--- /dev/null
+++ b/packages/neuron-ui/src/utils/calculateClaimEpochNumber.ts
@@ -0,0 +1,20 @@
+import { WITHDRAW_EPOCHS } from 'utils/const'
+
+interface EpochInfo {
+ index: bigint
+ number: bigint
+ length: bigint
+}
+
+export default (depositEpochInfo: EpochInfo, currentEpochInfo: EpochInfo) => {
+ let depositedEpochs = currentEpochInfo.number - depositEpochInfo.number
+ const depositEpochFraction = depositEpochInfo.index * currentEpochInfo.length
+ const currentEpochFraction = currentEpochInfo.index * depositEpochInfo.length
+ if (currentEpochFraction > depositEpochFraction) {
+ depositedEpochs += BigInt(1)
+ }
+ const minLockEpochs =
+ ((depositedEpochs + BigInt(WITHDRAW_EPOCHS - 1)) / BigInt(WITHDRAW_EPOCHS)) * BigInt(WITHDRAW_EPOCHS)
+ const targetEpochNumber = depositEpochInfo.number + minLockEpochs
+ return targetEpochNumber
+}
diff --git a/packages/neuron-ui/src/utils/const.ts b/packages/neuron-ui/src/utils/const.ts
index 135ae4ab4f..b56c8dffd7 100644
--- a/packages/neuron-ui/src/utils/const.ts
+++ b/packages/neuron-ui/src/utils/const.ts
@@ -11,6 +11,13 @@ export const CONFIRMATION_THRESHOLD = 30
export const MAX_DECIMAL_DIGITS = 8
+export const MIN_DEPOSIT_AMOUNT = 102
+
+export const SHANNON_CKB_RATIO = 1e8
+
+export const MEDIUM_FEE_RATE = 6000
+export const WITHDRAW_EPOCHS = 180
+
export enum ConnectionStatus {
Online = 'online',
Offline = 'offline',
@@ -36,6 +43,7 @@ export enum Routes {
NetworkEditor = '/network',
WalletEditor = '/editwallet',
Prompt = '/prompt',
+ NervosDAO = '/nervos-dao',
}
export enum CapacityUnit {
diff --git a/packages/neuron-ui/src/utils/formatters.ts b/packages/neuron-ui/src/utils/formatters.ts
index a39bbc2835..0240e1a73a 100644
--- a/packages/neuron-ui/src/utils/formatters.ts
+++ b/packages/neuron-ui/src/utils/formatters.ts
@@ -133,12 +133,13 @@ export const shannonToCKBFormatter = (shannon: string = '0', showPositiveSign?:
return +unsignedCKB === 0 ? '0' : `${sign}${unsignedCKB}`
}
-export const localNumberFormatter = (num: string | number = 0) => {
- if (Number.isNaN(+num)) {
+export const localNumberFormatter = (num: string | number | bigint = 0) => {
+ if (typeof num !== 'bigint' && Number.isNaN(+num)) {
console.warn(`Nuumber is not a valid number`)
return num
}
- return numberFormatter.format(+num)
+ const n: any = BigInt(num)
+ return numberFormatter.format(n)
}
export const uniformTimeFormatter = (time: string | number | Date) => {
diff --git a/packages/neuron-ui/src/utils/parsers.ts b/packages/neuron-ui/src/utils/parsers.ts
index 65a76e0f9a..eb89147814 100644
--- a/packages/neuron-ui/src/utils/parsers.ts
+++ b/packages/neuron-ui/src/utils/parsers.ts
@@ -24,8 +24,11 @@ export const prompt = (search: string) => {
export const queryParsers = { history, prompt }
export const epochParser = (epoch: string) => {
+ const e = BigInt(epoch)
return {
- index: +epoch & 0xffff,
+ length: (e >> BigInt(40)) & BigInt(0xffff),
+ index: (e >> BigInt(24)) & BigInt(0xffff),
+ number: e & BigInt(0xffffff),
}
}
diff --git a/packages/neuron-ui/src/widgets/QRCode/index.tsx b/packages/neuron-ui/src/widgets/QRCode/index.tsx
index af5ce69a19..7ef814096d 100644
--- a/packages/neuron-ui/src/widgets/QRCode/index.tsx
+++ b/packages/neuron-ui/src/widgets/QRCode/index.tsx
@@ -82,6 +82,7 @@ const QRCode = ({
includeMargin = false,
exportable = false,
dispatch,
+ remark,
}: {
value: string
size: number
@@ -93,6 +94,7 @@ const QRCode = ({
includeMargin?: boolean
exportable?: boolean
dispatch: StateDispatch
+ remark?: JSX.Element
}) => {
const [t] = useTranslation()
const qrcode = new QRCodeImpl(-1, level)
@@ -156,8 +158,9 @@ const QRCode = ({
+ {remark || null}
{exportable ? (
-
+
{t('qrcode.copy')}
{t('qrcode.save')}
diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json
index 150733eb54..429f913134 100644
--- a/packages/neuron-wallet/package.json
+++ b/packages/neuron-wallet/package.json
@@ -3,7 +3,7 @@
"productName": "Neuron",
"description": "CKB Neuron Wallet",
"homepage": "https://www.nervos.org/",
- "version": "0.24.1",
+ "version": "0.24.2",
"private": true,
"author": {
"name": "Nervos Core Dev",
@@ -64,7 +64,7 @@
"electron-devtools-installer": "2.2.4",
"electron-notarize": "0.1.1",
"lint-staged": "9.2.5",
- "neuron-ui": "0.24.1",
+ "neuron-ui": "0.24.2",
"rimraf": "3.0.0",
"spectron": "8.0.0",
"ts-transformer-imports": "0.4.3",
diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts
index 3648782f6e..189dc30381 100644
--- a/packages/neuron-wallet/src/controllers/api.ts
+++ b/packages/neuron-wallet/src/controllers/api.ts
@@ -269,7 +269,7 @@ export default class ApiController {
@MapApiResponse
public static async getTransactionList(
- params: Controller.Params.TransactionsByKeywords,
+ params: Controller.Params.TransactionsByKeywords
) {
return TransactionsController.getAllByKeywords(params)
}
@@ -284,15 +284,15 @@ export default class ApiController {
return TransactionsController.updateDescription(params)
}
+ @MapApiResponse
public static async showTransactionDetails(hash: string) {
showWindow(`${env.mainURL}#/transaction/${hash}`, i18n.t(`messageBox.transaction.title`, { hash }))
}
// Dao
-
@MapApiResponse
public static async getDaoCells(
- params: Controller.Params.GetDaoCellsParams,
+ params: Controller.Params.GetDaoCellsParams
) {
return DaoController.getDaoCells(params)
}
diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts
index 3d52c5eebc..e5e404d159 100644
--- a/packages/neuron-wallet/src/controllers/app/index.ts
+++ b/packages/neuron-wallet/src/controllers/app/index.ts
@@ -38,7 +38,7 @@ export default class AppController {
createWindow = () => {
const windowState = windowStateKeeper({
defaultWidth: 1366,
- defaultHeight: 768,
+ defaultHeight: 900,
})
this.mainWindow = new BrowserWindow({
@@ -46,7 +46,7 @@ export default class AppController {
y: windowState.y,
width: windowState.width,
height: windowState.height,
- minWidth: 800,
+ minWidth: 900,
minHeight: 600,
show: false,
backgroundColor: '#e9ecef',
diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts
index 81c922e8fe..48765c75b5 100644
--- a/packages/neuron-wallet/src/services/wallets.ts
+++ b/packages/neuron-wallet/src/services/wallets.ts
@@ -749,13 +749,16 @@ export default class WalletService {
}
public calculateDaoMaximumWithdraw = async (depositOutPoint: OutPoint, withdrawBlockHash: string): Promise => {
- const calculateDaoMaximumWithdrawMethod = {
- name: 'calculateDaoMaximumWithdraw',
- method: 'calculate_dao_maximum_withdraw',
- paramsFormatters: [core.rpc.paramsFormatter.toOutPoint, core.rpc.paramsFormatter.toHash],
+ if (!(core.rpc as any).calculateDaoMaximumWithdraw) {
+ const calculateDaoMaximumWithdrawMethod = {
+ name: 'calculateDaoMaximumWithdraw',
+ method: 'calculate_dao_maximum_withdraw',
+ paramsFormatters: [core.rpc.paramsFormatter.toOutPoint, core.rpc.paramsFormatter.toHash],
+ }
+
+ core.rpc.addMethod(calculateDaoMaximumWithdrawMethod)
}
- core.rpc.addMethod(calculateDaoMaximumWithdrawMethod)
const result = await (core.rpc as any).calculateDaoMaximumWithdraw(
ConvertTo.toSdkOutPoint(depositOutPoint),
diff --git a/yarn.lock b/yarn.lock
index 78f5e5031e..d9217b3d51 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14005,10 +14005,10 @@ react-hotkeys@2.0.0-pre4:
dependencies:
prop-types "^15.6.1"
-react-i18next@10.12.2:
- version "10.12.2"
- resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-10.12.2.tgz#2f2d79b84c1f3e3844d110e4c9d5c73a48f99418"
- integrity sha512-tZCBhUz8rJtgmTi1z2pWEoQBvFHjwOS2+TQ7L4RfJq1LDirXi2m+3Pwg6gUECVCGenWomLufWNiTwRF9fmBrUQ==
+react-i18next@11.0.1:
+ version "11.0.1"
+ resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.0.1.tgz#179b10cf0026677739fa96df0a7b5494df435bd1"
+ integrity sha512-TazSMob+cEztaaMcX3IQQLltzv4+b3cl6dfs9tUMVj2fD0TRDbTsQ75AaLncw6jqZf08I0yAGHeJnqbBE0eZDw==
dependencies:
"@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.1"