README: second rework after review
Fix the 23 findings of the second review and the two leftovers from the first: SiteApproval's connection lifetime, the stateSchema.js module line, the flash line and title bar, the six network-bound screens, the token-only 0.000001 cutoff, the 12-character symbol cap, the time display, the native currency labels, the truncateAmountNeverZero screens, the browser suite rules, the build receipt contents, the External services list, the worker memory exceptions, POPUP_ONLY_TYPES, the undefined terms, the comma lists, the Rationale, Entrypoints and TODO sections, and the dropped crypto comment rule. A fact pass then checked every statement about the code and every absolute against each case, and a newcomer read removed repeats. Model: fable-5-1
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
# AutistMask
|
||||
|
||||
AutistMask is a browser extension. It is an Ethereum wallet for Chrome and
|
||||
Firefox. It is free software under the GPL-3.0 license, written by
|
||||
[@sneak](https://sneak.berlin).
|
||||
AutistMask is a GPL-3.0-licensed browser extension by
|
||||
[@sneak](https://sneak.berlin): an Ethereum wallet for Chrome and Firefox.
|
||||
|
||||
The wallet does four things:
|
||||
AutistMask does four things:
|
||||
|
||||
- It holds wallets made from a recovery phrase, a private key or an extended
|
||||
private key.
|
||||
@@ -20,7 +19,7 @@ It does nothing else. It has:
|
||||
- no advertising;
|
||||
- no tracking.
|
||||
|
||||
## Why it exists
|
||||
## Rationale
|
||||
|
||||
Popular browser wallets have grown:
|
||||
|
||||
@@ -48,7 +47,8 @@ Settings. The wallet uses that endpoint to:
|
||||
|
||||
The RPC endpoint sees every address that the wallet queries and every
|
||||
transaction that the wallet sends. A user who wants privacy can point the RPC
|
||||
URL, and the Blockscout URL, at a node of their own.
|
||||
URL at a node of their own, and the Blockscout URL at a Blockscout server of
|
||||
their own.
|
||||
|
||||
Two more services receive the user's data only after the user turns on a
|
||||
setting. Both settings are off in a new install. The Welcome screen and Settings
|
||||
@@ -67,7 +67,7 @@ sends nothing anywhere.
|
||||
|
||||
The section External services below lists each request.
|
||||
|
||||
## Getting started
|
||||
## Getting Started
|
||||
|
||||
Build the extension from a clone:
|
||||
|
||||
@@ -113,12 +113,12 @@ which this repository does not produce.
|
||||
|
||||
`manifest/firefox.json` requires Firefox 115 or newer.
|
||||
|
||||
The `.xpi` that `make package` writes is not signed. Release Firefox and Firefox
|
||||
ESR (the extended support release) refuse to install an unsigned add-on, and
|
||||
`xpinstall.signatures.required` has no effect on them. A permanent install of
|
||||
the unsigned file needs Firefox Developer Edition, Nightly or an unbranded build
|
||||
(Mozilla's build without the Firefox branding). On those,
|
||||
`xpinstall.signatures.required` must be set to `false` in `about:config`.
|
||||
The `.xpi` (Firefox's add-on package file) that `make package` writes is not
|
||||
signed. Release Firefox and Firefox ESR (the extended support release) refuse to
|
||||
install an unsigned add-on, and `xpinstall.signatures.required` has no effect on
|
||||
them. A permanent install of the unsigned file needs Firefox Developer Edition,
|
||||
Nightly or an unbranded build (Mozilla's build without the Firefox branding). On
|
||||
those, `xpinstall.signatures.required` must be set to `false` in `about:config`.
|
||||
|
||||
Every Firefox, release builds included, can load the extension as a temporary
|
||||
add-on from `about:debugging`. A temporary add-on is unloaded when Firefox
|
||||
@@ -173,8 +173,8 @@ offers "Use Blockscout" and "Check recipients on Etherscan".
|
||||
- "Allow weak passwords": off. While off, AddWallet refuses a password shorter
|
||||
than 12 characters. While on, one character is enough.
|
||||
- "Show tracked tokens with zero balance": on.
|
||||
- "UTC Timestamps": off. While off, timestamps are shown in local time with the
|
||||
UTC offset.
|
||||
- "UTC Timestamps": off. While off, a transaction's datetime is shown in local
|
||||
time with the UTC offset.
|
||||
- Theme: `System`, `Light` or `Dark`. Default `System`.
|
||||
- "Hide fake tokens impersonating a known symbol": on.
|
||||
- "Hide tokens with fewer than 1,000 holders": on.
|
||||
@@ -184,9 +184,9 @@ offers "Use Blockscout" and "Check recipients on Etherscan".
|
||||
- Tracked Tokens: the ERC-20 tokens tracked on the active network. Each network
|
||||
has its own list.
|
||||
- Allowed Sites: the sites allowed with "Remember my choice for this site".
|
||||
- Connected Sites: the sites allowed without it. Such a connection ends when the
|
||||
browser closes, when the active address changes, or when the site is removed
|
||||
in Settings.
|
||||
- Connected Sites: the sites allowed without "Remember my choice for this site".
|
||||
Such a connection ends when the browser closes, when the active address
|
||||
changes, or when the site is removed in Settings.
|
||||
- Denied Sites: the sites denied with "Remember my choice for this site".
|
||||
- "Remember my choice for this site": the checkbox on SiteApproval. Its last
|
||||
state is remembered. Default ticked.
|
||||
@@ -222,8 +222,8 @@ src/
|
||||
index.html the markup of every screen
|
||||
index.js popup entry point: loads the profile, restores the
|
||||
screen, runs the refresh
|
||||
viewRouter.js renders a screen the popup lands on without navigating
|
||||
to it
|
||||
viewRouter.js draws a screen that "Back" returns to when this page
|
||||
load has not drawn it yet
|
||||
theme.js applies the theme
|
||||
dustThreshold.js parses the dust threshold field
|
||||
styles/main.css Tailwind source, plus four classes of its own
|
||||
@@ -234,8 +234,9 @@ manifest/
|
||||
firefox.json Manifest V2 for Firefox
|
||||
icons/ the toolbar icon at the four sizes the manifests declare
|
||||
build.js bundles the extension into dist/
|
||||
script/ the entry points (see Development)
|
||||
tests/ jest unit tests; tests/e2e/ holds the browser suites
|
||||
script/ the entrypoints (see Development)
|
||||
tests/ jest unit tests and their helpers; tests/e2e/ holds the
|
||||
browser suites
|
||||
```
|
||||
|
||||
The shared modules, each in one line:
|
||||
@@ -253,7 +254,8 @@ The shared modules, each in one line:
|
||||
address scan on import.
|
||||
- `browserApi.js`: the one module that names `chrome` or `browser`; storage,
|
||||
messaging, windows and the lock.
|
||||
- `buildInfo.js`: the version, commit and date compiled into About.
|
||||
- `buildInfo.js`: the version, license, author, commit and date compiled into
|
||||
About.
|
||||
- `chainSwitch.js`: the popup's network switch.
|
||||
- `chainSwitchFields.js`: the fields a network switch changes.
|
||||
- `constants.js`: `DEBUG`, the default endpoints, the ERC-20 ABI and the burn
|
||||
@@ -272,8 +274,8 @@ The shared modules, each in one line:
|
||||
- `restorableViews.js`: the screens a reopened popup may land on.
|
||||
- `scamlist.js`: known scam addresses.
|
||||
- `state.js`: the popup's in-memory profile and `saveState()`.
|
||||
- `stateSchema.js`: `schemaVersion` and the check every profile read goes
|
||||
through.
|
||||
- `stateSchema.js`: `schemaVersion` and `assertStateUsable()`, the check that
|
||||
the two state modules run on each read.
|
||||
- `storedSettings.js`: reads "Use Blockscout" and "Check recipients on
|
||||
Etherscan" from storage.
|
||||
- `symbolDisplay.js`: the 12-character cap on a displayed symbol.
|
||||
@@ -287,8 +289,8 @@ The shared modules, each in one line:
|
||||
- `uniswap.js`: the Uniswap Universal Router decoder.
|
||||
- `vault.js`: password-based encryption with libsodium.
|
||||
- `wallet.js`: recovery phrases, key derivation and signers.
|
||||
- `walletDefects.js`: the notice for an xprv wallet whose stored key is not a
|
||||
master key.
|
||||
- `walletDefects.js`: the notice for an xprv wallet imported from a key that was
|
||||
not a master key.
|
||||
- `walletDelete.js`: removing a wallet or an address from the profile.
|
||||
|
||||
### Wallets, keys and encryption
|
||||
@@ -301,14 +303,18 @@ A wallet is one of three types:
|
||||
- An xprv wallet (`type: "xprv"`) comes from an extended private key. It behaves
|
||||
like an HD wallet but has no recovery phrase.
|
||||
|
||||
All key handling goes through `ethers`. Addresses are derived on the path
|
||||
`m/44'/60'/0'/0/n`, with no BIP-39 passphrase (the optional extra word some
|
||||
wallets add to a phrase). A new recovery phrase has 12 words. An extended
|
||||
All key derivation and signing goes through `ethers`. Addresses are derived on
|
||||
the path `m/44'/60'/0'/0/n`, with no BIP-39 passphrase (the optional extra word
|
||||
some wallets add to a phrase). A new recovery phrase has 12 words. An extended
|
||||
private key must be a master key, the root of the key tree. AddWallet refuses a
|
||||
child key, one derived below the root. Each HD or xprv address record stores its
|
||||
`index`, and signing derives the key at that index. `getSignerForAddress()` in
|
||||
`src/shared/wallet.js` refuses a key that does not belong to the address.
|
||||
|
||||
An xprv wallet imported from a key that was not a master key carries a notice in
|
||||
the wallet list (`src/shared/walletDefects.js`). Such a wallet shows no "+"
|
||||
button, and Send, site signing and private key export refuse it.
|
||||
|
||||
The secret of each wallet is encrypted with that wallet's password
|
||||
(`src/shared/vault.js`):
|
||||
|
||||
@@ -322,12 +328,14 @@ The password is not part of address derivation. Anyone holding the recovery
|
||||
phrase can restore the wallet elsewhere without it. The password protects the
|
||||
copy stored in this browser and nothing else.
|
||||
|
||||
Public data is stored unencrypted:
|
||||
Only the wallet secrets are encrypted. Everything else in the profile is stored
|
||||
as plain data, among it:
|
||||
|
||||
- the `xpub` of each HD or xprv wallet, the extended public key that its
|
||||
addresses are derived from;
|
||||
- the addresses and their balances;
|
||||
- the tracked tokens;
|
||||
- the site lists;
|
||||
- the settings.
|
||||
|
||||
The popup shows all of that without a password. The password is required to:
|
||||
@@ -350,12 +358,12 @@ which stays loaded. Both take the same code paths.
|
||||
|
||||
Three rules follow from the worker being stopped:
|
||||
|
||||
- Nothing is kept in module variables between events. The worker reads the
|
||||
profile from storage on every call (`getState()` in `src/background/state.js`)
|
||||
and writes it back under the lock (`updateState()`).
|
||||
- The profile is never kept in module variables. The worker reads it from
|
||||
storage on every call (`getState()` in `src/background/state.js`) and writes
|
||||
it back under the lock (`updateState()`).
|
||||
- The recurring balance refresh runs off an alarm (`src/shared/alarms.js`), not
|
||||
a timer. The browser holds the schedule and wakes the worker. The period is
|
||||
one minute. The refresh is skipped when the last refresh finished less than 30
|
||||
one minute. The refresh is skipped when the last refresh started less than 30
|
||||
seconds ago. An open popup refreshes every 10 seconds, so while the popup is
|
||||
open the background stays quiet.
|
||||
- Connections allowed without "Remember my choice for this site" are kept in the
|
||||
@@ -363,11 +371,12 @@ Three rules follow from the worker being stopped:
|
||||
worker stopping. Such a connection ends when the browser closes, when the
|
||||
active address changes, or when the site is removed in Settings.
|
||||
|
||||
Pending approvals are the exception. An approval, and the site's request waiting
|
||||
on it, live in the worker's memory. While any approval is pending, the worker
|
||||
calls `runtime.getPlatformInfo()` every 20 seconds. Chrome counts that call as
|
||||
activity and keeps the worker running. The timer stops itself once nothing is
|
||||
pending.
|
||||
Pending approvals and the record of broadcast nonces are the exceptions. Both
|
||||
live in the worker's memory, and both are lost when the worker stops. An
|
||||
approval, and the site's request waiting on it, exist nowhere else. So while any
|
||||
approval is pending, the worker calls `runtime.getPlatformInfo()` every 20
|
||||
seconds. Chrome counts that call as activity and keeps the worker running. The
|
||||
timer stops itself once nothing is pending.
|
||||
|
||||
Alarms the code no longer handles are listed in `OBSOLETE_ALARMS` and cleared on
|
||||
every start. The worker fetches nothing when it starts.
|
||||
@@ -431,36 +440,40 @@ Home otherwise. The Settings gear in the title bar is the only global control.
|
||||
|
||||
The popup saves the current screen. Reopening the popup lands on that screen
|
||||
when the screen is in `RESTORABLE_VIEWS` (`src/shared/restorableViews.js`).
|
||||
Every other screen falls back to Home. The two screens that show a secret,
|
||||
ExportPrivKey and ShowRecoveryPhrase, are not restorable. Neither are the two
|
||||
that erase a wallet, DeleteWallet and DeleteWalletLostPassword.
|
||||
Every other screen falls back to Home. A restorable screen whose data is gone
|
||||
falls back to Home too. The two screens that show a secret, ExportPrivKey and
|
||||
ShowRecoveryPhrase, are not restorable. Neither are the two that erase a wallet,
|
||||
DeleteWallet and DeleteWalletLostPassword.
|
||||
|
||||
A reopened popup renders only the wallet list and the screen that it lands on.
|
||||
"Back" onto a screen that this page load has not rendered renders that screen
|
||||
first (`src/popup/viewRouter.js`). When the data for that screen is gone, Home
|
||||
is shown instead. "Back" onto a screen already on the page only unhides it, so
|
||||
unsaved input in Settings survives. Home is rendered again on every "Back".
|
||||
A reopened popup draws only the wallet list and the screen that it lands on.
|
||||
When "Back" returns to a screen that this page load has not drawn yet,
|
||||
`src/popup/viewRouter.js` draws it first. When the data for that screen is gone,
|
||||
Home is shown instead. "Back" onto a screen already drawn only unhides it, so
|
||||
unsaved input in Settings survives. Home is drawn again on every "Back".
|
||||
|
||||
A network switch, or a change to "Use Blockscout", cuts the stack at the first
|
||||
screen that cannot be rendered from saved state. Every screen then counts as not
|
||||
rendered. Settings on top is redrawn in place. Any other screen is redrawn as a
|
||||
reopened popup would draw it. Five screens are drawn for the network of the
|
||||
transaction that they show, whichever network is active:
|
||||
screen that cannot be drawn from saved state. The cut also drops AddressToken
|
||||
unless it shows ETH. After either change, and after a change to "Check
|
||||
recipients on Etherscan", every screen but Settings counts as not drawn.
|
||||
Settings on top is redrawn in place. Any other screen is redrawn as a reopened
|
||||
popup would draw it. Six screens are drawn for the network of the transaction
|
||||
that they show, whichever network is active:
|
||||
|
||||
- ConfirmTx;
|
||||
- WaitTx;
|
||||
- SuccessTx;
|
||||
- ErrorTx;
|
||||
- TransactionDetail.
|
||||
- TransactionDetail;
|
||||
- TxApproval.
|
||||
|
||||
A screen that holds a secret in the page registers a cleanup with
|
||||
`onViewLeave()`. `showView()` runs the cleanup on every exit from that screen.
|
||||
So a revealed key or phrase, or a typed password, never survives in a hidden
|
||||
screen.
|
||||
|
||||
Two things are present on every screen but StateRecovery: the title bar with the
|
||||
Settings gear, and the flash message line under it. The flash line holds one
|
||||
line of text for two seconds.
|
||||
Every screen has the title bar and the flash message line under it. A flash
|
||||
message stays two seconds unless the screen sets another time. StateRecovery
|
||||
hides the Settings gear in the title bar.
|
||||
|
||||
On Sepolia, or with debug on, a red banner sits at the top of the page. It reads
|
||||
`[TESTNET]` on Sepolia, `DEBUG / INSECURE` with debug on, and
|
||||
@@ -493,10 +506,14 @@ Ticking a checkbox saves the setting at once. "Add wallet" opens AddWallet.
|
||||
|
||||
Shown while at least one wallet exists. The screen holds:
|
||||
|
||||
- the active address's ETH balance, with its USD value in parentheses;
|
||||
- the active address's ETH balance, with its USD value in parentheses when a
|
||||
price is known;
|
||||
- a "Total:" line with the USD value of the address's holdings (see Partial
|
||||
totals below);
|
||||
- the active address: colour dot, full address, explorer link, tap to copy;
|
||||
- the active address:
|
||||
- its colour dot;
|
||||
- the full address. Tapping it copies it;
|
||||
- an explorer link;
|
||||
- "Send" and "Receive" buttons for the active address;
|
||||
- the ETH/USD price, on mainnet;
|
||||
- the wallet list;
|
||||
@@ -506,8 +523,9 @@ Shown while at least one wallet exists. The screen holds:
|
||||
- an "Add additional wallet..." link.
|
||||
|
||||
Each wallet in the list shows its name. Tapping the name renames it in place. HD
|
||||
and xprv wallets also show a "+" button that derives the next address. Each
|
||||
address of a wallet is a block:
|
||||
and xprv wallets also show a "+" button that derives the next address, unless
|
||||
the wallet carries the notice from `src/shared/walletDefects.js`. Each address
|
||||
of a wallet is a block:
|
||||
|
||||
- a row with the colour dot and "Address N", bold when the address is active;
|
||||
- on that row, an `[info]` button and, on HD and xprv wallets holding more than
|
||||
@@ -539,7 +557,7 @@ Transitions:
|
||||
- `[info]`: AddressDetail.
|
||||
- `[x]`: DeleteAddress.
|
||||
- "Send": Send. Refused with a flash message when the active address has a zero
|
||||
ETH balance.
|
||||
ETH balance or belongs to a wallet carrying the `walletDefects.js` notice.
|
||||
- "Receive": Receive.
|
||||
- Tap a transaction row: TransactionDetail.
|
||||
- "Add additional wallet...": AddWallet.
|
||||
@@ -572,11 +590,12 @@ the RPC endpoint, five at a time. The scan stops after five unused addresses in
|
||||
a row. When the scan finds two or more used addresses, they replace the wallet's
|
||||
list. The flash line reports the count.
|
||||
|
||||
Refusals:
|
||||
A missing, short or mismatched password gets a full sentence on the error line.
|
||||
A flash message refuses:
|
||||
|
||||
- a missing, short or mismatched password: a full sentence on the error line;
|
||||
- an invalid phrase or key, an extended private key that is not a master key, or
|
||||
a phrase or address already in a wallet: a flash message.
|
||||
- an invalid phrase or key;
|
||||
- an extended private key that is not a master key;
|
||||
- a phrase or address already in a wallet.
|
||||
|
||||
"Back" returns to the previous screen.
|
||||
|
||||
@@ -587,7 +606,8 @@ Reached from `[info]` on Home. The screen holds:
|
||||
- a "Back" button;
|
||||
- the address's identicon;
|
||||
- the title "Wallet Name — Address N";
|
||||
- the full address with its ENS name, explorer link and tap to copy;
|
||||
- the full address, with its ENS name and an explorer link. Tapping the address
|
||||
copies it;
|
||||
- the address's USD total;
|
||||
- the balance list: ETH, then each token shown for the address. Each row opens
|
||||
AddressToken;
|
||||
@@ -601,7 +621,7 @@ Transitions:
|
||||
|
||||
- a balance row: AddressToken;
|
||||
- "Send": Send. Refused with a flash message when the address has a zero ETH
|
||||
balance;
|
||||
balance or belongs to a wallet carrying the `walletDefects.js` notice;
|
||||
- "Receive": Receive;
|
||||
- "+ Token": AddToken;
|
||||
- "Export Private Key": ExportPrivKey;
|
||||
@@ -650,8 +670,9 @@ Reached by tapping a balance row on AddressDetail. The screen holds:
|
||||
"Use Blockscout" is off.
|
||||
|
||||
"Send" opens Send with the token locked: the dropdown is replaced by the symbol
|
||||
and contract address. "Receive" opens Receive with the ERC-20 warning. A
|
||||
transaction row opens TransactionDetail. "Back" returns to AddressDetail.
|
||||
and contract address. "Receive" opens Receive, with the ERC-20 warning for a
|
||||
token. A transaction row opens TransactionDetail. "Back" returns to
|
||||
AddressDetail.
|
||||
|
||||
#### Send (`send`)
|
||||
|
||||
@@ -669,7 +690,7 @@ Reached from Home, AddressDetail or AddressToken. The screen holds:
|
||||
The dropdown offers ETH and the tokens of the address's balance list. It leaves
|
||||
out:
|
||||
|
||||
- holdings below 0.000001;
|
||||
- token holdings below 0.000001;
|
||||
- tokens with a spoofed symbol;
|
||||
- tokens on the fraud contract blocklist;
|
||||
- while "Hide tokens with fewer than 1,000 holders" is on, tokens with a
|
||||
@@ -799,8 +820,8 @@ Reached from Home, AddressDetail or AddressToken. The screen holds:
|
||||
- a QR code of the address;
|
||||
- the full address;
|
||||
- a "Copy address" button;
|
||||
- when opened from a token's screen, a warning to send only that token on this
|
||||
network to this address.
|
||||
- when opened from an ERC-20 token's screen, a warning to send only that token
|
||||
on this network to this address.
|
||||
|
||||
"Back" returns to the previous screen.
|
||||
|
||||
@@ -848,7 +869,8 @@ Reached from "+ Token" on AddressDetail. The screen holds:
|
||||
|
||||
"Add" looks up `symbol()`, `decimals()` and `name()` on the contract through the
|
||||
RPC endpoint. On success it adds the token to the tracked list, pops the stack
|
||||
and shows AddressDetail. A flash message refuses:
|
||||
and shows AddressDetail. If another screen is showing by then, the screen does
|
||||
not change. A flash message refuses:
|
||||
|
||||
- a token already tracked;
|
||||
- an address on the scam list;
|
||||
@@ -862,8 +884,8 @@ says so.
|
||||
Reached from the gear. The screen holds, under headings:
|
||||
|
||||
- Wallets: one row per wallet, with "+ Add wallet" under them. A row holds the
|
||||
name (tap to rename), a `[recovery phrase]` button on HD wallets, and an `[x]`
|
||||
button.
|
||||
name, a `[recovery phrase]` button on HD wallets, and an `[x]` button. Tapping
|
||||
the name renames it in place.
|
||||
- Passwords: the "Allow weak passwords" checkbox.
|
||||
- Tracked Tokens: one row per token tracked on the active network with an `[x]`
|
||||
button, and "+ Add token".
|
||||
@@ -898,8 +920,9 @@ Transitions:
|
||||
|
||||
- Switching the network restores the RPC and Blockscout URLs last used on that
|
||||
network, or the network's defaults, and the tokens tracked there. It clears
|
||||
every address's balances. It tells every open tab the new chain id with
|
||||
`chainChanged`. Choosing the network already active changes nothing.
|
||||
every address's balances and the fraud contract blocklist. It tells every open
|
||||
tab the new chain id with `chainChanged`. Choosing the network already active
|
||||
changes nothing.
|
||||
- Ticking or unticking "Use Blockscout" or "Check recipients on Etherscan"
|
||||
stores the setting. From then on every screen and every refresh uses the new
|
||||
value. Unticking "Use Blockscout" also drops every untracked token from every
|
||||
@@ -1004,8 +1027,8 @@ separate window. The screen holds:
|
||||
- "Allow" and "Deny" buttons.
|
||||
|
||||
"Allow" with "Remember" ticked adds the origin to Allowed Sites. "Allow" without
|
||||
it connects the site until the browser closes. "Deny" with "Remember" ticked
|
||||
adds the origin to Denied Sites. Closing the popup without an answer is a
|
||||
it adds the site to Connected Sites (see Settings). "Deny" with "Remember"
|
||||
ticked adds the origin to Denied Sites. Closing the popup without an answer is a
|
||||
denial.
|
||||
|
||||
#### TxApproval (`approve-tx`)
|
||||
@@ -1061,11 +1084,11 @@ as a personal message.
|
||||
|
||||
Typed data is shown as its domain, the primary type that `ethers` will sign, and
|
||||
the message fields that this type declares, in the type's order. Keys that the
|
||||
type does not declare are listed under "Not part of the signature". Typed data
|
||||
whose primary type is `Permit`, or one of the signature types of Permit2
|
||||
(Uniswap's token allowance contract), gets a red warning at the top. The warning
|
||||
names the spender, and each token and amount that the signature lets the spender
|
||||
take. `Unlimited` marks the field's largest value. `Unknown` marks anything the
|
||||
type does not declare are listed under "Not part of the signature". A red
|
||||
warning heads the message when the primary type is `Permit` or a Permit2
|
||||
signature type. Permit2 is Uniswap's token allowance contract. The warning names
|
||||
the spender, and each token and amount that the signature lets the spender take.
|
||||
`Unlimited` marks the field's largest value. `Unknown` marks anything the
|
||||
declared fields do not give.
|
||||
|
||||
"Sign" is disabled, with the reason on the error line, when:
|
||||
@@ -1112,15 +1135,23 @@ popup closes.
|
||||
|
||||
### Amounts
|
||||
|
||||
The same data is formatted the same way on every screen. Token and ETH amounts
|
||||
show four decimal places. History rows cut amounts to four decimals and never
|
||||
round up (`truncateAmount()` in `src/shared/amountDisplay.js`). The balance
|
||||
lists and Home's ETH balance round to four places. The screens that state what
|
||||
is being authorized cut as the history does, and extend an amount below 0.0001
|
||||
to its first nonzero digit (`truncateAmountNeverZero()`). So a nonzero amount
|
||||
never reads as zero there. Those screens are:
|
||||
These helpers write one kind of value on every screen that shows it:
|
||||
|
||||
- `formatUsd()` in `src/shared/prices.js`: USD values;
|
||||
- `isoDate()` and `timeAgo()` in `src/popup/views/helpers.js`: times;
|
||||
- `renderAddressHtml()` in the same file: most addresses.
|
||||
|
||||
Amounts are written by the two helpers below, or rounded by the balance lists.
|
||||
Most screens show token and ETH amounts with four decimal places. History rows
|
||||
cut amounts to four decimals and never round up (`truncateAmount()` in
|
||||
`src/shared/amountDisplay.js`). The balance lists and Home's ETH balance round
|
||||
to four places. The screens that state what is being authorized cut as the
|
||||
history does, and extend an amount below 0.0001 to its first nonzero digit
|
||||
(`truncateAmountNeverZero()`). So a nonzero amount never reads as zero there.
|
||||
Those screens are:
|
||||
|
||||
- TxApproval;
|
||||
- SignApproval's Permit warning;
|
||||
- ConfirmTx, and Send's current balance;
|
||||
- WaitTx, SuccessTx and ErrorTx.
|
||||
|
||||
@@ -1149,7 +1180,8 @@ as a token's decimals. A token's `decimals` is stored only as a source reported
|
||||
it, never guessed. A `null` balance means the decimals are unknown, never that
|
||||
the balance is zero. While "Use Blockscout" is off, the approval and status
|
||||
screens add a line under a token that neither the bundled list nor the tracked
|
||||
tokens name. The line says that Blockscout's report is not used.
|
||||
tokens name or give decimals for. The line says that Blockscout's report is not
|
||||
used.
|
||||
|
||||
The wallet's own ERC-20 send is encoded with the decimals the screen showed. At
|
||||
signing time the contract's `decimals()` is read only to be compared with those.
|
||||
@@ -1158,21 +1190,23 @@ A disagreement refuses the send (`src/shared/transferAmount.js`).
|
||||
A native amount is labelled with the native currency of the transaction's chain:
|
||||
`ETH` on mainnet, `SepoliaETH` on Sepolia (`nativeCurrencyByChainId()` in
|
||||
`src/shared/networks.js`). The balance lists and Send use the active network's.
|
||||
The decoded swap lines call the native currency `ETH` on both networks.
|
||||
|
||||
A transaction's time is shown as an ISO datetime and a relative age, written by
|
||||
`isoDate()` and `timeAgo()` in `src/popup/views/helpers.js`. With "UTC
|
||||
TransactionDetail shows the time as an ISO datetime and a relative age. A
|
||||
history row shows the age, with the datetime as its tooltip. With "UTC
|
||||
Timestamps" on, the datetime is in UTC.
|
||||
|
||||
Every nonzero holding is stored exactly. A holding below 0.000001 is left out
|
||||
of:
|
||||
Every nonzero holding is stored exactly. A token holding below 0.000001 is left
|
||||
out of:
|
||||
|
||||
- the balance lists;
|
||||
- the Send dropdown;
|
||||
- the address total;
|
||||
- the DeleteAddress warning.
|
||||
|
||||
A displayed token symbol is cut to 12 characters
|
||||
(`src/shared/symbolDisplay.js`).
|
||||
Most screens cut a token symbol to 12 characters
|
||||
(`src/shared/symbolDisplay.js`). The approval screens, the decoded calldata
|
||||
lines and Send's "Current balance" line show it in full.
|
||||
|
||||
#### Partial totals
|
||||
|
||||
@@ -1189,12 +1223,11 @@ same way on every screen:
|
||||
### Addresses
|
||||
|
||||
Every address is shown in full, on a row of its own that never wraps (the
|
||||
`.am-address` class in `src/popup/styles/main.css`). No screen shortens an
|
||||
address shown as an address. `truncateMiddle()` in `src/popup/views/helpers.js`
|
||||
removes at most 10 characters, and `renderAddressHtml()` never shortens an
|
||||
address below 32 characters, but no caller shortens one today. A token with no
|
||||
known symbol is labelled by the first 10 characters of its contract address and
|
||||
`…` (`resolveSymbol()` in `src/shared/tokenList.js`); Send and AddressToken show
|
||||
`.am-address` class in `src/popup/styles/main.css`). No caller shortens an
|
||||
address. `truncateMiddle()` in `src/popup/views/helpers.js` removes at most 10
|
||||
characters, and `renderAddressHtml()` keeps at least 32. A token with no known
|
||||
symbol is labelled by the first 10 characters of its contract address and `…`
|
||||
(`resolveSymbol()` in `src/shared/tokenList.js`); Send and AddressToken show
|
||||
that label.
|
||||
|
||||
On most screens, tapping an address copies it, and an explorer link sits beside
|
||||
@@ -1203,12 +1236,13 @@ Each explorer link opens the block explorer of the address's network:
|
||||
`etherscan.io` on mainnet and `sepolia.etherscan.io` on Sepolia. The links
|
||||
contact nothing until clicked.
|
||||
|
||||
Each address gets a colour dot chosen from its first four hex digits, and an
|
||||
identicon on the screens where space allows.
|
||||
Each address gets a colour dot chosen from its first four hex digits. An
|
||||
identicon appears on AddressDetail, AddressToken, ExportPrivKey, ConfirmTx and
|
||||
TransactionDetail.
|
||||
|
||||
### Scam protection
|
||||
|
||||
Five defenses are on by default.
|
||||
Six defenses are built in. Four of them are settings, on by default.
|
||||
|
||||
Known symbol spoofing. `KNOWN_SYMBOLS` in `src/shared/tokenList.js` maps each
|
||||
symbol of the bundled list to the contracts that may bear it. `ETH` and every
|
||||
@@ -1232,8 +1266,9 @@ number written in digits counts as a count (`src/shared/holders.js`).
|
||||
Fraud contract blocklist. Detecting a spoofed transfer adds its contract to
|
||||
`fraudContracts` in the profile. While "Hide transactions from detected fraud
|
||||
contracts" is on, the history hides transfers from those contracts. The Send
|
||||
dropdown always leaves them out. Turning the spoof setting off also stops new
|
||||
entries being learned.
|
||||
dropdown always leaves them out. Turning off "Hide fake tokens impersonating a
|
||||
known symbol" also stops new entries being added. A network switch clears the
|
||||
list.
|
||||
|
||||
Dust transactions. While "Hide dust transactions below N gwei" is on, the
|
||||
history hides native transfers below the threshold. Contract calls and token
|
||||
@@ -1245,15 +1280,7 @@ has approved them). ConfirmTx warns before a send to one of them. AddToken and
|
||||
SettingsAddToken refuse to track one. The list holds addresses involved in fraud
|
||||
only. It is not a sanctions list.
|
||||
|
||||
ConfirmTx also warns when the recipient is:
|
||||
|
||||
- a contract;
|
||||
- a burn address;
|
||||
- the sending address itself;
|
||||
- an address that has never sent a transaction and holds none of the network's
|
||||
native token;
|
||||
- while "Check recipients on Etherscan" is on, an address Etherscan labels as
|
||||
phishing, scam or exploiter.
|
||||
The other warnings on ConfirmTx are listed under that screen.
|
||||
|
||||
#### Phishing domains
|
||||
|
||||
@@ -1292,17 +1319,18 @@ when both tokens are known. The lines are:
|
||||
|
||||
- `Protocol`: `Uniswap Universal Router`, with the router's address.
|
||||
- `Token In` and `Token Out`: the currencies the swap spends and buys.
|
||||
`ETH (native)` for ETH. `Unknown (not named in the calldata)` when no step
|
||||
names one. `Unknown (could not be decoded)` when a V4 swap action could not be
|
||||
read or the transaction has an `EXECUTE_SUB_PLAN` step.
|
||||
`Token In` reads `ETH (native)` for ETH; `Token Out` reads `ETH`.
|
||||
`Unknown (not named in the calldata)` when no step names one.
|
||||
`Unknown (could not be decoded)` when a V4 swap action could not be read or
|
||||
the transaction has an `EXECUTE_SUB_PLAN` step.
|
||||
- `Amount`: the total that the steps take of `Token In` from the user. `Up to`
|
||||
is prefixed when the transaction has a V2 or V3 exact-out step. `Unlimited`
|
||||
marks an amount at or above the `uint160` maximum.
|
||||
`All available (V4 open delta)` and
|
||||
`Whatever an earlier step sent to the pair (V2 already paid)` name the two
|
||||
amounts that are not quantities. The line is left out when the decoder cannot
|
||||
bound what leaves the wallet; each amount that it did read then gets lines of
|
||||
its own.
|
||||
tell the most that can leave the wallet; each amount that it did read then
|
||||
gets lines of its own.
|
||||
- `Moved from the sender`, `Token moved` and `Moved to`: an amount taken from
|
||||
the sender that the `Amount` line does not include. The same three lines show
|
||||
what a `PERMIT2_TRANSFER_FROM` moves and where.
|
||||
@@ -1323,10 +1351,11 @@ when both tokens are known. The lines are:
|
||||
- no `Paid to` line is shown;
|
||||
- no allowance goes to a spender other than the router.
|
||||
- `Steps`: each command by name, in order. A step that the router lets fail
|
||||
without reverting is marked `(allowed to fail)`. A `BALANCE_CHECK_ERC20` step
|
||||
that the decoder could not read, and a V4 step with a swap action that it
|
||||
could not read, are marked `(could not be decoded)`. An `EXECUTE_SUB_PLAN`
|
||||
step is marked `(its steps are not shown)`.
|
||||
without reverting is marked `(allowed to fail)`. An `EXECUTE_SUB_PLAN` step is
|
||||
marked `(its steps are not shown)`. Two kinds of step are marked
|
||||
`(could not be decoded)`:
|
||||
- a `BALANCE_CHECK_ERC20` step that the decoder could not read;
|
||||
- a V4 step with a swap action that it could not read.
|
||||
- `Deadline`: the router's deadline as a UTC date and time. A deadline past the
|
||||
range of a JavaScript date reads
|
||||
`After 275760-09-13 00:00:00 (no deadline in practice)`.
|
||||
@@ -1348,8 +1377,9 @@ decide what the router still holds after each step. Those rules decide what the
|
||||
|
||||
The inpage provider (`src/content/inpage.js`) puts a `window.ethereum` provider
|
||||
on every page, unless another wallet already set one. It announces the provider
|
||||
through EIP-6963 with a fresh random UUID per page load. The content script
|
||||
(`src/content/index.js`) relays each request to the background.
|
||||
through EIP-6963, the standard that lets a page list the installed wallets, with
|
||||
a fresh random UUID per page load. The content script (`src/content/index.js`)
|
||||
relays each request to the background.
|
||||
|
||||
A site is its full origin: scheme, host and port. A choice for
|
||||
`https://app.example` says nothing about `http://app.example`. The background
|
||||
@@ -1365,8 +1395,9 @@ The background answers these methods:
|
||||
is allowed or connected, otherwise nothing.
|
||||
- `eth_chainId` and `net_version`: the active network's values.
|
||||
- `wallet_switchEthereumChain`: NetworkApproval, for a connected site naming a
|
||||
supported network. An unsupported chain is refused with code `4902`. A site
|
||||
that is not connected is refused with code `4100`.
|
||||
supported network other than the active one. A request naming the active
|
||||
network is answered with success at once. An unsupported chain is refused with
|
||||
code `4902`. A site that is not connected is refused with code `4100`.
|
||||
- `wallet_addEthereumChain`: success for a supported chain, code `4902`
|
||||
otherwise. It never switches the network.
|
||||
- `personal_sign`, `eth_sign`, `eth_signTypedData` and `eth_signTypedData_v4`:
|
||||
@@ -1380,9 +1411,9 @@ The background answers these methods:
|
||||
includes `eth_sendRawTransaction`.
|
||||
- Anything else is refused with code `4200`.
|
||||
|
||||
The background also answers messages from the extension's own pages, such as
|
||||
`AUTISTMASK_GET_CONNECTED_SITES` and `AUTISTMASK_REMOVE_SITE`. It answers them
|
||||
only when the sender is one of those pages.
|
||||
The background also answers messages from the extension's own pages. The types
|
||||
in `POPUP_ONLY_TYPES` in `src/background/index.js` are answered only when the
|
||||
sender is one of those pages.
|
||||
|
||||
One transaction approval exists at a time, wallet-wide, because filling in a
|
||||
transaction fixes its nonce. A second `eth_sendTransaction` while one is
|
||||
@@ -1390,13 +1421,13 @@ unanswered is refused with code `-32002`. One site approval, one signature
|
||||
approval and one network approval exist per site at a time, with the same code.
|
||||
|
||||
For `eth_sendTransaction`, the background fills in the transaction before any
|
||||
window opens (`src/shared/approvalTx.js`). The nonce is the account's next nonce
|
||||
from the node. The fees are the site's when it gave them, otherwise the node's.
|
||||
The gas limit is the node's estimate unless the site gave one. A site's nonce is
|
||||
ignored. When the node refuses the transaction or gives no answer within 20
|
||||
seconds, no window opens and the site gets the node's error. The popup signs
|
||||
exactly the object that it was shown. The background then checks the signed
|
||||
transaction (`verifySignedTx()` in `src/shared/approvalVerify.js`):
|
||||
window opens (`src/shared/approvalTx.js`). The nonce is the sending address's
|
||||
next nonce, read from the node. The fees are the site's when it gave them,
|
||||
otherwise the node's. The gas limit is the node's estimate unless the site gave
|
||||
one. A site's nonce is ignored. When the node refuses the transaction or gives
|
||||
no answer within 20 seconds, no window opens and the site gets an error. The
|
||||
popup signs exactly the object that it was shown. The background then checks the
|
||||
signed transaction (`verifySignedTx()` in `src/shared/approvalVerify.js`):
|
||||
|
||||
- the signer is the address that the approval was raised for;
|
||||
- the type is 0, 1 or 2;
|
||||
@@ -1408,18 +1439,21 @@ transaction (`verifySignedTx()` in `src/shared/approvalVerify.js`):
|
||||
|
||||
A mismatch spends the approval: the site gets an error, and the signed
|
||||
transaction is not retried. A wrong password leaves the approval standing. After
|
||||
a broadcast the nonce is recorded, and a second signed transaction with that
|
||||
nonce is refused. Signatures are checked the same way: the background recovers
|
||||
the signer from the signature and refuses any other address.
|
||||
a broadcast the nonce is recorded, and the background refuses a second signed
|
||||
transaction with that nonce until the worker stops. Signatures are checked the
|
||||
same way: the background recovers the signer from the signature and refuses any
|
||||
other address.
|
||||
|
||||
Switching the active address rejects every pending approval with code `4001` and
|
||||
closes its window. It ends every connection allowed without "Remember", and
|
||||
sends `accountsChanged` to every tab with permission.
|
||||
closes its window, except an approval already being signed and sent. It ends
|
||||
every connection allowed without "Remember". It sends `accountsChanged` to every
|
||||
tab: the active address to a site with permission, an empty list to the rest.
|
||||
|
||||
Approval windows open at 396 by 600 pixels, centred on the browser window last
|
||||
in focus. The window widens itself by however far the screen would scroll
|
||||
sideways. A transaction or signature approval whose window closes stays pending.
|
||||
The toolbar button then opens the oldest such approval instead of the wallet.
|
||||
in focus when that is a normal window. The window widens itself by however far
|
||||
the screen would scroll sideways. A transaction or signature approval whose
|
||||
window closes stays pending. The toolbar button then opens the oldest such
|
||||
approval instead of the wallet.
|
||||
|
||||
#### Ceilings
|
||||
|
||||
@@ -1440,17 +1474,20 @@ Ethereum JSON-RPC endpoint, contacted by default:
|
||||
- balance reads (`eth_getBalance`, `balanceOf` through `eth_call`) every 10
|
||||
seconds while the popup is open and every minute in the background;
|
||||
- ENS reverse lookups of the user's addresses on each refresh, and of history
|
||||
counterparties when a list is shown (cached for 12 hours in the popup);
|
||||
counterparties when AddressDetail or AddressToken shows its list (cached for
|
||||
12 hours in the popup);
|
||||
- the ENS name lookup when Send resolves a name;
|
||||
- on mainnet, Chainlink `latestRoundData()` reads for ETH and for each held or
|
||||
tracked token with a feed. They go as one batched request, at most every 5
|
||||
minutes while the popup is open. A reading older than the feed's heartbeat
|
||||
plus 30 minutes is no price;
|
||||
(the longest the feed goes without a new price) plus 30 minutes is no price;
|
||||
- the address scan on import;
|
||||
- the `symbol()`, `decimals()` and `name()` lookup when a token is added by
|
||||
contract address;
|
||||
- the From address's balance each time ConfirmTx is shown;
|
||||
- the recipient checks on ConfirmTx: `eth_getCode`, `eth_getTransactionCount`
|
||||
and `eth_getBalance`;
|
||||
- the token's `decimals()` when ConfirmTx signs an ERC-20 send;
|
||||
- fee estimates, nonces, broadcasts and receipt lookups;
|
||||
- `eth_chainId`, when "Save" beside the RPC URL in Settings checks the URL;
|
||||
- the methods in `PROXY_METHODS`, for any page that asks.
|
||||
@@ -1536,8 +1573,8 @@ base-uri 'none'
|
||||
- `connect-src https: http:` admits any RPC endpoint, a local node over
|
||||
`http://127.0.0.1` included. What the wallet contacts is bounded by its code,
|
||||
not by this directive.
|
||||
- `frame-src 'none'`, `form-action 'none'` and `base-uri 'none'` are named
|
||||
because the last two do not fall back to `default-src`.
|
||||
- `form-action` and `base-uri` are named because neither falls back to
|
||||
`default-src`. `frame-src 'none'` is stricter than the fallback.
|
||||
|
||||
### Debug mode
|
||||
|
||||
@@ -1567,21 +1604,23 @@ balances and ENS names, and each token contract looked up.
|
||||
### Appearance
|
||||
|
||||
- Black text on a white background, or white on black in the dark theme. Colour
|
||||
marks errors, warnings, address dots and identicons.
|
||||
is used for errors, warnings, the red banner, address dots and identicons.
|
||||
- Every piece of information is text in the system monospace font. The
|
||||
identicons and the QR code on Receive are the only pictures.
|
||||
identicons and the QR code on Receive are the only pictures in the popup.
|
||||
- Every control looks like a control. Buttons have a border, padding and a hover
|
||||
state. Clickable text is underlined. There are no invisible hit targets.
|
||||
- Nothing moves when a result arrives. Every element filled in later reserves
|
||||
its space with `min-height` or a placeholder. `visibility: hidden` is
|
||||
state. Clickable text is underlined. A clickable row changes its background on
|
||||
hover. There are no invisible hit targets.
|
||||
- Every element filled in later reserves its space with `min-height` or a
|
||||
placeholder, so a result arriving later moves nothing. `visibility: hidden` is
|
||||
preferred over `display: none` where the space must stay. An empty USD value
|
||||
is written as ` `.
|
||||
- The popup is 396 pixels wide (`body` in `src/popup/styles/main.css`) and up to
|
||||
600 pixels tall, the most a toolbar popup gets.
|
||||
- Styling is Tailwind utility classes in the markup. `main.css` adds four
|
||||
classes of its own: `.copy-flash-active` and `.copy-flash-fade` for the copy
|
||||
feedback, `.am-address` for the rule that an address never wraps, and
|
||||
`.am-byte-order` for the signature screen's message.
|
||||
classes of its own:
|
||||
- `.copy-flash-active` and `.copy-flash-fade`, the copy feedback;
|
||||
- `.am-address`, the rule that an address never wraps;
|
||||
- `.am-byte-order`, the byte-order layout of the signature screen's message.
|
||||
- No framework. The popup is plain JavaScript with one module per screen or
|
||||
group of screens.
|
||||
|
||||
@@ -1595,15 +1634,15 @@ balances and ENS names, and each token contract looked up.
|
||||
|
||||
## Development
|
||||
|
||||
### Entry points
|
||||
### Entrypoints
|
||||
|
||||
The repository follows
|
||||
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all).
|
||||
The `Makefile` targets are thin shims over `script/`:
|
||||
|
||||
- `script/bootstrap`: install the dependencies. Node and yarn come from the
|
||||
system or, failing that, from a pinned nvm install. Fails when node cannot
|
||||
find a package named in `package.json`.
|
||||
- `script/bootstrap`: install the dependencies. Node comes from the system or,
|
||||
failing that, from a pinned nvm install; yarn comes from corepack. Fails when
|
||||
node cannot find a package named in `package.json`.
|
||||
- `script/setup`: `script/bootstrap`, then the git pre-commit hook.
|
||||
- `script/test`: build the `test` stage of the `Dockerfile` with `--no-cache`.
|
||||
The stage runs the jest suite, stopped at 90 seconds and rerun verbose on
|
||||
@@ -1625,8 +1664,9 @@ The `Makefile` targets are thin shims over `script/`:
|
||||
- `script/projectname`: prints `autistmask`.
|
||||
- `script/package`: `make build`, then the release archives (see Release
|
||||
archives).
|
||||
- `script/check-censored`: fail when the other wallet's name appears anywhere
|
||||
but its allowed places. See Policies.
|
||||
- `script/check-censored`: one competing wallet's name is barred from code and
|
||||
documentation; fail when it appears anywhere but its allowed places (see
|
||||
Policies).
|
||||
- `script/vendor-blocklist`: refresh `src/shared/phishingBlocklist.json` from
|
||||
its upstream, pinned to a commit and to the sha256 of the fetched bytes.
|
||||
- `script/verify-build --expect release|debug --receipt PATH`: check `dist/`
|
||||
@@ -1675,6 +1715,7 @@ It copies into `dist/chrome/` and `dist/firefox/`:
|
||||
It compiles into the bundles:
|
||||
|
||||
- the version;
|
||||
- the license and the author;
|
||||
- the commit hash, marked `-dirty` when the working tree is modified;
|
||||
- the build date;
|
||||
- `DEBUG`.
|
||||
@@ -1729,17 +1770,20 @@ under a tag of its own, and removes the image afterwards. Neither is part of
|
||||
`make check`. Run them after any change under `src/popup/views/`, before
|
||||
committing.
|
||||
|
||||
Four rules hold for both suites:
|
||||
Two rules hold for both suites:
|
||||
|
||||
- Nothing under `tests/e2e/` is named `*.test.js`, so jest never picks the
|
||||
suites up.
|
||||
- Both suites share the test page and stub node in `tests/e2e/dapp.js` and the
|
||||
fixtures in `tests/e2e/network.js`; the drivers are separate.
|
||||
|
||||
Two more hold for the Chrome suite:
|
||||
|
||||
- A test that provokes a `console.error` on purpose declares it with
|
||||
`errors.expect()` (`tests/e2e/harness.js`). An undeclared error fails the run,
|
||||
and so does a declared one that never comes.
|
||||
- `playwright-core` in `package.json` stays at the version of the container
|
||||
image in `tests/e2e/Dockerfile`.
|
||||
- Both suites share the test page and stub node in `tests/e2e/dapp.js` and the
|
||||
fixtures in `tests/e2e/network.js`; the drivers are separate.
|
||||
|
||||
`make test-e2e` runs three programs in a pinned Playwright container:
|
||||
|
||||
@@ -1749,13 +1793,17 @@ Four rules hold for both suites:
|
||||
uncaught page error or `console.error`. It covers:
|
||||
- WebAssembly compiling in the real popup under the shipped policy;
|
||||
- the Welcome settings, and what reaches Blockscout and Etherscan;
|
||||
- wallet creation, Add Token and TransactionDetail;
|
||||
- wallet creation, AddToken and TransactionDetail;
|
||||
- the recovery phrase and private key screens;
|
||||
- address removal and Settings;
|
||||
- ConfirmTx's fee and balance checks, and the wallet's own ERC-20 send;
|
||||
- the receipt wait and StateRecovery;
|
||||
- the site round trips: connect, `personal_sign`, `eth_signTypedData_v4`,
|
||||
`eth_sendTransaction` and `wallet_switchEthereumChain`.
|
||||
- the site round trips:
|
||||
- connect;
|
||||
- `personal_sign`;
|
||||
- `eth_signTypedData_v4`;
|
||||
- `eth_sendTransaction`;
|
||||
- `wallet_switchEthereumChain`.
|
||||
- `tests/e2e/storagePartition.js` loads the extension from two directories into
|
||||
one profile, with and without the manifest `key`. With the key, both loads get
|
||||
the pinned extension id and read the same storage. Without it, the second load
|
||||
@@ -1769,10 +1817,14 @@ Four rules hold for both suites:
|
||||
geckodriver. The container has no network. The loopback server in
|
||||
`tests/e2e/dapp.js` serves the test page and a stub node.
|
||||
|
||||
- `tests/e2e/firefox/run.js` installs `dist/firefox/` as a temporary add-on. It
|
||||
covers popup load, StateRecovery, wallet creation, Add Token and the site
|
||||
round trips. Errors are read from Firefox's console service at each step
|
||||
boundary. Any uncaught error from an extension source fails the run.
|
||||
- `tests/e2e/firefox/run.js` installs `dist/firefox/` as a temporary add-on.
|
||||
Errors are read from Firefox's console service at each step boundary. Any
|
||||
uncaught error from an extension source fails the run. It covers:
|
||||
- popup load;
|
||||
- StateRecovery;
|
||||
- wallet creation;
|
||||
- AddToken;
|
||||
- the site round trips.
|
||||
- `tests/e2e/firefox/reinstall.js` installs the packaged `.xpi`, creates a
|
||||
wallet, restarts the browser and adds the add-on again. It decrypts the stored
|
||||
secret through the real ShowRecoveryPhrase screen. It then uninstalls and
|
||||
@@ -1784,9 +1836,15 @@ from the `check` workflow. `e2e-chrome` has a 40-minute cap and `e2e-firefox` a
|
||||
`.gitea/workflows/check.yml` is a copy of the file in the `sneak/prompts`
|
||||
repository and is not edited here.
|
||||
|
||||
## TODO
|
||||
|
||||
Planned work is on
|
||||
[the issue tracker](https://git.eeqj.de/sneak/AutistMask/issues). `TODO.md`
|
||||
holds the workflow, the status and the next step.
|
||||
|
||||
## Policies
|
||||
|
||||
- The other wallet is not named in code or documentation.
|
||||
- One competing wallet's name is barred from code and documentation.
|
||||
`script/check-censored` fails the lint stage and the build when the name
|
||||
appears outside its allowed places:
|
||||
- the two provider flags in `src/content/inpage.js`. Many sites check them
|
||||
|
||||
Reference in New Issue
Block a user