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

signature for email modal #4474

Merged
merged 18 commits into from
Aug 7, 2023
Merged

signature for email modal #4474

merged 18 commits into from
Aug 7, 2023

Conversation

IlyaSmiyukha
Copy link
Contributor

closes #4232

@vercel
Copy link

vercel bot commented Jul 11, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
dao ✅ Ready (Inspect) Visit Preview Aug 7, 2023 11:51am
pioneer-2 ✅ Ready (Inspect) Visit Preview Aug 7, 2023 11:51am
pioneer-2-storybook ✅ Ready (Inspect) Visit Preview Aug 7, 2023 11:51am

Copy link
Member

@thesan thesan left a comment

Choose a reason for hiding this comment

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

@IlyaSmiyukha technically it works but it's not an acceptable solution because creating api instances is resource intensive, this is why Atlas and Pioneer ended up moving the api instance on web workers (the page would freeze for users with lower resource computer). In this case the api instance is garbage collected and it's created again if the modal is reopened. I made sure of this using my browser profiler and the main thread does always spike shortly after opening the modal :
Screenshot from 2023-07-11 18-18-06
(the 1st row shows app screenshots, I couldn't figure out how to make it bigger).

Instead what I'm suggesting is to:

  1. On the client: Go to @/proxyApi/client/ProxyApi.ts and add a sign(account: string, message: any) method on the class. This method should call postMessage with a new message type and the parameters, and return firstValueFrom(messages.pipe(...)) by also filtering from a new message type and mapping it to the signature value returned be the worker.
  2. Then on the web worker: (@/proxyApi/worker/index.ts) the api.sign method can be called with the correct value and when it resolves the signature should be passed back to the client with postMessage (similarly to how it was done 1).

I haven't tried it but it seems the sign method is also called from the web worker on Atlas so it should work. You can check the other asynchronous messages passed to and from the web worker for reference and don't hesitate to ask me if you get stuck.

Copy link
Member

@thesan thesan left a comment

Choose a reason for hiding this comment

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

Nice work ! It's great the wallet instance was usable for this instead of having to mess with the web worker.

Now please use send to update the machine context with the signature and timestamp.

Also I just merged the new App tests from dev into backend. So in packages/ui/src/app/App.stories.tsx could you please as part of this PR:

  1. Define the member emails for the tests/stories. This can be done easily by adding this to the mocks:
    localStorage: {
      membersEmail: { alice: 'alice@example.com', bob: 'bob@example.com' }
    }
  2. Start adding a test for this flow. For this you will need a story where the emails above are not defined. To do that I usually use storybook args so that instead of just defining: membersEmail: { alice: 'alice@ex... I would define something like that: membersEmail: args.hasRegisteredEmail ? { alice: 'alice@ex... } : {}. Now by creating a story with { args: { hasRegisteredEmail: false } } the modal will show and the test flow can start.

packages/ui/src/app/App.stories.tsx Outdated Show resolved Hide resolved
packages/ui/src/app/App.stories.tsx Outdated Show resolved Hide resolved
packages/ui/src/app/App.stories.tsx Show resolved Hide resolved
packages/ui/src/app/App.stories.tsx Outdated Show resolved Hide resolved
const element = await screen.getByText('Sign up to email notifications')
expect(element)
await userEvent.click(screen.getByText('Not now'))
expect(element).not.toBeInTheDocument()
Copy link
Member

Choose a reason for hiding this comment

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

Nice one 👍

IlyaSmiyukha and others added 4 commits July 26, 2023 09:41
Co-authored-by: Theophile Sandoz <theophile.sandoz@gmail.com>
Co-authored-by: Theophile Sandoz <theophile.sandoz@gmail.com>
Co-authored-by: Theophile Sandoz <theophile.sandoz@gmail.com>
Co-authored-by: Theophile Sandoz <theophile.sandoz@gmail.com>
@IlyaSmiyukha
Copy link
Contributor Author

@thesan
Should be fine now

Comment on lines 72 to 73
target: 'canceled',
action: 'BACK',
Copy link
Member

Choose a reason for hiding this comment

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

For this to work the BACK action should be define in the EmailSubscriptionEvent and also the target should be prepare

@@ -16,6 +16,7 @@ type EmailSubscriptionState =
| { value: 'transaction'; context: Context }
| { value: 'success'; context: Context }
| { value: 'error'; context: Context }
| { value: 'canceled'; context: EmptyObject }
Copy link
Member

Choose a reason for hiding this comment

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

The state is "cancel" but I don't think it needs to be defined since it just goes back to the "prepare" state

@@ -40,11 +54,17 @@ export const EmailSubscriptionModal = () => {
)
}

if (state.matches('error')) {
if (state.matches('error') || state.matches('canceled')) {
Copy link
Member

Choose a reason for hiding this comment

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

Also if the "cancel" state just goes back to the "prepare" state it shouldn't show the failure modal.

await userEvent.type(modal.getByPlaceholderText('Add email for notifications here'), 'test@email.com')
await waitFor(() => expect(button.closest('button')).toBeEnabled())
await userEvent.click(button)
expect(modal.getByText('Transaction was canceled.'))
Copy link
Member

Choose a reason for hiding this comment

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

At this point the machine gets in the cancel state because wallet? signer.signPayload is undefined, the code tries to call it, and all errors are assumed to be the user cancelling the signature. So this is not correct. Instead please change the accounts mock so you can pass it a storybook action called "sign" which will be added to the mock wallet. Currently WALLET is a constant in the module scope so this should be changed.

Copy link
Member

@thesan thesan left a comment

Choose a reason for hiding this comment

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

Nice job!

@thesan thesan merged commit a7dabc2 into Joystream:backend Aug 7, 2023
4 checks passed
@IlyaSmiyukha IlyaSmiyukha deleted the feature/email-subsxription-sign branch August 11, 2023 05:49
@thesan thesan added the scope:notifications Notifications subsystem label Aug 11, 2023
@chrlschwb chrlschwb added qa-task and removed qa-task labels Sep 15, 2023
@thesan thesan added the community-dev issue suitable for community-dev pipeline label Oct 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community-dev issue suitable for community-dev pipeline scope:notifications Notifications subsystem
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants