Skip to content

Conversation

orestiseth
Copy link
Contributor

@orestiseth orestiseth commented Oct 14, 2025

Note

Adds setSelectedAccounts RPC (with validation and full scans), updates cron to synchronize only selected accounts, and bumps keyring dependencies.

  • Keyring:
    • New RPC: Handle KeyringRpcMethod.SetSelectedAccounts in KeyringHandler to validate IDs and fullScan selected accounts.
    • Validation: Add validateSelectedAccounts in handlers/validation.ts.
    • Account Creation: Default synchronize to false in createAccount.
    • Discovery: discoverAccounts now returns all discovered accounts (no history filter).
  • Cron:
    • Selected Sync: CronHandler now syncs only accounts returned by getSelectedAccounts (requires SnapsProvider); constructor and usage updated.
  • Bootstrap:
    • Wire SnapsProvider into CronHandler in src/index.ts.
  • Use Cases:
    • Remove fullScan during discover in AccountUseCases.discover.
  • Dependencies:
    • Bump @metamask/keyring-api to ^21.1.0 and @metamask/keyring-snap-sdk to ^7.1.0.
  • Manifest:
    • Update snap.manifest.json version to 1.3.0 and shasum.
  • Tests:
    • Update tests for selected-account syncing, new RPC, default synchronize=false, and skip history-filter test.

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

Copy link

socket-security bot commented Oct 14, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​metamask/​keyring-snap-sdk@​6.0.0 ⏵ 7.1.074 +210074 +394 -2100
Added@​metamask/​keyring-api@​21.1.01001001009650

View full report

const selectedAccounts = allAccounts.filter((account) =>
accountIdSet.has(account.id),
);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BTC snap has 2 methods for updating accounts. One is a full scan which previously was used when an account was created/discovered and the other one is a lighter synchronize which identified updates.

Since now we don't do any scanning on discovery we don't really know when it is the first time we see an account (without storing anything on snaps state).

Thus, on this PR we are going to run a full scan everytime the keyring method gets called and a synchronize on the cron job running every 30 seconds.

Feel free to add your thoughts. We can always store "seen" accounts on the snap state but I am not sure how efficient is going to be if a user creates loads of them.

Choose a reason for hiding this comment

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

Makes a lot of sense to me 👍

@orestiseth orestiseth marked this pull request as ready for review October 14, 2025 16:52
@orestiseth orestiseth requested a review from a team as a code owner October 14, 2025 16:52
@orestiseth orestiseth changed the title feat: introduce setSelectedAccounts feat: add support for setSelectedAccounts Oct 14, 2025
];
const request = { method: 'synchronizeAccounts' } as JsonRpcRequest;

it('synchronizes all accounts', async () => {

Choose a reason for hiding this comment

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

Suggested change
it('synchronizes all accounts', async () => {
it('synchronizes selected accounts', async () => {

});

it('filters out accounts that have no transaction history', async () => {
it.skip('filters out accounts that have no transaction history', async () => {

Choose a reason for hiding this comment

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

Why do we skip it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the filtering was happening when we were discovering accounts which included a full scan. Since now we don't scan the chain for activity we can't know if there were txs or not.

}
case `${KeyringRpcMethod.SetSelectedAccounts}`: {
assert(request, SetSelectedAccountsRequestStruct);
await this.setSelectedAccounts((request as any).params.accountIds);

Choose a reason for hiding this comment

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

I don't think the as any is needed here.

On line 149, assert narrows the type of request, so that on line 150 request is of type inferred from the struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually it should be await this.setSelectedAccounts(request.params.accounts);. I have the change locally but haven't pushed it yet. Will do in a bit.

Comment on lines +165 to +167
const isSubset = (first: Set<string>, second: Set<string>): boolean => {
return Array.from(first).every((element) => second.has(element));
};

Choose a reason for hiding this comment

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

👌

await this.#accountsUseCases.fullScan(account);
});

await Promise.all(scanPromises);
Copy link

@xavier-brochard xavier-brochard Oct 16, 2025

Choose a reason for hiding this comment

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

What about this?

Suggested change
await Promise.all(scanPromises);
await Promise.allSettled(scanPromises);

Ensures that a failing fullScan call doesn't prevent the others to complete

Comment on lines 350 to 352
const scanPromises = selectedAccounts.map(async (account) => {
await this.#accountsUseCases.fullScan(account);
});

Choose a reason for hiding this comment

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

Can simplify to:

Suggested change
const scanPromises = selectedAccounts.map(async (account) => {
await this.#accountsUseCases.fullScan(account);
});
const scanPromises = selectedAccounts.map(async (account) => this.#accountsUseCases.fullScan(account));

cursor[bot]

This comment was marked as outdated.

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.

3 participants