fix: version stored state, validate its shape, and give a corrupt blob a way out (closes #311)
Stored state had no version and no structural validation, so a corrupt blob produced a completely blank popup with no message and no recovery control, and made every dApp RPC call from every page answer a generic -32603. There was no reset or wipe control anywhere in the UI. saveState() now stamps a schema version and loadState() validates the shape. A version it does not understand, or a wallets array it cannot parse, lands on a recovery screen that names the problem, offers the stored record verbatim for export, and offers a destructive reset behind a typed confirmation. Unversioned but valid state -- which every existing install has -- migrates in place and keeps working; it is never shown a wipe prompt. A dApp call against unusable state answers -32007, which EIP-1474 leaves unassigned, rather than -32603. networkById() refuses an unknown id loudly instead of returning mainnet, and networkId is validated so a corrupt value cannot be used as an object key. Fields the gate does not refuse are floored by type, container and entries both: a malformed trackedTokens or tokenBalances entry is dropped rather than dereferenced. Verified by an independent sweep of 1152 corrupt blobs producing no blank popup, with the same harness showing 9 blanks against the previous revision.
This commit was merged in pull request #360.
This commit is contained in:
@@ -1761,6 +1761,75 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ STATE RECOVERY ============ -->
|
||||
<!--
|
||||
Shown when the stored profile cannot be read at all. Every
|
||||
other screen renders from that profile, so this one is reached
|
||||
without one and is the only way out of a wallet that would
|
||||
otherwise be a blank popup.
|
||||
-->
|
||||
<div id="view-state-recovery" class="view hidden">
|
||||
<h2 class="font-bold mb-2">Saved Data Cannot Be Read</h2>
|
||||
<p class="text-xs mb-2">
|
||||
AutistMask stopped rather than guessing. Nothing has been
|
||||
changed or erased, and nothing can be signed or sent until
|
||||
this is resolved.
|
||||
</p>
|
||||
<div
|
||||
id="state-recovery-problem"
|
||||
class="text-xs font-bold mb-3 break-words"
|
||||
></div>
|
||||
<p class="text-xs mb-2">
|
||||
Export the saved data first and keep it. It may hold the
|
||||
encrypted keys for your wallets, and it is the only copy.
|
||||
</p>
|
||||
<button
|
||||
id="btn-state-recovery-export"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
Export Saved Data
|
||||
</button>
|
||||
<textarea
|
||||
id="state-recovery-blob"
|
||||
readonly
|
||||
class="hidden border border-border p-1 w-full h-32 font-mono text-xs bg-bg text-fg mt-2"
|
||||
></textarea>
|
||||
<p class="text-xs mt-3 mb-2">
|
||||
<strong
|
||||
>Erasing the saved data deletes every wallet stored in
|
||||
this browser.</strong
|
||||
>
|
||||
Nothing on the blockchain changes and no money is moved, but
|
||||
without the exported copy above, or the recovery phrase for
|
||||
each wallet written down, everything they hold is gone
|
||||
forever.
|
||||
</p>
|
||||
<p class="text-xs mb-1">
|
||||
To confirm, type
|
||||
<strong>ERASE MY WALLET</strong>
|
||||
below.
|
||||
</p>
|
||||
<div class="mb-2">
|
||||
<input
|
||||
type="text"
|
||||
id="state-recovery-reset-input"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="Type ERASE MY WALLET"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="state-recovery-flash"
|
||||
class="text-xs text-red-500 mb-2 min-h-[1.25rem]"
|
||||
style="visibility: hidden"
|
||||
></div>
|
||||
<button
|
||||
id="btn-state-recovery-reset"
|
||||
class="border border-border text-red-500 px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
Erase Saved Data
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="index.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user