Skip to content

fix: integration with default transport#1357

Merged
elribonazo merged 1 commit into
mainfrom
fix/multichain-default-provider-issue
Oct 3, 2025
Merged

fix: integration with default transport#1357
elribonazo merged 1 commit into
mainfrom
fix/multichain-default-provider-issue

Conversation

@elribonazo

@elribonazo elribonazo commented Oct 2, 2025

Copy link
Copy Markdown
Contributor

Explanation

Fixes the integration with the default transport.

This PR fixes some issues connecting and sending RPC requests directly into the chrome extension from browser.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

Note

Adds 60s request timeouts, notification management (including sessionChanged), improved error handling, and updates tests; requests now delegate directly without manual JSON-RPC id.

  • Transport (packages/sdk-multichain/src/multichain/transports/default/index.ts):
    • Add 60s default request timeout and apply to wallet_getSession, wallet_revokeSession, wallet_createSession.
    • Introduce notification callback registry; emit wallet_sessionChanged after connect; clear callbacks on disconnect; onNotification returns unsubscribe.
    • Delegate request directly to underlying transport (remove manual jsonrpc/id).
    • Throw on wallet_createSession errors.
  • Tests:
    • Update web session tests to expect { timeout: 60 * 1000 } and no jsonrpc field in requests.
    • Adjust UI test: renderInstallModal onClose now unmounts modal.

Written by Cursor Bugbot for commit f9c9d7e. This will update automatically on new commits. Configure here.

@elribonazo elribonazo requested a review from a team as a code owner October 2, 2025 18:15
@elribonazo elribonazo force-pushed the fix/multichain-default-provider-issue branch from 2010660 to f9c9d7e Compare October 2, 2025 19:18
@codecov

codecov Bot commented Oct 2, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.99%. Comparing base (e4be769) to head (f9c9d7e).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1357   +/-   ##
=======================================
  Coverage   74.99%   74.99%           
=======================================
  Files         184      184           
  Lines        4519     4519           
  Branches     1108     1108           
=======================================
  Hits         3389     3389           
  Misses       1130     1130           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2025

Copy link
Copy Markdown

import type { ExtendedTransport, RPCAPI, Scope, SessionData } from 'src/domain';
import { addValidAccounts, getOptionalScopes, getValidAccounts } from 'src/multichain/utils';

const DEFAULT_REQUEST_TIMEOUT = 60 * 1000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is the basis for a 60 second timeout? Can you explain why we're adding this now? What is it fixing or protecting against specifically?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Was agreed with @chakra-guy, @adonesky1... while it does not hurt to leave the RPC calls without a timeout, at the same time, if we don't add one the requests could be running forever and we think it is more secure to just expire the RPC requests that are not answered in reasonable time.

If u wanted to establish a connection or do a RPC call, 60 seconds will be enough, same logic can be found in Mobile Wallet protocol itself.

const DEFAULT_REQUEST_TIMEOUT = 60 * 1000;

export class DefaultTransport implements ExtendedTransport {
#notificationCallbacks: Set<(data: unknown) => void> = new Set();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is the purpose of tracking these callbacks?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is it solving for us on this pass?

@elribonazo elribonazo Oct 3, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That is an excellent point @adonesky1

In Recent changes we moved all the Wallet related business logic into the Transport layer. By business logic we mean, handling connections, fetching sessions and doing session upgrade.

Before

In the past, the main export in the Multichain SDK had all that logic to manage session upgrades on connection or session restore, but combined with the Multichain api provider it led to unexpected wallet_getSession requests and bad user experience as the user requires one step on MWP to get the personal sign.

Ex: The user requests personal_sign. The Multichain api client will then trigger a wallet_getSession request. The personal sign message will only be received if the user manually goes to Mobile app and then back to the Dapp.

After

src/multichain/transports/mwp and src/multichain/transports/default, contain the 2 main transports that we need and add the same business logic on connection requests and invoke methods.

MWP and Default transport are responsible of handling wallet related business logic like upgrading the sessions on connection, reconnection, coming back to live from background, etc.

This also adds separation of concerns in the project, all that is wallet related remains contained inside the transports and the main class is just responsible of managing which flow we need to go into, really simple...

  • Multichain SDK is no longer responsible of handling wallet rpc requests or session upgrades
  • Transports do all this logic
  • Multichain SDK is just responsible of knowing which transport to plug into at any point in time and just iniciating the connection with the transport itself.
  • Transports, compared to before are now stronger and resolve connections only when the business logic is solved. EX, a Connection request only solves once we complete the connection with multichain-api itself + fetch a valid wallet_getSession or create a new one with wallet_createSession.

Answer

To the question of "Why we need notificationCallbacks" is because we are triggering this events from the Multichain DefaultTransport itself and we wanna be able to send notifications from our transport but also keep the multichain api transport notifications intact and working, thats why that is needed.
Kind of extending the events comming from the api client basically, does all the cleaning on disconnect too, so we should be good to go

@elribonazo elribonazo requested review from a team and adonesky1 October 3, 2025 06:42
@elribonazo elribonazo self-assigned this Oct 3, 2025
@elribonazo elribonazo enabled auto-merge (squash) October 3, 2025 09:18
@elribonazo elribonazo merged commit 3ff7401 into main Oct 3, 2025
44 checks passed
@elribonazo elribonazo deleted the fix/multichain-default-provider-issue branch October 3, 2025 10:44
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.

4 participants