kira-wallet 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,15 +43,16 @@ For a viewer without wallet or research actions, use `kira start --read-only`.
43
43
  Prefer an archive? [GitHub releases](https://github.com/realproject7/kira-wallet/releases/tag/v0.1.2)
44
44
  include the same package and its checksum.
45
45
 
46
- 1. **Review optional coverage.** Free research is enabled by default. In **Workspace settings**, connect Alchemy for broader
47
- ERC20 discovery. Free token sources have limited coverage; incomplete coverage
48
- stays visible. An AI or browser wallet connection does not enable an indexer.
49
- 2. **Add a watching wallet.** Paste a public address and give it a name. Add more
50
- wallets whenever you need them. The form starts free research of native, common tokens and Mint Club assets, with keyless ERC20 transfer discovery on Ethereum, Base, Optimism, Arbitrum, Polygon and BNB. RPC checks candidate balances; unfinished history remains visible. First balances appear before detailed research finishes.
51
- The basic scan saves usable results first. Choose **Start deep scan** for
52
- additional discovery and one representative sell estimate per asset. Deep
53
- scans show saved asset checks, available prices and unresolved checks. Pause
54
- and resume from saved work at any time. Unknown coverage stays visible.
46
+ 1. **Connect Alchemy.** Alchemy supplies the token index across networks.
47
+ Open **Connect Alchemy** in Kira and follow the [simple setup guide](docs/ALCHEMY_SETUP.md).
48
+ Run `kira connect alchemy` in your terminal and enter your app key at the
49
+ hidden prompt. The key stays in a private local file. No wallet key is needed.
50
+ 2. **Add a watching wallet.** Paste a public EVM address and give it a name.
51
+ Kira checks every configured network and all discovered token candidates,
52
+ including the full reachable Mint Club registry. There is no 128-candidate
53
+ limit. Balances appear as they are checked; prices and artwork follow.
54
+ **Analyze sell routes** is optional. It estimates sales and redemptions from
55
+ saved holdings and does not discover more tokens. Pause and resume work in Activity.
55
56
  3. **Connect your AI.** Install and sign in to the
56
57
  [Codex CLI](https://developers.openai.com/codex/cli) or
57
58
  [Claude Code](https://code.claude.com/docs/en/quickstart), then choose your
@@ -144,13 +145,17 @@ Original code and Kira character assets are available under the [MIT license](LI
144
145
  Third-party artwork and references retain their own terms; see
145
146
  [Third-party notices](THIRD_PARTY_NOTICES.md).
146
147
 
147
- ### Token coverage and optional Alchemy setup
148
+ ### Alchemy and token coverage
148
149
 
149
- Kira uses free public RPC with bounded fallback and checks a selected common-token
150
- list alongside native assets and Mint Club. Other ERC20 holdings can be missing.
151
- Incomplete results show recovery guidance on Home and the wallet page. Connect
152
- your own Alchemy account for broader discovery on supported networks, then
153
- refresh holdings. Public RPC remains the first choice for ordinary reads;
154
- Alchemy is a backup and supplies the dedicated token inventory API. See the
155
- [step-by-step Alchemy guide](docs/ALCHEMY_SETUP.md) and
156
- [RPC behavior](docs/FREE_RPC.md).
150
+ An Alchemy connection is required for new holdings and price lookups. Alchemy
151
+ RPC is preferred on configured supported networks; verified public endpoints
152
+ remain a fallback where allowed. Dedicated indexes provide token candidates,
153
+ then on-chain reads verify balances. Other configured networks still receive
154
+ native and Mint Club registry checks, plus an available explorer index.
155
+ Unsupported discovery and failed reads remain unknown.
156
+
157
+ DEX spot prices require at least $1,000 of source-reported pool liquidity.
158
+ Extremely one-sided pools are also excluded. This is a conservative estimate
159
+ policy, not a claim that holdings can be sold at the displayed price. Saved
160
+ thin-pool quotes are excluded from totals without changing their raw evidence.
161
+ See the [Alchemy setup guide](docs/ALCHEMY_SETUP.md).
@@ -43,3 +43,7 @@ token safety, current balance, value or an exhaustive inventory. No service SDK
43
43
  or credential is distributed. Selected new known identities use issuer documents,
44
44
  PancakeSwap integration references and freshly verified on-chain metadata; their
45
45
  per-contract provenance is in the catalog.
46
+
47
+ ## Alchemy setup illustration
48
+
49
+ `viewer/static/alchemy-create-app.png` is an unmodified example screenshot from Alchemy’s public API key walkthrough, used to explain app setup. Source: https://www.alchemy.com/docs/create-an-api-key . The image contains no Kira operator account or credential. Alchemy retains rights to its interface and illustration.
package/curve_pricing.py CHANGED
@@ -12,13 +12,21 @@ def resolve(graph, prices):
12
12
  nodes={(r['chain_id'],r['address'].lower()):r for r in graph if r.get('address')}
13
13
  known={(r['chain_id'],r['address'].lower()):r for r in prices}
14
14
  cache={}
15
+ def rejected_reserve(key,seen):
16
+ if key in seen:return False
17
+ node=nodes.get(key);price=known.get(key)
18
+ if not node or not node.get('is_curve'):return bool(price and price.get('quality')=='unreliable')
19
+ if price and price.get('usd') is not None and price.get('basis')!='Curve spot' and price.get('quality') not in ('unfunded','unreliable'):return False
20
+ return rejected_reserve((key[0],node['reserve_token'].lower()),seen|{key})
15
21
  def visit(key,seen):
16
22
  if key in cache:return cache[key]
17
23
  if key in seen:return None
18
24
  existing=known.get(key)
19
25
  node=nodes.get(key)
26
+ if existing and existing.get('quality')=='unreliable' and not (node and node.get('is_curve')):
27
+ cache[key]={**existing,'usd':None};return cache[key]
20
28
  unfunded=node and not node.get('error') and node.get('is_curve') and node.get('funded') is False
21
- if existing and existing.get('usd') is not None and existing.get('quality') not in ('unfunded','unreliable') and (existing.get('basis')!='Curve spot' or not unfunded):
29
+ if existing and existing.get('usd') is not None and existing.get('quality') not in ('unfunded','unreliable') and (existing.get('basis')!='Curve spot' or not unfunded and not rejected_reserve(key,set())):
22
30
  cache[key]=existing;return existing
23
31
  if not node or node.get('error') or not node.get('is_curve'):return None
24
32
  if not node['funded']:
@@ -27,6 +35,10 @@ def resolve(graph, prices):
27
35
  'observed_at':node.get('observed_at'),'block_number':node.get('block_number')}
28
36
  cache[key]=record;return record
29
37
  parent=visit((key[0],node['reserve_token'].lower()),seen|{key})
38
+ if parent and parent.get('quality')=='unreliable':
39
+ record={'chain_id':key[0],'address':node['address'],'usd':None,'basis':'Curve spot','quality':'unreliable',
40
+ 'source':node.get('source'),'observed_at':node.get('observed_at'),'block_number':node.get('block_number')}
41
+ cache[key]=record;return record
30
42
  if not parent or parent.get('usd') is None:return None
31
43
  usd=float(node['price_in_reserve'])*parent['usd']
32
44
  if not math.isfinite(usd) or usd<0:return None
@@ -48,12 +60,16 @@ def enrich(snapshot,market,folder,deadline=None):
48
60
  networks=json.loads((h.ASSETS/'sources/rpc-candidates.json').read_text())
49
61
  input_path=folder/'reserve-graph-input.json'
50
62
  atomic(input_path,{'wallet':snapshot['wallet_address'],'tokens':snapshot['tokens'],'networks':networks,
51
- 'market_budget_ms':max(0,int((deadline-time.monotonic())*1000)) if deadline is not None else 180_000})
63
+ # Leave time for Node startup and the final atomic graph publication
64
+ # before the parent's hard stop. Completed checkpoints remain useful.
65
+ 'market_budget_ms':max(0,int((deadline-time.monotonic()-1)*1000)) if deadline is not None else 180_000})
52
66
  run_node('reserves',input_path,folder/'reserve-graph.json',deadline=deadline)
53
67
  recorded=json.loads((folder/'reserve-graph.json').read_text());graph=recorded['tokens']
54
68
  if recorded.get('market_pending'):raise MarketPause('Reserve checks reached the market time budget. Resume saved checks in Activity.')
55
69
  ordinary=[r for r in graph if r.get('address') and r.get('is_curve') is False and r['chain_id'] in ALCHEMY]
56
70
  prices=list(market.get('tokens',[]))
71
+ rejected={(p['chain_id'],p['address'].lower()) for p in prices if p.get('quality')=='unreliable'}
72
+ ordinary=[r for r in ordinary if (r['chain_id'],r['address'].lower()) not in rejected]
57
73
  # Only reserve assets are requested. Identify prices by network and contract, never symbol.
58
74
  requests=[{'network':ALCHEMY[r['chain_id']],'address':r['address']} for r in ordinary]
59
75
  inverse={value:key for key,value in ALCHEMY.items()}
@@ -1,103 +1,78 @@
1
1
  # Connect Alchemy to Kira
2
2
 
3
- Kira works with free public RPC by default. It checks native assets, selected
4
- common token contracts and the Mint Club registry, and uses keyless transfer
5
- discovery on supported networks. Unfinished history and other ERC20 holdings
6
- may still be missing. For broader token discovery, connect your own Alchemy account.
7
- Kira runs these requests locally and does not operate a hosted relay.
3
+ Alchemy supplies the token index Kira uses across networks. Kira requires your
4
+ own Alchemy connection for new holdings and price research. No wallet keys,
5
+ seed phrase, signature or spending permission is needed.
8
6
 
9
- ## Create an Alchemy app
7
+ The app includes a screenshot guide at `/alchemy-guide.html`, linked from
8
+ **Connect Alchemy**. Its dashboard illustration is Alchemy’s published example;
9
+ it contains no Kira operator account or key.
10
10
 
11
- 1. Sign in to the [Alchemy dashboard](https://dashboard.alchemy.com/).
12
- A new account may already have a default app. Use it, or open your team
13
- menu, Team Overview, Apps, then Create new app.
14
- 2. Name the app and select the mainnets you want to research. Check that the
15
- app has Node API and Portfolio API access for those networks. Create it.
16
- 3. Copy the app API key. The Endpoints tab shows its network URLs. Kira's
17
- combined Alchemy setup needs the key, so you do not need to copy each URL.
11
+ ## 1. Get your app key
18
12
 
19
- These steps follow Alchemy's [official API key guide](https://www.alchemy.com/docs/create-an-api-key),
20
- checked on October 9, 2026. Dashboard wording can change.
13
+ Open the [Alchemy dashboard](https://dashboard.alchemy.com/). A new account may
14
+ already have a default app. Use it or choose **Apps → Create new app**. Enable
15
+ the networks you use and confirm Node API and Portfolio API access. Copy the
16
+ app API key from its details page. You do not need separate endpoint URLs.
21
17
 
22
- ## Connect the key locally
18
+ These steps follow the [official walkthrough](https://www.alchemy.com/docs/create-an-api-key).
19
+ Dashboard labels can change. Review your account’s API access and usage limits.
23
20
 
24
- Create a private directory and file in your terminal:
21
+ ## 2. Connect locally
25
22
 
26
- ```sh
27
- mkdir -p ~/.config/kira
28
- touch ~/.config/kira/alchemy.env
29
- chmod 600 ~/.config/kira/alchemy.env
30
- ```
31
-
32
- Open the file in a local text editor. On macOS, you can use:
33
-
34
- ```sh
35
- open -e ~/.config/kira/alchemy.env
36
- ```
37
-
38
- Add this line, replacing `YOUR_KEY` inside the editor:
39
-
40
- ```dotenv
41
- ALCHEMY_API_KEY=YOUR_KEY
42
- ```
43
-
44
- Save the file, then run:
23
+ Run this in your terminal:
45
24
 
46
25
  ```sh
47
- kira config import-env --file ~/.config/kira/alchemy.env
26
+ kira connect alchemy
48
27
  ```
49
28
 
50
- For a non-default workspace, supply its existing `--data-dir` before `config`.
51
- Kira stores the file reference. Credentials stay outside the browser, chat and
52
- published analysis. Do not commit this file to a repository. A process
53
- environment variable with the same name overrides the file value; check that
54
- if an old key remains active.
55
-
56
- If detailed research is running, import-env queues a Local connection setup
57
- job in Activity. The writer pauses safely, applies the file reference, and
58
- resumes detailed research automatically. Wait for the setup job to complete,
59
- then recheck the connection. The public job contains no key value or file path.
60
- A legacy CLI analysis keeps its writer lock; its queued setup waits until that
61
- analysis finishes or is stopped.
62
-
63
- ## Check the connection and refresh
64
-
65
- Open Workspace settings, then Manage data connection. Select Alchemy and use
66
- "I added my key · check again". Save the connection. Finding the local key
67
- does not prove the account, API or network is working.
68
-
69
- For an existing wallet, choose Refresh this wallet's holdings or Refresh
70
- holdings on its page. A new analysis confirms access and coverage. Old saved
71
- analyses retain their original observations and warnings. Saving a connection
72
- does not register a wallet or start research automatically.
73
-
74
- ## What uses the key
75
-
76
- Ordinary balances prefer public RPC. After two failed or unavailable public
77
- providers, Kira tries the configured custom backup within the read deadline.
78
- Advanced settings can choose custom first or require custom only. Existing
79
- explicit custom-only restrictions remain in force.
80
-
81
- Alchemy token discovery uses the key directly. Standard public RPC cannot
82
- enumerate arbitrary ERC20 holdings. Kira uses Alchemy's
83
- [Tokens By Wallet endpoint](https://www.alchemy.com/docs/data/portfolio-apis/portfolio-api-endpoints/portfolio-api-endpoints/get-tokens-by-address),
84
- then verifies discovered candidates with on-chain balance reads.
85
-
86
- ## If tokens are still missing
87
-
88
- - **Local key unavailable:** confirm the file exists, its variable name matches
89
- the connection settings, and you ran the import command in the right workspace.
90
- - **Discovery failed:** check the app's enabled APIs and networks and Alchemy's
91
- usage dashboard. Correct access or limits, then retry holdings.
92
- - **Some balances could not be checked:** wait briefly and retry. Public and
93
- custom providers both have outages and limits. Review Advanced read preferences
94
- if a custom-only endpoint is unavailable.
95
- - **Unsupported network:** broader discovery is unavailable there. Connecting
96
- Alchemy cannot cover every network or every token. Known-contract reads remain
97
- useful, and missing holdings remain unknown.
98
-
99
- Alchemy has account allowances and throughput limits. Check the current
100
- [plans](https://www.alchemy.com/docs/reference/pricing-plans) and API availability
101
- before selecting a plan. Kira does not create an account, subscribe or upgrade
102
- it. Public-first balance reads reduce ordinary use of the key; discovery still
103
- consumes Alchemy allowance. No connection guarantees a complete token inventory.
29
+ Paste the key at the hidden prompt and press Enter. Kira stores it in a private
30
+ local file and queues the connection setup. The key never appears in the
31
+ command, browser, chat, public job or analysis.
32
+
33
+ For another workspace, use `kira --data-dir /path/to/workspace connect alchemy`.
34
+ For an existing environment file, `kira config import-env --file PATH` retains
35
+ that file reference. Add `--key-env NAME` when its variable has a different name.
36
+ The browser’s advanced option accepts the variable name only.
37
+
38
+ ## 3. Add or refresh a wallet
39
+
40
+ Return to Kira and choose **Check connection**. Add a public wallet, or refresh
41
+ holdings for an existing wallet. A found local key does not prove every API or
42
+ network is available; the holdings results record actual access and gaps.
43
+
44
+ Each holdings lookup checks every configured network and all returned token
45
+ candidates. Reachable Mint Club registries are enumerated too. There is no
46
+ 128-candidate cutoff. Unsupported indexes, failed balances and missing prices
47
+ or artwork remain unknown.
48
+
49
+ Price responses also supply artwork by network and contract. Kira reuses that
50
+ metadata instead of requiring another successful lookup for the same logo.
51
+ Completed reserve-price paths remain usable when a bounded pass pauses;
52
+ unfinished paths keep their original unknown state.
53
+ Further reserve traversal focuses on funded curves whose USD price is still
54
+ unknown. Bounded checks leave time to save their completed results.
55
+
56
+ **Analyze sell routes** is optional. It uses the saved balances and their
57
+ original blocks to estimate a representative sale or redemption. It is not
58
+ required for tokens, prices or logos and does not expand the holdings inventory.
59
+
60
+ ## Troubleshooting
61
+
62
+ - Run the command in the workspace you are viewing.
63
+ - Check the app’s networks, Node API, Portfolio API and usage in Alchemy.
64
+ - Retry holdings after access or provider errors are resolved.
65
+ - An unsupported network can still have native or Mint Club balances. An indexer
66
+ cannot guarantee every arbitrary token, and another provider cannot restart
67
+ a retired network.
68
+
69
+ Kira makes requests locally through your account. Review Alchemy’s current
70
+ [plans and limits](https://www.alchemy.com/docs/reference/pricing-plans).
71
+
72
+ The research engine spaces its private Alchemy node reads at least 250 ms apart
73
+ in one shared lane across Alchemy networks. An Alchemy throughput response cools
74
+ that lane before queued reads can use another Alchemy host. Public and other
75
+ custom RPC endpoints keep their existing pacing and fallback behavior. Canonical
76
+ block checks and provider backoff still apply. This is a local scheduling policy,
77
+ not a guarantee about an account's available capacity. Alchemy's
78
+ [throughput allowance is shared across apps and chains](https://support.alchemy.com/articles/3788245542-is-alchemy-s-throughput-cu-s-limit-shared-across-all-apps-or-set-per-chain).
package/docs/CLI.md CHANGED
@@ -17,17 +17,22 @@ Registry publication remains an operator action. The code and original character
17
17
 
18
18
  ## Lifecycle
19
19
 
20
- Wallet registration and holdings refresh run a basic scan first. Use the saved
21
- result immediately, then choose **Start deep scan** in the wallet or Activity
22
- to check remaining networks and more complex markets. Deep scanning is optional,
23
- has no overall time limit, and supports **Pause scan** and **Resume deep scan**.
24
- It runs while Kira is running on this computer. App restart preserves saved
25
- results and requires an explicit resume for interrupted work.
26
-
27
- CLI equivalents are `kira jobs deepen BASIC_JOB_ID`, `kira jobs cancel JOB_ID`
28
- and `kira jobs resume JOB_ID`. A repeated deepen request uses the same child;
29
- it does not restart paused or finished work. Refreshing holdings starts a new
30
- basic scan. Neither basic nor deep completion guarantees all holdings or prices.
20
+ Connect Alchemy once with `kira connect alchemy`. The operator enters the app
21
+ key at a hidden terminal prompt. New wallet and price research requires this
22
+ connection; saved portfolios remain readable without it.
23
+
24
+ Wallet registration and holdings refresh check every configured network and all
25
+ returned candidates, including the reachable Mint Club registry. There is no
26
+ 128-candidate cap. Saved balances appear as checks finish; price and artwork
27
+ lookup is independent of optional sell analysis.
28
+
29
+ Choose **Analyze sell routes** only for sale or redemption estimates. Internally,
30
+ `kira jobs deepen HOLDINGS_JOB_ID` admits one child using that wallet’s immutable
31
+ holdings source. It does not discover tokens or reread balances. Use `kira jobs
32
+ cancel JOB_ID` to pause and `kira jobs resume JOB_ID` to continue. A newer holdings
33
+ lookup supersedes earlier analysis. Old limited scans require a holdings refresh
34
+ before the new sell-analysis action. Slices remain bounded, with no overall
35
+ completion deadline or exhaustive-market guarantee.
31
36
 
32
37
  Use `kira setup` for your first setup. For everyday use, `kira start` starts
33
38
  the local app with browser controls and opens it in your browser. The default
@@ -58,12 +63,10 @@ Published 0.1.4 explains limited discovery before wallet registration and beside
58
63
  holdings. Missing coverage keeps the portfolio estimate partial. Existing snapshots require a holdings refresh after connecting
59
64
  an indexer; a price refresh does not discover missing tokens.
60
65
 
61
- Free research checks known assets, Mint Club and keyless token candidates on supported networks. Alchemy is optional. For broader ERC20 discovery,
62
- open Custom RPC & token coverage, select Alchemy and follow its local key guide.
63
- Published 0.1.5 uses one save for Alchemy RPC and discovery; chain overrides
64
- remain under Advanced. Never paste the key into the browser. `kira doctor`
65
- checks whether the configured key is available. Configuration alone does not
66
- prove complete coverage; inspect the recorded results and gaps.
66
+ Alchemy is required for new research. Open **Workspace settings → Alchemy** and
67
+ follow the [setup guide](ALCHEMY_SETUP.md). Alchemy reads run first; verified
68
+ public RPC remains an allowed fallback. Existing custom-only preferences are
69
+ preserved. Missing networks and token prices remain explicit in saved results.
67
70
 
68
71
  Connecting Codex or Claude is optional. Use Connect your AI when ready, verify
69
72
  a generic response and explicitly choose context permissions. Assistant answers
@@ -80,10 +83,11 @@ authentication. Verified adapter versions are Codex 0.158.x and Claude Code
80
83
  verified. This is a native CLI connection, with no Kira account, API-key proxy or
81
84
  hosted portfolio backend.
82
85
 
83
- From published 0.1.5, setup opens the existing Account / Permissions / Ready
84
- modal directly. Choose Codex or Claude, then Use default model or a readable
85
- model choice. Codex choices come from bounded native metadata; Claude offers
86
- Sonnet, Opus and Haiku aliases. A catalog is not proof of account access.
86
+ Setup leaves the wallet checklist visible. Choose **Connect AI** or **Connect a
87
+ model** to open the Account / Permissions / Ready modal. Choose Codex or Claude,
88
+ then Use default model or a readable model choice. Codex choices come from
89
+ bounded native metadata; Claude offers Sonnet, Opus and Haiku aliases. A catalog
90
+ is not proof of account access.
87
91
  Advanced accepts a custom identifier and preserves saved identifiers absent
88
92
  from the catalog. Workspace settings reopens the same selector and permissions. Choose no automatic wallet context, one registered wallet,
89
93
  or the whole recorded portfolio. A generic response check sends no wallet data
@@ -114,7 +118,6 @@ assets and writable runtime files use separate roots.
114
118
 
115
119
  ```sh
116
120
  kira rpc public
117
- kira discovery none
118
121
  kira doctor
119
122
  kira doctor --live --chains 1,8453,81457 --budget 30
120
123
  ```
@@ -225,11 +228,11 @@ original encryption passphrase. No signing, key export or account deletion
225
228
  endpoint is exposed. OWS absence does not block ordinary address or browser
226
229
  wallet onboarding.
227
230
 
228
- ## Free reads and broader token coverage
231
+ ## Provider reads and coverage
229
232
 
230
- Public RPC is preferred for ordinary reads, including when a custom backup is
231
- configured. Advanced settings can select custom first or custom only. For CLI
232
- configuration, use `kira rpc set --chain 8453 --url-env KIRA_BASE_RPC --priority
233
- public_first`. Existing custom-only choices remain unchanged. Alchemy token
234
- discovery uses the configured key directly. See [free RPC behavior](FREE_RPC.md)
235
- and the [Alchemy setup guide](ALCHEMY_SETUP.md).
233
+ Alchemy token discovery uses your key directly. Configured Alchemy RPC reads
234
+ run before public fallback. The browser exposes one Alchemy connection rather
235
+ than free and expanded modes. Existing low-level RPC references remain available
236
+ through the CLI. See [Alchemy setup](ALCHEMY_SETUP.md). `FREE_RPC.md` retains the
237
+ historical free-discovery implementation and its evidence; it is not the current
238
+ onboarding policy.
package/docs/FREE_RPC.md CHANGED
@@ -1,4 +1,11 @@
1
- # Free RPC reads and token coverage
1
+ # Historical free RPC reads and token coverage
2
+
3
+ Current research requires Alchemy. Holdings check every configured network and
4
+ all returned candidates with full reachable Mint Club enumeration. Alchemy reads
5
+ run first. Sell analysis is optional and uses saved holdings only. See
6
+ [Alchemy setup](ALCHEMY_SETUP.md). The free-discovery policies and acceptance
7
+ limits below are retained as historical implementation evidence, not current
8
+ onboarding defaults.
2
9
 
3
10
  Kira contacts public providers directly from the local research process. No
4
11
  Kira relay or shared credential is required. Free public services are best
@@ -147,6 +154,9 @@ RPC-verified balances. Other Routescan chains are not presumed supported.
147
154
  Explicit keyless opt-outs and custom-only preferences remain respected.
148
155
 
149
156
  Initial reports check Base, Ethereum and Blast, up to 128 candidates per chain.
157
+ This scheduling scope also applies to Alchemy discovery. It is not a three-chain
158
+ limit of public RPC. Initial price and artwork metadata has a separate bounded
159
+ lookup, so unfinished sell-estimate research cannot suppress those lookups.
150
160
  Selected common contracts take priority. Remaining candidates and networks are
151
161
  explicitly pending. A user-selected deep scan checks every configured
152
162
  network, its recorded inventory policy and markets. In full mode, pinned registry counts,
@@ -187,37 +187,38 @@ secret value is copied into the request, receipt, viewer or model context.
187
187
  Explicit cancellation survives recovery and exception boundaries as stopped.
188
188
  A completed publication receipt still wins a cancellation race.
189
189
 
190
- ## Basic scans and optional deep scans
191
-
192
- New wallet.add and wallet.refresh jobs have scan_policy: optional_depth_v1.
193
- The basic scan checks initial balances on Base, Ethereum and Blast and publishes
194
- usable results. Finishing a basic scan does not start more provider work.
195
- Unstarted legacy parents also do not acquire new child jobs on app restart.
196
- The viewer presents the result as "Basic scan ready", with coverage gaps visible.
197
-
198
- An explicit job.deepen request targets a succeeded or partial baseline with a
199
- saved result. It admits exactly one enrichment child per parent under the
200
- request lock. Concurrent clicks, new request keys and restart recovery all
201
- return that same child, including a previously paused child. A separate explicit
202
- job.resume is required to resume it. A newer basic generation rejects starting
203
- or resuming old deep work. No saved balances are copied into a new analysis.
204
-
205
- A deep scan has no overall twenty-minute completion deadline. It keeps the
206
- bounded, checkpointed engine slices, provider backoff, single writer,
207
- short-operation priority and no-progress protection described above.
208
- "Pause scan" uses job.cancel to stop the current worker and retain results and
209
- checkpoints. "Resume deep scan" requeues the same job. Publication still wins a
210
- pause race. Finished partial results describe unknown coverage, not failure to
211
- meet a time target or proof of exhaustive holdings.
212
-
213
- The wallet card and Activity restore their state from persisted jobs. Buttons
214
- require the existing protected local session and are disabled while disconnected,
215
- submitting or pausing. Sample and watch-only workspaces cannot start scans.
216
- Current-step bars use actual bounded counts. Unknown totals have no percentage.
217
- Only a stable measured step may show an expiring ETA range; overall time remains
218
- unknown. progress_observed_at advances on actual checked work or a saved initial
219
- publication, not repeated errors or provider waits. Quiet and disconnected states
220
- are explicit. Live announcements concern state transitions, not every count.
190
+ ## All-network holdings and optional sell analysis
191
+
192
+ New wallet.add and wallet.refresh jobs record `scan_policy: alchemy_inventory_v1`.
193
+ They require a configured local Alchemy key before registration or provider work.
194
+ The internal baseline phase invokes `wallet.py --phase holdings`: every configured
195
+ network, all indexer candidates, and full reachable Mint Club registry enumeration.
196
+ The 128-read batch size remains an RPC payload bound, never a token-inventory cap.
197
+ Newly checked chains are published progressively as immutable initial snapshots.
198
+ Initial token prices stay unknown until the metadata pass checks them. Alchemy
199
+ artwork can appear immediately. Final holdings include bounded price and artwork
200
+ lookup without market-route analysis.
201
+
202
+ An explicit `job.deepen` admits one enrichment child per current holdings parent.
203
+ It invokes `--phase sell --holdings-snapshot SNAPSHOT`. The source must belong to
204
+ that wallet and have `pipeline.phase: holdings`. Its balances, blocks and clocks
205
+ are copied into the new analysis without running discovery, registry scans or
206
+ balance refresh. Route checks use those recorded blocks. Partial historical
207
+ scans require a new holdings lookup first. New holdings supersede older analysis.
208
+
209
+ Pause and resume preserve the same job and its evidence. App restart requires
210
+ explicit resume for queued or interrupted scans. Market slices, provider pacing,
211
+ short-operation priority, immutable publication and no-progress protection remain.
212
+ There is no overall twenty-minute deadline. Finite route work never proves every
213
+ market has been searched. The viewer calls this optional action **Analyze sell
214
+ routes**; holdings, token prices and artwork do not depend on it.
215
+ Pending or failed route checks stay in sell-analysis progress and do not
216
+ invalidate the saved holdings coverage.
217
+
218
+ Current-step bars use real counts. Unknown durations have no ETA or percentage.
219
+ Detailed stages remain in Activity; chat has one collapsed status line. Review
220
+ not selected for this operator-authorized change. Earlier free-scan paragraphs
221
+ in this contract are historical and do not override this section.
221
222
 
222
223
  ### Asset-focused market review
223
224