tollkit-wallet 0.2.2 → 0.3.1
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 +13 -0
- package/dist/actions.d.ts +131 -35
- package/dist/ai.d.ts +13 -1
- package/dist/ai.js +2 -2
- package/dist/ai.js.map +1 -1
- package/dist/autopilot.d.ts +7 -0
- package/dist/autopilot.js +118 -3
- package/dist/autopilot.js.map +1 -1
- package/dist/bots.d.ts +92 -0
- package/dist/bots.js +183 -0
- package/dist/bots.js.map +1 -0
- package/dist/bridge.js +7 -5
- package/dist/bridge.js.map +1 -1
- package/dist/dapp.d.ts +11 -0
- package/dist/dapp.js +82 -14
- package/dist/dapp.js.map +1 -1
- package/dist/dashboard.d.ts +12 -0
- package/dist/dashboard.js +136 -14
- package/dist/dashboard.js.map +1 -1
- package/dist/data/token-list.d.ts +12 -0
- package/dist/data/token-list.js +13 -0
- package/dist/data/token-list.js.map +1 -0
- package/dist/evmsend.d.ts +30 -0
- package/dist/evmsend.js +47 -0
- package/dist/evmsend.js.map +1 -0
- package/dist/holdings.d.ts +6 -0
- package/dist/holdings.js +41 -8
- package/dist/holdings.js.map +1 -1
- package/dist/ledger.d.ts +1 -0
- package/dist/ledger.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/pay.js +1 -1
- package/dist/pay.js.map +1 -1
- package/dist/policy.d.ts +2 -2
- package/dist/rules.d.ts +57 -6
- package/dist/rules.js +46 -4
- package/dist/rules.js.map +1 -1
- package/dist/seller.js +15 -4
- package/dist/seller.js.map +1 -1
- package/dist/send.js +3 -2
- package/dist/send.js.map +1 -1
- package/dist/solconfirm.d.ts +13 -0
- package/dist/solconfirm.js +21 -0
- package/dist/solconfirm.js.map +1 -0
- package/dist/stake.js +3 -2
- package/dist/stake.js.map +1 -1
- package/dist/swap.d.ts +58 -5
- package/dist/swap.js +327 -21
- package/dist/swap.js.map +1 -1
- package/dist/tokenlist.d.ts +70 -0
- package/dist/tokenlist.js +259 -0
- package/dist/tokenlist.js.map +1 -0
- package/dist/trademode.d.ts +3 -0
- package/dist/trademode.js +23 -0
- package/dist/trademode.js.map +1 -0
- package/dist/ui.js +202 -19
- package/dist/ui.js.map +1 -1
- package/dist/wallet.d.ts +13 -1
- package/dist/wallet.js +85 -5
- package/dist/wallet.js.map +1 -1
- package/extension/background.js +1 -1
- package/extension/popup.js +1 -1
- package/package.json +2 -2
package/dist/ui.js
CHANGED
|
@@ -12,18 +12,24 @@ export const PAGE = String.raw `<!doctype html>
|
|
|
12
12
|
@media (prefers-color-scheme:light){:root:not([data-theme=dark]){--bg:#eceef3;--card:#fff;--surf:#f4f5f8;--surf2:#e9ebf1;--line:#e1e3ea;--tx:#15161b;--mut:#666a7a}}
|
|
13
13
|
*{box-sizing:border-box}html,body{margin:0;background:var(--bg);color:var(--tx);font:14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif}
|
|
14
14
|
.wrap{max-width:420px;margin:24px auto;padding:0 16px}
|
|
15
|
-
.card{background:var(--card);border:1px solid var(--line);border-radius:20px;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,.35);display:flex;flex-direction:column;min-height:
|
|
15
|
+
.card{background:var(--card);border:1px solid var(--line);border-radius:20px;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,.35);display:flex;flex-direction:column;height:calc(100vh - 96px);height:calc(100dvh - 96px);min-height:520px;max-height:900px}
|
|
16
16
|
header{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line)}
|
|
17
17
|
.logo{width:30px;height:30px;flex:none;display:block}
|
|
18
18
|
.brand{font:700 15px ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:-.01em;white-space:nowrap}.brand .dot{color:#4a8eff}.brand .sub{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;font-weight:500;color:var(--mut);margin-left:6px}
|
|
19
19
|
.cp{margin-left:auto;flex:none;border:0;background:var(--surf2);color:var(--tx);border-radius:9px;padding:6px 10px;font:600 12px inherit;cursor:pointer;display:flex;align-items:center;gap:5px}
|
|
20
20
|
.cp svg{width:14px;height:14px}.cp.done{color:var(--ok)}header .pill{margin-left:auto;white-space:nowrap;font-size:11px;padding:4px 9px;border-radius:99px;background:var(--surf);color:var(--mut)}
|
|
21
|
-
main{flex:1;padding:16px;overflow:auto}
|
|
22
|
-
nav{display:grid;grid-template-columns:repeat(6,1fr);border-top:1px solid var(--line);background:var(--card)}
|
|
21
|
+
main{flex:1;min-height:0;padding:16px;overflow:auto;overscroll-behavior:contain}
|
|
22
|
+
nav{flex:none;display:grid;grid-template-columns:repeat(6,1fr);border-top:1px solid var(--line);background:var(--card)}
|
|
23
23
|
nav button{background:none;border:0;color:var(--mut);padding:10px 0 12px;font:inherit;font-size:11px;cursor:pointer;position:relative}
|
|
24
24
|
nav button svg{display:block;margin:0 auto 3px;width:20px;height:20px}
|
|
25
25
|
nav button.on{color:var(--acc)}
|
|
26
26
|
.badge{position:absolute;top:5px;left:calc(50% + 6px);background:var(--bad);color:#fff;border-radius:99px;font-size:10px;padding:0 5px;min-width:16px}
|
|
27
|
+
.badge.dot{min-width:0;width:8px;height:8px;padding:0;top:7px;left:calc(50% + 8px)}
|
|
28
|
+
nav button.attn{--hi:var(--acc)}nav button.attn-bad{--hi:var(--bad)}nav button.attn-warn{--hi:var(--warn)}nav button.attn-ok{--hi:var(--ok)}
|
|
29
|
+
nav button.attn:not(.on){color:var(--hi)}nav button.attn .badge{background:var(--hi);color:#fff}nav button.attn-warn .badge{color:#1a1206}
|
|
30
|
+
nav button.attn:not(.on)::before{content:"";position:absolute;left:50%;top:6px;width:34px;height:34px;margin-left:-17px;border-radius:50%;background:radial-gradient(circle,color-mix(in srgb,var(--hi) 30%,transparent),transparent 70%);animation:navhi 2.4s ease-in-out infinite;pointer-events:none}
|
|
31
|
+
nav button.attn:not(.on) .emo{opacity:1;filter:none}
|
|
32
|
+
@keyframes navhi{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1.1)}}
|
|
27
33
|
.big{font-size:34px;font-weight:700;letter-spacing:-.5px;margin:6px 0 2px}
|
|
28
34
|
.mut{color:var(--mut)}.sm{font-size:12px}
|
|
29
35
|
.row{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--surf);border-radius:12px;margin-top:8px}
|
|
@@ -170,6 +176,16 @@ input,select{transition:border-color .2s ease,box-shadow .25s ease}input:focus,s
|
|
|
170
176
|
.aist{margin:0 0 4px;padding-left:18px;font-size:13px;line-height:1.55}.aist li{margin:5px 0}
|
|
171
177
|
.aidlg code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.88em;color:var(--acc);overflow-wrap:anywhere}
|
|
172
178
|
.kbd{font-family:ui-monospace,monospace;font-size:.85em;background:var(--surf2);border:1px solid var(--line);border-radius:6px;padding:1px 6px}
|
|
179
|
+
.tmdlg{max-width:560px}.tmdlg h2{text-align:center}.tmdlg .ailead{text-align:center}
|
|
180
|
+
.tmopts{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:6px 0 12px}@media(max-width:480px){.tmopts{grid-template-columns:1fr}}
|
|
181
|
+
.tmopt{display:flex;flex-direction:column;gap:6px;text-align:left;background:var(--surf);border:1px solid var(--line);border-radius:16px;padding:14px;color:var(--tx);font:inherit;cursor:pointer;animation:tk-rise .5s var(--ease) both;animation-delay:calc(var(--i,0)*90ms + 120ms);transition:border-color .2s ease,transform .25s var(--ease),box-shadow .25s ease}
|
|
182
|
+
.tmopt:hover,.tmopt:focus-visible{border-color:var(--acc);transform:translateY(-2px);box-shadow:0 14px 34px -18px rgba(var(--glow),.55)}.tmopt b{font-size:15.5px}.tmopt small{color:var(--mut);font-size:12.5px;line-height:1.45}.tmopt .botcta{margin-top:auto}
|
|
183
|
+
.tmico{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:12px;flex:none}.tmico svg{width:21px;height:21px}.tmico.sm{width:32px;height:32px;border-radius:10px}.tmico.sm svg{width:18px;height:18px}
|
|
184
|
+
.tmai{background:color-mix(in srgb,#d97757 18%,transparent);color:#d97757}.tmpy{background:color-mix(in srgb,var(--acc) 16%,transparent);color:var(--acc)}
|
|
185
|
+
.pycard{background:var(--surf);border:1px solid color-mix(in srgb,var(--acc) 40%,var(--line));border-radius:14px;padding:12px;margin:12px 0 4px}.pyct{display:flex;align-items:center;gap:10px}.pyct>div{flex:1}
|
|
186
|
+
.pystep{display:flex;align-items:center;gap:8px;margin:16px 0 4px}.pystep b{font-size:14px}.pyn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:color-mix(in srgb,var(--acc) 18%,transparent);color:var(--acc);font-size:12px;font-weight:700}
|
|
187
|
+
.pymore{margin:2px 0 6px}.pymore summary{cursor:pointer;font-size:12.5px;color:var(--mut)}.pymore summary:hover{color:var(--tx)}
|
|
188
|
+
.tmlater{padding:4px 10px 0}.tmseg{margin:0}.tmseg .bsb{padding:5px 12px}
|
|
173
189
|
.aicmd{display:flex;gap:8px;align-items:flex-start;background:#08090c;border:1px solid var(--line);border-radius:12px;padding:9px 9px 9px 13px;margin:8px 0}
|
|
174
190
|
.aicmd pre{flex:1;min-width:0;margin:0;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:#cdd6e4;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
175
191
|
.aicp{padding:6px 11px;font-size:12.5px;border-radius:9px}
|
|
@@ -230,6 +246,24 @@ input,select{transition:border-color .2s ease,box-shadow .25s ease}input:focus,s
|
|
|
230
246
|
.tl{width:100%;height:100%;border-radius:50%;background:var(--surf2);display:flex;align-items:center;justify-content:center;font-size:10.5px;font-weight:700;color:var(--mut);letter-spacing:-.02em}
|
|
231
247
|
.rowc{cursor:pointer}.rowc:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
|
|
232
248
|
.hfoot{margin-top:8px;font-size:12px;color:var(--mut);text-align:center}
|
|
249
|
+
.botc{background:var(--surf);border:1px solid var(--line);border-radius:14px;padding:12px;margin-top:8px}.botct{display:flex;align-items:flex-start;gap:8px;justify-content:space-between}.botpill{white-space:nowrap}.botpill.ok{background:rgba(60,207,145,.15);color:var(--ok)}.botpill.warn{background:rgba(245,184,74,.15);color:var(--warn)}.botpill.bad{background:rgba(255,107,107,.15);color:var(--bad)}
|
|
250
|
+
.botstats{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:10px}.botstats div{background:var(--card);border-radius:10px;padding:6px 8px;min-width:0}.botstats small{display:block;color:var(--mut);font-size:11px}.botstats b{font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
|
|
251
|
+
.botcat{display:grid;grid-template-columns:1fr 1fr;grid-auto-flow:row dense;gap:8px}.botlim{font-style:normal;color:var(--mut);opacity:.75;font-size:11px;margin-left:4px;white-space:nowrap}.botf input.botcap{animation:botcap .5s ease}@keyframes botcap{0%,100%{border-color:var(--line)}30%{border-color:var(--acc);box-shadow:0 0 0 3px rgba(var(--glow),.25)}}.botwrap{grid-column:1/-1;display:grid;grid-template-rows:1fr}.botin{min-height:0}.botin>.botform{margin:0}.botwrap.drop{animation:botopen .42s var(--ease) both}.botwrap.drop .botform{animation:botslide .42s var(--ease) both}.botwrap.closing{animation:botshut .24s ease-in both}.botwrap.drop .botin,.botwrap.closing .botin{overflow:hidden}
|
|
252
|
+
@keyframes botopen{from{grid-template-rows:0fr}to{grid-template-rows:1fr}}@keyframes botslide{from{opacity:0;transform:translateY(-14px) scale(.98)}to{opacity:1;transform:none}}@keyframes botshut{from{grid-template-rows:1fr;opacity:1}to{grid-template-rows:0fr;opacity:0}}
|
|
253
|
+
nav button .emo{display:block;margin:0 auto 3px;width:20px;height:20px;font-size:17px;line-height:20px;text-align:center;opacity:.75;filter:grayscale(.35);transition:transform .45s var(--ease),opacity .3s,filter .3s}nav button.on .emo{opacity:1;filter:none;transform:translateY(-2px) scale(1.1)}.bottpl{text-align:left;background:var(--surf);border:1px solid var(--line);border-radius:12px;padding:10px;color:var(--tx);font:inherit;cursor:pointer;display:flex;flex-direction:column;gap:4px}.bottpl small{color:var(--mut);font-size:12px;line-height:1.35}.bottpl.on,.bottpl:hover{border-color:var(--acc)}
|
|
254
|
+
.tplh{display:flex;align-items:flex-start;justify-content:space-between;gap:6px}.tplh b{min-width:0}
|
|
255
|
+
.botcta{margin-top:auto;align-self:flex-start;display:inline-flex;align-items:center;gap:6px;padding:6px 11px;border-radius:99px;border:0;background:color-mix(in srgb,var(--acc) 15%,transparent);color:var(--acc);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;transition:background .2s ease}
|
|
256
|
+
.botcta svg{transition:transform .25s var(--ease)}.bottpl:hover .botcta,.botcta:hover{background:color-mix(in srgb,var(--acc) 24%,transparent)}.bottpl:hover .botcta svg,.botcta:hover svg{transform:translateX(3px)}
|
|
257
|
+
.botcta.g{background:transparent;color:var(--mut);padding-left:6px;padding-right:6px}.botcta.g:hover{background:var(--surf2);color:var(--tx)}
|
|
258
|
+
.bottpl>.botcta{margin-top:auto;padding-top:6px}.bottpl>.boardl{margin-bottom:6px}
|
|
259
|
+
.bottpl.has{cursor:default;border-color:color-mix(in srgb,var(--ok) 45%,var(--line))}.bottpl.has.err{border-color:color-mix(in srgb,var(--bad) 55%,var(--line))}.bottpl.has.on{border-color:var(--acc)}
|
|
260
|
+
.tplbtns{display:flex;flex-wrap:wrap;gap:4px;margin-top:auto;padding-top:6px}.tplbtns .botcta{margin-top:0}
|
|
261
|
+
.botc.botflash{animation:botflash 1.6s ease}@keyframes botflash{0%,60%{border-color:var(--acc);box-shadow:0 0 0 3px color-mix(in srgb,var(--acc) 30%,transparent)}100%{border-color:var(--line);box-shadow:none}}
|
|
262
|
+
.botgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.botf{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--mut)}.botf input,.botf select{background:var(--card);border:1px solid var(--line);color:var(--tx);border-radius:10px;padding:8px;font:inherit;font-size:13px;min-width:0}
|
|
263
|
+
.botshare{display:flex;gap:8px;align-items:flex-start;font-size:12px;color:var(--mut);margin-top:14px;line-height:1.4}.botshare input{width:auto;flex:0 0 auto;margin:2px 0 0}.addt .crow2 select{flex:0 0 104px;width:104px}.addt .crow2 input{flex:1 1 auto;min-width:0;width:auto}@media(max-width:420px){.botcat,.botgrid{grid-template-columns:1fr}.botstats{grid-template-columns:1fr 1fr}}
|
|
264
|
+
.tlogo{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block}.tbadge{font-size:10px;padding:1px 6px;vertical-align:1px;margin-left:4px}
|
|
265
|
+
.atlist{display:flex;flex-direction:column;gap:4px;margin-top:8px;max-height:320px;overflow-y:auto}.atrow{display:flex;align-items:center;gap:10px;text-align:left;background:var(--surf);border:1px solid var(--line);border-radius:12px;padding:8px 10px;color:var(--tx);font:inherit;cursor:pointer}.atrow:hover{border-color:var(--acc)}.atn{min-width:0;display:flex;flex-direction:column}.atn small{color:var(--mut);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
266
|
+
.atw{margin-top:10px;padding:10px;border-radius:10px;background:rgba(255,107,107,.08);border:1px solid rgba(255,107,107,.35);color:var(--bad);font-size:13px}.atw ul,.atchk ul{margin:6px 0 0;padding-left:18px}.atw li{margin:3px 0;color:var(--tx)}.atwarn{border-color:rgba(255,107,107,.45)}
|
|
233
267
|
.crow2{display:flex;gap:6px;margin-top:8px}.crow2 select,.crow2 input{background:var(--card);border:1px solid var(--line);color:var(--tx);border-radius:10px;padding:8px;font:inherit;font-size:13px}.crow2 input{flex:1;min-width:0}.crow2 .b{padding:8px 14px}
|
|
234
268
|
.chdlg{max-width:560px}
|
|
235
269
|
.chh{display:flex;align-items:center;gap:10px}.chh h2{margin:0;font-size:18px}
|
|
@@ -284,11 +318,12 @@ var COIN=${COIN_JSON};
|
|
|
284
318
|
var AIIC=${AI_ICON_JSON},AIO=null,AIPW="",AIMSG={},AIOPEN={},AIBUSY=null;
|
|
285
319
|
function aiSvg(k){var i=AIIC[k];return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor"'+(i.rule?' fill-rule="'+i.rule+'"':'')+' d="'+i.d+'"/></svg>'}
|
|
286
320
|
var AIMETA={claude:["claude","Claude"],"claude-code":["claude","Claude Code"],cursor:["cursor","Cursor"],vscode:["copilot","VS Code"],codex:["terminal","Codex"],gemini:["gemini","Gemini CLI"]};
|
|
287
|
-
function aiBtn(){var on=((S.connect||{}).apps||[]).filter(function(a){return a.added});
|
|
321
|
+
function aiBtn(){var on=((S.connect||{}).apps||[]).filter(function(a){return a.added}),rm=(S.connect||{}).remote;
|
|
322
|
+
if(rm&&rm.on)on=[{id:"claude"}];
|
|
288
323
|
if(!on.length)return '<button class="b aib" onclick="openAI()"><span class="aiic">'+aiSvg("claude")+aiSvg("cursor")+aiSvg("gemini")+'</span>Connect your AI</button>';
|
|
289
324
|
var icons=[],names=[];on.forEach(function(a){var m=AIMETA[a.id];if(!m)return;names.push(m[1]);if(icons.indexOf(m[0])<0)icons.push(m[0])});
|
|
290
325
|
var wait=(S.rules||[]).filter(function(r){return r.status==="proposed"}).length;
|
|
291
|
-
return '<div class="aiconn"><button class="aich" onclick="openAI()" title="Manage connected AI apps"><span class="aistk">'+icons.slice(0,4).map(function(k){return '<i class="ail-'+k+'">'+aiSvg(k)+'</i>'}).join("")+'</span><span class="aichn"><b>'+esc(names.join(" + "))+'</b><small
|
|
326
|
+
return '<div class="aiconn"><button class="aich" onclick="openAI()" title="Manage connected AI apps"><span class="aistk">'+icons.slice(0,4).map(function(k){return '<i class="ail-'+k+'">'+aiSvg(k)+'</i>'}).join("")+'</span><span class="aichn"><b>'+esc(rm&&rm.on?"Your AI apps":names.join(" + "))+'</b><small>'+(rm&&rm.on&&!rm.online?'<span class="warn">●</span> Waiting for the wallet':'<span class="ok">●</span> Connected')+'</small></span></button>'+
|
|
292
327
|
'<button class="b aiap" onclick="goAuto()"><svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><path d="M13 2L4 14h7l-1 8 9-12h-7z" fill="currentColor"/></svg>Autopilot'+(wait?'<span class="aiwt">'+wait+'</span>':'')+'</button></div>'}
|
|
293
328
|
function goAuto(){go("autopilot");setTimeout(function(){var t=document.getElementById("chin");if(t&&!t.disabled)t.focus()},120)}
|
|
294
329
|
function aiCfg(){var c=S.connect||{};return c.launch||{command:"npx",args:["-y","tollkit-wallet","mcp"],env:{TOLLKIT_WALLET_PASSWORD_FILE:c.password_file||""}}}
|
|
@@ -316,7 +351,34 @@ else if(st.added){line='<span class="warn">Needs an update</span>';btn='<button
|
|
|
316
351
|
else{line='Found on this computer';btn='<button class="b aiadd" data-act="add" data-id="'+x.id+'"'+(busy?" disabled":"")+'>'+(busy?"Adding…":"Add")+'</button>'}
|
|
317
352
|
return '<div class="airow" style="--i:'+i+'"><div class="airt">'+aiSvg(x.icon)+'<div class="ainm"><b>'+esc(x.name)+'</b><small>'+line+'</small></div>'+btn+'</div>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')+'<button class="aihand" data-hand="'+x.id+'">'+(AIOPEN[x.id]?"Hide steps":"Do it by hand")+'</button>'+(AIOPEN[x.id]?'<div class="aihb">'+x.hand()+'</div>':'')+'</div>'}
|
|
318
353
|
function svgOk(){return '<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true" style="vertical-align:-2px;margin-right:4px"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></svg>'}
|
|
354
|
+
// Adding a connector by its address. Steps checked against each app's docs on 2026-10-14: support.claude.com/en/articles/11175166,
|
|
355
|
+
// developers.openai.com/api/docs/guides/developer-mode, code.claude.com/docs/en/mcp-quickstart, cursor.com/docs/mcp,
|
|
356
|
+
// code.visualstudio.com/docs/copilot/reference/mcp-configuration, developers.openai.com/codex/mcp, geminicli.com/docs/tools/mcp-server.
|
|
357
|
+
var AIREMOTE=[
|
|
358
|
+
{id:"claude",name:"Claude",sub:"Web, desktop and mobile",icon:"claude",hand:function(u){return '<ol class="aist"><li>Open <a href="https://claude.ai/customize/connectors" target="_blank" rel="noopener">claude.ai/customize/connectors</a>, click <b>+</b>, then <b>Add custom connector</b>.</li><li>Paste your address and click <b>Add</b>.</li></ol><p class="aismall">Free plans can add one custom connector. On Team and Enterprise, an Owner adds it (Add → Custom → Web).</p>'}},
|
|
359
|
+
{id:"chatgpt",name:"ChatGPT",sub:"Developer mode",icon:"terminal",hand:function(u){return '<ol class="aist"><li>In ChatGPT on the web: <b>Settings → Apps → Advanced settings</b>, turn on <b>Developer mode</b>.</li><li>Click <b>Create app</b>, paste your address, choose <b>No authentication</b>, and create it.</li></ol><p class="aismall">Developer mode depends on your ChatGPT plan; OpenAI’s help pages list which.</p>'}},
|
|
360
|
+
{id:"claude-code",name:"Claude Code",sub:"Terminal",icon:"claude",hand:function(u){return '<p class="aip">Paste into your terminal:</p>'+aiCode("ar-cc","claude mcp add --transport http --scope user tollkit-wallet "+shq(u))}},
|
|
361
|
+
{id:"cursor",name:"Cursor",sub:"Code editor",icon:"cursor",hand:function(u){return '<p class="aip">Add this to <span class="kbd">~/.cursor/mcp.json</span>:</p>'+aiCode("ar-cu",JSON.stringify({mcpServers:{"tollkit-wallet":{url:u}}},null,2))}},
|
|
362
|
+
{id:"vscode",name:"VS Code",sub:"With GitHub Copilot",icon:"copilot",hand:function(u){return '<p class="aip">Run <b>MCP: Add Server</b>, choose <b>HTTP</b> and paste your address. Or add to <span class="kbd">mcp.json</span>:</p>'+aiCode("ar-vs",JSON.stringify({servers:{"tollkit-wallet":{type:"http",url:u}}},null,2))}},
|
|
363
|
+
{id:"codex",name:"Codex",sub:"OpenAI’s terminal agent",icon:"terminal",hand:function(u){return '<p class="aip">Add to <span class="kbd">~/.codex/config.toml</span>:</p>'+aiCode("ar-cx",'[mcp_servers.tollkit_wallet]\nurl = "'+u+'"')}},
|
|
364
|
+
{id:"gemini",name:"Gemini CLI",sub:"Terminal",icon:"gemini",hand:function(u){return '<p class="aip">Paste into your terminal:</p>'+aiCode("ar-gm","gemini mcp add -s user --transport http tollkit-wallet "+shq(u))}}
|
|
365
|
+
];
|
|
366
|
+
function aiRemote(r){var h='<h2>Connect your AI</h2><p class="ailead">Let Claude, ChatGPT, Cursor or another AI app use this wallet. It follows your limits, can’t withdraw or see your keys, and any rules it suggests wait in Autopilot for you.</p>',m=AIMSG.remote;
|
|
367
|
+
if(!r.on)return h+'<label class="ailbl" for="aipw">Wallet password</label><input id="aipw" class="aiin" type="password" autocomplete="current-password" placeholder="Needed to turn this on" value="'+esc(AIPW)+'">'+
|
|
368
|
+
'<button class="b aigoap" data-ract="on"'+(AIBUSY?" disabled":"")+'>'+(AIBUSY?"Making it…":"Make my connector address")+'</button>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')+
|
|
369
|
+
'<p class="aismall">You get a private web address to add to your AI app. Tollkit’s server passes the app’s requests to this wallet while Chrome is open and the wallet is unlocked. Your keys stay here.</p>';
|
|
370
|
+
h+='<label class="ailbl">Your connector address</label>'+aiCode("ai-url",r.url)+
|
|
371
|
+
'<p class="aismall"><span class="'+(r.online?"ok":"warn")+'">●</span> '+(r.online?"The wallet is reachable.":"Waiting for the wallet to check in…")+' Anyone with this address can use the wallet within your limits, so keep it private.</p>'+
|
|
372
|
+
'<div class="ailist">'+AIREMOTE.map(function(x,i){return '<div class="airow" style="--i:'+i+'"><div class="airt">'+aiSvg(x.icon)+'<div class="ainm"><b>'+esc(x.name)+'</b><small>'+esc(x.sub)+'</small></div></div><button class="aihand" data-hand="r-'+x.id+'">'+(AIOPEN["r-"+x.id]?"Hide steps":"How to add it")+'</button>'+(AIOPEN["r-"+x.id]?'<div class="aihb">'+x.hand(r.url)+'</div>':'')+'</div>'}).join("")+'</div>'+
|
|
373
|
+
'<div class="aidone"><b>Check it worked.</b> Ask your AI: <b>“What’s in my Tollkit wallet?”</b></div>'+
|
|
374
|
+
'<label class="ailbl" for="aipw">Wallet password (for a new address)</label><input id="aipw" class="aiin" type="password" autocomplete="current-password" value="'+esc(AIPW)+'">'+
|
|
375
|
+
'<div class="btns" style="margin-top:10px"><button class="b g" data-ract="new"'+(AIBUSY?" disabled":"")+'>New address</button><button class="b no" data-ract="off"'+(AIBUSY?" disabled":"")+'>Turn off</button></div>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')+
|
|
376
|
+
'<p class="aismall">A new address stops the old one. Turning off stops every app.</p>';
|
|
377
|
+
return h}
|
|
378
|
+
function aiRemoteDo(act){if(act!=="off"&&!AIPW){AIMSG.remote=[0,"Type your wallet password first."];aiRender();document.getElementById("aipw").focus();return}
|
|
379
|
+
AIBUSY="remote";AIMSG.remote=null;aiRender();api("/connect/remote",{password:AIPW,action:act}).then(function(){AIPW="";AIMSG.remote=act==="off"?[1,"Turned off. No app can reach the wallet now."]:act==="new"?[1,"New address made. Add it to your apps again."]:null;return refresh()}).catch(function(e){AIMSG.remote=[0,e.message]}).then(function(){AIBUSY=null;aiRender()})}
|
|
319
380
|
function aiRender(){if(!AIO)return;var c=S.connect||{},foc=document.activeElement&&document.activeElement.id==="aipw";
|
|
381
|
+
if(c.remote){var sc0=AIO.querySelector(".aidlg").scrollTop;AIO.querySelector(".aibody").innerHTML=aiRemote(c.remote);AIO.querySelector(".aidlg").scrollTop=sc0;var pw0=document.getElementById("aipw");if(pw0){pw0.oninput=function(){AIPW=pw0.value};if(foc)pw0.focus()}return}
|
|
320
382
|
var h='<h2>Connect your AI</h2><p class="ailead">Let Claude, Cursor or another AI app use this wallet. It follows your limits, can’t withdraw or see your keys, and any rules it suggests wait in Autopilot for you.</p>'+
|
|
321
383
|
'<label class="ailbl" for="aipw">Wallet password</label><input id="aipw" class="aiin" type="password" autocomplete="current-password" placeholder="Needed to add an app" value="'+esc(AIPW)+'">'+
|
|
322
384
|
'<p class="aismall">'+(c.ready?'Your AI apps unlock the wallet with a saved copy of this password, readable only by your account on this computer.':'Adding an app saves a copy of this password on this computer, readable only by your account, so the app can unlock the wallet. Anyone who can read it and your wallet folder could spend within your limits.')+'</p>'+
|
|
@@ -327,7 +389,7 @@ function openAI(){if(!AIO){AIO=document.createElement("div");AIO.className="aio"
|
|
|
327
389
|
function closeAI(){if(AIO){AIO.remove();AIO=null;AIPW="";AIMSG={}}}
|
|
328
390
|
function aiDo(act,id){if(act!=="remove"&&!AIPW){AIMSG[id]=[0,"Type your wallet password first."];aiRender();document.getElementById("aipw").focus();return}
|
|
329
391
|
AIBUSY=id;AIMSG[id]=null;aiRender();api("/connect",{password:AIPW,action:act,app:id}).then(function(r){AIMSG[id]=[1,r.message];return refresh()}).catch(function(e){AIMSG[id]=[0,e.message]}).then(function(){AIBUSY=null;aiRender()})}
|
|
330
|
-
function aiClick(e){var t=e.target.closest("button,a");if(!t)return;if(t.classList.contains("aix"))closeAI();else if(t.hasAttribute("data-act"))aiDo(t.getAttribute("data-act"),t.getAttribute("data-id"));else if(t.hasAttribute("data-hand")){var k=t.getAttribute("data-hand");AIOPEN[k]=!AIOPEN[k];aiRender()}else if(t.hasAttribute("data-copy")){var el=document.getElementById(t.getAttribute("data-copy")),v=el?el.textContent:"",done=function(){t.textContent="Copied";setTimeout(function(){t.textContent="Copy"},1500)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(v).then(done,function(){fallback(v);done()});else{fallback(v);done()}}}
|
|
392
|
+
function aiClick(e){var t=e.target.closest("button,a");if(!t)return;if(t.classList.contains("aix"))closeAI();else if(t.hasAttribute("data-ract"))aiRemoteDo(t.getAttribute("data-ract"));else if(t.hasAttribute("data-act"))aiDo(t.getAttribute("data-act"),t.getAttribute("data-id"));else if(t.hasAttribute("data-hand")){var k=t.getAttribute("data-hand");AIOPEN[k]=!AIOPEN[k];aiRender()}else if(t.hasAttribute("data-copy")){var el=document.getElementById(t.getAttribute("data-copy")),v=el?el.textContent:"",done=function(){t.textContent="Copied";setTimeout(function(){t.textContent="Copy"},1500)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(v).then(done,function(){fallback(v);done()});else{fallback(v);done()}}}
|
|
331
393
|
document.addEventListener("keydown",function(e){if(AIO&&e.key==="Escape")closeAI()});
|
|
332
394
|
var BUY={o:null,chain:null,asset:"USDC",amt:"50",custom:"",test:false,err:null,busy:false,done:null};
|
|
333
395
|
var BUYA={base:["USDC","ETH"],ethereum:["USDC","ETH"],solana:["USDC","SOL"]};
|
|
@@ -460,11 +522,30 @@ var CHT={o:null,coin:"",sym:"",chain:"",name:"",range:"1D",data:null,loading:fal
|
|
|
460
522
|
function coinOf(chain,sym){var c=(S.coins||{})[chain]||{};return c[sym]||c[String(sym).toUpperCase()]||""}
|
|
461
523
|
function rowAttrs(coin,sym,chain,name){return coin?' rowc" tabindex="0" role="button" aria-label="'+esc((name||sym)+" price chart")+'" data-chart="'+esc(coin)+'" data-sym="'+esc(sym)+'" data-chain="'+esc(chain)+'" data-name="'+esc(name||sym)+'"':'"'}
|
|
462
524
|
function holdRows(){var H=S.holdings;if(!H)return {rows:"",tot:0,chg:0};var rows="",tot=0,chg=0;(H.tokens||[]).forEach(function(t){var a=Number(t.amount),val=t.usd||0;tot+=val;if(typeof t.change_24h==="number")chg+=val-val/(1+t.change_24h);
|
|
463
|
-
rows+='<div class="row'+rowAttrs(t.coin,t.symbol,t.chain,t.name)+'>'+tokIcon(t.symbol,t.chain)+'<div style="min-width:0"><div class="tname">'+esc(t.name||t.symbol)+'</div><div class="sm">'+(typeof t.change_24h==="number"?'<span class="'+(t.change_24h>=0?"ok":"bad")+'">'+(t.change_24h>=0?"+":"")+(t.change_24h*100).toFixed(2)+'%</span><span class="mut"> · '+esc(CHAIN_NAMES[t.chain]||t.chain)+'</span>':'<span class="mut">'+esc(CHAIN_NAMES[t.chain]||t.chain)+'</span>')+'</div></div><div class="r"><div class="usdv">'+fmtUsd(val)+'</div><div class="sm mut">'+esc(fmtAmt(a))+' '+esc(t.symbol)+'</div></div></div>'});
|
|
525
|
+
rows+='<div class="row'+rowAttrs(t.coin,t.symbol,t.chain,t.name)+'>'+tokIcon(t.symbol,t.chain,t.icon)+'<div style="min-width:0"><div class="tname">'+esc(t.name||t.symbol)+(t.trust==="unlisted"?' <span class="chip warn tbadge" title="Not on the wallet’s token list. Check it before you trade it.">Unverified</span>':'')+'</div><div class="sm">'+(typeof t.change_24h==="number"?'<span class="'+(t.change_24h>=0?"ok":"bad")+'">'+(t.change_24h>=0?"+":"")+(t.change_24h*100).toFixed(2)+'%</span><span class="mut"> · '+esc(CHAIN_NAMES[t.chain]||t.chain)+'</span>':'<span class="mut">'+esc(CHAIN_NAMES[t.chain]||t.chain)+'</span>')+'</div></div><div class="r"><div class="usdv">'+fmtUsd(val)+'</div><div class="sm mut">'+esc(fmtAmt(a))+' '+esc(t.symbol)+'</div></div></div>'});
|
|
464
526
|
return {rows:rows,tot:tot,chg:chg}}
|
|
465
|
-
function holdFoot(){var H=S.holdings;if(!H)return "";return '<div class="hfoot">'+(H.hidden?'<span>'+H.hidden+' token'+(H.hidden>1?"s":"")+' without a price hidden</span> · ':'')+'<button class="aihand" style="padding:0" onclick="addTok()">
|
|
466
|
-
var ADDT=false,ADDM=null
|
|
467
|
-
function
|
|
527
|
+
function holdFoot(){var H=S.holdings;if(!H)return "";return '<div class="hfoot">'+(H.hidden?'<span>'+H.hidden+' token'+(H.hidden>1?"s":"")+' without a price hidden</span> · ':'')+'<button class="aihand" style="padding:0" onclick="addTok()">'+(ADDT?"Close":"Add a token")+'</button></div>'+(ADDT?addTokSheet():(ADDM&&ADDM[0]?'<div class="msg okk">'+esc(ADDM[1])+'</div>':''))}
|
|
528
|
+
var ADDT=false,ADDM=null,AT={chain:"base",q:"",res:null,chk:null,busy:false,timer:null,confirm:false,gen:0};
|
|
529
|
+
function addTok(){ADDT=!ADDT;ADDM=null;AT.res=null;AT.chk=null;AT.q="";AT.confirm=false;render();if(ADDT){setTimeout(function(){var q=document.getElementById("at_q");if(q)q.focus();atSearch()},30)}}
|
|
530
|
+
function addTokSheet(){return '<div class="row addt" style="display:block"><div class="sm mut">Search by name or symbol, or paste a contract or mint address. Every token gets Tollkit’s scam check before it\'s added.</div><div class="crow2"><select id="at_chain" onchange="AT.chain=this.value;AT.chk=null;atSearch()">'+[["base","Base"],["ethereum","Ethereum"],["solana","Solana"]].map(function(o){return '<option value="'+o[0]+'"'+(AT.chain===o[0]?" selected":"")+'>'+o[1]+'</option>'}).join("")+'</select><input id="at_q" placeholder="USDC, Bonk, 0x…" autocomplete="off" spellcheck="false" value="'+esc(AT.q)+'" oninput="AT.q=this.value;clearTimeout(AT.timer);AT.timer=setTimeout(atSearch,300)"></div><div id="at_res">'+atResHtml()+'</div>'+(ADDM?'<div class="msg '+(ADDM[0]?"okk":"err")+'">'+esc(ADDM[1])+'</div>':'')+'</div>'}
|
|
531
|
+
function atBadge(t){return t.trust==="core"?'<span class="chip ok tbadge">Built in</span>':t.trust==="listed"?'<span class="chip tbadge">'+(t.chain==="solana"?"Jupiter verified":"Listed")+'</span>':'<span class="chip warn tbadge">Not verified</span>'}
|
|
532
|
+
function atResHtml(){if(AT.chk)return atCheckHtml(AT.chk);if(AT.busy)return '<div class="sm mut" style="padding:8px 2px">Searching…</div>';if(!AT.res)return "";var q=AT.q.trim(),isAddr=AT.chain==="solana"?/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(q):/^0x[0-9a-fA-F]{40}$/.test(q);
|
|
533
|
+
var h=AT.res.map(function(t,i){return '<button class="atrow" data-ati="'+i+'">'+tokIcon(t.symbol,t.chain,t.logo)+'<span class="atn"><b>'+esc(t.symbol)+'</b> '+atBadge(t)+'<small>'+esc(t.name)+' · '+esc(short(t.address))+'</small></span></button>'}).join("");
|
|
534
|
+
if(isAddr&&!AT.res.some(function(t){return t.address.toLowerCase()===q.toLowerCase()}))h='<button class="atrow" data-atq="1"><div class="ic tok"><span class="tl">?</span></div><span class="atn"><b>Check this address</b><small>'+esc(short(q))+'</small></span></button>'+h;
|
|
535
|
+
if(!h)h='<div class="sm mut" style="padding:8px 2px">No match. Paste the token’s address to check it.</div>';
|
|
536
|
+
return '<div class="atlist">'+h+'</div>'+(AT.chain==="solana"?'<div class="sm mut" style="text-align:right;margin-top:4px">Powered by Jupiter</div>':'<div class="sm mut" style="text-align:right;margin-top:4px">Superchain and Uniswap token lists</div>')}
|
|
537
|
+
function atPaint(){var el=document.getElementById("at_res");if(el)el.innerHTML=atResHtml();else render()}
|
|
538
|
+
function atSearch(){var c=AT.chain,q=AT.q,g=++AT.gen;AT.chk=null;AT.busy=true;atPaint();api("/tokens/search",{chain:c,q:q}).then(function(r){if(g!==AT.gen)return;AT.res=r.tokens||[];AT.busy=false;atPaint()}).catch(function(e){AT.busy=false;AT.res=[];ADDM=[0,e.message];atPaint()})}
|
|
539
|
+
function atCheck(addr){clearTimeout(AT.timer);var g=++AT.gen;AT.busy=false;ADDM=null;AT.confirm=false;AT.chk={loading:true,address:addr};atPaint();api("/tokens/check",{chain:AT.chain,address:addr}).then(function(r){if(g!==AT.gen)return;AT.chk=r.check;atPaint()}).catch(function(e){AT.chk=null;ADDM=[0,e.message];render()})}
|
|
540
|
+
function atCheckHtml(c){if(c.loading)return '<div class="ap" style="margin-top:8px"><div class="sm mut">Running Tollkit’s token check…</div></div>';var w=c.warnings||[],p=c.powers||[],f=c.facts||[];
|
|
541
|
+
return '<div class="ap atchk'+(w.length?" atwarn":"")+'" style="margin-top:8px"><div style="display:flex;align-items:center;gap:10px">'+tokIcon(c.symbol||"?",c.chain,c.logo)+'<div style="min-width:0"><b>'+esc(c.symbol||"Unknown")+'</b> '+atBadge(c)+'<div class="sm mut">'+esc(c.name||"")+' · '+esc(short(c.address))+'</div></div></div>'+
|
|
542
|
+
(w.length?'<div class="atw"><b>'+w.length+' warning'+(w.length>1?"s":"")+'</b><ul>'+w.map(function(x){return '<li>'+esc(x)+'</li>'}).join("")+'</ul></div>':'<div class="sm ok" style="margin-top:8px">No warnings from the check. That doesn’t make a token safe.</div>')+
|
|
543
|
+
(p.length?'<div class="sm" style="margin-top:8px"><b>What the issuer can do</b><ul>'+p.map(function(x){return '<li>'+esc(x)+'</li>'}).join("")+'</ul></div>':'')+
|
|
544
|
+
(f.length?'<div class="sm mut" style="margin-top:6px">'+f.map(esc).join(" ")+'</div>':'')+
|
|
545
|
+
'<div class="btns"><button class="b g" onclick="AT.chk=null;atPaint()">Back</button>'+(w.length?(AT.confirm?'<button class="b no" onclick="atAdd(true)">Yes, add it anyway</button>':'<button class="b no" onclick="AT.confirm=true;atPaint()">Add anyway</button>'):'<button class="b ok" onclick="atAdd(false)">Add</button>')+'</div>'+(w.length&&AT.confirm?'<div class="sm bad" style="margin-top:6px">Only add it if you know where it came from. Many scam tokens copy real names.</div>':'')+'</div>'}
|
|
546
|
+
function atAdd(confirm){var c=AT.chk;api("/tokens/add",{chain:c.chain,address:c.address,confirm:!!confirm}).then(function(r){if(r.needs_confirm){AT.chk=r.check;AT.confirm=true;atPaint();return}ADDT=false;AT.chk=null;ADDM=[1,"Added "+r.token.symbol+"."];refresh().then(function(){render()})}).catch(function(e){ADDM=[0,e.message];render()})}
|
|
547
|
+
document.addEventListener("error",function(e){var t=e.target;if(t&&t.classList&&t.classList.contains("tlogo")){var sp=document.createElement("span");sp.className="tl";sp.textContent=t.getAttribute("data-tl")||"?";t.replaceWith(sp)}},true);
|
|
548
|
+
document.addEventListener("click",function(e){var b=e.target.closest&&e.target.closest("[data-ati],[data-atq]");if(!b)return;if(b.hasAttribute("data-atq"))atCheck(AT.q.trim());else{var t=AT.res[Number(b.getAttribute("data-ati"))];if(t)atCheck(t.address)}});
|
|
468
549
|
document.addEventListener("click",function(e){var r=e.target.closest&&e.target.closest("[data-chart]");if(r)openChart(r.getAttribute("data-chart"),r.getAttribute("data-sym"),r.getAttribute("data-chain"),r.getAttribute("data-name"))});
|
|
469
550
|
document.addEventListener("keydown",function(e){if(e.key==="Enter"&&document.activeElement&&document.activeElement.hasAttribute&&document.activeElement.hasAttribute("data-chart")){var r=document.activeElement;openChart(r.getAttribute("data-chart"),r.getAttribute("data-sym"),r.getAttribute("data-chain"),r.getAttribute("data-name"))}if(CHT.o&&e.key==="Escape")closeChart()});
|
|
470
551
|
function openChart(coin,sym,chain,name){CHT.coin=coin;CHT.sym=sym;CHT.chain=chain;CHT.name=name;CHT.data=null;CHT.err=null;CHT.table=false;CHT.hover=null;if(!CHT.o){CHT.o=document.createElement("div");CHT.o.className="aio";CHT.o.innerHTML='<div class="aidlg chdlg" role="dialog" aria-modal="true" aria-label="Price chart"><button class="aix" aria-label="Close">×</button><div class="aibody"></div></div>';CHT.o.addEventListener("mousedown",function(e){if(e.target===CHT.o)closeChart()});CHT.o.addEventListener("click",function(e){var t=e.target.closest("button");if(!t)return;if(t.classList.contains("aix"))closeChart();else if(t.hasAttribute("data-rg")){CHT.range=t.getAttribute("data-rg");loadChart()}else if(t.hasAttribute("data-tbl")){CHT.table=!CHT.table;drawChart()}});document.body.appendChild(CHT.o)}loadChart()}
|
|
@@ -522,7 +603,7 @@ var cards=(m.rules||[]).map(function(id){var r=(S.rules||[]).filter(function(x){
|
|
|
522
603
|
return '<div class="tc-cm tc-ai'+nw+(m.error?" tc-err":"")+'"><div class="tc-cav">'+aiSvg("claude")+'</div><div class="tc-cbw">'+(m.checkin?'<div class="tc-ctag">Check-in · '+tm(m.ts)+'</div>':'')+'<div class="tc-cb">'+fmtAi(m.text)+'</div>'+(cards?'<div class="tc-ccards">'+cards+'</div>':'')+'</div></div>'}
|
|
523
604
|
function svgClock(){return '<svg viewBox="0 0 24 24" width="13" height="13" aria-hidden="true"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 7v5l3 2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>'}
|
|
524
605
|
function chatBox(){var A=S.ai;if(!A)return "";var M=A.messages||[],busy=A.busy||CH.sending;
|
|
525
|
-
var head='<div class="tc-chd"><div class="tc-chn">'+aiSvg("claude")+'<div><b>'+esc(aiName())+'</b><small>'+(busy?'<span class="ok">Working…</span>':A.provider?'Your Claude, on this computer':'Not set up')+'</small></div></div>'+
|
|
606
|
+
var head='<div class="tc-chd"><div class="tc-chn">'+aiSvg("claude")+'<div><b>'+esc(aiName())+'</b><small>'+(busy?'<span class="ok">Working…</span>':A.provider?esc(A.provider.note||'Your Claude, on this computer'):'Not set up')+'</small></div></div>'+
|
|
526
607
|
'<div class="tc-chr"><label class="tc-chk" title="Let the AI review your rules on a schedule">'+svgClock()+'<select onchange="setCheckin(this.value)">'+[[0,"Check-ins off"],[1,"Every hour"],[4,"Every 4 hours"],[12,"Every 12 hours"],[24,"Daily"]].map(function(o){return '<option value="'+o[0]+'"'+(A.checkin.every_hours===o[0]?" selected":"")+'>'+o[1]+'</option>'}).join("")+'</select></label>'+(M.length?'<button class="b g tc-chx'+(CH.confirmNew?" tc-warn":"")+'" onclick="newChat()" title="Start over. Your rules stay on.">'+(CH.confirmNew?'Clear chat?':'<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20h4L19 9l-4-4L4 16z M14 6l4 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/></svg>New chat')+'</button>':'')+'</div></div>';
|
|
527
608
|
if(!A.provider)return '<div class="tc-chat">'+head+'<div class="tc-cempty"><b>Chat with your AI here</b><p>Install <b>Claude Code</b> on this computer and sign in once (run <code>claude</code> in Terminal). Then reopen this page. It uses your own Claude plan; the wallet never sees your Claude login.</p></div></div>';
|
|
528
609
|
var body=M.length?M.map(chatMsg).join(""):'<div class="tc-cempty"><b>What do you want your autopilot to do?</b><p>Say it in your own words. '+esc(aiName())+' checks prices and your balances, then suggests rules you can turn on with one tap.</p><div class="tc-cchips">'+CHIPS.map(function(c,i){return '<button class="tc-cchip" onclick="chatSend(CHIPS['+i+'])">'+esc(c)+'</button>'}).join("")+'</div></div>';
|
|
@@ -538,7 +619,7 @@ function chatPw(){api("/ai/password",{password:CH.pw}).then(function(){CH.pw="";
|
|
|
538
619
|
function setCheckin(h){api("/ai/checkin",{hours:Number(h)}).then(function(){flash=[1,Number(h)?"Check-ins on. "+aiName()+" will review your rules and suggest changes for you to approve.":"Check-ins off."];refresh()}).catch(function(e){flash=[0,e.message];render()})}
|
|
539
620
|
function newChat(){if(!CH.confirmNew){CH.confirmNew=true;LASTAP=null;render();clearTimeout(CH.cnT);CH.cnT=setTimeout(function(){CH.confirmNew=false;LASTAP=null;render()},4000);return}
|
|
540
621
|
clearTimeout(CH.cnT);CH.confirmNew=false;api("/ai/new",{}).then(function(){CH.n=-1;CH.top=null;flash=[1,"New chat started. Your rules are unchanged."];return refresh()}).catch(function(e){flash=[0,e.message];render()})}
|
|
541
|
-
function tokIcon(sym,chain){var k=String(sym||"").toUpperCase();if(k==="WETH")k="ETH";var svg=COIN.coin[k];return '<div class="ic tok">'+(svg||'<span class="tl">'+esc(k.slice(0,4))+'</span>')+(chain&&COIN.chain[chain]?'<span class="cb">'+COIN.chain[chain]+'</span>':"")+'</div>'}
|
|
622
|
+
function tokIcon(sym,chain,logo){var k=String(sym||"").toUpperCase();if(k==="WETH")k="ETH";var svg=COIN.coin[k];return '<div class="ic tok">'+(svg||(logo&&logo.indexOf("https:")===0?'<img class="tlogo" src="'+esc(logo)+'" alt="" loading="lazy" referrerpolicy="no-referrer" data-tl="'+esc(k.slice(0,4))+'">':'<span class="tl">'+esc(k.slice(0,4))+'</span>'))+(chain&&COIN.chain[chain]?'<span class="cb">'+COIN.chain[chain]+'</span>':"")+'</div>'}
|
|
542
623
|
function chainIcon(chain,extra){return '<div class="ic tok">'+(COIN.chain[chain]||esc(String(chain||"?")[0].toUpperCase()))+(extra&&COIN.chain[extra]?'<span class="cb">'+COIN.chain[extra]+'</span>':"")+'</div>'}
|
|
543
624
|
function kindIcon(e){if(e.kind==="stake")return tokIcon("SOL","solana");var m=/^[\d.,]+ ([A-Za-z]+)/.exec(e.detail||"");if(e.kind!=="payment"&&m)return tokIcon(m[1],e.chain);return '<div class="ic tok"><span class="glyph">'+(e.kind==="payment"?"P":e.kind==="trade"?"S":"W")+'</span>'+(COIN.chain[e.chain]?'<span class="cb">'+COIN.chain[e.chain]+'</span>':"")+'</div>'}
|
|
544
625
|
function amt(x){var n=Number(x);return isFinite(n)?n.toLocaleString(undefined,{maximumFractionDigits:6}):String(x)}
|
|
@@ -558,6 +639,7 @@ var prop=R.filter(function(r){return r.status==="proposed"&&!inChat[r.id]}),act=
|
|
|
558
639
|
var pv=PV?'<div class="ap" style="margin-top:10px"><div class="sm mut" style="margin-bottom:6px">Preview: nothing runs until you turn it on</div>'+(PV.rules.length?PV.rules.map(function(r){return '<div style="margin:4px 0">• '+esc(r.description)+(r.problem?' <span class="bad sm">('+esc(r.problem)+')</span>':"")+'</div>'}).join(""):'<div class="bad">No rules understood.</div>')+(PV.unparsed.length?'<div class="sm warn" style="margin-top:6px">Not understood: '+esc(PV.unparsed.join(" · "))+'</div>':"")+'<div class="btns"><button class="b g" onclick="PV=null;render()">Discard</button><button class="b ok"'+(PV.rules.length&&!PV.rules.some(function(r){return r.problem})?"":" disabled")+' onclick="addRules()">Turn on</button></div></div>':"";
|
|
559
640
|
var manualOpen=CH.manual||!S.ai||!(S.ai||{}).provider;
|
|
560
641
|
return '<div class="sm">'+st+'</div><div class="sm mut" style="margin-top:3px">Every fill follows your limits and approvals, with the same 0.5% fee as any swap.</div>'+msg()+
|
|
642
|
+
(S.trade_mode==="python"?pyCard():"")+botsHtml()+'<h3>Ask Claude</h3>'+
|
|
561
643
|
chatBox()+
|
|
562
644
|
(prop.length?'<h3>Waiting for you</h3>'+prop.map(ruleCard).join(""):"")+
|
|
563
645
|
'<h3>Your rules</h3>'+(act.length?act.map(ruleCard).join(""):'<div class="mut sm">No rules on yet.</div>')+
|
|
@@ -565,6 +647,50 @@ chatBox()+
|
|
|
565
647
|
'<details class="mrule"'+(manualOpen?" open":"")+' ontoggle="CH.manual=this.open"><summary>Write a rule yourself</summary><textarea id="stxt" rows="3" placeholder="e.g. Buy $25 of SOL every Monday. Sell half my ETH if it rises 10% and all if it falls 8%." style="width:100%;margin-top:8px;background:var(--surf);border:1px solid var(--line);color:var(--tx);border-radius:10px;padding:10px;font:inherit;resize:vertical"></textarea>'+
|
|
566
648
|
'<div class="toggles" style="margin-top:6px">'+TEMPL.map(function(t,i){return '<button class="chip" style="border:0;cursor:pointer" onclick="document.getElementById(\'stxt\').value=TEMPL['+i+']">'+esc(t)+'</button>'}).join("")+'</div>'+
|
|
567
649
|
'<div style="margin-top:10px"><button class="b" onclick="preview()">Preview</button></div>'+pv+'</details>'}
|
|
650
|
+
// ---- Bots: rule-based (no AI) bots, their status and results, and Tollkit's public board ----
|
|
651
|
+
var BOT={open:null,tpl:null,anim:false,flash:null,chain:"base",token:"ETH",params:{},pv:null,err:null,busy:false,more:{}};
|
|
652
|
+
function botPill(st){var m={running:["ok","Running"],waiting:["","Waiting for its price"],paused:["warn","Paused"],error:["bad","Stopped by errors"],done:["","Finished"],stopped:["","Stopped"]}[st]||["",st];return '<span class="chip botpill '+m[0]+'">'+m[1]+'</span>'}
|
|
653
|
+
function money(n){return (n<0?"−":"")+fmtUsd(Math.abs(n))}
|
|
654
|
+
function botCard(b){var res=b.result_usd!==null?'<span class="'+(b.result_usd>=0?"ok":"bad")+'">'+(b.result_usd>=0?"+":"")+money(b.result_usd)+(b.result_pct!==null?' ('+(b.result_pct>=0?"+":"")+b.result_pct+'%)':'')+'</span>':'<span class="mut">—</span>';
|
|
655
|
+
var live=b.status==="running"||b.status==="waiting"||b.status==="error",open=BOT.more[b.id];
|
|
656
|
+
return '<div class="botc'+(BOT.flash===b.id?" botflash":"")+'" data-botcard="'+esc(b.id)+'"><div class="botct"><div style="min-width:0"><b>'+esc(b.name)+'</b><div class="sm mut">'+esc(CHAIN_NAMES[b.chain]||b.chain)+(b.last_trade?' · last trade '+ago(b.last_trade):' · no trades yet')+'</div></div>'+botPill(b.status)+'</div>'+
|
|
657
|
+
'<div class="botstats"><div><small>Trades</small><b>'+b.trades_ok+'</b></div><div><small>Failed</small><b class="'+(b.trades_failed?"bad":"")+'">'+b.trades_failed+'</b></div><div><small>Success</small><b>'+(b.success_rate===null?"—":b.success_rate+"%")+'</b></div><div><small>Result</small><b>'+res+'</b></div></div>'+
|
|
658
|
+
(b.round_trips?'<div class="sm mut" style="margin-top:6px">'+b.round_trips+' buy-and-sell round trip'+(b.round_trips>1?"s":"")+' done</div>':'')+
|
|
659
|
+
'<div class="btns" style="margin-top:8px"><button class="b g" data-botmore="'+esc(b.id)+'">'+(open?"Hide":"Details")+'</button>'+(b.status==="paused"?'<button class="b ok" data-botst="active" data-bot="'+esc(b.id)+'">Resume</button>':live?'<button class="b g" data-botst="paused" data-bot="'+esc(b.id)+'">Pause</button>':'')+(b.status!=="done"&&b.status!=="stopped"?'<button class="b no" data-botst="cancelled" data-bot="'+esc(b.id)+'">Stop</button>':'')+'</div>'+
|
|
660
|
+
(open?'<div class="sm" style="margin-top:8px">'+b.rules.map(function(r){return '<div style="margin:4px 0">• '+esc(r.description)+' <span class="mut">('+esc(r.status)+')</span>'+(r.last_error?'<div class="bad">'+esc(r.last_error)+'</div>':'')+'</div>'}).join("")+'<div class="mut" style="margin-top:4px">Spent '+fmtUsd(b.spent_usd)+' · received '+fmtUsd(b.received_usd)+(b.value_now_usd!==null&&b.units_held?' · holding about '+fmtUsd(b.value_now_usd):'')+'</div></div>':'')+'</div>'}
|
|
661
|
+
function boardFor(id){var B=S.bot_board;if(!B||!B.templates)return null;for(var i=0;i<B.templates.length;i++)if(B.templates[i].template===id)return B.templates[i];return null}
|
|
662
|
+
function boardLine(id){var x=boardFor(id);if(!x||x.bots<3)return '<div class="sm mut">Not enough shared results yet.</div>';return '<div class="sm mut">'+x.bots+' bots shared · median result '+(x.median_result_pct>=0?"+":"")+x.median_result_pct+'% · '+x.success_rate+'% of trades went through</div>'}
|
|
663
|
+
function botsHtml(){var L=S.bots||[],T=S.bot_templates||[];
|
|
664
|
+
var h='<h3>Your bots</h3>'+(L.length?L.map(botCard).join(""):'<div class="mut sm">No bots yet. Start one below; it follows your limits like any trade.</div>');
|
|
665
|
+
h+='<h3>Start a bot</h3><div class="sm mut" style="margin-bottom:6px">Plain rules, no AI. You see every step before it starts.</div><div class="botcat">'+T.map(function(t){var on=BOT.tpl===t.id;return tplCard(t,on,L)+(on?'<div class="botwrap'+(BOT.anim?" drop":"")+'"><div class="botin">'+botForm()+'</div></div>':'')}).join("")+'</div>';
|
|
666
|
+
BOT.anim=false;
|
|
667
|
+
h+='<label class="botshare"><input type="checkbox" id="botshare"'+(S.bot_share?" checked":"")+' onchange="botShare(this.checked)"> Share my bots’ results with Tollkit’s public bot board (anonymous: bot type, token, trade counts and result %, no addresses or amounts)</label>';
|
|
668
|
+
return h}
|
|
669
|
+
var ARROW='<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>';
|
|
670
|
+
function tplCard(t,on,L){var mine=L.filter(function(b){return b.template===t.id}),live=mine.filter(function(b){return b.status!=="done"&&b.status!=="stopped"});
|
|
671
|
+
var head='<div class="tplh"><b>'+esc(t.name)+'</b>'+(live.length===1?botPill(live[0].status):live.length>1?'<span class="chip botpill ok">'+live.length+' bots</span>':'')+'</div>';
|
|
672
|
+
if(!live.length){var past=mine.length?'<div class="sm mut">Your last one: '+esc(({done:"finished",stopped:"stopped"})[mine[0].status]||mine[0].status)+'.</div>':'';
|
|
673
|
+
return '<button class="bottpl'+(on?" on":"")+'" data-tpl="'+esc(t.id)+'" aria-expanded="'+on+'">'+head+'<small>'+esc(t.blurb)+'</small>'+boardLine(t.id)+past+'<span class="botcta">'+(on?'Close setup':(mine.length?'Set up again':'Set up '+esc(t.name)+' bot')+ARROW)+'</span></button>'}
|
|
674
|
+
var b=live[0],line;if(live.length===1){var res=b.result_usd!==null?' · <span class="'+(b.result_usd>=0?"ok":"bad")+'">'+(b.result_usd>=0?"+":"")+money(b.result_usd)+'</span>':'';line=esc(b.token)+' on '+esc(CHAIN_NAMES[b.chain]||b.chain)+' · '+b.trades_ok+' trade'+(b.trades_ok===1?"":"s")+(b.trades_failed?' · <span class="bad">'+b.trades_failed+' failed</span>':'')+res+(b.last_trade?' · last '+ago(b.last_trade):'')}
|
|
675
|
+
else{var c={};live.forEach(function(x){c[x.status]=(c[x.status]||0)+1});line=Object.keys(c).map(function(k){return c[k]+' '+({running:"running",waiting:"waiting for a price",paused:"paused",error:"stopped by errors"})[k]}).join(" · ")}
|
|
676
|
+
return '<div class="bottpl has'+(on?" on":"")+(live.some(function(x){return x.status==="error"})?" err":"")+'">'+head+'<div class="sm">'+line+'</div>'+boardLine(t.id)+'<div class="tplbtns"><button class="botcta" data-botview="'+esc(b.id)+'">'+(live.length>1?'View bots':'View bot')+ARROW+'</button><button class="botcta g" data-tpl="'+esc(t.id)+'" aria-expanded="'+on+'">'+(on?'Close setup':'+ Set up another')+'</button></div></div>'}
|
|
677
|
+
function botForm(){var t=(S.bot_templates||[]).filter(function(x){return x.id===BOT.tpl})[0];if(!t)return "";
|
|
678
|
+
var f=t.fields.map(function(x){var v=BOT.params[x.key]!==undefined?BOT.params[x.key]:x.default;if(x.kind==="choice")return '<label class="botf"><span>'+esc(x.label)+'</span><select data-bp="'+esc(x.key)+'">'+x.choices.map(function(c){return '<option value="'+esc(c[0])+'"'+(String(v)===c[0]?" selected":"")+'>'+esc(c[1])+'</option>'}).join("")+'</select></label>';var lim=x.kind==="pct"&&x.max!==undefined?' <em class="botlim">up to '+Number(x.max).toLocaleString()+'%</em>':'';return '<label class="botf"><span>'+esc(x.label)+lim+'</span><input type="number" step="any" inputmode="decimal" data-bp="'+esc(x.key)+'"'+(x.min!==undefined?' min="'+x.min+'"':'')+(x.max!==undefined?' max="'+x.max+'"':'')+' value="'+esc(String(v))+'"></label>'}).join("");
|
|
679
|
+
return '<div class="ap botform" style="white-space:normal"><b>'+esc(t.name)+'</b><div class="sm mut" style="margin:4px 0 8px">Risk: '+esc(t.risk)+'</div><div class="botgrid"><label class="botf"><span>Network</span><select id="bot_chain">'+[["base","Base"],["ethereum","Ethereum"],["solana","Solana"]].map(function(o){return '<option value="'+o[0]+'"'+(BOT.chain===o[0]?" selected":"")+'>'+o[1]+'</option>'}).join("")+'</select></label><label class="botf"><span>Token (symbol or address)</span><input id="bot_token" value="'+esc(BOT.token)+'" autocomplete="off" spellcheck="false"></label>'+f+'</div>'+
|
|
680
|
+
(BOT.err?'<div class="msg err">'+esc(BOT.err)+'</div>':'')+(BOT.pv?'<div class="sm" style="margin-top:8px"><div class="mut">'+(BOT.pv.price?'Today’s price about $'+Number(BOT.pv.price).toLocaleString(undefined,{maximumSignificantDigits:6})+'. ':'')+'It will:</div>'+BOT.pv.rules.map(function(r){return '<div style="margin:4px 0">• '+esc(r.description)+'</div>'}).join("")+'</div>':'')+
|
|
681
|
+
'<div class="btns"><button class="b g" onclick="botClose()">Cancel</button>'+(BOT.pv?'<button class="b ok" onclick="botGo(\'start\')"'+(BOT.busy?" disabled":"")+'>Start bot</button>':'<button class="b" onclick="botGo(\'preview\')"'+(BOT.busy?" disabled":"")+'>Preview</button>')+'</div></div>'}
|
|
682
|
+
function botRead(){var c=document.getElementById("bot_chain"),t=document.getElementById("bot_token");if(c)BOT.chain=c.value;if(t)BOT.token=t.value.trim();document.querySelectorAll("[data-bp]").forEach(function(el){BOT.params[el.getAttribute("data-bp")]=el.tagName==="SELECT"?el.value:Number(el.value)})}
|
|
683
|
+
function botGo(what){botRead();BOT.busy=true;BOT.err=null;render();api("/bots/"+what,{template:BOT.tpl,chain:BOT.chain,token:BOT.token,params:BOT.params}).then(function(r){BOT.busy=false;if(what==="preview"){BOT.pv=r;render()}else{BOT.tpl=null;BOT.pv=null;flash=[1,"Bot started. It shows under Your bots."];refresh().then(function(){render()})}}).catch(function(e){BOT.busy=false;BOT.err=e.message;render()})}
|
|
684
|
+
function botClose(){var w=document.querySelector(".botwrap");BOT.pv=null;BOT.err=null;var done=function(){BOT.tpl=null;render()};if(!w||(window.matchMedia&&matchMedia("(prefers-reduced-motion: reduce)").matches)){done();return}w.classList.remove("drop");w.classList.add("closing");setTimeout(done,240)}
|
|
685
|
+
function botShare(on){api("/bots/share",{on:on}).then(function(){refresh()}).catch(function(e){flash=[0,e.message];render()})}
|
|
686
|
+
document.addEventListener("click",function(e){var t=e.target.closest&&e.target.closest("[data-tpl],[data-botst],[data-botmore],[data-botview]");if(!t)return;
|
|
687
|
+
if(t.hasAttribute("data-botview")){var vid=t.getAttribute("data-botview");BOT.more[vid]=true;BOT.flash=vid;render();var card=document.querySelector('[data-botcard="'+vid+'"]');if(card&&card.scrollIntoView)card.scrollIntoView({behavior:RM?"auto":"smooth",block:"center"});setTimeout(function(){if(BOT.flash===vid){BOT.flash=null;var c2=document.querySelector('[data-botcard="'+vid+'"]');if(c2)c2.classList.remove("botflash")}},1600);return}
|
|
688
|
+
if(t.hasAttribute("data-tpl")){var id=t.getAttribute("data-tpl");if(BOT.tpl===id){botClose();return}BOT.tpl=id;BOT.anim=true;BOT.params={};BOT.pv=null;BOT.err=null;if(BOT.chain==="solana"&&BOT.token==="ETH")BOT.token="SOL";render();setTimeout(function(){var w=document.querySelector(".botwrap");if(!w)return;w.classList.remove("drop");if(w.scrollIntoView)w.scrollIntoView({behavior:"smooth",block:"nearest"})},460);return}
|
|
689
|
+
if(t.hasAttribute("data-botmore")){var k=t.getAttribute("data-botmore");BOT.more[k]=!BOT.more[k];render();return}
|
|
690
|
+
var st=t.getAttribute("data-botst"),bid=t.getAttribute("data-bot");api("/bots/status",{bot:bid,status:st}).then(function(){flash=[1,st==="paused"?"Paused.":st==="active"?"Resumed.":"Stopped."];refresh().then(function(){render()})}).catch(function(e){flash=[0,e.message];render()})});
|
|
691
|
+
document.addEventListener("input",function(e){var t=e.target;if(!t||!t.hasAttribute||!t.hasAttribute("data-bp")||t.tagName!=="INPUT"||t.value==="")return;var mx=t.getAttribute("max");if(mx!==null&&Number(t.value)>Number(mx)){t.value=mx;t.classList.remove("botcap");void t.offsetWidth;t.classList.add("botcap")}});
|
|
692
|
+
document.addEventListener("focusout",function(e){var t=e.target;if(!t||!t.hasAttribute||!t.hasAttribute("data-bp")||t.tagName!=="INPUT")return;var mn=t.getAttribute("min");if(mn!==null&&(t.value===""||Number(t.value)<Number(mn)))t.value=mn});
|
|
693
|
+
document.addEventListener("change",function(e){if(e.target&&e.target.id==="bot_chain"){BOT.chain=e.target.value;var ti=document.getElementById("bot_token");if(ti&&(ti.value==="ETH"||ti.value==="SOL")){ti.value=BOT.chain==="solana"?"SOL":"ETH";BOT.token=ti.value}BOT.pv=null}else if(e.target&&(e.target.id==="bot_token"||e.target.hasAttribute&&e.target.hasAttribute("data-bp")))BOT.pv=null});
|
|
568
694
|
function preview(){var t=document.getElementById("stxt").value;api("/rules/preview",{text:t}).then(function(r){PV=r;flash=null;render()}).catch(function(e){flash=[0,e.message];render()})}
|
|
569
695
|
function addRules(){var rules=PV.rules.map(function(r){var o={};for(var k in r)if(k!=="description"&&k!=="problem")o[k]=r[k];return o});api("/rules",{rules:rules}).then(function(){PV=null;flash=[1,"Turned on. The autopilot is watching prices."];refresh()}).catch(function(e){flash=[0,e.message];render()})}
|
|
570
696
|
function setRule(id,st){api("/rules/status",{id:id,status:st}).then(function(){flash=[1,st==="active"?"Turned on.":st==="paused"?"Paused.":"Cancelled."];refresh()}).catch(function(e){flash=[0,e.message];render()})}
|
|
@@ -591,15 +717,34 @@ function rowUsd(e){if(Number(e.usd)>0)return usd(e.usd);var m=(e.kind==="stake"?
|
|
|
591
717
|
function usd(n){n=Number(n)||0;return "$"+n.toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:n<1&&n>0?4:2})}
|
|
592
718
|
function ago(ts){var s=(Date.now()-Date.parse(ts))/1000;if(s<60)return "just now";if(s<3600)return Math.floor(s/60)+"m ago";if(s<86400)return Math.floor(s/3600)+"h ago";return new Date(ts).toLocaleDateString()}
|
|
593
719
|
var ICONS={autopilot:'<path d="M13 2L4 14h7l-1 8 9-12h-7z"/>',home:'<path d="M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/>',activity:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',approvals:'<path d="M5 13l4 4L19 7"/>',settings:'<path d="M4 6h10M18 6h2M4 12h4M12 12h8M4 18h12"/><circle cx="16" cy="6" r="2"/><circle cx="10" cy="12" r="2"/><circle cx="18" cy="18" r="2"/>',withdraw:'<path d="M12 4v12m0 0l-5-5m5 5l5-5M5 20h14"/>'};
|
|
594
|
-
var TABS=["home","activity","autopilot","approvals","settings","withdraw"]
|
|
595
|
-
function nav(){var el=document.getElementById("nav");if(!el.querySelector("button")){el.innerHTML='<div class="ind" id="ind"></div>'+TABS.map(function(k){return '<button data-k="'+k+'" onclick="go(\''+k+'\')"
|
|
720
|
+
var TABS=["home","activity","autopilot","approvals","settings","withdraw"];
|
|
721
|
+
function nav(){var el=document.getElementById("nav");if(!el.querySelector("button")){el.innerHTML='<div class="ind" id="ind"></div>'+TABS.map(function(k){return '<button data-k="'+k+'" onclick="go(\''+k+'\')">'+(k==="autopilot"?'<span class="emo" aria-hidden="true">\u{1F916}</span>':'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">'+ICONS[k]+'</svg>')+(k==="autopilot"?"Bots":k[0].toUpperCase()+k.slice(1))+'</button>'}).join("")}
|
|
596
722
|
el.querySelectorAll("button").forEach(function(b){b.classList.toggle("on",b.getAttribute("data-k")===tab)});
|
|
597
723
|
document.getElementById("ind").style.transform="translateX("+(TABS.indexOf(tab)*100)+"%)";
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
724
|
+
navMark(el)}
|
|
725
|
+
// Why a tab is worth a tap. Activity and Home only count what's new since this page opened (or since you last looked).
|
|
726
|
+
var SEEN=null;
|
|
727
|
+
function navSeen(k){if(!S||!SEEN)return;if(k==="activity")(S.receipts||[]).forEach(function(r){SEEN.rc[r.id]=r.status});if(k==="home"&&S.live)S.live.events.forEach(function(e){SEEN.ev[e.id]=1})}
|
|
728
|
+
function navWhy(){var w={};if(!S)return w;
|
|
729
|
+
if(!SEEN){SEEN={rc:{},ev:{}};navSeen("activity");navSeen("home")}
|
|
730
|
+
if(tab==="activity"||tab==="home")navSeen(tab);
|
|
731
|
+
var np=(S.pending||[]).length;if(np)w.approvals={n:np,lvl:"bad",t:np+(np>1?" requests are":" request is")+" waiting for your OK"};
|
|
732
|
+
var prop=(S.rules||[]).filter(function(r){return r.status==="proposed"}).length,berr=(S.bots||[]).filter(function(b){return b.status==="error"}).length;
|
|
733
|
+
if(prop||berr)w.autopilot={n:prop+berr,lvl:berr?"bad":"acc",t:[prop?prop+" suggested rule"+(prop>1?"s":"")+" to review":"",berr?berr+" bot"+(berr>1?"s":"")+" stopped by errors":""].filter(Boolean).join(" · ")};
|
|
734
|
+
var bk=S.backup;if(bk&&!bk.done)w.settings={lvl:"warn",t:"Your wallet isn't backed up yet"};
|
|
735
|
+
var nr=0,nf=0;(S.receipts||[]).forEach(function(r){var was=SEEN.rc[r.id];if(was===undefined||(r.status==="failed"&&was!=="failed")){nr++;if(r.status==="failed")nf++}});
|
|
736
|
+
if(nr)w.activity={n:nr,lvl:nf?"bad":"acc",t:nr+" new in Activity"+(nf?" ("+nf+" failed)":"")};
|
|
737
|
+
var nd=S.live?S.live.events.filter(function(e){return e.direction==="in"&&!SEEN.ev[e.id]}).length:0;
|
|
738
|
+
if(nd)w.home={n:nd,lvl:"ok",t:nd+" new deposit"+(nd>1?"s":"")};
|
|
739
|
+
return w}
|
|
740
|
+
function navMark(el){var w=navWhy();el.querySelectorAll("button").forEach(function(b){var k=b.getAttribute("data-k"),r=w[k],name=k==="autopilot"?"Bots":k[0].toUpperCase()+k.slice(1);
|
|
741
|
+
var key=r?r.lvl+"|"+(r.n||"")+"|"+r.t:"";if(b.getAttribute("data-why")===key)return;b.setAttribute("data-why",key);
|
|
742
|
+
b.classList.remove("attn","attn-bad","attn-warn","attn-ok","attn-acc");var old=b.querySelector(".badge");if(old)old.remove();
|
|
743
|
+
b.title=r?r.t:"";b.setAttribute("aria-label",r?name+": "+r.t:name);if(!r)return;
|
|
744
|
+
b.classList.add("attn","attn-"+r.lvl);var sp=document.createElement("span");sp.className="badge"+(r.n?"":" dot");sp.textContent=r.n?(r.n>99?"99+":String(r.n)):"";b.appendChild(sp)})}
|
|
745
|
+
function go(k){if(k==="autopilot"&&S&&!S.trade_mode)openTM();if(k===tab&&!flash)return;var changed=k!==tab;tab=k;flash=null;render(true);if(changed){var mm=document.getElementById("main");if(mm)mm.scrollTop=0}}
|
|
601
746
|
function msg(){return flash?'<div class="msg '+(flash[0]?"okk":"err")+'">'+esc(flash[1])+'</div>':""}
|
|
602
|
-
function render(enter){nav();if(!S)return;var a=S.approvals||"none";var ap=document.getElementById("appr");ap.classList.toggle("live",a!=="none"||!!S.live);ap.textContent=(S.live?"Live":"")+(S.live?" · ":"")+(a==="none"?"Approvals off":"Approvals on");ap.title=a==="none"?"Set up Telegram or keep this page open":"Answered via "+a.replace("+"," and ");ap.onclick=function(){go("settings")};ap.style.cursor="pointer";var m=document.getElementById("main");
|
|
747
|
+
function render(enter){nav();if(!S)return;if(PYO)pyRender();var a=S.approvals||"none";var ap=document.getElementById("appr");ap.classList.toggle("live",a!=="none"||!!S.live);ap.textContent=(S.live?"Live":"")+(S.live?" · ":"")+(a==="none"?"Approvals off":"Approvals on");ap.title=a==="none"?"Set up Telegram or keep this page open":"Answered via "+a.replace("+"," and ");ap.onclick=function(){go("settings")};ap.style.cursor="pointer";var m=document.getElementById("main");
|
|
603
748
|
if(tab!=="autopilot")LASTAP=null;if(tab!=="settings"){LIMD={};LIMPW=""}var prevTab=m.dataset.tab;m.dataset.tab=tab;if(tab==="home")m.innerHTML=home();else if(tab==="activity")m.innerHTML=activity();else if(tab==="approvals")m.innerHTML=approvals();else if(tab==="settings")m.innerHTML=settings();else if(tab==="autopilot"){var h=autopilot();if(!enter&&h===LASTAP&&prevTab==="autopilot"){chatAfter();return}m.innerHTML=h;LASTAP=h;chatAfter()}else{m.innerHTML=withdraw();tokOpts()}
|
|
604
749
|
after(m,enter)}
|
|
605
750
|
var shown=null;
|
|
@@ -637,6 +782,44 @@ function limT(id,on,text){var c=lv(id,on);return '<label><input type="checkbox"
|
|
|
637
782
|
function setRow(icon,title,sub,btn){return '<div class="row">'+icon+'<div style="min-width:0"><div>'+title+'</div><div class="sm mut">'+sub+'</div></div><div class="r">'+btn+'</div></div>'}
|
|
638
783
|
var SICO={ai:'<path d="M12 3v3M12 18v3M3 12h3M18 12h3"/><rect x="7" y="7" width="10" height="10" rx="2"/>',tg:'<path d="M21 4L3 11l6 2 2 6 3-4 5 4z"/>',bk:'<path d="M12 3l8 4v5c0 5-3.5 8-8 9-4.5-1-8-4-8-9V7z"/>',ext:'<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.7 3.8 5.7 3.8 9s-1.3 6.3-3.8 9c-2.5-2.7-3.8-5.7-3.8-9S9.5 5.7 12 3z"/>'};
|
|
639
784
|
function sIco(k){return '<div class="ic"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">'+SICO[k]+'</svg></div>'}
|
|
785
|
+
// Opening the Bots tab before picking: AI trading or Python trading. Python bots get the wallet's bot link (the same one AI apps use).
|
|
786
|
+
var TMO=null,PYO=null,PYPW="",PYMSG=null,PYBUSY=false;
|
|
787
|
+
var CODEICO='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 7l-5 5 5 5M16 7l5 5-5 5M13.5 4l-3 16"/></svg>';
|
|
788
|
+
function openTM(){if(TMO)return;TMO=document.createElement("div");TMO.className="aio tmo";
|
|
789
|
+
TMO.innerHTML='<div class="aidlg tmdlg" role="dialog" aria-modal="true" aria-label="How do you want to trade?"><h2>How do you want to trade?</h2><p class="ailead">Pick one to start. You can switch any time in Settings.</p><div class="tmopts">'+
|
|
790
|
+
'<button class="tmopt" data-tm="ai" style="--i:0"><span class="tmico tmai">'+aiSvg("claude")+'</span><b>AI trading</b><small>Tell Claude what you want in plain words. It suggests rules and bots, and nothing runs until you turn it on. You can also connect your own AI app.</small><span class="botcta">Start with AI'+ARROW+'</span></button>'+
|
|
791
|
+
'<button class="tmopt" data-tm="python" style="--i:1"><span class="tmico tmpy">'+CODEICO+'</span><b>Python trading</b><small>Run your own Python bots: four starter strategies, backtests on past prices and paper trading with pretend money.</small><span class="botcta">Start with Python'+ARROW+'</span></button>'+
|
|
792
|
+
'</div><p class="aismall" style="text-align:center;margin-bottom:4px">Either way, every trade stays inside your spending limits and approvals.</p><div style="text-align:center"><button class="aihand tmlater" data-tm="later">Decide later</button></div></div>';
|
|
793
|
+
TMO.addEventListener("click",function(e){var b=e.target.closest("[data-tm]");if(!b)return;var m=b.getAttribute("data-tm");if(m==="later"){closeTM();return}pickTM(m,true)});document.body.appendChild(TMO)}
|
|
794
|
+
function closeTM(){if(TMO){TMO.remove();TMO=null}}
|
|
795
|
+
function pickTM(m,first){api("/trade-mode",{mode:m}).then(function(){closeTM();return refresh()}).then(function(){if(!first){render();return}if(m==="python"){go("autopilot");openPy()}else{go("autopilot");setTimeout(function(){var c=document.querySelector(".tc-chat");if(c&&c.scrollIntoView)c.scrollIntoView({behavior:RM?"auto":"smooth",block:"start"})},120)}}).catch(function(e){flash=[0,e.message];closeTM();render()})}
|
|
796
|
+
function pyLocalEnv(){var l=(S.connect||{}).launch||{},env=l.env||{};return Object.keys(env).filter(function(k){return /^TOLLKIT_WALLET_/.test(k)}).map(function(k){return 'export '+k+'="'+env[k]+'"'}).join("\n")}
|
|
797
|
+
function pyBody(){var c=S.connect||{},r=c.remote,lim=S.policy||{},m=PYMSG,n=0;
|
|
798
|
+
function step(t){n++;return '<div class="pystep"><span class="pyn">'+n+'</span><b>'+t+'</b></div>'}
|
|
799
|
+
var h='<h2>Python bots</h2><p class="ailead">Run your own trading bots in Python. They trade through this wallet, inside your limits, and can’t withdraw, change limits or see your keys.</p>';
|
|
800
|
+
h+=step("Install")+aiCode("py-i","pip install tollkit-wallet")+'<p class="aismall">Python 3.9 or newer. No other packages needed.</p>';
|
|
801
|
+
var ready=false,env="";
|
|
802
|
+
if(r){h+=step("Your bot link");
|
|
803
|
+
if(!r.on){h+='<label class="ailbl" for="pypw">Wallet password</label><input id="pypw" class="aiin" type="password" autocomplete="current-password" placeholder="Needed to make the link" value="'+esc(PYPW)+'"><button class="b aigoap" data-pyact="on"'+(PYBUSY?" disabled":"")+'>'+(PYBUSY?"Making it…":"Make my bot link")+'</button>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')+'<p class="aismall">Your bot sends its requests to Tollkit’s server, which passes them to this wallet while Chrome is open and the wallet is unlocked. Your keys stay here.</p>'}
|
|
804
|
+
else{ready=true;env='export TOLLKIT_LINK="'+r.url+'"';h+=aiCode("py-link",r.url)+'<p class="aismall"><span class="'+(r.online?"ok":"warn")+'">●</span> '+(r.online?"The wallet is reachable.":"Waiting for the wallet to check in…")+' Keep this link private: anyone with it can trade inside your limits. It’s the same link your AI apps use. Keep Chrome open with the wallet unlocked while a bot runs.</p>'+
|
|
805
|
+
'<details class="pymore"><summary>New link or turn off</summary><label class="ailbl" for="pypw">Wallet password (for a new link)</label><input id="pypw" class="aiin" type="password" autocomplete="current-password" value="'+esc(PYPW)+'"><div class="btns" style="margin-top:8px"><button class="b g" data-pyact="new"'+(PYBUSY?" disabled":"")+'>New link</button><button class="b no" data-pyact="off"'+(PYBUSY?" disabled":"")+'>Turn off</button></div><p class="aismall">A new link stops the old one, for bots and AI apps alike.</p></details>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')}}
|
|
806
|
+
else{h+=step("Let your scripts unlock the wallet");
|
|
807
|
+
if(c.ready){ready=true;env=pyLocalEnv();h+='<p class="aismall"><span class="ok">●</span> Saved. Scripts on this computer unlock the wallet with a copy of your password that only your account can read.</p>'}
|
|
808
|
+
else h+='<label class="ailbl" for="pypw">Wallet password</label><input id="pypw" class="aiin" type="password" autocomplete="current-password" value="'+esc(PYPW)+'"><button class="b aigoap" data-pyact="pw"'+(PYBUSY?" disabled":"")+'>'+(PYBUSY?"Saving…":"Save it for my scripts")+'</button>'+(m?'<div class="aim '+(m[0]?"ok":"bad")+'">'+esc(m[1])+'</div>':'')+'<p class="aismall">Saves a copy of the password on this computer, readable only by your account. Anyone who can read it and your wallet folder could trade inside your limits.</p>'}
|
|
809
|
+
if(ready){h+=step("Try it")+aiCode("py-try",(env?env+"\n":"")+"tollkit-bot check\ntollkit-bot backtest dip-buyer\ntollkit-bot run dip-buyer")+'<p class="aismall">Paper trading (pretend money, live prices) unless you add <code>--live</code>. Built in: <code>dca</code>, <code>dip-buyer</code>, <code>momentum</code>, <code>rebalance</code>.'+(r?' On Windows PowerShell: <code>$env:TOLLKIT_LINK="…"</code>.':'')+'</p>'+
|
|
810
|
+
step("Write your own")+aiCode("py-code",'from tollkit_wallet import Strategy, buy, hold\n\nclass BuyDips(Strategy):\n token, chain = "ETH", "base"\n def decide(self, m, notes):\n if m.change_pct(24) is not None and m.change_pct(24) <= -5 and m.cash >= 20:\n return buy(20, "down 5% in a day")\n return hold()')+
|
|
811
|
+
'<p class="aismall"><code>tollkit-bot new my_bot.py</code> writes a full example to edit. Trades over '+usd(lim.approval_above_usd||0)+' wait for you in Approvals.</p>'}
|
|
812
|
+
return h}
|
|
813
|
+
function pyRender(){if(!PYO)return;var d=PYO.querySelector(".aidlg"),sc=d.scrollTop,foc=document.activeElement&&document.activeElement.id==="pypw";PYO.querySelector(".aibody").innerHTML=pyBody();d.scrollTop=sc;var pw=document.getElementById("pypw");if(pw){pw.oninput=function(){PYPW=pw.value};if(foc)pw.focus()}}
|
|
814
|
+
function openPy(){if(!PYO){PYO=document.createElement("div");PYO.className="aio";PYO.innerHTML='<div class="aidlg" role="dialog" aria-modal="true" aria-label="Python bots"><button class="aix" aria-label="Close">×</button><div class="aibody"></div></div>';PYO.addEventListener("mousedown",function(e){if(e.target===PYO)closePy()});PYO.addEventListener("click",pyClick);document.body.appendChild(PYO)}pyRender()}
|
|
815
|
+
function closePy(){if(PYO){PYO.remove();PYO=null;PYPW="";PYMSG=null}}
|
|
816
|
+
function pyDo(act){if(act!=="off"&&!PYPW){PYMSG=[0,"Type your wallet password first."];pyRender();var p=document.getElementById("pypw");if(p)p.focus();return}
|
|
817
|
+
PYBUSY=true;PYMSG=null;pyRender();(act==="pw"?api("/ai/password",{password:PYPW}):api("/connect/remote",{password:PYPW,action:act})).then(function(){PYPW="";PYMSG=act==="off"?[1,"Turned off. No bot or app can reach the wallet now."]:act==="new"?[1,"New link made. Update it in your bots and AI apps."]:null;return refresh()}).catch(function(e){PYMSG=[0,e.message]}).then(function(){PYBUSY=false;pyRender()})}
|
|
818
|
+
function pyClick(e){var t=e.target.closest("button");if(!t)return;if(t.classList.contains("aix"))closePy();else if(t.hasAttribute("data-pyact"))pyDo(t.getAttribute("data-pyact"));else if(t.hasAttribute("data-copy")){var el=document.getElementById(t.getAttribute("data-copy")),v=el?el.textContent:"",done=function(){t.textContent="Copied";setTimeout(function(){t.textContent="Copy"},1500)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(v).then(done,function(){fallback(v);done()});else{fallback(v);done()}}}
|
|
819
|
+
function pyStatus(){var c=S.connect||{},r=c.remote;if(r)return r.on?(r.online?'<span class="ok">●</span> Bot link on, wallet reachable':'<span class="warn">●</span> Bot link on, waiting for the wallet'):'No bot link yet';return c.ready?'<span class="ok">●</span> Ready for scripts on this computer':'Not set up yet'}
|
|
820
|
+
function pyCard(){return '<div class="pycard"><div class="pyct"><span class="tmico tmpy sm">'+CODEICO+'</span><div style="min-width:0"><b>Python bots</b><div class="sm mut">'+pyStatus()+'</div></div><button class="botcta" onclick="openPy()">'+(((S.connect||{}).remote||{}).on||(!(S.connect||{}).remote&&(S.connect||{}).ready)?"Show setup":"Set up")+ARROW+'</button></div></div>'}
|
|
821
|
+
function tradeRow(){var m=S.trade_mode;return '<div class="row"><div style="min-width:0"><div>Trading with</div><div class="sm mut">'+(m==="python"?"Your own Python bots.":m==="ai"?"Claude and your AI apps.":"Not picked yet.")+' Both use the same limits.</div></div><div class="r"><div class="bseg tmseg"><button class="bsb'+(m==="ai"?" on":"")+'" onclick="pickTM(\'ai\',false)">AI</button><button class="bsb'+(m==="python"?" on":"")+'" onclick="pickTM(\'python\',false)">Python</button></div></div></div>'+
|
|
822
|
+
setRow('<div class="ic">'+CODEICO.replace('aria-hidden','width="17" height="17" aria-hidden')+'</div>',"Python bots",pyStatus(),'<button class="b g sbtn" onclick="openPy()">'+(S.trade_mode==="python"?"Setup":"Set up")+'</button>')}
|
|
640
823
|
function settings(){var p=S.policy,sp=S.spent_today||{},dirty=Object.keys(LIMD).length>0;
|
|
641
824
|
var lim='<h3>Spending limits</h3><div class="mut sm">Your AI and autopilot have to stay inside these and can\'t change them. Saving needs your password.</div>'+
|
|
642
825
|
'<div class="sgrp">Swaps</div><div class="grid2">'+limF("per_trade_usd","Per swap ($)","Largest single swap")+limF("daily_trades_usd","Swaps per day ($)",null,sp.trades_usd||0)+limF("approval_above_usd","Ask me above ($)","Bigger swaps wait for your OK")+limF("max_slippage_bps","Max slippage (bps)","100 bps = 1%")+'</div>'+
|
|
@@ -657,7 +840,7 @@ var exr=setRow(sIco("ext"),"Browser extension",ex.paired?'<span class="ok">Paire
|
|
|
657
840
|
(EXC?'<div class="row" style="flex-wrap:wrap"><div style="min-width:0"><div class="sm mut">Paste this code into the Tollkit extension. It works once, for 5 minutes.</div><div class="addr" style="font-size:17px;letter-spacing:.06em;margin-top:4px">'+esc(EXC)+'</div></div><div class="r">'+cpBtn(EXC)+'</div></div>':'')+
|
|
658
841
|
(ex.sites.length?ex.sites.map(function(x){var h=x.origin.replace(/^https?:\/\//,"");return '<div class="row"><div style="min-width:0"><div>'+esc(h)+'</div><div class="sm mut">'+[x.evm?"Base/Ethereum":"",x.solana?"Solana":""].filter(Boolean).join(" + ")+'</div></div><div class="r"><button class="b no sbtn" data-extoff="'+esc(x.origin)+'">Disconnect</button></div></div>'}).join(""):'')+
|
|
659
842
|
(ex.paired?'<div class="sm" style="margin-top:6px"><a href="#" onclick="extUnpair();return false">Unpair all browsers</a></div>':'');
|
|
660
|
-
return lim+'<h3>AI</h3>'+ai+'<h3>Websites</h3>'+exr+'<h3>Approvals</h3>'+tg+'<h3>Recovery</h3>'+bkr}
|
|
843
|
+
return lim+'<h3>How you trade</h3>'+tradeRow()+'<h3>AI</h3>'+ai+'<h3>Websites</h3>'+exr+'<h3>Approvals</h3>'+tg+'<h3>Recovery</h3>'+bkr}
|
|
661
844
|
var EXC=null,EXCN=0;
|
|
662
845
|
function extCode(){api("/extmgr/code",{}).then(function(r){EXC=r.code;EXCN=(S.ext||{}).paired||0;render()}).catch(function(e){flash=[0,e.message];render()})}
|
|
663
846
|
document.addEventListener("click",function(e){var b=e.target.closest&&e.target.closest("[data-extoff]");if(b)extOff(b.getAttribute("data-extoff"))});
|
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACtE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACtE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuTnB,SAAS;WACT,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+iBC,CAAC"}
|
package/dist/wallet.d.ts
CHANGED
|
@@ -33,6 +33,13 @@ export interface WalletOptions {
|
|
|
33
33
|
dapp?: Partial<ConstructorParameters<typeof DappBridge>[0]>;
|
|
34
34
|
/** Override for tests / other channels. Default: Telegram if configured. */
|
|
35
35
|
approve?: ((text: string) => Promise<Decision>) | null;
|
|
36
|
+
/** Override for tests: Tollkit's separately-sent Solana fee (recipient, SOL price, balance and sender). */
|
|
37
|
+
solFee?: {
|
|
38
|
+
recipient?: string;
|
|
39
|
+
solUsd?: number;
|
|
40
|
+
balance?: () => Promise<bigint>;
|
|
41
|
+
send?: (lamports: bigint, to: string) => Promise<string>;
|
|
42
|
+
};
|
|
36
43
|
}
|
|
37
44
|
export interface SwapResult {
|
|
38
45
|
ok: boolean;
|
|
@@ -93,7 +100,7 @@ export declare class TollkitWallet {
|
|
|
93
100
|
max_slippage_bps: number;
|
|
94
101
|
chains: ("base" | "ethereum" | "solana")[];
|
|
95
102
|
block_seller_warnings: boolean;
|
|
96
|
-
agent_rules: "
|
|
103
|
+
agent_rules: "auto" | "propose";
|
|
97
104
|
withdraw_addresses: {
|
|
98
105
|
address: string;
|
|
99
106
|
chain: "base" | "ethereum" | "solana";
|
|
@@ -119,8 +126,13 @@ export declare class TollkitWallet {
|
|
|
119
126
|
private taker;
|
|
120
127
|
/** Dollar value of a quote. Stable side if there is one; Jupiter reports it; otherwise price the sell side against USDC. */
|
|
121
128
|
valueOf(q: SwapQuote): Promise<number | null>;
|
|
129
|
+
/** Where and how much Tollkit's separately-sent Solana fee is. */
|
|
130
|
+
private separateFee;
|
|
131
|
+
private sendSolFee;
|
|
122
132
|
/** A priced, checked quote. Nothing is signed. */
|
|
123
133
|
quote(req: SwapRequest): Promise<SwapResult>;
|
|
134
|
+
/** Core, listed (Superchain list on Base/Ethereum, Jupiter-verified on Solana) or added by the owner. */
|
|
135
|
+
private knownToken;
|
|
124
136
|
private priced;
|
|
125
137
|
/** Quote, check, approve if needed, reserve, sign, send, record. */
|
|
126
138
|
swap(req: SwapRequest): Promise<SwapResult>;
|