Skip to content

Commit

Permalink
feat(neuron-ui): update the Send View according to the new transactio…
Browse files Browse the repository at this point in the history
…n fee model.
  • Loading branch information
Keith-CY committed Oct 23, 2019
1 parent ca3e850 commit dc415f3
Show file tree
Hide file tree
Showing 19 changed files with 140 additions and 144 deletions.
12 changes: 3 additions & 9 deletions packages/neuron-ui/src/components/PasswordRequest/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '' },
},
Expand All @@ -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
}
Expand All @@ -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) => {
Expand Down
63 changes: 31 additions & 32 deletions packages/neuron-ui/src/components/Send/hooks.ts
Original file line number Diff line number Diff line change
@@ -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<typeof setTimeout>
let generateTxTimer: ReturnType<typeof setTimeout>

const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
useCallback(
Expand Down Expand Up @@ -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) =>
Expand Down Expand Up @@ -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<any>,
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')

Expand Down
11 changes: 3 additions & 8 deletions packages/neuron-ui/src/components/Send/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -211,12 +211,7 @@ const Send = ({
</Stack>
</Stack>

<TransactionFeePanel
fee={shannonToCKBFormatter(fee)}
cycles={send.cycles}
price={send.price}
onPriceChange={updateTransactionPrice}
/>
<TransactionFeePanel fee={shannonToCKBFormatter(fee)} price={send.price} onPriceChange={updateTransactionPrice} />

<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 20 }}>
<Stack.Item styles={{ root: { width: labelWidth } }}>
Expand Down
9 changes: 8 additions & 1 deletion packages/neuron-ui/src/components/Transaction/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
52 changes: 24 additions & 28 deletions packages/neuron-ui/src/components/TransactionFeePanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionFee> = ({
cycles,
price,
fee,
onPriceChange,
}: TransactionFee) => {
const TransactionFee: React.FunctionComponent<TransactionFee> = ({ price, fee, onPriceChange }: TransactionFee) => {
const [t] = useTranslation()
const [showDetail, setShowDetail] = useState(false)
const leftStackWidth = '70%'
Expand All @@ -48,7 +42,18 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
<Label>{t('send.fee')}</Label>
</Stack.Item>
<Stack.Item grow>
<TextField value={`${fee} CKB`} readOnly />
<TextField
value={`${fee} CKB`}
readOnly
styles={{
field: {
color: '#888',
},
fieldGroup: {
borderColor: '#eee!important',
},
}}
/>
</Stack.Item>
{actionSpacer}
</Stack>
Expand Down Expand Up @@ -79,7 +84,7 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
<Label>{t('send.price')}</Label>
</Stack.Item>
<Stack.Item grow>
<TextField value={price} onChange={onPriceChange} aria-label="price" />
<TextField value={price} onChange={onPriceChange} aria-label="price" suffix="shannons/kB" />
</Stack.Item>
{actionSpacer}
</Stack>
Expand All @@ -93,10 +98,10 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
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 <Icon iconName="ArrowDown" />
Expand All @@ -110,15 +115,6 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
/>
</Stack.Item>
</Stack>

<Stack>
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 20 }}>
<Stack.Item styles={{ root: { width: labelWidth } }}>
<Label>{t('send.total-cycles')}</Label>
</Stack.Item>
<Stack.Item>{cycles}</Stack.Item>
</Stack>
</Stack>
</Stack>
</Stack>
)
Expand Down
6 changes: 3 additions & 3 deletions packages/neuron-ui/src/services/remote/apiMethodWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ export const RemoteNotLoadError = {
},
}

export const apiMethodWrapper = (
export const apiMethodWrapper = <T = any>(
callControllerMethod: (
controller: any
) => (
params: any
params: T
) => Promise<{
status: any
result: any
message: { code?: number; content?: string; meta?: { [key: string]: string } }
}>
) => async (realParams?: any): Promise<ControllerResponse> => {
) => async (realParams: T): Promise<ControllerResponse> => {
if (!window.remote) {
return RemoteNotLoadError
}
Expand Down
6 changes: 3 additions & 3 deletions packages/neuron-ui/src/services/remote/app.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { apiMethodWrapper } from './apiMethodWrapper'

export const getNeuronWalletState = apiMethodWrapper(controller => () => controller.loadInitData())
export const getNeuronWalletState = apiMethodWrapper<void>(controller => () => controller.loadInitData())

export const handleViewError = apiMethodWrapper(controller => (errorMessage: string) =>
export const handleViewError = apiMethodWrapper<string>(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)
)

Expand Down
10 changes: 5 additions & 5 deletions packages/neuron-ui/src/services/remote/networks.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { apiMethodWrapper } from './apiMethodWrapper'

export const setCurrentNetowrk = apiMethodWrapper((api: any) => (networkID: string) => {
export const setCurrentNetowrk = apiMethodWrapper<string>(api => networkID => {
return api.setCurrentNetowrk(networkID)
})

export const createNetwork = apiMethodWrapper(api => (params: Controller.CreateNetworkParams) => {
export const createNetwork = apiMethodWrapper<Controller.CreateNetworkParams>(api => params => {
return api.createNetwork(params)
})

export const updateNetwork = apiMethodWrapper(api => ({ networkID, options }: Controller.UpdateNetworkParams) => {
export const updateNetwork = apiMethodWrapper<Controller.UpdateNetworkParams>(api => ({ networkID, options }) => {
return api.updateNetwork(networkID, options)
})

export const getAllNetworks = apiMethodWrapper(api => () => {
export const getAllNetworks = apiMethodWrapper<void>(api => () => {
return api.getAllNetworks()
})

export const getCurrentNetworkID = apiMethodWrapper(api => () => {
export const getCurrentNetworkID = apiMethodWrapper<void>(api => () => {
return api.getCurrentNetworkID()
})

Expand Down
16 changes: 9 additions & 7 deletions packages/neuron-ui/src/services/remote/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>(api => () => api.getCurrentWallet())

export const getWalletList = apiMethodWrapper(api => () => api.getAllWallets())
export const getWalletList = apiMethodWrapper<void>(api => () => api.getAllWallets())

export const createWallet = apiMethodWrapper(api => (params: Controller.CreateWalletParams) => api.createWallet(params))

Expand All @@ -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)
Expand All @@ -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,
Expand All @@ -45,8 +47,8 @@ export default {
deleteWallet,
backupWallet,
getCurrentWallet,
sendCapacity,
calculateCycles,
generateTx,
sendTx,
getAddressesByWalletID,
updateAddressDescription,
}
Loading

0 comments on commit dc415f3

Please sign in to comment.