Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: SOL-46 adds the multichain transactions controller package #5133

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

zone-live
Copy link
Contributor

@zone-live zone-live commented Jan 13, 2025

Explanation

This PR adds a new package to the Core repo, with the new MultichainTransactions controller, it comes from my original extension PR, and it's responsibility is to track transactions for non-EVM accounts, with different block times, by using the Solana and Bitcoin snaps as the data source. It shares the same approach/structure with the MultichainBalancesController, given that responsibilities are very similar.

References

It relates to the PR opened in extension that will be updated after this one is merged.

Changelog

@metamask/multichain-transactions-controller

  • ADDED: New multichain-transactions-controller package, with the MultichainTransactionsController to track the transactions for non-EVM accounts by using the Solana and Bitcoin snaps as the data source..

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
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

@zone-live zone-live marked this pull request as ready for review January 13, 2025 14:22
@zone-live zone-live requested a review from a team as a code owner January 13, 2025 14:22
@zone-live zone-live changed the title chore: SOL-46 adds the multichain transactions controller package feat: SOL-46 adds the multichain transactions controller package Jan 13, 2025
.github/CODEOWNERS Outdated Show resolved Hide resolved
@zone-live zone-live requested a review from danroc January 15, 2025 12:04
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Hello! Thanks for pinging us about this. Just had some comments below. I think reaching 100% test coverage to avoid pain in the future, aligning the controller with our controller guidelines, and adjusting the dependencies in package.json are the most important items here.


const controllerName = 'MultichainTransactionsController';

export type PaginationOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add JSDoc for this type? How is it used?

/**
* Default state of the {@link MultichainTransactionsController}.
*/
export const defaultState: MultichainTransactionsControllerState = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use a function to construct the default state rather than keep it in a constant? This would align with our controller guidelines: https://github.com/MetaMask/core/blob/main/docs/writing-controllers.md#provide-a-default-representation-of-state

* using the `persist` flag; and if they can be sent to Sentry or not, using
* the `anonymous` flag.
*/
const MultichainTransactionsControllerMetadata = {
Copy link
Contributor

Choose a reason for hiding this comment

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

The name of the metadata variable should not be capitalized.

Suggested change
const MultichainTransactionsControllerMetadata = {
const multichainTransactionsControllerMetadata = {

Comment on lines +148 to +151
state,
}: {
messenger: MultichainTransactionsControllerMessenger;
state: MultichainTransactionsControllerState;
Copy link
Contributor

Choose a reason for hiding this comment

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

The state argument should be a partial version of the eventual state, and should be optional: https://github.com/MetaMask/core/blob/main/docs/writing-controllers.md#accept-an-optional-partial-representation-of-state

Suggested change
state,
}: {
messenger: MultichainTransactionsControllerMessenger;
state: MultichainTransactionsControllerState;
state = {},
}: {
messenger: MultichainTransactionsControllerMessenger;
state?: Partial<MultichainTransactionsControllerState>;

* Update the transactions of all tracked accounts
*/
async updateTransactions() {
await Promise.allSettled(
Copy link
Contributor

Choose a reason for hiding this comment

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

This is probably the first time I've seen allSettled used in a controller! Nice.

"@metamask/accounts-controller": "^21.0.0",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/keyring-controller": "^19.0.3",
"@metamask/keyring-internal-api": "^2.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be in dependencies? I notice that we import this package directly in MultichainTransactionsController.

"@metamask/keyring-internal-api": "^2.0.0",
"@metamask/keyring-snap-client": "^2.0.0",
"@metamask/snaps-controllers": "^9.10.0",
"@metamask/snaps-sdk": "^6.7.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be in dependencies? I notice that we import this package directly in MultichainTransactionsController.

return;
}

this.#handle = setInterval(this.#callback, this.#interval);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it a concern if the callback takes longer than the interval? If so, what are your thoughts on maintaining the loop using setTimeout instead of setInterval?

describe('MultichainTransactionsTracker', () => {
it('starts polling when calling start', async () => {
const { tracker } = setupTracker();
const spyPoller = jest.spyOn(Poller.prototype, 'start');
Copy link
Contributor

Choose a reason for hiding this comment

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

What are your thoughts on using jest.mock to mock the Poller class? Reaching into the prototype to do so seems a bit odd to me.

// Every 5s in milliseconds.
const TRANSACTIONS_TRACKING_INTERVAL = 5 * 1000;

export class MultichainTransactionsTracker {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thoughts on adding JSDoc for this class? What is the purpose of this class?

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