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: Re-simulate focused transactions every 3000 ms #5189

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

Conversation

OGPoyraz
Copy link
Member

@OGPoyraz OGPoyraz commented Jan 23, 2025

Explanation

This PR adds ResimulateHelper, which focuses on transactionMeta.isFocused property and re-simulates transaction depending on that value.

In order to capsulate re-simulation logic, this PR also relocates other utility functions under the new created ResimulationHelper.ts file.

References

Fixes: https://github.com/MetaMask/MetaMask-planning/issues/3922
Extension PR: MetaMask/metamask-extension#29878

Changelog

@metamask/transaction-controller

  • ADDED: Adds ability of re-simulating transaction depending on the isFocused property on transactionMeta
    • isFocused property is expected to set by client.
    • Re-simulation of transactions will occur every 3 seconds if isFocused is true.
  • Adds updateTransactionFocus function to update the isFocused property on transactionMeta.

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

@OGPoyraz
Copy link
Member Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "21.0.2-preview-9df90b5",
  "@metamask-previews/address-book-controller": "6.0.2-preview-9df90b5",
  "@metamask-previews/announcement-controller": "7.0.2-preview-9df90b5",
  "@metamask-previews/approval-controller": "7.1.2-preview-9df90b5",
  "@metamask-previews/assets-controllers": "46.0.1-preview-9df90b5",
  "@metamask-previews/base-controller": "7.1.1-preview-9df90b5",
  "@metamask-previews/build-utils": "3.0.2-preview-9df90b5",
  "@metamask-previews/composable-controller": "10.0.0-preview-9df90b5",
  "@metamask-previews/controller-utils": "11.4.5-preview-9df90b5",
  "@metamask-previews/ens-controller": "15.0.1-preview-9df90b5",
  "@metamask-previews/eth-json-rpc-provider": "4.1.7-preview-9df90b5",
  "@metamask-previews/gas-fee-controller": "22.0.2-preview-9df90b5",
  "@metamask-previews/json-rpc-engine": "10.0.2-preview-9df90b5",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.6-preview-9df90b5",
  "@metamask-previews/keyring-controller": "19.0.4-preview-9df90b5",
  "@metamask-previews/logging-controller": "6.0.3-preview-9df90b5",
  "@metamask-previews/message-manager": "12.0.0-preview-9df90b5",
  "@metamask-previews/multichain": "2.1.0-preview-9df90b5",
  "@metamask-previews/multichain-transactions-controller": "0.0.1-preview-9df90b5",
  "@metamask-previews/name-controller": "8.0.2-preview-9df90b5",
  "@metamask-previews/network-controller": "22.1.1-preview-9df90b5",
  "@metamask-previews/notification-services-controller": "0.16.0-preview-9df90b5",
  "@metamask-previews/permission-controller": "11.0.5-preview-9df90b5",
  "@metamask-previews/permission-log-controller": "3.0.2-preview-9df90b5",
  "@metamask-previews/phishing-controller": "12.3.1-preview-9df90b5",
  "@metamask-previews/polling-controller": "12.0.2-preview-9df90b5",
  "@metamask-previews/preferences-controller": "15.0.1-preview-9df90b5",
  "@metamask-previews/profile-sync-controller": "4.1.1-preview-9df90b5",
  "@metamask-previews/queued-request-controller": "9.0.0-preview-9df90b5",
  "@metamask-previews/rate-limit-controller": "6.0.2-preview-9df90b5",
  "@metamask-previews/remote-feature-flag-controller": "1.3.0-preview-9df90b5",
  "@metamask-previews/selected-network-controller": "21.0.0-preview-9df90b5",
  "@metamask-previews/signature-controller": "23.2.0-preview-9df90b5",
  "@metamask-previews/token-search-discovery-controller": "1.0.0-preview-9df90b5",
  "@metamask-previews/transaction-controller": "43.0.0-preview-9df90b5",
  "@metamask-previews/user-operation-controller": "22.0.0-preview-9df90b5"
}

@OGPoyraz
Copy link
Member Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "21.0.2-preview-4dd7520a",
  "@metamask-previews/address-book-controller": "6.0.2-preview-4dd7520a",
  "@metamask-previews/announcement-controller": "7.0.2-preview-4dd7520a",
  "@metamask-previews/approval-controller": "7.1.2-preview-4dd7520a",
  "@metamask-previews/assets-controllers": "46.0.1-preview-4dd7520a",
  "@metamask-previews/base-controller": "7.1.1-preview-4dd7520a",
  "@metamask-previews/build-utils": "3.0.2-preview-4dd7520a",
  "@metamask-previews/composable-controller": "10.0.0-preview-4dd7520a",
  "@metamask-previews/controller-utils": "11.4.5-preview-4dd7520a",
  "@metamask-previews/ens-controller": "15.0.1-preview-4dd7520a",
  "@metamask-previews/eth-json-rpc-provider": "4.1.7-preview-4dd7520a",
  "@metamask-previews/gas-fee-controller": "22.0.2-preview-4dd7520a",
  "@metamask-previews/json-rpc-engine": "10.0.2-preview-4dd7520a",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.6-preview-4dd7520a",
  "@metamask-previews/keyring-controller": "19.0.4-preview-4dd7520a",
  "@metamask-previews/logging-controller": "6.0.3-preview-4dd7520a",
  "@metamask-previews/message-manager": "12.0.0-preview-4dd7520a",
  "@metamask-previews/multichain": "2.1.0-preview-4dd7520a",
  "@metamask-previews/multichain-transactions-controller": "0.0.1-preview-4dd7520a",
  "@metamask-previews/name-controller": "8.0.2-preview-4dd7520a",
  "@metamask-previews/network-controller": "22.1.1-preview-4dd7520a",
  "@metamask-previews/notification-services-controller": "0.16.0-preview-4dd7520a",
  "@metamask-previews/permission-controller": "11.0.5-preview-4dd7520a",
  "@metamask-previews/permission-log-controller": "3.0.2-preview-4dd7520a",
  "@metamask-previews/phishing-controller": "12.3.1-preview-4dd7520a",
  "@metamask-previews/polling-controller": "12.0.2-preview-4dd7520a",
  "@metamask-previews/preferences-controller": "15.0.1-preview-4dd7520a",
  "@metamask-previews/profile-sync-controller": "4.1.1-preview-4dd7520a",
  "@metamask-previews/queued-request-controller": "9.0.0-preview-4dd7520a",
  "@metamask-previews/rate-limit-controller": "6.0.2-preview-4dd7520a",
  "@metamask-previews/remote-feature-flag-controller": "1.3.0-preview-4dd7520a",
  "@metamask-previews/selected-network-controller": "21.0.0-preview-4dd7520a",
  "@metamask-previews/signature-controller": "23.2.0-preview-4dd7520a",
  "@metamask-previews/token-search-discovery-controller": "1.0.0-preview-4dd7520a",
  "@metamask-previews/transaction-controller": "43.0.0-preview-4dd7520a",
  "@metamask-previews/user-operation-controller": "22.0.0-preview-4dd7520a"
}

@OGPoyraz OGPoyraz marked this pull request as ready for review January 24, 2025 12:47
@OGPoyraz OGPoyraz requested review from a team as code owners January 24, 2025 12:47
jpuri
jpuri previously approved these changes Jan 24, 2025
@OGPoyraz
Copy link
Member Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "21.0.2-preview-f3d5e317",
  "@metamask-previews/address-book-controller": "6.0.2-preview-f3d5e317",
  "@metamask-previews/announcement-controller": "7.0.2-preview-f3d5e317",
  "@metamask-previews/approval-controller": "7.1.2-preview-f3d5e317",
  "@metamask-previews/assets-controllers": "46.0.1-preview-f3d5e317",
  "@metamask-previews/base-controller": "7.1.1-preview-f3d5e317",
  "@metamask-previews/build-utils": "3.0.2-preview-f3d5e317",
  "@metamask-previews/composable-controller": "10.0.0-preview-f3d5e317",
  "@metamask-previews/controller-utils": "11.4.5-preview-f3d5e317",
  "@metamask-previews/ens-controller": "15.0.1-preview-f3d5e317",
  "@metamask-previews/eth-json-rpc-provider": "4.1.7-preview-f3d5e317",
  "@metamask-previews/gas-fee-controller": "22.0.2-preview-f3d5e317",
  "@metamask-previews/json-rpc-engine": "10.0.2-preview-f3d5e317",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.6-preview-f3d5e317",
  "@metamask-previews/keyring-controller": "19.0.4-preview-f3d5e317",
  "@metamask-previews/logging-controller": "6.0.3-preview-f3d5e317",
  "@metamask-previews/message-manager": "12.0.0-preview-f3d5e317",
  "@metamask-previews/multichain": "2.1.0-preview-f3d5e317",
  "@metamask-previews/multichain-transactions-controller": "0.0.1-preview-f3d5e317",
  "@metamask-previews/name-controller": "8.0.2-preview-f3d5e317",
  "@metamask-previews/network-controller": "22.1.1-preview-f3d5e317",
  "@metamask-previews/notification-services-controller": "0.16.0-preview-f3d5e317",
  "@metamask-previews/permission-controller": "11.0.5-preview-f3d5e317",
  "@metamask-previews/permission-log-controller": "3.0.2-preview-f3d5e317",
  "@metamask-previews/phishing-controller": "12.3.1-preview-f3d5e317",
  "@metamask-previews/polling-controller": "12.0.2-preview-f3d5e317",
  "@metamask-previews/preferences-controller": "15.0.1-preview-f3d5e317",
  "@metamask-previews/profile-sync-controller": "4.1.1-preview-f3d5e317",
  "@metamask-previews/queued-request-controller": "9.0.0-preview-f3d5e317",
  "@metamask-previews/rate-limit-controller": "6.0.2-preview-f3d5e317",
  "@metamask-previews/remote-feature-flag-controller": "1.3.0-preview-f3d5e317",
  "@metamask-previews/selected-network-controller": "21.0.0-preview-f3d5e317",
  "@metamask-previews/signature-controller": "23.2.0-preview-f3d5e317",
  "@metamask-previews/token-search-discovery-controller": "1.0.0-preview-f3d5e317",
  "@metamask-previews/transaction-controller": "43.0.0-preview-f3d5e317",
  "@metamask-previews/user-operation-controller": "22.0.0-preview-f3d5e317"
}

@OGPoyraz OGPoyraz force-pushed the 3922-re-simulate-transactions-for-every-new-block branch from f159aea to ea69888 Compare January 29, 2025 12:57
@OGPoyraz
Copy link
Member Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "21.0.2-preview-bd04b248",
  "@metamask-previews/address-book-controller": "6.0.2-preview-bd04b248",
  "@metamask-previews/announcement-controller": "7.0.2-preview-bd04b248",
  "@metamask-previews/approval-controller": "7.1.2-preview-bd04b248",
  "@metamask-previews/assets-controllers": "46.0.1-preview-bd04b248",
  "@metamask-previews/base-controller": "7.1.1-preview-bd04b248",
  "@metamask-previews/build-utils": "3.0.2-preview-bd04b248",
  "@metamask-previews/composable-controller": "10.0.0-preview-bd04b248",
  "@metamask-previews/controller-utils": "11.4.5-preview-bd04b248",
  "@metamask-previews/ens-controller": "15.0.1-preview-bd04b248",
  "@metamask-previews/eth-json-rpc-provider": "4.1.7-preview-bd04b248",
  "@metamask-previews/gas-fee-controller": "22.0.2-preview-bd04b248",
  "@metamask-previews/json-rpc-engine": "10.0.2-preview-bd04b248",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.6-preview-bd04b248",
  "@metamask-previews/keyring-controller": "19.0.4-preview-bd04b248",
  "@metamask-previews/logging-controller": "6.0.3-preview-bd04b248",
  "@metamask-previews/message-manager": "12.0.0-preview-bd04b248",
  "@metamask-previews/multichain": "2.1.0-preview-bd04b248",
  "@metamask-previews/multichain-transactions-controller": "0.0.1-preview-bd04b248",
  "@metamask-previews/name-controller": "8.0.2-preview-bd04b248",
  "@metamask-previews/network-controller": "22.1.1-preview-bd04b248",
  "@metamask-previews/notification-services-controller": "0.17.0-preview-bd04b248",
  "@metamask-previews/permission-controller": "11.0.5-preview-bd04b248",
  "@metamask-previews/permission-log-controller": "3.0.2-preview-bd04b248",
  "@metamask-previews/phishing-controller": "12.3.1-preview-bd04b248",
  "@metamask-previews/polling-controller": "12.0.2-preview-bd04b248",
  "@metamask-previews/preferences-controller": "15.0.1-preview-bd04b248",
  "@metamask-previews/profile-sync-controller": "4.1.1-preview-bd04b248",
  "@metamask-previews/queued-request-controller": "9.0.0-preview-bd04b248",
  "@metamask-previews/rate-limit-controller": "6.0.2-preview-bd04b248",
  "@metamask-previews/remote-feature-flag-controller": "1.3.0-preview-bd04b248",
  "@metamask-previews/selected-network-controller": "21.0.0-preview-bd04b248",
  "@metamask-previews/signature-controller": "23.2.0-preview-bd04b248",
  "@metamask-previews/token-search-discovery-controller": "1.0.0-preview-bd04b248",
  "@metamask-previews/transaction-controller": "43.0.0-preview-bd04b248",
  "@metamask-previews/user-operation-controller": "22.0.0-preview-bd04b248"
}

@OGPoyraz OGPoyraz changed the title feat: Resimulate transactions for every new block feat: Re-simulate focused transactions every 3000 ms Jan 29, 2025
/**
* Whether the transaction confirmation window is focused.
*/
isFocused?: boolean;
Copy link
Member

Choose a reason for hiding this comment

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

Would it be more helpful to call this isActive?

As the UI can own what this means, currently focused and visible but those requirements may change in future?

onStateChange: (listener) => {
this.messagingSystem.subscribe(
'TransactionController:stateChange',
listener,
Copy link
Member

Choose a reason for hiding this comment

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

Can we use a selector to limit the events to when the transactions change?

export type ResimulateHelperOptions = {
getTransactions: () => TransactionMeta[];
onStateChange: (listener: () => void) => void;
updateSimulationData: (transactionMeta: TransactionMeta) => Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

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

Would it be more explicit to call this simulateTransaction as it actually performs the simulation, not just updates state?

this.#getTransactions = getTransactions;
this.#updateSimulationData = updateSimulationData;

onStateChange(() => {
Copy link
Member

Choose a reason for hiding this comment

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

Minor, would it be cleaner for this callback to go in a private function rather than within the constructor?

);

// Start or stop resimulation based on the current isFocused state
unapprovedTransactions.forEach((transactionMeta) => {
Copy link
Member

Choose a reason for hiding this comment

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

Minor, would it be cleaner to have a #getActiveUnapprovedTransactions(active: boolean)?


export class ResimulateHelper {
// Map of transactionId <=> isActive
readonly #activeResimulations: Map<string, boolean> = new Map();
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this property at all?

Can we not infer the active transaction IDs from the keys of #intervalIds?

}

this.#removeListener(transactionId);
log(`Stopped resimulating transaction ${transactionId} every 3 seconds`);
Copy link
Member

Choose a reason for hiding this comment

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

Minor, should we avoid hardcoding the duration here so it's dynamic based on the constant?

@@ -926,6 +930,17 @@ export class TransactionController extends BaseController<
this.#checkForPendingTransactionAndStartPolling,
);

new ResimulateHelper({
updateSimulationData: this.#updateSimulationData.bind(this),
onStateChange: (listener) => {
Copy link
Member

Choose a reason for hiding this comment

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

Should we call this onTransactionsUpdate for accuracy if we use a selector?

* @param transactionId - The ID of the transaction to update.
* @param isFocused - The new focus state.
*/
updateTransactionFocus(transactionId: string, isFocused: boolean) {
Copy link
Member

Choose a reason for hiding this comment

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

setTransactionActive as per my other comment about decoupling?

isFocused,
};

this.updateTransaction(
Copy link
Member

Choose a reason for hiding this comment

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

We want to exclusively use #updateTransactionInternal going forward as it uses callbacks to update meaning there is no risk of race conditions from multiple updates.

It would also mean we don't need to query the existing state in this method.

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