Sending, site transactions, site signatures and private key export
derived the key at the address's position in the wallet's list. After
an import whose scan passed over an unused index, or after removing an
address that was not the last, that position named another address's
key.
Each HD and xprv address record now stores the index it was derived at
(at wallet creation, by the import scan, by "+"). getSignerForAddress()
derives at that index, refuses a record without one, and refuses any key
whose address differs from the record's. The confirmation screen signs
as the From address it shows, not the selected one. The export screen
reports a refusal instead of calling the password wrong.
Model: opus-5-5
The add wallet screen reported a missing, short or mismatched password in
the flash line at the top of the popup, and the private key export,
recovery phrase and delete wallet screens each wrote to a line of their own
above the password field. All four now use showError() and hideError() with
a fixed-height error line below the field, as the send confirmation and
approval screens do. On the add wallet screen the line sits beside the
Import button, which keeps its place at 360x600. The line clears when the
screen is shown again and when the password is tried again. Other add
wallet messages stay in the flash line.
Model: opus-5-5
Leaving the private key export or recovery phrase screen drops the
selection it was showing, but the settings gear had just pushed the
screen onto the Back stack, so Back from Settings landed on a password
prompt that could only fail. Each screen's leave handler now also takes
it off the top of the stack, which is what a reopened popup already does
to these screens. Back from Settings goes to the address screen for the
export screen; for the recovery phrase screen, opened from Settings, it
stays on Settings once, as after a reopen.
Jest tests drive the gear and then Back, and each screen's own Back, for
both screens; leavePrivkeyScreen() in the e2e suite expects the address
screen.
Model: opus-5-5
show() found the address line through the element inside it, then
replaced the line's contents with renderAddressHtml(), which deleted
that element, so the next show() in the same popup session threw
before it navigated. The line now carries the export-privkey-address
id itself and is looked up by it. No other view that renders an
address finds its container through a child.
The jest DOM stub now takes an element out of the document when its
parent's contents are replaced, and a new test opens the screen
twice. The #253 e2e case no longer reopens the popup before its
second open.
Model: opus-5-5
A rejected password was reported three different ways depending on which screen
you were on, including the fragment "Wrong password." which is not a sentence.
All six decryptWithPassword call sites now show the same full sentence.
Strings only -- a wrong password still fails closed on every screen and still
resolves no pending approval.
A test pins the invariant per call site: each decryptWithPassword call is walked
out to its enclosing try and forward to that block's catch, and the prose shown
there must equal the canonical sentence. Per-file matching was not enough, since
a file with two call sites kept passing while one of them diverged.