Skip to content

Commit 7b74969

Browse files
authored
Merge pull request #568 from hyperweb-io/noah/grouped-autoconnect
Connect in bulk to accounts being restored from local storage
2 parents 6c8d1c0 + c2e4958 commit 7b74969

File tree

1 file changed

+102
-18
lines changed

1 file changed

+102
-18
lines changed

packages/core/src/manager.ts

Lines changed: 102 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ export class WalletManager extends StateBase {
348348

349349
private _reconnect = async (
350350
walletName: WalletName,
351-
checkConnection = false
351+
checkConnection = false,
352+
onlyChainNames?: ChainName[]
352353
) => {
353354
if (
354355
checkConnection &&
@@ -359,9 +360,21 @@ export class WalletManager extends StateBase {
359360
this.logger?.debug('[Event Emit] `refresh_connection` (manager)');
360361
this.coreEmitter.emit('refresh_connection');
361362
await this.getMainWallet(walletName).connect();
362-
await this.getMainWallet(walletName)
363-
.getChainWalletList(true)[0]
364-
?.connect(true);
363+
await Promise.all(
364+
this.getMainWallet(walletName)
365+
.getChainWalletList(true)
366+
.map((w, index) =>
367+
!onlyChainNames
368+
? // If no chains specified, just connect the first chain wallet and sync to all active chain wallets.
369+
index === 0
370+
? w.connect(true)
371+
: undefined
372+
: // If chains specified, connect only the specified chains, without sync.
373+
onlyChainNames.includes(w.chainName)
374+
? w.connect(false)
375+
: undefined
376+
)
377+
);
365378
};
366379

367380
private _restoreAccounts = async () => {
@@ -375,32 +388,103 @@ export class WalletManager extends StateBase {
375388
const mainWallet = this.getMainWallet(walletName);
376389
mainWallet.activate();
377390

391+
let onlyChainNames: ChainName[] | undefined;
378392
if (mainWallet.clientMutable.state === State.Done) {
379393
const accountsStr = window.localStorage.getItem(
380394
'cosmos-kit@2:core//accounts'
381395
);
382396
if (accountsStr && accountsStr !== '[]') {
383397
const accounts: SimpleAccount[] = JSON.parse(accountsStr);
384-
accounts.forEach((data) => {
385-
const chainWallet = mainWallet
386-
.getChainWalletList(false)
387-
.find(
388-
(w) =>
389-
w.chainRecord.chain?.chain_id === data.chainId &&
390-
w.namespace === data.namespace
391-
);
392-
chainWallet?.activate();
393-
if (mainWallet.walletInfo.mode === 'wallet-connect') {
394-
chainWallet?.setData(data);
395-
chainWallet?.setState(State.Done);
398+
399+
const accountChainWallets = accounts.flatMap(
400+
(data): ChainWalletBase | [] => {
401+
const chainWallet = mainWallet
402+
.getChainWalletList(false)
403+
.find(
404+
(w) =>
405+
w.chainRecord.chain?.chain_id === data.chainId &&
406+
w.namespace === data.namespace
407+
);
408+
chainWallet?.activate();
409+
if (mainWallet.walletInfo.mode === 'wallet-connect') {
410+
chainWallet?.setData(data);
411+
chainWallet?.setState(State.Done);
412+
}
413+
return chainWallet || [];
396414
}
397-
});
415+
);
416+
398417
mainWallet.setState(State.Done);
418+
419+
// Activate all repos for the account chains and get their chain
420+
// records.
421+
const connectedChainRecords = accountChainWallets.flatMap(
422+
(chainWallet): ChainRecord | [] => {
423+
try {
424+
const repo = this.getWalletRepo(chainWallet.chainName);
425+
repo.activate();
426+
return repo.chainRecord;
427+
} catch {
428+
return [];
429+
}
430+
}
431+
);
432+
433+
const attemptConnectAll = async () => {
434+
try {
435+
await mainWallet.client?.enable?.(
436+
connectedChainRecords.map(
437+
(chainRecord) => chainRecord.chain.chain_id
438+
)
439+
);
440+
return true;
441+
} catch (error) {
442+
// If the error is a wallet rejection, log and return false to
443+
// indicate user rejection. Do not throw to continue.
444+
if (error instanceof Error && mainWallet.rejectMatched(error)) {
445+
this.logger?.error(
446+
`Failed to connect to stored chains: ${error.message}`
447+
);
448+
return false;
449+
}
450+
451+
throw error;
452+
}
453+
};
454+
455+
// Connect to all chains at once. On error (other than user
456+
// rejection), attempt to add each chain and try again.
457+
try {
458+
const rejected = !(await attemptConnectAll());
459+
// If user rejected, do not call `_reconnect` at the bottom or
460+
// else every chain wallet will attempt to connect to all chains
461+
// again.
462+
if (rejected) {
463+
return;
464+
}
465+
} catch (error) {
466+
// If failed to enable, add each chain and try again.
467+
for (const chainRecord of connectedChainRecords) {
468+
await mainWallet.client?.addChain?.(chainRecord);
469+
}
470+
471+
const rejected = !(await attemptConnectAll());
472+
// If user rejected, do not call `_reconnect` at the bottom or
473+
// else every chain wallet will attempt to connect to all chains
474+
// again.
475+
if (rejected) {
476+
return;
477+
}
478+
}
479+
480+
onlyChainNames = connectedChainRecords.map(
481+
(chainRecord) => chainRecord.name
482+
);
399483
}
400484
}
401485

402486
if (mainWallet.walletInfo.mode !== 'wallet-connect') {
403-
await this._reconnect(walletName);
487+
await this._reconnect(walletName, undefined, onlyChainNames);
404488
}
405489
} catch (error) {
406490
if (error instanceof WalletNotProvidedError) {

0 commit comments

Comments
 (0)