Skip to content

Comments

prep: release v2.9.0#715

Merged
kvhnuke merged 37 commits intodevelopfrom
devop/release-2-9
Jun 30, 2025
Merged

prep: release v2.9.0#715
kvhnuke merged 37 commits intodevelopfrom
devop/release-2-9

Conversation

@kvhnuke
Copy link
Contributor

@kvhnuke kvhnuke commented Jun 17, 2025

Summary by CodeRabbit

  • New Features

    • Added support for the Sonic network, including network configuration, token lists, asset info, and activity tracking.
    • Introduced typed message (EIP-712) signing for Ethereum hardware wallets (Ledger and Trezor), with UI enhancements for hardware wallet message display.
    • Added Solana staking promotional banners in the app menu and network assets views, with user interaction tracking and persistent dismissal state.
  • Improvements

    • The transaction verification UI now prioritizes displaying the token recipient address where available.
    • Updated new network announcements to highlight Sonic.
    • Enhanced transaction nonce retrieval to improve compatibility with Rootstock addresses.
    • Expanded token inclusion criteria for swaps to support RBTC tokens as native currency.
  • Dependency Updates

    • Upgraded multiple dependencies and development tools across packages for improved stability and compatibility.

@coderabbitai
Copy link

coderabbitai bot commented Jun 17, 2025

## Walkthrough

This update introduces support for the Sonic network across the codebase, including new configuration, asset, activity, and token list handlers. It also adds EIP-712 typed message signing support for hardware wallets, updating relevant interfaces, implementations, and UI flows. Solana staking promotional banners with state management and event tracking are added to the UI. Numerous package dependencies are updated with minor and patch version bumps.

## Changes

| Files/Paths                                                                                      | Change Summary                                                                                                  |
|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| packages/extension/src/providers/ethereum/networks/sonic.ts                                    | New Sonic network configuration and export.                                                                    |
| packages/extension/src/providers/ethereum/networks/index.ts                                    | Imports and adds Sonic network to exported networks object.                                                    |
| packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts| Adds Sonic to Etherscan network endpoints.                                                                     |
| packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts                | Adds Sonic to supported MEW asset info networks.                                                               |
| packages/extension/src/providers/ethereum/libs/assets-handlers/token-lists.ts                  | Adds Sonic and Conflux token lists to Coingecko mappings.                                                      |
| packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts       | Extends supported network names with Sonic.                                                                    |
| packages/extension/src/providers/common/libs/new-features.ts                                   | Updates newNetworks array to feature Sonic.                                                                    |
| packages/types/src/networks.ts                                                                 | Adds Sonic to NetworkNames and CoingeckoPlatform enums.                                                        |
| packages/extension/package.json                                                                | Bumps package version; updates multiple dependencies.                                                          |
| packages/extension-bridge/package.json<br>packages/keyring/package.json<br>packages/name-resolution/package.json<br>packages/request/package.json<br>packages/signers/bitcoin/package.json<br>packages/signers/ethereum/package.json<br>packages/signers/kadena/package.json<br>packages/signers/polkadot/package.json<br>packages/storage/package.json<br>packages/swap/package.json<br>packages/types/package.json<br>packages/utils/package.json | Updates devDependencies and/or runtime dependencies (patch/minor bumps).                                       |
| package.json                                                                                   | Updates @swc/core devDependency version.                                                                       |
| packages/hw-wallets/package.json                                                               | Updates dependencies; adds @metamask/eth-sig-util and @trezor/connect-plugin-ethereum.                         |
| packages/hw-wallets/src/types.ts                                                               | Adds SignTypedMessageRequest interface and abstract signTypedMessage method to HWWalletProvider.               |
| packages/hw-wallets/src/index.ts                                                               | Adds signTypedMessage method to HWwalletManager.                                                               |
| packages/hw-wallets/src/ledger/ethereum/index.ts                                               | Implements signTypedMessage for Ledger Ethereum; adds typedMessage capability.                                 |
| packages/hw-wallets/src/ledger/bitcoin/index.ts<br>packages/hw-wallets/src/ledger/solana/index.ts<br>packages/hw-wallets/src/ledger/substrate/index.ts<br>packages/hw-wallets/src/trezor/bitcoin/index.ts<br>packages/hw-wallets/src/trezor/solana/index.ts | Adds signTypedMessage method that rejects as unsupported.                                                      |
| packages/hw-wallets/src/trezor/ethereum/index.ts                                               | Implements signTypedMessage for Trezor Ethereum; adds typedMessage capability.                                 |
| packages/extension/src/providers/ethereum/ui/libs/signer.ts                                    | Adds TypedMessageSigner function for EIP-712 signing (hardware and software); updates exports.                 |
| packages/extension/src/providers/ethereum/ui/types.ts                                          | Adds SignerTypedMessageOptions interface for typed message signing.                                            |
| packages/extension/src/providers/ethereum/ui/eth-sign-typedata.vue                             | Refactors to use new TypedMessageSigner; adds hardware wallet message UI.                                      |
| packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue                        | Updates "To" address logic to prefer tokenTo over toAddress in UI and identicon.                               |
| packages/extension/src/providers/ethereum/networks/sdn.ts                                     | Updates Shiden WebSocket node URL.                                                                              |
| packages/extension/src/providers/ethereum/networks/tlos.ts                                    | Updates Telos RPC node URL.                                                                                      |
| packages/extension/src/providers/ethereum/networks/vic.ts                                     | Updates Viction WebSocket node URL.                                                                              |
| packages/extension/src/providers/ethereum/libs/transaction/index.ts                           | Converts sender address to lowercase for transaction count retrieval to support Rootstock addresses.           |
| packages/swap/src/providers/changelly/index.ts                                                | Includes tokens with protocol "RBTC" in fromTokens list for swaps, alongside fixRateEnabled tokens.             |
| packages/extension/src/libs/banners-state/index.ts                                            | Adds BannersState class to manage Solana staking banner visibility state in persistent storage.                 |
| packages/extension/src/libs/banners-state/types.ts                                            | Adds StorageKeys enum and IState type for banners state management.                                            |
| packages/extension/src/libs/metrics/index.ts                                                  | Adds trackSolanaStakingBanner event tracking function; minor formatting updates.                               |
| packages/extension/src/libs/metrics/types.ts                                                  | Adds SolanaStakingBannerEvents enum; fixes UpdatesOpenLocation enum syntax and formatting.                      |
| packages/extension/src/types/provider.ts                                                      | Adds bannersState member to InternalStorageNamespace enum.                                                     |
| packages/extension/src/ui/action/components/app-menu/components/solana-staking-banner.vue     | New Solana staking promotional banner Vue component with event tracking and close functionality.               |
| packages/extension/src/ui/action/components/app-menu/index.vue                                | Integrates Solana staking banner into app menu with state management and close handling.                        |
| packages/extension/src/ui/action/icons/banners/attractive-apr-icon.vue                        | Adds new SVG icon component for Attractive APR.                                                                |
| packages/extension/src/ui/action/icons/banners/consistent-rewards-icon.vue                    | Adds new SVG icon component for Consistent Rewards.                                                            |
| packages/extension/src/ui/action/icons/common/close-icon-white.vue                            | Adds new SVG close icon component in white.                                                                     |
| packages/extension/src/ui/action/icons/common/enkrypt-staking-logo-white.vue                  | Adds new SVG component for Enkrypt Staking logo in white and purple gradient.                                  |
| packages/extension/src/ui/action/icons/common/enkrypt-staking-logo.vue                        | Adds new SVG component for Enkrypt Staking logo in standard colors.                                            |
| packages/extension/src/ui/action/views/network-assets/components/network-assets-solana-staking-banner.vue | New Solana staking banner component for network assets view with event tracking and close functionality.        |
| packages/extension/src/ui/action/views/network-assets/index.vue                               | Integrates Solana staking banner into network assets view with state management and close handling.             |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant UI as eth-sign-typedata.vue
    participant Signer as TypedMessageSigner
    participant HW as HWwalletManager
    participant Ledger/Trezor as Hardware Wallet
    participant SW as Software Signer
    participant BG as Background Script

    UI->>Signer: TypedMessageSigner(options)
    alt Hardware wallet
        Signer->>HW: signTypedMessage(options)
        HW->>Ledger/Trezor: signTypedMessage(options)
        Ledger/Trezor-->>HW: signature or error
        HW-->>Signer: signature or error
    else Software wallet
        Signer->>SW: compute hash (typedSignatureHash or eip712Hash)
        SW->>BG: sign hash with account
        BG-->>SW: signature or error
        SW-->>Signer: signature or error
    end
    Signer-->>UI: signature or error

Possibly related PRs

  • enkryptcom/enKrypt#714: Adds support for the Sonic network with similar configuration and handler updates.
  • enkryptcom/enKrypt#708: Introduces Solana staking banners and related state management and event tracking in the UI.
  • enkryptcom/enKrypt#713: Implements typed message signing support for hardware wallets and UI, closely related to signer and wallet provider changes.

Suggested reviewers

  • gamalielhere
  • NickKelly1
  • olgakup


<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 43efc384d59a4e2ea8c9855b91e3b548b1421617 and 34171ccfd3e31147f4e7ebf2b3bb1361431d0f7c.

</details>

<details>
<summary>⛔ Files ignored due to path filters (3)</summary>

* `packages/extension/src/ui/action/assets/banners/solana-staking-banner-bg.png` is excluded by `!**/*.png`
* `packages/extension/src/ui/action/assets/banners/solana-staking-banner-tokens-img.png` is excluded by `!**/*.png`
* `packages/extension/src/ui/action/assets/banners/solana-staking-banner.png` is excluded by `!**/*.png`

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `packages/extension/src/libs/banners-state/index.ts` (1 hunks)
* `packages/extension/src/ui/action/components/app-menu/components/solana-staking-banner.vue` (1 hunks)
* `packages/extension/src/ui/action/components/app-menu/index.vue` (9 hunks)
* `packages/extension/src/ui/action/views/network-assets/components/network-assets-solana-staking-banner.vue` (1 hunks)
* `packages/extension/src/ui/action/views/network-assets/index.vue` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (5)</summary>

* packages/extension/src/libs/banners-state/index.ts
* packages/extension/src/ui/action/components/app-menu/index.vue
* packages/extension/src/ui/action/views/network-assets/components/network-assets-solana-staking-banner.vue
* packages/extension/src/ui/action/views/network-assets/index.vue
* packages/extension/src/ui/action/components/app-menu/components/solana-staking-banner.vue

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: buildAll
* GitHub Check: test
* GitHub Check: test

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=enkryptcom/enKrypt&utm_content=715):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@github-actions
Copy link

github-actions bot commented Jun 17, 2025

💼 Build Files
chrome: enkrypt-chrome-34171ccf.zip
firefox: enkrypt-firefox-34171ccf.zip

💉 Virus total analysis
chrome: 34171ccf
firefox: 34171ccf

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (1)
packages/extension/package.json (1)

3-3: Version string is still 2.8.0 – should be 2.9.0 for this release
The PR title indicates release v2.9.0, but the package.json version field remains 2.8.0. Forgetting to bump this prevents consumers and the CI publish step from picking up the new release.

-  "version": "2.8.0",
+  "version": "2.9.0",
🧹 Nitpick comments (8)
packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue (1)

85-95: Use nullish coalescing throughout for clarity

Right now you mix || and ??, which can be surprising when empty string values appear.
decodedTx?.tokenTo ?? decodedTx?.toAddress ?? '~' would read a bit clearer and avoid subtle falsy traps.

Not critical, just readability.

packages/extension/src/providers/ethereum/ui/types.ts (1)

40-45: Tighten up the typedData typing for better DX
typedData is declared as any, which leaks type-safety to every consumer. Consider aligning this with the EIP-712 TypedData definition that already exists in the codebase (@metamask/eth-sig-util or your own helper types) or at least Record<string, unknown>.

-export interface SignerTypedMessageOptions {
-  typedData: any;
+export interface SignerTypedMessageOptions {
+  typedData: Record<string, unknown>; // or a dedicated TypedData type
packages/hw-wallets/src/trezor/solana/index.ts (1)

71-75: Align method style with the rest of the class (async + throw)
Other unsupported-feature stubs in this class (signPersonalMessage) are declared async and simply throw. For consistency and slightly cleaner stack-traces you can do the same here:

-  signTypedMessage(_request: SignTypedMessageRequest): Promise<string> {
-    return Promise.reject(
-      new Error("trezor-solana: signTypedMessage not supported"),
-    );
-  }
+  async signTypedMessage(): Promise<string> {
+    throw new Error("trezor-solana: signTypedMessage not supported");
+  }
packages/hw-wallets/package.json (1)

3-3: Optional: bump internal package version for clarity
@enkryptcom/hw-wallets stays at 0.0.12, yet new public APIs (signTypedMessage) were added. Semver-wise this is at least a minor bump (0.0.13) to avoid consumers silently missing the new feature.

packages/extension/src/providers/ethereum/ui/eth-sign-typedata.vue (1)

9-9: Guard rendering of hardware-specific banner

<hardware-wallet-msg> is rendered unconditionally, which means it shows up even for software-only accounts. Wrap the component in a v-if="account.isHardware" (or equivalent) to avoid confusing users.

packages/hw-wallets/src/trezor/ethereum/index.ts (1)

138-148: Hash pre-computation duplicates Trezor-Connect logic

transformTypedData already returns the two hashes, but ethereumSignTypedData can compute them internally when metamask_v4_compat is set. Supplying both hashes is harmless yet redundant. Consider dropping the manual transform to reduce code surface (and the dependency).

packages/extension/src/providers/ethereum/ui/libs/signer.ts (2)

124-131: Early-exit for unsupported V1 is good, but expose proper error code

Consider returning the same ErrorCodes.unsupportedMethod shape used elsewhere, so the UI can handle all “not supported” errors uniformly.


119-180: Type alias shadowing

Inside the non-hardware branch you redeclare const version = options.version… which shadows the outer version variable coming from the function arguments. While harmless, it interrupts readability—prefer renaming the inner constant.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13df0aa and 6753404.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (28)
  • package.json (1 hunks)
  • packages/extension-bridge/package.json (2 hunks)
  • packages/extension/package.json (5 hunks)
  • packages/extension/src/providers/ethereum/ui/eth-sign-typedata.vue (3 hunks)
  • packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue (1 hunks)
  • packages/extension/src/providers/ethereum/ui/libs/signer.ts (2 hunks)
  • packages/extension/src/providers/ethereum/ui/types.ts (1 hunks)
  • packages/hw-wallets/package.json (3 hunks)
  • packages/hw-wallets/src/index.ts (2 hunks)
  • packages/hw-wallets/src/ledger/bitcoin/index.ts (2 hunks)
  • packages/hw-wallets/src/ledger/ethereum/index.ts (3 hunks)
  • packages/hw-wallets/src/ledger/solana/index.ts (2 hunks)
  • packages/hw-wallets/src/ledger/substrate/index.ts (2 hunks)
  • packages/hw-wallets/src/trezor/bitcoin/index.ts (2 hunks)
  • packages/hw-wallets/src/trezor/ethereum/index.ts (4 hunks)
  • packages/hw-wallets/src/trezor/solana/index.ts (2 hunks)
  • packages/hw-wallets/src/types.ts (2 hunks)
  • packages/keyring/package.json (2 hunks)
  • packages/name-resolution/package.json (3 hunks)
  • packages/request/package.json (2 hunks)
  • packages/signers/bitcoin/package.json (2 hunks)
  • packages/signers/ethereum/package.json (2 hunks)
  • packages/signers/kadena/package.json (2 hunks)
  • packages/signers/polkadot/package.json (2 hunks)
  • packages/storage/package.json (2 hunks)
  • packages/swap/package.json (3 hunks)
  • packages/types/package.json (2 hunks)
  • packages/utils/package.json (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/hw-wallets/src/ledger/substrate/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/ledger/bitcoin/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/ledger/solana/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/trezor/bitcoin/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/trezor/solana/index.ts (1)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/hw-wallets/src/ledger/ethereum/index.ts (2)
packages/hw-wallets/src/types.ts (1)
  • SignTypedMessageRequest (56-62)
packages/utils/src/index.ts (2)
  • bufferToHex (38-38)
  • hexToBuffer (39-39)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: buildAll
🔇 Additional comments (30)
package.json (1)

37-37: Approve bump of @swc/core
The development dependency @swc/core was updated to ^1.12.1, aligning with other minor bumps across the monorepo.

packages/swap/package.json (4)

3-3: Bump swap package version to 0.0.4
Aligns with the coordinated v2.9.0 release across the monorepo.


34-34: Upgrade rango-sdk-basic to ^0.1.69
Keeps the swap package in sync with the latest SDK improvements.


42-45: Update core TypeScript linting and ESLint tooling
Bumps @types/node, @typescript-eslint plugins/parsers, and eslint for consistent code quality checks.


56-57: Bump supplementary devDependencies: typescript-eslint & vitest
Ensures test runner and ESLint config are up-to-date across packages.

packages/keyring/package.json (3)

32-32: Upgrade @polkadot/util to ^13.5.2
Pulls in the latest utility functions and bug fixes from the Polkadot team.


37-40: Align core TypeScript & ESLint tooling versions
Bumps @types/node, @typescript-eslint plugins/parsers, and eslint for uniform linting setup.


51-52: Update devDependencies: typescript-eslint & vitest
Brings the test framework and ESLint integration in line with the monorepo standard.

packages/name-resolution/package.json (3)

25-28: Upgrade TypeScript & ESLint dev tooling
Bumps @types/node, @typescript-eslint plugins/parsers, and eslint to maintain consistency.


39-41: Bump test & tooling packages: typescript-eslint, viem, vitest
Updates the Ethereum client (viem) version and testing setup.


51-51: Upgrade @bonfida/spl-name-service to 3.0.11
Ensures name resolution uses the latest Solana Name Service updates.

packages/extension-bridge/package.json (3)

47-47: Bump @types/node to ^24.0.3
Keeps Node definitions current for the extension bridge.


49-52: Update ESLint plugins, parser & bumpp
Aligns linting and release tooling versions with the rest of the monorepo.


64-64: Upgrade typescript-eslint to 8.34.1
Ensures consistent ESLint integration across packages.

packages/signers/polkadot/package.json (3)

27-28: Upgrade @polkadot/util & util-crypto to ^13.5.2
Incorporates the latest performance and security fixes from Polkadot libraries.


34-37: Align core TypeScript & ESLint tooling
Bumps @types/node, @typescript-eslint plugins/parsers, and eslint for consistent development environment.


48-49: Update devDependencies: typescript-eslint & vitest
Brings testing and linting integration up-to-date with the monorepo standard.

packages/utils/package.json (1)

27-31: Dependency bumps look safe – just verify CI passes

All changes are simple patch/minor upgrades that should remain semver-compatible.
Please make sure the lock-file is updated and that npm audit / unit tests still pass in CI after the bump.

Also applies to: 33-37, 48-49

packages/signers/kadena/package.json (1)

31-37: Consistent version alignment – no further action

Dev-dependency bumps mirror the rest of the monorepo.
No functional impact detected.

Also applies to: 33-37, 47-49

packages/signers/ethereum/package.json (1)

35-39: Dev-dependency sync looks good

Nothing to flag here.

Also applies to: 49-50

packages/hw-wallets/src/trezor/bitcoin/index.ts (1)

119-123: Explicit unsupported path OK – expose capability flag to avoid calls

The stubbed signTypedMessage correctly rejects, but the provider’s capability list (getCapabilities) hasn’t been updated.
Since it still advertises only signMessage/signTx, higher-level code won’t call this method, so the defensive rejection is fine.

No change required.

packages/hw-wallets/src/ledger/solana/index.ts (1)

85-89: Explicit rejection looks good – nothing else to do
The provider cleanly implements the new interface and rejects unsupported functionality. Consistent with the capability list returned below.

packages/hw-wallets/src/ledger/bitcoin/index.ts (1)

209-213: Good – provider explicitly rejects unsupported feature
Implementation complies with the new abstract method.

packages/hw-wallets/src/types.ts (2)

56-62: Interface addition LGTM
The shape matches EIP-712 needs and the union of V3/V4 keeps things strict.


111-112: Abstract method addition LGTM
All concrete providers now either implement or explicitly reject the call – fulfils type safety.

packages/hw-wallets/src/index.ts (1)

71-76: Good addition – manager now exposes typed-message signing
The new signTypedMessage delegate follows the same lazy-initialisation pattern used by the other signers. Looks solid.

packages/hw-wallets/src/ledger/ethereum/index.ts (2)

141-165: Edge-case & readability tweaks for the new EIP-712 flow

  1. TypedDataUtils.hashStruct already returns a 32-byte buffer – no need to convert twice; consider passing the raw buffer to Ledger rather than hex to avoid one extra copy.
  2. as SignTypedDataVersion.V3 | SignTypedDataVersion.V4 is redundant; request.version as SignTypedDataVersion is sufficient and less noisy.
  3. v is converted with BigInt(result.v - 27). result.v is already a number; Number(result.v) - 27 is clearer and avoids an unnecessary BigInt → number → BigInt round-trip.
-    const messageHash = TypedDataUtils.hashStruct(
+    const messageHash = TypedDataUtils.hashStruct(
       request.primaryType,
       request.message,
       request.types,
-      request.version as SignTypedDataVersion.V3 | SignTypedDataVersion.V4,
+      request.version as SignTypedDataVersion,
     );
@@
-        bufferToHex(domainHash, true),
-        bufferToHex(messageHash, true),
+        bufferToHex(domainHash, true),
+        bufferToHex(messageHash, true),
       )
       .then((result) => {
-        const v = BigInt(result.v - 27);
+        const v = Number(result.v) - 27;
         return toRpcSig(v, hexToBuffer(result.r), hexToBuffer(result.s));
       });

Please sanity-test with a real Ledger: whitelist both V3 & V4 payloads and ensure the signature matches eth-sig-util’s recoverTypedSignature.


189-190: Capability advertised only if firmware really supports it
typedMessage is now exposed unconditionally. Older Ledger firmware (< 2.1.0) will reject signEIP712HashedMessage, which may break UI feature-detection. Consider gating this on an explicit firmware check (similar to ledgerService.getAppAndVersion) or at least documenting the minimum firmware required.

packages/extension/src/providers/ethereum/ui/eth-sign-typedata.vue (2)

54-56: Path sanity-check

The import path for the banner component jumps two directories up into common/ui/verify-transaction. Confirm that this file really exists once the build is flattened; otherwise the component will break at runtime.


106-117: ```shell
#!/bin/bash

Locate and display sanitizeData function for context

sanitizer=$(fd sanitize-typed-data.ts)
echo "=== File: $sanitizer ==="
sed -n '1,200p' "$sanitizer"


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (1)
packages/extension/src/libs/banners-state/index.ts (1)

27-32: Consider consistency in resetBanners method.

For consistency with other methods, consider using individual assignments rather than direct property access on the state object.

   async resetBanners(): Promise<void> {
-    const state = await this.getOrInitializeState();
-    state.isHideNetworkAssetSolanStakingBanner = false;
-    state.isHideSolanStakingBanner = false;
-    await this.storage.set(StorageKeys.bannersInfo, state);
+    const newState: IState = {
+      isHideSolanStakingBanner: false,
+      isHideNetworkAssetSolanStakingBanner: false,
+    };
+    await this.storage.set(StorageKeys.bannersInfo, newState);
   }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc644eb and e694cbf.

⛔ Files ignored due to path filters (3)
  • packages/extension/src/ui/action/assets/banners/solana-stacking-banner-bg.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/banners/solana-stacking-banner-tokens-img.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/banners/solana-stacking-banner.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • packages/extension/src/libs/banners-state/index.ts (1 hunks)
  • packages/extension/src/libs/banners-state/types.ts (1 hunks)
  • packages/extension/src/libs/metrics/index.ts (5 hunks)
  • packages/extension/src/libs/metrics/types.ts (1 hunks)
  • packages/extension/src/types/provider.ts (2 hunks)
  • packages/extension/src/ui/action/components/app-menu/components/solana-staking-banner.vue (1 hunks)
  • packages/extension/src/ui/action/components/app-menu/index.vue (4 hunks)
  • packages/extension/src/ui/action/icons/banners/attractive-apr-icon.vue (1 hunks)
  • packages/extension/src/ui/action/icons/banners/consistent-rewards-icon.vue (1 hunks)
  • packages/extension/src/ui/action/icons/common/close-icon-white.vue (1 hunks)
  • packages/extension/src/ui/action/icons/common/enkrypt-staking-logo-white.vue (1 hunks)
  • packages/extension/src/ui/action/icons/common/enkrypt-staking-logo.vue (1 hunks)
  • packages/extension/src/ui/action/views/network-assets/components/network-assets-solana-staking-banner.vue (1 hunks)
  • packages/extension/src/ui/action/views/network-assets/index.vue (4 hunks)
✅ Files skipped from review due to trivial changes (7)
  • packages/extension/src/ui/action/icons/banners/attractive-apr-icon.vue
  • packages/extension/src/ui/action/icons/common/close-icon-white.vue
  • packages/extension/src/ui/action/icons/banners/consistent-rewards-icon.vue
  • packages/extension/src/libs/banners-state/types.ts
  • packages/extension/src/ui/action/icons/common/enkrypt-staking-logo-white.vue
  • packages/extension/src/ui/action/icons/common/enkrypt-staking-logo.vue
  • packages/extension/src/ui/action/components/app-menu/components/solana-staking-banner.vue
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/extension/src/libs/banners-state/index.ts (1)
packages/extension/src/libs/banners-state/types.ts (1)
  • IState (5-8)
🪛 Biome (1.9.4)
packages/extension/src/types/provider.ts

[error] 136-136: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (14)
packages/extension/src/types/provider.ts (1)

58-58: LGTM: Banner state namespace addition is well-integrated.

The addition of bannersState to the InternalStorageNamespace enum is consistent with the existing pattern and properly supports the new banner state management functionality.

packages/extension/src/libs/metrics/types.ts (2)

72-73: LGTM: Quote style consistency improvement.

The change from double quotes to single quotes improves code consistency across the codebase.


75-78: LGTM: Well-structured event enum for banner tracking.

The SolanaStakingBannerEvents enum follows the established naming pattern with descriptive event identifiers using dot notation, which will provide clear analytics tracking.

packages/extension/src/libs/banners-state/index.ts (1)

5-25: LGTM: Well-structured state management class.

The BannersState class provides a clean abstraction for managing banner visibility with proper initialization and storage handling.

packages/extension/src/ui/action/views/network-assets/components/network-assets-solana-staking-banner.vue (3)

1-41: LGTM: Well-structured promotional banner component.

The template structure is clean with proper layering of background, image, and content. The close button positioning and event handling are implemented correctly.


60-63: LGTM: Proper event tracking implementation.

The openStakingLink function correctly tracks user interactions before opening the external link, providing valuable analytics data.


9-17: Verify asset paths exist and consider using dynamic imports.

The hardcoded image paths should be verified to ensure the assets exist at the specified locations.

#!/bin/bash
# Verify that the banner asset images exist
fd -t f "solana-stacking-banner-bg.png" --exec echo "Found: {}"
fd -t f "solana-stacking-banner-tokens-img.png" --exec echo "Found: {}"
packages/extension/src/libs/metrics/index.ts (4)

15-16: LGTM: Import additions for banner event tracking.

The import statement is correctly updated to include the new SolanaStakingBannerEvents type.


29-41: LGTM: Improved parameter formatting consistency.

The change from commas to semicolons in the type annotations improves readability and consistency with TypeScript conventions.


97-106: LGTM: Improved function formatting with explicit return type.

The reformatting of trackUpdatesEvents to a multi-line function with explicit return type improves code readability and consistency.


118-120: LGTM: Consistent banner event tracking implementation.

The trackSolanaStakingBanner function follows the established pattern for event tracking and properly categorizes banner events under 'solStakingBanner'.

packages/extension/src/ui/action/views/network-assets/index.vue (1)

91-92: LGTM! Clean imports.

The component and BannersState imports are properly structured.

packages/extension/src/ui/action/components/app-menu/index.vue (2)

208-209: LGTM! Clean imports.

The component and BannersState imports are properly structured.


271-273: Clarify commented banner logic.

The banner display logic is commented out, which means the banner will never show in the app menu. Is this intentional for a gradual rollout or should this be enabled?

If this should be enabled, apply this diff:

-  // if (await bannersState.showSolanaStakingBanner()) {
-  //   isSolanaStackingBanner.value = true;
-  // }
+  try {
+    if (await bannersState.showSolanaStakingBanner()) {
+      isSolanaStakingBanner.value = true;
+    }
+  } catch (error) {
+    console.error('Failed to check banner state:', error);
+  }

@kvhnuke kvhnuke merged commit dc24615 into develop Jun 30, 2025
5 checks passed
@kvhnuke kvhnuke deleted the devop/release-2-9 branch June 30, 2025 17:38
@coderabbitai coderabbitai bot mentioned this pull request Jun 30, 2025
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.

6 participants