balchemy 0.1.23 → 0.2.0
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 +19 -4
- package/dist/colors.d.ts +37 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +58 -0
- package/dist/colors.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -43
- package/dist/index.js.map +1 -1
- package/dist/terminal-logo.d.ts.map +1 -1
- package/dist/terminal-logo.js +9 -14
- package/dist/terminal-logo.js.map +1 -1
- package/dist/tui/AgentBridge.d.ts +3 -0
- package/dist/tui/AgentBridge.d.ts.map +1 -1
- package/dist/tui/AgentBridge.js +239 -41
- package/dist/tui/AgentBridge.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +6 -15
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/ChatAgent.d.ts +3 -0
- package/dist/tui/ChatAgent.d.ts.map +1 -1
- package/dist/tui/ChatAgent.js +59 -17
- package/dist/tui/ChatAgent.js.map +1 -1
- package/dist/tui/ChatPanel.d.ts +2 -1
- package/dist/tui/ChatPanel.d.ts.map +1 -1
- package/dist/tui/ChatPanel.js +19 -7
- package/dist/tui/ChatPanel.js.map +1 -1
- package/dist/tui/SecretInput.d.ts +9 -0
- package/dist/tui/SecretInput.d.ts.map +1 -0
- package/dist/tui/SecretInput.js +32 -0
- package/dist/tui/SecretInput.js.map +1 -0
- package/dist/tui/Wizard.d.ts +20 -0
- package/dist/tui/Wizard.d.ts.map +1 -0
- package/dist/tui/Wizard.js +400 -0
- package/dist/tui/Wizard.js.map +1 -0
- package/dist/tui/setup-guidance.d.ts +3 -0
- package/dist/tui/setup-guidance.d.ts.map +1 -1
- package/dist/tui/setup-guidance.js +29 -10
- package/dist/tui/setup-guidance.js.map +1 -1
- package/dist/tui/start-wizard.d.ts +2 -0
- package/dist/tui/start-wizard.d.ts.map +1 -0
- package/dist/tui/start-wizard.js +30 -0
- package/dist/tui/start-wizard.js.map +1 -0
- package/dist/tui/utils.d.ts +3 -0
- package/dist/tui/utils.d.ts.map +1 -0
- package/dist/tui/utils.js +14 -0
- package/dist/tui/utils.js.map +1 -0
- package/dist/wizard.js +1 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +7 -6
- package/templates/agent.config.yaml +71 -0
- package/LICENSE +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-logo.js","sourceRoot":"","sources":["../src/terminal-logo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal-logo.js","sourceRoot":"","sources":["../src/terminal-logo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAC;AAEhC,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;AAEnD,iFAAiF;AAEjF,MAAM,eAAe,GAAG;IACtB,EAAE;IACF,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;IACrD,KAAK,CAAC,CAAC,CAAC,2CAA2C,CAAC,CAAC,CAAC,EAAE;IACxD,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;IAClC,EAAE;CACH,CAAC;AAWF,SAAS,cAAc;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAExC,+BAA+B;IAC/B,IACE,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,SAAS;QAClB,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAC9B,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0BAA0B;IAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,iFAAiF;AAEjF,SAAS,YAAY,CAAC,KAAmB,EAAE,SAAiB;IAC1D,OAAO,uBAAuB,KAAK,CAAC,QAAQ,mBAAmB,SAAS,0BAA0B,KAAK,CAAC,MAAM,MAAM,CAAC;AACvH,CAAC;AAED,iFAAiF;AAEjF,SAAS,WAAW,CAAC,KAAmB,EAAE,SAAiB;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,yBAAyB,SAAS,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACvF,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,SAAS,GAAG,EAAE;IACvC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,gCAAgC;IAChC,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC;IACtD,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC;IACrD,CAAC;IAED,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAuB,EAAE,QAAQ,EAAE,WAAW,CAAC;KACzE,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;gBACvC,OAAO;oBACL,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAC9B,QAAQ,EAAE,GAAG,CAAC,UAAU;iBACzB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -3,6 +3,7 @@ type StateSetters = {
|
|
|
3
3
|
addMessage: (msg: ChatMessage) => void;
|
|
4
4
|
setStatus: (updater: (prev: StatusData) => StatusData) => void;
|
|
5
5
|
confirmTrade: (preview: string) => Promise<boolean>;
|
|
6
|
+
setThinking: (value: boolean) => void;
|
|
6
7
|
};
|
|
7
8
|
export declare class AgentBridge {
|
|
8
9
|
private loop;
|
|
@@ -34,6 +35,8 @@ export declare class AgentBridge {
|
|
|
34
35
|
private beginSetupFlow;
|
|
35
36
|
private setupPromptFor;
|
|
36
37
|
private setupPromptForStrategyChain;
|
|
38
|
+
private createTradingWalletsForSetup;
|
|
39
|
+
private selectedChainsForSetup;
|
|
37
40
|
private reviewStrategyWithAi;
|
|
38
41
|
private handleSetupInput;
|
|
39
42
|
private callSetupAgent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentBridge.d.ts","sourceRoot":"","sources":["../../src/tui/AgentBridge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAa,SAAS,EAAc,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"AgentBridge.d.ts","sourceRoot":"","sources":["../../src/tui/AgentBridge.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/AgentBridge.js
CHANGED
|
@@ -5,6 +5,7 @@ import { ChatAgent } from "./ChatAgent.js";
|
|
|
5
5
|
import { buildSetupRequiredMessage, getInitialSetupStep, isSetupReady, parseNetworkSelection, parseSetupStatusSnapshot, } from "./setup-guidance.js";
|
|
6
6
|
import { buildStrategyUpdateArgs } from "./session-sync.js";
|
|
7
7
|
import { loadAgent, saveAgent } from "../agent-store.js";
|
|
8
|
+
import { resolveProviderLabel } from "./utils.js";
|
|
8
9
|
/** Truncate verbose API errors (429 JSON blobs, stack traces) to a readable one-liner. */
|
|
9
10
|
function truncateError(raw) {
|
|
10
11
|
// Extract HTTP status code if present
|
|
@@ -31,16 +32,35 @@ function truncateError(raw) {
|
|
|
31
32
|
}
|
|
32
33
|
return clean;
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
/** Map raw errors to user-friendly messages for the TUI. */
|
|
36
|
+
function friendlyError(err) {
|
|
37
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
38
|
+
// Auth errors
|
|
39
|
+
if (/\b401\b/.test(raw))
|
|
40
|
+
return "Authentication failed (401). Check your API key in settings (^S).";
|
|
41
|
+
if (/\b403\b/.test(raw))
|
|
42
|
+
return "Access denied (403). Your API key may lack required permissions.";
|
|
43
|
+
// Rate limiting
|
|
44
|
+
if (/\b429\b/.test(raw))
|
|
45
|
+
return truncateError(raw);
|
|
46
|
+
// Server errors
|
|
47
|
+
if (/\b500\b/.test(raw))
|
|
48
|
+
return "LLM server error (500). Try again shortly.";
|
|
49
|
+
if (/\b502\b/.test(raw))
|
|
50
|
+
return "LLM gateway error (502). The provider may be experiencing issues.";
|
|
51
|
+
if (/\b503\b/.test(raw))
|
|
52
|
+
return "LLM service unavailable (503). Try again in a moment.";
|
|
53
|
+
// Network errors
|
|
54
|
+
if (/ECONNREFUSED/i.test(raw))
|
|
55
|
+
return "Cannot reach LLM server. Check your network or provider status.";
|
|
56
|
+
if (/ETIMEDOUT|ESOCKETTIMEDOUT/i.test(raw))
|
|
57
|
+
return "Connection timed out. Check your network connection.";
|
|
58
|
+
if (/ENOTFOUND/i.test(raw))
|
|
59
|
+
return "DNS lookup failed. Check your network connection.";
|
|
60
|
+
if (/abort/i.test(raw) && /timeout/i.test(raw))
|
|
61
|
+
return "Request timed out. The LLM took too long to respond.";
|
|
62
|
+
// Fallback to truncated version
|
|
63
|
+
return `LLM error: ${truncateError(raw)}`;
|
|
44
64
|
}
|
|
45
65
|
function parseJsonObject(text) {
|
|
46
66
|
try {
|
|
@@ -499,7 +519,7 @@ export class AgentBridge {
|
|
|
499
519
|
}));
|
|
500
520
|
},
|
|
501
521
|
onError: (err) => {
|
|
502
|
-
this.addErrorMessage(err
|
|
522
|
+
this.addErrorMessage(friendlyError(err));
|
|
503
523
|
},
|
|
504
524
|
onStatusChange: (status) => {
|
|
505
525
|
this.setters.setStatus((prev) => ({
|
|
@@ -561,7 +581,7 @@ export class AgentBridge {
|
|
|
561
581
|
this.addAgentMessage(reply);
|
|
562
582
|
}
|
|
563
583
|
catch (err) {
|
|
564
|
-
this.addErrorMessage(
|
|
584
|
+
this.addErrorMessage(friendlyError(err));
|
|
565
585
|
}
|
|
566
586
|
}
|
|
567
587
|
async stop() {
|
|
@@ -592,11 +612,18 @@ export class AgentBridge {
|
|
|
592
612
|
timestamp: Date.now(),
|
|
593
613
|
});
|
|
594
614
|
if (this.setupFlow) {
|
|
595
|
-
|
|
615
|
+
this.setters.setThinking(true);
|
|
616
|
+
try {
|
|
617
|
+
await this.handleSetupInput(text);
|
|
618
|
+
}
|
|
619
|
+
finally {
|
|
620
|
+
this.setters.setThinking(false);
|
|
621
|
+
}
|
|
596
622
|
return;
|
|
597
623
|
}
|
|
598
624
|
if (!this.chatAgent)
|
|
599
625
|
return;
|
|
626
|
+
this.setters.setThinking(true);
|
|
600
627
|
try {
|
|
601
628
|
const reply = await this.chatAgent.chat(this.withRuntimeContext(text), (name, result) => {
|
|
602
629
|
this.applyToolResult(name, result);
|
|
@@ -607,7 +634,10 @@ export class AgentBridge {
|
|
|
607
634
|
await this.tryStartLoop();
|
|
608
635
|
}
|
|
609
636
|
catch (err) {
|
|
610
|
-
this.addErrorMessage(
|
|
637
|
+
this.addErrorMessage(friendlyError(err));
|
|
638
|
+
}
|
|
639
|
+
finally {
|
|
640
|
+
this.setters.setThinking(false);
|
|
611
641
|
}
|
|
612
642
|
}
|
|
613
643
|
/** Start AgentLoop if setup just completed during this session. */
|
|
@@ -642,6 +672,10 @@ export class AgentBridge {
|
|
|
642
672
|
const step = getInitialSetupStep(snapshot);
|
|
643
673
|
this.setupFlow = {
|
|
644
674
|
step,
|
|
675
|
+
rootWalletBound: snapshot.developerWalletBound === true,
|
|
676
|
+
...(snapshot.rootWalletKind ? { rootWalletKind: snapshot.rootWalletKind } : {}),
|
|
677
|
+
evmWalletBound: snapshot.evmWalletBound === true,
|
|
678
|
+
solanaWalletBound: snapshot.solanaWalletBound === true,
|
|
645
679
|
...(snapshot.selectedChains && snapshot.selectedChains.length > 0 ? { selectedChains: snapshot.selectedChains } : {}),
|
|
646
680
|
};
|
|
647
681
|
this.addAgentMessage(`${buildSetupRequiredMessage(snapshot)}\n\n${this.setupPromptFor(this.setupFlow.step)}`);
|
|
@@ -649,15 +683,15 @@ export class AgentBridge {
|
|
|
649
683
|
setupPromptFor(step) {
|
|
650
684
|
switch (step) {
|
|
651
685
|
case "developer-wallet":
|
|
652
|
-
return "Paste your Base/EVM 0x developer wallet. This is the recovery, Hub, and withdrawal wallet. Trading wallets are created separately.";
|
|
686
|
+
return "Paste your Base/EVM 0x developer wallet. This is the Base root, recovery, Hub, and withdrawal wallet. Trading wallets are created separately.";
|
|
653
687
|
case "developer-wallet-confirm":
|
|
654
688
|
return "Paste the same 0x developer wallet again to confirm it.";
|
|
655
689
|
case "networks":
|
|
656
690
|
return "Which networks should this agent trade on: Solana, Base, or both?";
|
|
657
691
|
case "solana-recovery-wallet":
|
|
658
|
-
return "Paste your Solana recovery/withdrawal wallet address. This is
|
|
692
|
+
return "Paste your Solana root/recovery/withdrawal wallet address. This same address is used for Solana recovery and SOL/SPL withdrawals. It is separate from the Solana trading wallet I create for execution.";
|
|
659
693
|
case "solana-recovery-wallet-confirm":
|
|
660
|
-
return "Paste the same Solana
|
|
694
|
+
return "Paste the same Solana wallet again to confirm it.";
|
|
661
695
|
case "slippage":
|
|
662
696
|
return "Set slippage in percent or bps. Examples: 1% = 100 bps, 3% = 300 bps, 5% = 500 bps.";
|
|
663
697
|
case "strategy":
|
|
@@ -679,6 +713,24 @@ export class AgentBridge {
|
|
|
679
713
|
"You can write it messy; I will ask follow-ups if anything critical is missing.",
|
|
680
714
|
].join("\n");
|
|
681
715
|
}
|
|
716
|
+
async createTradingWalletsForSetup(chains) {
|
|
717
|
+
const walletLines = [];
|
|
718
|
+
for (const chain of chains) {
|
|
719
|
+
const structured = await this.callSetupAgent({ action: "create_wallet", chain });
|
|
720
|
+
const wallet = readWallet({ ...structured, chain });
|
|
721
|
+
if (wallet)
|
|
722
|
+
this.upsertWallet(wallet);
|
|
723
|
+
const address = wallet?.address ?? firstString(structured.address, asRecord(structured.wallet)?.address);
|
|
724
|
+
walletLines.push(`${chainTitle(chain)} trading wallet: ${address ?? "(created)"}`);
|
|
725
|
+
}
|
|
726
|
+
return walletLines;
|
|
727
|
+
}
|
|
728
|
+
selectedChainsForSetup(flow) {
|
|
729
|
+
if (flow.selectedChains && flow.selectedChains.length > 0) {
|
|
730
|
+
return flow.selectedChains;
|
|
731
|
+
}
|
|
732
|
+
return [...new Set(this.knownWallets.map((wallet) => wallet.chain))];
|
|
733
|
+
}
|
|
682
734
|
async reviewStrategyWithAi(chain, selectedChains, notes) {
|
|
683
735
|
const fallback = fallbackStrategyReview(chain, notes);
|
|
684
736
|
if (!this.chatAgent)
|
|
@@ -734,7 +786,11 @@ export class AgentBridge {
|
|
|
734
786
|
if (flow.step === "developer-wallet-confirm") {
|
|
735
787
|
const wallet = text.trim();
|
|
736
788
|
if (!flow.developerWallet || wallet.toLowerCase() !== flow.developerWallet.toLowerCase()) {
|
|
737
|
-
this.setupFlow = {
|
|
789
|
+
this.setupFlow = {
|
|
790
|
+
...flow,
|
|
791
|
+
step: "developer-wallet",
|
|
792
|
+
developerWallet: undefined,
|
|
793
|
+
};
|
|
738
794
|
this.addAgentMessage("The confirmation did not match. Start again by pasting the Base/EVM 0x developer wallet.");
|
|
739
795
|
return;
|
|
740
796
|
}
|
|
@@ -747,10 +803,61 @@ export class AgentBridge {
|
|
|
747
803
|
if (masterKey) {
|
|
748
804
|
this.persistMasterKey(masterKey);
|
|
749
805
|
}
|
|
750
|
-
|
|
806
|
+
if (flow.selectedChains && flow.selectedChains.length > 0) {
|
|
807
|
+
const nextFlow = {
|
|
808
|
+
...flow,
|
|
809
|
+
step: "networks",
|
|
810
|
+
rootWalletBound: true,
|
|
811
|
+
rootWalletKind: "evm",
|
|
812
|
+
evmWalletBound: true,
|
|
813
|
+
};
|
|
814
|
+
if (flow.selectedChains.includes("solana") && !flow.solanaRecoveryWallet && !flow.solanaWalletBound) {
|
|
815
|
+
this.setupFlow = { ...nextFlow, step: "solana-recovery-wallet" };
|
|
816
|
+
this.addAgentMessage(`${masterKey ? `Developer wallet bound.
|
|
817
|
+
|
|
818
|
+
Master key saved encrypted locally and shown here so you can copy it externally:
|
|
819
|
+
${masterKey}
|
|
820
|
+
|
|
821
|
+
It is shown once in real environments.` : "Developer wallet bound."}
|
|
822
|
+
|
|
823
|
+
${this.setupPromptFor("solana-recovery-wallet")}`);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
this.setupFlow = nextFlow;
|
|
827
|
+
const walletLines = await this.createTradingWalletsForSetup(flow.selectedChains);
|
|
828
|
+
this.setupFlow = {
|
|
829
|
+
...flow,
|
|
830
|
+
step: "slippage",
|
|
831
|
+
rootWalletBound: true,
|
|
832
|
+
rootWalletKind: "evm",
|
|
833
|
+
evmWalletBound: true,
|
|
834
|
+
};
|
|
835
|
+
this.addAgentMessage(`${masterKey ? `Developer wallet bound.
|
|
836
|
+
|
|
837
|
+
Master key saved encrypted locally and shown here so you can copy it externally:
|
|
838
|
+
${masterKey}
|
|
839
|
+
|
|
840
|
+
It is shown once in real environments.` : "Developer wallet bound."}
|
|
841
|
+
|
|
842
|
+
Copyable trading wallet addresses:
|
|
843
|
+
${walletLines.join("\n")}
|
|
844
|
+
|
|
845
|
+
${this.setupPromptFor("slippage")}`);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
this.setupFlow = { step: "networks", rootWalletBound: true, rootWalletKind: "evm", evmWalletBound: true };
|
|
751
849
|
this.addAgentMessage(masterKey
|
|
752
|
-
? `Developer wallet bound
|
|
753
|
-
|
|
850
|
+
? `Developer wallet bound.
|
|
851
|
+
|
|
852
|
+
Master key saved encrypted locally and shown here so you can copy it externally:
|
|
853
|
+
${masterKey}
|
|
854
|
+
|
|
855
|
+
It is shown once in real environments.
|
|
856
|
+
|
|
857
|
+
${this.setupPromptFor("networks")}`
|
|
858
|
+
: `Developer wallet bound.
|
|
859
|
+
|
|
860
|
+
${this.setupPromptFor("networks")}`);
|
|
754
861
|
return;
|
|
755
862
|
}
|
|
756
863
|
if (flow.step === "networks") {
|
|
@@ -759,20 +866,32 @@ export class AgentBridge {
|
|
|
759
866
|
this.addAgentMessage("Choose Solana, Base, or both.");
|
|
760
867
|
return;
|
|
761
868
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
869
|
+
if (chains.includes("base") && !flow.evmWalletBound) {
|
|
870
|
+
this.setupFlow = { ...flow, step: "developer-wallet", selectedChains: chains };
|
|
871
|
+
this.addAgentMessage(`Trading networks selected: ${formatChains(chains)}.
|
|
872
|
+
|
|
873
|
+
${this.setupPromptFor("developer-wallet")}`);
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
if (chains.includes("solana") && !flow.solanaRecoveryWallet && !flow.solanaWalletBound) {
|
|
877
|
+
this.setupFlow = { ...flow, step: "solana-recovery-wallet", selectedChains: chains };
|
|
878
|
+
this.addAgentMessage(`Trading networks selected: ${formatChains(chains)}.
|
|
879
|
+
|
|
880
|
+
${this.setupPromptFor("solana-recovery-wallet")}`);
|
|
881
|
+
return;
|
|
770
882
|
}
|
|
883
|
+
const walletLines = await this.createTradingWalletsForSetup(chains);
|
|
771
884
|
this.setupFlow = {
|
|
772
|
-
|
|
885
|
+
...flow,
|
|
886
|
+
step: "slippage",
|
|
773
887
|
selectedChains: chains,
|
|
774
888
|
};
|
|
775
|
-
this.addAgentMessage(`Trading networks configured: ${formatChains(chains)}
|
|
889
|
+
this.addAgentMessage(`Trading networks configured: ${formatChains(chains)}.
|
|
890
|
+
|
|
891
|
+
Copyable trading wallet addresses:
|
|
892
|
+
${walletLines.join("\n")}
|
|
893
|
+
|
|
894
|
+
${this.setupPromptFor("slippage")}`);
|
|
776
895
|
return;
|
|
777
896
|
}
|
|
778
897
|
if (flow.step === "solana-recovery-wallet") {
|
|
@@ -791,11 +910,59 @@ export class AgentBridge {
|
|
|
791
910
|
this.setupFlow = {
|
|
792
911
|
step: "solana-recovery-wallet",
|
|
793
912
|
...(flow.developerWallet ? { developerWallet: flow.developerWallet } : {}),
|
|
913
|
+
...(flow.rootWalletBound !== undefined ? { rootWalletBound: flow.rootWalletBound } : {}),
|
|
914
|
+
...(flow.rootWalletKind ? { rootWalletKind: flow.rootWalletKind } : {}),
|
|
915
|
+
...(flow.evmWalletBound !== undefined ? { evmWalletBound: flow.evmWalletBound } : {}),
|
|
916
|
+
...(flow.solanaWalletBound !== undefined ? { solanaWalletBound: flow.solanaWalletBound } : {}),
|
|
794
917
|
...(flow.selectedChains ? { selectedChains: flow.selectedChains } : {}),
|
|
795
918
|
};
|
|
796
919
|
this.addAgentMessage("The Solana wallet confirmation did not match. Paste the Solana recovery/withdrawal wallet again.");
|
|
797
920
|
return;
|
|
798
921
|
}
|
|
922
|
+
if (!flow.rootWalletBound) {
|
|
923
|
+
const structured = await this.callSetupAgent({
|
|
924
|
+
action: "bind_solana_root_wallet",
|
|
925
|
+
solanaWalletAddress: flow.solanaRecoveryWallet,
|
|
926
|
+
solanaWalletAddressConfirm: wallet,
|
|
927
|
+
});
|
|
928
|
+
const masterKey = extractMasterKey(structured);
|
|
929
|
+
if (masterKey) {
|
|
930
|
+
this.persistMasterKey(masterKey);
|
|
931
|
+
}
|
|
932
|
+
const selectedChains = flow.selectedChains && flow.selectedChains.length > 0 ? flow.selectedChains : ["solana"];
|
|
933
|
+
this.setupFlow = {
|
|
934
|
+
...flow,
|
|
935
|
+
step: "networks",
|
|
936
|
+
solanaRecoveryWallet: wallet,
|
|
937
|
+
rootWalletBound: true,
|
|
938
|
+
rootWalletKind: "solana",
|
|
939
|
+
solanaWalletBound: true,
|
|
940
|
+
selectedChains,
|
|
941
|
+
};
|
|
942
|
+
const walletLines = await this.createTradingWalletsForSetup(selectedChains);
|
|
943
|
+
this.setupFlow = {
|
|
944
|
+
...flow,
|
|
945
|
+
step: "slippage",
|
|
946
|
+
solanaRecoveryWallet: wallet,
|
|
947
|
+
rootWalletBound: true,
|
|
948
|
+
rootWalletKind: "solana",
|
|
949
|
+
solanaWalletBound: true,
|
|
950
|
+
selectedChains,
|
|
951
|
+
};
|
|
952
|
+
this.addAgentMessage(`Solana developer/recovery wallet confirmed:
|
|
953
|
+
${wallet}
|
|
954
|
+
|
|
955
|
+
${masterKey ? `Master key saved encrypted locally and shown here so you can copy it externally:
|
|
956
|
+
${masterKey}
|
|
957
|
+
|
|
958
|
+
It is shown once in real environments.
|
|
959
|
+
|
|
960
|
+
` : ""}Copyable trading wallet addresses:
|
|
961
|
+
${walletLines.join("\n")}
|
|
962
|
+
|
|
963
|
+
${this.setupPromptFor("slippage")}`);
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
799
966
|
try {
|
|
800
967
|
await this.callSetupAgent({
|
|
801
968
|
action: "bind_solana_developer_wallet",
|
|
@@ -806,8 +973,26 @@ export class AgentBridge {
|
|
|
806
973
|
catch (err) {
|
|
807
974
|
this.addSystemMessage(`Solana recovery wallet stored locally for this setup. MCP did not bind it directly: ${err instanceof Error ? err.message : String(err)}`);
|
|
808
975
|
}
|
|
809
|
-
|
|
810
|
-
|
|
976
|
+
const selectedChains = flow.selectedChains && flow.selectedChains.length > 0
|
|
977
|
+
? flow.selectedChains
|
|
978
|
+
: this.selectedChainsForSetup(flow);
|
|
979
|
+
const walletLines = selectedChains.length > 0
|
|
980
|
+
? await this.createTradingWalletsForSetup(selectedChains)
|
|
981
|
+
: [];
|
|
982
|
+
this.setupFlow = {
|
|
983
|
+
...flow,
|
|
984
|
+
step: "slippage",
|
|
985
|
+
solanaRecoveryWallet: wallet,
|
|
986
|
+
solanaWalletBound: true,
|
|
987
|
+
...(selectedChains.length > 0 ? { selectedChains } : {}),
|
|
988
|
+
};
|
|
989
|
+
this.addAgentMessage(`Solana recovery/withdrawal wallet confirmed:
|
|
990
|
+
${wallet}
|
|
991
|
+
|
|
992
|
+
${walletLines.length > 0 ? `Copyable trading wallet addresses:
|
|
993
|
+
${walletLines.join("\n")}
|
|
994
|
+
|
|
995
|
+
` : ""}${this.setupPromptFor("slippage")}`);
|
|
811
996
|
return;
|
|
812
997
|
}
|
|
813
998
|
if (flow.step === "slippage") {
|
|
@@ -817,7 +1002,12 @@ export class AgentBridge {
|
|
|
817
1002
|
return;
|
|
818
1003
|
}
|
|
819
1004
|
await this.callSetupAgent({ action: "configure_slippage", slippageBps: bps });
|
|
820
|
-
const selectedChains = flow
|
|
1005
|
+
const selectedChains = this.selectedChainsForSetup(flow);
|
|
1006
|
+
if (selectedChains.length === 0) {
|
|
1007
|
+
this.setupFlow = { ...flow, step: "networks" };
|
|
1008
|
+
this.addAgentMessage(`I need the selected trading networks before strategy setup.\n\n${this.setupPromptFor("networks")}`);
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
821
1011
|
const currentStrategyChain = nextStrategyChain(selectedChains, {}) ?? selectedChains[0];
|
|
822
1012
|
this.setupFlow = { ...flow, step: "strategy", slippageBps: bps, currentStrategyChain, chainStrategies: {} };
|
|
823
1013
|
this.addAgentMessage(`Slippage set to ${bps} bps.\n\n${this.setupPromptForStrategyChain(currentStrategyChain)}`);
|
|
@@ -825,14 +1015,20 @@ export class AgentBridge {
|
|
|
825
1015
|
}
|
|
826
1016
|
if (flow.step === "strategy") {
|
|
827
1017
|
const strategyNote = text.trim();
|
|
828
|
-
const
|
|
1018
|
+
const selectedChainsForFlow = this.selectedChainsForSetup(flow);
|
|
1019
|
+
const chain = flow.currentStrategyChain ?? selectedChainsForFlow[0];
|
|
1020
|
+
if (!chain) {
|
|
1021
|
+
this.setupFlow = { ...flow, step: "networks" };
|
|
1022
|
+
this.addAgentMessage(`I need the selected trading networks before strategy setup.\n\n${this.setupPromptFor("networks")}`);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
829
1025
|
if (strategyNote.length < 8) {
|
|
830
1026
|
this.addAgentMessage("That is too short for live setup. Add trade size, entry filters, exits, max positions, or avoid rules.");
|
|
831
1027
|
return;
|
|
832
1028
|
}
|
|
833
1029
|
const previousNotes = flow.strategyNotes?.[chain] ?? [];
|
|
834
1030
|
const notes = [...previousNotes, strategyNote];
|
|
835
|
-
const selectedChains =
|
|
1031
|
+
const selectedChains = selectedChainsForFlow.length > 0 ? selectedChainsForFlow : [chain];
|
|
836
1032
|
const strategyNotes = {
|
|
837
1033
|
...(flow.strategyNotes ?? {}),
|
|
838
1034
|
[chain]: notes,
|
|
@@ -891,12 +1087,14 @@ export class AgentBridge {
|
|
|
891
1087
|
step: "strategy",
|
|
892
1088
|
...(flow.developerWallet ? { developerWallet: flow.developerWallet } : {}),
|
|
893
1089
|
...(flow.solanaRecoveryWallet ? { solanaRecoveryWallet: flow.solanaRecoveryWallet } : {}),
|
|
1090
|
+
...(flow.rootWalletBound !== undefined ? { rootWalletBound: flow.rootWalletBound } : {}),
|
|
1091
|
+
...(flow.rootWalletKind ? { rootWalletKind: flow.rootWalletKind } : {}),
|
|
894
1092
|
...(flow.selectedChains ? { selectedChains: flow.selectedChains } : {}),
|
|
895
1093
|
...(flow.slippageBps !== undefined ? { slippageBps: flow.slippageBps } : {}),
|
|
896
1094
|
chainStrategies: {},
|
|
897
|
-
currentStrategyChain: (flow
|
|
1095
|
+
currentStrategyChain: this.selectedChainsForSetup(flow)[0] ?? "solana",
|
|
898
1096
|
};
|
|
899
|
-
this.addAgentMessage(this.setupPromptForStrategyChain((flow
|
|
1097
|
+
this.addAgentMessage(this.setupPromptForStrategyChain(this.selectedChainsForSetup(flow)[0] ?? "solana"));
|
|
900
1098
|
return;
|
|
901
1099
|
}
|
|
902
1100
|
if (!isAffirmative(text)) {
|
|
@@ -905,7 +1103,7 @@ export class AgentBridge {
|
|
|
905
1103
|
}
|
|
906
1104
|
if (!flow.strategyText) {
|
|
907
1105
|
this.setupFlow = { ...flow, step: "strategy" };
|
|
908
|
-
this.addAgentMessage(this.setupPromptForStrategyChain(flow.currentStrategyChain ?? (flow
|
|
1106
|
+
this.addAgentMessage(this.setupPromptForStrategyChain(flow.currentStrategyChain ?? this.selectedChainsForSetup(flow)[0] ?? "solana"));
|
|
909
1107
|
return;
|
|
910
1108
|
}
|
|
911
1109
|
await this.callSetupAgent({
|
|
@@ -922,7 +1120,7 @@ export class AgentBridge {
|
|
|
922
1120
|
}
|
|
923
1121
|
if (flow.step === "subscriptions") {
|
|
924
1122
|
if (isAffirmative(text)) {
|
|
925
|
-
const chains = flow
|
|
1123
|
+
const chains = this.selectedChainsForSetup(flow);
|
|
926
1124
|
if (chains.includes("solana")) {
|
|
927
1125
|
await this.mcp.callTool("create_subscription", {
|
|
928
1126
|
type: "new_token_launch",
|
|
@@ -943,7 +1141,7 @@ export class AgentBridge {
|
|
|
943
1141
|
}
|
|
944
1142
|
}
|
|
945
1143
|
catch (err) {
|
|
946
|
-
this.addErrorMessage(`Setup failed: ${err
|
|
1144
|
+
this.addErrorMessage(`Setup failed: ${friendlyError(err).replace(/^LLM error: /, "")}`);
|
|
947
1145
|
this.addAgentMessage(`${this.setupPromptFor(this.setupFlow?.step ?? flow.step)} Try again.`);
|
|
948
1146
|
}
|
|
949
1147
|
}
|