Skip to content

Commit bc19d05

Browse files
committed
refactor: apply code review
1 parent 5994b14 commit bc19d05

File tree

5 files changed

+69
-82
lines changed

5 files changed

+69
-82
lines changed

packages/multichain-account-service/src/MultichainAccountWallet.ts

Lines changed: 65 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -332,95 +332,100 @@ export class MultichainAccountWallet<
332332
*
333333
* NOTE: This method should only be called on a newly created wallet.
334334
*
335-
* @param opts - The options for the discovery and creation of accounts.
336-
* @param opts.skippedProviders - The providers to skip.
337335
* @returns The accounts for each provider.
338336
*/
339-
async discoverAndCreateAccounts({
340-
skippedProviders = [],
341-
}: {
342-
skippedProviders: AccountProviderType[];
343-
}): Promise<{
344-
[AccountProviderType]: Bip44Account<KeyringAccount>[];
345-
}> {
346-
const providers = this.#providers.filter(
347-
(provider) => !skippedProviders.includes(provider.providerType),
348-
);
337+
async discoverAndCreateAccounts(): Promise<Record<string, number>> {
338+
const providers = this.#providers;
339+
const providerContexts = new Map<
340+
Bip44Provider,
341+
{
342+
stopped: boolean;
343+
running?: Promise<void>;
344+
index: number;
345+
count: number;
346+
}
347+
>();
349348

350-
const results: Record<AccountProviderType, Bip44Account<KeyringAccount>[]> =
351-
{};
352-
const nextIndex = new Map<Bip44Provider, number>(
353-
providers.map((p) => [p, 0]),
354-
);
355-
const stopped = new Set<Bip44Provider>();
356-
const inFlight = new Map<Bip44Provider, Promise<void>>();
349+
for (const p of providers) {
350+
providerContexts.set(p, { stopped: false, index: 0, count: 0 });
351+
}
357352

358-
let high = 0;
353+
let maxGroupIndex = 0;
359354

360355
const schedule = (p: Bip44Provider, index: number) => {
361-
const run = (async () => {
356+
const providerCtx = providerContexts.get(p);
357+
if (!providerCtx) {
358+
throw new Error(`Provider ${p} not found in providerContexts`);
359+
}
360+
361+
if (providerCtx.stopped || providerCtx.running) {
362+
return;
363+
}
364+
365+
providerCtx.index = index;
366+
367+
providerCtx.running = (async () => {
362368
try {
363369
const accounts = await p.discoverAndCreateAccounts({
364370
entropySource: this.#entropySource,
365371
groupIndex: index,
366372
});
367373

368-
inFlight.delete(p);
369-
370-
if (accounts.length > 0) {
371-
stopped.add(p);
372-
} else {
373-
results[p.providerType] = [
374-
...(results[p.providerType] ?? []),
375-
...accounts,
376-
];
377-
378-
const next = index + 1;
379-
nextIndex.set(p, next);
380-
if (next > high) {
381-
high = next;
382-
383-
for (const q of providers) {
384-
if (
385-
!stopped.has(q) &&
386-
!inFlight.has(q) &&
387-
(nextIndex.get(q) ?? 0) < high
388-
) {
389-
schedule(q, high);
390-
}
391-
}
392-
}
374+
if (!accounts.length) {
375+
providerCtx.stopped = true;
376+
return;
377+
}
378+
379+
providerCtx.count += accounts.length;
393380

394-
if (!stopped.has(p)) {
395-
const target = Math.max(high, nextIndex.get(p) ?? 0);
396-
schedule(p, target);
381+
const next = index + 1;
382+
providerCtx.index = next;
383+
384+
if (next > maxGroupIndex) {
385+
maxGroupIndex = next;
386+
for (const [q, qCtx] of providerContexts) {
387+
if (
388+
!qCtx.stopped &&
389+
!qCtx.running &&
390+
qCtx.index < maxGroupIndex
391+
) {
392+
schedule(q, maxGroupIndex);
393+
}
397394
}
398395
}
399-
} catch {
400-
inFlight.delete(p);
401-
stopped.add(p);
396+
} catch (err) {
397+
providerCtx.stopped = true;
398+
console.error(err);
399+
} finally {
400+
providerCtx.running = undefined;
401+
if (!providerCtx.stopped) {
402+
const target = Math.max(maxGroupIndex, providerCtx.index);
403+
schedule(p, target);
404+
}
402405
}
403406
})();
404-
405-
inFlight.set(p, run);
406407
};
407408

408409
for (const p of providers) {
409410
schedule(p, 0);
410411
}
411412

412-
while (inFlight.size > 0) {
413-
await Promise.race(inFlight.values());
413+
while ([...providerContexts.values()].some((ctx) => Boolean(ctx.running))) {
414+
const racers = [...providerContexts.values()]
415+
.map((c) => c.running)
416+
.filter(Boolean) as Promise<void>[];
417+
await Promise.race(racers);
414418
}
415419

416420
await this.alignGroups();
417421

418-
const out: Record<AccountProviderType, Bip44Account<KeyringAccount>[]> = {};
422+
const discoveredAccounts: Record<string, number> = {};
419423

420-
for (const p of providers) {
421-
out[p.providerType] = results[p.providerType] ?? [];
424+
for (const [p, ctx] of providerContexts) {
425+
const groupKey = p.snapId ?? 'Evm';
426+
discoveredAccounts[groupKey] = ctx.count;
422427
}
423428

424-
return out;
429+
return discoveredAccounts;
425430
}
426431
}

packages/multichain-account-service/src/providers/BaseAccountProvider.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,8 @@ export abstract class BaseAccountProvider
4242
{
4343
protected readonly messenger: MultichainAccountServiceMessenger;
4444

45-
readonly providerType: AccountProviderType;
46-
47-
constructor(
48-
messenger: MultichainAccountServiceMessenger,
49-
providerType: AccountProviderType,
50-
) {
45+
constructor(messenger: MultichainAccountServiceMessenger) {
5146
this.messenger = messenger;
52-
this.providerType = providerType;
5347
}
5448

5549
#getAccounts(

packages/multichain-account-service/src/providers/EvmAccountProvider.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ function assertInternalAccountExists(
3131
}
3232

3333
export class EvmAccountProvider extends BaseAccountProvider {
34-
constructor(messenger: MultichainAccountServiceMessenger) {
35-
super(messenger, AccountProviderType.Evm);
36-
}
37-
3834
isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {
3935
return (
4036
account.type === EthAccountType.Eoa &&

packages/multichain-account-service/src/providers/SnapAccountProvider.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@ export type RestrictedSnapKeyringCreateAccount = (
1515
export abstract class SnapAccountProvider extends BaseAccountProvider {
1616
readonly snapId: SnapId;
1717

18-
constructor(
19-
snapId: SnapId,
20-
messenger: MultichainAccountServiceMessenger,
21-
providerType: AccountProviderType,
22-
) {
23-
super(messenger, providerType);
18+
constructor(snapId: SnapId, messenger: MultichainAccountServiceMessenger) {
19+
super(messenger);
2420

2521
this.snapId = snapId;
2622
}

packages/multichain-account-service/src/providers/SolAccountProvider.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ export class SolAccountProvider extends SnapAccountProvider {
1616
static SOLANA_SNAP_ID = 'npm:@metamask/solana-wallet-snap' as SnapId;
1717

1818
constructor(messenger: MultichainAccountServiceMessenger) {
19-
super(
20-
SolAccountProvider.SOLANA_SNAP_ID,
21-
messenger,
22-
AccountProviderType.Solana,
23-
);
19+
super(SolAccountProvider.SOLANA_SNAP_ID, messenger);
2420
}
2521

2622
isAccountCompatible(account: Bip44Account<InternalAccount>): boolean {

0 commit comments

Comments
 (0)