Skip to content

Conversation

@cryptonoyaiba
Copy link
Contributor

@cryptonoyaiba cryptonoyaiba commented Jul 22, 2025

Description

  • Add Pulse class with installPulseModules() and addHook() methods
  • Define HookType enum and PulseConfig interface
  • Add HookMultiplexer ABI support
  • Integrate Pulse into ModularSdk via pulse getter
  • Update example to use new Pulse methods
  • Support automated Hook Multiplexer, Credible Account, and Resource Lock Validator installation
  • Updated network configs for Sepolia to use latest version of Bootstrap that installs the Hooks before Validators
  • Added new fields to NetworkConfig object to now include "credibleAccountModule" and "ResourceLockValidator"

Types of changes

What types of changes does your code introduce?

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Other (please describe):

Further comments (optional)

  • Tested using examples/pulse/install-latest-pulse-modules.ts

Summary by CodeRabbit

  • New Features

    • Introduced a new Pulse module with tools for installing and managing Pulse ecosystem smart contract modules.
    • Added a utility script to automate Pulse module installation on the Sepolia network.
    • Provided new interfaces and enums for Pulse configuration and hook management.
    • Enabled centralized access to Pulse-related features via a new module entry point.
    • Integrated Pulse functionality into the SDK with a dedicated getter for streamlined access.
  • Enhancements

    • Added contract address fields for credible account module, resource lock validator, and a new Hook Multiplexer V2 to network configurations.
    • Updated the Sepolia network bootstrap contract address.
  • Chores

    • Incremented the SDK package version to 6.1.1.
  • Style

    • Improved code formatting and consistency across the SDK.
  • Bug Fixes

    • Disabled retries on a specific RPC request to improve reliability.

- Add Pulse class with installPulseModules() and addHook() methods
- Define HookType enum and PulseConfig interface
- Add HookMultiplexer ABI support
- Integrate Pulse into ModularSdk via pulse getter
- Update example to use new Pulse methods
- Support automated Hook Multiplexer, Credible Account, and Resource Lock Validator installation
- Updated network configs for Sepolia to use latest version of Bootstrap that installs the Hooks before Validators
- Added new fields to NetworkConfig object to now include "credibleAccountModule" and "ResourceLockValidator"
@coderabbitai
Copy link

coderabbitai bot commented Jul 22, 2025

Walkthrough

This change introduces a new Pulse module management feature to the modular SDK. It adds a Pulse class with methods for installing, uninstalling, and verifying Pulse ecosystem modules. Supporting utilities, interfaces, and constants are added, and a new example script demonstrates module installation. Minor formatting and a new Pulse getter are added to the SDK core. The Sepolia network configuration is updated with new contract addresses, and the package version is bumped.

Changes

File(s) Change Summary
examples/pulse/install-latest-pulse-modules.ts New example script to automate Pulse module installation and verification on Sepolia.
package.json Bumped @etherspot/modular-sdk version from 6.1.0 to 6.1.1.
src/sdk/network/constants.ts, src/sdk/network/interfaces.ts Added hookMultiPlexerV2 contract address to all networks; updated interface accordingly.
src/sdk/pulse/constants.ts Added new exported enum HookType for hook type identifiers.
src/sdk/pulse/index.ts New module entry point re-exporting Pulse class, interfaces, and utilities.
src/sdk/pulse/interfaces.ts New interfaces: PulseConfig and SigHookInit for Pulse module configuration and signature hooks.
src/sdk/pulse/pulse.ts New Pulse class for installing, uninstalling, and verifying Pulse modules; supports hook management.
src/sdk/pulse/utils.ts New utility functions for encoding HookMultiplexer initialization data and ABI.
src/sdk/sdk.ts Formatting/refactoring; added private _pulse property and lazy pulse getter to ModularSdk.
src/sdk/base/HttpRpcClient.ts Modified RPC request to disable retries for eth_sendUserOperation calls.
CHANGELOG.md Added changelog entries describing new Pulse features, updated network config, and example scripts.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ExampleScript
    participant ModularSdk
    participant Pulse
    participant Blockchain

    User->>ExampleScript: Run install-latest-pulse-modules.ts
    ExampleScript->>ModularSdk: Initialize with config
    ExampleScript->>ModularSdk: Get counterfactual address & balance
    ExampleScript->>Pulse: modularSdk.pulse.installPulseModules(config)
    Pulse->>ModularSdk: Retrieve network config and addresses
    Pulse->>Pulse: (Optional) Uninstall old HookMultiplexer
    Pulse->>Pulse: Install HookMultiplexer, CredibleAccountModule, ResourceLockValidator
    Pulse->>ModularSdk: Batch and send user operation
    ModularSdk->>Blockchain: Submit user operation
    Blockchain-->>ModularSdk: Return userOpHash
    ExampleScript->>Blockchain: Poll for receipt
    Blockchain-->>ExampleScript: Return receipt/status
    ExampleScript->>Pulse: isPulseModulesInstalled(config)
    Pulse->>ModularSdk: Check installed modules
    Pulse-->>ExampleScript: Return install status
    ExampleScript->>User: Log results and exit
Loading

Estimated code review effort

4 (~90 minutes)

Possibly related PRs

Suggested reviewers

  • kanthgithub
  • vignesha22
  • ch4r10t33r

Poem

Hopping through the modular code,
A rabbit brings new Pulse to load.
With hooks and modules, neat and bright,
Sepolia’s ready, install takes flight!
From ABI to install, all’s in sync,
Version bumped with a happy wink.
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/pulse/install-latest-pulse-modules.ts

Oops! Something went wrong! :(

ESLint: 8.28.0

ReferenceError: Cannot read config file: /.eslintrc.js
Error: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///.eslintrc.js:1:1
at ModuleJobSync.runSync (node:internal/modules/esm/module_job:498:37)
at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:437:47)
at loadESMFromCJS (node:internal/modules/cjs/loader:1523:24)
at Module._compile (node:internal/modules/cjs/loader:1674:5)
at Object..js (node:internal/modules/cjs/loader:1824:10)
at Module.load (node:internal/modules/cjs/loader:1427:32)
at Module._load (node:internal/modules/cjs/loader:1250:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb052ee and 0ca59ab.

📒 Files selected for processing (1)
  • examples/pulse/install-latest-pulse-modules.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/pulse/install-latest-pulse-modules.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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.

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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

Yooo! You forgot to bump the version in package.json!

- CircleCI fix (explicit import path change)
@github-actions
Copy link

Yooo! You forgot to bump the version in package.json!

- Version bump
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: 5

🧹 Nitpick comments (5)
src/sdk/pulse/interfaces.ts (1)

3-9: Consider using Hex type for address fields for better type safety

The address fields in PulseConfig are typed as string, but using the Hex type from viem would provide better type safety and consistency with the rest of the codebase.

export interface PulseConfig {
-  hookMultiplexerAddress?: string;
-  credibleAccountModuleAddress?: string;
-  resourceLockValidatorAddress?: string;
+  hookMultiplexerAddress?: Hex;
+  credibleAccountModuleAddress?: Hex;
+  resourceLockValidatorAddress?: Hex;
  uninstallOldHookMultiplexer?: boolean;
-  oldHookMultiplexerAddress?: string;
+  oldHookMultiplexerAddress?: Hex;
}
examples/pulse/install-latest-pulse-modules.ts (1)

45-47: Remove commented code

The commented line should be removed if not needed, or uncommented if it's intended to be used.

      uninstallOldHookMultiplexer: false,
-      // oldHookMultiplexerAddress: HOOK_MULTIPLEXER_ADDRESS,
src/sdk/sdk.ts (1)

263-263: Use optional chaining for cleaner code

The condition can be simplified using optional chaining.

-    if (version && version.includes('skandha')) return this.bundler.getSkandhaGasPrice();
+    if (version?.includes('skandha')) return this.bundler.getSkandhaGasPrice();
src/sdk/pulse/pulse.ts (2)

132-132: Remove commented code

The commented line should be removed if not needed.

    const hmpInitData = getHookMultiPlexerInitData([credibleAccountModuleAddress]);
-    // const config = _makeBootstrapConfig(hookMultiplexerAddress, hmpInitData);

7-7: Unused import

The _makeBootstrapConfig import is not used and should be removed.

-import { _makeBootstrapConfig } from '../base/Bootstrap.js';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05dd049 and 0f32ec9.

📒 Files selected for processing (10)
  • examples/pulse/install-latest-pulse-modules.ts (1 hunks)
  • package.json (1 hunks)
  • src/sdk/network/constants.ts (36 hunks)
  • src/sdk/network/interfaces.ts (1 hunks)
  • src/sdk/pulse/constants.ts (1 hunks)
  • src/sdk/pulse/index.ts (1 hunks)
  • src/sdk/pulse/interfaces.ts (1 hunks)
  • src/sdk/pulse/pulse.ts (1 hunks)
  • src/sdk/pulse/utils.ts (1 hunks)
  • src/sdk/sdk.ts (13 hunks)
🧬 Code Graph Analysis (2)
src/sdk/pulse/utils.ts (1)
src/sdk/pulse/interfaces.ts (1)
  • SigHookInit (11-14)
src/sdk/sdk.ts (7)
src/sdk/pulse/pulse.ts (1)
  • Pulse (12-203)
src/sdk/common/utils/viem-utils.ts (2)
  • getPublicClientByChain (29-35)
  • getPublicClient (21-27)
src/sdk/network/constants.ts (1)
  • Networks (91-649)
src/sdk/interfaces.ts (1)
  • PaymasterApi (4-7)
src/sdk/errorHandler/errorHandler.service.ts (1)
  • ErrorHandler (3-17)
src/sdk/base/VerifyingPaymasterAPI.ts (1)
  • VerifyingPaymasterAPI (27-100)
src/sdk/common/interfaces.ts (2)
  • UserOpsRequest (9-13)
  • BatchUserOpsRequest (3-7)
🪛 Gitleaks (8.27.2)
src/sdk/network/constants.ts

118-118: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Biome (1.9.4)
src/sdk/sdk.ts

[error] 263-263: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧰 Additional context used
🧬 Code Graph Analysis (2)
src/sdk/pulse/utils.ts (1)
src/sdk/pulse/interfaces.ts (1)
  • SigHookInit (11-14)
src/sdk/sdk.ts (7)
src/sdk/pulse/pulse.ts (1)
  • Pulse (12-203)
src/sdk/common/utils/viem-utils.ts (2)
  • getPublicClientByChain (29-35)
  • getPublicClient (21-27)
src/sdk/network/constants.ts (1)
  • Networks (91-649)
src/sdk/interfaces.ts (1)
  • PaymasterApi (4-7)
src/sdk/errorHandler/errorHandler.service.ts (1)
  • ErrorHandler (3-17)
src/sdk/base/VerifyingPaymasterAPI.ts (1)
  • VerifyingPaymasterAPI (27-100)
src/sdk/common/interfaces.ts (2)
  • UserOpsRequest (9-13)
  • BatchUserOpsRequest (3-7)
🪛 Gitleaks (8.27.2)
src/sdk/network/constants.ts

118-118: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Biome (1.9.4)
src/sdk/sdk.ts

[error] 263-263: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (8)
package.json (1)

3-3: LGTM - Appropriate version bump for new feature.

The version increment from "6.1.0" to "6.1.1" is appropriate for the addition of new Pulse module functionality.

src/sdk/network/interfaces.ts (1)

20-23: LGTM - Interface properly extended for Pulse modules.

The addition of credibleAccountModule and resourceLockValidator properties to the contracts object correctly supports the new Pulse ecosystem functionality. The interface syntax is also properly formatted.

src/sdk/pulse/constants.ts (1)

1-7: LGTM - Well-structured enum for hook types.

The HookType enum provides clear, type-safe constants with appropriate hexadecimal values for different hook categories. This will ensure consistent usage across the Pulse module.

src/sdk/pulse/index.ts (1)

1-3: LGTM - Clean barrel export pattern.

The index file properly centralizes all Pulse module exports, providing a clean public API surface for the new functionality.

src/sdk/network/constants.ts (3)

105-106: LGTM - Consistent addition of new contract fields across all networks.

The new credibleAccountModule and resourceLockValidator fields are properly added to all network configurations, maintaining consistency across the SDK.

Also applies to: 120-121, 136-137, 151-152, 166-167, 181-182, 196-197, 211-212, 227-228, 242-243, 257-258, 272-273, 287-288, 302-303, 317-318, 332-333, 347-348, 362-363, 377-378, 392-393, 407-408, 422-423, 437-438, 452-453, 467-468, 482-483, 497-498, 512-513, 527-528, 542-543, 557-558, 572-573, 587-588, 602-603, 617-618, 645-646


116-116: LGTM - Bootstrap address update for Sepolia network.

The bootstrap contract address update for Sepolia appears to be a legitimate upgrade to use the latest version that supports the new Pulse functionality.


118-118: Static analysis false positive - this is a valid contract address.

The static analysis tool flagged this as a potential API key, but this is actually a valid Ethereum contract address for the erc20SessionKeyValidator on the Sepolia network. Contract addresses are public information and not sensitive credentials.

src/sdk/sdk.ts (1)

52-52: Well-implemented lazy initialization for Pulse module

The lazy initialization pattern for the Pulse module is well-implemented, providing good encapsulation and on-demand instantiation.

Also applies to: 133-138

} = config;

// Get network config
const chainId = this.modularSdk['chainId'];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid accessing private properties of ModularSdk

The code accesses the private chainId property of ModularSdk in multiple places. This breaks encapsulation and could break if the internal implementation changes.

Consider adding a public getter method to ModularSdk to expose the chainId:

In ModularSdk:

getChainId(): number {
  return this.chainId;
}

Then update the Pulse class to use:

-    const chainId = this.modularSdk['chainId'];
+    const chainId = this.modularSdk.getChainId();

Also applies to: 91-91, 166-166

🤖 Prompt for AI Agents
In src/sdk/pulse/pulse.ts at lines 38, 91, and 166, the code accesses the
private property 'chainId' of ModularSdk directly, breaking encapsulation. To
fix this, add a public getter method getChainId() in the ModularSdk class that
returns this.chainId, then update the Pulse class to call this public method
instead of accessing the private property directly.

throw new ErrorHandler('Hook Multiplexer address not found in network configuration');
}

const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;
Copy link

@coderabbitai coderabbitai bot Jul 22, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unused variable

The address variable is retrieved but never used in the addHook method.

-    const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;
-
    // Clear existing UserOps from batch
    await this.modularSdk.clearUserOpsFromBatch();
📝 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.

Suggested change
const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;
// src/sdk/pulse/pulse.ts
// … existing code …
// Clear existing UserOps from batch
await this.modularSdk.clearUserOpsFromBatch();
// … following code …
🤖 Prompt for AI Agents
In src/sdk/pulse/pulse.ts at line 179, the variable `address` is assigned but
never used in the addHook method. Remove the declaration and assignment of the
`address` variable to clean up the code and avoid unused variable warnings.

Copy link
Contributor

Choose a reason for hiding this comment

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

agree with AI here

Copy link

Choose a reason for hiding this comment

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

@nikhilkumar1612 I'll help you remove that unused variable from the addHook method.

Task: Remove unused variable from addHook method

  • Remove the unused address variable declaration in the addHook method
  • Clean up the code to avoid unused variable warnings

The change will be implemented by another agent. This removes the unused variable and cleans up the code as suggested.


⏳ Preparing changes...

Copy link

Choose a reason for hiding this comment

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

A summary of the changes CodeRabbit can apply:

  • Remove the unused address variable declaration from the addHook method in src/sdk/pulse/pulse.ts to clean up the code.
  • ✅ Create PR with these edits
  • 📌 Create commit in current branch
  • 📋 Get copyable edits

Comment on lines +58 to +64
const encodedData = encodeAbiParameters(abiType, [
globalHooks,
valueHooks,
delegatecallHooks,
sigHooks,
targetSigHooks,
] as any);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid using 'any' type casting

The as any type casting defeats TypeScript's type safety. Consider properly typing the parameters.

The type casting to any appears to be used to bypass TypeScript's type checking for the tuple array parameters. This should be addressed by properly typing the function parameters to match the expected ABI types.

🤖 Prompt for AI Agents
In src/sdk/pulse/utils.ts around lines 58 to 64, the use of 'as any' to cast the
array passed to encodeAbiParameters bypasses TypeScript's type safety. To fix
this, define the array with the correct tuple type that matches the expected ABI
parameter types instead of using 'any'. Adjust the types of globalHooks,
valueHooks, delegatecallHooks, sigHooks, and targetSigHooks or create a properly
typed tuple to pass to encodeAbiParameters, ensuring full type safety without
casting.

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: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

3-14: Consider bumping the minor version instead of patch & fix naming inconsistencies

– According to SemVer, introducing new public-facing functionality (Pulse class, SDK getter, new enum/interface, etc.) is a MINOR change, so 6.2.0 would be more appropriate than 6.1.1.
– The bullet list mixes camelCase (resourceLockValidator) with Pascal Case (Resource Lock Validator) and inconsistent capitalisation of credibleAccountModule. Align the field names with the exact identifiers used in code to avoid confusion.

Example diff:

-## [6.1.1] - 2025-07-22
+## [6.2.0] - 2025-07-22
 ...
-- Support for automated Hook Multiplexer, Credible Account, and Resource Lock Validator installation
-- Added `credibleAccountModule` and `resourceLockValidator` fields to `NetworkConfig` object
+- Support for automated Hook Multiplexer, *CredibleAccount* module, and *ResourceLockValidator* installation
+- Added `credibleAccountModule` and `resourceLockValidator` fields to `NetworkConfig`
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f32ec9 and cb35087.

📒 Files selected for processing (1)
  • CHANGELOG.md (1 hunks)

- Removed logs from pulse/constants.ts
- Increased polling on example for getting UserOpReceipt to reduce unnecessary load
entryPoint: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
walletFactory: '0x38CC0EDdD3a944CA17981e0A19470d2298B8d43a',
bootstrap: '0xCF2808eA7d131d96E5C73Eb0eCD8Dc84D33905C7',
bootstrap: '0x6e5E238F8cA164CDe6a8C88407FB242b05524658',
Copy link
Contributor

Choose a reason for hiding this comment

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

@cryptonoyaiba i dont think we have to change the bootstrap address as it will result in a different counterfactual wallet address

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry yes, you are right. I change this back and also I noticed im using an outdated contract addresses for modules. I'll deploy and update

- Updated Pulse contract module addresses on Sepolia to latest.
- Reverted Bootstrap contract address on Sepolia back to original.
- Adjusted latest Pulse module example script to use new addresses.
…spot/etherspot-modular-sdk into feature/hook-multiplexer-migration
- Fix for incorrect HookType assignment
throw new ErrorHandler('Hook Multiplexer address not found in network configuration');
}

const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;
Copy link
Contributor

Choose a reason for hiding this comment

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

agree with AI here

- Updated PulseConfig to no longer use hookMultiPlexer addresses as taking from NetworkConfigs and made credibleAccountModule and resourceLockValidator addresses mandatory
- Removed credibleAccountModule and resourceLockValidator fields from NetworkConfig as these will be passed in via intent-sdk
- Updated pulse functions to match this.
- Updated install-latest-pulse-modules example to match this.
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: 2

♻️ Duplicate comments (4)
src/sdk/pulse/pulse.ts (4)

32-32: Avoid accessing private properties of ModularSdk

The code accesses the private chainId property of ModularSdk. This breaks encapsulation and could break if the internal implementation changes.


85-85: Avoid accessing private properties of ModularSdk

The code accesses the private chainId property of ModularSdk. This breaks encapsulation.


160-160: Avoid accessing private properties of ModularSdk

The code accesses the private chainId property of ModularSdk. This breaks encapsulation.


173-173: Remove unused variable

The address variable is retrieved but never used in the addHook method.

🧹 Nitpick comments (1)
src/sdk/pulse/pulse.ts (1)

126-126: Remove commented code or provide explanation.

There's commented code referencing _makeBootstrapConfig. Either remove it if it's no longer needed or add a comment explaining why it's kept for future reference.

const hmpInitData = getHookMultiPlexerInitData([credibleAccountModuleAddress]);
-// const config = _makeBootstrapConfig(hookMultiplexerAddress, hmpInitData);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a70c9b6 and 4c3615a.

📒 Files selected for processing (5)
  • examples/pulse/install-latest-pulse-modules.ts (1 hunks)
  • src/sdk/network/constants.ts (35 hunks)
  • src/sdk/network/interfaces.ts (1 hunks)
  • src/sdk/pulse/interfaces.ts (1 hunks)
  • src/sdk/pulse/pulse.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/sdk/network/constants.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/sdk/network/interfaces.ts
  • examples/pulse/install-latest-pulse-modules.ts
🔇 Additional comments (2)
src/sdk/pulse/interfaces.ts (1)

1-12: LGTM! Clean and well-structured interface definitions.

The interfaces are properly typed and follow TypeScript best practices. The PulseConfig interface appropriately uses optional properties where needed, and the type imports are correct.

src/sdk/pulse/pulse.ts (1)

149-149: No security issue with EOA address in ResourceLockValidator initialization
The installResourceLockValidator method encodes the wallet’s EOA address into the module’s initData—this is a public identifier (not a secret key) and must be supplied so the validator knows which address is authorized to unlock resources. Exposing it in transaction calldata is expected and safe (all calldata is on-chain, public). This matches existing patterns elsewhere in the SDK.

No changes required.

Comment on lines 28 to 75
async installPulseModules(config: PulseConfig): Promise<string> {
const { credibleAccountModuleAddress, resourceLockValidatorAddress, uninstallOldHookMultiplexer = false } = config;

// Get network config
const chainId = this.modularSdk['chainId'];
const networkConfig = Networks[chainId];
if (!networkConfig) {
throw new ErrorHandler('Network configuration not found for chain ID: ' + chainId);
}

// Use provided addresses or fall back to network defaults
const HOOK_MULTIPLEXER_ADDRESS_V2 = networkConfig.contracts.hookMultiPlexerV2 as Hex;
const CREDIBLE_ACCOUNT_MODULE_ADDRESS = (credibleAccountModuleAddress ||
networkConfig.contracts.credibleAccountModule) as Hex;
const RESOURCE_LOCK_VALIDATOR_ADDRESS = (resourceLockValidatorAddress ||
networkConfig.contracts.resourceLockValidator) as Hex;
const HOOK_MULTIPLEXER_ADDRESS = networkConfig.contracts.hookMultiPlexer as Hex;

if (!HOOK_MULTIPLEXER_ADDRESS_V2 || !CREDIBLE_ACCOUNT_MODULE_ADDRESS || !RESOURCE_LOCK_VALIDATOR_ADDRESS) {
throw new ErrorHandler('Required contract addresses not found in network configuration');
}

// Get wallet address
const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;

// Clear existing UserOps from batch
await this.modularSdk.clearUserOpsFromBatch();

// Uninstall old hook multiplexer if requested and installed
if (uninstallOldHookMultiplexer && HOOK_MULTIPLEXER_ADDRESS) {
await this.uninstallOldHookMultiplexer(address, HOOK_MULTIPLEXER_ADDRESS);
}

// Install Hook Multiplexer with Credible Account Module as subhook
await this.installHookMultiplexer(address, HOOK_MULTIPLEXER_ADDRESS_V2, CREDIBLE_ACCOUNT_MODULE_ADDRESS);

// Install Credible Account Module as Validator
await this.installCredibleAccountValidator(address, CREDIBLE_ACCOUNT_MODULE_ADDRESS);

// Install Resource Lock Validator
await this.installResourceLockValidator(address, RESOURCE_LOCK_VALIDATOR_ADDRESS);

// Estimate and send the UserOp
const op = await this.modularSdk.estimate();
const uoHash = await this.modularSdk.send(op);

return uoHash;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding transaction confirmation and error handling.

The installPulseModules method performs multiple critical operations but lacks robust error handling and transaction confirmation. If any intermediate step fails, the user operation may be in an inconsistent state.

Consider wrapping the installation process in try-catch blocks and adding transaction confirmation:

async installPulseModules(config: PulseConfig): Promise<string> {
+  try {
    const { credibleAccountModuleAddress, resourceLockValidatorAddress, uninstallOldHookMultiplexer = false } = config;
    
    // ... existing code ...
    
    // Estimate and send the UserOp
    const op = await this.modularSdk.estimate();
    const uoHash = await this.modularSdk.send(op);
    
+    // Wait for transaction confirmation
+    await this.waitForTransaction(uoHash);
    
    return uoHash;
+  } catch (error) {
+    // Clear any pending operations on failure
+    await this.modularSdk.clearUserOpsFromBatch();
+    throw new ErrorHandler(`Failed to install Pulse modules: ${error.message}`);
+  }
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/sdk/pulse/pulse.ts between lines 28 and 75, the installPulseModules
method lacks error handling and transaction confirmation, risking inconsistent
states if steps fail. Wrap the entire installation process in a try-catch block
to catch and handle errors gracefully. After sending the user operation, add
logic to confirm the transaction completion before returning, ensuring each step
completes successfully or errors are properly managed.

const addHookCalldata = encodeFunctionData({
abi: HookMultiplexer,
functionName: 'addHook',
args: [hookAddress as Hex, hookType as Hex],
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate hook address format before encoding.

The method casts hookAddress to Hex without validation. This could lead to runtime errors if an invalid address format is provided.

Add address validation before encoding:

+// Validate hook address format
+if (!hookAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
+  throw new ErrorHandler('Invalid hook address format');
+}
+
// Encode the addHook function call
const addHookCalldata = encodeFunctionData({
  abi: HookMultiplexer,
  functionName: 'addHook',
  args: [hookAddress as Hex, hookType as Hex],
});
📝 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.

Suggested change
args: [hookAddress as Hex, hookType as Hex],
// Validate hook address format
if (!hookAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
throw new ErrorHandler('Invalid hook address format');
}
// Encode the addHook function call
const addHookCalldata = encodeFunctionData({
abi: HookMultiplexer,
functionName: 'addHook',
args: [hookAddress as Hex, hookType as Hex],
});
🤖 Prompt for AI Agents
In src/sdk/pulse/pulse.ts at line 182, the code casts hookAddress to Hex without
validating its format, which risks runtime errors. Add a validation step before
this line to check if hookAddress is a valid address format, and only proceed
with encoding if it passes validation. If invalid, handle the error
appropriately, such as throwing an error or returning early.

- Added missing hookMultiPlexerV2 param in NetworkConfig for chain id 79479957.
- Updated pulse function params to no longer decide between network config variable and passed in parameter for credibleAccountModule and resourceLockValidator.
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: 0

♻️ Duplicate comments (4)
src/sdk/pulse/pulse.ts (4)

78-101: Fix private property access in status check method.

The method correctly checks module installation status but accesses the private chainId property directly, breaking encapsulation.

async isPulseModulesInstalled(config: PulseConfig): Promise<{
  hookMultiPlexer: boolean;
  credibleAccountValidator: boolean;
  resourceLockValidator: boolean;
}> {
- const chainId = this.modularSdk['chainId'];
+ const chainId = this.modularSdk.getChainId(); // Assumes public getter exists
  const networkConfig = Networks[chainId];
  
  // ... rest of the method remains the same
}

32-32: Fix encapsulation violation by accessing private chainId property.

The code accesses the private chainId property of ModularSdk in multiple places, breaking encapsulation and potentially causing issues if the internal implementation changes.

Verify if a public getter method exists for chainId in ModularSdk:

#!/bin/bash
# Check if ModularSdk has a public chainId getter method
ast-grep --pattern $'class ModularSdk {
  $$$
  getChainId() {
    $$$
  }
  $$$
}'

# Also check for any public chainId property or method
rg -A 3 "chainId.*:" --include="*.ts" | head -20

Also applies to: 83-83, 156-156


28-73: Add comprehensive error handling and transaction confirmation.

The installPulseModules method performs multiple critical operations but lacks robust error handling. If any intermediate step fails, the user operation may be in an inconsistent state. Additionally, there's still the issue of accessing private chainId property directly.

Consider adding comprehensive error handling:

async installPulseModules(config: PulseConfig): Promise<string> {
+  try {
    const { credibleAccountModuleAddress, resourceLockValidatorAddress, uninstallOldHookMultiplexer = false } = config;

    // Get network config
-   const chainId = this.modularSdk['chainId'];
+   const chainId = this.modularSdk.getChainId(); // Assumes public getter exists
    const networkConfig = Networks[chainId];
    if (!networkConfig) {
      throw new ErrorHandler('Network configuration not found for chain ID: ' + chainId);
    }

    // ... rest of the method ...

    // Estimate and send the UserOp
    const op = await this.modularSdk.estimate();
    const uoHash = await this.modularSdk.send(op);

+   // Wait for transaction confirmation if needed
+   // await this.waitForTransaction(uoHash);

    return uoHash;
+  } catch (error) {
+    // Clear any pending operations on failure
+    await this.modularSdk.clearUserOpsFromBatch();
+    throw new ErrorHandler(`Failed to install Pulse modules: ${error.message}`);
+  }
}

154-192: Multiple issues need to be addressed in addHook method.

This method has several issues that were identified in previous reviews: unused variable, private property access, and missing input validation.

async addHook(hookAddress: string, hookType: HookType, hookMultiplexerAddress?: string): Promise<string> {
  // Get network config
- const chainId = this.modularSdk['chainId'];
+ const chainId = this.modularSdk.getChainId(); // Assumes public getter exists
  const networkConfig = Networks[chainId];
  if (!networkConfig) {
    throw new ErrorHandler('Network configuration not found for chain ID: ' + chainId);
  }

  // Use provided address or fall back to network default
  const HOOK_MULTIPLEXER_ADDRESS = (hookMultiplexerAddress || networkConfig.contracts.hookMultiPlexer) as Hex;

  if (!HOOK_MULTIPLEXER_ADDRESS) {
    throw new ErrorHandler('Hook Multiplexer address not found in network configuration');
  }

+ // Validate hook address format
+ if (!hookAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
+   throw new ErrorHandler('Invalid hook address format');
+ }

- const address: Hex = (await this.modularSdk.getCounterFactualAddress()) as Hex;
-
  // Clear existing UserOps from batch
  await this.modularSdk.clearUserOpsFromBatch();

  // Encode the addHook function call
  const addHookCalldata = encodeFunctionData({
    abi: HookMultiplexer,
    functionName: 'addHook',
    args: [hookAddress as Hex, hookType as Hex],
  });

  // Add the call to the batch (calling addHook on the Hook Multiplexer)
  await this.modularSdk.addUserOpsToBatch({
    to: HOOK_MULTIPLEXER_ADDRESS,
    data: addHookCalldata,
  });

  // Estimate and send the UserOp
  const op = await this.modularSdk.estimate();
  const uoHash = await this.modularSdk.send(op);

  return uoHash;
}
🧹 Nitpick comments (1)
src/sdk/pulse/pulse.ts (1)

116-130: Remove commented code and improve readability.

The method is functionally correct but contains commented-out code that should be removed for cleaner code.

private async installHookMultiplexer(
  address: Hex,
  hookMultiplexerAddress: Hex,
  credibleAccountModuleAddress: Hex,
): Promise<void> {
  const hmpInitData = getHookMultiPlexerInitData([credibleAccountModuleAddress]);
- // const config = _makeBootstrapConfig(hookMultiplexerAddress, hmpInitData);

  const hmpInstallCalldata = encodeFunctionData({
    abi: parseAbi(accountAbi),
    functionName: 'installModule',
    args: [BigInt(MODULE_TYPE.HOOK), hookMultiplexerAddress, hmpInitData],
  });
  await this.modularSdk.addUserOpsToBatch({ to: address, data: hmpInstallCalldata });
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c3615a and cb052ee.

📒 Files selected for processing (2)
  • src/sdk/network/constants.ts (36 hunks)
  • src/sdk/pulse/pulse.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sdk/network/constants.ts
🔇 Additional comments (5)
src/sdk/pulse/pulse.ts (5)

1-11: LGTM! Clean imports and dependencies.

The import statements are well-organized, importing necessary modules from the SDK ecosystem including viem utilities, network configurations, and Pulse-specific interfaces.


12-17: LGTM! Simple and clean class structure.

The Pulse class constructor properly initializes with a ModularSdk instance, following good encapsulation practices.


103-114: LGTM! Well-structured uninstall logic.

The method properly checks if the old module is installed before attempting to uninstall it, preventing unnecessary operations. The ABI encoding and function call setup is correct.


132-142: LGTM! Clean validator installation implementation.

The Credible Account Validator installation logic is well-structured with proper ABI encoding and parameter handling.


144-152: LGTM! Resource Lock Validator setup is correct.

The method properly initializes the Resource Lock Validator with the EOA address, which is the expected configuration for this validator type.

Copy link
Contributor

@nikhilkumar1612 nikhilkumar1612 left a comment

Choose a reason for hiding this comment

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

LGTM

@cryptonoyaiba cryptonoyaiba merged commit 4dd7a5a into master Jul 24, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants