Commit Graph
602 Commits
Author SHA1 Message Date
sneak de22b4edb0 docs: code comments name the headings README has now (closes #724)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
The README rewrite renamed or merged several headings that comments still
cited. Each comment now names the current heading.

The e2e workflow's citations of "In CI" are dropped, because no section has what
they pointed at.

The comment on withLock() no longer states a Firefox private window exception,
because the manifest keeps the extension out of those windows.

Two comments also take corrections from reviews: the cases with no total in
DeleteAddress's warning, and the screens that say a swap's amount could not be
decoded.

Model: opus-5-5
2026-11-03 12:11:36 +00:00
clawbot a65e84c2dd docs: the sentences the rewrite reviews left as follow-up notes (closes #723)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Each sentence named on #723 now
matches the code on `next`:

- the Firefox load steps are numbered;
- the AddToken refusal lists name a token that fakes a known symbol;
- the worker's in-memory state is listed in full;
- `script/bootstrap` falls back to `npm install -g` for yarn;
- the Send line under a `null` ETH balance holds with ETH selected, and
  "Max" has a line of its own;
- the Home and Send lines there name `SepoliaETH` on Sepolia;
- the well-known symbols are given per network;
- a network switch empties the fraud contract list;
- the cases where an import leaves out a removed address are spelled out;
- a new token's line depends on "Show tracked tokens with zero balance";
- wallet drainer is defined at first use only.

Model: fable-5-1
2026-11-03 13:06:17 +01:00
clawbot 64ec571a17 fix: long symbols wrap on TxApproval and TransactionDetail, and SuccessTx keeps its amount and recipient (closes #743)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
TxApproval and TransactionDetail cut off a long symbol, amount or description at
the edge of the screen. These lines now wrap.

SuccessTx hid its Amount and To lines whenever it had a decoded action, even one
that showed neither. Each line is now hidden only when a readable decoded line
shows the same thing. A swap with no Amount line now shows its amount on
SuccessTx, as WaitTx and ErrorTx do.

Model: opus-5-5
2026-11-03 12:27:20 +01:00
clawbot 1d40e2d7d5 fix: a saved SuccessTx in another shape reopens as itself, and long amounts wrap (closes #740)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
The popup refused a saved SuccessTx whose decoded record was in a shape it
did not expect, and showed Home. SuccessTx already shows only the lines it
can read, so the popup no longer checks the record first.

A long amount or token symbol was cut off at the edge of the screen. These
now wrap:

- the Amount figure
- each decoded amount
- the token symbol
- the name and description of SuccessTx's decoded action

WaitTx and ErrorTx share the line that shows the symbol, so they gain this
too.

Model: opus-5-5
2026-11-03 11:38:35 +01:00
clawbot 9c691dfa6b fix: the ETH line reads unknown at an address no refresh has read (closes #736)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
An address's ETH balance is now null until a refresh has read it. That covers
a new address, a new wallet, addresses a wallet scan finds, and every address
after a network switch.

Its line reads `quantity unknown`, Home's balance `unknown (ETH)`, and Send
`Current balance: unknown (ETH)`. Max says the balance is unknown. Send is no
longer refused as zero. The address has no total, and DeleteAddress warns that
it may hold a balance.

A refresh also deletes `balanceNotFetched` only when it read every address in
the stored record.

Model: opus-5-5
2026-11-03 11:24:18 +01:00
clawbot 448afdb5ce fix: a saved wait in another shape reaches SuccessTx when its receipt arrives (closes #734)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A saved wait whose decoded record is in another shape threw when its
receipt arrived. WaitTx then stayed on screen with the counter stopped.
decodedDetailsHtml() now shows only the lines whose label and value are
text. SuccessTx shows the amount and recipient when no line can be read.

WaitTx and ErrorTx now show each allowance's Allowance token line. Long
amounts use break-words, so words stay whole. ErrorTx sets up copying
when it has no hash, so the token's address can be copied.

Model: opus-5-5
2026-11-03 10:14:05 +01:00
clawbot 49713e1cdb fix: Home's list drops the previous network's rows after a network switch (closes #718)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A network switch left the previous network's rows or failure message in Home's
list until the new network's answer landed. Home now replaces them with
"Loading..." when it first draws on a new network. A redraw on the same network
keeps its rows.

Home, AddressDetail and AddressToken compared the page's network before reading
storage. A switch made in Settings could change the page during that read, and
the answer was still drawn. They now compare after the read, for an answer and
for a failure.

Model: opus-5-5
2026-11-03 09:54:35 +01:00
clawbot 1ea0730a81 fix: the wait and error screens show a swap's Permit2 allowance amounts (closes #733)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A swap can give another spender an allowance that its Amount figure leaves
out, and these two screens did not show it. Both now show each Permit2
allowance amount under the figure, with the Moved from the sender amounts.
movedFromSenderHtml() is now movedOrAllowedHtml(), as it shows both.

An amount too long for one line now wraps on these screens, rather than losing
its last digits at the screen's edge.

Model: opus-5-5
2026-11-03 09:14:23 +01:00
clawbot 4531e8bce5 fix: a tracked token reads quantity unknown at an address no refresh has read (closes #720)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A new address, a new wallet and a network switch each leave tracked tokens
with no balance entry, so their lines read 0.0000 before any refresh had read
them.

Each of these now sets `balanceNotFetched` on the tracked tokens, and a refresh
already clears it. Their lines read `quantity unknown` until then. Addresses
that the wallet scan finds get the same. A refresh that did not read every
address the page now holds leaves the field set.

Model: opus-5-5
2026-11-03 08:39:40 +01:00
clawbot f79390cad5 fix: the wait and error screens show a swap's Moved from the sender amounts (closes #722)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A swap's Amount figure can leave out what its Moved from the sender lines
take, so these screens could read as if less left the wallet than can have
left. Both now show each of those amounts under the figure, using the decoded
details they already receive. The error screen saves those details too, so a
reopened popup keeps the lines. A saved record in another shape shows only the
lines it can read.

Model: opus-5-5
2026-11-03 08:12:41 +01:00
clawbot 21d5e42528 fix: a double click on a Top tokens button tracks the token once (closes #729)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A "Top tokens:" button had no already-tracked check and stays enabled until its
save ends, so a fast double click tracked the token twice in memory. Its handler
now checks first. A second click shows "Already tracked." and tracks nothing.
The top 100 dropdown already has this check, so it is unchanged.

Model: opus-5-5
2026-11-03 07:37:04 +01:00
clawbot ba61bedaaf fix: a chain switch gives trackedTokens its own copy of the network's list (closes #719)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
After a switch, `trackedTokens` and that network's list in
`networkTrackedTokens` were one array. So a page's next add or removal also
changed `networkTrackedTokens`, and the save wrote that page's older copy over
the stored one. Another page's add on the previous network was lost, and its
removal was undone.

`applyChainSwitchFields()` now copies the incoming network's list. An add or
removal on the active network changes only `trackedTokens`.

Model: opus-5-5
2026-11-03 07:10:33 +01:00
clawbot 42a5d94b49 fix: the swap decoder shows the ETH of a WRAP_ETH that does not set the input side (closes #721)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A later WRAP_ETH of a stated amount now counts as a take from the sender.
When it pays anyone but the router, it gets its own Moved from the sender
lines, with the recipient on Moved to. When it pays the router, it joins
the Amount line if Token In is ETH, and otherwise gets those lines too.
When the router may already hold ETH, the amount reads Up to.

A WRAP_ETH whose input this decoder cannot read gets a line saying the
amount could not be decoded.

A WRAP_ETH of CONTRACT_BALANCE states no amount and reads as before, so
Uniswap's own routes do not change.

Model: opus-5-5
2026-11-03 06:51:14 +01:00
clawbot 267b69382e fix: a second click on Add while the lookup waits tracks the token once (closes #727)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
The "already tracked" check ran only before the contract lookup, so a second click while the first lookup waited tracked the token twice. AddToken and SettingsAddToken now check again when the lookup answers. An answer for a token tracked meanwhile shows the "already tracked" flash message and tracks nothing.

Model: opus-5-5
2026-11-03 06:24:14 +01:00
clawbot 1a4fb0803d fix: a save merges this page's tracked token change into the stored list (closes #717)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A save wrote `trackedTokens` whole, so two pages on one network dropped each
other's adds and brought back each other's removals.

A save that keeps the network now merges this page's change into the stored
list by contract address. A save that switches networks is unchanged.

`mergeTrackedTokens()` does that merge, and the two other merges of tracked
tokens now call it. It keeps one record per contract address, this page's for
a token both lists hold, so a token held twice no longer multiplies.

Model: opus-5-5
2026-11-03 05:59:42 +01:00
clawbot 076726b13d docs: rewrite README.md sentence by sentence against the prose rules (closes #672)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Rewrites README.md from scratch for
#672: what the program is, how
to use it, every setting, the design, then development and tests. Every
statement was checked against the code on next. Where the old text and
the code disagreed, the code decides; the PR body lists each
disagreement and judgement call.

Model: fable-5-1
Co-authored-by: clawbot <clawbot@noreply.example.org>
2026-11-03 04:49:03 +01:00
clawbot c90efa988b docs: rewrite the user guide sentence by sentence against the prose rules
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Rewrites docs/README.md from scratch for
#672. Every statement was
checked against the code on next. The two false statements of the old
guide are gone: history rows show the other party's address in full
(the only shortened address is the label of a token with no known
symbol), and the balance list hides a token that claims ETH from the
wrong contract. Each technical word is defined in a short clause where
it first appears: block, receipt, network fee, gas, swap, token
approval, Permit, Permit2, Uniswap, contract, origin, host name, port,
nonce, hash, node.

Model: fable-5-1
2026-11-03 04:08:10 +01:00
clawbot 754cf9686f fix: the bundled token list names tokens on Ethereum Mainnet only (closes #632)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
bundledToken(address, chainId) in tokenList.js answers only for Ethereum
Mainnet's chain id. Every reader of TOKEN_BY_ADDRESS now goes through it,
with the chain id of the transaction, balance or history entry it draws.
The token sources the screens build carry that chain id. The Uniswap
decoder sets the transaction's chain id on them. fetchTokenBalances()
takes the chain id of the network it asks about.

isSpoofedSymbol() takes the chain id of the token's network. It checks the
bundled list's symbols only on Ethereum Mainnet. The native asset's labels
stay reserved on every network.

Twenty existing tests and four shared test helpers read the bundled
list without naming a network. Each now names Ethereum Mainnet.

Model: opus-5-5
2026-11-03 03:41:15 +01:00
clawbot 430ea0166e docs: rewrite docs/RELEASE.md sentence by sentence against the prose rules
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Rewrite docs/RELEASE.md from scratch for
#672: a terms list, what is
needed, and six numbered steps, each with its check. Every statement is
checked against the Makefile, script/, build.js, the two workflows and the
tests. The step that described distribution routes not built is cut. The
reproducibility claim names the build date that build.js compiles in, so it
holds only within one UTC day.

The commit carries the findings of the three reviews, the last two in the
third review's wording: the self-contained check is described with the
browser's directory as its subject, and Node and yarn must be on the PATH,
because script/bootstrap leaves an nvm install off it.

Model: fable-5-1
2026-11-03 03:40:28 +01:00
clawbot ae0b86a8ac fix: the swap decoder names where a WRAP_ETH pays and shows a V4 step's ETH as a maximum when the router may hold ETH (closes #665)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A `WRAP_ETH` that sets the input side and pays its WETH to anyone but
the router names that recipient on its `Moved to` line.

V4 pays a `SETTLE` of ETH from the router's own ETH, whichever payer it
names. When an earlier step may leave ETH in the router, the ETH that
the user pays a later V4 step gets lines of its own. Their
`Moved from the sender` line reads `Up to <amount>`, or
`Unknown (could not be decoded)` when the amount is not known. The
decoder never subtracts the router's ETH from that amount. Without such
an earlier step, the lines read as before.

Model: opus-5-5
2026-11-03 03:02:10 +01:00
clawbot d89099d90a fix: the address screen shows a token just added at its fetched balance, not 0.0000 (closes #516)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A balance refresh that returns now draws the balances on AddressDetail or
AddressToken again when that screen is up, not only the wallet list. Their
transaction lists are left alone.

Every add path on AddToken and SettingsAddToken tracks a token through
trackToken(), which gives the tracked record `balanceNotFetched: true`. While
the field is set, the token's line reads `quantity unknown` instead of 0.0000,
and Send reads its balance as unknown. refreshBalances() now resolves with the
tracked tokens whose balance it read at every address. The popup's refresh
deletes the field from those tokens in the stored record and leaves the rest of
the stored list as it is. Removing the token removes the field, and each network
keeps its own records.

Model: opus-5-5
2026-11-03 02:25:25 +01:00
clawbot 664629a1b6 fix: a split swap's Min. received is the sum of its steps' minimums (closes #647)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
The step that sets the output side gives the minimum. When that step
and earlier swap steps each pay the output token to the sender, the
minimum is now the sum of their minimums. There is no figure when the
decoder reads none from one of them, or when one of them pays part of
that token elsewhere.

These steps drop earlier steps from the sum:

- a V2 or V3 swap step that spends the output token;
- a V4 step with a swap action that spends that token, or with a SETTLE
  or SETTLE_ALL of that token;
- a PERMIT2_TRANSFER_FROM of that token.

A step after the step that sets the output side drops nothing from the
sum.

Model: opus-5-5
2026-11-03 00:21:40 +01:00
clawbot 26a2a51387 fix: two pages switching networks no longer lose tracked tokens (closes #701)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
A page that had not yet taken another page's network switch could lose
tracked tokens.

- Its save wrote its network's list as the new network's list. saveState()
  now keeps that list and merges the change into its own network's list in
  networkTrackedTokens.
- Its own switch wrote its old per-network lists over the stored ones.
  onChainSwitch() now first takes the stored switch with takeStoredNetwork().
- takeStoredNetwork() dropped the page's unsaved change. It now keeps it in
  the list of the page's network. This also fixes
  #706.
- A page already on the stored network now takes the stored
  networkTrackedTokens before it switches, because another page's save may
  have changed a list this page holds.

Model: opus-5-5
2026-11-03 00:04:20 +01:00
clawbot b5737f915c fix: a transaction history that lands after a network switch is dropped (closes #657)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Home, AddressDetail and AddressToken remember which network is active
before they ask Blockscout for the transaction history. Each screen drops
the answer if another network is active on the page or in storage when the
answer lands. AddressDetail and AddressToken also drop an answer that lands
once the screen shows another address. AddressToken also drops an answer
that lands once the screen shows another token.

A dropped answer draws no rows and saves no fraud contracts. A failed
request goes through the same checks. A dropped failure shows no message.
Holding the lock, the save adds new fraud contracts only if the page and
the stored record still name the request's network.

storedNetworkIs() reads the stored network, in src/shared/storedSettings.js.

Model: opus-5-5
2026-11-02 23:41:24 +01:00
clawbot 016acbcda5 fix: Settings ignores an endpoint check once the same "Save" is tapped again (closes #698)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Each RPC and Blockscout "Save" in Settings now counts its taps. A check
that answers after a newer tap of the same "Save" stores nothing and
leaves the flash message alone. Before this change, the older check's
error or refusal replaced the newer tap's "Saved.".

The save also checks for a newer tap at two points. A tap made while the
save waits for the lock means nothing is stored. A tap made during the
write means no flash message is shown.

Model: opus-5-5
2026-11-02 22:59:23 +01:00
clawbot 7ababcf69e fix: the balance list and the add-token screens apply the spoof rule to tracked tokens (closes #705)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A tracked token that the spoof rule refuses still got a zero row in the balance list while "Show tracked tokens with zero balance" was on. balanceLinesForAddress() now asks isSpoofedSymbol() before it adds that row. AddToken and SettingsAddToken refuse such a token after the contract lookup, with the flash "Not added: this token fakes a known symbol." The bundled-list buttons on SettingsAddToken need no check: the rule never refuses a bundled token. README.md and docs/README.md now say the balance list drops such a token whatever the settings.

Model: opus-5-5
2026-11-02 06:04:07 +01:00
clawbot 3191577f73 test: make test fails when jest force-stops a worker (closes #711)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
When a test left a timer running, jest force-stopped the worker that ran the test and printed "A worker process has failed to exit gracefully", but the run still passed. Both test scripts in package.json now run jest through script/lib/jest.js. The helper runs jest inside its own process, so the terminal output is unchanged, and it exits 1 when jest writes that warning to stderr. Jest 30 has no option that fails the run on it. The eslint.config.js comment on script/lib/ now says those files run on plain node and are never bundled.

Model: opus-5-5
2026-11-02 01:44:22 +01:00
clawbot acb2577fec test: the test suite exits on its own, without --forceExit (closes #585)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Some tests left timers running when they ended, and --forceExit hid them; both test scripts drop it. Six background test files left the background's 20-second timer running while an approval was pending; each now stubs it for the whole file. Five popup test files left a flash message's two-second timer running; they now use fake timers, and a wait on real zero-delay timeouts became jest.advanceTimersByTimeAsync(0). Two ethers timers can still run for up to 250 ms after a test ends; they stop before jest checks for open handles.

Model: opus-5-5
2026-10-28 01:09:12 +01:00
clawbot a33a40a6fa build: say beside the install why yarn prints the workspaces warning (closes #595)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Yarn 1 prints "Workspaces can only be enabled in private projects." for each dependency whose package.json has a workspaces field without "private": true. Two do: eslint 10.8.1, and babel-plugin-istanbul 7.0.1, which jest pulls in. No update removes the field, and removing the warning would mean downgrading both below what this repo and jest require. A one-line comment beside the install in script/bootstrap and in the Dockerfile now names both packages and says why the warning stays; every Dockerfile install runs script/bootstrap, so one comment there is enough.

Model: opus-5-5
2026-10-28 00:28:27 +01:00
clawbot 5192419cac docs: README matches ConfirmTx's wrong-password message and fee-bound refusal (closes #610)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
README's ConfirmTx section quoted "Wrong password." for a wrong password; the screen says "That password is incorrect. Please try again.", and the README now quotes that. The other password screens describe their error without quoting it, and DeleteWallet already quoted it right. The fee-bound refusal no longer says the RPC endpoint always fills in the gas limit and fees at signing: for an ETH amount that Max filled in, they come from the screen's own fee estimate. The transition names `assertWithinCeilings()` and lists what it checks.

Model: opus-5-5
2026-10-28 00:05:20 +01:00
clawbot 41842b197e fix: a token lookup that answers after the user left AddToken no longer changes the screen (closes #603)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
When the contract lookup on AddToken answered, the popup went to AddressDetail even after the user had opened another screen. It now goes there only while AddToken shows and has not been opened again since Add was pressed; AddToken counts its openings as Send does. The token is still added as before unless the network changed. An answer, found or failed, from an earlier opening leaves the screen and the status line alone, so a later lookup's "Looking up token..." stays.

Judgement call: a user who went Back to AddressDetail during the lookup sees the new token once that screen is drawn again.

Model: opus-5-5
2026-10-27 23:16:10 +01:00
clawbot 8998d6c661 fix: a refresh asked for while another runs is no longer dropped (closes #581)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
doRefreshAndRender() returned at once when a refresh was already running. An import asks for a refresh after its address scan, and that request was dropped when it came during a refresh, so the addresses the scan found showed 0.0000 until the next ten-second refresh. A request made through ctx while a refresh runs now leads to one more refresh once the running one ends, however many such requests came in. A tick of the ten-second timer during a refresh is still dropped, so the wallet asks the node no more often than before.

Model: opus-5-5
2026-10-27 20:14:09 +01:00
clawbot 08e47c39ad fix: a network switch in Settings keeps another page's token on the network it was added on (closes #692)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A network switch in Settings filed under the new network a token or fraud contract that another page stored since this page's last save, because the switch's save writes only the fields this page changed. Before the switch, onChainSwitch() now takes the stored tracked tokens into the page's own list with takeStoredTrackedTokens(), matched by contract address, so a token either page added or removed stays as that page left it. The switch then files that list under the previous network. When the stored record is on another network, no tokens are taken. Fraud contracts are cleared on every switch, as before.

Model: opus-5-5
2026-10-27 18:05:01 +01:00
clawbot 7ba0a5ff75 fix: TransactionDetail drops a Blockscout answer for another transaction (closes #675)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
TransactionDetail asks Blockscout for its transaction without waiting for the answer. If the user pressed Back and opened another transaction before Blockscout answered, the second screen showed the first transaction's block, network details, decoded details and raw data. loadFullTxDetails() now drops the answer once TransactionDetail shows another transaction; the same hash on another network counts as another transaction. An answer that lands while Settings is up is still drawn. Every failed request is still logged.

Model: opus-5-5
2026-10-27 15:30:40 +01:00
clawbot cd5951a4f8 fix: Settings never shows "Saved." for a URL the input no longer shows (closes #695)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
The RPC and Blockscout "Save" buttons in Settings now store nothing when the input no longer shows the URL that was checked. When another page changes the network, "Use Blockscout" or "Check recipients on Etherscan", this page draws Settings again, and a redraw during the check puts this page's URL back in the input. Before this change, the typed URL was then stored and "Saved." appeared. A save refused because the input changed shows "The URL was not saved because it was changed during the check." A user's own edit during the check refuses the save too.

Model: opus-5-5
2026-10-27 14:34:50 +01:00
clawbot bcdffa56a4 fix: Settings stores the URL on screen when another page stored a different one (closes #688)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
The RPC and Blockscout "Save" buttons in Settings now set the URL in the stored record, inside the save. Before this change, the save wrote only fields that differed from what the page last saved. If another page stored a different URL for the same network, a "Save" of the URL this page loaded left the other page's URL stored, and the flash still read "Saved.". The save still refuses a URL when the active network is no longer the one Settings showed.

Model: opus-5-5
2026-10-27 12:36:48 +01:00
clawbot c0a3a02418 fix: a network switch in Settings leaves no balance from the previous network stored (closes #653)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A network switch in Settings could leave the previous network's balance in the stored record. The switch clears the page's balances inside its save, but the save writes only fields the page changed since its last save. When the page had last saved "0" for an address, the cleared "0" was no change, so a balance the background's refresh stored meanwhile stayed under the new network. The switch's save now always writes the cleared balances and the time of the last balance refresh. Every other field merges as before.

Model: opus-5-5
2026-10-27 10:14:06 +01:00
clawbot f550d8c8d2 fix: a zero-minimum balance check never sets the output side (closes #649)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A BALANCE_CHECK_ERC20 of the sender with a zero minimum, or one the router lets fail, no longer sets Token Out or the minimum. Before, it set both whenever the output side held no minimum, so after an UNWRAP_WETH that drops the minimum, a zero check of USDC named USDC as Token Out, a token the swap did not pay. A check with a positive minimum, not allowed to fail, sets the output side as before. Two existing tests that expected the wrong token are corrected, and README states the rule.

Model: opus-5-5
2026-10-27 08:57:59 +01:00
clawbot fc6cffcaba fix: a Permit2 transfer of the zero address never reads as ETH (closes #685)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A PERMIT2_TRANSFER_FROM of the zero address read Token moved: ETH, with an ETH figure, though Permit2 moves no ETH. Such a move now names the zero address as its token on Token moved and Token moved into the router, and gives its amount in base units on Moved from the sender and Paid to. The zero-address check from the permit lines is now one function, permit2TokenInfo(), shared by the move lines. A V4 step of ETH that states no amount still gets its own lines beside such a move, so no line about ETH leaving is dropped.

Model: opus-5-5
2026-10-27 07:53:05 +01:00
clawbot 5615b08760 fix: Settings refuses an endpoint URL whose network changed before it was stored (closes #663)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
The RPC and Blockscout "Save" buttons in Settings now store a URL only for the network that Settings showed when "Save" was tapped. The URL is set inside the save, under the lock, so the popup cannot follow a network switch saved elsewhere between setting it and writing it. If that network is no longer active on the page or in the stored record, the save is refused and the flash reads "The URL was not saved because the network changed." "Saved." appears only for a stored URL. The RPC check compares the node's chain id with the network shown at the tap.

Model: opus-5-5
2026-10-27 07:27:15 +01:00
clawbot ec6b6b57a3 fix: a V4 SETTLE of ETH paid from the router reads as moved from the sender (closes #682)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
V4Router pays a SETTLE of ETH from the router's own ETH, whichever payer it names, and the router holds the transaction's value. A V4 SETTLE of ETH that names the router as payer now counts as ETH the user pays. With no ETH left in the router by an earlier step, it reads as a SETTLE the user pays. When an earlier step left ETH there, it gets lines of its own reading Up to and the amount. When the amount is not known, as for CONTRACT_BALANCE, its Moved from the sender line reads Unknown (could not be decoded). No line now shows less ETH than such a SETTLE can take.

Model: opus-5-5
2026-10-27 06:49:37 +01:00
clawbot 36b200247a fix: a permit on the zero address never reads as ETH (closes #660)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Permit2 has no allowance of ETH, but the swap decoder read the zero address in a PERMIT2_PERMIT or a batch entry as ETH. Its Allowance token line now names the zero address, as for a token nothing knows. Its amount never stands as the Amount figure, and it never counts as an allowance of Token In, so a route that pays ETH after such a permit shows that ETH. Tests cover the single permit, the batch entry and the 1-wei route.

Model: opus-5-5
2026-10-27 05:12:38 +01:00
clawbot b4e166cdc7 fix: read USD prices from Chainlink price feeds through the RPC endpoint (closes #525)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
CoinDesk now refuses requests without an API key, so mainnet showed no USD prices. Mainnet prices now come from Chainlink's USD price feeds, read with eth_call through the user's RPC endpoint; no other service is asked. The bundled list pairs each of 53 tokens with its feed by contract address, and ETH and WETH use ETH/USD. The popup reads the feeds of ETH and the tokens the user holds or tracks in one batched request, at most every 5 minutes. A reading older than its heartbeat plus 30 minutes, or not positive, is no price. A token with no feed shows no USD value. CoinDesk is gone.

RULES.md still names the CoinDesk price API.

Model: opus-5-5
2026-10-27 04:23:17 +01:00
clawbot 53551c6382 fix: the StateRecovery erase warning names every kind of wallet backup (closes #593)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
The StateRecovery erase warning told every user to rely on each wallet's recovery phrase. A wallet imported from a private key or an extended private key has none; its backup is that key. The warning now names all three, in the words the delete-wallet screens use, and README's StateRecovery entry says what a wallet can be added again from. A test reads the warning.

Model: opus-5-5
2026-10-27 03:46:17 +01:00
clawbot 33ab99b7be fix: closing a transaction or signature approval window leaves the request pending (closes #673)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Closing a transaction or signature approval window no longer rejects the request; only Cancel does. The browser can close that window when the user clicks away, for example to copy the password from a password manager. The request stays pending and the site gets no answer. Pressing the toolbar button opens the oldest such request, unless an approved attempt still holds it. A Reject the background refuses keeps the window open with the background's message. The worker points the toolbar back at the wallet when it starts.

While such a request waits, the transaction slot stays held, so another site's eth_sendTransaction gets -32002. An address switch still rejects pending approvals with 4001.

Model: opus-5-5
2026-10-27 00:56:36 +01:00
clawbot b58ecec1f9 fix: AutistMask does not work in Firefox private windows (closes #646)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Firefox gives an extension page in a private window locks of its own, so a popup there could save between the background's read and its write and undo a network switch the background saved. `manifest/firefox.json` now sets `"incognito": "not_allowed"`, so such a page cannot read or write extension storage, and `tests/manifest.test.js` pins the key. README and the user guide say AutistMask does not work in Firefox private windows. Chrome needs no change: in its default incognito mode an extension page shares the background's lock.

A Firefox user on "Never remember history" can no longer run AutistMask at all.

Model: opus-5-5
2026-10-26 23:51:22 +01:00
clawbot 387f40689e feat: an "Allow weak passwords" setting lets a new wallet have a short password (closes #674)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Settings has a new "Allow weak passwords" checkbox, off in a new profile. While it is off, AddWallet refuses a password shorter than 12 characters, as before. While it is on, AddWallet accepts any password that is not empty. Key derivation is unchanged: one Argon2id derivation at libsodium's interactive setting. README's Key Decisions now states those parameters and why one light derivation is enough: the password's length is what protects the stored secret.

The screens say "password", as README's wording rules require, so the setting is "Allow weak passwords".

Model: opus-5-5
2026-10-26 22:35:02 +01:00
clawbot bf8aa9f5dd fix: Blockscout and Etherscan lookups are off until the user turns them on (closes #668)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Out of the box the wallet sent the user's addresses to Blockscout and each recipient's address to Etherscan. Two settings, "Use Blockscout" and "Check recipients on Etherscan", now gate every request that sends the user's data to those services. Both start off and are offered unticked on Welcome and in Settings. Each request reads its setting from storage before it asks. An answer that lands after the setting went off is dropped. While a setting is off, the screens that rely on it say so. ENS lookups ask only the RPC endpoint, so a name resolved off-chain does not resolve.

RULES.md's External Communication item is now out of date. Its new wording will be proposed on #211 once this lands.

Model: opus-5-5 (implementation, summary); fable-5-1 (prose)
2026-10-26 21:38:29 +01:00
clawbot c316d9ee78 fix: tracked tokens' balances are read through the RPC endpoint (closes #669)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
refreshBalances() now reads the balance of every token tracked on the
active network, at every address, with balanceOf through the same
provider as the ETH balance. The entry takes its holder count and
decimals from Blockscout's entry for the token in the same refresh, or
keeps them from before while Blockscout fails. A failed balanceOf keeps
the token's previous entry, or takes Blockscout's entry when there is
none, and is logged. Blockscout's answer still adds the tokens the user
has not tracked, as before.

The browser test for a hostile symbol now untracks the stub token
first, because a tracked token is listed under the symbol it was added
with.

Model: opus-5-5
2026-10-21 14:16:26 +02:00
clawbot b9bb1569fd fix: a V4 step that spends some of its output currency shows no Min. received (closes #574)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A V4 step's Min. received was the sum of the minimums of the swap
actions that buy its output currency, even when another swap action in
the same step spends some of that currency. The user then receives
less than that figure. decodeV4Swap() now gives no minimum when a swap
action in the step also spends the output currency, as it already does
for other minimums it cannot state. A multi-hop action counts only the
currency it spends and the one it ends with, so a path through an
intermediate currency is not read as spending it.

Model: opus-5-5
2026-10-21 07:34:26 +02:00