Skip to content

Commit dc415f3

Browse files
committed
feat(neuron-ui): update the Send View according to the new transaction fee model.
1 parent ca3e850 commit dc415f3

File tree

19 files changed

+140
-144
lines changed

19 files changed

+140
-144
lines changed

packages/neuron-ui/src/components/PasswordRequest/index.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import { useTranslation } from 'react-i18next'
44
import { Stack, Text, Label, Modal, TextField, PrimaryButton, DefaultButton } from 'office-ui-fabric-react'
55
import { StateWithDispatch, AppActions } from 'states/stateProvider/reducer'
66
import { sendTransaction, deleteWallet, backupWallet } from 'states/stateProvider/actionCreators'
7-
import { priceToFee, CKBToShannonFormatter } from 'utils/formatters'
87

98
const PasswordRequest = ({
109
app: {
11-
send: { txID, outputs, description, price, cycles },
10+
send: { description, generatedTx },
1211
loadings: { sending: isSending = false },
1312
passwordRequest: { walletID = '', actionType = null, password = '' },
1413
},
@@ -32,15 +31,10 @@ const PasswordRequest = ({
3231
break
3332
}
3433
sendTransaction({
35-
id: txID,
3634
walletID,
37-
items: outputs.map(output => ({
38-
address: output.address,
39-
capacity: CKBToShannonFormatter(output.amount, output.unit),
40-
})),
35+
tx: generatedTx,
4136
description,
4237
password,
43-
fee: priceToFee(price, cycles),
4438
})(dispatch, history)
4539
break
4640
}
@@ -62,7 +56,7 @@ const PasswordRequest = ({
6256
break
6357
}
6458
}
65-
}, [dispatch, walletID, password, actionType, txID, description, outputs, cycles, price, history, isSending])
59+
}, [dispatch, walletID, password, actionType, description, history, isSending, generatedTx])
6660

6761
const onChange = useCallback(
6862
(_e, value?: string) => {

packages/neuron-ui/src/components/Send/hooks.ts

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import React, { useState, useCallback, useEffect, useMemo } from 'react'
22

33
import { AppActions, StateDispatch } from 'states/stateProvider/reducer'
4-
import { calculateCycles } from 'services/remote/wallets'
4+
import { generateTx } from 'services/remote/wallets'
55

6-
import { outputsToTotalAmount, priceToFee } from 'utils/formatters'
6+
import { outputsToTotalAmount, CKBToShannonFormatter } from 'utils/formatters'
77
import { verifyAddress, verifyAmount, verifyAmountRange, verifyTransactionOutputs } from 'utils/validators'
8-
import { ErrorCode } from 'utils/const'
9-
import { MAX_DECIMAL_DIGITS } from '../../utils/const'
8+
import { ErrorCode, MAX_DECIMAL_DIGITS } from 'utils/const'
9+
import calculateFee from 'utils/calculateFee'
10+
1011
import { TransactionOutput } from '.'
1112

12-
let cyclesTimer: ReturnType<typeof setTimeout>
13+
let generateTxTimer: ReturnType<typeof setTimeout>
1314

1415
const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
1516
useCallback(
@@ -49,49 +50,47 @@ const useRemoveTransactionOutput = (dispatch: StateDispatch) =>
4950
const useOnTransactionChange = (
5051
walletID: string,
5152
items: TransactionOutput[],
53+
price: string,
5254
dispatch: StateDispatch,
5355
setIsTransactionValid: Function,
5456
setTotalAmount: Function
5557
) => {
5658
useEffect(() => {
57-
clearTimeout(cyclesTimer)
58-
cyclesTimer = setTimeout(() => {
59+
clearTimeout(generateTxTimer)
60+
generateTxTimer = setTimeout(() => {
61+
dispatch({
62+
type: AppActions.UpdateGeneratedTx,
63+
payload: null,
64+
})
5965
if (verifyTransactionOutputs(items)) {
6066
setIsTransactionValid(true)
6167
const totalAmount = outputsToTotalAmount(items)
6268
setTotalAmount(totalAmount)
63-
calculateCycles({
69+
const realParams = {
6470
walletID,
65-
capacities: totalAmount,
66-
})
67-
.then(response => {
68-
if (response.status) {
69-
if (Number.isNaN(+response.result)) {
70-
throw new Error('Invalid Cycles')
71-
}
71+
items: items.map(item => ({
72+
address: item.address,
73+
capacity: CKBToShannonFormatter(item.amount, item.unit),
74+
})),
75+
feeRate: price,
76+
}
77+
generateTx(realParams)
78+
.then((res: any) => {
79+
if (res.status === 1) {
7280
dispatch({
73-
type: AppActions.UpdateSendCycles,
74-
payload: response.result,
81+
type: AppActions.UpdateGeneratedTx,
82+
payload: res.result,
7583
})
76-
} else {
77-
throw new Error('Cycles Not Calculated')
7884
}
7985
})
80-
.catch(() => {
81-
dispatch({
82-
type: AppActions.UpdateSendCycles,
83-
payload: '0',
84-
})
86+
.catch((err: Error) => {
87+
console.error(err)
8588
})
8689
} else {
8790
setIsTransactionValid(false)
88-
dispatch({
89-
type: AppActions.UpdateSendCycles,
90-
payload: '0',
91-
})
9291
}
9392
}, 300)
94-
}, [walletID, items, dispatch, setIsTransactionValid, setTotalAmount])
93+
}, [walletID, items, price, dispatch, setIsTransactionValid, setTotalAmount])
9594
}
9695

9796
const useOnSubmit = (items: TransactionOutput[], dispatch: StateDispatch) =>
@@ -170,12 +169,12 @@ const useClear = (dispatch: StateDispatch) => useCallback(() => clear(dispatch),
170169

171170
export const useInitialize = (
172171
items: TransactionOutput[],
173-
price: string,
174-
cycles: string,
172+
generatedTx: any | null,
175173
dispatch: React.Dispatch<any>,
176174
t: any
177175
) => {
178-
const fee = useMemo(() => priceToFee(price, cycles), [price, cycles]) // in shannon
176+
const fee = useMemo(() => calculateFee(generatedTx), [generatedTx])
177+
179178
const [isTransactionValid, setIsTransactionValid] = useState(false)
180179
const [totalAmount, setTotalAmount] = useState('0')
181180

packages/neuron-ui/src/components/Send/index.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ const Send = ({
5757
onGetAddressErrorMessage,
5858
onGetAmountErrorMessage,
5959
onClear,
60-
} = useInitialize(send.outputs, send.price, send.cycles, dispatch, t)
61-
useOnTransactionChange(walletID, send.outputs, dispatch, setIsTransactionValid, setTotalAmount)
60+
} = useInitialize(send.outputs, send.generatedTx, dispatch, t)
61+
useOnTransactionChange(walletID, send.outputs, send.price, dispatch, setIsTransactionValid, setTotalAmount)
6262
const leftStackWidth = '70%'
6363
const labelWidth = '140px'
6464

@@ -211,12 +211,7 @@ const Send = ({
211211
</Stack>
212212
</Stack>
213213

214-
<TransactionFeePanel
215-
fee={shannonToCKBFormatter(fee)}
216-
cycles={send.cycles}
217-
price={send.price}
218-
onPriceChange={updateTransactionPrice}
219-
/>
214+
<TransactionFeePanel fee={shannonToCKBFormatter(fee)} price={send.price} onPriceChange={updateTransactionPrice} />
220215

221216
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 20 }}>
222217
<Stack.Item styles={{ root: { width: labelWidth } }}>

packages/neuron-ui/src/components/Transaction/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,15 @@ const Transaction = () => {
210210
const currentWallet = currentWalletCache.load()
211211
if (currentWallet) {
212212
const hash = window.location.href.split('/').pop()
213+
if (!hash) {
214+
showErrorMessage(
215+
t(`messages.error`),
216+
t(`messages.codes.${ErrorCode.FieldNotFound}`, { fieldName: 'transaction hash' })
217+
)
218+
return
219+
}
213220
getTransaction({ hash, walletID: currentWallet.id })
214-
.then(res => {
221+
.then((res: any) => {
215222
if (res.status) {
216223
setTransaction(res.result)
217224
} else {

packages/neuron-ui/src/components/TransactionFeePanel/index.tsx

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,24 @@ import { useTranslation } from 'react-i18next'
44

55
interface TransactionFee {
66
fee: string
7-
cycles: string
87
price: string
98
onPriceChange: any
109
}
1110

1211
const calculateSpeed = (price: number) => {
13-
if (price >= 160) {
14-
return '180'
12+
if (price >= 16000) {
13+
return '18000'
1514
}
16-
if (price >= 40) {
17-
return '60'
15+
if (price >= 4000) {
16+
return '6000'
1817
}
19-
if (price >= 20) {
20-
return '30'
18+
if (price >= 2000) {
19+
return '3000'
2120
}
2221
return '0'
2322
}
2423

25-
const TransactionFee: React.FunctionComponent<TransactionFee> = ({
26-
cycles,
27-
price,
28-
fee,
29-
onPriceChange,
30-
}: TransactionFee) => {
24+
const TransactionFee: React.FunctionComponent<TransactionFee> = ({ price, fee, onPriceChange }: TransactionFee) => {
3125
const [t] = useTranslation()
3226
const [showDetail, setShowDetail] = useState(false)
3327
const leftStackWidth = '70%'
@@ -48,7 +42,18 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
4842
<Label>{t('send.fee')}</Label>
4943
</Stack.Item>
5044
<Stack.Item grow>
51-
<TextField value={`${fee} CKB`} readOnly />
45+
<TextField
46+
value={`${fee} CKB`}
47+
readOnly
48+
styles={{
49+
field: {
50+
color: '#888',
51+
},
52+
fieldGroup: {
53+
borderColor: '#eee!important',
54+
},
55+
}}
56+
/>
5257
</Stack.Item>
5358
{actionSpacer}
5459
</Stack>
@@ -79,7 +84,7 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
7984
<Label>{t('send.price')}</Label>
8085
</Stack.Item>
8186
<Stack.Item grow>
82-
<TextField value={price} onChange={onPriceChange} aria-label="price" />
87+
<TextField value={price} onChange={onPriceChange} aria-label="price" suffix="shannons/kB" />
8388
</Stack.Item>
8489
{actionSpacer}
8590
</Stack>
@@ -93,10 +98,10 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
9398
dropdownWidth={140}
9499
selectedKey={selectedSpeed}
95100
options={[
96-
{ key: '180', text: 'immediately' },
97-
{ key: '60', text: '~ 30s' },
98-
{ key: '30', text: '~ 1min' },
99-
{ key: '0', text: '~ 3min' },
101+
{ key: '18000', text: 'immediately' },
102+
{ key: '6000', text: '~ 10 blocks' },
103+
{ key: '3000', text: '~ 100 blocks' },
104+
{ key: '0', text: '~ 500 blocks' },
100105
]}
101106
onRenderCaretDown={() => {
102107
return <Icon iconName="ArrowDown" />
@@ -110,15 +115,6 @@ const TransactionFee: React.FunctionComponent<TransactionFee> = ({
110115
/>
111116
</Stack.Item>
112117
</Stack>
113-
114-
<Stack>
115-
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 20 }}>
116-
<Stack.Item styles={{ root: { width: labelWidth } }}>
117-
<Label>{t('send.total-cycles')}</Label>
118-
</Stack.Item>
119-
<Stack.Item>{cycles}</Stack.Item>
120-
</Stack>
121-
</Stack>
122118
</Stack>
123119
</Stack>
124120
)

packages/neuron-ui/src/services/remote/apiMethodWrapper.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ export const RemoteNotLoadError = {
2121
},
2222
}
2323

24-
export const apiMethodWrapper = (
24+
export const apiMethodWrapper = <T = any>(
2525
callControllerMethod: (
2626
controller: any
2727
) => (
28-
params: any
28+
params: T
2929
) => Promise<{
3030
status: any
3131
result: any
3232
message: { code?: number; content?: string; meta?: { [key: string]: string } }
3333
}>
34-
) => async (realParams?: any): Promise<ControllerResponse> => {
34+
) => async (realParams: T): Promise<ControllerResponse> => {
3535
if (!window.remote) {
3636
return RemoteNotLoadError
3737
}

packages/neuron-ui/src/services/remote/app.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { apiMethodWrapper } from './apiMethodWrapper'
22

3-
export const getNeuronWalletState = apiMethodWrapper(controller => () => controller.loadInitData())
3+
export const getNeuronWalletState = apiMethodWrapper<void>(controller => () => controller.loadInitData())
44

5-
export const handleViewError = apiMethodWrapper(controller => (errorMessage: string) =>
5+
export const handleViewError = apiMethodWrapper<string>(controller => errorMessage =>
66
controller.handleViewError(errorMessage)
77
)
8-
export const contextMenu = apiMethodWrapper(controller => (params: { type: string; id: string }) =>
8+
export const contextMenu = apiMethodWrapper<{ type: string; id: string }>(controller => params =>
99
controller.contextMenu(params)
1010
)
1111

packages/neuron-ui/src/services/remote/networks.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import { apiMethodWrapper } from './apiMethodWrapper'
22

3-
export const setCurrentNetowrk = apiMethodWrapper((api: any) => (networkID: string) => {
3+
export const setCurrentNetowrk = apiMethodWrapper<string>(api => networkID => {
44
return api.setCurrentNetowrk(networkID)
55
})
66

7-
export const createNetwork = apiMethodWrapper(api => (params: Controller.CreateNetworkParams) => {
7+
export const createNetwork = apiMethodWrapper<Controller.CreateNetworkParams>(api => params => {
88
return api.createNetwork(params)
99
})
1010

11-
export const updateNetwork = apiMethodWrapper(api => ({ networkID, options }: Controller.UpdateNetworkParams) => {
11+
export const updateNetwork = apiMethodWrapper<Controller.UpdateNetworkParams>(api => ({ networkID, options }) => {
1212
return api.updateNetwork(networkID, options)
1313
})
1414

15-
export const getAllNetworks = apiMethodWrapper(api => () => {
15+
export const getAllNetworks = apiMethodWrapper<void>(api => () => {
1616
return api.getAllNetworks()
1717
})
1818

19-
export const getCurrentNetworkID = apiMethodWrapper(api => () => {
19+
export const getCurrentNetworkID = apiMethodWrapper<void>(api => () => {
2020
return api.getCurrentNetworkID()
2121
})
2222

packages/neuron-ui/src/services/remote/wallets.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { apiMethodWrapper } from './apiMethodWrapper'
22

33
export const updateWallet = apiMethodWrapper(api => (params: Controller.UpdateWalletParams) => api.updateWallet(params))
44

5-
export const getCurrentWallet = apiMethodWrapper(api => () => api.getCurrentWallet())
5+
export const getCurrentWallet = apiMethodWrapper<void>(api => () => api.getCurrentWallet())
66

7-
export const getWalletList = apiMethodWrapper(api => () => api.getAllWallets())
7+
export const getWalletList = apiMethodWrapper<void>(api => () => api.getAllWallets())
88

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

@@ -24,7 +24,11 @@ export const setCurrentWallet = apiMethodWrapper(api => (id: Controller.SetCurre
2424
api.setCurrentWallet(id)
2525
)
2626

27-
export const sendCapacity = apiMethodWrapper(api => (params: Controller.SendTransaction) => api.sendCapacity(params))
27+
export const generateTx = apiMethodWrapper(api => (params: Controller.GenerateTransactionParams) =>
28+
api.generateTx(params)
29+
)
30+
31+
export const sendTx = apiMethodWrapper(api => (params: Controller.SendTransactionParams) => api.sendTx(params))
2832

2933
export const getAddressesByWalletID = apiMethodWrapper(api => (walletID: Controller.GetAddressesByWalletIDParams) =>
3034
api.getAddressesByWalletID(walletID)
@@ -34,8 +38,6 @@ export const updateAddressDescription = apiMethodWrapper(api => (params: Control
3438
api.updateAddressDescription(params)
3539
)
3640

37-
export const calculateCycles = apiMethodWrapper(api => (params: Controller.ComputeCycles) => api.computeCycles(params))
38-
3941
export default {
4042
updateWallet,
4143
getWalletList,
@@ -45,8 +47,8 @@ export default {
4547
deleteWallet,
4648
backupWallet,
4749
getCurrentWallet,
48-
sendCapacity,
49-
calculateCycles,
50+
generateTx,
51+
sendTx,
5052
getAddressesByWalletID,
5153
updateAddressDescription,
5254
}

0 commit comments

Comments
 (0)