Conversation
…rom assistive tech
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds broad EVM/Ethereum support across the extension: Ethereum account types, address handling, EVM asset fetching (worker), providers/fee estimation, signer adapter, UI account-type controls, and send-fund fee/transaction flow changes. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as AddressInput UI
participant Addr as AddressInput
participant UIParent as Add/Watch UI
participant Backend as Extension Backend
participant Keyring as Keyring
User->>UI: Paste/enter address
UI->>Addr: validate input
Addr->>Addr: isEthereumAddress(addr)?
alt Ethereum
Addr->>UIParent: setType('ethereum')
else Substrate
Addr->>UIParent: setType(undefined)
end
User->>UIParent: Confirm create watch-only
UIParent->>Backend: createAccountExternal(name, addr, undefined, type)
Backend->>Keyring: keyring.addExternal({ address, type })
Keyring-->>Backend: added
Backend-->>UIParent: success
sequenceDiagram
actor User
participant SendUI as Send Fund UI
participant Step3 as Step3Amount
participant FeeHook as useLimitedFeeCall
participant ChainAPI as Chain API
participant ParaSpell as ParaSpell Builder
participant Backend as Node / Extrinsic
User->>SendUI: Configure transfer (amount, recipient, chain)
SendUI->>Step3: render inputs
Step3->>FeeHook: request fee (amount, decimal, recipientAddress, recipientChain, transferType)
FeeHook->>ChainAPI: resolve chain info / decimals
FeeHook->>FeeHook: build onChainParam
FeeHook->>Backend: prepare call / estimate fee
alt paraspell supported
Step3->>ParaSpell: build paraSpell transaction & getTransferInfo
ParaSpell-->>Step3: paraSpellTransaction + paraSpellFee
end
FeeHook-->>Step3: (call, limitedTotalFee, params)
Step3->>SendUI: update UI, enable signing
sequenceDiagram
participant Worker as SharedWorker
participant Provider as Eth Provider
participant Contracts as ERC20 Contracts
participant Port as MessagePort
participant Main as Main Thread
Main->>Worker: request getEvmAssets(addresses, chain)
Worker->>Provider: init provider for chain
loop per address
Worker->>Contracts: call balanceOf for tokens
Contracts-->>Worker: token balances
Worker->>Provider: getBalance(native)
Provider-->>Worker: native balance
Worker->>Worker: assemble assets array
end
Worker->>Port: postMessage({ function: 'getEvmAssets', result })
Port-->>Main: deliver assets
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/extension-polkagate/src/themes/dark.ts (1)
14-14: Clarify or correct the comment.The comment indicates this property is "for staking," but the PR is focused on adding EVM chain support. Please verify whether this comment is accurate or should be updated to reflect its actual usage in the EVM-related UI changes.
packages/extension-polkagate/src/hooks/useFetchAssetsOnChains.ts (1)
107-143: Filter relay chain addresses tosubstrateAddressesfor consistency.Relay chains (line 117) currently receive the unfiltered
addressesarray, while asset hubs (line 134) and multi-asset chains (line 139) only receivesubstrateAddresses. Since relay chains are substrate-based and cannot process Ethereum addresses, they should usesubstrateAddressesas well. This would also require moving the relay chain logic check after the substrate address guard (currently at lines 120-122).
🤖 Fix all issues with AI Agents
In @.env.example:
- Line 1: The EXTENSION_PREFIX in .env.example was changed to the generic
MY_EXTENSION; revert it to the project-specific value (e.g., POLKAGATE) or
another appropriate project identifier by updating the EXTENSION_PREFIX entry in
.env.example, and then verify all usages of process.env.EXTENSION_PREFIX (search
for EXTENSION_PREFIX in the codebase) still expect that value and adjust any
documentation or tests that assume POLKAGATE to match the new prefix if you
intentionally want a different name.
In @package.json:
- Line 27: The package.json "build" script contains an invalid double ampersand
("&& &&") causing a shell syntax error; open the "build" script entry (the value
for the "build" key) and remove the extra ampersand so the commands are chained
correctly (i.e., ensure there is a single "&&" between "yarn copy-prod-manifest"
and "yarn apply-version"), leaving the rest of the pipeline
("polkadot-dev-build-ts && yarn build:zip && yarn build:rollup") intact.
- Around line 60-62: The project imports v5 sub-packages (@ethersproject/bytes,
@ethersproject/keccak256, @ethersproject/transactions) while using ethers v6;
update signerAdaptor.ts to import arrayify, keccak256, serialize and
UnsignedTransaction (or the v6 equivalent types) directly from "ethers" instead
of the @ethersproject/* packages, adjust any call signatures to match ethers v6
APIs per the ethers v6 migration guide, and remove the three @ethersproject/*
dependencies from package.json to avoid version mixing and bundle duplication.
- Line 87: Update the dependency entry for "@web3icons/react" in package.json
from "^4.0.25" to "^4.1.12"; after editing the "@web3icons/react" version
string, run your package manager (npm install or yarn install) to update
node_modules and regenerate the lockfile (package-lock.json or yarn.lock), then
run the test/build to ensure nothing breaks.
In @packages/extension-base/src/background/handlers/Extension.ts:
- Around line 113-114: In accountsCreateExternal, keyring.addExternal is being
called with the account type inside the meta object; move the type out to the
third argument: update the call in accountsCreateExternal so it passes address
and a meta object with genesisHash and name, and supply type as the separate
third parameter to keyring.addExternal.
In @packages/extension-polkagate/src/components/FormatBalance2.tsx:
- Around line 40-49: The getFormat function may access decimals[0] or tokens[1]
when the arrays are shorter than expected; validate that decimals and tokens are
non-empty at the start of getFormat (or throw a clear error) and change the
token fallback to use tokens[0] instead of tokens[1]; ensure the returned tuple
uses formatIndex if in-range otherwise decimals[0] and tokens[0] as safe
fallbacks to avoid undefined accesses.
- Around line 58-63: splitFormat assumes value contains both '.' and a space
which can cause a runtime error when postfixFull is undefined; add validation in
splitFormat to safely handle malformed input by checking that value includes a
'.' before splitting and that postfixFull is defined before calling split(' '),
providing sensible fallbacks (e.g., postfix = '' and unit = '') or returning a
safe default React node; ensure createElement(prefix, postfix, unit, label,
isShort, decimalPoint) always receives defined strings and preserve existing
behavior for valid inputs.
- Around line 82-89: FormatBalance currently calls getFormat(decimals, tokens,
formatIndex) without ensuring decimals and tokens are non-empty arrays, risking
runtime errors in getFormat; update the useMemo for formatInfo (in function
FormatBalance) to validate that decimals and tokens are arrays with length > 0
(e.g., Array.isArray(decimals) && decimals.length && Array.isArray(tokens) &&
tokens.length) before calling getFormat, and if validation fails fall back to a
safe default (either the provided format prop or a safe format object/undefined)
so getFormat is never invoked with empty or invalid arrays.
- Around line 65-80: The applyFormat function uses rest.slice(4) without
validating rest length and compares prefix length to K_LENGTH (which is
unclear); update this by renaming K_LENGTH to a clearer SI_UNIT_THRESHOLD (or
similar) and update all references, and defend the slice by ensuring rest.length
>= 4 before slicing (e.g., compute unit = rest.length >= 4 ? rest.slice(4) : ''
or use a safe substring equivalent) so you never index past the string; keep the
original behavior of switching to SI formatting using the renamed threshold.
- Around line 51-56: In createElement ensure postfix is defensively handled
before any use: coerce postfix to a safe string (e.g., const safePostfix =
postfix ?? '') and use safePostfix everywhere (replace postfix, postfix?.slice,
and the parseFloat check that sets maybeTilde) and guard the parseFloat
comparison (skip maybeTilde when safePostfix is empty or shorter than
decimalPoint). Update references in createElement (maybeTilde, trimmedPostfix,
slice for span content) to use the safe variable so no code path calls
parseFloat or .slice on undefined.
In @packages/extension-polkagate/src/components/PasswordInput.tsx:
- Line 76: The focusing state is initialized incorrectly from the focused prop,
causing an inverted visual when autoFocus triggers; change the initialization of
focusing in PasswordInput (state variable focusing and setter setFocused) to a
hard-coded default (e.g., false) instead of using the focused prop, and if you
need initial sync, handle it in a useEffect that sets focusing based on focused
only once on mount; also ensure the onFocus handler that calls toggle() remains
consistent so autoFocus won’t flip the visual state unexpectedly.
In @packages/extension-polkagate/src/components/signerAdaptor.ts:
- Around line 49-54: The v value is computed incorrectly as sig[64] + 27 in
signerAdaptor.ts; update the signature recovery calculation to be EIP-155
compliant by using the transaction chainId: compute recoveryId = sig[64] & 1 (0
or 1) and set v = chainId * 2 + 35 + recoveryId (for chainId present) instead of
adding 27; ensure the signing method that contains sigBytes -> sig/r/s/v (the
method where const sigBytes = this.keypair.sign(msgHash) is used) accepts or
reads the appropriate chainId (e.g., from the transaction or this object) and
falls back to v = recoveryId + 27 only if chainId is undefined/null for legacy
behavior.
- Around line 26-60: Ensure the signer only uses ECDSA/secp256k1 keypairs by
validating the key type before signing: in the constructor of the SignerAdaptor
class or at the very start of signTransaction(tx: TransactionRequest) check
this.keypair.type (or equivalent property/method on the keypair) and if it is
not ECDSA/secp256k1 (e.g., not "ecdsa" or "secp256k1") throw a clear error
describing the unsupported key type; do not attempt to sign with non-ECDSA
keypairs (fail fast) and include this.keypair reference in the validation to
locate the check quickly.
- Line 4: Remove the top-level //@ts-nocheck from signerAdaptor.ts and re-enable
TypeScript checking; then fix any resulting type errors in the signer adaptor
implementation (e.g., adjust types for functions/values such as the signer
adaptor export, sign/verify methods, key objects, and any helper functions) by
declaring proper interfaces/types or using narrow, explicit casts; if an
individual line truly cannot be typed immediately, replace broad suppression
with targeted @ts-expect-error comments and short explanations next to them
rather than disabling checks for the whole file.
- Around line 26-66: signTransaction and sendTransaction lack validation and
error handling; add input checks (e.g., ensure tx.to is present and valid,
gasPrice/gasLimit/nonce/value types are sane, tx.data convertible), validate
signature parts after this.keypair.sign (ensure sigBytes length >=65 and r/s/v
in expected ranges) and wrap signing and serialization in try/catch to throw
descriptive errors (e.g., "signTransaction: invalid input", "signTransaction:
signing failed", "signTransaction: invalid signature"). In sendTransaction wrap
provider.broadcastTransaction in try/catch to translate network/provider errors
into clear errors (e.g., "sendTransaction: broadcast failed") and rethrow or
return a rejected Promise; reference signTransaction, sendTransaction,
this.keypair.sign, serialize, keccak256, and provider.broadcastTransaction when
locating code to change.
In @packages/extension-polkagate/src/components/SignUsingProxy.tsx:
- Line 121: The component widened the type of the prop proxies to include null
but the code still only checks for undefined; update all loading checks (e.g.,
the loadingProxy boolean and the JSX loading indicator) to treat null like
undefined by changing conditions from proxies === undefined to proxies == null
or (proxies === undefined || proxies === null), and ensure any subsequent
branches that assume proxies is an array first guard against proxies being null
before accessing it.
In @packages/extension-polkagate/src/fullscreen/sendFund/index.tsx:
- Around line 52-78: The effect currently mis-checks the recipient component and
blocks recalculation: replace the incorrect check of RecipientAddress with a
runtime check of the recipient value (variable to) in the condition; ensure
ethFeeRef is reset so fees can be recalculated when inputs change (e.g., set
ethFeeRef.current = false in a finally or cleanup when amount/to/token/address
change or avoid a permanent guard and instead guard per-request), and remove the
//@ts-ignore by constructing the correct FeeInfo-typed object before calling
setInputs (import or define FeeInfo and set fee: { originFee: res as FeeInfo }
or map res to the expected structure) so setInputs receives the properly typed
fee shape when getEthFee resolves; keep getEthFee, ethFeeRef, inputs, setInputs,
address, chainName, amount, to, token as the referenced symbols to locate
changes.
In @packages/extension-polkagate/src/fullscreen/sendFund/useLimitedFeeCall.ts:
- Around line 146-156: The onChainParam useMemo builds transfer args with the
sender `address` instead of the destination `recipientAddress`; update the three
branches in `onChainParam` (the currencies/tokens branch, the assets branch, and
the balances branch) to use `recipientAddress` as the destination
(`['recipientAddress', assetToTransfer.currencyId, amountAsBN]`,
`[parsedAssetId, recipientAddress, amountAsBN]`, and `[recipientAddress,
amountAsBN]` respectively) and include `recipientAddress` in the useMemo
dependency array; also remove the unsafe `as unknown` cast on
`assetToTransfer.currencyId` and replace it with a correct typed assertion or
ensure `currencyId` is correctly typed on `FetchedBalance` so the parameter
matches the expected on-chain API type.
In @packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts:
- Around line 102-108: The @ts-ignore on the setParaSpellState update hides a
type mismatch: the fallback object only sets paraSpellFee.originFee and omits
paraSpellFee.destinationFee which violates the expected ParaspellFees shape;
update the setParaSpellState callback (the function passed to setParaSpellState)
to provide a full-paraspell fee object matching ParaspellFees (include both
originFee and destinationFee with BN_ZERO or appropriate defaults), or
alternatively fix the ParaspellFees type if the destinationFee can be optional,
or if suppression is truly required replace @ts-ignore with @ts-expect-error and
add a comment explaining why the type mismatch is safe; specifically reference
setParaSpellState, paraSpellFee, originFee, destinationFee, ParaspellFees and
BN_ZERO when making the change.
In @packages/extension-polkagate/src/hooks/useEthSigner.ts:
- Line 10: The import for getEthProvider is pointing to the wrong path; update
the import statement that references getEthProvider in useEthSigner.ts to import
from the evmUtils folder (i.e., replace the '../util/getEthProvider' import with
the correct '../util/evmUtils/getEthProvider' path) so the getEthProvider symbol
resolves to the actual module.
- Around line 13-17: The useEthSigner hook (useEthSigner) currently never sets
its signer state because the signer resolution logic (commented-out block around
lines 18-47 and similar at 49-50) is removed, so the hook always returns
undefined; either re-enable/implement that logic to resolve and set the
JsonRpcSigner (using chainName and address to instantiate provider and call
getSigner) and update signer via setSigner, or add a clear TODO/FIXME at the top
of useEthSigner stating it is intentionally a placeholder and ensure callers
handle undefined signer; also add a unit or runtime guard in dependent code to
gracefully handle an undefined signer before marking the PR ready.
- Around line 18-47: The large commented-out useMemo/useEffect block in
useEthSigner.ts (the provider useMemo and side-effect that calls
provider.getSigner and setSigner) and its debugging console.log calls should not
remain in production; either fully implement and uncomment this logic using
getEthProvider, provider, signer, setSigner (ensuring proper dependency arrays
and type guards for provider.getSigner) or delete the commented block entirely
(or replace it with a single TODO comment describing the intended behavior).
Also remove all console.log statements referenced in the comment (the logs
around '_provider', 'Getting signer ...', and 'signer:') so no debug prints
remain. Ensure references to getEthProvider, provider.getSigner, setSigner,
signer remain correct if you implement the logic.
- Line 4: Remove the top-line `//@ts-nocheck`, delete the unused `Wallet`
import, and correct the faulty import path from '../util/getEthProvider' to
'../util/evmUtils/getEthProvider' so TypeScript can resolve the module in the
useEthSigner hook; keep all other imports and the useEthSigner implementation
unchanged.
In @packages/extension-polkagate/src/hooks/useFetchAssetsOnChains.ts:
- Around line 88-105: There is a leftover debug console.log in
useFetchAssetsOnChains.ts: remove the console.log(' to fetch evm chains
balances:', evmAddresses?.length) inside the block that checks evmAddresses and
isEvmChain so production logs aren’t polluted; keep the surrounding logic intact
(the destructuring that produces evmAddresses/substrateAddresses, the chainName
resolution via getChainName(genesisHash, genesisOptions), the error branch that
returns FAILED, and the final return fetchEvmAssets(chainName, evmAddresses)).
In @packages/extension-polkagate/src/popup/history/explorer.ts:
- Around line 8-10: The Ethereum explorer branch currently always returns a
mainnet tx URL and concatenates raw data; update the explorer logic in
explorer.ts to (1) use the incoming type parameter (when type === 'account'
build an /address/ URL, when 'extrinsic' or 'tx' use /tx/), (2) resolve the
correct Etherscan-style domain per chain using the ETH_CHAIN_IDS.ts mapping
(support "ethereum", "polygon", "arbitrum", "optimism", "base", etc.) and pick
the correct subdomain for testnets like sepolia, (3) validate the data parameter
with a simple regex for tx-hash or checksummed/hex address before building the
URL and return a safe fallback (null or a standardized error object) for invalid
data, and (4) centralize this in the same function/block that references
chainName, type, and data so other EVM chains are handled consistently.
In @packages/extension-polkagate/src/themes/dark.ts:
- Line 40: The dark theme defines a redundant warning.light color in
packages/extension-polkagate/src/themes/dark.ts (warning.light: '#FFCE4F') that
is unused and inconsistent with light.ts; either remove the warning.light
property from the exported dark theme object or add a matching warning.light to
light.ts and update components/styles to reference warning.light where a lighter
warning variant is required (search for usages of the warning palette and ensure
components reference warning.light instead of duplicating colors). Ensure the
change keeps the exported theme shape consistent across dark.ts and light.ts and
run a project-wide search for "warning.light" to verify no broken references
remain.
In @packages/extension-polkagate/src/util/api/getEtherscan.ts:
- Around line 81-103: In getEthTxHistory, validate the chain input before
building the URL: check the result of EVM_CHAIN_ID_MAP[chainName.toLowerCase()]
(and optionally getChainInfoByName(chainName)) and if chainId (or tokenDecimal)
is undefined, throw or return a rejected Promise with a clear "unsupported
chain" error (including the provided chainName and/or a list of supported
chains) instead of proceeding to construct the URL; locate symbols
getEthTxHistory, EVM_CHAIN_ID_MAP and getChainInfoByName to add this guard so
you never call the Etherscan API with chainid=undefined.
- Line 6: Remove the node-fetch import and switch to the native browser fetch:
delete the line importing 'node-fetch' in getEtherscan.ts, update any calls in
the getEthTxHistory function to use the global fetch (no import), and if
TypeScript compilation complains about fetch types ensure the project includes
DOM lib typings (or add appropriate types) so the native fetch is recognized at
compile time.
- Around line 47-72: The function convertTxToPolkaGateStyle hardcodes
asset_symbol: 'ETH' which breaks support for other EVM chains; change
convertTxToPolkaGateStyle to accept a token symbol parameter (e.g., symbol) or
derive it using EVM_CHAIN_ID_MAP given the chain id, update where
convertTxToPolkaGateStyle is called (the caller around line 118) to pass the
correct native token symbol (BNB, MATIC, AVAX, etc.) based on chain info, and
ensure the returned object uses that symbol instead of the hardcoded 'ETH'.
In @packages/extension-polkagate/src/util/evmUtils/constantsEth.ts:
- Around line 62-68: The chain key is misspelled as "goreli" in this file which
conflicts with the correct "goerli" used at line 62; update all occurrences of
the "goreli" string keys in the exported constants (in this file’s constantsEth
object) to "goerli" so token lookups (e.g., the USDC entry and any ERC20
lookups) use a consistent chain name.
- Around line 9-16: The Goerli testnet constant and map entry are misspelled and
use the wrong genesis hash: rename GORELI_GENESISHASH to GOERLI_GENESISHASH (or
update its usage) and update its value to the correct Goerli genesis hash
0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a; then update
the EVM_GENESISHASH_MAP key from "goreli" to "goerli" (and reference the
corrected GOERLI_GENESISHASH) so the map and other code (e.g., getLogo2.ts) use
the consistent "goerli" spelling and correct hash.
In @packages/extension-polkagate/src/util/evmUtils/ETH_CHAIN_IDS.ts:
- Line 21: Rename the mistaken key berachainBepolia to berachainSepolia in the
ETH_CHAIN_IDS map and update any usages that reference berachainBepolia to the
new key; keep the numeric value (80069) unchanged so lookups still resolve
correctly and adjust any tests or type definitions that reference the old
identifier (e.g., in code that accesses ETH_CHAIN_IDS.berachainBepolia).
In @packages/extension-polkagate/src/util/evmUtils/getEthProvider.ts:
- Line 8: There is a misspelling of the Goerli testnet — update the key/value
"goreli" to the correct "goerli" wherever it appears (specifically in the
NETWORK_MAP constant and in the isTestNet function) so references match the
proper network name; ensure both occurrences are renamed consistently and run
tests/type checks to confirm no other references remain.
In @packages/extension-polkagate/src/util/getChain.ts:
- Line 22: The return uses an unsafe assertion "found as unknown as NetworkInfo"
allowing undefined to be treated as NetworkInfo; instead return the variable
found directly (remove the double-cast) so the function respects its declared
return type NetworkInfo | undefined—locate the found variable and the return
statement in getChain (the line returning found as unknown as NetworkInfo) and
replace it with a plain return found.
In @packages/extension-polkagate/src/util/getLogo2.ts:
- Line 66: The array evmChainsWithEthLogo contains the correctly spelled chain
name "goerli" but the genesis-hash mapping in the constants (the genesis hash
map key currently spelled "goreli") is misspelled, causing lookup mismatches;
update the genesis hash map key from "goreli" to "goerli" (and search/replace
any other occurrences of the misspelling) so keys in the genesis hash map match
evmChainsWithEthLogo and other lookups that use "goerli".
In
@packages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnEvm.js:
- Around line 68-77: The code incorrectly treats a zero bigint balance as falsy
and returns early; update the check around the result of
tokenContract['balanceOf'] (variable balance in getAssetOnEvm.js) to only bail
out for failed fetches (null or undefined) rather than any falsy value—i.e.,
replace the `if (!balance)` style check with an explicit null/undefined check
(e.g., `balance == null` or `balance === undefined`) so zero balances (0n) are
preserved for downstream processing.
In
@packages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnRelayChain.js:
- Line 21: The line mutates the input addresses array; instead create a new
array (e.g., normalizedAddresses) by mapping addresses with the existing
isEthereumAddress and evmToAddress logic instead of reassigning to addresses,
and then use normalizedAddresses wherever the code currently references
addresses (ensure references such as the mapping line and any subsequent calls
that expect normalized values are updated to use normalizedAddresses).
In @packages/extension-polkagate/src/util/workers/shared-helpers/getNFTs.js:
- Around line 239-245: The check for filteredAddresses is incorrect because
filter() always returns an array; replace the truthiness check with an emptiness
check so that when filteredAddresses is undefined/null or has length === 0 you
short-circuit and post the NFT_FUNCTION_NAME result as undefined; update the
logic around filteredAddresses (from the isEthereumAddress filter step) to test
(!filteredAddresses || filteredAddresses.length === 0) before calling
getNFTs([]) and calling port.postMessage(JSON.stringify({ functionName:
NFT_FUNCTION_NAME, results: undefined })) to avoid unnecessary work.
In @packages/extension/manifest.dev.json:
- Around line 2-3: The manifest's "description" currently references only
Polkadot/Substrate ecosystems but this PR adds Ethereum/EVM support; update the
"description" value in packages/extension/manifest.dev.json (the JSON key
"description") to mention both Polkadot/Substrate and Ethereum/EVM-based
blockchains (e.g., "A user-friendly wallet for seamless browser-based
interaction with Polkadot/Substrate and Ethereum/EVM-based blockchains."),
keeping the message concise and within any store length limits.
In @packages/extension/manifest.prod.json:
- Around line 2-3: Update the "description" value in manifest.prod.json to
mention both Polkadot/Substrate and Ethereum/EVM support: locate the
"description" field (currently "A user-friendly wallet for seamless
browser-based interaction with Polkadot/Substrate-based blockchains.") and
change it to a concise string that references both ecosystems (e.g., include
"Polkadot/Substrate and Ethereum/EVM" or similar phrasing) to reflect the new
EVM support.
In @replacements/interfaces.js:
- Around line 54-73: The Goerli entry in the evmTestChains array uses an
incorrect SLIP-44 coin type (prefix: 5); update the Goerli testnet object (the
object with displayName "Goerli Testnet" inside evmTestChains) to use prefix: 60
to match Ethereum's coin type so address derivation and network identification
remain consistent with mainnet and Sepolia.
🟠 Major comments (16)
packages/extension-polkagate/src/components/PasswordInput.tsx-76-76 (1)
76-76: Logic error: inverted focus state when auto-focusing.Initializing
focusingwith thefocusedprop creates incorrect visual behavior whenfocused={true}is passed:
focusingstate initializes totrueautoFocus={focused}(line 131) causes the input to focus on mount- The
onFocusevent fires and callstoggle(), flippingfocusingfromtruetofalse- The Check icon now displays as unfocused (bulk variant, common color) even though the input IS focused
This inverts the expected visual state whenever the component auto-focuses.
🔎 Recommended fix
Revert to the original hard-coded initialization:
- const [focusing, setFocused] = useState<boolean>(focused); + const [focusing, setFocused] = useState<boolean>(false);If you need to synchronize initial focus state with the prop, consider using
useEffectto handle the initial focus without conflicting with the toggle behavior, or reconsider whether the toggle callback should be conditional.packages/extension-polkagate/src/components/FormatBalance2.tsx-82-89 (1)
82-89: Add validation for required array props.The component passes
decimalsandtokenstogetFormat(Line 87) without validating they are non-empty arrays. Given the array access issues ingetFormat, this could cause runtime errors.🔎 Proposed validation
function FormatBalance({ children, decimalPoint = FLOATING_POINT_DIGIT, decimals, format, formatIndex, isShort, label, labelPost, style, tokenColor, tokens, value, valueFormatted, withCurrency, withSi }: FormatBalanceProps): React.ReactElement<FormatBalanceProps> { const { t } = useTranslation(); const { isHideNumbers } = useIsHideNumbers(); + + if (!decimals?.length || !tokens?.length) { + console.error('FormatBalance: decimals and tokens must be non-empty arrays'); + return <div style={style}>-</div>; + } const formatInfo = useMemo(() => format || getFormat(decimals, tokens, formatIndex) , [decimals, tokens, format, formatIndex]);packages/extension-polkagate/src/components/FormatBalance2.tsx-65-80 (1)
65-80: Verify string slice safety and improve constant naming.Two concerns:
Line 74:
rest.slice(4)assumes the string returned byformatBalancehas at least 4 characters in therestportion. While this may be guaranteed by the@polkadot/utillibrary, it's not explicitly validated here.Line 38: The constant
K_LENGTH = 3 + 1is unclear. Consider renaming to something more descriptive likeSI_UNIT_THRESHOLDto clarify its purpose (threshold for switching to SI unit formatting).🔎 Suggested improvements
Add validation for slice operation:
if (prefix.length > K_LENGTH) { const [major, rest] = formatBalance(value, { decimals, withSi: withSi ?? true, withUnit: false }).split('.'); const minor = rest.slice(0, decimalPoint); - const unit = rest.slice(4); + const unit = rest?.slice(4) ?? ''; return <>{major}.<span>{minor}</span><span style={{ color: tokenColor ?? 'inherit' }}>{unit}{unit ? unitPost : ` ${unitPost}`}</span>{labelPost || ''}</>; }Improve constant naming:
-const K_LENGTH = 3 + 1; +const SI_UNIT_THRESHOLD = 4;packages/extension-polkagate/src/popup/history/explorer.ts-8-10 (1)
8-10: Multiple issues with Ethereum link generation.
Type parameter ignored — The function accepts
type: 'account' | 'extrinsic'but always returns a transaction URL (/tx/) for Ethereum, even whentype === 'account'. Etherscan uses/address/for accounts and/tx/for transactions.Mainnet-only hardcoding — The implementation only supports Ethereum mainnet. Testnets like Sepolia require different subdomains (e.g.,
sepolia.etherscan.io).Limited EVM chain coverage — The PR objectives mention "comprehensive Ethereum/EVM support," but this only handles a chain named "ethereum". The codebase includes configurations for Polygon, Arbitrum, Optimism, Base, and other EVM chains in
ETH_CHAIN_IDS.ts, yet none receive explorer link support.No data validation — The
dataparameter is concatenated directly without validation. Invalid or malformed data produces broken URLs.packages/extension-polkagate/src/components/signerAdaptor.ts-26-66 (1)
26-66: Add error handling and input validation.The methods lack error handling for:
- Invalid transaction parameters (e.g., missing
toaddress)- Network failures during provider calls
- Signing failures
- Invalid signature construction
- Broadcast failures
This can lead to unclear error messages and difficult debugging for users.
🔎 Recommended error handling enhancements
async signTransaction(tx: TransactionRequest): Promise<string> { + if (!tx.to && !tx.data) { + throw new Error('Transaction must have either a recipient address (to) or data'); + } + + try { const chainId = tx.chainId ?? 1; // ... rest of signing logic ... const sigBytes = this.keypair.sign(msgHash); + + if (!sigBytes || sigBytes.length !== 65) { + throw new Error(`Invalid signature length: expected 65 bytes, got ${sigBytes?.length || 0}`); + } const sig = new Uint8Array(sigBytes); // ... construct r, s, v ... return serialize(txUnsigned, sigTyped); + } catch (error) { + throw new Error(`Failed to sign transaction: ${error instanceof Error ? error.message : String(error)}`); + } } async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> { + try { const signedTx = await this.signTransaction(tx); - return this.provider.broadcastTransaction(signedTx); + } catch (error) { + throw new Error(`Failed to send transaction: ${error instanceof Error ? error.message : String(error)}`); + } }packages/extension-polkagate/src/components/signerAdaptor.ts-27-33 (1)
27-33: Replace hardcoded defaults with network-fetched values.The current implementation uses hardcoded fallback values that will cause transaction failures or suboptimal behavior:
nonce ?? 0(line 28): Using nonce 0 will fail if the account has sent any prior transactions. The nonce must be fetched from the network.gasPrice ?? ethers.parseUnits('10', 'gwei')(line 29): 10 gwei is arbitrary and may be too high (wasting funds) or too low (causing transaction delays). Should fetch current gas price.gasLimit ?? 21000(line 30): 21000 is only correct for simple ETH transfers. Contract interactions and token transfers require gas estimation.chainId ?? 1(line 27): Defaulting to mainnet (chainId 1) is dangerous—users could accidentally broadcast test transactions to mainnet.🔎 Proposed fix using provider for dynamic values
async signTransaction(tx: TransactionRequest): Promise<string> { - const chainId = tx.chainId ?? 1; - const nonce = tx.nonce ?? 0; - const gasPrice = BigInt(tx.gasPrice ?? ethers.parseUnits('10', 'gwei')); - const gasLimit = BigInt(tx.gasLimit ?? 21000); + const network = await this.provider.getNetwork(); + const chainId = tx.chainId ?? Number(network.chainId); + + const address = this.getAddress(); + const nonce = tx.nonce ?? await this.provider.getTransactionCount(address, 'pending'); + + const feeData = await this.provider.getFeeData(); + const gasPrice = BigInt(tx.gasPrice ?? feeData.gasPrice ?? ethers.parseUnits('10', 'gwei')); + + // Estimate gas if not provided and we have a valid 'to' address + let gasLimit = BigInt(tx.gasLimit ?? 21000); + if (!tx.gasLimit && tx.to) { + try { + gasLimit = await this.provider.estimateGas(tx); + } catch { + gasLimit = 21000n; // fallback for simple transfers + } + } + const to = tx.to?.toString() ?? undefined;Note: Consider throwing an error if critical parameters like
toare missing instead of allowing undefined values.package.json-60-62 (1)
60-62: Replace @ethersproject v5 imports with ethers v6 equivalents to eliminate version mixing.The code in
signerAdaptor.tsdirectly imports utilities from@ethersproject/bytes,@ethersproject/keccak256, and@ethersproject/transactions(all v5) while also usingethersv6. According to ethers v6 documentation, all functionality from these v5 sub-packages has been consolidated into the mainethersv6 package with updated APIs:
arrayify()from@ethersproject/bytes→ available frometherskeccak256()from@ethersproject/keccak256→ available fromethersserialize()andUnsignedTransactionfrom@ethersproject/transactions→ available fromethersMigrate these imports to use
ethersv6 directly and remove the v5 sub-packages from dependencies to avoid code duplication, potential bundle bloat, and API inconsistencies. See the ethers v6 migration guide for renamed utilities and updated API signatures.packages/extension-polkagate/src/hooks/useEthSigner.ts-13-17 (1)
13-17: Hook is non-functional and always returnsundefined.The hook initializes a
signerstate but never updates it, meaning it will always returnundefined. All signer resolution logic is commented out (lines 18-47).This is acceptable for WIP but must be addressed before merging:
- Either implement the commented-out logic
- Or add a clear TODO/FIXME comment explaining this is a placeholder
- Ensure dependent code gracefully handles
undefinedsignerGiven the PR is marked WIP, please ensure this hook is fully functional before marking the PR ready for review.
Also applies to: 49-50
packages/extension-polkagate/src/hooks/useEthSigner.ts-18-47 (1)
18-47: Remove or implement commented-out code before merging.Large blocks of commented code reduce readability and should be avoided in production code.
Please either:
- Implement and uncomment this logic when ready
- Remove it entirely (git history preserves the code if needed later)
- Replace with clear TODO comments explaining what needs to be implemented
Additionally, remove debugging
console.logstatements (lines 23, 27, 41, 46) before merging, as they should not appear in production code.packages/extension-polkagate/src/hooks/useEthSigner.ts-4-4 (1)
4-4: Fix the import path and remove//@ts-nocheck.The import statement at line 10 uses an incorrect path:
'../util/getEthProvider'should be'../util/evmUtils/getEthProvider'. This module resolution error is likely why//@ts-nocheckwas added. Fix the import path instead of suppressing type checking. Also remove the unusedWalletimport on line 7.packages/extension-polkagate/src/util/api/getEtherscan.ts-15-15 (1)
15-15: Add validation for missing API key.The
ETHERSCAN_API_KEYis retrieved fromprocess.envwithout validation. If the environment variable is not set, the API calls will fail with unclear error messages. Consider adding validation and providing a helpful error message.🔎 Proposed fix
const ETHERSCAN_API_KEY = process.env['ETHERSCAN_API_KEY']; + +if (!ETHERSCAN_API_KEY) { + console.warn('ETHERSCAN_API_KEY not configured. Etherscan API calls will fail.'); +}replacements/interfaces.js-54-73 (1)
54-73: Incorrect prefix for Goerli testnet.Line 56 assigns
prefix: 5to the Goerli testnet, but Ethereum testnets should use the same SLIP-44 coin type as Ethereum mainnet, which is60. Having different prefixes for mainnet and testnets could cause issues with address derivation and network identification.🔎 Proposed fix
const evmTestChains = [ { - prefix: 5, // Goerli testnet + prefix: 60, // Ethereum SLIP-44 coin type network: "goerli", displayName: "Goerli Testnet", symbols: ["ETH"], decimals: [18], standardAccount: "0x", website: "https://goerli.net/#about" }, { prefix: 60, // Sepolia testnet network: "sepolia", displayName: "Sepolia Testnet", symbols: ["ETH"], decimals: [18], standardAccount: "0x", website: "https://sepolia.dev" } ];packages/extension-polkagate/src/util/api/getEtherscan.ts-47-72 (1)
47-72: Hardcoded ETH symbol may not work for all EVM chains.Line 56 hardcodes
asset_symbol: 'ETH', but this function is intended to support multiple EVM chains (as evidenced by theEVM_CHAIN_ID_MAP). Chains like BNB, Polygon, and Avalanche have different native tokens (BNB, MATIC, AVAX). Consider passing the token symbol as a parameter or deriving it from chain info.🔎 Proposed fix
-const convertTxToPolkaGateStyle = (transfers: EtherscanTx[], decimal: number | undefined) => { +const convertTxToPolkaGateStyle = (transfers: EtherscanTx[], decimal: number | undefined, token: string | undefined) => { return transfers.map(({ blockNumber, from, functionName, gasPrice, gasUsed, hash, isError, nonce, timeStamp, to, transactionIndex, value }) => { const _gasUsed = new BN(gasUsed); const _gasPrice = new BN(gasPrice); const feeWei = _gasUsed.mul(_gasPrice); return { amount: amountToHuman(value, decimal), - asset_symbol: 'ETH', + asset_symbol: token || 'ETH', block_num: Number(blockNumber),Then update the caller at line 118:
- transfers: convertTxToPolkaGateStyle(data.result, decimal) + transfers: convertTxToPolkaGateStyle(data.result, decimal, chainInfo?.coin)Committable suggestion skipped: line range outside the PR's diff.
packages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnRelayChain.js-21-21 (1)
21-21: Avoid mutating the inputaddressesarray.The current implementation mutates the input parameter directly, which is a side effect that could surprise callers. Consider creating a new array instead.
🔎 Proposed fix
- addresses = addresses.map((addr) => isEthereumAddress(addr) ? evmToAddress(addr) : addr); + const normalizedAddresses = addresses.map((addr) => isEthereumAddress(addr) ? evmToAddress(addr) : addr);Then update line 23 to use
normalizedAddressesinstead ofaddresses:- const { api, balanceInfo, connectionsToBeClosed } = await getBalances(chainName, addresses, userAddedEndpoints, port) ?? {}; + const { api, balanceInfo, connectionsToBeClosed } = await getBalances(chainName, normalizedAddresses, userAddedEndpoints, port) ?? {};Committable suggestion skipped: line range outside the PR's diff.
packages/extension-polkagate/src/hooks/useFetchAssetsOnChains.ts-88-105 (1)
88-105: Remove debug console.log statement.The address splitting logic is correct, but Line 95 contains a debug
console.logstatement that should be removed before merging to production.🔎 Proposed fix
if (evmAddresses?.length && isEvmChain) { - console.log(' to fetch evm chains balances:', evmAddresses?.length) const chainName = getChainName(genesisHash, genesisOptions);packages/extension-polkagate/src/fullscreen/sendFund/index.tsx-52-78 (1)
52-78: Several issues in ETH fee calculation effect.
Bug on Line 55: The condition
!RecipientAddresschecks if the imported component is falsy, which will always be truthy. This appears to be a mistake - perhaps you intended to check!to(recipient address value) instead?
ethFeeRefnever resets: OnceethFeeRef.currentis set totrueon Line 63, it's never reset. This means the ETH fee will only be calculated once per component mount. If the user changes amount, recipient, or token, the fee won't be recalculated.
@ts-ignoresuppresses type errors: The type mismatch on Line 72 should be addressed properly rather than suppressed.🔎 Proposed fix
useEffect(() => { const { amount, fee, recipientAddress: to, token } = inputs ?? {}; - if (ethFeeRef.current || fee || !address || !chainName || !isEthereumAddress(address) || !amount || !to || !token || !RecipientAddress) { + if (fee?.originFee || !address || !chainName || !isEthereumAddress(address) || !amount || !to || !token) { return; } if (Number(amount) <= 0) { return; } - ethFeeRef.current = true; - getEthFee({ chainName, from: address, to, token, value: amount }).then((res) => { - //@ts-ignore - res && setInputs((prev) => ({ + res && setInputs((prev: Inputs | undefined) => ({ ...(prev || {}), - fee: { originFee: res } + fee: { originFee: res as FeeInfo } })); }).catch(console.error); }, [address, chainName, inputs]);Note: You may need to import or define the proper type for
FeeInfoto match the expected structure.Committable suggestion skipped: line range outside the PR's diff.
🟡 Minor comments (13)
packages/extension-polkagate/src/themes/dark.ts-40-40 (1)
40-40: Remove the unusedwarning.lightcolor or implement its usage.The
warning.lightproperty at line 40 is not referenced anywhere in the codebase. Additionally, the light theme variant inlight.tsdoes not include alightproperty for the warning palette, creating an inconsistency. Either remove this property or ensure it is actively used in components/styles before merging.packages/extension-polkagate/src/components/FormatBalance2.tsx-51-56 (1)
51-56: Add defensive handling for postfix parameter.The
postfixparameter may beundefinedin edge cases (e.g., if the input value doesn't contain a decimal point), but Line 53 uses it without optional chaining while Line 55 does use optional chaining.🔎 Proposed fix for consistent null safety
function createElement(prefix: string, postfix: string, unit: string, label: LabelPost = '', isShort = false, decimalPoint: number, tokenColor?: string | undefined): React.ReactNode { - const trimmedPostfix = postfix?.replace(/0+$/, '') || ''; - const maybeTilde = postfix && parseFloat(trimmedPostfix) > parseFloat(trimmedPostfix.slice(0, decimalPoint)) ? '~' : ''; + const trimmedPostfix = postfix?.replace(/0+$/, '') ?? ''; + const maybeTilde = trimmedPostfix && parseFloat(trimmedPostfix) > parseFloat(trimmedPostfix.slice(0, decimalPoint)) ? '~' : ''; return <>{`${maybeTilde}${prefix}${isShort ? '' : '.'}`}{!isShort && <span>{`00${postfix?.slice(0, decimalPoint) || ''}`.slice(-decimalPoint)}</span>}<span style={{ color: tokenColor ?? 'inherit' }}> {unit}</span>{label}</>; }packages/extension/manifest.prod.json-2-3 (1)
2-3: Update the extension description to reflect EVM support.The description currently mentions only "Polkadot/Substrate-based blockchains," but this PR adds comprehensive Ethereum/EVM support. The description should be updated to reflect both ecosystems.
🔎 Proposed fix
- "description": "A user-friendly wallet for seamless browser-based interaction with Polkadot/Substrate-based blockchains.", + "description": "A user-friendly wallet for seamless browser-based interaction with Polkadot/Substrate and Ethereum/EVM-based blockchains.",packages/extension/manifest.dev.json-2-3 (1)
2-3: Update the extension description to reflect EVM support.The description currently mentions only "Polkadot/Substrate-based blockchains," but this PR adds comprehensive Ethereum/EVM support. The description should be updated to reflect both ecosystems.
🔎 Proposed fix
- "description": "A user-friendly wallet for seamless browser-based interaction with Polkadot/Substrate-based blockchains.", + "description": "A user-friendly wallet for seamless browser-based interaction with Polkadot/Substrate and Ethereum/EVM-based blockchains.",package.json-87-87 (1)
87-87: Update @web3icons/react to the latest stable version 4.1.12.
@web3icons/react@4.0.25is outdated; the latest stable version is4.1.12. Update this dependency to include the latest improvements and bug fixes.
react-devtools-core@7.0.1is already at the latest stable version..env.example-1-1 (1)
1-1: Verify the EXTENSION_PREFIX value change.The prefix changed from
POLKAGATEtoMY_EXTENSION, which appears to be a generic placeholder. For the PolkaGate extension, this should likely remainPOLKAGATEor use a more project-appropriate value.packages/extension-polkagate/src/util/evmUtils/ETH_CHAIN_IDS.ts-21-21 (1)
21-21: Fix typo in chain name.Line 21 contains
berachainBepoliawhich appears to be a typo. Based on the pattern of other testnet naming (e.g.,sepolia,abstractSepolia), this should likely beberachainSepolia.🔎 Proposed fix
- berachainBepolia: 80069, + berachainSepolia: 80069,packages/extension-polkagate/src/util/workers/shared-helpers/getNFTs.js-239-245 (1)
239-245: Fix the empty array check.The condition
!filteredAddressesonly catchesnullorundefined, butfilter()always returns an array. If all addresses are Ethereum addresses,filteredAddresseswill be an empty array[], which is truthy, and the function will proceed to callgetNFTs([])unnecessarily.🔎 Proposed fix
const filteredAddresses = addresses?.filter((addr) => !isEthereumAddress(addr)); - if (!filteredAddresses) { + if (!filteredAddresses || filteredAddresses.length === 0) { console.warn('Shared worker, No addresses to NFTs'); return port.postMessage(JSON.stringify({ functionName: NFT_FUNCTION_NAME, results: undefined })); }packages/extension-polkagate/src/util/evmUtils/constantsEth.ts-62-68 (1)
62-68: Inconsistent spelling: "goerli" here vs "goreli" elsewhere.Line 62 uses "goerli" (correct) while lines 9 and 14 use "goreli" (incorrect). This will cause lookup failures when trying to match chain names to ERC20 tokens.
packages/extension-polkagate/src/util/getLogo2.ts-66-66 (1)
66-66: Inconsistent spelling: "goerli" vs "goreli".This array uses "goerli" (correct spelling), but in
constantsEth.tsthe genesis hash map uses "goreli" (misspelled). This inconsistency will cause lookups to fail when matching chain names.packages/extension-polkagate/src/util/evmUtils/constantsEth.ts-9-16 (1)
9-16: Fix misspelled Goerli network name and incorrect genesis hash.The Goerli testnet is misspelled as "goreli" on lines 9 and 14, conflicting with the correct spelling "goerli" used on line 62 and in
getLogo2.tsline 66. Additionally, the current genesis hash is incorrect; the correct Goerli genesis hash is0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a.Suggested fix
-const GORELI_GENESISHASH = '0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789ab'; +const GOERLI_GENESISHASH = '0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a'; export const EVM_GENESISHASH_MAP: Record<string, string> = { ethereum: ETHEREUM_GENESISHASH, - goreli: GORELI_GENESISHASH, + goerli: GOERLI_GENESISHASH, sepolia: SEPOLIA_GENESISHASH }; export const EVM_TEST_CHAINS_GENESISHASH = [ - GORELI_GENESISHASH, + GOERLI_GENESISHASH, SEPOLIA_GENESISHASH ];Committable suggestion skipped: line range outside the PR's diff.
packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts-102-108 (1)
102-108: Remove or justify the @ts-ignore directive.The
@ts-ignorecomment on line 102 suggests a type mismatch that's being suppressed rather than resolved. This can mask real type safety issues.Please either:
- Fix the underlying type issue by ensuring
ParaspellFeescorrectly types theoriginFeeproperty- Use
@ts-expect-errorwith a comment explaining why the type mismatch is expected and safe- Adjust the fallback structure to match the expected type
🔎 Investigation needed
// Current code suppresses the error: // @ts-ignore setParaSpellState((pre) => ({ ...(pre || {}), paraSpellFee: { originFee: { fee: BN_ZERO } } }));Based on lines 92-96, the expected structure is:
paraSpellFee: { destinationFee: info.destination.xcmFee, originFee: info.origin.xcmFee }The fallback only provides
originFeewithoutdestinationFee, which may cause issues downstream.packages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnEvm.js-68-77 (1)
68-77: Zero balances are incorrectly skipped.Lines 75-77 skip processing when
balanceis falsy, which includes zero balances (0nin bigint):if (!balance) { return; }This means accounts with zero token balances won't have those tokens listed in their assets, which could confuse users or break UI assumptions.
🔎 Proposed fix
try { balance = await tokenContract['balanceOf'](addr); } catch (err) { console.warn(`Failed to fetch balanceOf for ERC-20 ${token} for ${addr} on ${chainName}:`, err?.message || err); return; } -if (!balance) { +if (balance === null || balance === undefined) { return; }This allows zero balances through while still filtering out failed fetches.
| function getFormat(decimals: number[], tokens: string[], formatIndex = 0): [number, string] { | ||
| return [ | ||
| formatIndex < decimals.length | ||
| ? decimals[formatIndex] | ||
| : decimals[0], | ||
| formatIndex < tokens.length | ||
| ? tokens[formatIndex] | ||
| : tokens[1] | ||
| ]; | ||
| } |
There was a problem hiding this comment.
Fix array bounds issue in fallback logic.
Lines 44 and 47 have potential array access issues:
- Line 44: Assumes
decimalsarray is non-empty when accessingdecimals[0] - Line 47: Assumes
tokensarray has at least 2 elements when accessingtokens[1]
If tokens has only one element, tokens[1] will be undefined, causing incorrect rendering or runtime errors.
🔎 Proposed fix
function getFormat(decimals: number[], tokens: string[], formatIndex = 0): [number, string] {
return [
formatIndex < decimals.length
? decimals[formatIndex]
: decimals[0],
formatIndex < tokens.length
? tokens[formatIndex]
- : tokens[1]
+ : tokens[0]
];
}Alternatively, add validation to ensure arrays have the expected minimum length:
function getFormat(decimals: number[], tokens: string[], formatIndex = 0): [number, string] {
if (decimals.length === 0 || tokens.length === 0) {
throw new Error('decimals and tokens arrays must not be empty');
}
return [
formatIndex < decimals.length ? decimals[formatIndex] : decimals[0],
formatIndex < tokens.length ? tokens[formatIndex] : tokens[0]
];
}🤖 Prompt for AI Agents
In @packages/extension-polkagate/src/components/FormatBalance2.tsx around lines
40 - 49, The getFormat function may access decimals[0] or tokens[1] when the
arrays are shorter than expected; validate that decimals and tokens are
non-empty at the start of getFormat (or throw a clear error) and change the
token fallback to use tokens[0] instead of tokens[1]; ensure the returned tuple
uses formatIndex if in-range otherwise decimals[0] and tokens[0] as safe
fallbacks to avoid undefined accesses.
| function splitFormat(value: string, decimalPoint: number, label?: LabelPost, isShort?: boolean): React.ReactNode { | ||
| const [prefix, postfixFull] = value.split('.'); | ||
| const [postfix, unit] = postfixFull.split(' '); | ||
|
|
||
| return createElement(prefix, postfix, unit, label, isShort, decimalPoint); | ||
| } |
There was a problem hiding this comment.
Add validation for expected string format.
Lines 59-60 assume value contains both a '.' and a ' ' character, but no validation is performed:
- If
valuehas no '.',postfixFullwill beundefined - Calling
.split(' ')onundefinedwill cause a runtime error
🔎 Proposed fix with validation
function splitFormat(value: string, decimalPoint: number, label?: LabelPost, isShort?: boolean): React.ReactNode {
const [prefix, postfixFull] = value.split('.');
+
+ if (!postfixFull) {
+ // Handle case where value doesn't contain decimal point
+ return <>{prefix}{label}</>;
+ }
+
const [postfix, unit] = postfixFull.split(' ');
return createElement(prefix, postfix, unit, label, isShort, decimalPoint);
}🤖 Prompt for AI Agents
In @packages/extension-polkagate/src/components/FormatBalance2.tsx around lines
58 - 63, splitFormat assumes value contains both '.' and a space which can cause
a runtime error when postfixFull is undefined; add validation in splitFormat to
safely handle malformed input by checking that value includes a '.' before
splitting and that postfixFull is defined before calling split(' '), providing
sensible fallbacks (e.g., postfix = '' and unit = '') or returning a safe
default React node; ensure createElement(prefix, postfix, unit, label, isShort,
decimalPoint) always receives defined strings and preserve existing behavior for
valid inputs.
| console.log('Signature:', signature); | ||
| console.log('payload', payload); | ||
| console.log('signer', from); | ||
| const check = signatureVerify(String(payload), signature, from); | ||
|
|
||
| console.log('signatureVerify result:', check); |
There was a problem hiding this comment.
Critical: Signature verification result is ignored, and type conversion is incorrect.
The code computes a signature verification but never uses the result. The transaction proceeds to extrinsic.addSignature() on line 149 regardless of whether verification passes or fails, making this check ineffective.
Additionally, the type conversion String(payload) is incorrect when payload is of type ExtrinsicPayloadValue (an object). Converting an object with String() produces "[object Object]", which will always fail verification. The payload parameter has the union type Uint8Array | ExtrinsicPayloadValue | HexString, so this code path will produce incorrect results for object payloads.
Security & debugging concerns:
- Logging the signature and payload (lines 142-143) exposes sensitive cryptographic material in console logs.
- These changes appear unrelated to the PR objective (EVM chain support) and may be leftover debug code.
🔎 Proposed resolution
If signature verification is intended: Check the result and handle failures appropriately:
- console.log('✈️ Sending the transaction ...');
- console.log('Signature:', signature);
- console.log('payload', payload);
- console.log('signer', from);
- const check = signatureVerify(String(payload), signature, from);
-
- console.log('signatureVerify result:', check);
+ console.log('✈️ Sending the transaction ...');
+
+ // Verify signature before submission
+ const payloadToVerify = payload instanceof Uint8Array ? payload :
+ typeof payload === 'string' ? payload :
+ extrinsic.toU8a();
+ const check = signatureVerify(payloadToVerify, signature, from);
+
+ if (!check.isValid) {
+ console.error('❌ Invalid signature detected');
+ resolve({ block: 0, failureText: 'Invalid signature', fee: '', success: false, txHash: '' });
+ return;
+ }If this is debug code: Remove the verification and sensitive logging entirely:
console.log('✈️ Sending the transaction ...');
- console.log('Signature:', signature);
- console.log('payload', payload);
- console.log('signer', from);
- const check = signatureVerify(String(payload), signature, from);
-
- console.log('signatureVerify result:', check);
extrinsic.addSignature(from, signature, payload);Committable suggestion skipped: line range outside the PR's diff.
| } | ||
|
|
||
| return found; | ||
| return found as unknown as NetworkInfo; |
There was a problem hiding this comment.
Unsafe type assertion returns undefined as NetworkInfo.
The type assertion as unknown as NetworkInfo forces TypeScript to accept undefined as NetworkInfo when no matching chain is found. This violates type safety and can cause runtime errors in calling code that expects a valid NetworkInfo object.
🔎 Proposed fix
- return found as unknown as NetworkInfo;
+ return found;The function signature already declares NetworkInfo | undefined as the return type, so the type assertion is unnecessary. Simply return found directly.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return found as unknown as NetworkInfo; | |
| return found; |
🤖 Prompt for AI Agents
In @packages/extension-polkagate/src/util/getChain.ts at line 22, The return
uses an unsafe assertion "found as unknown as NetworkInfo" allowing undefined to
be treated as NetworkInfo; instead return the variable found directly (remove
the double-cast) so the function respects its declared return type NetworkInfo |
undefined—locate the found variable and the return statement in getChain (the
line returning found as unknown as NetworkInfo) and replace it with a plain
return found.
| const polkagateAddedGenesisHashes = { | ||
| ethereum: '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3', | ||
| goerli: '0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789ab', | ||
| sepolia: '0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9' | ||
| }; | ||
|
|
||
| const assetHubs = [{ | ||
| "prefix": 42, | ||
| "network": "westmint", | ||
| "displayName": "Westend Asset Hub", | ||
| "symbols": ["WND"], | ||
| "decimals": [12], | ||
| "standardAccount": "*25519", | ||
| "website": "https://polkadot.network" | ||
| }, | ||
| { | ||
| "prefix": 2, | ||
| "network": "statemine", | ||
| "displayName": "Kusama Asset Hub", | ||
| "symbols": ["KSM"], | ||
| "decimals": [12], | ||
| "standardAccount": "*25519", | ||
| "website": "https://kusama.network" | ||
| }, | ||
| { | ||
| "prefix": 0, | ||
| "network": "statemint", | ||
| "displayName": "Polkadot Asset Hub", | ||
| "symbols": ["DOT"], | ||
| "decimals": [10], | ||
| "standardAccount": "*25519", | ||
| "website": "https://polkadot.network" | ||
| }, | ||
| { | ||
| "prefix": 0, | ||
| "network": "paseoAssetHub", | ||
| "displayName": "Paseo Asset Hub", | ||
| "symbols": ["PAS"], | ||
| "decimals": [10], | ||
| "standardAccount": "*25519", | ||
| "website": "https://polkadot.network" | ||
| }]; | ||
| Object.entries(polkagateAddedGenesisHashes).forEach(([key, hash]) => (knownGenesis[key] = [hash])); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Ethereum mainnet genesis hash block 0
💡 Result:
Ethereum mainnet genesis (block 0) hash: 0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3. [1][2]
Genesis block mined: July 30, 2015. To fetch locally: eth.getBlock(0). [2][3]
Sources:
- Ethereum genesis/hash discussion. [1]
- Ethereum Foundation blog / genesis details. [2]
- Example showing eth.getBlock(0) output. [3]
🌐 Web query:
Goerli testnet genesis hash block 0
💡 Result:
Goerli (Görli) genesis block (block 0) hash: 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a. [1]
Source: eth-clients Goerli testnet metadata. [1]
🌐 Web query:
Sepolia testnet genesis hash block 0
💡 Result:
Do you mean the on-chain block 0 hash (genesis block hash) for Sepolia, or the genesis.json file contents (e.g., the chain genesis configuration)?
🌐 Web query:
Sepolia testnet block 0 genesis hash 0x25a5cc
💡 Result:
Short answer: No — Sepolia's genesis (block 0) is not 0x25a5cc.
Authoritative values from the eth-clients sepolia repo:
- Eth1 deposit block hash (used in genesis eth1_data.block_hash): 0x491ebac1b7f9c0eb426047a495dc577140cb3e09036cd3f7266eda86b635d9fa. [1]
- Beacon-chain initial state root / genesis state (Initial State Root): 0xfb9afe32150fa39f4b346be2519a67e2a4f5efcd50a1dc192c3f6b3d013d2798. [1]
- Genesis block root (two variants shown in repo): 0xeade62f0457b2fdf48e7d3fc4b60736688286be7c7a3ac4c9a16a5e0600bd9e4 (without state-root update) and 0xfb9b64fe445f76696407e1e3cc390371edff147bf712db86db6197d4b31ede43 (with state-root update). [1]
Source: eth-clients/sepolia GitHub repository (Sepolia testnet configuration). [1]
If you want, I can look up the exact block-0 record on a block explorer (Etherscan/Sepolia scan) and paste its displayed hash.
🌐 Web query:
Sepolia chain ID genesis block hash explorers
💡 Result:
- Chain ID (Ethereum Sepolia): 11155111. [1][2]
- Genesis block hash (Sepolia): 0x25a5cc106…8993e6dd9 (commonly shown truncated in docs). [1][3]
- Common Sepolia explorers:
- Sepolia Etherscan — https://sepolia.etherscan.io. [2]
- Sepolia Otterscan — https://sepolia.otterscan.io. [0]
- Routescan (testnet view) — https://11155111.testnet.routescan.io. [0]
- Other providers (APIs/RPCs): Alchemy, Infura, Ankr, public RPCs (see Sepolia resources). [2][3]
Sources: [1] sepolia.dev (Sepolia resources), [2] Chain-List / Alchemy Sepolia pages, [3] Alchemy overview for Sepolia.
Fix incorrect Goerli genesis hash.
The Goerli genesis hash is incorrect. The code contains 0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789ab, but the correct Goerli genesis hash (block 0) is 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a. This incorrect value will cause Goerli chain identification to fail. The Ethereum mainnet and Sepolia hashes are correct.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI Agents
In @package.json:
- Around line 60-62: package.json lists @ethersproject/bytes,
@ethersproject/keccak256, and @ethersproject/transactions at v5.8.0 while the
repo uses ethers v6.15.0, causing v5/v6 conflicts; choose one strategy:
(recommended) remove the three "@ethersproject/*" dependencies and update code
to import utilities (e.g., keccak256, byte helpers) from "ethers" v6, or
alternatively downgrade "ethers" to a v5.x release to keep the @ethersproject v5
packages; update package.json accordingly and adjust all imports that reference
'@ethersproject/keccak256', '@ethersproject/bytes',
'@ethersproject/transactions' to the appropriate "ethers" v6 APIs (or to
v5-compatible imports if you downgrade).
🧹 Nitpick comments (1)
package.json (1)
50-50: Consider using dev manifest for watch mode.The watch script copies the production manifest before starting webpack watch. Since watch mode is typically used during development, consider using
copy-dev-manifestinstead to ensure the development manifest is active.🔎 Proposed fix
- "watch": "yarn copy-prod-manifest && cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch" + "watch": "yarn copy-dev-manifest && cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch"
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Analyze (javascript)
- GitHub Check: build
🔇 Additional comments (1)
package.json (1)
60-62: Verify dependency versions and security advisories.Ensure the added dependencies are using secure, compatible versions and check for any known vulnerabilities:
@ethersproject/bytes@^5.8.0@ethersproject/keccak256@^5.8.0@ethersproject/transactions@^5.8.0@web3icons/react@^4.0.25ethers@^6.15.0react-devtools-core@^7.0.1#!/bin/bash # Verify latest versions and security advisories for new dependencies echo "=== Checking latest versions ===" for pkg in "@ethersproject/bytes" "@ethersproject/keccak256" "@ethersproject/transactions" "ethers" "@web3icons/react" "react-devtools-core"; do echo "Package: $pkg" npm view "$pkg" version 2>/dev/null || echo " Could not fetch version" done echo -e "\n=== Checking for security advisories ===" for pkg in "ethersproject/bytes" "ethersproject/keccak256" "ethersproject/transactions" "ethers" "web3icons/react" "react-devtools-core"; do echo "Checking: $pkg" gh api graphql -f query=" { securityVulnerabilities(first: 5, ecosystem: NPM, package: \"${pkg}\") { nodes { advisory { summary severity publishedAt } vulnerableVersionRange firstPatchedVersion { identifier } } } }" 2>/dev/null | jq -r '.data.securityVulnerabilities.nodes[] | " [\(.advisory.severity)] \(.advisory.summary) | Vulnerable: \(.vulnerableVersionRange) | Patched: \(.firstPatchedVersion.identifier // "N/A")"' || echo " No advisories found or error occurred" doneAlso applies to: 87-87, 96-96, 138-138
| "@ethersproject/bytes": "^5.8.0", | ||
| "@ethersproject/keccak256": "^5.8.0", | ||
| "@ethersproject/transactions": "^5.8.0", |
There was a problem hiding this comment.
Resolve ethers version conflict.
The project is mixing ethers v6.15.0 with @ethersproject/* packages at v5.8.0. Ethers v6 is a complete rewrite that internalized all @ethersproject packages with breaking changes. Using both versions simultaneously creates:
- Duplicate functionality and increased bundle size
- API inconsistencies (v5 vs v6 have different interfaces)
- Potential runtime conflicts
- Developer confusion about which version to import
Choose one strategy:
- Option 1 (recommended): Use
ethersv6 exclusively and remove the@ethersproject/*v5 packages. Ethers v6 includes all necessary utilities internally. - Option 2: Use
ethersv5 alongside@ethersproject/*v5 packages (requires downgrading ethers to v5.x).
🔎 Recommended fix (Option 1)
- "@ethersproject/bytes": "^5.8.0",
- "@ethersproject/keccak256": "^5.8.0",
- "@ethersproject/transactions": "^5.8.0",
"@lottiefiles/dotlottie-react": "^0.17.5",Then import from ethers v6 instead:
// Before (v5):
import { keccak256 } from '@ethersproject/keccak256';
import { arrayify } from '@ethersproject/bytes';
// After (v6):
import { keccak256, getBytes } from 'ethers';Also applies to: 96-96
🤖 Prompt for AI Agents
In @package.json around lines 60 - 62, package.json lists @ethersproject/bytes,
@ethersproject/keccak256, and @ethersproject/transactions at v5.8.0 while the
repo uses ethers v6.15.0, causing v5/v6 conflicts; choose one strategy:
(recommended) remove the three "@ethersproject/*" dependencies and update code
to import utilities (e.g., keccak256, byte helpers) from "ethers" v6, or
alternatively downgrade "ethers" to a v5.x release to keep the @ethersproject v5
packages; update package.json accordingly and adjust all imports that reference
'@ethersproject/keccak256', '@ethersproject/bytes',
'@ethersproject/transactions' to the appropriate "ethers" v6 APIs (or to
v5-compatible imports if you downgrade).
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @packages/extension-polkagate/src/util/evmUtils/constantsEth.ts:
- Around line 49-69: The ERC20_TOKENS object has a naming inconsistency for the
Goerli testnet key (mistyped as "goreli"); update the key to "goerli" so it
matches references elsewhere (e.g., EVM_GENESISHASH_MAP,
getLogo2/getEthProvider) and ensure the nested entry remains USDC with its
existing contract, icon, and empty priceId; verify no other occurrences of
"goreli" remain in ERC20_TOKENS or related constants.
- Line 9: The constant name GORELI_GENESISHASH is misspelled and its value is an
invalid placeholder; rename the identifier to GOERLI_GENESISHASH and replace its
value with the official Goerli genesis hash
0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a so chain
identification and lookups (e.g., where ERC20_TOKENS uses the goerli key)
resolve correctly.
🧹 Nitpick comments (2)
packages/extension-polkagate/src/util/evmUtils/constantsEth.ts (2)
34-39: Consider whether additional ERC20 methods are needed.The ABI includes the essential methods for balance queries and basic transfers. However, standard ERC20 tokens also include
approve,transferFrom, andallowancemethods which enable delegated transfers and are commonly used in DeFi interactions.If the extension will support more complex ERC20 interactions beyond simple transfers, consider expanding the ABI.
📝 Extended ERC20 ABI (if needed)
export const ERC20_ABI = [ 'function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)', 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function totalSupply() view returns (uint256)', + 'function allowance(address owner, address spender) view returns (uint256)', + 'function approve(address spender, uint256 amount) returns (bool)', 'function transfer(address to, uint256 amount) returns (bool)', + 'function transferFrom(address from, address to, uint256 amount) returns (bool)' ];
41-45: Consider tightening the icon type for better type safety.The
iconproperty usesReact.ComponentType<any>which is less type-safe than theReact.ComponentType<{ size: number }>used inTOKEN_MAP.🔧 Proposed type improvement
interface TokenInfo { contract: string; - icon: React.ComponentType<any>; + icon: React.ComponentType<{ size: number }>; priceId: string; }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/extension-polkagate/src/util/constants.tspackages/extension-polkagate/src/util/evmUtils/constantsEth.tspackages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnRelayChain.js
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/extension-polkagate/src/util/workers/shared-helpers/getAssetOnRelayChain.js
🧰 Additional context used
🧬 Code graph analysis (1)
packages/extension-polkagate/src/util/constants.ts (1)
packages/extension-polkagate/src/util/evmUtils/constantsEth.ts (1)
ETHEREUM_TEST_CHAINS_GENESISHASH(18-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Analyze (javascript)
- GitHub Check: build
🔇 Additional comments (7)
packages/extension-polkagate/src/util/constants.ts (4)
6-7: LGTM!The import is correctly structured and the imported constant is properly used in
TEST_NETS.
79-86: LGTM!Good refactoring to extract Polkadot test nets into a named constant. This improves clarity and maintainability.
88-92: LGTM!The composition of
TEST_NETScorrectly combines both Polkadot and Ethereum test networks to support the new EVM functionality.
348-353: LGTM!The EVM entry follows the established pattern and integrates cleanly with the existing asset fetching function names.
packages/extension-polkagate/src/util/evmUtils/constantsEth.ts (3)
1-6: LGTM!Imports are correctly structured with proper type-only import for React and icon components from
@web3icons/react.
18-26: Array composition is correct, pending genesis hash fixes.The structure and composition of these arrays is sound. However, the validity depends on resolving the
GORELI_GENESISHASHissues flagged above.
28-32: LGTM!The
TOKEN_MAPis well-typed and correctly maps token symbols to their React icon components with the appropriate prop interface.
| import { TokenETH, TokenUSDC, TokenUSDT } from '@web3icons/react'; | ||
|
|
||
| export const ETHEREUM_GENESISHASH = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'; | ||
| const GORELI_GENESISHASH = '0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789ab'; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the file mentioned in the review
fd -t f "constantsEth.ts" -x cat -n {}Repository: PolkaGate/extension
Length of output: 2443
🏁 Script executed:
# Search for all references to GORELI/GOERLI in the codebase
rg -in "goreli" --type ts | head -30Repository: PolkaGate/extension
Length of output: 668
🏁 Script executed:
# Check the EVM_GENESISHASH_MAP and related code around lines 9-19
fd -t f "constantsEth.ts" -x sed -n '1,30p' {}Repository: PolkaGate/extension
Length of output: 1063
🌐 Web query:
Goerli Ethereum testnet genesis hash official
💡 Result:
Official Goerli genesis block hash: 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a. [1]
Sources:
[1] eth-clients/goerli (Goerli testnet configuration).
🌐 Web query:
Ethereum Goerli genesis block hash 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a
💡 Result:
Yes — the Goerli testnet genesis block hash is 0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a. [1]
Sources:
[1] eth-clients/goerli (Goerli metadata, genesis hash).
🏁 Script executed:
# Check if there are any tests or configurations that validate these hash values
fd -t f -e ts -e json -e config | xargs rg -l "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3|0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9" | head -10Repository: PolkaGate/extension
Length of output: 125
🏁 Script executed:
# Check how this constant is used in the codebase
rg -B3 -A3 "ETHEREUM_TEST_CHAINS_GENESISHASH|EVM_GENESISHASH_MAP" --type ts | head -50Repository: PolkaGate/extension
Length of output: 3025
Fix the Goerli constant name and correct the invalid genesis hash.
Line 9 contains two critical issues:
-
Misspelled constant name:
GORELI_GENESISHASHis missing the 'e' — the correct spelling isGOERLI_GENESISHASH. This creates an inconsistency with line 62 whereERC20_TOKENSusesgoerlias the key. -
Incorrect genesis hash: The value
0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789abis invalid. The pattern ending in123456789abappears to be a placeholder. The official Goerli genesis hash is0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a.
This impacts chain identification logic and will cause failures when validating Goerli transactions or blocks.
Required fixes
-const GORELI_GENESISHASH = '0x5fbe6b8f0e9b91f8c5c88ee6f7a3b7f7d05c1e71f6e4c4c1c6e8c123456789ab';
+const GOERLI_GENESISHASH = '0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a';Update line 14:
export const EVM_GENESISHASH_MAP: Record<string, string> = {
ethereum: ETHEREUM_GENESISHASH,
- goreli: GORELI_GENESISHASH,
+ goerli: GOERLI_GENESISHASH,
sepolia: SEPOLIA_GENESISHASH
};Update line 19:
export const ETHEREUM_TEST_CHAINS_GENESISHASH = [
- GORELI_GENESISHASH,
+ GOERLI_GENESISHASH,
SEPOLIA_GENESISHASH
];Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @packages/extension-polkagate/src/util/evmUtils/constantsEth.ts at line 9,
The constant name GORELI_GENESISHASH is misspelled and its value is an invalid
placeholder; rename the identifier to GOERLI_GENESISHASH and replace its value
with the official Goerli genesis hash
0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a so chain
identification and lookups (e.g., where ERC20_TOKENS uses the goerli key)
resolve correctly.
| export const ERC20_TOKENS: ERC20_TOKENS_TYPE = { | ||
| ethereum: { | ||
| USDC: { | ||
| contract: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', | ||
| icon: TokenUSDC, | ||
| priceId: 'usd-coin' | ||
| }, | ||
| USDT: { | ||
| contract: '0xdAC17F958D2ee523a2206206994597C13D831ec7', | ||
| icon: TokenUSDT, | ||
| priceId: 'tether' | ||
| } | ||
| }, | ||
| goerli: { | ||
| USDC: { | ||
| contract: '0x07865c6e87b9f70255377e024ace6630c1eaa37f', | ||
| icon: TokenUSDC, | ||
| priceId: '' | ||
| } | ||
| } | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/extension-polkagate/src/util/evmUtils/constantsEth.ts | head -80Repository: PolkaGate/extension
Length of output: 2443
🌐 Web query:
What are the official Ethereum mainnet contract addresses for USDC and USDT tokens?
💡 Result:
-
USDC (Ethereum mainnet): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48. [1][2]
-
USDT (Ethereum mainnet): 0xdAC17F958D2ee523a2206206994597C13D831ec7. [3]
Sources:
[1] Circle — USDC contract addresses.
[2] Etherscan — Circle: USDC token contract.
[3] Etherscan — Tether: USDT token contract.
🏁 Script executed:
# Check for references to goerli and goreli in the codebase
rg -ni "go[e]?rli" --type ts packages/extension-polkagate/src/Repository: PolkaGate/extension
Length of output: 487
🌐 Web query:
What is the official Goerli testnet contract address for USDC token?
💡 Result:
The Goerli USDC contract address is: 0x07865c6E87B9F70255377e024ace6630C1Eaa37F. [1][2][3]
Sources:
- Swing docs (lists USDC on Goerli). [1]
- Zenland docs (lists Goerli USDC address). [2]
- Payb.is supported-assets list (USDC-GOERLI). [3]
Fix goerli/goreli naming inconsistency.
The naming inconsistency is confirmed: Line 14 uses goreli: while line 62 uses goerli:. This must be corrected for consistency across the codebase, as other files (getLogo2.ts, getEthProvider.ts) reference goerli. Ensure the key in ERC20_TOKENS aligns with EVM_GENESISHASH_MAP.
All contract addresses are verified as correct:
- USDC (mainnet):
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 - USDT (mainnet):
0xdAC17F958D2ee523a2206206994597C13D831ec7 - USDC (Goerli):
0x07865c6e87b9f70255377e024ace6630c1eaa37f
The empty priceId on line 66 for testnet USDC is intentional—testnet tokens lack market prices.
🤖 Prompt for AI Agents
In @packages/extension-polkagate/src/util/evmUtils/constantsEth.ts around lines
49 - 69, The ERC20_TOKENS object has a naming inconsistency for the Goerli
testnet key (mistyped as "goreli"); update the key to "goerli" so it matches
references elsewhere (e.g., EVM_GENESISHASH_MAP, getLogo2/getEthProvider) and
ensure the nested entry remains USDC with its existing contract, icon, and empty
priceId; verify no other occurrences of "goreli" remain in ERC20_TOKENS or
related constants.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/extension-polkagate/src/fullscreen/components/AccountListModal.tsx (1)
75-149: Fix chain filtering to avoid empty list and broken section headers
Whenchainis undefined,isEvmChainisundefined, so the current inline filter (isEvmChain !== (account.type === 'ethereum')) hides all accounts. Also, filtering inside themapbreaksisFirstAccount/isLastand can suppress section headers, whileNothingFoundand the Apply button still rely on unfiltered counts. Consider filtering by chain infilteredCategorizedAccountsand only when chain type is known, then remove the inlineifinside the map.✅ Suggested fix (move chain filter into memo)
- const filteredCategorizedAccounts = useMemo(() => { - if (!searchKeyword) { - return categorizedAccounts; - } - - const keywordLower = searchKeyword.toLowerCase(); - - return Object.entries(categorizedAccounts).reduce((acc, [label, accounts]) => { - const filteredAccounts = accounts.filter((account) => - account.name?.toLowerCase().includes(keywordLower) || - account.address.toLowerCase().includes(keywordLower) - ); - - if (filteredAccounts.length > 0) { - acc[label] = filteredAccounts; - } - - return acc; - }, {} as Record<string, AccountJson[]>); - }, [categorizedAccounts, searchKeyword]); + const filteredCategorizedAccounts = useMemo(() => { + const keywordLower = searchKeyword?.toLowerCase(); + const hasChainType = !!chain?.definition?.chainType; + + return Object.entries(categorizedAccounts).reduce((acc, [label, accounts]) => { + const chainFiltered = hasChainType + ? accounts.filter((account) => (account.type === 'ethereum') === isEvmChain) + : accounts; + + const filteredAccounts = keywordLower + ? chainFiltered.filter((account) => + account.name?.toLowerCase().includes(keywordLower) || + account.address.toLowerCase().includes(keywordLower) + ) + : chainFiltered; + + if (filteredAccounts.length > 0) { + acc[label] = filteredAccounts; + } + + return acc; + }, {} as Record<string, AccountJson[]>); + }, [categorizedAccounts, searchKeyword, isEvmChain, chain?.definition?.chainType]);- {accounts.map((account, accIndex) => { + {accounts.map((account, accIndex) => { const isFirstProfile = profileIndex === 0; const isFirstAccount = accIndex === 0; const isLast = accIndex === accounts.length - 1; - - if (isEvmChain !== (account.type === 'ethereum')) { - return null; - }packages/extension-polkagate/src/fullscreen/sendFund/index.tsx (1)
257-280: Addcall: undefinedto RESET_INPUTS to prevent stale transaction signing.The
callfield is not cleared in the RESET_INPUTS object (index.tsx:109-118), but it persists in the Inputs state and is reused as a fallback at line 280. When sender or network changes, onReset is triggered (index.tsx:132-138), but it fails to clear the previouscall, creating a window where the SignArea could use an outdated transaction before Step3Amount recomputes it.Required fix
const RESET_INPUTS: Partial<Inputs> = { amount: undefined, amountAsBN: undefined, fee: undefined, feeInfo: undefined, paraSpellTransaction: undefined, + call: undefined, recipientAddress: undefined, recipientChain: undefined, recipientGenesisHashOrParaId: undefined };
🤖 Fix all issues with AI agents
In `@packages/extension-polkagate/src/components/AddressInput.tsx`:
- Around line 57-75: When resetting or switching away from EVM addresses, clear
the previously set account type: update onReset (used to clear the input) to
also call setType?.(undefined) and include setType in its dependency array, and
update onSet to call setType?.('ethereum') when isEvm is true and call
setType?.(undefined) when isEvm is false so non‑EVM inputs don't leave the
parent stuck on 'ethereum'; reference the onReset and onSet callbacks and the
setType setter in your changes.
🧹 Nitpick comments (3)
packages/extension-polkagate/src/fullscreen/sendFund/partials/RecipientAddress.tsx (1)
33-42: Verify edge case whenrecipientChain.valueis undefined.The reset logic correctly clears the address when the chain changes. However, if
inputs?.recipientChain?.valueisundefinedwhilegenesisHashis defined, the condition evaluates totrueand resets the address—even on initial render or before the recipient chain is set. Please verify this is the intended behavior.Also, minor inconsistency: local state is set to
nullwhilerecipientAddressis set toundefined. Consider aligning these for consistency:♻️ Suggested consistency fix
useEffect(() => { if (genesisHash && genesisHash !== inputs?.recipientChain?.value) { - setAddress(null); + setAddress(undefined); setInputs((prevInputs) => ({ ...(prevInputs || {}), recipientAddress: undefined })); } }, [genesisHash, inputs?.recipientChain?.value, setInputs]);,
packages/extension-polkagate/src/util/api/getTransfers.ts (1)
9-17: Avoid exporting a mutable singleton fornullObject.Now that this is public, any consumer can mutate it; since
getTxTransfersreturns the same reference, a single mutation can taint all future results. Consider freezing and returning a clone (or expose a factory) to prevent shared-state bugs.♻️ Proposed fix (immutable + clone)
-export const nullObject = { - code: 0, - data: { - count: 0, - transfers: null - }, - generated_at: Date.now(), - message: 'Failed' -} as unknown as TransferRequest; +export const nullObject = Object.freeze({ + code: 0, + data: Object.freeze({ + count: 0, + transfers: null + }), + generated_at: Date.now(), + message: 'Failed' +}) as Readonly<TransferRequest>; + +const cloneNullTransfer = (): TransferRequest => ({ + ...nullObject, + data: { ...nullObject.data } +});- return (await Promise.resolve(nullObject)); + return (await Promise.resolve(cloneNullTransfer()));- return (await Promise.resolve(nullObject)); + return (await Promise.resolve(cloneNullTransfer()));packages/extension-polkagate/src/fullscreen/sendFund/index.tsx (1)
31-75: Consider removing the commented‑out ETH fee block or gating it.Leaving large commented sections in production code makes the flow harder to reason about. If this is future work, consider a feature flag or a tracked TODO; otherwise, delete it.
🧹 Optional cleanup
- // const ethFeeRef = useRef<boolean>(false); ... - // useEffect(() => { - // const { amount, fee, recipientAddress: to, token } = inputs ?? {}; - // ... - // }, [address, chainName, inputs]);
| const onReset = useCallback((): void => { | ||
| setAddress?.(null); | ||
| setEnteredAddress(undefined); | ||
| setInvalidAddress(false); | ||
| }, [setAddress]); | ||
|
|
||
| const onSet = useCallback((value: string): void => { | ||
| const isEvm = isEthereumAddress(value); | ||
|
|
||
| isEvm && setType?.('ethereum'); | ||
| const isValid = isValidAddress(value); | ||
|
|
||
| isValid | ||
| ? setAddress?.(value) | ||
| : setAddress?.(undefined); | ||
|
|
||
| setEnteredAddress(value); | ||
| setInvalidAddress(!isValid); | ||
| }, [setAddress, setType]); |
There was a problem hiding this comment.
Clear stale setType when input resets or switches away from EVM.
After an EVM address is entered, setType is never cleared. If the user clears the field or enters a non‑EVM address, the parent can remain stuck on ethereum, which can mis-route account‑type handling.
🛠️ Proposed fix
- const onReset = useCallback((): void => {
- setAddress?.(null);
- setEnteredAddress(undefined);
- setInvalidAddress(false);
- }, [setAddress]);
+ const onReset = useCallback((): void => {
+ setAddress?.(null);
+ setEnteredAddress(undefined);
+ setInvalidAddress(false);
+ setType?.((prev) => (prev === 'ethereum' ? undefined : prev));
+ }, [setAddress, setType]);
const onSet = useCallback((value: string): void => {
const isEvm = isEthereumAddress(value);
- isEvm && setType?.('ethereum');
+ setType?.((prev) => (isEvm ? 'ethereum' : prev === 'ethereum' ? undefined : prev));
const isValid = isValidAddress(value);🤖 Prompt for AI Agents
In `@packages/extension-polkagate/src/components/AddressInput.tsx` around lines 57
- 75, When resetting or switching away from EVM addresses, clear the previously
set account type: update onReset (used to clear the input) to also call
setType?.(undefined) and include setType in its dependency array, and update
onSet to call setType?.('ethereum') when isEvm is true and call
setType?.(undefined) when isEvm is false so non‑EVM inputs don't leave the
parent stuck on 'ethereum'; reference the onReset and onSet callbacks and the
setType setter in your changes.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@package.json`:
- Line 50: The "watch" npm script currently runs the production manifest copy
("copy-prod-manifest") which makes development runs inconsistent with "start"
and "build:dev"; update the "watch" script to use the development manifest step
(replace "copy-prod-manifest" with the dev manifest command or make it
conditional) so that the "watch" script aligns with NODE_ENV=development and
"build:dev" behavior; ensure you update the script named "watch" in package.json
and verify there is a corresponding dev manifest copy task (or add one) rather
than invoking "copy-prod-manifest".
In `@packages/extension-polkagate/src/popup/receive/Receive.tsx`:
- Around line 95-100: Add a useEffect in Receive.tsx that watches the networks
value and updates chainsToShow via setChainsToShow when networks change so the
dropdown reflects updated options from useGenesisHashOptions; e.g., inside the
Receive component add a useEffect(() => setChainsToShow(networks), [networks])
to keep chainsToShow in sync with networks (ensure this complements the existing
onSearch logic).
In `@packages/extension-polkagate/src/util/api/signAndSend.ts`:
- Line 16: The import signatureVerify from '@polkadot/util-crypto' in
signAndSend.ts is unused and causing a TS6133 build error; remove the unused
import statement (the "signatureVerify" specifier) from the import line in
packages/extension-polkagate/src/util/api/signAndSend.ts so the file only
imports what is actually used.
🧹 Nitpick comments (2)
packages/extension-polkagate/src/popup/receive/Receive.tsx (2)
93-94: Avoid mutating hook output with in‑place sort.
Array.sort()mutatesallChains, which can produce unexpected ordering side effects. Prefer sorting a copy.♻️ Suggested change
- const networks = useMemo(() => allChains.sort(customSort), [allChains, customSort]); + const networks = useMemo(() => [...allChains].sort(customSort), [allChains, customSort]);
239-245: Remove or update the stale commented Ethereum auto‑select block.It still references the old
NetworkInfoshape, which can confuse future edits. Consider deleting or updating it to the new DropdownOption format.
| "test": "polkadot-dev-run-test --silent --detectOpenHandles --testPathPattern=packages/extension-polkagate/src --maxWorkers=1", | ||
| "test:one": "polkadot-dev-run-test --detectOpenHandles", | ||
| "watch": "cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch" | ||
| "watch": "yarn copy-prod-manifest && cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch" |
There was a problem hiding this comment.
Use the dev manifest for the watch flow.
start runs with NODE_ENV=development, but watch copies the prod manifest, which can mask dev-only permissions or URLs and makes dev behavior inconsistent with build:dev. Consider switching to the dev manifest (or make it conditional).
Proposed fix
- "watch": "yarn copy-prod-manifest && cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch"
+ "watch": "yarn copy-dev-manifest && cd packages/extension && yarn polkadot-exec-webpack --config webpack.watch.cjs --mode development --watch"🤖 Prompt for AI Agents
In `@package.json` at line 50, The "watch" npm script currently runs the
production manifest copy ("copy-prod-manifest") which makes development runs
inconsistent with "start" and "build:dev"; update the "watch" script to use the
development manifest step (replace "copy-prod-manifest" with the dev manifest
command or make it conditional) so that the "watch" script aligns with
NODE_ENV=development and "build:dev" behavior; ensure you update the script
named "watch" in package.json and verify there is a corresponding dev manifest
copy task (or add one) rather than invoking "copy-prod-manifest".
| const [chainsToShow, setChainsToShow] = useState<DropdownOption[]>(networks); | ||
|
|
||
| const onSearch = useCallback((keyword: string) => { | ||
| if (!keyword) { | ||
| return setChainsToShow(networks); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat packages/extension-polkagate/src/popup/receive/Receive.tsx | head -150Repository: PolkaGate/extension
Length of output: 6066
🏁 Script executed:
fd -t f 'useGenesisHashOptions' --exec grep -l "useGenesisHashOptions" {} \; | head -5Repository: PolkaGate/extension
Length of output: 128
🏁 Script executed:
cat packages/extension-polkagate/src/hooks/useGenesisHashOptions.tsRepository: PolkaGate/extension
Length of output: 2553
🏁 Script executed:
# Check if there are any other useEffect hooks in the Receive.tsx component that might handle this
cat packages/extension-polkagate/src/popup/receive/Receive.tsx | grep -n "useEffect\|useState\|networks"Repository: PolkaGate/extension
Length of output: 689
Add useEffect to sync chainsToShow when networks changes.
When useGenesisHashOptions updates (e.g., metadata/testnet toggle), the displayed chain list becomes stale until the user performs a new search. Without a sync effect, chainsToShow will not reflect the latest network options.
🛠️ Suggested fix
-import React, { useCallback, useMemo, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
@@
const [chainsToShow, setChainsToShow] = useState<DropdownOption[]>(networks);
+
+ useEffect(() => {
+ setChainsToShow(networks);
+ }, [networks]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const [chainsToShow, setChainsToShow] = useState<DropdownOption[]>(networks); | |
| const onSearch = useCallback((keyword: string) => { | |
| if (!keyword) { | |
| return setChainsToShow(networks); | |
| } | |
| import React, { useCallback, useEffect, useMemo, useState } from 'react'; | |
| const [chainsToShow, setChainsToShow] = useState<DropdownOption[]>(networks); | |
| useEffect(() => { | |
| setChainsToShow(networks); | |
| }, [networks]); | |
| const onSearch = useCallback((keyword: string) => { | |
| if (!keyword) { | |
| return setChainsToShow(networks); | |
| } |
🤖 Prompt for AI Agents
In `@packages/extension-polkagate/src/popup/receive/Receive.tsx` around lines 95 -
100, Add a useEffect in Receive.tsx that watches the networks value and updates
chainsToShow via setChainsToShow when networks change so the dropdown reflects
updated options from useGenesisHashOptions; e.g., inside the Receive component
add a useEffect(() => setChainsToShow(networks), [networks]) to keep
chainsToShow in sync with networks (ensure this complements the existing
onSearch logic).
| import type { HexString } from '@polkadot/util/types'; | ||
| import type { TxResult } from '../types'; | ||
|
|
||
| import { signatureVerify } from '@polkadot/util-crypto'; |
There was a problem hiding this comment.
Fix build-breaking unused import.
signatureVerify is unused and is failing CI (TS6133). Remove it or use it intentionally.
🛠️ Proposed fix (remove unused import)
-import { signatureVerify } from '@polkadot/util-crypto';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { signatureVerify } from '@polkadot/util-crypto'; |
🧰 Tools
🪛 GitHub Actions: CI Workflow
[error] 16-16: TS6133: 'signatureVerify' is declared but its value is never read.
🪛 GitHub Check: build
[failure] 16-16:
'signatureVerify' is declared but its value is never read.
🤖 Prompt for AI Agents
In `@packages/extension-polkagate/src/util/api/signAndSend.ts` at line 16, The
import signatureVerify from '@polkadot/util-crypto' in signAndSend.ts is unused
and causing a TS6133 build error; remove the unused import statement (the
"signatureVerify" specifier) from the import line in
packages/extension-polkagate/src/util/api/signAndSend.ts so the file only
imports what is actually used.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts`:
- Around line 64-82: The stale paraSpellState issue is caused by leaving
previous paraSpellTransaction/paraSpellFee in state while builder.build() runs;
at the start of the effect (before calling builder.build()) clear/reset the
paraSpell-related state via setParaSpellState to remove paraSpellTransaction and
paraSpellFee (e.g., set to null/undefined or an empty object), keep the existing
cancelled flag logic, and ensure any subsequent setParaSpellState((pre) => ({
...(pre||{}), paraSpellTransaction: tx })) only sets the new tx when not
cancelled so old values cannot persist if the new build fails.
- Around line 102-108: The error fallback for ParaspellFees used in
setParaSpellState omits required fields on originFee (it currently sets only
originFee: { fee: BN_ZERO }), causing a type mismatch with ParaspellFees /
TXcmFeeBase; update the fallback to include the required properties (e.g.,
originFee: { fee: BN_ZERO, sufficient: false, balanceAfter: 0n } or another
appropriate default) or explicitly cast the object as ParaspellFees to satisfy
the type checker; locate the update in the setParaSpellState call and adjust the
originFee shape (and destinationFee if used) so it matches the ParaspellFees
interface.
🧹 Nitpick comments (1)
packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts (1)
66-111: Parallelbuild()andgetTransferInfo()can produce partial state.Since both calls fire independently, one can succeed while the other fails — leaving
paraSpellTransactionset butparaSpellFeezeroed (or vice versa). Ensure the consumer checks that bothparaSpellTransactionand a validparaSpellFeeare present before allowing the user to submit.
| let cancelled = false; | ||
|
|
||
| Promise.all([builder.build(), builder.getTransferInfo()]) | ||
| .then(([tx, info]) => { | ||
| builder.build() | ||
| .then((tx) => { | ||
| if (cancelled) { | ||
| return; | ||
| } | ||
|
|
||
| setParaSpellState({ | ||
| setParaSpellState((pre) => ({ | ||
| ...(pre || {}), | ||
| paraSpellTransaction: tx | ||
| })); | ||
| }).catch((err) => { | ||
| if (!cancelled) { | ||
| setError('Something went wrong while building transaction!'); | ||
| } | ||
|
|
||
| console.error('building transaction error', err); | ||
| }); |
There was a problem hiding this comment.
Stale paraSpellState persists across effect re-runs.
When dependencies change and the effect re-runs, the old paraSpellTransaction and paraSpellFee remain in state until the new promises resolve (or reject). If the new build() fails, the previous transaction stays in state—potentially mismatched with the current inputs. This could let a user submit a transaction built with outdated parameters.
Reset state at the top of the effect body:
Proposed fix
const amount = transferType === 'All' ? 'ALL' : amountAsBN.toString();
try {
+ setParaSpellState({});
+
const builder = Builder({ abstractDecimals: false }/* node api/ws_url_string/ws_url_array - optional*/)🤖 Prompt for AI Agents
In `@packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts`
around lines 64 - 82, The stale paraSpellState issue is caused by leaving
previous paraSpellTransaction/paraSpellFee in state while builder.build() runs;
at the start of the effect (before calling builder.build()) clear/reset the
paraSpell-related state via setParaSpellState to remove paraSpellTransaction and
paraSpellFee (e.g., set to null/undefined or an empty object), keep the existing
cancelled flag logic, and ensure any subsequent setParaSpellState((pre) => ({
...(pre||{}), paraSpellTransaction: tx })) only sets the new tx when not
cancelled so old values cannot persist if the new build fails.
| // @ts-ignore | ||
| setParaSpellState((pre) => ({ | ||
| ...(pre || {}), | ||
| paraSpellFee: { | ||
| originFee: { fee: BN_ZERO } | ||
| } | ||
| })); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for ParaspellFees type definition
echo "=== ParaspellFees type definition ==="
rg -n "type ParaspellFees|interface ParaspellFees" --type=ts -A 10
echo ""
echo "=== xcmFee type definition ==="
rg -n "type xcmFee|interface xcmFee" --type=ts -A 10
echo ""
echo "=== How paraSpellFee is accessed in the codebase ==="
rg -n "paraSpellFee" --type=ts -B 2 -A 2 | head -100
echo ""
echo "=== How originFee is accessed ==="
rg -n "\.originFee" --type=ts -B 2 -A 2
echo ""
echo "=== How destinationFee is accessed ==="
rg -n "\.destinationFee" --type=ts -B 2 -A 2Repository: PolkaGate/extension
Length of output: 10109
🏁 Script executed:
#!/bin/bash
# Find TXcmFeeBase definition
echo "=== TXcmFeeBase type definition ==="
rg -n "type TXcmFeeBase|interface TXcmFeeBase" --type=ts -A 15
echo ""
echo "=== Check for direct access to originFee properties other than .fee ==="
rg -n "originFee\." --type=ts -B 1 -A 1 | grep -v "originFee.fee"
echo ""
echo "=== Check for direct access to originFee.sufficient ==="
rg -n "sufficient" --type=ts -B 2 -A 2
echo ""
echo "=== Check for direct access to originFee.balanceAfter ==="
rg -n "balanceAfter" --type=ts -B 2 -A 2Repository: PolkaGate/extension
Length of output: 14976
Address type mismatch in the error fallback for ParaspellFees.
The error fallback at lines 105-107 sets originFee: { fee: BN_ZERO }, which violates the ParaspellFees interface. originFee requires TXcmFeeBase & { sufficient: boolean; balanceAfter: bigint; }, but the fallback omits sufficient and balanceAfter. While the current codebase only accesses originFee.fee (which exists) and safely handles optional destinationFee with defensive chaining, the type mismatch should be resolved to prevent future bugs if the code evolves to access these properties. Consider aligning the fallback object with the expected ParaspellFees shape or explicitly typing the error state.
🤖 Prompt for AI Agents
In `@packages/extension-polkagate/src/fullscreen/sendFund/useParaSpellFeeCall.ts`
around lines 102 - 108, The error fallback for ParaspellFees used in
setParaSpellState omits required fields on originFee (it currently sets only
originFee: { fee: BN_ZERO }), causing a type mismatch with ParaspellFees /
TXcmFeeBase; update the fallback to include the required properties (e.g.,
originFee: { fee: BN_ZERO, sufficient: false, balanceAfter: 0n } or another
appropriate default) or explicitly cast the object as ParaspellFees to satisfy
the type checker; locate the update in the setParaSpellState call and adjust the
originFee shape (and destinationFee if used) so it matches the ParaspellFees
interface.
|
Issues To Fix: |
Summary by CodeRabbit
New Features
Improvements
Dependencies