Skip to content

Commit

Permalink
feat: Add QueuedRequestController batching (#22865)
Browse files Browse the repository at this point in the history
## **Description**

The `QueuedRequestController` will now batch requests by origin.
Requests from the same UI now get shown together, just as they were
before this queuing feature was added. The only remaining difference is
that we no longer show requests from different origins in the same
batch, which we view as a security/usability improvement.

## **Related issues**

Fixes:

## **Manual testing steps**

**important** make sure any dapp used for testing has a permission
(eth_accounts for example), as well as the per-domain network feature
flag turned on, then refresh the dapp before begining testing.

make sure to also test that everything works unchanged with the feature
flag off

1. Turn on per-domain network feature flag
2. go to test dapp and connect
3. refresh the test dapp
4. go to any other website (msn.com for example)
5. in the devtools, run this:
```
await window.ethereum.request({
  "method": "wallet_requestPermissions",
  "params": [
    {
      "eth_accounts": {}
    }
  ]
});
```
6. go back to the testdapp tab, make 2 or 3 send transaction calls
7. ensure that the UI displays the number of transactions being
processed, and allows you to go back and forward through the
transactions.
8. before confirming or rejecting any of those transactions, switch to
the tab with msn.ca and run this 2-3 times:
```
await window.ethereum.request({
  "method": "eth_sendTransaction",
  "params": [
    {
      "to": "0x77ff877eE79c3f8C5aD244c037e5580EdCC6eF2c",
      "from": "your address",
      "value": "0x1"
    }
  ]
});
```
9. ensure that the you are still only able to scrub through the 3
transactions. Reject each of them.
10. You should now see the next set of 3 (from the domain msn.com).

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've clearly explained what problem this PR is solving and how it
is solved.
- [ ] I've linked related issues
- [ ] I've included manual testing steps
- [ ] I've included screenshots/recordings if applicable
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [ ] I’ve properly set the pull request status:
  - [ ] In case it's not yet "ready for review", I've set it to "draft".
- [ ] In case it's "ready for review", I've changed it from "draft" to
"non-draft".

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Zachary Belford <belfordz66@gmail.com>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 21, 2024
1 parent 23dbcb5 commit 1bb5dcd
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 163 deletions.
31 changes: 10 additions & 21 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,11 @@ export function setupController(
updateBadge,
);

controller.controllerMessenger.subscribe(
METAMASK_CONTROLLER_EVENTS.QUEUED_REQUEST_STATE_CHANGE,
updateBadge,
);

controller.txController.initApprovals();

/**
Expand All @@ -820,35 +825,19 @@ export function setupController(
}

function getUnapprovedTransactionCount() {
let count = controller.appStateController.waitingForUnlock.length;
let count =
controller.appStateController.waitingForUnlock.length +
controller.approvalController.getTotalApprovalCount();

if (controller.preferencesController.getUseRequestQueue()) {
count += controller.queuedRequestController.length();
} else {
count += controller.approvalController.getTotalApprovalCount();
count += controller.queuedRequestController.state.queuedRequestCount;
}
return count;
}

controller.controllerMessenger.subscribe(
'QueuedRequestController:countChanged',
(count) => {
updateBadge();
if (count > 0) {
triggerUi();
}
},
);

notificationManager.on(
NOTIFICATION_MANAGER_EVENTS.POPUP_CLOSED,
({ automaticallyClosed }) => {
if (controller.preferencesController.getUseRequestQueue()) {
// when the feature flag is on, rejecting unnapproved notifications in this way does nothing (since the controllers havent seen the requests yet)
// Also, the updating of badge / triggering of UI happens from the countChanged event when the feature flag is on, so we dont need that here either.
// The only thing that we might want to add here is possibly calling a method to empty the queue / do the same thing as rejecting all confirmed?
return;
}

if (!automaticallyClosed) {
rejectUnapprovedNotifications();
} else if (getUnapprovedTransactionCount() > 0) {
Expand Down
10 changes: 9 additions & 1 deletion app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ export const METAMASK_CONTROLLER_EVENTS = {
UPDATE_BADGE: 'updateBadge',
// TODO: Add this and similar enums to the `controllers` repo and export them
APPROVAL_STATE_CHANGE: 'ApprovalController:stateChange',
QUEUED_REQUEST_STATE_CHANGE: 'QueuedRequestController:stateChange',
};

// stream channels
Expand Down Expand Up @@ -405,6 +406,11 @@ export default class MetamaskController extends EventEmitter {
this.queuedRequestController = new QueuedRequestController({
messenger: this.controllerMessenger.getRestricted({
name: 'QueuedRequestController',
allowedActions: [
'NetworkController:getState',
'NetworkController:setActiveNetwork',
'SelectedNetworkController:getNetworkClientIdForDomain',
],
}),
});

Expand Down Expand Up @@ -4839,7 +4845,9 @@ export default class MetamaskController extends EventEmitter {
}

const requestQueueMiddleware = createQueuedRequestMiddleware({
messenger: this.controllerMessenger,
enqueueRequest: this.queuedRequestController.enqueueRequest.bind(
this.queuedRequestController,
),
useRequestQueue: this.preferencesController.getUseRequestQueue.bind(
this.preferencesController,
),
Expand Down
36 changes: 20 additions & 16 deletions lavamoat/browserify/beta/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -1882,29 +1882,33 @@
},
"@metamask/queued-request-controller": {
"packages": {
"@metamask/base-controller": true,
"@metamask/providers>@metamask/json-rpc-engine": true,
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/controller-utils": true,
"@metamask/selected-network-controller": true
"@metamask/queued-request-controller>@metamask/base-controller": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/controller-utils": {
"@metamask/queued-request-controller>@metamask/base-controller": {
"globals": {
"URL": true,
"console.error": true,
"fetch": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/controller-utils>@spruceid/siwe-parser": true,
"@metamask/ethjs>@metamask/ethjs-unit": true,
"@metamask/utils": true,
"bn.js": true,
"browserify>buffer": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true
"immer": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine": {
"packages": {
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"webpack>events": true
}
},
"@metamask/rpc-methods-flask>nanoid": {
Expand Down
36 changes: 20 additions & 16 deletions lavamoat/browserify/desktop/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -2033,29 +2033,33 @@
},
"@metamask/queued-request-controller": {
"packages": {
"@metamask/base-controller": true,
"@metamask/providers>@metamask/json-rpc-engine": true,
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/controller-utils": true,
"@metamask/selected-network-controller": true
"@metamask/queued-request-controller>@metamask/base-controller": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/controller-utils": {
"@metamask/queued-request-controller>@metamask/base-controller": {
"globals": {
"URL": true,
"console.error": true,
"fetch": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/controller-utils>@spruceid/siwe-parser": true,
"@metamask/ethjs>@metamask/ethjs-unit": true,
"@metamask/utils": true,
"bn.js": true,
"browserify>buffer": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true
"immer": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine": {
"packages": {
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"webpack>events": true
}
},
"@metamask/rate-limit-controller": {
Expand Down
36 changes: 20 additions & 16 deletions lavamoat/browserify/flask/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -2085,29 +2085,33 @@
},
"@metamask/queued-request-controller": {
"packages": {
"@metamask/base-controller": true,
"@metamask/providers>@metamask/json-rpc-engine": true,
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/controller-utils": true,
"@metamask/selected-network-controller": true
"@metamask/queued-request-controller>@metamask/base-controller": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/controller-utils": {
"@metamask/queued-request-controller>@metamask/base-controller": {
"globals": {
"URL": true,
"console.error": true,
"fetch": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/controller-utils>@spruceid/siwe-parser": true,
"@metamask/ethjs>@metamask/ethjs-unit": true,
"@metamask/utils": true,
"bn.js": true,
"browserify>buffer": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true
"immer": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine": {
"packages": {
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"webpack>events": true
}
},
"@metamask/rate-limit-controller": {
Expand Down
36 changes: 20 additions & 16 deletions lavamoat/browserify/main/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -2008,29 +2008,33 @@
},
"@metamask/queued-request-controller": {
"packages": {
"@metamask/base-controller": true,
"@metamask/providers>@metamask/json-rpc-engine": true,
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/controller-utils": true,
"@metamask/selected-network-controller": true
"@metamask/queued-request-controller>@metamask/base-controller": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/controller-utils": {
"@metamask/queued-request-controller>@metamask/base-controller": {
"globals": {
"URL": true,
"console.error": true,
"fetch": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/controller-utils>@spruceid/siwe-parser": true,
"@metamask/ethjs>@metamask/ethjs-unit": true,
"@metamask/utils": true,
"bn.js": true,
"browserify>buffer": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true
"immer": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine": {
"packages": {
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"webpack>events": true
}
},
"@metamask/rate-limit-controller": {
Expand Down
36 changes: 20 additions & 16 deletions lavamoat/browserify/mmi/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -2141,29 +2141,33 @@
},
"@metamask/queued-request-controller": {
"packages": {
"@metamask/base-controller": true,
"@metamask/providers>@metamask/json-rpc-engine": true,
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/controller-utils": true,
"@metamask/selected-network-controller": true
"@metamask/queued-request-controller>@metamask/base-controller": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/controller-utils": {
"@metamask/queued-request-controller>@metamask/base-controller": {
"globals": {
"URL": true,
"console.error": true,
"fetch": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/controller-utils>@spruceid/siwe-parser": true,
"@metamask/ethjs>@metamask/ethjs-unit": true,
"@metamask/utils": true,
"bn.js": true,
"browserify>buffer": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true
"immer": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine": {
"packages": {
"@metamask/providers>@metamask/rpc-errors": true,
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/utils": true
}
},
"@metamask/queued-request-controller>@metamask/json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"webpack>events": true
}
},
"@metamask/rate-limit-controller": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@
"@metamask/post-message-stream": "^8.0.0",
"@metamask/ppom-validator": "^0.28.0",
"@metamask/providers": "^14.0.2",
"@metamask/queued-request-controller": "^0.3.0",
"@metamask/queued-request-controller": "^0.6.0",
"@metamask/rate-limit-controller": "^3.0.0",
"@metamask/safe-event-emitter": "^2.0.0",
"@metamask/scure-bip39": "^2.0.3",
Expand Down
Loading

0 comments on commit 1bb5dcd

Please sign in to comment.