# Wallet and position reads — 14 September 2026

## Current scope

External-wallet connection and live Base position reads. No browser-generated wallet, private-key storage, signatures, approvals, deposits, borrow/repay, or exit sends are added. The strategy builder still saves local examples. Transaction integration is a separate change.

Entry points:

- `app.html?preview=wallet#portfolio` — external wallet, with Cattle-scoped reconnect preference.
- `app.html?preview=sample#portfolio` — two explicitly synthetic positions; no wallet or RPC reads.
- `app.html?preview=address&address=thetadeployer#portfolio` — live public reads of the operator’s two positions.
- Replace `thetadeployer` with a checksummed or lowercase Ethereum address. `watch=` is also accepted; `demo=1` is an alias for the operator address.

Preview targets live in the URL, never in wallet identity storage. Samples are not passed to the live reader. A fresh sample/address entry never loads the wallet bundle or reconnects a remembered wallet. An already connected wallet can remain connected while viewing a separate preview; the two identities are displayed separately, and no transaction surface exists.

## Wallet choices and state

The site carries its own copy of Gyro’s Web3Onboard bridge: injected wallets, WalletConnect, and Coinbase Wallet. Cattle’s initialization tail sets Cattle metadata, Base as WalletConnect’s required chain, the dapp URL, the mint theme, and disables automatic connection of prior wallets. Generic bridge address writes are removed. Only the wallet label is retained in `cattle.wallet.v1`.

The adapter owns reconnect and state changes. It listens to the selected provider, not a possibly different `window.ethereum`. Every account/network read clears the preceding identity, captures a revision, and rejects superseded results. Disconnect removes listeners and its reconnect preference. An unsupported network preserves the wallet connection and offers an explicit Base switch.

Wallet reads have deadlines. Interactive wallet selection has a cancellation path and a five-minute upper bound; no elapsed time is treated as consent. Public RPC accepts read methods only. No method for signing or sending a transaction is exposed by the Cattle adapter.

The inherited picker’s close div is made keyboard-accessible, the modal receives an accessible name, Tab cycles inside it, and Escape closes it. Vendor cryptographic code is unchanged. Ethers 5.7.2 is copied locally for ABI encoding/decoding; it is not a frontend framework.

References: [EIP-1193 account and network events](https://eips.ethereum.org/EIPS/eip-1193), [Web3Onboard core](https://web3onboard.thirdweb.com/docs/modules/core), [WalletConnect dapp URL and chain configuration](https://web3onboard.thirdweb.com/docs/wallets/walletconnect).

## Read-only trial coverage

Source: `../../thetaAaveCattle/docs/reports/base-short-trial-2026-09-12.md`, especially its September 14 update; `docs/FRONTEND_NOTES.md` section 5; and `docs/FRONTEND_CHECKLIST.md`.

- Chain: Base, 8453.
- Factory D: `0xc77fd615481ca88463ce324dd207ad70dfe7c00e`, deployment block 51,221,777.
- Implementation: `0xcae71867ce8a68fac56c9fe51459e68f24b15dd8`.
- Lens: `0xe55c37eed6d298080e5e3b4c1e2472af925091c0`.
- Operator: `0x4a4c7c5549359b9fff0137bb3ec4d48c4aa79cc7`.
- Short D: `0x9E36DE6741b81a428EE6d76D12b5dFF32465Ce77`.
- Long E: `0x7BBf122149fA2D8727325e3f8f05C6E79C010D58`.

These are trial records, not a frozen production release. The current factory only is covered; older retired factories are not silently counted as empty or integrated as new creates.

Discovery reads the known factory’s `DeploymentResolved` logs in bounded chunks, decodes the 889-byte clone, filters its immutable owner, checks event metadata and implementation, verifies the creation receipt, recovers the creation salt, and confirms `predict(owner, salt)`. Direct and nested ABI create calls are supported; a salt that cannot be recovered leaves the read incomplete. Clone shape alone never authenticates a position.

Pair reads use the same block number, with its hash rechecked after the scan. Balances, Aave account values and order previews come from the lens. Aave values are USD with eight decimals, as documented by the backend Aave interface. Token units come from clone metadata; symbols are read from the underlying. Strike is quote per base at 1e18, not assumed USD per base.

`aaveOk == false` makes account figures unavailable. `previewOk == false` means failed preview, not zero orders. Post-outflow health is displayed only for an available preview with Aave data; incoming proceeds are not included. A debt-free account is labeled “No debt”. `closed` is not treated as empty. Collateral less debt is not an exit quote; exit fees are excluded.

Discovery compares complete log results from BlockPI and bloXroute. Each contributing endpoint checks the shared snapshot hash before and after its log request. PublicNode is excluded from logs after a 403; Tenderly is a call fallback because its log range limit is smaller. The configured log range is 5,000 blocks. Known D/E creation events guard against silent omissions. A refresh discards the old snapshot immediately; source changes abort and invalidate requests. A 45-second read deadline leaves a visible retry state. Partial reads never advance a browser discovery cache.

The dedicated Cloudflare D1 index stores certified deployment events only. The browser checks the indexed hash and scans every block from `indexedBlock + 1` through its current read block, then reads all lens/account values at that current block. Stale, warming, failed or mismatched indexes trigger full discovery from factory deployment. `index=0` forces this path. See [indexer/README.md](indexer/README.md) for the cron, atomic SQL checkpoints, shared RPC anchors and reorg recovery.

## Evidence and limits

- Live browser lookup verified both D and E without a wallet, including factory prediction and lens reads. Desktop capture: Base block 51,290,480; mobile capture: 51,290,526. Both are actual snapshots from direct fallback while the new cron warmed up.
- 60 native Node tests cover input handling, wallet identity changes and races, cancellation, timeouts, storage denial, wrong chain, reconnect options, URL mode separation, RPC restrictions, shared provider anchors, code/event attestation, fixed borrowing examples and actual SQL/Worker/index-consumer scenarios. Independent review cleared the final fixes.
- An injected EIP-1193 test provider at `0x1111…1111` verified actual picker connection, change to `0x2222…2222`, unsupported-chain retention, explicit Base switching, and silent reload restoration. Its code has no key or signing implementation and is never loaded by the app.
- A fresh sample URL with the remembered fixture wallet made zero wallet requests and loaded no wallet bundle. Rechecked on final JS v12: zero RPC/index fetches, no connected identity, two explicitly synthetic positions. No fixture balance is labeled live.
- Fault-injected RPC failure leaves no totals or preceding snapshot and provides Retry. Warming-index HTTP 503 also recovered to direct reads in the real browser; that expected resource error was the only error observed in those final captures.
- After cron caught up, the browser used checkpoint 51,290,649, directly scanned 51,290,650–51,290,672 on both log providers, and read both lens accounts at 51,290,672. No console errors were observed.
- A fixed-block comparison at Base 51,290,704 returned byte-for-byte equal position objects for indexed discovery and full discovery; both found two verified positions with no incomplete reads. One unthrottled measurement was 7.6 seconds versus 8.5 seconds; this is a single observation, not a latency guarantee.
- WalletConnect selection loaded its modal without console errors. No physical wallet pairing, signature or transaction was performed. Hardware-wallet-specific UX remains an operator check.
- A new public release, new factories, live creation, debt operations and exit transactions remain outside this change.

## Bundle provenance

Gyro source SHA-256 `d40316bc44555c2176cd9b8b31df5403340b0face39c6cbb9ba6105a6e32942b`; Cattle artifact SHA-256 `0c01d1ce956da9ca93b7209e452ce097ec1a61ebdaf02eb0aa044f5f41156d00`. Reproduce with `python3 cattle/tools/sync-wallet-bridge.py`; the script refuses a changed source digest.

## Queued product-language and visual guidance

The user clarified that long is generally bullish, while short is commonly a range/yield intent. The short strategy targets a spread intended to cover option premium; the long does not have that spread target. Neither is an exact payoff replica. The perpetuals-versus-dated-futures comparison is a conceptual framing, not a claim that these dated Cattle positions have no expiry. This guidance is recorded for a later copy iteration; the wallet change preserves the approved visual direction.

The user also preferred the moonlit-pasture concept and suggested a cute night toggle. This is queued for the next theme pass, at the user’s stated “no rush” priority. Journal entries 07–09 preserve the sequence.
