near / near-wallet

Web wallet for NEAR Protocol which stores keys in browser's localStorage
https://wallet.near.org
MIT License
220 stars 176 forks source link

Authorization UX: Redesign of Login & Transaction Signatures + Emails #1630

Open heycorwin opened 3 years ago

heycorwin commented 3 years ago

Problem Summary

There are a number of instances when a user performs a transaction, where they are required to confirm the transaction. Additionally, users with 2FA receive messages detailing the transaction and are required to use the code provided in order to confirm. Once a transaction is processed, success states are used to confirm that the transaction has been processed successfully. While all of these exist currently, their utility is low. Each of these screens and emails either provide little context and information about the transaction (eg gas), hide it unnecessarily, or lack a certain degree of polish in the language and phrasing that is used.

Proposed Solution

It would be worth attacking all of these instances in one fell swoop. We have an opportunity to improve the consistency across all instances of transactions confirmation messaging and success states. First, we should identify every instance, and then determine what transaction metadata is most useful for the user for each (could perform some light research to inform this). We should then craft a consistent UI to display this metadata for each instance of user authorization and success in the wallet, as well as fine-tune our 2FA messaging templates.

Dependencies

Identify all instances of Transaction Confirmations

Referenced in

heycorwin commented 3 years ago

@jimmy3dita Would you be able to assist in filling in any gaps here?

stefanopepe commented 3 years ago

Feature Design Considerations

I think we can abstract this feature as "an alert for every action that requires the wallet private key to be completed".

The actions are:

  1. Send Tokens
  2. Authorize Keys (authorize app)
  3. Call Methods

Out of scope >> will explain below:

  1. stake
  2. create account
  3. delete account

1. Send Tokens

This is straightforward, we need to display amount and recipient

2. Authorize Keys (authorize app)

Any confirmation should enable the user to know:

In my opinion, this class of authorizations requires a lot of adversarial thinking and find a high-level security abstraction. Ideally, the user should be able to understand, in less than one second, if this key is able to:

  1. lock the user out of the wallet (a full access key can override 2FA, delete previous keys and lock you out)
  2. drain all funds without any additional confirmation
  3. drain up to x funds with a confirmation
  4. perform a set of actions on his behalf (e.g. stake/unstake, transfer/sell fungible and non-fungible tokens) with or without any additional confirmation >> this is tricky because 2FA will require them to get back to the wallet anyway!

3. Call Methods

Staking and unstaking, adding 2FA, changing 2FA, transferring fungible and non-fungible tokens are all call methods that require the private key. Any confirmation should enable the user to know:

In this case, we need some key-value table (I would love to see it on a public document, so the community can contribute) such that:

To make things a bit worse, the unstake would look like:

{
  "request": {
    "receiver_id": "08investinwomen_runbybisontrails.poolv1.near",
    "actions": [
      {
        "type": "FunctionCall",
        "gas": "125000000000000",
        "method_name": "unstake",
        "args": "eyJhbW91bnQiOiIxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIn0=",
        "amount": "0",
        "deposit": "0"
      }
    ]
  }
}

The args eyJhbW91bnQiOiIxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIn0= is the Base64 encoded string for {"amount":"1000000000000000000000000"}, but it can be more complex if it is a batch transaction, or contains Rainbow Bridge proofs.

4. Out Of Scope

Stake This is a legacy method that allowed a wallet owner to stake on its own behalf and is similar to sending tokens. Now everything is going through staking pools, so this specific command should be disabled from happening via near-api-js or at least ignored.

Create account & Delete Account These are mostly handled by the backend, we may want in the future to enable power-users to access these methods, but I don't really see the value to have it in the wallet.

Scalability Considerations

We all agree that NEAR Wallet team cannot maintain an (exponentially growing) table with smart contract call methods and their arguments. The good news is that we need this abstraction across all user-facing NEAR products and potentially the entire ecosystem. So far, I've seen the need to understand transactions on:

  1. our wallet UI, either for the confirmation alert and the recent activity
  2. all 2FA confirmation messages (SMS and emails)
  3. block explorer

So, while the confirmation UX urgently needs improvements, I see the opportunity to launch a cross-functional work that may structurally solve the problem, and use some "collective intelligence" to properly represent this very heterogeneous information. We already partially discussed (the Widget concept, and the "PR-able" list of contracts and tokens).

Low-hanging fruit

Abstract this information on a new repository (or an easy-to-contribute-to directory in the wallet repo), and add the first items ourselves - starting from your actions above, and then pushing NEAR and external developers to review the content.

Next steps

  1. Triage your list of actions against the three classes I presented, and mark the critical ones (e.g. "add full access key" and "send")
  2. Create a "jack-of-all-trades" confirmation that simply prettify the json - so we cover any corner case
  3. Query the ledger to measure the most common contract calls and their arguments
  4. Focus on the top 5 or 6 to manually prioritize what is the key information and in which context (before and after)
  5. Have some "mock UI" or "mock testnet accounts" that allow us to fully test the messaging without sending actual money
  6. Call to arms for the community - and improve it!