Skip to content

[🧠 Smart Account] EVM Smart Account#1890

Open
jungcome7 wants to merge 81 commits intodevelopfrom
roy/evm-smart-account
Open

[🧠 Smart Account] EVM Smart Account#1890
jungcome7 wants to merge 81 commits intodevelopfrom
roy/evm-smart-account

Conversation

@jungcome7
Copy link
Copy Markdown
Collaborator

@jungcome7 jungcome7 commented Mar 24, 2026

Summary

  • EVM Smart Account (EIP-7702 + ERC-5792) 통합 브랜치
  • 관련 PR들을 여기에 합쳐서 테스트 진행

Thunnini and others added 15 commits March 23, 2026 16:41
- typescript: 5.0.4 → ^5.7.0 (resolved 5.9.3)
- @typescript-eslint/*: ^5.52.0 → ^7.0.0
- @types/node: ^18.13.0 → ^22.0.0
- eslint: ^8.34.0 → ^8.56.0 (required by @typescript-eslint v7)
- eslint-plugin-unused-imports: ^2.0.0 → ^4.0.0

Type error fixes for TS 5.7+ compatibility:
- Uint8Array generic: use `let digest: Uint8Array` instead of
  `let digest = new Uint8Array()` to avoid ArrayBuffer narrowing
- keyof with symbol: add typeof guard before .startsWith() and
  wrap symbol in String() for template literals (provider/inject.ts)
- NodeJS.Timer → ReturnType<typeof setInterval> (removed in @types/node 22)
- mergeStores: change rest parameter to array parameter to fix
  spread of recursive conditional type (TS 5.4+ stricter check)
- Remove deleted @typescript-eslint/camelcase rule from eslintrc
- Add @typescript-eslint/no-unused-vars with underscore ignore pattern
- Patch miscreant node_modules via post-install for Uint8Array<ArrayBufferLike>

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce ox library and replace @ethersproject utility functions:
- getAddress() → Address.from() (cosmos, stores-eth)
- id() → Hash.keccak256(Hex.fromString()) (background)
- hexValue() → Hex.fromNumber() (stores-eth)
- parseUnits() → Value.from() (stores-eth)
- parseBytes32String() → Hex.toBytes() + TextDecoder (stores-eth)

Remove unused @ethersproject dependencies:
- @keplr-wallet/cosmos: remove @ethersproject/address
- @keplr-wallet/stores-eth: remove address, bytes, units, strings
- @keplr-wallet/background: remove @ethersproject/address

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove @ethersproject packages that are not imported in source code:
- @keplr-wallet/background: remove @ethersproject/wallet
- @keplr-wallet/hooks: remove @ethersproject/address
- @keplr-wallet/hooks-evm: remove @ethersproject/address
- @keplr-wallet/hooks-starknet: remove @ethersproject/address, providers
- @keplr-wallet/stores-starknet: remove abi, address, bytes, transactions, units
- @keplr-wallet/chain-validator: remove @ethersproject/abi

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrate all ABI encoding/decoding from ethers Interface to ox AbiFunction:
- constants.ts: replace Interface with individual AbiFunction definitions
- account/base.ts: encodeFunctionData → AbiFunction.encodeData
- erc20-balance.ts: encodeFunctionData → AbiFunction.encodeData
- erc20-metadata.ts: encode/decode → AbiFunction.encodeData/decodeResult
- stores-etc erc20 query: same migration as above
- send-token.tsx: BigNumber instanceof → typeof bigint check,
  amount.toHexString() → template literal with toString(16)

Remove @ethersproject/abi from stores-eth, stores-etc
Remove @ethersproject/bignumber from extension

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t deps

Phase 4 — Transaction serialization:
- Define UnsignedEVMTransaction type replacing ethers UnsignedTransaction
- Add serializeEVMTransaction() helper using ox TxEnvelope (verified
  byte-identical RLP output)
- Replace serialize()/TransactionTypes across 11 files (stores-eth,
  background, extension sign utils, hardware wallet flows)

Phase 5 — EIP-712 and ENS:
- Replace _TypedDataEncoder with ox TypedData.hashDomain/hashStruct
  (verified byte-identical hash output)
- Replace JsonRpcProvider ENS resolution with manual RPC calls using
  ox Ens.namehash + AbiFunction + simpleFetch

Remove all @ethersproject dependencies:
- @ethersproject/transactions from stores-eth, background, extension
- @ethersproject/hash from background
- @ethersproject/providers from hooks, hooks-evm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ox AbiFunction.decodeData does not verify the function selector,
unlike ethers decodeFunctionData. This caused approve transactions
to be incorrectly decoded as transfers, rendering the wrong sign view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous migration used ENSIP-1 addr(bytes32) which only returns
ETH addresses. ethers getAddress(60) used ENSIP-9 addr(bytes32,uint256)
with coinType 60. Restore the same behavior to support resolvers that
only implement the multi-coin address interface.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hand-written {name: string, type: string} types with
TypedData.Parameter and TypedData.TypedData from ox. This removes
both `as any` casts that were added during the ethers→ox migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ethers used `chainId || 0` when chainId was missing. The ox migration
incorrectly defaulted to 1 (mainnet), which could silently produce
wrong signatures if chainId were ever omitted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ts-loader: 9.4.2 → 9.5.4
fork-ts-checker-webpack-plugin: 7.2.13 → 9.1.0

The old versions were not tested with TypeScript 5.9.3 and caused
the extension to break on watch-mode rebuilds during development.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ox Address.from() returns lowercase addresses as-is without applying
EIP-55 checksum, unlike ethers getAddress(). Address.checksum() matches
the original ethers behavior of always returning checksummed addresses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove stale comment about primaryType inference (eip712.ts)
- Rewrite ethersjs reference to be library-agnostic (service.ts)
- Remove "ethers-compatible" from EVMSignatureLike JSDoc (serialize.ts)
- Add console.warn when ERC20 selector matches but decoding fails
- Fix "ENS or is not set" typo (name-service-ens.ts)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Large numeric literals in test assertions trigger the rule under
TypeScript 5.9.3's stricter eslint integration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…reset

eslint-mdx v2 failed to parse .mdx files because @1stg/remark-preset
uses ESM top-level await which is incompatible with require().
v3 no longer depends on @1stg/remark-preset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
keplr-wallet-extension Ready Ready Preview, Comment Apr 7, 2026 7:20am

Request Review

jungcome7 and others added 6 commits March 24, 2026 16:19
Move hardcoded values scattered across service.ts into constants.ts:
- Signature recovery IDs (SIGNATURE_V_FALSE/TRUE)
- RPC error codes (4001, 4200, -32602, 4902)
- ERC-20 transfer selector, default chain ID, ETH coin type

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract 9 pure functions from service.ts into helper.ts:
- encodeSignature, normalizeSigner, getEthAddressFromPubkey
- applyEIP1559Type, parseChainIdParam, parseTxParam
- rethrowAsProviderError, toHexQty, normalizeUnsignedTx
- EVMTransactionParam interface

Add 40 unit tests covering all extracted helpers (no mocks needed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split the 1472-line monolithic KeyRingEthereumService into focused modules:

- service.ts (875 lines): signing, RPC dispatcher, transaction handlers
- chain-handlers.ts (341 lines): chain switch/add, permissions, asset watch, RPC passthrough
- ws-handlers.ts (184 lines): WebSocket subscribe/unsubscribe with own state

Key changes in service.ts:
- request() reduced from 640-line switch to ~70-line dispatcher
- 8 duplicated "Request rejected" catch blocks → rethrowAsProviderError()
- 6 duplicated ETH address derivations → getSelectedEthAddress()
- 4 duplicated signature encodings → encodeSignature()
- eth_sendTransaction / eth_signTransaction (~240 lines) → prepareAndSignTransaction()
- Duplicate eth_getTransactionByHash case removed
- All magic numbers replaced with named constants

No circular dependencies: service → chain-handlers/ws-handlers → helper (unidirectional).
Zero functional or behavioral changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
x → value, n → clamped, q → parsed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement wallet_getCapabilities RPC handler to check whether an EOA
is delegated to a trusted smart account contract via EIP-7702.

- types: DelegationStatus, GetCapabilitiesResult
- helper: parseDelegation() — parse eth_getCode response
- service: getSmartAccountCapabilities() + dispatch handler
- constants: ALLOWED_DELEGATORS, EIP7702_DELEGATION_PREFIX
- feature flag: "eip-7702" on 11 EVM chains
- 7 unit tests for parseDelegation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

EIP-7702 delegation 판별 위에 ERC-5792 응답 레이어를 추가한다.
- handleGetCapabilities: 주소 형식(-32602)·소유권(4100) 검증
- getAtomicCapability: delegation 상태를 ERC-5792 atomic capability 형식으로 반환
- 미지원 체인 키 생략, RPC 실패 시 키 생략 (ERC-5792 MUST)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jungcome7 jungcome7 changed the title EVM Smart Account [Smart Account] EVM Smart Account Mar 26, 2026
@jungcome7 jungcome7 changed the title [Smart Account] EVM Smart Account 🔐 [Smart Account] EVM Smart Account Mar 26, 2026
@jungcome7 jungcome7 changed the title 🔐 [Smart Account] EVM Smart Account [🧠 Smart Account] EVM Smart Account Mar 26, 2026
…on serialization

- Introduced `eip712.spec.ts` to test EIP-712 message validation for Evmos and Injective transactions.
- Added `serialize.spec.ts` to validate serialization of legacy and EIP-1559 transactions, ensuring correct handling of chainId and signature formats.
- Updated `serialize.ts` to enforce chainId requirement for typed transactions, preventing silent mis-serialization.
Add focused ENS resolution coverage around the ox-based resolver path.

- normalize mixed-case ENS names before computing the node hash

- expose resolveENSWithEthCall so the resolution flow can be unit tested without RPC fixtures

- document that Keplr intentionally resolves ETH addresses via ENSIP-9 multicoin records only

- add hooks ENS tests for normalization, resolver absence, invalid multicoin payloads, and empty records

- add a jest config for hooks-evm so equivalent ENS tests can run there as well
Avoid converting gas fee fields through JavaScript Number before serializing transaction inputs.

- build maxFeePerGas and maxPriorityFeePerGas from BigInt-backed values

- handle gasPrice the same way so decimal and 0x-prefixed integer strings share one path

- keep ox Hex serialization while eliminating precision loss for large fee values
Tighten TypeScript upgrade follow-up tooling so failures surface earlier and package overrides stay consistent with the root ESLint config.

- make miscreant patch steps distinguish between already-patched, patchable, and stale upstream source

- throw with a targeted error when an expected patch anchor disappears instead of silently no-oping

- update packages/unit to disable the base no-loss-of-precision rule name used by the root config
piatoss3612 and others added 2 commits April 2, 2026 13:41
packages/cosmos/src/bech32/index.ts imports ox but it was not listed
in package.json dependencies, causing import/no-extraneous-dependencies
lint failure in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same import/no-extraneous-dependencies lint error as cosmos package.
These three packages import from "ox" but didn't declare it in
their package.json dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[🧠 Smart Account] EIP-7702 upgrade/downgrade service
jungcome7 and others added 4 commits April 3, 2026 14:43
…ounts

Add GetEthereumAddressForVaultMsg to resolve ethereum hex address
for a specific vaultId instead of relying on the globally selected
account. This fixes incorrect address, balance, and delegation
status when managing smart accounts for non-active vaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…or errored

Add per-chain isLoading/hasError to ChainStatus and pass disabled
prop to ChainRowItem toggle, preventing interaction before the
delegation status query resolves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[🧠 Smart Account] EIP-7702 network toggle & TX confirmation UI
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

Storybook Deployed

🔗 Preview: https://chainapsis.github.io/keplr-wallet/storybook/

Last updated: 2026-04-03T07:37:24Z

jungcome7 and others added 9 commits April 6, 2026 15:39
Pass authorizationList from UnsignedEVMTransaction to eth_estimateGas
params, enabling EIP-7702 gas estimation through the store layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ments

- Add createAtomicBatchTransaction using ox/erc7821 Execute.encodeData
- Add buildDelegationStateOverride for non-upgraded account gas estimation
- Export helper functions for UI consumption
- Simplify handleSendCalls (no pre-built TX, gas estimated by UI)
- Add origin/strategy/apiVersion to batchCallsMap
- Fix atomic hardcoding and version hardcoding in handleGetCallsStatus
- Add origin isolation in handleGetCallsStatus

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…o store

Remove EstimateSmartAccountFeeMsg and use stores-eth simulateGas +
hooks-evm computeEIP1559TxFees for reactive fee estimation. This
aligns with the regular EVM sign page pattern and enables automatic
fee updates when network conditions change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contract deployment (missing `to`) is not supported in execute()
batch since it uses CALL opcode, not CREATE. Explicitly reject
instead of silently defaulting to zero address.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…es-eth

createAtomicBatchTransaction and buildDelegationStateOverride are
UI-only utilities (not used in background). Move to stores-eth
where other EVM utilities like serializeEVMTransaction live.

Decouple from background-specific dependencies (ALLOWED_DELEGATORS,
buildDummyAuthorizationList) by accepting authorizationList as param.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add !feeDisplay to approveDisabled guard to prevent approval when
gas simulation succeeded but fee queries have not resolved yet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Let the error propagate so the error boundary catches it and shows
the cache reset page, since a missing chainId is a critical failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simulate L1 data fee via simulateOpStackL1Fee for chains with
"op-stack-l1-data-fee" feature and include it in the total estimated fee.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[🧠 Smart Account] EIP-5792 atomic batch TX assembly + store-based fee estimation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants