kira-wallet 0.1.12 → 0.1.13
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 +23 -18
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/curve_pricing.py +15 -1
- package/docs/ALCHEMY_SETUP.md +46 -86
- package/docs/CLI.md +32 -29
- package/docs/FREE_RPC.md +11 -1
- package/docs/JOB_CONTRACT.md +32 -31
- package/docs/RELEASE.md +54 -4
- package/kira_agent.py +1 -0
- package/kira_cli.py +21 -2
- package/kira_config.py +12 -5
- package/kira_jobs.py +24 -6
- package/kira_ows.py +1 -0
- package/package.json +1 -1
- package/pipeline-onchain.cjs +18 -6
- package/sources/job-envelope-v1.schema.json +1 -1
- package/viewer/model.py +55 -11
- package/viewer/onboarding.py +1 -1
- package/viewer/refresh-curve-prices.cjs +5 -4
- package/viewer/refresh_prices.py +37 -8
- package/viewer/server.py +1 -1
- package/viewer/static/agent.js +7 -12
- package/viewer/static/alchemy-create-app.png +0 -0
- package/viewer/static/alchemy-guide.css +1 -0
- package/viewer/static/alchemy-guide.html +10 -0
- package/viewer/static/app.js +10 -7
- package/viewer/static/chat-workspace.css +11 -2
- package/viewer/static/chat-workspace.js +12 -3
- package/viewer/static/index.html +21 -26
- package/viewer/static/jobs.js +32 -69
- package/viewer/static/ows.js +1 -0
- package/viewer/static/report.js +7 -9
- package/viewer/static/watching.js +3 -2
- package/viewer/static/workspace-model.js +23 -41
- package/viewer/token_images.py +27 -5
- package/wallet.py +192 -63
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. **
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
###
|
|
148
|
+
### Alchemy and token coverage
|
|
148
149
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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).
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -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
|
|
@@ -54,6 +66,8 @@ def enrich(snapshot,market,folder,deadline=None):
|
|
|
54
66
|
if recorded.get('market_pending'):raise MarketPause('Reserve checks reached the market time budget. Resume saved checks in Activity.')
|
|
55
67
|
ordinary=[r for r in graph if r.get('address') and r.get('is_curve') is False and r['chain_id'] in ALCHEMY]
|
|
56
68
|
prices=list(market.get('tokens',[]))
|
|
69
|
+
rejected={(p['chain_id'],p['address'].lower()) for p in prices if p.get('quality')=='unreliable'}
|
|
70
|
+
ordinary=[r for r in ordinary if (r['chain_id'],r['address'].lower()) not in rejected]
|
|
57
71
|
# Only reserve assets are requested. Identify prices by network and contract, never symbol.
|
|
58
72
|
requests=[{'network':ALCHEMY[r['chain_id']],'address':r['address']} for r in ordinary]
|
|
59
73
|
inverse={value:key for key,value in ALCHEMY.items()}
|
package/docs/ALCHEMY_SETUP.md
CHANGED
|
@@ -1,103 +1,63 @@
|
|
|
1
1
|
# Connect Alchemy to Kira
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21
|
+
## 2. Connect locally
|
|
22
|
+
|
|
23
|
+
Run this in your terminal:
|
|
25
24
|
|
|
26
25
|
```sh
|
|
27
|
-
|
|
28
|
-
touch ~/.config/kira/alchemy.env
|
|
29
|
-
chmod 600 ~/.config/kira/alchemy.env
|
|
26
|
+
kira connect alchemy
|
|
30
27
|
```
|
|
31
28
|
|
|
32
|
-
|
|
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.
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
37
|
|
|
38
|
-
|
|
38
|
+
## 3. Add or refresh a wallet
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
43
|
|
|
44
|
-
|
|
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.
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
**Analyze sell routes** is optional. It uses the saved balances and their
|
|
50
|
+
original blocks to estimate a representative sale or redemption. It is not
|
|
51
|
+
required for tokens, prices or logos and does not expand the holdings inventory.
|
|
52
|
+
|
|
53
|
+
## Troubleshooting
|
|
54
|
+
|
|
55
|
+
- Run the command in the workspace you are viewing.
|
|
56
|
+
- Check the app’s networks, Node API, Portfolio API and usage in Alchemy.
|
|
57
|
+
- Retry holdings after access or provider errors are resolved.
|
|
58
|
+
- An unsupported network can still have native or Mint Club balances. An indexer
|
|
59
|
+
cannot guarantee every arbitrary token, and another provider cannot restart
|
|
60
|
+
a retired network.
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
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.
|
|
62
|
+
Kira makes requests locally through your account. Review Alchemy’s current
|
|
63
|
+
[plans and limits](https://www.alchemy.com/docs/reference/pricing-plans).
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
model choice. Codex choices come from
|
|
86
|
-
Sonnet, Opus and Haiku aliases. A catalog
|
|
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
|
-
##
|
|
231
|
+
## Provider reads and coverage
|
|
229
232
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
discovery
|
|
235
|
-
|
|
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
|
-
#
|
|
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,
|
package/docs/JOB_CONTRACT.md
CHANGED
|
@@ -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
|
-
##
|
|
191
|
-
|
|
192
|
-
New wallet.add and wallet.refresh jobs
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
The
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
job.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
|
package/docs/RELEASE.md
CHANGED
|
@@ -79,7 +79,7 @@ The earlier unpublished 0.1.2 candidate is preserved in the ignored
|
|
|
79
79
|
`dist/preserved-0.1.2-bad8f02/` directory. Use the current `dist/release.json`
|
|
80
80
|
and its matching archive for publication; do not mix manifests from candidates.
|
|
81
81
|
|
|
82
|
-
Keep published GitHub tags, release assets and npm versions through 0.1.
|
|
82
|
+
Keep published GitHub tags, release assets and npm versions through 0.1.12
|
|
83
83
|
immutable. Do not rebuild them from later documentation commits. Future package
|
|
84
84
|
changes need a new version. Release preparation does not publish a GitHub
|
|
85
85
|
release, promote the website or publish to npm.
|
|
@@ -95,12 +95,12 @@ python3 scripts/prepare-release.py
|
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
`prepare-release.py` scans the package boundary and creates
|
|
98
|
-
`dist/kira-wallet-0.1.
|
|
98
|
+
`dist/kira-wallet-0.1.13.tgz`. The ignored `dist/release.json` records its source
|
|
99
99
|
commit, SHA-256 and member count. It never publishes. After reviewing that
|
|
100
100
|
manifest, the operator's final command from the project root is:
|
|
101
101
|
|
|
102
102
|
```sh
|
|
103
|
-
npm publish ./dist/kira-wallet-0.1.
|
|
103
|
+
npm publish ./dist/kira-wallet-0.1.13.tgz --access public
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
Use the operator's npm account and complete authentication or OTP personally.
|
|
@@ -269,7 +269,7 @@ Use only the archive matching the final `dist/release.json` source commit,
|
|
|
269
269
|
SHA-256 and installed member hashes. A registry dry run does not publish or
|
|
270
270
|
establish registry credentials. Registry publication remains operator-only.
|
|
271
271
|
|
|
272
|
-
##
|
|
272
|
+
## Published 0.1.12
|
|
273
273
|
|
|
274
274
|
This release consolidates the completed PR20 through PR29 stack into the default
|
|
275
275
|
release branch. It includes the native HTML showcase, simpler local startup and
|
|
@@ -298,3 +298,53 @@ Prepare the final archive only after the release source has landed. Its exact
|
|
|
298
298
|
commit and hashes belong in `dist/release.json`. Actual npm publication remains
|
|
299
299
|
operator-only. Personal installations and paused automation are separate from
|
|
300
300
|
release preparation.
|
|
301
|
+
|
|
302
|
+
## Release candidate: 0.1.13
|
|
303
|
+
|
|
304
|
+
Version 0.1.13 requires a locally available Alchemy key reference before wallet
|
|
305
|
+
research. `kira connect alchemy` accepts the key privately in an interactive
|
|
306
|
+
terminal. Onboarding has two steps, connecting Alchemy and adding a wallet,
|
|
307
|
+
with an included guide using a public blank Alchemy example. AI connection is
|
|
308
|
+
optional and its dialog opens only after an explicit connection action. Chat
|
|
309
|
+
research status is a collapsible single line.
|
|
310
|
+
|
|
311
|
+
Default holdings research attempts all 18 configured mainnets and six testnets.
|
|
312
|
+
It checks every discovered, prior or known candidate and the available Mint Club
|
|
313
|
+
registry. There is no 128-token candidate limit; 128 remains an RPC payload batch
|
|
314
|
+
size. Failed network access and unavailable indexers remain explicit unknowns.
|
|
315
|
+
This is not a guarantee of complete discovery on arbitrary EVM networks. Testnet
|
|
316
|
+
values never enter portfolio USD totals. Existing limited snapshots need a new
|
|
317
|
+
holdings refresh to gain the restored inventory coverage.
|
|
318
|
+
|
|
319
|
+
Default holdings, prices and artwork do not require a deep scan. Optional
|
|
320
|
+
`Analyze sell routes` reuses the same wallet's immutable saved balances, blocks
|
|
321
|
+
and observation times. It researches liquidation paths without rediscovering
|
|
322
|
+
tokens or refreshing balances. Bounded engine slices, provider pacing, pause,
|
|
323
|
+
resume and no-progress protection remain. It has no overall time limit.
|
|
324
|
+
|
|
325
|
+
Prices from DEX pools below USD 1,000 liquidity, or explicitly one-sided pools,
|
|
326
|
+
cannot contribute to portfolio totals. Rejected reserve prices cannot reappear
|
|
327
|
+
through cached indexer or dependent curve estimates. Balances remain visible
|
|
328
|
+
with unknown USD values. Valid spot estimates still do not establish executable
|
|
329
|
+
sale proceeds. Price-only updates preserve immutable holdings and prior market
|
|
330
|
+
records, reuse fresh batched curve facts and publish explicit partial results
|
|
331
|
+
when a bounded lookup cannot finish.
|
|
332
|
+
|
|
333
|
+
Artwork uses chain and contract identity with Mint Club and Alchemy sources,
|
|
334
|
+
including allowed Alchemy and CoinMarketCap hosts. The Mint Club image fallback
|
|
335
|
+
retries once before initials. No original image is promised for an unknown token.
|
|
336
|
+
Failed Mint Club detail batches receive one smaller retry, and remaining errors
|
|
337
|
+
keep coverage partial rather than silently becoming completed records.
|
|
338
|
+
|
|
339
|
+
The source in PR31 passed the full suite, clean installation and actual-wallet
|
|
340
|
+
holdings, price, artwork and sell-only pause/resume checks. Release preparation
|
|
341
|
+
reruns the required suite and clean installation, scans tracked source and
|
|
342
|
+
history, and compares every final archive member with the landed source and
|
|
343
|
+
its isolated installation. Product acceptance may be reused only for identical
|
|
344
|
+
product bytes. Preserve raw history findings and apply only the exact normal
|
|
345
|
+
CLI merge-metadata acceptance described above. Review not selected.
|
|
346
|
+
|
|
347
|
+
Prepare the final archive from the landed version PR. Freeze its source commit,
|
|
348
|
+
SHA-256 and member hashes, then dry-run that exact archive. npm publication is
|
|
349
|
+
operator-only. Do not upgrade the personal app, resume paused automation,
|
|
350
|
+
publish a GitHub release or deploy the website during preparation.
|
package/kira_agent.py
CHANGED
|
@@ -24,6 +24,7 @@ PROVIDERS = {
|
|
|
24
24
|
}
|
|
25
25
|
CODEX_DISABLED = ('shell_tool', 'unified_exec', 'shell_snapshot', 'apps', 'plugins', 'remote_plugin', 'browser_use', 'browser_use_external', 'computer_use', 'image_generation', 'view_image', 'multi_agent', 'hooks', 'memories', 'skill_search', 'skill_mcp_dependency_install', 'code_mode', 'code_mode_host', 'goals')
|
|
26
26
|
SYSTEM = ('You are Kira, a careful wallet research partner. Answer in the language of the user. '
|
|
27
|
+
'Alchemy connection is required for new holdings and price research. Holdings lookups cover every configured network without a 128-candidate cap. Sell-route analysis is optional and uses saved holdings; it is not needed for token discovery, prices or artwork. '
|
|
27
28
|
'Use only the provided recorded facts. Unknown data is not zero. Preserve chain and contract identities, '
|
|
28
29
|
'observation times, coverage gaps, and the difference between curve spot estimates and executable prices. '
|
|
29
30
|
'The current recorded context supersedes older facts in the conversation. '
|
package/kira_cli.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
|
+
import re
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
import shutil
|
|
8
9
|
import signal
|
|
@@ -144,6 +145,22 @@ def sample(root):
|
|
|
144
145
|
atomic(root/'wallets.json',{'schema_version':1,'demo':True,'wallets':[{'address':address,'address_key':address,'tags':['Demo wallet'],
|
|
145
146
|
'latest_snapshot':{'directory':folder,'result':folder+'/results.json'}}]})
|
|
146
147
|
|
|
148
|
+
def connect_alchemy(root):
|
|
149
|
+
"""Only the operator types the key, at a hidden terminal prompt."""
|
|
150
|
+
import getpass
|
|
151
|
+
from kira_jobs import JobStore
|
|
152
|
+
if not sys.stdin.isatty():raise ValueError('Run kira connect alchemy in an interactive terminal. The API key is entered privately there.')
|
|
153
|
+
key=getpass.getpass('Alchemy API key (hidden): ').strip()
|
|
154
|
+
if not key or len(key)>512 or not re.fullmatch(r'[A-Za-z0-9_-]+',key):raise ValueError('Enter the app API key, without an endpoint URL.')
|
|
155
|
+
directory=root/'.secrets';directory.mkdir(mode=0o700,exist_ok=True)
|
|
156
|
+
if directory.is_symlink():raise ValueError('The private key directory must not be a symlink.')
|
|
157
|
+
import tempfile
|
|
158
|
+
fd,name=tempfile.mkstemp(prefix='alchemy-',suffix='.env',dir=directory)
|
|
159
|
+
with os.fdopen(fd,'w') as stream:
|
|
160
|
+
stream.write('ALCHEMY_API_KEY='+key+'\n');stream.flush();os.fsync(stream.fileno())
|
|
161
|
+
store=JobStore(root);job=store.queue_import(name,'ALCHEMY_API_KEY');store.launch()
|
|
162
|
+
print(json.dumps({'status':'configuration_queued','job_id':job['job_id'],'note':'Your key is stored privately on this computer. Return to Kira and check the connection.'}))
|
|
163
|
+
|
|
147
164
|
def main():
|
|
148
165
|
parser=argparse.ArgumentParser(description=__doc__)
|
|
149
166
|
parser.add_argument('--data-dir',default=os.environ.get('KIRA_DATA_DIR',str(Path.home()/'.local/share/kira-wallet')))
|
|
@@ -157,6 +174,7 @@ def main():
|
|
|
157
174
|
setup=sub.add_parser('setup');setup.add_argument('--port',type=int,default=8787);setup.add_argument('--no-open',action='store_true')
|
|
158
175
|
sub.add_parser('stop');sub.add_parser('status');sub.add_parser('wallets')
|
|
159
176
|
sub.add_parser('tools')
|
|
177
|
+
connection=sub.add_parser('connect');connection.add_argument('provider',choices=['alchemy'])
|
|
160
178
|
d=sub.add_parser('doctor');d.add_argument('--live',action='store_true');d.add_argument('--chains',default='1,8453,81457');d.add_argument('--budget',type=int,default=30)
|
|
161
179
|
demo=sub.add_parser('demo');demo.add_argument('--port',type=int,default=8790)
|
|
162
180
|
add=sub.add_parser('add');add.add_argument('address');add.add_argument('--tag',required=True);add.add_argument('--resume')
|
|
@@ -204,7 +222,8 @@ def main():
|
|
|
204
222
|
from kira_config import load_config,config_path,redact
|
|
205
223
|
try:
|
|
206
224
|
initialize(root)
|
|
207
|
-
if args.command=='
|
|
225
|
+
if args.command=='connect':connect_alchemy(root)
|
|
226
|
+
elif args.command=='init':print(json.dumps({'status':'initialized','rpc_mode':load_config()['rpc']['mode']}))
|
|
208
227
|
elif args.command=='start':
|
|
209
228
|
url=start(root,args.port,args.controls)
|
|
210
229
|
if not args.no_open:
|
|
@@ -215,7 +234,7 @@ def main():
|
|
|
215
234
|
if not args.no_open:
|
|
216
235
|
import webbrowser
|
|
217
236
|
webbrowser.open(url)
|
|
218
|
-
print(json.dumps({'setup_url':url,'note':'
|
|
237
|
+
print(json.dumps({'setup_url':url,'note':'Connect Alchemy, then add a public wallet. AI connection is optional.'}))
|
|
219
238
|
elif args.command=='stop':stop(root)
|
|
220
239
|
elif args.command=='status':
|
|
221
240
|
item=live_record(root);print(json.dumps({'status':'running' if item else 'stopped','url':f"http://127.0.0.1:{item['port']}" if item else None}))
|