fix(multichain-account-service): guard fire-and-forget alignment with ensureReady - #9812
Conversation
| // Ensure the Snap platform is ready for every non-EVM provider BEFORE | ||
| // acquiring the wallet lock. Without this guard the lock would be held | ||
| // while waiting for onboarding to complete, blocking all subsequent | ||
| // wallet operations that also need the lock. | ||
| await Promise.all( | ||
| otherProviders.map((provider) => provider.ensureReady()), | ||
| ); |
There was a problem hiding this comment.
For now, we scope this fix only for this code-path.
We could use ensureReady on other code-paths wherever we need a provider, but most calls are already doing that. This one is a bit more different than the other since it's a fire-and-forget and might hold the lock asynchronously (which can be held forever during onboarding, see the PR's description for the flow).
There was a problem hiding this comment.
Should we use promise.allsettled? If one provider fails, it would fail for the alignment of the other providers
There was a problem hiding this comment.
Good question 🤔 I guess we can turn that into a "best-effort" operation in that case. We do have explicit alignments to also address this kind of failure and be resilient anyway.
That makes sense IMO, let me try to do that!
Thanks 😄
There was a problem hiding this comment.
In the normal case, this will never fail. But at least, now it's even more resilient, thanks!
Explanation
If we try to create a multichain account wallet during onboarding, the post-alignment part (e.g. non-EVM account creations) is locking this wallet's lock until onboarding is completed.
This prevents any other kind of operations on that wallet that requires the wallet's mutex to be locked again.
This is what we do now for the QR sync wallet during onboarding, like:
waitForAllProvidersToFinishCreatingAccounts=false)To prevent this from happening, we now guard every post-alignment with a call to
ensureReadyon each providers before proceeding. This makes sure we only schedule wallet's operation once the providers are ready to proceed anything.In the case of the
SnapAccountProvider, this means they will wait for the Snap platform to boot up before starting to lock the wallet's mutex, solving the initial issue "naturally".References
{import,export}Stateactions #9663Checklist
Note
Medium Risk
Changes wallet locking order during group creation—a sensitive concurrency path—but scope is limited to deferred post-alignment and includes tests for lock timing and partial provider failure.
Overview
Fixes a deadlock during onboarding when non-EVM post-alignment ran under the wallet mutex while Snap providers were still waiting for the platform—blocking later steps such as QR sync metadata import.
Fire-and-forget post-alignment (when
waitForAllProvidersToFinishCreatingAccountsis false) now callsensureReadyon all non-EVM providers before acquiring the alignment lock. Only providers that become ready are aligned; failures are logged and skipped so a later explicit alignment can recover them.The
ensureReadyhook is added to the BIP-44 provider contract (no-op on base/EVM, delegated throughAccountProviderWrapper, Snap waits viaSnapAccountService:ensureReady).Reviewed by Cursor Bugbot for commit 954eab5. Bugbot is set up for automated code reviews on this repo. Configure here.