-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: infinit loop issue in Edit pool FS, negative number at unstake #1682
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -13,7 +13,7 @@ | |||||||||||
import type { ChangesProps } from '.'; | ||||||||||||
|
||||||||||||
import { Divider, Grid, Typography } from '@mui/material'; | ||||||||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'; | ||||||||||||
Check failure on line 16 in packages/extension-polkagate/src/fullscreen/stake/pool/commonTasks/editPool/Review.tsx
|
||||||||||||
|
||||||||||||
import SelectProxyModal2 from '@polkadot/extension-polkagate/src/fullscreen/governance/components/SelectProxyModal2'; | ||||||||||||
import { PROXY_TYPE } from '@polkadot/extension-polkagate/src/util/constants'; | ||||||||||||
|
@@ -37,89 +37,115 @@ | |||||||||||
step: number; | ||||||||||||
} | ||||||||||||
|
||||||||||||
export default function Review ({ address, api, chain, changes, formatted, pool, setRefresh, setStep, setTxInfo, step }: Props): React.ReactElement { | ||||||||||||
const { t } = useTranslation(); | ||||||||||||
const proxies = useProxies(api, formatted); | ||||||||||||
const getRole = (role: string | undefined | null) => { | ||||||||||||
if (role === undefined) { | ||||||||||||
return 'Noop'; | ||||||||||||
} else if (role === null) { | ||||||||||||
return 'Remove'; | ||||||||||||
} else { | ||||||||||||
return { set: role }; | ||||||||||||
} | ||||||||||||
}; | ||||||||||||
|
||||||||||||
const [selectedProxy, setSelectedProxy] = useState<Proxy | undefined>(); | ||||||||||||
const [proxyItems, setProxyItems] = useState<ProxyItem[]>(); | ||||||||||||
const [isPasswordError, setIsPasswordError] = useState(false); | ||||||||||||
const [estimatedFee, setEstimatedFee] = useState<Balance>(); | ||||||||||||
const usePoolTransactionPreparation = (api: ApiPromise | undefined, changes: ChangesProps | undefined, pool: MyPoolInfo, formatted: string, maybeCurrentCommissionPayee?: string) => { | ||||||||||||
const [inputs, setInputs] = useState<StakingInputs>(); | ||||||||||||
|
||||||||||||
const selectedProxyAddress = selectedProxy?.delegate as unknown as string; | ||||||||||||
|
||||||||||||
//@ts-ignore | ||||||||||||
const maybeCurrentCommissionPayee = pool?.bondedPool?.commission?.current?.[1]?.toString() as string | undefined; | ||||||||||||
|
||||||||||||
useEffect((): void => { | ||||||||||||
const fetchedProxyItems = proxies?.map((p: Proxy) => ({ proxy: p, status: 'current' })) as ProxyItem[]; | ||||||||||||
|
||||||||||||
setProxyItems(fetchedProxyItems); | ||||||||||||
}, [proxies]); | ||||||||||||
|
||||||||||||
const extraInfo = useMemo(() => ({ | ||||||||||||
action: 'Pool Staking', | ||||||||||||
fee: String(estimatedFee || 0), | ||||||||||||
subAction: 'Edit Pool' | ||||||||||||
}), [estimatedFee]); | ||||||||||||
const [estimatedFee, setEstimatedFee] = useState<Balance>(); | ||||||||||||
|
||||||||||||
useEffect(() => { | ||||||||||||
if (!api || !changes) { | ||||||||||||
return; | ||||||||||||
} | ||||||||||||
|
||||||||||||
const batchAll = api.tx['utility']['batchAll']; | ||||||||||||
const setMetadata = api.tx['nominationPools']['setMetadata']; | ||||||||||||
const updateRoles = api.tx['nominationPools']['updateRoles']; | ||||||||||||
const setCommission = api.tx['nominationPools']['setCommission']; | ||||||||||||
const { nominationPools: { setCommission, setMetadata, updateRoles }, utility: { batchAll } } = api.tx; | ||||||||||||
|
||||||||||||
const txs: { call: SubmittableExtrinsicFunction<'promise', AnyTuple>, params: unknown[] }[] = []; | ||||||||||||
|
||||||||||||
const getRole = (role: string | undefined | null) => { | ||||||||||||
if (role === undefined) { | ||||||||||||
return 'Noop'; | ||||||||||||
} else if (role === null) { | ||||||||||||
return 'Remove'; | ||||||||||||
} else { | ||||||||||||
return { set: role }; | ||||||||||||
} | ||||||||||||
}; | ||||||||||||
|
||||||||||||
changes.newPoolName !== undefined && | ||||||||||||
txs.push({ call: setMetadata, params: [pool.poolId, changes?.newPoolName] }); | ||||||||||||
if (changes.newPoolName !== undefined) { | ||||||||||||
txs.push({ call: setMetadata, params: [pool.poolId, changes.newPoolName] }); | ||||||||||||
} | ||||||||||||
|
||||||||||||
changes.newRoles !== undefined && !Object.values(changes.newRoles).every((value) => value === undefined) && | ||||||||||||
txs.push({ call: updateRoles, params: [pool.poolId, getRole(changes.newRoles.newRoot), getRole(changes.newRoles.newNominator), getRole(changes.newRoles.newBouncer)] }); | ||||||||||||
if (changes.newRoles && !Object.values(changes.newRoles).every((value) => value === undefined)) { | ||||||||||||
txs.push({ | ||||||||||||
call: updateRoles, | ||||||||||||
params: [ | ||||||||||||
pool.poolId, | ||||||||||||
getRole(changes.newRoles?.newRoot), | ||||||||||||
getRole(changes.newRoles?.newNominator), | ||||||||||||
getRole(changes.newRoles?.newBouncer) | ||||||||||||
] | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
changes.commission !== undefined && (changes.commission.value !== undefined || changes.commission.payee) && | ||||||||||||
txs.push({ call: setCommission, params: [pool.poolId, [(changes.commission.value || 0) * 10 ** 7, changes.commission.payee || maybeCurrentCommissionPayee]] }); | ||||||||||||
if (changes.commission && | ||||||||||||
(changes.commission.value !== undefined || changes.commission.payee)) { | ||||||||||||
txs.push({ | ||||||||||||
call: setCommission, | ||||||||||||
params: [ | ||||||||||||
pool.poolId, | ||||||||||||
[ | ||||||||||||
(changes.commission.value || 0) * 10 ** 7, | ||||||||||||
changes.commission.payee || maybeCurrentCommissionPayee | ||||||||||||
] | ||||||||||||
] | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
const call = txs.length > 1 ? batchAll : txs[0].call; | ||||||||||||
const params = txs.length > 1 | ||||||||||||
? [txs.map(({ call, params }) => call(...params))] | ||||||||||||
: txs[0].params; | ||||||||||||
|
||||||||||||
let fee: Balance = api.createType('Balance', BN_ONE) as Balance; | ||||||||||||
|
||||||||||||
// Estimate transaction fee | ||||||||||||
if (!api?.call?.['transactionPaymentApi']) { | ||||||||||||
fee = api.createType('Balance', BN_ONE) as Balance; | ||||||||||||
setEstimatedFee(fee); | ||||||||||||
} | ||||||||||||
|
||||||||||||
call(...params).paymentInfo(formatted) | ||||||||||||
.then((i) => { | ||||||||||||
fee = api.createType('Balance', i?.partialFee) as Balance; | ||||||||||||
setEstimatedFee(fee); | ||||||||||||
}) | ||||||||||||
.catch(console.error); | ||||||||||||
|
||||||||||||
const extraInfo = { | ||||||||||||
action: 'Pool Staking', | ||||||||||||
fee: String(fee ?? 0), | ||||||||||||
subAction: 'Edit Pool' | ||||||||||||
}; | ||||||||||||
|
||||||||||||
setInputs({ | ||||||||||||
call, | ||||||||||||
extraInfo, | ||||||||||||
params | ||||||||||||
}); | ||||||||||||
}, [api, changes, extraInfo, maybeCurrentCommissionPayee, pool.poolId]); | ||||||||||||
}, [api, changes, pool, formatted, maybeCurrentCommissionPayee]); | ||||||||||||
|
||||||||||||
useEffect(() => { | ||||||||||||
if (!api || !inputs?.call) { | ||||||||||||
return; | ||||||||||||
} | ||||||||||||
return { estimatedFee, inputs }; | ||||||||||||
}; | ||||||||||||
|
||||||||||||
if (!api?.call?.['transactionPaymentApi']) { | ||||||||||||
return setEstimatedFee(api.createType('Balance', BN_ONE) as Balance); | ||||||||||||
} | ||||||||||||
function Review ({ address, api, chain, changes, formatted, pool, setRefresh, setStep, setTxInfo, step }: Props): React.ReactElement { | ||||||||||||
const { t } = useTranslation(); | ||||||||||||
const proxies = useProxies(api, formatted); | ||||||||||||
|
||||||||||||
inputs.call(...inputs.params)?.paymentInfo(formatted).then((i) => { | ||||||||||||
setEstimatedFee(api.createType('Balance', i?.partialFee) as Balance); | ||||||||||||
}).catch(console.error); | ||||||||||||
}, [api, formatted, inputs]); | ||||||||||||
const [selectedProxy, setSelectedProxy] = useState<Proxy | undefined>(); | ||||||||||||
const [proxyItems, setProxyItems] = useState<ProxyItem[]>(); | ||||||||||||
const [isPasswordError, setIsPasswordError] = useState(false); | ||||||||||||
|
||||||||||||
const selectedProxyAddress = selectedProxy?.delegate as unknown as string; | ||||||||||||
|
||||||||||||
//@ts-ignore | ||||||||||||
const maybeCurrentCommissionPayee = pool?.bondedPool?.commission?.current?.[1]?.toString() as string | undefined; | ||||||||||||
Comment on lines
+139
to
+140
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove @ts-ignore and fix type assertion The Replace with proper type checking: - //@ts-ignore
- const maybeCurrentCommissionPayee = pool?.bondedPool?.commission?.current?.[1]?.toString() as string | undefined;
+ const maybeCurrentCommissionPayee = pool?.bondedPool?.commission?.current &&
+ Array.isArray(pool.bondedPool.commission.current) &&
+ pool.bondedPool.commission.current[1]?.toString(); 📝 Committable suggestion
Suggested change
|
||||||||||||
|
||||||||||||
useEffect((): void => { | ||||||||||||
const fetchedProxyItems = proxies?.map((p: Proxy) => ({ proxy: p, status: 'current' })) as ProxyItem[]; | ||||||||||||
|
||||||||||||
setProxyItems(fetchedProxyItems); | ||||||||||||
}, [proxies]); | ||||||||||||
|
||||||||||||
const { estimatedFee, inputs } = usePoolTransactionPreparation(api, changes, pool, formatted,maybeCurrentCommissionPayee); | ||||||||||||
|
||||||||||||
const closeProxy = useCallback(() => setStep(STEPS.REVIEW), [setStep]); | ||||||||||||
|
||||||||||||
|
@@ -149,7 +175,7 @@ | |||||||||||
<Grid alignItems='center' container direction='column' justifyContent='center' sx={{ m: 'auto', pt: '8px', width: '90%' }}> | ||||||||||||
<Infotip showQuestionMark text={changes?.newPoolName}> | ||||||||||||
<Typography fontSize='16px' fontWeight={300} lineHeight='23px'> | ||||||||||||
{t<string>('Pool name')} | ||||||||||||
{t('Pool name')} | ||||||||||||
</Typography> | ||||||||||||
</Infotip> | ||||||||||||
<Typography fontSize='25px' fontWeight={400} lineHeight='42px' maxWidth='100%' overflow='hidden' textOverflow='ellipsis' whiteSpace='nowrap'> | ||||||||||||
|
@@ -164,23 +190,23 @@ | |||||||||||
<ShowPoolRole | ||||||||||||
chain={chain} | ||||||||||||
roleAddress={changes?.newRoles?.newRoot as string} | ||||||||||||
roleTitle={t<string>('Root')} | ||||||||||||
roleTitle={t('Root')} | ||||||||||||
showDivider | ||||||||||||
/> | ||||||||||||
} | ||||||||||||
{changes?.newRoles?.newNominator !== undefined && | ||||||||||||
<ShowPoolRole | ||||||||||||
chain={chain} | ||||||||||||
roleAddress={changes?.newRoles?.newNominator} | ||||||||||||
roleTitle={t<string>('Nominator')} | ||||||||||||
roleTitle={t('Nominator')} | ||||||||||||
showDivider | ||||||||||||
/> | ||||||||||||
} | ||||||||||||
{changes?.newRoles?.newBouncer !== undefined && | ||||||||||||
<ShowPoolRole | ||||||||||||
chain={chain} | ||||||||||||
roleAddress={changes?.newRoles?.newBouncer} | ||||||||||||
roleTitle={t<string>('Bouncer')} | ||||||||||||
roleTitle={t('Bouncer')} | ||||||||||||
showDivider | ||||||||||||
/> | ||||||||||||
} | ||||||||||||
|
@@ -201,7 +227,7 @@ | |||||||||||
<ShowPoolRole | ||||||||||||
chain={chain} | ||||||||||||
roleAddress={changes.commission.payee || maybeCurrentCommissionPayee} | ||||||||||||
roleTitle={t<string>('Commission payee')} | ||||||||||||
roleTitle={t('Commission payee')} | ||||||||||||
showDivider | ||||||||||||
/> | ||||||||||||
} | ||||||||||||
|
@@ -218,13 +244,13 @@ | |||||||||||
<SignArea2 | ||||||||||||
address={address} | ||||||||||||
call={inputs?.call} | ||||||||||||
extraInfo={extraInfo} | ||||||||||||
extraInfo={inputs?.extraInfo} | ||||||||||||
isPasswordError={isPasswordError} | ||||||||||||
onSecondaryClick={onBackClick} | ||||||||||||
params={inputs?.params} | ||||||||||||
primaryBtnText={t<string>('Confirm')} | ||||||||||||
primaryBtnText={t('Confirm')} | ||||||||||||
proxyTypeFilter={PROXY_TYPE.NOMINATION_POOLS} | ||||||||||||
secondaryBtnText={t<string>('Back')} | ||||||||||||
secondaryBtnText={t('Back')} | ||||||||||||
selectedProxy={selectedProxy} | ||||||||||||
setIsPasswordError={setIsPasswordError} | ||||||||||||
setRefresh={setRefresh} | ||||||||||||
|
@@ -252,3 +278,5 @@ | |||||||||||
</Grid> | ||||||||||||
); | ||||||||||||
} | ||||||||||||
|
||||||||||||
export default React.memo(Review); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure
extraInfo
uses the updated fee valueThe
fee
used inextraInfo
may not reflect the actual estimated fee because fee estimation is asynchronous. AssignextraInfo
after the fee estimation completes to ensure accurate information.Modify the code to set
extraInfo
after fee estimation: