Deliver EVM integration for governance portal#773
Merged
Conversation
frankmeds
approved these changes
Apr 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds EVM wallet support (MetaMask, Ledger Live, Brave Wallet, Coinbase Wallet, and any
window.ethereum-injecting extension) as an alternative to the existing ZilPay connector inthe Governance Portal.
No new frontend dependencies — all EVM wallet interaction goes through the
browser-injected
window.ethereumprovider.@web3modal/standalone+@wagmi/corewereconsidered but rejected: wagmi v2 and viem are ESM-only and conflict with Vue CLI 4 /
Webpack 4, requiring invasive config changes not worth taking on in a legacy project. The
trade-off is that WalletConnect QR-code flow is not supported, which is acceptable because
the target users connect hardware Ledgers via MetaMask or Ledger Live.
Phase 1 — Decouple blockchain reads from ZilPay (
governance-snapshot)src/helpers/zilliqa.ts— shared@zilliqa-js/zilliqasingleton pointed athttps://api.zilliqa.com/getBlockNumberandgetTotalSupplyinsrc/helpers/web3.tsto use the RPCsingleton directly instead of the ZilPay provider object
zrc2-balance-ofstrategy insrc/helpers/get-scores.tsto use the RPCsingleton
src/store/modules/app.tsandsrc/views/Create.vue— ZilPay isno longer involved in any read path
Phase 2 — EVM connector and store wiring (
governance-snapshot)"evm"entry tosrc/helpers/connectors.jsonEVMConnectorclass tosrc/helpers/plugins/LockPlugin.ts— connects viaeth_requestAccounts, session-checks viaeth_accounts(no prompt), logout clearslocalStorageonlyEVMConnectorinsrc/auth.tsloadProviderinsrc/store/modules/web3.ts: EVM path derivesbase16/bech32from the connected address using
toBech32Addressfrom@zilliqa-js/crypto; subscribes toaccountsChangedeventssignMessageinsrc/helpers/web3.ts: EVM path signs viapersonal_sign(EIP-191), returning
{ message, signature }; ZilPay Schnorr path unchangedsend()insrc/store/modules/app.tsto includesigType: 'evm' | 'schnorr'inthe API request body
src/components/Modal/Account.vueto show a generic wallet iconfor non-ZilPay connectors
Phase 3 — Backend EVM signature verification (
governance-api)ethersdependencylib/utils/verify-evm-signature.ts— verifies EIP-191personal_signsignaturesusing
ethers.utils.verifyMessage+ecrecoverlib/routes/message.ts: routes signature verification bysigType—'evm'usesECDSA recovery, default uses existing Schnorr path; all existing ZilPay and legacy
submissions continue to work unchanged
Key design decisions
0xprefix). The existing
validation.isBech32guard inmessage.tsalready handles thiscorrectly.
base16 address — no changes needed to balance retrieval or the 30 gZIL proposal minimum
check.
web3state shape ({ base16, bech32 }) is unchanged;bech32is derived fromthe EVM address via
toBech32Address._lock.connectorlocalStorage pattern as ZilPay.Test plan
window.ethereum— new path)