diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28d0b2fe98..e195f0def8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,25 @@
+## [0.23.1](https://github.com/nervosnetwork/neuron/compare/v0.23.0...v0.23.1) (2019-10-28)
+
+
+### Bug Fixes
+
+* break => continue ([05ae69e](https://github.com/nervosnetwork/neuron/commit/05ae69e))
+* return => break ([97b8ea4](https://github.com/nervosnetwork/neuron/commit/97b8ea4))
+
+
+### Features
+
+* Add a few db indices ([83dffb5](https://github.com/nervosnetwork/neuron/commit/83dffb5))
+* display disconnection errors and dismiss them on getting connec… ([#1019](https://github.com/nervosnetwork/neuron/issues/1019)) ([e866c66](https://github.com/nervosnetwork/neuron/commit/e866c66))
+* Optimize output db query ([6e36550](https://github.com/nervosnetwork/neuron/commit/6e36550))
+* stringify the result from api controller ([1f4d4ea](https://github.com/nervosnetwork/neuron/commit/1f4d4ea))
+* **neuron-ui:** add a tooltip to display synchronized block number and the tip block number ([9e52fef](https://github.com/nervosnetwork/neuron/commit/9e52fef))
+* **neuron-ui:** display confirmations of pending transactions in the recent activity list ([9aebede](https://github.com/nervosnetwork/neuron/commit/9aebede))
+* **neuron-ui:** update history list to make it more compact ([35d8b87](https://github.com/nervosnetwork/neuron/commit/35d8b87))
+* **neuron-ui:** update the Send View according to the new transaction fee model. ([dc415f3](https://github.com/nervosnetwork/neuron/commit/dc415f3))
+
+
+
# [0.23.0](https://github.com/nervosnetwork/neuron/compare/v0.22.2...v0.23.0) (2019-10-23)
diff --git a/lerna.json b/lerna.json
index 5ca6b56c1f..2dda7cfd60 100644
--- a/lerna.json
+++ b/lerna.json
@@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
- "version": "0.23.0",
+ "version": "0.23.1",
"npmClient": "yarn",
"useWorkspaces": true
}
diff --git a/package.json b/package.json
index 4a3bc1a13d..81517a7c77 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "neuron",
"productName": "Neuron",
"description": "CKB Neuron Wallet",
- "version": "0.23.0",
+ "version": "0.23.1",
"private": true,
"author": {
"name": "Nervos Core Dev",
diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json
index b6f9ba3d03..7167113c56 100644
--- a/packages/neuron-ui/package.json
+++ b/packages/neuron-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "neuron-ui",
- "version": "0.23.0",
+ "version": "0.23.1",
"private": true,
"author": {
"name": "Nervos Core Dev",
diff --git a/packages/neuron-ui/src/components/CustomRows/ActivityRow.tsx b/packages/neuron-ui/src/components/CustomRows/ActivityRow.tsx
index 692d395c89..7b83f0be21 100644
--- a/packages/neuron-ui/src/components/CustomRows/ActivityRow.tsx
+++ b/packages/neuron-ui/src/components/CustomRows/ActivityRow.tsx
@@ -34,13 +34,13 @@ const ActivityRow = (props?: ActivityRowProps) => {
return (
{`${typeLabel} ${shannonToCKBFormatter(value)} CKB`}
{statusLabel}
{time}
-
{status === 'success' ? confirmations : ''}
+
{confirmations}
)
}
diff --git a/packages/neuron-ui/src/components/CustomRows/GroupHeader.tsx b/packages/neuron-ui/src/components/CustomRows/GroupHeader.tsx
new file mode 100644
index 0000000000..29d727052b
--- /dev/null
+++ b/packages/neuron-ui/src/components/CustomRows/GroupHeader.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import { Stack, Text, getTheme } from 'office-ui-fabric-react'
+
+const {
+ palette: { neutralLighterAlt, neutralSecondary, neutralLighter },
+} = getTheme()
+
+const GroupHeader = ({ group }: any) => {
+ const { name } = group
+ return (
+
+ {name}
+
+ )
+}
+export default GroupHeader
diff --git a/packages/neuron-ui/src/components/CustomRows/HistoryRow.tsx b/packages/neuron-ui/src/components/CustomRows/HistoryRow.tsx
new file mode 100644
index 0000000000..3a3e0a4539
--- /dev/null
+++ b/packages/neuron-ui/src/components/CustomRows/HistoryRow.tsx
@@ -0,0 +1,22 @@
+import React from 'react'
+import { DetailsRow, IDetailsRowProps } from 'office-ui-fabric-react'
+
+const HistoryRow = (props?: IDetailsRowProps) => {
+ return props ? (
+
+ ) : null
+}
+
+export default HistoryRow
diff --git a/packages/neuron-ui/src/components/Overview/index.tsx b/packages/neuron-ui/src/components/Overview/index.tsx
index bbc376b1e3..8694c28e1f 100644
--- a/packages/neuron-ui/src/components/Overview/index.tsx
+++ b/packages/neuron-ui/src/components/Overview/index.tsx
@@ -118,7 +118,7 @@ const Overview = ({
const activityItems: ActivityItem[] = useMemo(
() =>
items.map(item => {
- let confirmations = '(-)'
+ let confirmations = ''
let typeLabel: string = item.type
let { status } = item
if (item.blockNumber !== undefined) {
@@ -147,7 +147,7 @@ const Overview = ({
status,
statusLabel: t(`overview.statusLabel.${status}`),
value: item.value.replace(/^-/, ''),
- confirmations: item.status === 'success' ? confirmations : '',
+ confirmations: ['success', 'pending'].includes(item.status) ? confirmations : '',
typeLabel: t(`overview.${typeLabel}`),
}
}),
diff --git a/packages/neuron-ui/src/components/PasswordRequest/index.tsx b/packages/neuron-ui/src/components/PasswordRequest/index.tsx
index b892f50401..89a2885a44 100644
--- a/packages/neuron-ui/src/components/PasswordRequest/index.tsx
+++ b/packages/neuron-ui/src/components/PasswordRequest/index.tsx
@@ -4,11 +4,10 @@ import { useTranslation } from 'react-i18next'
import { Stack, Text, Label, Modal, TextField, PrimaryButton, DefaultButton } from 'office-ui-fabric-react'
import { StateWithDispatch, AppActions } from 'states/stateProvider/reducer'
import { sendTransaction, deleteWallet, backupWallet } from 'states/stateProvider/actionCreators'
-import { priceToFee, CKBToShannonFormatter } from 'utils/formatters'
const PasswordRequest = ({
app: {
- send: { txID, outputs, description, price, cycles },
+ send: { description, generatedTx },
loadings: { sending: isSending = false },
passwordRequest: { walletID = '', actionType = null, password = '' },
},
@@ -32,15 +31,10 @@ const PasswordRequest = ({
break
}
sendTransaction({
- id: txID,
walletID,
- items: outputs.map(output => ({
- address: output.address,
- capacity: CKBToShannonFormatter(output.amount, output.unit),
- })),
+ tx: generatedTx,
description,
password,
- fee: priceToFee(price, cycles),
})(dispatch, history)
break
}
@@ -62,7 +56,7 @@ const PasswordRequest = ({
break
}
}
- }, [dispatch, walletID, password, actionType, txID, description, outputs, cycles, price, history, isSending])
+ }, [dispatch, walletID, password, actionType, description, history, isSending, generatedTx])
const onChange = useCallback(
(_e, value?: string) => {
diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts
index 6263d4a792..1f1bad2e5e 100644
--- a/packages/neuron-ui/src/components/Send/hooks.ts
+++ b/packages/neuron-ui/src/components/Send/hooks.ts
@@ -1,15 +1,16 @@
import React, { useState, useCallback, useEffect, useMemo } from 'react'
import { AppActions, StateDispatch } from 'states/stateProvider/reducer'
-import { calculateCycles } from 'services/remote/wallets'
+import { generateTx } from 'services/remote/wallets'
-import { outputsToTotalAmount, priceToFee } from 'utils/formatters'
+import { outputsToTotalAmount, CKBToShannonFormatter } from 'utils/formatters'
import { verifyAddress, verifyAmount, verifyAmountRange, verifyTransactionOutputs } from 'utils/validators'
-import { ErrorCode } from 'utils/const'
-import { MAX_DECIMAL_DIGITS } from '../../utils/const'
+import { ErrorCode, MAX_DECIMAL_DIGITS } from 'utils/const'
+import calculateFee from 'utils/calculateFee'
+
import { TransactionOutput } from '.'
-let cyclesTimer: ReturnType
+let generateTxTimer: ReturnType
const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
useCallback(
@@ -49,49 +50,47 @@ const useRemoveTransactionOutput = (dispatch: StateDispatch) =>
const useOnTransactionChange = (
walletID: string,
items: TransactionOutput[],
+ price: string,
dispatch: StateDispatch,
setIsTransactionValid: Function,
setTotalAmount: Function
) => {
useEffect(() => {
- clearTimeout(cyclesTimer)
- cyclesTimer = setTimeout(() => {
+ clearTimeout(generateTxTimer)
+ generateTxTimer = setTimeout(() => {
+ dispatch({
+ type: AppActions.UpdateGeneratedTx,
+ payload: null,
+ })
if (verifyTransactionOutputs(items)) {
setIsTransactionValid(true)
const totalAmount = outputsToTotalAmount(items)
setTotalAmount(totalAmount)
- calculateCycles({
+ const realParams = {
walletID,
- capacities: totalAmount,
- })
- .then(response => {
- if (response.status) {
- if (Number.isNaN(+response.result)) {
- throw new Error('Invalid Cycles')
- }
+ items: items.map(item => ({
+ address: item.address,
+ capacity: CKBToShannonFormatter(item.amount, item.unit),
+ })),
+ feeRate: price,
+ }
+ generateTx(realParams)
+ .then((res: any) => {
+ if (res.status === 1) {
dispatch({
- type: AppActions.UpdateSendCycles,
- payload: response.result,
+ type: AppActions.UpdateGeneratedTx,
+ payload: res.result,
})
- } else {
- throw new Error('Cycles Not Calculated')
}
})
- .catch(() => {
- dispatch({
- type: AppActions.UpdateSendCycles,
- payload: '0',
- })
+ .catch((err: Error) => {
+ console.error(err)
})
} else {
setIsTransactionValid(false)
- dispatch({
- type: AppActions.UpdateSendCycles,
- payload: '0',
- })
}
}, 300)
- }, [walletID, items, dispatch, setIsTransactionValid, setTotalAmount])
+ }, [walletID, items, price, dispatch, setIsTransactionValid, setTotalAmount])
}
const useOnSubmit = (items: TransactionOutput[], dispatch: StateDispatch) =>
@@ -170,12 +169,12 @@ const useClear = (dispatch: StateDispatch) => useCallback(() => clear(dispatch),
export const useInitialize = (
items: TransactionOutput[],
- price: string,
- cycles: string,
+ generatedTx: any | null,
dispatch: React.Dispatch,
t: any
) => {
- const fee = useMemo(() => priceToFee(price, cycles), [price, cycles]) // in shannon
+ const fee = useMemo(() => calculateFee(generatedTx), [generatedTx])
+
const [isTransactionValid, setIsTransactionValid] = useState(false)
const [totalAmount, setTotalAmount] = useState('0')
diff --git a/packages/neuron-ui/src/components/Send/index.tsx b/packages/neuron-ui/src/components/Send/index.tsx
index f6a23e66b5..6784299e9a 100644
--- a/packages/neuron-ui/src/components/Send/index.tsx
+++ b/packages/neuron-ui/src/components/Send/index.tsx
@@ -57,8 +57,8 @@ const Send = ({
onGetAddressErrorMessage,
onGetAmountErrorMessage,
onClear,
- } = useInitialize(send.outputs, send.price, send.cycles, dispatch, t)
- useOnTransactionChange(walletID, send.outputs, dispatch, setIsTransactionValid, setTotalAmount)
+ } = useInitialize(send.outputs, send.generatedTx, dispatch, t)
+ useOnTransactionChange(walletID, send.outputs, send.price, dispatch, setIsTransactionValid, setTotalAmount)
const leftStackWidth = '70%'
const labelWidth = '140px'
@@ -211,12 +211,7 @@ const Send = ({
-
+
diff --git a/packages/neuron-ui/src/components/Transaction/index.tsx b/packages/neuron-ui/src/components/Transaction/index.tsx
index 4d07dcbdf8..54b83c0b54 100644
--- a/packages/neuron-ui/src/components/Transaction/index.tsx
+++ b/packages/neuron-ui/src/components/Transaction/index.tsx
@@ -210,8 +210,15 @@ const Transaction = () => {
const currentWallet = currentWalletCache.load()
if (currentWallet) {
const hash = window.location.href.split('/').pop()
+ if (!hash) {
+ showErrorMessage(
+ t(`messages.error`),
+ t(`messages.codes.${ErrorCode.FieldNotFound}`, { fieldName: 'transaction hash' })
+ )
+ return
+ }
getTransaction({ hash, walletID: currentWallet.id })
- .then(res => {
+ .then((res: any) => {
if (res.status) {
setTransaction(res.result)
} else {
diff --git a/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx b/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx
index 948b395ce2..a37d689ad8 100644
--- a/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx
+++ b/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx
@@ -4,30 +4,24 @@ import { useTranslation } from 'react-i18next'
interface TransactionFee {
fee: string
- cycles: string
price: string
onPriceChange: any
}
const calculateSpeed = (price: number) => {
- if (price >= 160) {
- return '180'
+ if (price >= 16000) {
+ return '18000'
}
- if (price >= 40) {
- return '60'
+ if (price >= 4000) {
+ return '6000'
}
- if (price >= 20) {
- return '30'
+ if (price >= 2000) {
+ return '3000'
}
return '0'
}
-const TransactionFee: React.FunctionComponent = ({
- cycles,
- price,
- fee,
- onPriceChange,
-}: TransactionFee) => {
+const TransactionFee: React.FunctionComponent = ({ price, fee, onPriceChange }: TransactionFee) => {
const [t] = useTranslation()
const [showDetail, setShowDetail] = useState(false)
const leftStackWidth = '70%'
@@ -48,7 +42,18 @@ const TransactionFee: React.FunctionComponent = ({
-
+
{actionSpacer}
@@ -79,7 +84,7 @@ const TransactionFee: React.FunctionComponent = ({
-
+
{actionSpacer}
@@ -93,10 +98,10 @@ const TransactionFee: React.FunctionComponent = ({
dropdownWidth={140}
selectedKey={selectedSpeed}
options={[
- { key: '180', text: 'immediately' },
- { key: '60', text: '~ 30s' },
- { key: '30', text: '~ 1min' },
- { key: '0', text: '~ 3min' },
+ { key: '18000', text: 'immediately' },
+ { key: '6000', text: '~ 10 blocks' },
+ { key: '3000', text: '~ 100 blocks' },
+ { key: '0', text: '~ 500 blocks' },
]}
onRenderCaretDown={() => {
return
@@ -110,15 +115,6 @@ const TransactionFee: React.FunctionComponent = ({
/>
-
-
-
-
-
-
- {cycles}
-
-
)
diff --git a/packages/neuron-ui/src/components/TransactionList/index.tsx b/packages/neuron-ui/src/components/TransactionList/index.tsx
index b3c34caf5c..174df1fbf0 100644
--- a/packages/neuron-ui/src/components/TransactionList/index.tsx
+++ b/packages/neuron-ui/src/components/TransactionList/index.tsx
@@ -1,17 +1,19 @@
import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import {
- Stack,
- Text,
ShimmeredDetailsList,
TextField,
IconButton,
IColumn,
IGroup,
CheckboxVisibility,
+ CollapseAllVisibility,
getTheme,
} from 'office-ui-fabric-react'
+import GroupHeader from 'components/CustomRows/GroupHeader'
+import HistoryRow from 'components/CustomRows/HistoryRow'
+
import { StateDispatch } from 'states/stateProvider/reducer'
import { contextMenu, showTransactionDetails } from 'services/remote'
@@ -22,7 +24,6 @@ import {
uniformTimeFormatter,
localNumberFormatter,
} from 'utils/formatters'
-import { onRenderRow } from 'utils/fabricUIRender'
import { CONFIRMATION_THRESHOLD } from 'utils/const'
const theme = getTheme()
@@ -32,24 +33,6 @@ interface FormatTransaction extends State.Transaction {
date: string
}
-const onRenderHeader = ({ group }: any) => {
- const { name } = group
- return (
-
- {name}
-
- )
-}
-
const TransactionList = ({
isLoading = false,
items = [],
@@ -185,6 +168,10 @@ const TransactionList = ({
borderless
readOnly={!isSelected}
styles={{
+ root: {
+ flex: '1',
+ paddingRight: '15px',
+ },
fieldGroup: {
backgroundColor: isSelected ? '#fff' : 'transparent',
borderColor: 'transparent',
@@ -268,9 +255,10 @@ const TransactionList = ({
enableShimmer={isLoading}
columns={transactionColumns}
items={txs}
- groups={groups.filter(group => group.count !== 0)}
+ groups={groups}
groupProps={{
- onRenderHeader,
+ collapseAllVisibility: CollapseAllVisibility.hidden,
+ onRenderHeader: GroupHeader,
}}
checkboxVisibility={CheckboxVisibility.hidden}
onItemInvoked={item => {
@@ -282,7 +270,7 @@ const TransactionList = ({
}
}}
className="listWithDesc"
- onRenderRow={onRenderRow}
+ onRenderRow={HistoryRow}
/>
)
}
diff --git a/packages/neuron-ui/src/containers/Footer/index.tsx b/packages/neuron-ui/src/containers/Footer/index.tsx
index 3cece43d72..1ac36af58f 100644
--- a/packages/neuron-ui/src/containers/Footer/index.tsx
+++ b/packages/neuron-ui/src/containers/Footer/index.tsx
@@ -34,7 +34,7 @@ export const SyncStatus = ({
const percentage = +syncedBlockNumber / +tipBlockNumber
return (
-
+
{+syncedBlockNumber + bufferBlockNumber < +tipBlockNumber ? (
<>
{t('sync.syncing')}
diff --git a/packages/neuron-ui/src/containers/Main/hooks.ts b/packages/neuron-ui/src/containers/Main/hooks.ts
index 1dae29b28e..f696bea215 100644
--- a/packages/neuron-ui/src/containers/Main/hooks.ts
+++ b/packages/neuron-ui/src/containers/Main/hooks.ts
@@ -21,7 +21,7 @@ import {
Command as CommandSubject,
} from 'services/subjects'
import { ckbCore, getTipBlockNumber, getBlockchainInfo } from 'services/chain'
-import { ConnectionStatus } from 'utils/const'
+import { ConnectionStatus, ErrorCode } from 'utils/const'
import {
networks as networksCache,
currentNetworkID as currentNetworkIDCache,
@@ -40,6 +40,10 @@ export const useSyncChainData = ({ chainURL, dispatch }: { chainURL: string; dis
type: AppActions.UpdateTipBlockNumber,
payload: BigInt(tipBlockNumber).toString(),
})
+ dispatch({
+ type: AppActions.ClearNotificationsOfCode,
+ payload: ErrorCode.NodeDisconnected,
+ })
})
.catch((err: Error) => {
if (process.env.NODE_ENV === 'development') {
diff --git a/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts b/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
index ddf5a26940..d21f8db749 100644
--- a/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
+++ b/packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
@@ -1,4 +1,3 @@
-// TODO: use error code
interface SuccessFromController {
status: 1
result: any
@@ -12,6 +11,7 @@ interface FailureFromController {
meta?: { [key: string]: string }
}
}
+
export type ControllerResponse = SuccessFromController | FailureFromController
export const RemoteNotLoadError = {
@@ -21,17 +21,9 @@ export const RemoteNotLoadError = {
},
}
-export const apiMethodWrapper = (
- callControllerMethod: (
- controller: any
- ) => (
- params: any
- ) => Promise<{
- status: any
- result: any
- message: { code?: number; content?: string; meta?: { [key: string]: string } }
- }>
-) => async (realParams?: any): Promise
=> {
+export const apiMethodWrapper = (
+ callControllerMethod: (controller: any) => (params: T) => Promise
+) => async (realParams: T): Promise => {
if (!window.remote) {
return RemoteNotLoadError
}
@@ -44,7 +36,16 @@ export const apiMethodWrapper = (
},
}
}
- const res = await callControllerMethod(controller)(realParams)
+
+ const res: SuccessFromController | FailureFromController = await callControllerMethod(controller)(realParams)
+ .then(stringifiedRes => (stringifiedRes ? JSON.parse(stringifiedRes) : stringifiedRes))
+ .catch(() => ({
+ status: 0,
+ message: {
+ content: 'Invalid response format',
+ },
+ }))
+
if (process.env.NODE_ENV === 'development' && window.localStorage.getItem('log-response')) {
console.group('api controller')
console.info(JSON.stringify(res, null, 2))
diff --git a/packages/neuron-ui/src/services/remote/app.ts b/packages/neuron-ui/src/services/remote/app.ts
index 5a7856d64a..6b31ba7645 100644
--- a/packages/neuron-ui/src/services/remote/app.ts
+++ b/packages/neuron-ui/src/services/remote/app.ts
@@ -1,11 +1,11 @@
import { apiMethodWrapper } from './apiMethodWrapper'
-export const getNeuronWalletState = apiMethodWrapper(controller => () => controller.loadInitData())
+export const getNeuronWalletState = apiMethodWrapper(controller => () => controller.loadInitData())
-export const handleViewError = apiMethodWrapper(controller => (errorMessage: string) =>
+export const handleViewError = apiMethodWrapper(controller => errorMessage =>
controller.handleViewError(errorMessage)
)
-export const contextMenu = apiMethodWrapper(controller => (params: { type: string; id: string }) =>
+export const contextMenu = apiMethodWrapper<{ type: string; id: string }>(controller => params =>
controller.contextMenu(params)
)
diff --git a/packages/neuron-ui/src/services/remote/networks.ts b/packages/neuron-ui/src/services/remote/networks.ts
index 9ae86fe729..f45ef7382f 100644
--- a/packages/neuron-ui/src/services/remote/networks.ts
+++ b/packages/neuron-ui/src/services/remote/networks.ts
@@ -1,22 +1,22 @@
import { apiMethodWrapper } from './apiMethodWrapper'
-export const setCurrentNetowrk = apiMethodWrapper((api: any) => (networkID: string) => {
+export const setCurrentNetowrk = apiMethodWrapper(api => networkID => {
return api.setCurrentNetowrk(networkID)
})
-export const createNetwork = apiMethodWrapper(api => (params: Controller.CreateNetworkParams) => {
+export const createNetwork = apiMethodWrapper(api => params => {
return api.createNetwork(params)
})
-export const updateNetwork = apiMethodWrapper(api => ({ networkID, options }: Controller.UpdateNetworkParams) => {
+export const updateNetwork = apiMethodWrapper(api => ({ networkID, options }) => {
return api.updateNetwork(networkID, options)
})
-export const getAllNetworks = apiMethodWrapper(api => () => {
+export const getAllNetworks = apiMethodWrapper(api => () => {
return api.getAllNetworks()
})
-export const getCurrentNetworkID = apiMethodWrapper(api => () => {
+export const getCurrentNetworkID = apiMethodWrapper(api => () => {
return api.getCurrentNetworkID()
})
diff --git a/packages/neuron-ui/src/services/remote/wallets.ts b/packages/neuron-ui/src/services/remote/wallets.ts
index 594f7d8870..2ab31713d1 100644
--- a/packages/neuron-ui/src/services/remote/wallets.ts
+++ b/packages/neuron-ui/src/services/remote/wallets.ts
@@ -2,9 +2,9 @@ import { apiMethodWrapper } from './apiMethodWrapper'
export const updateWallet = apiMethodWrapper(api => (params: Controller.UpdateWalletParams) => api.updateWallet(params))
-export const getCurrentWallet = apiMethodWrapper(api => () => api.getCurrentWallet())
+export const getCurrentWallet = apiMethodWrapper(api => () => api.getCurrentWallet())
-export const getWalletList = apiMethodWrapper(api => () => api.getAllWallets())
+export const getWalletList = apiMethodWrapper(api => () => api.getAllWallets())
export const createWallet = apiMethodWrapper(api => (params: Controller.CreateWalletParams) => api.createWallet(params))
@@ -24,7 +24,11 @@ export const setCurrentWallet = apiMethodWrapper(api => (id: Controller.SetCurre
api.setCurrentWallet(id)
)
-export const sendCapacity = apiMethodWrapper(api => (params: Controller.SendTransaction) => api.sendCapacity(params))
+export const generateTx = apiMethodWrapper(api => (params: Controller.GenerateTransactionParams) =>
+ api.generateTx(params)
+)
+
+export const sendTx = apiMethodWrapper(api => (params: Controller.SendTransactionParams) => api.sendTx(params))
export const getAddressesByWalletID = apiMethodWrapper(api => (walletID: Controller.GetAddressesByWalletIDParams) =>
api.getAddressesByWalletID(walletID)
@@ -34,8 +38,6 @@ export const updateAddressDescription = apiMethodWrapper(api => (params: Control
api.updateAddressDescription(params)
)
-export const calculateCycles = apiMethodWrapper(api => (params: Controller.ComputeCycles) => api.computeCycles(params))
-
export default {
updateWallet,
getWalletList,
@@ -45,8 +47,8 @@ export default {
deleteWallet,
backupWallet,
getCurrentWallet,
- sendCapacity,
- calculateCycles,
+ generateTx,
+ sendTx,
getAddressesByWalletID,
updateAddressDescription,
}
diff --git a/packages/neuron-ui/src/states/initStates/app.ts b/packages/neuron-ui/src/states/initStates/app.ts
index c6eca66d88..c4532a26db 100644
--- a/packages/neuron-ui/src/states/initStates/app.ts
+++ b/packages/neuron-ui/src/states/initStates/app.ts
@@ -14,9 +14,9 @@ const appState: State.App = {
unit: CapacityUnit.CKB,
},
],
- price: '0',
- cycles: '0',
+ price: '1000',
description: '',
+ generatedTx: '',
},
passwordRequest: {
actionType: null,
diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts
index 2efad915fa..1111c41d9d 100644
--- a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts
+++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts
@@ -76,9 +76,6 @@ export const addPopup = (text: string) => (dispatch: StateDispatch) => {
}
export const addNotification = (message: State.Message) => (dispatch: StateDispatch) => {
- if (message && message.code === ErrorCode.NodeDisconnected) {
- return
- }
dispatch({
type: AppActions.AddNotification,
payload: message,
diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
index 9aaf4757d9..4e59511fbf 100644
--- a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
+++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts
@@ -7,7 +7,7 @@ import {
getCurrentWallet,
updateWallet,
setCurrentWallet as setRemoteCurrentWallet,
- sendCapacity,
+ sendTx,
getAddressesByWalletID,
updateAddressDescription as updateRemoteAddressDescription,
deleteWallet as deleteRemoteWallet,
@@ -141,7 +141,10 @@ export const setCurrentWallet = (id: string) => (dispatch: StateDispatch) => {
})
}
-export const sendTransaction = (params: Controller.SendTransaction) => (dispatch: StateDispatch, history: any) => {
+export const sendTransaction = (params: Controller.SendTransactionParams) => (
+ dispatch: StateDispatch,
+ history: any
+) => {
dispatch({
type: AppActions.UpdateLoadings,
payload: {
@@ -149,7 +152,7 @@ export const sendTransaction = (params: Controller.SendTransaction) => (dispatch
},
})
setTimeout(() => {
- sendCapacity(params)
+ sendTx(params)
.then(res => {
if (res.status === 1) {
dispatch({
diff --git a/packages/neuron-ui/src/states/stateProvider/reducer.ts b/packages/neuron-ui/src/states/stateProvider/reducer.ts
index a040a2eeb7..5f20b4d629 100644
--- a/packages/neuron-ui/src/states/stateProvider/reducer.ts
+++ b/packages/neuron-ui/src/states/stateProvider/reducer.ts
@@ -28,8 +28,8 @@ export enum AppActions {
RemoveSendOutput = 'removeSendOutput',
UpdateSendOutput = 'updateSendOutput',
UpdateSendPrice = 'updateSendPrice',
- UpdateSendCycles = 'updateSendCycles',
UpdateSendDescription = 'updateSendDescription',
+ UpdateGeneratedTx = 'updateGeneratedTx',
ClearSendState = 'clearSendState',
UpdateMessage = 'updateMessage',
AddNotification = 'addNotification',
@@ -357,9 +357,9 @@ export const reducer = (
},
}
}
- case AppActions.UpdateSendCycles: {
+ case AppActions.UpdateSendDescription: {
/**
- * payload: new cycles
+ * payload: new description
*/
return {
...state,
@@ -367,22 +367,19 @@ export const reducer = (
...app,
send: {
...app.send,
- cycles: payload,
+ description: payload,
},
},
}
}
- case AppActions.UpdateSendDescription: {
- /**
- * payload: new description
- */
+ case AppActions.UpdateGeneratedTx: {
return {
...state,
app: {
...app,
send: {
...app.send,
- description: payload,
+ generatedTx: payload || null,
},
},
}
diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts
index ac4fd95909..6fbf936369 100644
--- a/packages/neuron-ui/src/types/App/index.d.ts
+++ b/packages/neuron-ui/src/types/App/index.d.ts
@@ -63,8 +63,8 @@ declare namespace State {
txID: string
outputs: Output[]
price: string
- cycles: string
description: string
+ generatedTx: any | null
}
interface Popup {
diff --git a/packages/neuron-ui/src/types/Controller/index.d.ts b/packages/neuron-ui/src/types/Controller/index.d.ts
index 5f1f5ae489..b7d56a6a98 100644
--- a/packages/neuron-ui/src/types/Controller/index.d.ts
+++ b/packages/neuron-ui/src/types/Controller/index.d.ts
@@ -33,16 +33,21 @@ declare namespace Controller {
}
type SetCurrentWalletParams = string
- interface SendTransaction {
- id: string
+
+ interface SendTransactionParams {
+ walletID: string
+ tx: string
+ password: string
+ description?: string
+ }
+
+ interface GenerateTransactionParams {
walletID: string
items: {
address: string
capacity: string
}[]
- password: string
- fee: string
- description: string
+ feeRate: string
}
interface ComputeCycles {
diff --git a/packages/neuron-ui/src/utils/calculateFee.ts b/packages/neuron-ui/src/utils/calculateFee.ts
new file mode 100644
index 0000000000..e36fa958e5
--- /dev/null
+++ b/packages/neuron-ui/src/utils/calculateFee.ts
@@ -0,0 +1,15 @@
+export default (tx: any) => {
+ if (!tx) {
+ return '0'
+ }
+ const inputCapacities = tx.inputs.reduce(
+ (result: bigint, input: { capacity: string }) => result + BigInt(input.capacity),
+ BigInt(0)
+ )
+ const outputCapacities = tx.outputs.reduce(
+ (result: bigint, output: { capacity: string }) => result + BigInt(output.capacity),
+ BigInt(0)
+ )
+
+ return (inputCapacities - outputCapacities).toString()
+}
diff --git a/packages/neuron-ui/src/utils/formatters.ts b/packages/neuron-ui/src/utils/formatters.ts
index 5b11497609..a39bbc2835 100644
--- a/packages/neuron-ui/src/utils/formatters.ts
+++ b/packages/neuron-ui/src/utils/formatters.ts
@@ -145,14 +145,6 @@ export const uniformTimeFormatter = (time: string | number | Date) => {
return timeFormatter.format(+time).replace(/\//g, '-')
}
-export const priceToFee = (price: string, cycles: string) => {
- if (Number.isNaN(+price)) {
- console.warn(`Price is not a valid number`)
- return `0`
- }
- return (BigInt(price) * BigInt(cycles)).toString()
-}
-
export const addressesToBalance = (addresses: State.Address[] = []) => {
return addresses
.reduce((total, addr) => {
@@ -191,7 +183,6 @@ export default {
shannonToCKBFormatter,
localNumberFormatter,
uniformTimeFormatter,
- priceToFee,
addressesToBalance,
outputsToTotalAmount,
failureResToNotification,
diff --git a/packages/neuron-wallet/.eslintrc.js b/packages/neuron-wallet/.eslintrc.js
index 8eae8dced0..0e675fe66c 100644
--- a/packages/neuron-wallet/.eslintrc.js
+++ b/packages/neuron-wallet/.eslintrc.js
@@ -14,13 +14,14 @@ module.exports = {
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "local",
"args": "after-used",
- "ignoreRestSiblings": false
+ "ignoreRestSiblings": false,
+ "argsIgnorePattern": "^_"
}],
"curly": [2, "all"],
"implicit-arrow-linebreak": "off",
"arrow-parens": [2, "as-needed"],
"max-len": [2, {
- "code": 120,
+ "code": 140,
"ignoreComments": true,
"ignoreTrailingComments": true,
"ignoreUrls": true,
diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json
index 78109fab77..1c2ee19132 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.23.0",
+ "version": "0.23.1",
"private": true,
"author": {
"name": "Nervos Core Dev",
@@ -47,7 +47,7 @@
"rxjs": "6.5.3",
"sha3": "2.0.7",
"sqlite3": "4.1.0",
- "typeorm": "0.2.19",
+ "typeorm": "0.2.20",
"uuid": "3.3.3"
},
"devDependencies": {
@@ -64,7 +64,7 @@
"electron-devtools-installer": "2.2.4",
"electron-notarize": "0.1.1",
"lint-staged": "9.2.5",
- "neuron-ui": "0.23.0",
+ "neuron-ui": "0.23.1",
"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 9638e00c3f..8187715338 100644
--- a/packages/neuron-wallet/src/controllers/api.ts
+++ b/packages/neuron-wallet/src/controllers/api.ts
@@ -10,14 +10,14 @@ import {
SyncInfoController,
SkipDataAndTypeController,
NetworksController
- } from 'controllers'
+} from 'controllers'
import { NetworkType, NetworkID, Network } from 'types/network'
import NetworksService from 'services/networks'
import WalletsService from 'services/wallets'
import SkipDataAndType from 'services/settings/skip-data-and-type'
import { ConnectionStatusSubject } from 'models/subjects/node'
import { SystemScriptSubject } from 'models/subjects/system-script'
-import { CatchControllerError } from 'decorators/errors'
+import { MapApiResponse } from 'decorators'
import { ResponseCode } from 'utils/const'
import { TransactionWithoutHash } from 'types/cell-types'
@@ -27,7 +27,9 @@ import { TransactionWithoutHash } from 'types/cell-types'
*/
export default class ApiController {
// App
- public static loadInitData = async () => {
+
+ @MapApiResponse
+ public static async loadInitData() {
const walletsService = WalletsService.getInstance()
const networksService = NetworksService.getInstance()
const [
@@ -114,69 +116,71 @@ export default class ApiController {
return { status: ResponseCode.Success, result: initState }
}
- public static handleViewError = (error: string) => {
+ @MapApiResponse
+ public static handleViewError(error: string) {
if (env.isDevMode) {
console.error(error)
}
}
+ @MapApiResponse
public static async contextMenu(params: { type: string; id: string }) {
return popContextMenu(params)
}
// Wallets
- @CatchControllerError
+ @MapApiResponse
public static async getAllWallets() {
return WalletsController.getAll()
}
- @CatchControllerError
+ @MapApiResponse
public static async getCurrentWallet() {
return WalletsController.getCurrent()
}
- @CatchControllerError
- public static async importMnemonic(params: { name: string, password: string, mnemonic: string }) {
+ @MapApiResponse
+ public static async importMnemonic(params: { name: string; password: string; mnemonic: string }) {
return WalletsController.importMnemonic(params)
}
- @CatchControllerError
- public static async importKeystore(params: { name: string, password: string, keystorePath: string }) {
+ @MapApiResponse
+ public static async importKeystore(params: { name: string; password: string; keystorePath: string }) {
return WalletsController.importKeystore(params)
}
- @CatchControllerError
- public static async createWallet(params: { name: string, password: string, mnemonic: string }) {
+ @MapApiResponse
+ public static async createWallet(params: { name: string; password: string; mnemonic: string }) {
return WalletsController.create(params)
}
- @CatchControllerError
- public static async updateWallet(params: { id: string, password: string, name: string, newPassword?: string }) {
- WalletsController.update(params)
+ @MapApiResponse
+ public static async updateWallet(params: { id: string; password: string; name: string; newPassword?: string }) {
+ return WalletsController.update(params)
}
- @CatchControllerError
+ @MapApiResponse
public static async deleteWallet({ id = '', password = '' }) {
return WalletsController.delete({ id, password })
}
- @CatchControllerError
+ @MapApiResponse
public static async backupWallet({ id = '', password = '' }) {
return WalletsController.backup({ id, password })
}
- @CatchControllerError
+ @MapApiResponse
public static async setCurrentWallet(id: string) {
return WalletsController.activate(id)
}
- @CatchControllerError
+ @MapApiResponse
public static async getAddressesByWalletID(id: string) {
return WalletsController.getAllAddresses(id)
}
- @CatchControllerError
+ @MapApiResponse
public static async sendCapacity(params: {
id: string
walletID: string
@@ -191,20 +195,18 @@ export default class ApiController {
return WalletsController.sendCapacity(params)
}
- @CatchControllerError
+ @MapApiResponse
public static async sendTx(params: {
- id: string
walletID: string
- tx: TransactionWithoutHash,
+ tx: TransactionWithoutHash
password: string
description?: string
}) {
return WalletsController.sendTx(params)
}
- @CatchControllerError
+ @MapApiResponse
public static async generateTx(params: {
- id: string
walletID: string
items: {
address: string
@@ -216,20 +218,12 @@ export default class ApiController {
return WalletsController.generateTx(params)
}
- @CatchControllerError
- public static async calculateFee(params: {
- id: string
- tx: TransactionWithoutHash
- }) {
- return WalletsController.calculateFee(params)
- }
-
- @CatchControllerError
+ @MapApiResponse
public static async computeCycles(params: { walletID: string; capacities: string }) {
return WalletsController.computeCycles(params)
}
- @CatchControllerError
+ @MapApiResponse
public static async updateAddressDescription(params: {
walletID: string
address: string
@@ -240,46 +234,46 @@ export default class ApiController {
// Networks
- @CatchControllerError
+ @MapApiResponse
public static async getAllNetworks() {
return NetworksController.getAll()
}
- @CatchControllerError
+ @MapApiResponse
public static async createNetwork({ name, remote, type = NetworkType.Normal, chain = 'ckb' }: Network) {
return NetworksController.create({ name, remote, type, chain })
}
- @CatchControllerError
+ @MapApiResponse
public static async updateNetwork(id: NetworkID, options: Partial) {
return NetworksController.update(id, options)
}
- @CatchControllerError
+ @MapApiResponse
public static async getCurrentNetworkID() {
return NetworksController.currentID()
}
- @CatchControllerError
+ @MapApiResponse
public static async setCurrentNetowrk(id: NetworkID) {
return NetworksController.activate(id)
}
// Transactions
- @CatchControllerError
+ @MapApiResponse
public static async getTransactionList(
params: Controller.Params.TransactionsByKeywords,
) {
return TransactionsController.getAllByKeywords(params)
}
- @CatchControllerError
+ @MapApiResponse
public static async getTransaction(walletID: string, hash: string) {
return TransactionsController.get(walletID, hash)
}
- @CatchControllerError
+ @MapApiResponse
public static async updateTransactionDescription(params: { hash: string; description: string }) {
return TransactionsController.updateDescription(params)
}
@@ -290,7 +284,7 @@ export default class ApiController {
// Misc
- @CatchControllerError
+ @MapApiResponse
public static async updateSkipDataAndType(skip: boolean) {
return SkipDataAndTypeController.update(skip)
}
diff --git a/packages/neuron-wallet/src/controllers/networks.ts b/packages/neuron-wallet/src/controllers/networks.ts
index 4e0c718de0..a7bc506784 100644
--- a/packages/neuron-wallet/src/controllers/networks.ts
+++ b/packages/neuron-wallet/src/controllers/networks.ts
@@ -1,13 +1,11 @@
import { NetworkType, NetworkID, Network } from 'types/network'
import NetworksService from 'services/networks'
-import { CatchControllerError } from 'decorators'
import { ResponseCode } from 'utils/const'
import { IsRequired, InvalidName, NetworkNotFound, CurrentNetworkNotSet } from 'exceptions'
const networksService = NetworksService.getInstance()
export default class NetworksController {
- @CatchControllerError
public static async getAll() {
const networks = await networksService.getAll()
return {
@@ -16,7 +14,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async get(id: NetworkID) {
if (typeof id === 'undefined') {
throw new IsRequired('ID')
@@ -33,7 +30,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async create({ name, remote, type = NetworkType.Normal }: Network) {
if (!name || !remote) {
throw new IsRequired('Name and address')
@@ -49,7 +45,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async update(id: NetworkID, options: Partial) {
if (options.name && options.name === 'error') {
throw new InvalidName('Network')
@@ -62,7 +57,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async delete(id: NetworkID) {
await networksService.delete(id)
@@ -72,7 +66,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async currentID() {
const currentID = await networksService.getCurrentID()
if (currentID) {
@@ -84,7 +77,6 @@ export default class NetworksController {
throw new CurrentNetworkNotSet()
}
- @CatchControllerError
public static async activate(id: NetworkID) {
await networksService.activate(id)
return {
@@ -93,7 +85,6 @@ export default class NetworksController {
}
}
- @CatchControllerError
public static async clear() {
await networksService.clear()
return {
diff --git a/packages/neuron-wallet/src/controllers/skip-data-and-type.ts b/packages/neuron-wallet/src/controllers/skip-data-and-type.ts
index 5357dc450d..9b88d1d19f 100644
--- a/packages/neuron-wallet/src/controllers/skip-data-and-type.ts
+++ b/packages/neuron-wallet/src/controllers/skip-data-and-type.ts
@@ -1,9 +1,7 @@
-import { CatchControllerError } from 'decorators/errors'
import { ResponseCode } from 'utils/const'
import SkipDataAndType from 'services/settings/skip-data-and-type'
export default class SkipDataAndTypeController {
- @CatchControllerError
public static async update(skip: boolean): Promise> {
SkipDataAndType.getInstance().update(skip)
@@ -13,7 +11,6 @@ export default class SkipDataAndTypeController {
}
}
- @CatchControllerError
public static async get(): Promise> {
const skip = SkipDataAndType.getInstance().get()
diff --git a/packages/neuron-wallet/src/controllers/sync-info.ts b/packages/neuron-wallet/src/controllers/sync-info.ts
index fc94e804b2..786380441e 100644
--- a/packages/neuron-wallet/src/controllers/sync-info.ts
+++ b/packages/neuron-wallet/src/controllers/sync-info.ts
@@ -1,9 +1,7 @@
-import { CatchControllerError } from 'decorators'
import BlockNumber from 'services/sync/block-number'
import { ResponseCode } from 'utils/const'
export default class SyncInfoController {
- @CatchControllerError
public static async currentBlockNumber() {
const blockNumber = new BlockNumber()
const current: bigint = await blockNumber.getCurrent()
diff --git a/packages/neuron-wallet/src/controllers/transactions.ts b/packages/neuron-wallet/src/controllers/transactions.ts
index 3781bc94fb..b2e1a0a18c 100644
--- a/packages/neuron-wallet/src/controllers/transactions.ts
+++ b/packages/neuron-wallet/src/controllers/transactions.ts
@@ -4,7 +4,6 @@ import { TransactionsService, PaginationResult, TransactionsByLockHashesParam }
import AddressesService from 'services/addresses'
import WalletsService from 'services/wallets'
-import { CatchControllerError } from 'decorators'
import { ResponseCode } from 'utils/const'
import { TransactionNotFound, CurrentWalletNotSet, ServiceHasNoResponse } from 'exceptions'
import LockUtils from 'models/lock-utils'
@@ -12,7 +11,6 @@ import LockUtils from 'models/lock-utils'
const CELL_COUNT_THRESHOLD = 10
export default class TransactionsController {
- @CatchControllerError
public static async getAll(
params: TransactionsByLockHashesParam,
): Promise>> {
@@ -28,7 +26,6 @@ export default class TransactionsController {
}
}
- @CatchControllerError
public static async getAllByKeywords(
params: Controller.Params.TransactionsByKeywords,
): Promise & Controller.Params.TransactionsByKeywords>> {
@@ -52,7 +49,6 @@ export default class TransactionsController {
}
}
- @CatchControllerError
public static async getAllByAddresses(
params: Controller.Params.TransactionsByAddresses,
): Promise & Controller.Params.TransactionsByAddresses>> {
@@ -82,7 +78,6 @@ export default class TransactionsController {
}
}
- @CatchControllerError
public static async get(
walletID: string,
hash: string,
@@ -132,7 +127,6 @@ export default class TransactionsController {
}
}
- @CatchControllerError
public static async updateDescription({ hash, description }: { hash: string; description: string }) {
await TransactionsService.updateDescription(hash, description)
diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts
index eacaa5d865..f194b7ec31 100644
--- a/packages/neuron-wallet/src/controllers/wallets.ts
+++ b/packages/neuron-wallet/src/controllers/wallets.ts
@@ -5,7 +5,6 @@ import Keystore from 'models/keys/keystore'
import Keychain from 'models/keys/keychain'
import { validateMnemonic, mnemonicToSeedSync } from 'models/keys/mnemonic'
import { AccountExtendedPublicKey, ExtendedPrivateKey } from 'models/keys/key'
-import { CatchControllerError } from 'decorators'
import { ResponseCode } from 'utils/const'
import {
CurrentWalletNotSet,
@@ -20,11 +19,9 @@ import {
import i18n from 'utils/i18n'
import AddressService from 'services/addresses'
import WalletCreatedSubject from 'models/subjects/wallet-created-subject'
-import logger from 'utils/logger'
-import { TransactionWithoutHash } from 'types/cell-types';
+import { TransactionWithoutHash } from 'types/cell-types'
export default class WalletsController {
- @CatchControllerError
public static async getAll(): Promise[]>> {
const walletsService = WalletsService.getInstance()
const wallets = walletsService.getAll()
@@ -53,7 +50,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async get(id: string): Promise> {
const walletsService = WalletsService.getInstance()
if (typeof id === 'undefined') {
@@ -70,7 +66,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async importMnemonic({
name,
password,
@@ -92,7 +87,6 @@ export default class WalletsController {
return result
}
- @CatchControllerError
public static async create({
name,
password,
@@ -165,7 +159,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async importKeystore({
name,
password,
@@ -193,7 +186,7 @@ export default class WalletsController {
const accountKeychain = masterKeychain.derivePath(AccountExtendedPublicKey.ckbAccountPath)
const accountExtendedPublicKey = new AccountExtendedPublicKey(
accountKeychain.publicKey.toString('hex'),
- accountKeychain.chainCode.toString('hex')
+ accountKeychain.chainCode.toString('hex'),
)
const walletsService = WalletsService.getInstance()
@@ -214,7 +207,7 @@ export default class WalletsController {
}
// TODO: update addresses?
- @CatchControllerError
+
public static async update({
id,
name,
@@ -249,7 +242,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async delete({
id = '',
password = '',
@@ -268,7 +260,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async backup({
id = '',
password = '',
@@ -291,12 +282,10 @@ export default class WalletsController {
result: true,
})
}
- }
- )
+ })
})
}
- @CatchControllerError
public static async getCurrent() {
const currentWallet = WalletsService.getInstance().getCurrent() || null
return {
@@ -305,7 +294,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async activate(id: string) {
const walletsService = WalletsService.getInstance()
walletsService.setCurrent(id)
@@ -319,7 +307,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async getAllAddresses(id: string) {
const addresses = await AddressService.allAddressesByWalletId(id).then(addrs =>
addrs.map(
@@ -348,7 +335,6 @@ export default class WalletsController {
}
}
- @CatchControllerError
public static async sendCapacity(params: {
id: string
walletID: string
@@ -368,32 +354,22 @@ export default class WalletsController {
if (!params.fee || params.fee === '0') {
feeRate = '1000'
}
- try {
- const walletsService = WalletsService.getInstance()
- const hash = await walletsService.sendCapacity(
- params.walletID,
- params.items,
- params.password,
- params.fee,
- feeRate,
- params.description
- )
- return {
- status: ResponseCode.Success,
- result: hash,
- }
- } catch (err) {
- logger.error(`sendCapacity:`, err)
- return {
- status: err.code || ResponseCode.Fail,
- message: `Error: "${err.message}"`,
- }
+ const walletsService = WalletsService.getInstance()
+ const hash = await walletsService.sendCapacity(
+ params.walletID,
+ params.items,
+ params.password,
+ params.fee,
+ feeRate,
+ params.description
+ )
+ return {
+ status: ResponseCode.Success,
+ result: hash,
}
}
- @CatchControllerError
public static async sendTx(params: {
- id: string
walletID: string
tx: TransactionWithoutHash
password: string
@@ -402,30 +378,20 @@ export default class WalletsController {
if (!params) {
throw new IsRequired('Parameters')
}
- try {
- const walletsService = WalletsService.getInstance()
- const hash = await walletsService.sendTx(
- params.walletID,
- params.tx,
- params.password,
- params.description
- )
- return {
- status: ResponseCode.Success,
- result: hash,
- }
- } catch (err) {
- logger.error(`sendTx:`, err)
- return {
- status: err.code || ResponseCode.Fail,
- message: `Error: "${err.message}"`,
- }
+ const walletsService = WalletsService.getInstance()
+ const hash = await walletsService.sendTx(
+ params.walletID,
+ params.tx,
+ params.password,
+ params.description
+ )
+ return {
+ status: ResponseCode.Success,
+ result: hash,
}
}
- @CatchControllerError
public static async generateTx(params: {
- id: string
walletID: string
items: {
address: string
@@ -437,72 +403,31 @@ export default class WalletsController {
if (!params) {
throw new IsRequired('Parameters')
}
- try {
- const walletsService = WalletsService.getInstance()
- const tx = await walletsService.generateTx(
- params.walletID,
- params.items,
- params.fee,
- params.feeRate,
- )
- return {
- status: ResponseCode.Success,
- result: tx,
- }
- } catch (err) {
- logger.error(`generateTx:`, err)
- return {
- status: err.code || ResponseCode.Fail,
- message: `Error: "${err.message}"`,
- }
- }
- }
-
- @CatchControllerError
- public static async calculateFee(params: {
- id: string
- tx: TransactionWithoutHash
- }) {
- if (!params) {
- throw new IsRequired('Parameters')
- }
- try {
- const walletsService = WalletsService.getInstance()
- const fee = await walletsService.calculateFee(params.tx)
- return {
- status: ResponseCode.Success,
- result: fee,
- }
- } catch (err) {
- logger.error(`calculateFee:`, err)
- return {
- status: err.code || ResponseCode.Fail,
- message: `Error: "${err.message}"`,
- }
+ const walletsService = WalletsService.getInstance()
+ const tx = await walletsService.generateTx(
+ params.walletID,
+ params.items,
+ params.fee,
+ params.feeRate,
+ )
+ return {
+ status: ResponseCode.Success,
+ result: tx,
}
}
- @CatchControllerError
public static async computeCycles(params: { walletID: string; capacities: string }) {
if (!params) {
throw new IsRequired('Parameters')
}
- try {
- const walletsService = WalletsService.getInstance()
- const cycles = await walletsService.computeCycles(params.walletID, params.capacities)
- return {
- status: ResponseCode.Success,
- result: cycles,
- }
- } catch (err) {
- return {
- status: ResponseCode.Fail,
- message: `Error: "${err.message}"`,
- }
+ const walletsService = WalletsService.getInstance()
+ const cycles = await walletsService.computeCycles(params.walletID, params.capacities)
+ return {
+ status: ResponseCode.Success,
+ result: cycles,
}
}
- @CatchControllerError
public static async updateAddressDescription({
walletID,
address,
diff --git a/packages/neuron-wallet/src/database/chain/entities/input.ts b/packages/neuron-wallet/src/database/chain/entities/input.ts
index b72bb12f30..4c4fb018c4 100644
--- a/packages/neuron-wallet/src/database/chain/entities/input.ts
+++ b/packages/neuron-wallet/src/database/chain/entities/input.ts
@@ -2,7 +2,6 @@ import { Entity, BaseEntity, Column, ManyToOne, PrimaryGeneratedColumn } from 't
import { OutPoint, Input as InputInterface, Script } from 'types/cell-types'
import Transaction from './transaction'
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
// cellbase input may have same OutPoint
@Entity()
export default class Input extends BaseEntity {
diff --git a/packages/neuron-wallet/src/database/chain/entities/output.ts b/packages/neuron-wallet/src/database/chain/entities/output.ts
index 8ec0559ebd..33a39688ff 100644
--- a/packages/neuron-wallet/src/database/chain/entities/output.ts
+++ b/packages/neuron-wallet/src/database/chain/entities/output.ts
@@ -2,7 +2,6 @@ import { Entity, BaseEntity, Column, PrimaryColumn, ManyToOne } from 'typeorm'
import { Script, OutPoint, Cell } from 'types/cell-types'
import TransactionEntity from './transaction'
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
@Entity()
export default class Output extends BaseEntity {
@PrimaryColumn({
diff --git a/packages/neuron-wallet/src/database/chain/entities/transaction.ts b/packages/neuron-wallet/src/database/chain/entities/transaction.ts
index 3cbcae9063..3ec73f0077 100644
--- a/packages/neuron-wallet/src/database/chain/entities/transaction.ts
+++ b/packages/neuron-wallet/src/database/chain/entities/transaction.ts
@@ -21,7 +21,6 @@ const txDbChangedSubject = isRenderer
? remote.require('./models/subjects/tx-db-changed-subject').default.getSubject()
: TxDbChangedSubject.getSubject()
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
@Entity()
export default class Transaction extends BaseEntity {
@PrimaryColumn({
@@ -125,6 +124,9 @@ export default class Transaction extends BaseEntity {
updateCreatedAt() {
this.createdAt = Date.now().toString()
this.updatedAt = this.createdAt
+ if (!this.timestamp) {
+ this.timestamp = this.createdAt
+ }
}
@BeforeUpdate()
diff --git a/packages/neuron-wallet/src/database/chain/migrations/1572006450765-AddIndices.ts b/packages/neuron-wallet/src/database/chain/migrations/1572006450765-AddIndices.ts
new file mode 100644
index 0000000000..7c6b4ba054
--- /dev/null
+++ b/packages/neuron-wallet/src/database/chain/migrations/1572006450765-AddIndices.ts
@@ -0,0 +1,17 @@
+import {MigrationInterface, QueryRunner, TableIndex} from "typeorm";
+
+export class AddIndices1572006450765 implements MigrationInterface {
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.createIndex("input", new TableIndex({ columnNames: ["transactionHash", "lockHash"] }))
+ await queryRunner.createIndex("output", new TableIndex({ columnNames: ["transactionHash", "lockHash"] }))
+ await queryRunner.createIndex("transaction", new TableIndex({ columnNames: ["status"] }))
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.dropIndex("input", new TableIndex({ columnNames: ["transactionHash", "lockHash"] }))
+ await queryRunner.dropIndex("output", new TableIndex({ columnNames: ["transactionHash", "lockHash"] }))
+ await queryRunner.dropIndex("transaction", new TableIndex({ columnNames: ["status"] }))
+ }
+
+}
diff --git a/packages/neuron-wallet/src/database/chain/migrations/1572137226866-AddIndexToTxTimestamp.ts b/packages/neuron-wallet/src/database/chain/migrations/1572137226866-AddIndexToTxTimestamp.ts
new file mode 100644
index 0000000000..4d9e78704b
--- /dev/null
+++ b/packages/neuron-wallet/src/database/chain/migrations/1572137226866-AddIndexToTxTimestamp.ts
@@ -0,0 +1,13 @@
+import {MigrationInterface, QueryRunner, TableIndex} from "typeorm";
+
+export class AddIndexToTxTimestamp1572137226866 implements MigrationInterface {
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.createIndex("transaction", new TableIndex({ columnNames: ["timestamp"] }))
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.dropIndex("transaction", new TableIndex({ columnNames: ["timestamp"] }))
+ }
+
+}
diff --git a/packages/neuron-wallet/src/database/chain/migrations/1572226722928-AddOutputIndex.ts b/packages/neuron-wallet/src/database/chain/migrations/1572226722928-AddOutputIndex.ts
new file mode 100644
index 0000000000..1efc10a913
--- /dev/null
+++ b/packages/neuron-wallet/src/database/chain/migrations/1572226722928-AddOutputIndex.ts
@@ -0,0 +1,13 @@
+import {MigrationInterface, QueryRunner, TableIndex} from "typeorm";
+
+export class AddOutputIndex1572226722928 implements MigrationInterface {
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.createIndex("output", new TableIndex({ columnNames: ["lockHash", "status", "hasData", "typeScript"] }))
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.dropIndex("output", new TableIndex({ columnNames: ["lockHash", "status", "hasData", "typeScript"] }))
+ }
+
+}
diff --git a/packages/neuron-wallet/src/database/chain/ormconfig.ts b/packages/neuron-wallet/src/database/chain/ormconfig.ts
index d71471384b..75b405fe6e 100644
--- a/packages/neuron-wallet/src/database/chain/ormconfig.ts
+++ b/packages/neuron-wallet/src/database/chain/ormconfig.ts
@@ -13,6 +13,9 @@ import { InitMigration1566959757554 } from './migrations/1566959757554-InitMigra
import { AddTypeAndHasData1567144517514 } from './migrations/1567144517514-AddTypeAndHasData'
import { ChangeHasDataDefault1568621556467 } from './migrations/1568621556467-ChangeHasDataDefault'
import { AddLockToInput1570522869590 } from './migrations/1570522869590-AddLockToInput'
+import { AddIndices1572006450765 } from './migrations/1572006450765-AddIndices'
+import { AddIndexToTxTimestamp1572137226866 } from './migrations/1572137226866-AddIndexToTxTimestamp'
+import { AddOutputIndex1572226722928 } from './migrations/1572226722928-AddOutputIndex'
export const CONNECTION_NOT_FOUND_NAME = 'ConnectionNotFoundError'
@@ -26,7 +29,7 @@ const connectOptions = async (genesisBlockHash: string): Promise {
- await getConnection().manager.query(`PRAGMA busy_timeout = 3000;`)
-}
-
export const initConnection = async (genesisBlockHash: string) => {
// try to close connection, if not exist, will throw ConnectionNotFoundError when call getConnection()
try {
@@ -58,7 +61,8 @@ export const initConnection = async (genesisBlockHash: string) => {
try {
await createConnection(connectionOptions)
- await setBusyTimeout()
+ await getConnection().manager.query(`PRAGMA busy_timeout = 3000;`)
+ await getConnection().manager.query(`PRAGMA temp_store = MEMORY;`)
} catch (err) {
logger.error(err.message)
}
diff --git a/packages/neuron-wallet/src/decorators/index.ts b/packages/neuron-wallet/src/decorators/index.ts
index 55b5deea58..3581bbe329 100644
--- a/packages/neuron-wallet/src/decorators/index.ts
+++ b/packages/neuron-wallet/src/decorators/index.ts
@@ -1,10 +1,10 @@
-import errorDecorators from './errors'
+import mappers from './mappers'
import validatorDecorators from './validators'
-export const { CatchControllerError } = errorDecorators
+export const { MapApiResponse } = mappers
export const { Validate, Password, Required } = validatorDecorators
export default {
- ...errorDecorators,
+ ...mappers,
...validatorDecorators,
}
diff --git a/packages/neuron-wallet/src/decorators/errors.ts b/packages/neuron-wallet/src/decorators/mappers.ts
similarity index 56%
rename from packages/neuron-wallet/src/decorators/errors.ts
rename to packages/neuron-wallet/src/decorators/mappers.ts
index d61af6c823..8907e5dc63 100644
--- a/packages/neuron-wallet/src/decorators/errors.ts
+++ b/packages/neuron-wallet/src/decorators/mappers.ts
@@ -3,27 +3,27 @@ import logger from 'utils/logger'
const NODE_DISCONNECTED_CODE = 104
-export const CatchControllerError = (_target: any, _name: string, descriptor: PropertyDescriptor) => {
+export const MapApiResponse = (target: any, name: string, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value
return {
...descriptor,
- async value(...args: any[]) {
+ async value(...args: any[]): Promise {
try {
- return await originalMethod(...args)
+ const res = await originalMethod(...args)
+ return JSON.stringify(res)
} catch (err) {
- logger.error(`CatchControllerError:`, err)
+ logger.error(`${target.name}.${name}:`, err)
if (err.code === 'ECONNREFUSED') {
err.code = NODE_DISCONNECTED_CODE
}
- return {
+ const res = {
status: err.code || ResponseCode.Fail,
message: typeof err.message === 'string' ? { content: err.message } : err.message,
}
+ return JSON.stringify(res)
}
},
}
}
-export default {
- CatchControllerError,
-}
+export default { MapApiResponse }
diff --git a/packages/neuron-wallet/src/listeners/tx-status.ts b/packages/neuron-wallet/src/listeners/tx-status.ts
index 3f9be3f9e8..b33499320d 100644
--- a/packages/neuron-wallet/src/listeners/tx-status.ts
+++ b/packages/neuron-wallet/src/listeners/tx-status.ts
@@ -36,8 +36,6 @@ const getTransactionStatus = async (hash: string) => {
}
}
-/* eslint no-await-in-loop: "off" */
-/* eslint no-restricted-syntax: "off" */
const trackingStatus = async () => {
const pendingTransactions = await FailedTransaction.pendings()
if (!pendingTransactions.length) {
diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts
index 552d8472ae..717d88b50d 100644
--- a/packages/neuron-wallet/src/services/addresses.ts
+++ b/packages/neuron-wallet/src/services/addresses.ts
@@ -95,8 +95,6 @@ export default class AddressService {
)
}
- /* eslint no-await-in-loop: "off" */
- /* eslint no-restricted-syntax: "off" */
public static updateTxCountAndBalances = async (
addresses: string[],
url: string = NodeService.getInstance().core.rpc.node.url
diff --git a/packages/neuron-wallet/src/services/cells.ts b/packages/neuron-wallet/src/services/cells.ts
index 28ad494d26..c8db467daa 100644
--- a/packages/neuron-wallet/src/services/cells.ts
+++ b/packages/neuron-wallet/src/services/cells.ts
@@ -7,9 +7,6 @@ import SkipDataAndType from './settings/skip-data-and-type'
export const MIN_CELL_CAPACITY = '6100000000'
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
-/* eslint no-await-in-loop: "warn" */
-/* eslint no-restricted-syntax: "warn" */
export default class CellsService {
// exclude hasData = true and typeScript != null
public static getBalance = async (
@@ -31,9 +28,16 @@ export default class CellsService {
const cells: OutputEntity[] = await getConnection()
.getRepository(OutputEntity)
- .find({
- where: queryParams,
- })
+ .createQueryBuilder('output')
+ .select([
+ "output.lockHash",
+ "output.status",
+ "output.hasData",
+ "output.typeScript",
+ "output.capacity"
+ ])
+ .where(queryParams)
+ .getMany()
const capacity: bigint = cells.map(c => BigInt(c.capacity)).reduce((result, c) => result + c, BigInt(0))
diff --git a/packages/neuron-wallet/src/services/indexer/indexer-rpc.ts b/packages/neuron-wallet/src/services/indexer/indexer-rpc.ts
index be389a51cd..2abcc574b9 100644
--- a/packages/neuron-wallet/src/services/indexer/indexer-rpc.ts
+++ b/packages/neuron-wallet/src/services/indexer/indexer-rpc.ts
@@ -16,27 +16,15 @@ export default class IndexerRPC {
return this.core.rpc.indexLockHash(lockHash, indexFrom)
}
- public getTransactionByLockHash = async (
- lockHash: string,
- page: string,
- per: string,
- reverseOrder: boolean = false
- ) => {
- const result = await this.core.rpc.getTransactionsByLockHash(lockHash, page, per, reverseOrder)
- return result
+ public getTransactionsByLockHash = async (lockHash: string, page: string, per: string, reverseOrder: boolean = false) => {
+ return await this.core.rpc.getTransactionsByLockHash(lockHash, page, per, reverseOrder)
}
public getLockHashIndexStates = async () => {
return this.core.rpc.getLockHashIndexStates()
}
- public getLiveCellsByLockHash = async (
- lockHash: string,
- page: string,
- per: string,
- reverseOrder: boolean = false
- ) => {
- const result = await this.core.rpc.getLiveCellsByLockHash(lockHash, page, per, reverseOrder)
- return result
+ public getLiveCellsByLockHash = async (lockHash: string, page: string, per: string, reverseOrder: boolean = false) => {
+ return await this.core.rpc.getLiveCellsByLockHash(lockHash, page, per, reverseOrder)
}
}
diff --git a/packages/neuron-wallet/src/services/indexer/queue.ts b/packages/neuron-wallet/src/services/indexer/queue.ts
index cbd0487059..6391300c77 100644
--- a/packages/neuron-wallet/src/services/indexer/queue.ts
+++ b/packages/neuron-wallet/src/services/indexer/queue.ts
@@ -26,7 +26,6 @@ enum TxPointType {
}
export default class IndexerQueue {
- // private lockHashes: string[]
private lockHashInfos: LockHashInfo[]
private indexerRPC: IndexerRPC
private getBlocksService: GetBlocks
@@ -48,7 +47,6 @@ export default class IndexerQueue {
private url: string
constructor(url: string, lockHashInfos: LockHashInfo[], tipNumberSubject: Subject) {
- // this.lockHashes = lockHashes
this.lockHashInfos = lockHashInfos
this.url = url
this.indexerRPC = new IndexerRPC(url)
@@ -62,7 +60,6 @@ export default class IndexerQueue {
}
public setLockHashInfos = (lockHashInfos: LockHashInfo[]): void => {
- // this.lockHashes = lockHashes
this.lockHashInfos = lockHashInfos
this.indexed = false
}
@@ -76,8 +73,6 @@ export default class IndexerQueue {
this.resetFlag = true
}
- /* eslint no-await-in-loop: "off" */
- /* eslint no-restricted-syntax: "off" */
public start = async () => {
while (!this.stopped) {
try {
@@ -148,8 +143,7 @@ export default class IndexerQueue {
.map(state => HexUtils.toDecimal(state.blockNumber))
const uniqueBlockNumbers = [...new Set(blockNumbers)]
const blockNumbersBigInt = uniqueBlockNumbers.map(num => BigInt(num))
- const minBlockNumber = Utils.min(blockNumbersBigInt)
- return minBlockNumber
+ return Utils.min(blockNumbersBigInt)
}
public indexLockHashes = async (lockHashInfos: LockHashInfo[]) => {
@@ -168,10 +162,12 @@ export default class IndexerQueue {
let page = 0
let stopped = false
while (!stopped) {
- const txs = await this.indexerRPC.getTransactionByLockHash(lockHash, `0x${page.toString(16)}`, `0x${this.per.toString(16)}`)
+ const txs = await this.indexerRPC.getTransactionsByLockHash(lockHash, `0x${page.toString(16)}`, `0x${this.per.toString(16)}`)
if (txs.length < this.per) {
stopped = true
}
+ logger.debug(`indexer txs for: ${type} ${lockHash}, page: ${page}, tx count: ${txs.length}`)
+
for (const tx of txs) {
let txPoint: CKBComponents.TransactionPoint | null = null
if (type === TxPointType.CreatedBy) {
@@ -197,11 +193,9 @@ export default class IndexerQueue {
addresses: [address],
url: this.url,
})
- return
+ continue
}
- logger.debug('indexer fetched tx:', type, txPoint.txHash)
-
// tx timestamp / blockNumber / blockHash
let txEntity: TransactionEntity | undefined = await TransactionPersistor.get(transaction.hash)
if (!txEntity || !txEntity.blockHash) {
diff --git a/packages/neuron-wallet/src/services/sync/block-listener.ts b/packages/neuron-wallet/src/services/sync/block-listener.ts
index 92932aa024..e509503e56 100644
--- a/packages/neuron-wallet/src/services/sync/block-listener.ts
+++ b/packages/neuron-wallet/src/services/sync/block-listener.ts
@@ -77,8 +77,6 @@ export default class BlockListener {
})
}
- /* eslint no-await-in-loop: "off" */
- /* eslint no-restricted-syntax: "off" */
public setToTip = async () => {
const timeout = 5000
let number: bigint = BigInt(0)
diff --git a/packages/neuron-wallet/src/services/sync/check-and-save/output.ts b/packages/neuron-wallet/src/services/sync/check-and-save/output.ts
index 04c49684ce..7537f83dd1 100644
--- a/packages/neuron-wallet/src/services/sync/check-and-save/output.ts
+++ b/packages/neuron-wallet/src/services/sync/check-and-save/output.ts
@@ -18,7 +18,7 @@ export default class CheckOutput {
return this.output
}
- public checkLockHash = async (lockHashList: string[]): Promise => {
+ public checkLockHash = (lockHashList: string[]): boolean => {
return lockHashList.includes(this.output.lockHash!)
}
}
diff --git a/packages/neuron-wallet/src/services/sync/check-and-save/tx.ts b/packages/neuron-wallet/src/services/sync/check-and-save/tx.ts
index 537f236017..98a9b832f5 100644
--- a/packages/neuron-wallet/src/services/sync/check-and-save/tx.ts
+++ b/packages/neuron-wallet/src/services/sync/check-and-save/tx.ts
@@ -25,7 +25,7 @@ export default class CheckTx {
}
public check = async (lockHashes: string[]): Promise => {
- const outputs: Cell[] = await this.filterOutputs(lockHashes)
+ const outputs: Cell[] = this.filterOutputs(lockHashes)
const inputAddresses = await this.filterInputs(lockHashes)
const outputAddresses: string[] = outputs.map(output => {
@@ -50,22 +50,18 @@ export default class CheckTx {
return false
}
- public filterOutputs = async (lockHashes: string[]) => {
- const cells: Cell[] = (await Promise.all(
- this.tx.outputs!.map(async output => {
- const checkOutput = new CheckOutput(output)
- const result = await checkOutput.checkLockHash(lockHashes)
- if (result) {
- return output
- }
- return false
- })
- )).filter(cell => !!cell) as Cell[]
+ public filterOutputs = (lockHashes: string[]) => {
+ const cells: Cell[] = this.tx.outputs!.map(output => {
+ const checkOutput = new CheckOutput(output)
+ const result = checkOutput.checkLockHash(lockHashes)
+ if (result) {
+ return output
+ }
+ return false
+ }).filter(cell => !!cell) as Cell[]
return cells
}
- /* eslint no-await-in-loop: "off" */
- /* eslint no-restricted-syntax: "warn" */
public filterInputs = async (lockHashes: string[]): Promise => {
const inputs = this.tx.inputs!
diff --git a/packages/neuron-wallet/src/services/sync/get-blocks.ts b/packages/neuron-wallet/src/services/sync/get-blocks.ts
index cc162cc3f4..9fa65b663f 100644
--- a/packages/neuron-wallet/src/services/sync/get-blocks.ts
+++ b/packages/neuron-wallet/src/services/sync/get-blocks.ts
@@ -9,6 +9,7 @@ import CheckTx from 'services/sync/check-and-save/tx'
import { TransactionPersistor } from 'services/tx'
import LockUtils from 'models/lock-utils'
import { addressesUsedSubject } from './renderer-params'
+import logger from 'utils/logger'
export default class GetBlocks {
private retryTime: number
@@ -34,18 +35,24 @@ export default class GetBlocks {
}
public getTipBlockNumber = async (): Promise => {
- const tip: string = await this.core.rpc.getTipBlockNumber()
- return tip
+ return this.core.rpc.getTipBlockNumber()
}
public checkAndSave = async (blocks: Block[], lockHashes: string[]): Promise => {
+ const cachedPreviousTxs = new Map()
for (const block of blocks) {
+ logger.debug(`checking block #${block.header.number}, ${block.transactions.length} txs`)
for (const tx of block.transactions) {
const checkTx = new CheckTx(tx, this.url)
const addresses = await checkTx.check(lockHashes)
if (addresses.length > 0) {
for (const input of tx.inputs!) {
- const previousTxWithStatus = await this.getTransaction(input.previousOutput!.txHash)
+ const previousTxHash = input.previousOutput!.txHash
+ let previousTxWithStatus = cachedPreviousTxs.get(previousTxHash)
+ if (!previousTxWithStatus) {
+ previousTxWithStatus = await this.getTransaction(previousTxHash)
+ cachedPreviousTxs.set(previousTxHash, previousTxWithStatus)
+ }
const previousTx = TypeConvert.toTransaction(previousTxWithStatus.transaction)
const previousOutput = previousTx.outputs![+input.previousOutput!.index]
input.lock = previousOutput.lock
@@ -60,20 +67,19 @@ export default class GetBlocks {
}
}
}
+ cachedPreviousTxs.clear()
}
public retryGetBlock = async (num: string): Promise => {
const block: Block = await Utils.retry(this.retryTime, this.retryInterval, async () => {
- const b: Block = await this.getBlockByNumber(num)
- return b
+ return await this.getBlockByNumber(num)
})
return block
}
public getTransaction = async (hash: string): Promise => {
- const tx = await this.core.rpc.getTransaction(hash)
- return tx
+ return await this.core.rpc.getTransaction(hash)
}
public getHeader = async (hash: string): Promise => {
@@ -88,8 +94,7 @@ export default class GetBlocks {
public genesisBlockHash = async (): Promise => {
const hash: string = await Utils.retry(3, 100, async () => {
- const h: string = await this.core.rpc.getBlockHash('0x0')
- return h
+ return await this.core.rpc.getBlockHash('0x0')
})
return hash
diff --git a/packages/neuron-wallet/src/services/sync/queue.ts b/packages/neuron-wallet/src/services/sync/queue.ts
index 68dd417d24..526daf6f65 100644
--- a/packages/neuron-wallet/src/services/sync/queue.ts
+++ b/packages/neuron-wallet/src/services/sync/queue.ts
@@ -46,7 +46,6 @@ export default class Queue {
this.lockHashes = lockHashes
}
- /* eslint no-await-in-loop: "off" */
public start = async () => {
while (!this.stopped) {
try {
@@ -136,7 +135,7 @@ export default class Queue {
const range = await this.rangeForCheck.getRange()
const rangeFirstBlockHeader: BlockHeader = range[0]
await this.currentBlockNumber.updateCurrent(BigInt(rangeFirstBlockHeader.number))
- await this.rangeForCheck.clearRange()
+ this.rangeForCheck.clearRange()
await TransactionPersistor.deleteWhenFork(rangeFirstBlockHeader.number)
throw new Error(`chain forked: ${checkResult.type}`)
} else if (checkResult.type === CheckResultType.BlockHeadersNotMatch) {
diff --git a/packages/neuron-wallet/src/services/sync/utils.ts b/packages/neuron-wallet/src/services/sync/utils.ts
index eeb6d3cd1f..668319ebe8 100644
--- a/packages/neuron-wallet/src/services/sync/utils.ts
+++ b/packages/neuron-wallet/src/services/sync/utils.ts
@@ -21,7 +21,6 @@ export default class Utils {
return new Promise(resolve => setTimeout(resolve, ms))
}
- /* eslint no-await-in-loop: "off" */
public static retry = async (times: number, interval: number, callback: any): Promise => {
let retryTime = 0
@@ -39,7 +38,6 @@ export default class Utils {
return undefined
}
- /* eslint no-restricted-syntax: "off" */
public static mapSeries = async (array: any[], callback: any): Promise => {
const result = []
for (const item of array) {
diff --git a/packages/neuron-wallet/src/services/tx/indexer-transaction.ts b/packages/neuron-wallet/src/services/tx/indexer-transaction.ts
index 5beb9393d7..5255f987b3 100644
--- a/packages/neuron-wallet/src/services/tx/indexer-transaction.ts
+++ b/packages/neuron-wallet/src/services/tx/indexer-transaction.ts
@@ -64,7 +64,7 @@ export default class IndexerTransaction {
})
.getOne()
- if (output) {
+ if (output && output.status !== OutputStatus.Dead) {
await getConnection().manager.update(
InputEntity,
{
@@ -83,7 +83,7 @@ export default class IndexerTransaction {
.getRepository(TransactionEntity)
.createQueryBuilder('tx')
.where({
- hash: output.outPointTxHash,
+ hash: txHash,
})
.getOne()
if (tx) {
diff --git a/packages/neuron-wallet/src/services/tx/transaction-persistor.ts b/packages/neuron-wallet/src/services/tx/transaction-persistor.ts
index 1f885fa49e..9b8656794d 100644
--- a/packages/neuron-wallet/src/services/tx/transaction-persistor.ts
+++ b/packages/neuron-wallet/src/services/tx/transaction-persistor.ts
@@ -7,9 +7,6 @@ import LockUtils from 'models/lock-utils'
import { OutputStatus, TxSaveType } from './params'
import Utils from 'services/sync/utils'
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
-/* eslint no-await-in-loop: "off" */
-/* eslint no-restricted-syntax: "off" */
export class TransactionPersistor {
// After the tx is sent:
// 1. If the tx is not persisted before sending, output = sent, input = pending
@@ -265,11 +262,8 @@ export class TransactionPersistor {
}
public static get = async (txHash: string) => {
- const txEntity: TransactionEntity | undefined = await getConnection()
- .getRepository(TransactionEntity)
- .findOne(txHash, { relations: ['inputs', 'outputs'] })
-
- return txEntity
+ return await getConnection().getRepository(TransactionEntity)
+ .findOne(txHash, { relations: ['inputs'] })
}
public static saveSentTx = async (
diff --git a/packages/neuron-wallet/src/services/tx/transaction-service.ts b/packages/neuron-wallet/src/services/tx/transaction-service.ts
index 28022851f0..52c7e7ccbd 100644
--- a/packages/neuron-wallet/src/services/tx/transaction-service.ts
+++ b/packages/neuron-wallet/src/services/tx/transaction-service.ts
@@ -38,9 +38,6 @@ export enum SearchType {
Unknown = 'unknown',
}
-/* eslint @typescript-eslint/no-unused-vars: "warn" */
-/* eslint no-await-in-loop: "off" */
-/* eslint no-restricted-syntax: "off" */
export class TransactionsService {
public static filterSearchType = (value: string) => {
if (value === '') {
@@ -84,7 +81,7 @@ export class TransactionsService {
return [
`${
base[0]
- } AND (CAST(ifnull("tx"."timestamp", "tx"."createdAt") AS UNSIGNED BIG INT) >= :beginTimestamp AND CAST(ifnull("tx"."timestamp", "tx"."createdAt") AS UNSIGNED BIG INT) < :endTimestamp)`,
+ } AND (CAST("tx"."timestamp") AS UNSIGNED BIG INT) >= :beginTimestamp AND CAST("tx"."timestamp") AS UNSIGNED BIG INT) < :endTimestamp)`,
{
lockHashes: params.lockHashes,
beginTimestamp,
@@ -155,15 +152,14 @@ export class TransactionsService {
const query = getConnection()
.getRepository(TransactionEntity)
.createQueryBuilder('tx')
- .addSelect(`ifnull('tx'.timestamp, 'tx'.createdAt)`, 'tt')
.leftJoinAndSelect('tx.inputs', 'input')
.leftJoinAndSelect('tx.outputs', 'output')
.where(searchParams[0], searchParams[1] as ObjectLiteral)
- .orderBy(`tt`, 'DESC')
const totalCount: number = await query.getCount()
const transactions: TransactionEntity[] = await query
+ .orderBy(`tx.timestamp`, 'DESC')
.skip(skip)
.take(params.pageSize)
.getMany()
@@ -288,10 +284,8 @@ export class TransactionsService {
const count: number = await getConnection()
.getRepository(TransactionEntity)
.createQueryBuilder('tx')
- .leftJoinAndSelect('tx.inputs', 'input')
- .leftJoinAndSelect('tx.outputs', 'output')
.where(
- `(input.lockHash IN (:...lockHashes) OR output.lockHash IN (:...lockHashes)) AND tx.status IN (:...status)`,
+ `tx.hash in (select output.transactionHash from output where output.lockHash in (:...lockHashes) union select input.transactionHash from input where input.lockHash in (:...lockHashes)) AND tx.status IN (:...status)`,
{
lockHashes,
status,
diff --git a/packages/neuron-wallet/src/startup/sync-block-task/create.ts b/packages/neuron-wallet/src/startup/sync-block-task/create.ts
index 93558e0aa3..8a19b7e5fe 100644
--- a/packages/neuron-wallet/src/startup/sync-block-task/create.ts
+++ b/packages/neuron-wallet/src/startup/sync-block-task/create.ts
@@ -47,7 +47,6 @@ const loadURL = `file://${path.join(__dirname, 'index.html')}`
export { networkSwitchSubject }
-/* eslint global-require: "off" */
// create a background task to sync transactions
// this task is a renderer process
const createSyncBlockTask = () => {
diff --git a/packages/neuron-wallet/tests-e2e/tests/notification.ts b/packages/neuron-wallet/tests-e2e/tests/notification.ts
index a6e01c329a..103e139618 100644
--- a/packages/neuron-wallet/tests-e2e/tests/notification.ts
+++ b/packages/neuron-wallet/tests-e2e/tests/notification.ts
@@ -2,7 +2,7 @@ import Application from '../application'
import { createWallet } from '../operations'
/**
- * 1. check the alert, it should be empty
+ * 1. check the alert, it should be disconnected to the network
* 2. navigate to wallet settingsState
* 3. delete a wallet
* 4. input a wrong password
@@ -32,14 +32,15 @@ export default (app: Application) => {
describe('Test alert message and notification', () => {
const messages = {
+ disconnected: 'Fail to connect to the node',
incorrectPassword: 'Password is incorrect',
}
- app.test('There is no alerts after the app launched', async () => {
+ app.test('It should have an alert message of disconnection', async () => {
const { client } = app.spectron
const alertComponent = await client.$('.ms-MessageBar-text')
const msg = await client.elementIdText(alertComponent.value.ELEMENT)
- expect(msg.value).toBe('')
+ expect(msg.value).toBe(messages.disconnected)
})
app.test('It should have an alert message of incorrect password', async () => {
@@ -56,12 +57,14 @@ export default (app: Application) => {
expect(msg.value).toBe(messages.incorrectPassword)
})
- app.test('It should have a message in the notification', async () => {
+ app.test('It should have two messages in the notification', async () => {
const { client } = app.spectron
const messageComponents = await client.$$('.ms-Panel-content p')
expect(messageComponents.length).toBe(Object.keys(messages).length)
const incorrectPasswordMsg = await client.element(`//P[text()="${messages.incorrectPassword}"]`)
+ const disconnectMsg = await client.element(`//P[text()="${messages.disconnected}"]`)
expect(incorrectPasswordMsg.state).not.toBe('failure')
+ expect(disconnectMsg.state).not.toBe('failed')
})
// TODO: dismiss a message
@@ -76,7 +79,8 @@ export default (app: Application) => {
await app.waitUntilLoaded()
app.wait(4000)
const alertComponent = await client.$('.ms-MessageBar--error')
- expect(alertComponent.state).toBe('failure')
+ const msg = await client.elementIdText(alertComponent.value.ELEMENT)
+ expect(msg.value).toBe(messages.disconnected)
})
})
}
diff --git a/packages/neuron-wallet/tests-e2e/tests/sendTransaction.ts b/packages/neuron-wallet/tests-e2e/tests/sendTransaction.ts
index e179b240ce..468f880932 100644
--- a/packages/neuron-wallet/tests-e2e/tests/sendTransaction.ts
+++ b/packages/neuron-wallet/tests-e2e/tests/sendTransaction.ts
@@ -115,36 +115,36 @@ export default (app: Application) => {
await app.waitUntilLoaded()
})
- app.test('default price should be 0 and default speed should be 3min', async () => {
+ app.test('default price should be 1000 and default speed should be 500 blocks', async () => {
const { client } = app.spectron
const transactionFeePanel = client.$('div[aria-label="transaction fee"]')
const [, priceField] = await transactionFeePanel.$$('input')
- expect((await client.elementIdAttribute(priceField.value.ELEMENT, 'value')).value).toBe('0')
+ expect((await client.elementIdAttribute(priceField.value.ELEMENT, 'value')).value).toBe('1000')
const speedDropdown = await client.$('div[role=listbox]')
- expect((await client.elementIdAttribute(speedDropdown.value.ELEMENT, 'innerText')).value).toBe('~ 3min')
+ expect((await client.elementIdAttribute(speedDropdown.value.ELEMENT, 'innerText')).value).toBe('~ 500 blocks')
})
- app.test('Change speed to immediately and the price should be 180', async () => {
+ app.test('Change speed to ~ 100 blocks and the price should be 3000', async () => {
const { client } = app.spectron
client.click('div[role=listbox]')
await app.waitUntilLoaded()
- client.click('button[title=immediately]')
+ client.click('button[title="~ 100 blocks"]')
await app.waitUntilLoaded()
const transactionFeePanel = client.$('div[aria-label="transaction fee"]')
const [, priceField] = await transactionFeePanel.$$('input')
- expect((await client.elementIdAttribute(priceField.value.ELEMENT, 'value')).value).toBe('180')
+ expect((await client.elementIdAttribute(priceField.value.ELEMENT, 'value')).value).toBe('3000')
})
- app.test('Change the price to 150 and the speed should switch to ~ 30s', async () => {
+ app.test('Change the price to 100000 and the speed should switch to immediately', async () => {
const { client } = app.spectron
const transactionFeePanel = client.$('div[aria-label="transaction fee"]')
const [, priceField] = await transactionFeePanel.$$('input')
client.elementIdClear(priceField.value.ELEMENT)
await app.waitUntilLoaded()
- client.elementIdValue(priceField.value.ELEMENT, '150')
+ client.elementIdValue(priceField.value.ELEMENT, '00')
const speedDropdown = await client.$('div[role=listbox]')
- expect((await client.elementIdAttribute(speedDropdown.value.ELEMENT, 'innerText')).value).toBe('~ 30s')
+ expect((await client.elementIdAttribute(speedDropdown.value.ELEMENT, 'innerText')).value).toBe('immediately')
})
})
}
diff --git a/yarn.lock b/yarn.lock
index 210003eb60..6977c3373c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16613,10 +16613,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typeorm@0.2.19:
- version "0.2.19"
- resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.19.tgz#a0cff0714180e5720df157df02c5759a1a646dc3"
- integrity sha512-xKVx/W41zckQ7v8WYcpRhSKpjXDKG/Jgjy0RWvYelR8ZnfyblNRL12jF4P8tIhwXv6l5t01s7HEc9lR+zb6Gtg==
+typeorm@0.2.20:
+ version "0.2.20"
+ resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.20.tgz#efb60f2e55a7d08fc365f281ec2a71c87a9ebba5"
+ integrity sha512-VxB+9qH8D+PM19MIx18Zs3Fqv/ZINnnQvUGmBEiLYDrB9etdSdamgSTCIhWdFNndeJ6ldH4jbD0Z6HWsepMPlA==
dependencies:
app-root-path "^2.0.1"
buffer "^5.1.0"