-
Notifications
You must be signed in to change notification settings - Fork 15
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: Improve failed extension transaction handling #3349
Feat: Improve failed extension transaction handling #3349
Conversation
await waitForDbAfterExtensionAction({ | ||
method: ExtensionMethods.INSTALL, | ||
refetchExtensionData, | ||
initialiseTransactionFailed, | ||
setUserRolesTransactionFailed, | ||
}); | ||
|
||
toast.success( | ||
<Toast | ||
type="success" | ||
title={{ id: 'extensionInstall.toast.title.success' }} | ||
description={{ | ||
id: 'extensionInstall.toast.description.success', | ||
}} | ||
/>, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iamsamgibbs if there could be some errors while either initialising the transaction or setting the user roles, does it make sense to refetch the extension action and show the success toast?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case where the initialise transaction fails, I think you might be right that we don't need to refetch the extension data.
In the case where the setUserRole transaction fails, we still want to refetch the extension data to check that the extension has been enabled still.
As for the success toast, it's a bit of a confusing ones as technically the install was successful, but the initalise / setUserRoles transactions failed, so I've opted to still show the install success but also show a failure toast for initalise / setUserRoles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iamsamgibbs I really like your approach with the error steps 🙌 though I'm wondering if it is not more clear to set the initialiseTransactionFailed
and setUserRolesTransactionFailed
flags directly?
yield waitForTxResult(installExtension.channel); | ||
} catch (error) { | ||
// Declare an error step for the error handler | ||
error.step = ExtensionInstallAndEnableErrorStep.InstallExtension; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could throw specific errors and then have typeguards too
Like for example a ExtensionInstallError
which has a step property like this component I just randomly pulled up
and then we can check the error like this:
if (error instanceof ExtensionInstallError)
and the step property will be defined
Maybe it's overkill, just wanted to drop this here :D
…ansaction handling
5f905ce
to
4380ba0
Compare
export const getExtensionSettingsDefaultValues = ( | ||
extensionData: AnyExtensionData, | ||
): object => { | ||
const { initializationParams = [] } = extensionData; | ||
const defaultValues = getInitializationDefaultValues(initializationParams); | ||
|
||
if (!isInstalledExtensionData(extensionData)) { | ||
return defaultValues; | ||
} | ||
|
||
switch (extensionData.extensionId) { | ||
case Extension.StakedExpenditure: { | ||
return { | ||
stakeFraction: extensionData?.params?.stakedExpenditure?.stakeFraction | ||
? convertFractionToEth( | ||
extensionData.params.stakedExpenditure.stakeFraction, | ||
) | ||
: String(defaultValues.stakeFraction), | ||
}; | ||
} | ||
case Extension.MultisigPermissions: { | ||
const { colonyThreshold: globalThreshold } = | ||
extensionData.params?.multiSig ?? {}; | ||
|
||
return { | ||
thresholdType: | ||
globalThreshold !== undefined | ||
? getGlobalThresholdType(globalThreshold) | ||
: MultiSigThresholdType.MAJORITY_APPROVAL, | ||
globalThreshold: globalThreshold ?? 0, | ||
domainThresholds: [], | ||
} satisfies MultiSigSettingsFormValues; | ||
} | ||
default: { | ||
return defaultValues; | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just moving an existing function up to please the liner. Below here are the actual changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a lot to untangle damn, really nice job!
It covers so many edge cases and the comments are quite welcome since all of our extension enabling has so much proprietary logic :')
Thanks for the testing steps 💯
Voting reputation
Installing the voting reputation extension works ✔️
Rejecting installation ✔️
Failed initialisation ✔️
Rejected set user roles ✔️
Rejection from the banner ✔️
Everything goes through when signing the tx ✔️
Multisig
Rejected the install tx ✔️
Signed the enable step but rejected set user roles ✔️
The banner is shown ✔️
Settings still work ✔️
Staking advanced payments
Rejected initialise ✔️
Rejected set user roles ✔️
Accept install, initialise and reject set user roles ✔️
🚢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such a nice solution to look at code-wise and also to test 💯 Really nice job here @iamsamgibbs 🙌 🥇
Went through the testing steps for the Reputation Weighted Extension
extension
Then went through the testing steps for Multi-sig
And finally got to the Staking Advanced Payments
extension - here I also tested rejecting the deprecate and uninstall transactions and everything was working as expected
All nice and clean, let's get it merged 🎉
Description
This PR aims to improve failed transactions when installing / enabling / assigning permissions for extensions.
Currently, when installing an extension it will call the
extensionInstallAndEnable
saga which includes transactions for install, initialise and setUserRoles (and will conditionally call them depending on the extension configuration).However, if either the initalise or setUserRoles transaction fails or is rejected, the UI will not handle this error state correctly and will appear as though the extension has not been installed (even though the install transaction succeeded).
This PR aims to resolve this by adding error steps to the
extensionInstallAndEnable
saga and pick these up in the error handler to update the UI as appropriate.Whilst working on this, I discovered the same issue affects the
extensionEnable
saga and related handlers. This PR applies the same changes to theextensionEnable
saga and the places from which that is called.I also discovered an issue when re-enabling an extension which I have created a new issue for (#3430) and left a TODO in this PR which suggests a starting point for a potential fix.
Testing
This one is going to be a pain to test I am afraid! Before anything else, switch to the metamask wallet as we need to be able to reject specific transactions.
There a three extensions we will be testing with as the install / enable steps work slightly differently for each.
Reputation Weighted Extension
This extension has an install step which calls only the install transaction. It then has an entirely separate enable step which calls the initialise and setUserRoles transactions. This is the only extension which explicitly has this extra enable step.
Let us first test with the intended use.
install
transaction. The transaction should succeed, the success toast should appear and the tab should automatically switch to the "Extension settings" tab.initialise
andsetUserRoles
transactions. The transactions should succeed, the install success toast should appear and the tab should automatically switch to the "Overview" tab.Now let us test rejecting some of the transactions. First we must remove the extension.
Okay, we will reject each transaction.
Step 6 - Click the "Install" button and reject the
install
transaction. The transaction should fail, the install error toast should appear.Step 7 - Click the "Install" button and accept the
install
transaction. Select a governance style and click the "Enable" button. This time, reject theinitialise
transaction. ThesetUserRoles
transaction should not appear at all, theinitialise
transaction should fail, an enable error toast should appear.Step 8 - Click the "Enable" button again. Accept the
initialise
transaction and reject thesetUserRoles
transaction. Theinitialise
transaction should succeed, thesetUserRole
transaction should fail, the "Failed to assign extension permissions" toast should appear. Also note that the extension is intialised, the "Missing permissions banner" should appear.Step 9 - Click "Enable permissions" in the "Missing permissions banner". Reject the
setUserRoles
transaction. The banner should remain visible.Step 10 - Click "Enable permissions" in the "Missing permissions banner". Accept the transaction. The banner should switch to the green success banner.
Multi-sig Extension
This extension has only the install step, but calls both the
install
andsetUserRoles
transactions. It has noinitialise
transaction.Feel free to test with the intended use to make sure it still functions properly, but I will only detail the testing steps which cover the new functionality.
Step 1 - Navigate to: http://localhost:9091/planex/extensions/MultisigPermissions
Step 2 - Click the "Install" button and reject the
install
transaction. The transaction should fail, the install error toast should appear.Step 3 - Click the "Install" button. Accept the
install
transaction and reject thesetUserRoles
transaction. Theinstall
transaction should succeed, thesetUserRoles
transaction should fail, the install success toast should show (as technically the install did succeed), but also the assign extension permissions error toast should show. The tab should automatically switch to the "Extension settings" tab and the "Missing permissions banner" should show.Step 4 - Change the threshold type to a fixed threshold with 2 approvals, and click the "Save changes" button. Accept the
multicall
transaction. The "Missing permissions banner" should remain visible and the tab should not change.Feel free to retest the Manage permissions banner functionality here too if you wish.
Staking Advanced Payments
This extension has only the install step and calls all 3 of the
install
,initialise
andsetUserRoles
transactions.Step 1 - Navigate to: http://localhost:9091/planex/extensions/StakedExpenditure
Step 2 - This extension is installed by default, so deprecate and uninstall the extension.
Step 3 - Rejecting the
install
transaction should work exactly the same as the last two extensions, so let us skip that step. Click the "Install" button. Accept theinstall
transaction and reject theinitialise
transaction. Theinstall
transaction should succeed, theinitialise
transaction should fail and thesetUserRoles
transaction should not get called at all. The install success toast should show, but also the enable extension error toast should show. The tab should automatically switch to the "Extension settings" tab. The "Missing permissions banner" should not yet show at this point as the extension is not yet enabled. This is different than the multi-sig extension as the multi-sig extension does not have the initialise step.Step 4 - Click the "Enable" button. Reject the
initialise
transaction. ThesetUserRoles
transaction should not appear at all, theinitialise
transaction should fail, an enable error toast should appear.Step 5 - Click the "Enable" button again. Accept the
initialise
transaction and reject thesetUserRoles
transaction. Theinitialise
transaction should succeed, thesetUserRole
transaction should fail, the "Failed to assign extension permissions" error toast should appear. Also note that the extension is intialised, the "Missing permissions banner" should appear.From here, test the missing permissions banner functionality if you wish.
Final bit of testing, if you have made it this far, have a drink to sustain you for the last bit! ☕ We will test accepting the
install
andinitialise
transactions, but rejecting the setUserRoles transaction.install
transaction. Accept theinitialise
transaction. Reject thesetUserRoles
transaction. The install success toast should show, but also the extension permissions error toast should show. The tab should automatically switch to the "Extension settings" tab. This time the "missing permissions banner" should show as the extension has been enabled this time around.Further testing: Feel free to try and break this in anyway you can but the testing steps are hopefully thorough enough that this is not possible. There is an unrelated issue on master related to deprecating and re-enabling where the missing permissions banner will incorrectly show (#3430).
Diffs
New stuff ✨
extensionInstallAndEnable
andextensionEnable
sagashandleWaitingForDbAfterFormCompletion
utilChanges 🏗
waitForDbAfterExtensionAction
handles new error flagsuseInstall
hook now useshandleWaitingForDbAfterFormCompletion
util in onSuccess and onError handlersExtensionsSettingsForm
useshandleWaitingForDbAfterFormCompletion
util in onSuccess and onError handlersTODO
Resolves #2754
Contributes to #3337