Repository: OneKeyHQ/app-monorepo
Pull request #7214: OK-37734: enhance RPC call handling with duplicate request management
Author: login: originalix
Created: 2025-04-25T08:31:23Z | Merged: 2025-04-25T09:02:32Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
	- Improved performance by preventing duplicate concurrent RPC calls, ensuring identical requests share the same response.
	- Reduced unnecessary error log output for account alignment failures.
- **Refactor**
	- Updated request cache key generation to use native JSON serialization for improved consistency.
	- Made cache key generation method publicly accessible for broader use.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/packages/kit-bg/src/providers/ProviderApiEthereum.ts b/packages/kit-bg/src/providers/ProviderApiEthereum.ts
index 41f8dc854009..71156b200b81 100644
--- a/packages/kit-bg/src/providers/ProviderApiEthereum.ts
+++ b/packages/kit-bg/src/providers/ProviderApiEthereum.ts
@@ -102,6 +102,9 @@ class ProviderApiEthereum extends ProviderApiBase {
 
   private _rpcCache?: RpcCache;
 
+  // Map to duplicate concurrent requests with same parameters
+  private _duplicateRequestsMap: Map<string, Promise<any>> = new Map();
+
   // return a mocked chainId in non-evm, as empty string may cause dapp error
   private _getNetworkMockInfo() {
     return {
@@ -156,50 +159,79 @@ class ProviderApiEthereum extends ProviderApiBase {
   }
 
   public async rpcCall(request: IJsBridgeMessagePayload): Promise<any> {
-    return this.rpcSemaphore.runExclusive(async () => {
-      const { data } = request;
-      const { accountInfo: { networkId, address } = {} } = (
-        await this.getAccountsInfo(request)
-      )[0];
-      const rpcRequest = data as IJsonRpcRequest;
-
-      const { method, params } = rpcRequest;
-
-      if (!EVM_SAFE_RPC_METHODS.includes(method)) {
-        defaultLogger.discovery.dapp.dappRequestNotSupport({ request });
-        throw web3Errors.rpc.methodNotSupported();
-      }
+    const { data } = request;
+    const rpcRequest = data as IJsonRpcRequest;
+    const { method } = rpcRequest;
 
-      if (!address || !networkId) {
-        throw web3Errors.rpc.invalidParams('unauthorized');
-      }
+    const { accountInfo: { networkId, address } = {} } = (
+      await this.getAccountsInfo(request)
+    )[0];
 
-      const cache = this.rpcCache.get({
-        address,
-        networkId,
-        data: { method, params },
-      });
+    const { params } = rpcRequest;
 
-      if (cache) {
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
-        return cache;
-      }
+    if (!EVM_SAFE_RPC_METHODS.includes(method)) {
+      defaultLogger.discovery.dapp.dappRequestNotSupport({ request });
+      throw web3Errors.rpc.methodNotSupported();
+    }
 
-      const [result] = await this.backgroundApi.serviceDApp.proxyRPCCall({
-        networkId: networkId ?? '',
-        request: rpcRequest,
-        origin: request.origin ?? '',
-      });
+    if (!address || !networkId) {
+      throw web3Errors.rpc.invalidParams('unauthorized');
+    }
 
-      this.rpcCache.set({
-        address,
-        networkId,
-        data: { method, params },
-        value: result,
-      });
+    // Check cache first
+    const cache = this.rpcCache.get({
+      address,
+      networkId,
+      data: { method, params },
+    });
 
-      return result;
+    if (cache) {
+      console.log('ethRpc cache hit: ===> ', method);
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+      return cache;
+    }
+
+    const requestKey = this.rpcCache.generateKey({
+      address,
+      networkId,
+      data: { method, params },
     });
+
+    // Check if there's a duplicate request in progress
+    const duplicateRequest = this._duplicateRequestsMap.get(requestKey);
+    if (duplicateRequest) {
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+      return duplicateRequest;
+    }
+
+    // Create a new promise for this request
+    const promise = this.rpcSemaphore.runExclusive(async () => {
+      try {
+        const [result] = await this.backgroundApi.serviceDApp.proxyRPCCall({
+          networkId: networkId ?? '',
+          request: rpcRequest,
+          origin: request.origin ?? '',
+        });
+
+        this.rpcCache.set({
+          address,
+          networkId,
+          data: { method, params },
+          value: result,
+        });
+
+        return result;
+      } finally {
+        // Remove from duplication map after completion
+        this._duplicateRequestsMap.delete(requestKey);
+      }
+    });
+
+    // Store the promise for duplication
+    this._duplicateRequestsMap.set(requestKey, promise);
+
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+    return promise;
   }
 
   @providerApiMethod()
diff --git a/packages/kit-bg/src/services/ServiceDApp.ts b/packages/kit-bg/src/services/ServiceDApp.ts
index ed6e66564b4b..b675b2da34ba 100644
--- a/packages/kit-bg/src/services/ServiceDApp.ts
+++ b/packages/kit-bg/src/services/ServiceDApp.ts
@@ -1373,7 +1373,7 @@ class ServiceDApp extends ServiceBase {
       //   origin,
       //   storageType,
       // });
-      console.log(`Build dApp Account Error: `, e);
+      // console.log(`Build dApp Account Error: `, e);
       // If build account error, use the previous account
       return connectedAccountInfo;
     }
diff --git a/packages/shared/src/rpcCache/RpcCache.ts b/packages/shared/src/rpcCache/RpcCache.ts
index 12dffe3da1af..0c5c91131a5a 100644
--- a/packages/shared/src/rpcCache/RpcCache.ts
+++ b/packages/shared/src/rpcCache/RpcCache.ts
@@ -1,5 +1,3 @@
-import stringify from 'fast-json-stable-stringify';
-
 import { RpcCacheMethodMap } from './constants';
 
 interface ICacheKey {
@@ -41,10 +39,10 @@ export class RpcCache {
     return this._randomKeys[networkId];
   }
 
-  private generateKey({ address, networkId, data }: ICacheKey): string {
+  generateKey({ address, networkId, data }: ICacheKey): string {
     return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
       networkId,
-    )}--${data.method}--${stringify(data.params)}`;
+    )}--${data.method}--${JSON.stringify(data.params)}`;
   }
 
   get(params: ICacheKey): any | undefined {


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

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

Reviewing files that changed from the base of the PR and between d8fc7ed61b01c4932f63f51da3bc37eeff8f7ca8 and b2dde88030f3f531b732e174dd02b11672466247.

</details>

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

* `packages/kit-bg/src/providers/ProviderApiEthereum.ts` (2 hunks)
* `packages/kit-bg/src/services/ServiceDApp.ts` (1 hunks)
* `packages/shared/src/rpcCache/RpcCache.ts` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>packages/kit-bg/src/providers/ProviderApiEthereum.ts (2)</summary>

`105-107`: **Good call introducing `_duplicateRequestsMap`**

Tracking in-flight calls before they hit the network neatly avoids N× identical requests.  
Clean-up in the `finally` block prevents leaks. Nice.

---

`194-206`: **Key construction depends on non-stable stringify**

`requestKey` relies on `RpcCache.generateKey`, which now uses `JSON.stringify`.  
For the same reasons as noted in `RpcCache.ts`, different property order will break deduplication here.

Please verify that every caller constructs `params` deterministically (arrays are fine; plain objects are not) or switch back to a stable stringifier.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T08:40:53Z
user: login: huhuanming
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T08:54:19Z
user: login: weatherstar
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:02:30Z

Review comments:
diff_hunk: @@ -41,10 +39,10 @@ export class RpcCache {
     return this._randomKeys[networkId];
   }
 
-  private generateKey({ address, networkId, data }: ICacheKey): string {
+  generateKey({ address, networkId, data }: ICacheKey): string {
     return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
       networkId,
-    )}--${data.method}--${stringify(data.params)}`;
+    )}--${data.method}--${JSON.stringify(data.params)}`;
   }
path: packages/shared/src/rpcCache/RpcCache.ts
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Using `JSON.stringify` risks cache-key drift**

`JSON.stringify` does not guarantee a stable property order across platforms or object-construction paths.  
If two logically identical `params` objects have different key insertion orders, they’ll produce different cache keys. Your new dedup / cache logic may silently miss hits and fire extra RPCs.

Consider restoring a stable stringifier (e.g. `fast-json-stable-stringify`) or sorting keys before serialisation.

```diff
-import { /* stringify removed */ }
+import stringify from 'fast-json-stable-stringify';
...
-return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
-  networkId,
-) }--${data.method}--${JSON.stringify(data.params)}`;
+return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
+  networkId,
+)}--${data.method}--${stringify(data.params)}`;
```

---



</details>

**Use a stable serializer for `data.params` in `generateKey`**

`JSON.stringify` can produce different key orders and lead to cache misses. Swap it out for a stable stringifier.

• File: `packages/shared/src/rpcCache/RpcCache.ts`  
• Method: `generateKey`

Suggested diff:
```diff
-import { /* no-op */ }
+import stringify from 'fast-json-stable-stringify';
 
 generateKey({ address, networkId, data }: ICacheKey): string {
-  return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
-    networkId,
-  )}--${data.method}--${JSON.stringify(data.params)}`;
+  return `${address ?? ''}--${networkId ?? ''}--${this.getRandomKey(
+    networkId,
+  )}--${data.method}--${stringify(data.params)}`;
 }
```
Make sure to add `fast-json-stable-stringify` to your dependencies.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T08:40:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -156,50 +159,79 @@ class ProviderApiEthereum extends ProviderApiBase {
   }
 
   public async rpcCall(request: IJsBridgeMessagePayload): Promise<any> {
-    return this.rpcSemaphore.runExclusive(async () => {
-      const { data } = request;
-      const { accountInfo: { networkId, address } = {} } = (
-        await this.getAccountsInfo(request)
-      )[0];
-      const rpcRequest = data as IJsonRpcRequest;
-
-      const { method, params } = rpcRequest;
-
-      if (!EVM_SAFE_RPC_METHODS.includes(method)) {
-        defaultLogger.discovery.dapp.dappRequestNotSupport({ request });
-        throw web3Errors.rpc.methodNotSupported();
-      }
+    const { data } = request;
+    const rpcRequest = data as IJsonRpcRequest;
+    const { method } = rpcRequest;
 
-      if (!address || !networkId) {
-        throw web3Errors.rpc.invalidParams('unauthorized');
-      }
+    const { accountInfo: { networkId, address } = {} } = (
+      await this.getAccountsInfo(request)
+    )[0];
 
-      const cache = this.rpcCache.get({
-        address,
-        networkId,
-        data: { method, params },
-      });
+    const { params } = rpcRequest;
 
-      if (cache) {
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
-        return cache;
-      }
+    if (!EVM_SAFE_RPC_METHODS.includes(method)) {
+      defaultLogger.discovery.dapp.dappRequestNotSupport({ request });
+      throw web3Errors.rpc.methodNotSupported();
+    }
 
-      const [result] = await this.backgroundApi.serviceDApp.proxyRPCCall({
-        networkId: networkId ?? '',
-        request: rpcRequest,
-        origin: request.origin ?? '',
-      });
+    if (!address || !networkId) {
+      throw web3Errors.rpc.invalidParams('unauthorized');
+    }
 
-      this.rpcCache.set({
-        address,
-        networkId,
-        data: { method, params },
-        value: result,
-      });
+    // Check cache first
+    const cache = this.rpcCache.get({
+      address,
+      networkId,
+      data: { method, params },
+    });
 
-      return result;
+    if (cache) {
+      console.log('ethRpc cache hit: ===> ', method);
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+      return cache;
+    }
path: packages/kit-bg/src/providers/ProviderApiEthereum.ts
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Swap `console.log` for structured logger**

Plain `console.log` slips through production builds and clutters dev-tools.  
Use `defaultLogger.discovery.dapp` (or similar) so verbosity is configurable.

```diff
-      console.log('ethRpc cache hit: ===> ', method);
+      defaultLogger.rpc.cacheHit(`ethRpc cache hit: ${method}`);
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
      defaultLogger.rpc.cacheHit(`ethRpc cache hit: ${method}`);
      // eslint-disable-next-line @typescript-eslint/no-unsafe-return
      return cache;
    }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T08:40:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1373,7 +1373,7 @@ class ServiceDApp extends ServiceBase {
       //   origin,
       //   storageType,
       // });
-      console.log(`Build dApp Account Error: `, e);
+      // console.log(`Build dApp Account Error: `, e);
       // If build account error, use the previous account
path: packages/kit-bg/src/services/ServiceDApp.ts
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Remove commented-out debug log**

The disabled `console.log` adds noise to the diff and may return later during merges.  
Delete it to keep the codebase tidy.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T08:40:53Z
author_association: CONTRIBUTOR

PR comments:
user: login: codesandbox[bot]
created_at: 2025-04-25T08:31:26Z
body: #### Review or Edit in CodeSandbox

Open the branch in <a href="https://codesandbox.io/p/github/OneKeyHQ/app-monorepo/fix/cache-duplicate-rpc-request?mode=review&utm_source=gh_app">Web Editor</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=OneKeyHQ&repo=app-monorepo&branch=fix/cache-duplicate-rpc-request&utm_source=gh_app">VS Code</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=OneKeyHQ&repo=app-monorepo&branch=fix/cache-duplicate-rpc-request&insiders=true&utm_source=gh_app">Insiders</a><br>
Open <a href="https://codesandbox.io/p/devtool/preview/OneKeyHQ/app-monorepo/fix/cache-duplicate-rpc-request?task=preview&port=51423&redirect=true&utm_source=gh_app">Preview</a>

<!-- open-in-codesandbox:complete -->

author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-04-25T08:31:30Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update adds deduplication for Ethereum RPC requests in the `ProviderApiEthereum` class. It tracks ongoing identical requests and reuses their promises, preventing multiple concurrent calls with the same parameters. The change also adjusts the cache key generation in `RpcCache` to use `JSON.stringify` and makes the method public. A console log in `ServiceDApp` is commented out, but error handling remains unchanged.

## Changes

| File(s)                                                                                 | Change Summary                                                                                           |
|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| packages/kit-bg/src/providers/ProviderApiEthereum.ts                                    | Adds a map to track duplicate requests and refactors `rpcCall` to deduplicate concurrent RPC calls.      |
| packages/shared/src/rpcCache/RpcCache.ts                                                | Removes stable stringify dependency, makes `generateKey` public, and uses `JSON.stringify` for keys.     |
| packages/kit-bg/src/services/ServiceDApp.ts                                             | Comments out a console log in error handling; no impact on logic or exports.                             |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Caller1
    participant Caller2
    participant ProviderApiEthereum
    participant RpcCache

    Caller1->>ProviderApiEthereum: rpcCall(request)
    ProviderApiEthereum->>RpcCache: check cache for key
    RpcCache-->>ProviderApiEthereum: cache miss
    ProviderApiEthereum->>ProviderApiEthereum: check _duplicateRequestsMap
    alt No existing promise
        ProviderApiEthereum->>ProviderApiEthereum: create new promise
        ProviderApiEthereum->>RpcCache: store result in cache
        ProviderApiEthereum->>ProviderApiEthereum: remove promise from map
        ProviderApiEthereum-->>Caller1: return result
    else Existing promise
        ProviderApiEthereum-->>Caller1: return existing promise
    end

    Caller2->>ProviderApiEthereum: rpcCall(same request)
    ProviderApiEthereum->>RpcCache: check cache for key
    RpcCache-->>ProviderApiEthereum: cache miss
    ProviderApiEthereum->>ProviderApiEthereum: find existing promise in map
    ProviderApiEthereum-->>Caller2: return existing promise
```

## Assessment against linked issues

| Objective                                                        | Addressed | Explanation                                                                                  |
|------------------------------------------------------------------|-----------|----------------------------------------------------------------------------------------------|
| Deduplicate concurrent EVM RPC proxy requests to reduce load (OK-37734) | ✅        |                                                                                              |

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

---



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

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=OneKeyHQ/app-monorepo&utm_content=7214):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `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 generate unit testing code for this file.`
  -	`@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 generate unit testing code.`
  - `@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.`

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` or `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.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### 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 -->
author_association: CONTRIBUTOR