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

resolve issue with missing template error #10692

Merged
merged 3 commits into from
Mar 23, 2021

Conversation

brad-decker
Copy link
Contributor

Fixes: METAMASK-GSGN

Possible cause?

    this.setState({ mounted: true });
    if (isNotification && totalUnapprovedCount === 0) {
      global.platform.closeCurrentWindow();
    } else if (!isNotification && showAwaitingSwapScreen) {
      history.push(AWAITING_SWAP_ROUTE);
    } else if (!isNotification && haveSwapsQuotes) {
      history.push(VIEW_QUOTE_ROUTE);
    } else if (!isNotification && swapsFetchParams) {
      history.push(BUILD_QUOTE_ROUTE);
    } else if (firstPermissionsRequestId) { // <------ If this is undefined, which is an approval
      history.push(`${CONNECT_ROUTE}/${firstPermissionsRequestId}`);
    } else if (unconfirmedTransactionsCount > 0) {
      history.push(CONFIRM_TRANSACTION_ROUTE);
    } else if (Object.keys(suggestedTokens).length > 0) {
      history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE);
    } else if (pendingApprovals.length > 0) { // <------- Then this would be true
      history.push(CONFIRMATION_V_NEXT_ROUTE);
    }

Why would firstPermissionsRequestId be undefined when there is pending approval of this type? Not sure. This change just makes it so that the only approvals that will be caught on the last block of the else/if are ones that have templates. This might mean for that user that they don't get routed to the notification at all -- perhaps not a real solution but one that doesn't cause an error.

@metamaskbot
Copy link
Collaborator

Builds ready [e4cab02]
Page Load Metrics (604 ± 11 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint44745894
domContentLoaded5606476022311
load5666486042211
domInteractive5596466022311

@brad-decker brad-decker marked this pull request as ready for review March 22, 2021 17:57
@brad-decker brad-decker requested a review from a team as a code owner March 22, 2021 17:57
@Gudahtt
Copy link
Member

Gudahtt commented Mar 23, 2021

Why would firstPermissionsRequestId be undefined when there is pending approval of this type? Not sure.

I think this is the question we need to answer. I don't have much confidence that this change would make things less-broken without better understanding what went wrong here.

@Gudahtt
Copy link
Member

Gudahtt commented Mar 23, 2021

I've just traced through how these permission requests are handled, and it looks like we store two different related states for each request. We have permissionsRequests which tracks a request for permissions, and we have the Approval controller state which is the user confirmation asking for approval for this permission request.

It looks like the lifetime of the permissionsRequests entry should exceed the lifetime of the approval request 🤔 At least that's what I'm seeing. Either when rejecting or approving the confirmation, the approval request is removed first, before the permissions request. There must be some edge case at play here...

@brad-decker
Copy link
Contributor Author

I think this change is still likely a good one, but should be batched together with any adjustments we want to make to this flow to be safe. I'll also look through the trace and see if I can pinpoint a culprit or suggest a change to make this safer.

@Gudahtt
Copy link
Member

Gudahtt commented Mar 23, 2021

I agree that we should protect against routing things without templates to the template-based confirmation page. But I'm concerned that this PR as-written might result in the error being hidden, which would make fixing it properly more difficult.

@brad-decker
Copy link
Contributor Author

I agree that we should protect against routing things without templates to the template-based confirmation page. But I'm concerned that this PR as-written might result in the error being hidden, which would make fixing it properly more difficult.

I agree, that's what I meant by batching together, but in retrospect, that wasn't clearly decipherable from what I wrote.

@Gudahtt
Copy link
Member

Gudahtt commented Mar 23, 2021

Ah, sorry, understood. Even still though, should we not state our expectations here and throw an error if they're not met? e.g. maybe an else clause that throws an error for an unrecognized/invalid approval request would be useful. Otherwise it could hide errors in the future, even after this is fixed.

@brad-decker
Copy link
Contributor Author

If we rewind to before the template system/approval part of this logic, there wasn't an else statement catching errors there. I just added another else if onto the chain. Unless something changed with the permissions/approval controllers that landed alongside the template system, not before it, then the edge case existed then. We didn't know about it because it doesn't present as an error.

So I'd be in favor of adding an else statement, but maybe instead of throwing an Error we should just log it to sentry? Doesn't throwing an error in that case cause the user flow to be interrupted?

@Gudahtt
Copy link
Member

Gudahtt commented Mar 23, 2021

So I'd be in favor of adding an else statement, but maybe instead of throwing an Error we should just log it to sentry? Doesn't throwing an error in that case cause the user flow to be interrupted?

Sounds reasonable in principle, but what would happen to the user in this case? Throwing an error might be all we can do with the information we have, if it's an unaccounted for situation.

@metamaskbot
Copy link
Collaborator

Builds ready [9dfd273]
Page Load Metrics (614 ± 18 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint448358105
domContentLoaded5537356133818
load5547366143818
domInteractive5537356133818

@brad-decker
Copy link
Contributor Author

Sounds reasonable in principle, but what would happen to the user in this case? Throwing an error might be all we can do with the information we have, if it's an unaccounted for situation.

Yeah, fair. In any event, we should think about what to do in this case once all confirmations are using the approval controller. In that case, if we get to the point where the confirmation is not in the template system/not cared for in our logic, we could automatically reject it on the user's behalf and display a warning to the user while recording the details of the approval. That'd give us enough clues to work with I think.

@@ -115,7 +115,10 @@ export default function ConfirmationPage() {
const t = useI18nContext();
const dispatch = useDispatch();
const history = useHistory();
const pendingConfirmations = useSelector(getUnapprovedConfirmations, isEqual);
const pendingConfirmations = useSelector(
Copy link
Member

Choose a reason for hiding this comment

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

Was this the underlying error? I'm not quite sure I follow 🤔

My guess is that the problem occurs when there is a "request permissions" confirmation queued up behind a templated confirmation. I don't yet understand why it only affects the request permissions confirmation though 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wallet_requestPermissions uses the approval controller, which creates an entry in the pendingApprovals object. I was expecting that type of approval to always be handled by the routing login in the home component, and supersede this new page ever being called. However, if a wallet_addEtherumChain is queued up before a wallet_requestPermissions, the routing logic is skipped because there is already a notification window open and the user is viewing the addEthereumChain confirmation. Once they click confirm this page would have attempted to pull the remaining approval out which would be the wallet_requestPermissions one.

Copy link
Member

Choose a reason for hiding this comment

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

Ahhh I see! That makes sense, thanks

@@ -102,7 +103,7 @@ const mapStateToProps = (state) => {
isMainnet: getIsMainnet(state),
originOfCurrentTab,
shouldShowWeb3ShimUsageNotification,
pendingApprovals: Object.values(pendingApprovals),
pendingApprovals,
Copy link
Member

Choose a reason for hiding this comment

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

Nit: it might be worth renaming this prop, now that it no longer includes all pending approvals. Maybe something like pendingConfirmations, like you used on the confirmation page.

Gudahtt
Gudahtt previously approved these changes Mar 23, 2021
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

It would be better if we handled the else case, but, not a blocker as that's a pre-existing problem.

@metamaskbot
Copy link
Collaborator

Builds ready [50e8783]
Page Load Metrics (1229 ± 172 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaintNaNNaNNaNNaNNaN
domContentLoaded58721031222358172
load58821061229358172
domInteractive58721031222358172

@brad-decker
Copy link
Contributor Author

@Gudahtt gonna do the else block in a different PR -- need to think through the logic there. it won't be an else block, but rather another else-if or perhaps reworking the entire structure of this logic because the else block will trigger always because its in the componentDidMount method.

@brad-decker brad-decker merged commit 255586a into develop Mar 23, 2021
@brad-decker brad-decker deleted the fix-template-not-found-issue branch March 23, 2021 21:12
@github-actions github-actions bot locked and limited conversation to collaborators Mar 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants