@prktsol/prkt 1.0.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/.env.devnet.all-protocols.example +18 -0
- package/.env.devnet.autonomous.example +16 -0
- package/.env.devnet.jupiter.example +16 -0
- package/.env.devnet.kamino.example +17 -0
- package/.env.devnet.marinade.example +16 -0
- package/.env.devnet.orca.example +16 -0
- package/.env.devnet.raydium.example +17 -0
- package/.env.example +32 -0
- package/ARCHITECTURE.md +159 -0
- package/CLI.md +509 -0
- package/CLI_QUICKSTART.md +108 -0
- package/COMPATIBILITY.md +103 -0
- package/DEVNET_PROTOCOL_ADDRESSES.md +72 -0
- package/README.md +339 -0
- package/dist/agent/AgentManager.js +166 -0
- package/dist/agent/AgentRuntime.js +92 -0
- package/dist/agent/DecisionEngine.js +95 -0
- package/dist/agent/MockPriceFeed.js +13 -0
- package/dist/agent/intents/types.js +2 -0
- package/dist/agent/new-index.js +17 -0
- package/dist/agent/policyFactory.js +54 -0
- package/dist/agent/registry/AgentRegistry.js +16 -0
- package/dist/agent/runner/AgentRunner.js +266 -0
- package/dist/agent/strategies/MemoHeartbeatStrategy.js +15 -0
- package/dist/agent/strategies/SimpleScriptedTransferStrategy.js +27 -0
- package/dist/agent/strategies/TokenRebalancerStrategy.js +35 -0
- package/dist/agent/strategies/TreasuryDistributorStrategy.js +29 -0
- package/dist/agent/strategies/UniversalDeFiStrategy.js +19 -0
- package/dist/agent/types/AgentContext.js +2 -0
- package/dist/cli/index.js +1159 -0
- package/dist/cli/services/activityStore.js +42 -0
- package/dist/cli/services/agentRegistry.js +123 -0
- package/dist/cli/services/agentRuntime.js +55 -0
- package/dist/cli/services/storagePaths.js +64 -0
- package/dist/cli/services/strategyFactory.js +66 -0
- package/dist/cli/services/walletCrypto.js +120 -0
- package/dist/cli/services/walletRegistry.js +145 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/utils/completion.js +62 -0
- package/dist/cli/utils/output.js +44 -0
- package/dist/config/agentPolicies.js +37 -0
- package/dist/config/env.js +249 -0
- package/dist/config/policyPresets.js +105 -0
- package/dist/core/balances/BalanceService.js +34 -0
- package/dist/core/funding/DevnetFundingService.js +105 -0
- package/dist/core/idempotency/ExecutionIdempotencyGuard.js +100 -0
- package/dist/core/index.js +19 -0
- package/dist/core/rpc/RpcClient.js +45 -0
- package/dist/core/rpc/RpcFailoverClient.js +97 -0
- package/dist/core/tokens/TokenService.js +75 -0
- package/dist/core/transactions/PostTransactionVerifier.js +103 -0
- package/dist/core/transactions/TransactionService.js +104 -0
- package/dist/core/types/services.js +2 -0
- package/dist/core/wallet/WalletManager.js +120 -0
- package/dist/defi/DeFiCoordinator.js +93 -0
- package/dist/defi/DeFiExecutor.js +29 -0
- package/dist/defi/DeFiPolicyGuard.js +31 -0
- package/dist/defi/adapters/JupiterAdapter.js +25 -0
- package/dist/defi/adapters/KaminoAdapter.js +50 -0
- package/dist/defi/adapters/MarinadeAdapter.js +25 -0
- package/dist/defi/adapters/RaydiumAdapter.js +45 -0
- package/dist/defi/kamino/kaminoInstructionCompat.js +24 -0
- package/dist/defi/kamino/kaminoLiveConfig.js +60 -0
- package/dist/defi/kamino/loadKaminoMarketWithFallback.js +68 -0
- package/dist/defi/lp/LpInstructionBuilder.js +2 -0
- package/dist/defi/lp/RaydiumLpInstructionBuilder.js +100 -0
- package/dist/defi/lp/raydiumDevnetConfig.js +62 -0
- package/dist/defi/protocols.js +29 -0
- package/dist/defi/types.js +2 -0
- package/dist/defi/universal/UniversalDeFiOrchestrator.js +126 -0
- package/dist/defi/universal/adapters.js +73 -0
- package/dist/defi/universal/index.js +5 -0
- package/dist/defi/universal/liveExecutors.js +394 -0
- package/dist/defi/universal/types.js +2 -0
- package/dist/demo/scenarios/multiAgentDevnetScenario.js +170 -0
- package/dist/demo/scripts/runMultiAgentDevnetDemo.js +17 -0
- package/dist/dex/JupiterSwapClient.js +59 -0
- package/dist/dex/SwapExecutor.js +52 -0
- package/dist/index.js +22 -0
- package/dist/kora/KoraRpcClient.js +60 -0
- package/dist/kora/KoraSigner.js +57 -0
- package/dist/kora/gaslessDemo.js +18 -0
- package/dist/policy/PolicyGuard.js +158 -0
- package/dist/policy/emergencyLock.js +164 -0
- package/dist/policy/engine/PolicyEngine.js +237 -0
- package/dist/policy/errors.js +10 -0
- package/dist/policy/index.js +7 -0
- package/dist/policy/sandbox/SandboxExecutor.js +77 -0
- package/dist/policy/types/policy.js +2 -0
- package/dist/scripts/devnetFunding.js +28 -0
- package/dist/scripts/devnetWalletPreflight.js +16 -0
- package/dist/scripts/localnetCheck.js +27 -0
- package/dist/scripts/managedAgentWallet.js +81 -0
- package/dist/scripts/mode.js +6 -0
- package/dist/scripts/releaseReadiness.js +93 -0
- package/dist/scripts/runAgentUniversalDeFi.js +115 -0
- package/dist/scripts/runAutonomousAgentWalletDevnet.js +154 -0
- package/dist/scripts/runAutonomousPortfolioDevnet.js +390 -0
- package/dist/scripts/runBorrowStrategy.js +35 -0
- package/dist/scripts/runDeFiSuite.js +41 -0
- package/dist/scripts/runDemoRehearsal.js +111 -0
- package/dist/scripts/runDevnetWalletDemo.js +53 -0
- package/dist/scripts/runGaslessMemo.js +23 -0
- package/dist/scripts/runGaslessWalletDemo.js +60 -0
- package/dist/scripts/runKaminoDevnet.js +109 -0
- package/dist/scripts/runLpStrategy.js +32 -0
- package/dist/scripts/runMarinadeDevnet.js +97 -0
- package/dist/scripts/runOrcaLpDevnet.js +208 -0
- package/dist/scripts/runRaydiumLpDevnet.js +95 -0
- package/dist/scripts/runReleaseReadiness.js +22 -0
- package/dist/scripts/runStakeStrategy.js +33 -0
- package/dist/scripts/runStressTest.js +41 -0
- package/dist/scripts/runTradeLoop.js +53 -0
- package/dist/scripts/runUniversalDeFiDemo.js +84 -0
- package/dist/scripts/runYieldStrategy.js +33 -0
- package/dist/scripts/runtimeFactory.js +27 -0
- package/dist/scripts/shared.js +24 -0
- package/dist/scripts/simulateAttack.js +40 -0
- package/dist/scripts/simulateSwarm.js +106 -0
- package/dist/simulation/attack.js +30 -0
- package/dist/solana/programs.js +9 -0
- package/dist/spl/TokenWallet.js +65 -0
- package/dist/types/policy.js +2 -0
- package/dist/wallet/WalletManager.js +5 -0
- package/package.json +99 -0
|
@@ -0,0 +1,1159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
8
|
+
const agentRegistry_1 = require("./services/agentRegistry");
|
|
9
|
+
const agentRuntime_1 = require("./services/agentRuntime");
|
|
10
|
+
const activityStore_1 = require("./services/activityStore");
|
|
11
|
+
const storagePaths_1 = require("./services/storagePaths");
|
|
12
|
+
const walletRegistry_1 = require("./services/walletRegistry");
|
|
13
|
+
const walletCrypto_1 = require("./services/walletCrypto");
|
|
14
|
+
const output_1 = require("./utils/output");
|
|
15
|
+
const env_1 = require("../config/env");
|
|
16
|
+
const policyPresets_1 = require("../config/policyPresets");
|
|
17
|
+
const RpcClient_1 = require("../core/rpc/RpcClient");
|
|
18
|
+
const TransactionService_1 = require("../core/transactions/TransactionService");
|
|
19
|
+
const TokenService_1 = require("../core/tokens/TokenService");
|
|
20
|
+
const BalanceService_1 = require("../core/balances/BalanceService");
|
|
21
|
+
const DevnetFundingService_1 = require("../core/funding/DevnetFundingService");
|
|
22
|
+
const multiAgentDevnetScenario_1 = require("../demo/scenarios/multiAgentDevnetScenario");
|
|
23
|
+
const policy_1 = require("../policy");
|
|
24
|
+
const completion_1 = require("./utils/completion");
|
|
25
|
+
const program = new commander_1.Command();
|
|
26
|
+
const walletRegistry = new walletRegistry_1.WalletRegistry();
|
|
27
|
+
const agentRegistry = new agentRegistry_1.AgentRegistryStore(walletRegistry);
|
|
28
|
+
const activityStore = new activityStore_1.ActivityStore();
|
|
29
|
+
const CUSTODY_MODEL = "local-per-user";
|
|
30
|
+
const POLICY_EXECUTION_MODEL = "user-owned agent wallets with policy-guarded execution";
|
|
31
|
+
function outputOptions(command) {
|
|
32
|
+
const options = command.optsWithGlobals();
|
|
33
|
+
return {
|
|
34
|
+
json: Boolean(options.json)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function activity(kind, details, extra) {
|
|
38
|
+
try {
|
|
39
|
+
activityStore.append({
|
|
40
|
+
createdAtIso: new Date().toISOString(),
|
|
41
|
+
kind,
|
|
42
|
+
details,
|
|
43
|
+
...extra
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : "unknown activity-store error";
|
|
48
|
+
console.error(`Activity log warning: ${message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function resolveWalletName(entity) {
|
|
52
|
+
const wallet = walletRegistry.find(entity);
|
|
53
|
+
if (wallet) {
|
|
54
|
+
return wallet.name;
|
|
55
|
+
}
|
|
56
|
+
const agent = agentRegistry.find(entity);
|
|
57
|
+
if (agent) {
|
|
58
|
+
return agent.walletName;
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`Unknown wallet/agent '${entity}'.`);
|
|
61
|
+
}
|
|
62
|
+
function resolveAgentRecord(agentId) {
|
|
63
|
+
const agent = agentRegistry.find(agentId);
|
|
64
|
+
if (agent) {
|
|
65
|
+
return agent;
|
|
66
|
+
}
|
|
67
|
+
const wallet = walletRegistry.find(agentId);
|
|
68
|
+
if (wallet) {
|
|
69
|
+
return agentRegistry.ensureForWallet(wallet.name);
|
|
70
|
+
}
|
|
71
|
+
throw new Error(`Unknown agent '${agentId}'.`);
|
|
72
|
+
}
|
|
73
|
+
function parseSol(input) {
|
|
74
|
+
const value = Number(input);
|
|
75
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
76
|
+
throw new Error("amount must be a positive number");
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
function parseOptionalCsv(input) {
|
|
81
|
+
if (!input) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const values = input
|
|
85
|
+
.split(",")
|
|
86
|
+
.map((entry) => entry.trim())
|
|
87
|
+
.filter((entry) => entry.length > 0);
|
|
88
|
+
return values.length > 0 ? values : [];
|
|
89
|
+
}
|
|
90
|
+
function parseOptionalPositiveInteger(input, fieldName) {
|
|
91
|
+
if (input === undefined) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const parsed = Number(input);
|
|
95
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
96
|
+
throw new Error(`${fieldName} must be a non-negative integer`);
|
|
97
|
+
}
|
|
98
|
+
return parsed;
|
|
99
|
+
}
|
|
100
|
+
async function buildServices() {
|
|
101
|
+
const rpcClient = new RpcClient_1.RpcClient((0, env_1.getRpcUrl)(), "confirmed");
|
|
102
|
+
const tokenService = new TokenService_1.TokenService(rpcClient);
|
|
103
|
+
const transactionService = new TransactionService_1.TransactionService(rpcClient);
|
|
104
|
+
const balanceService = new BalanceService_1.BalanceService(rpcClient, tokenService);
|
|
105
|
+
return { balanceService, rpcClient, tokenService, transactionService };
|
|
106
|
+
}
|
|
107
|
+
async function buildOverviewRows() {
|
|
108
|
+
const { balanceService } = await buildServices();
|
|
109
|
+
const agents = agentRegistry.synchronizeWithWallets();
|
|
110
|
+
const rows = [];
|
|
111
|
+
for (const entry of agents) {
|
|
112
|
+
const wallet = walletRegistry.find(entry.walletName);
|
|
113
|
+
if (!wallet) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const owner = new web3_js_1.PublicKey(wallet.publicKey);
|
|
117
|
+
const sol = await balanceService.getSolBalance(owner);
|
|
118
|
+
const trackedMints = entry.trackedMints ?? [];
|
|
119
|
+
const trackedSpl = [];
|
|
120
|
+
for (const mint of trackedMints) {
|
|
121
|
+
const balance = await balanceService.getSplTokenBalance({
|
|
122
|
+
owner,
|
|
123
|
+
mint: new web3_js_1.PublicKey(mint)
|
|
124
|
+
});
|
|
125
|
+
trackedSpl.push(`${mint.slice(0, 6)}...:${balance.toFixed(4)}`);
|
|
126
|
+
}
|
|
127
|
+
rows.push({
|
|
128
|
+
agent: entry.name,
|
|
129
|
+
lastAction: entry.lastAction ?? "-",
|
|
130
|
+
lastSignature: entry.lastSignature ?? "-",
|
|
131
|
+
policyMode: entry.policyMode,
|
|
132
|
+
sol: sol.toFixed(4),
|
|
133
|
+
status: entry.status,
|
|
134
|
+
trackedSpl: trackedSpl.join(", ") || "-",
|
|
135
|
+
wallet: wallet.publicKey
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return rows;
|
|
139
|
+
}
|
|
140
|
+
program
|
|
141
|
+
.name("prkt")
|
|
142
|
+
.description("PRKT CLI - Solana agentic wallet operations")
|
|
143
|
+
.option("--json", "output machine-readable JSON");
|
|
144
|
+
program
|
|
145
|
+
.command("init")
|
|
146
|
+
.description("initialize local PRKT state for this user install")
|
|
147
|
+
.action((_, command) => {
|
|
148
|
+
const dataDirStatus = (0, storagePaths_1.probeCliDataDir)();
|
|
149
|
+
const payload = {
|
|
150
|
+
cliDataDir: dataDirStatus.path,
|
|
151
|
+
cliDataDirHealth: dataDirStatus.details,
|
|
152
|
+
cliDataDirWritable: dataDirStatus.writable,
|
|
153
|
+
custodyModel: CUSTODY_MODEL,
|
|
154
|
+
masterKeySource: (0, walletCrypto_1.getPlatformMasterKeySource)(),
|
|
155
|
+
policyExecutionModel: POLICY_EXECUTION_MODEL,
|
|
156
|
+
recommendedNextSteps: [
|
|
157
|
+
"Run `prkt config show` to inspect runtime config",
|
|
158
|
+
"Run `prkt wallet create --name <name>` or `prkt agent create --agent <id>` to provision a wallet",
|
|
159
|
+
"Use `prkt policy show --agent <agent>` and `prkt policy set-limits ...` before enabling live execution"
|
|
160
|
+
]
|
|
161
|
+
};
|
|
162
|
+
activity("config", { action: "init" });
|
|
163
|
+
(0, output_1.printResult)(outputOptions(command), payload, "PRKT initialized");
|
|
164
|
+
});
|
|
165
|
+
const wallet = program.command("wallet").description("wallet management and transfers");
|
|
166
|
+
wallet
|
|
167
|
+
.command("create")
|
|
168
|
+
.requiredOption("--name <name>", "wallet name")
|
|
169
|
+
.description("create a managed wallet")
|
|
170
|
+
.action((options, command) => {
|
|
171
|
+
const created = walletRegistry.create(options.name);
|
|
172
|
+
const agent = agentRegistry.ensureForWallet(options.name);
|
|
173
|
+
activity("wallet", { action: "create", name: options.name, publicKey: created.record.publicKey });
|
|
174
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
175
|
+
custodyModel: CUSTODY_MODEL,
|
|
176
|
+
dataDir: (0, storagePaths_1.getCliDataDir)(),
|
|
177
|
+
defaultPolicyPreset: agent.policyPreset,
|
|
178
|
+
explorer: (0, output_1.addressExplorer)(created.record.publicKey),
|
|
179
|
+
name: created.record.name,
|
|
180
|
+
publicKey: created.record.publicKey,
|
|
181
|
+
masterKeySource: (0, walletCrypto_1.getPlatformMasterKeySource)(),
|
|
182
|
+
recoveryKey: created.recoveryKey
|
|
183
|
+
}, `Wallet ${options.name} created`);
|
|
184
|
+
});
|
|
185
|
+
wallet
|
|
186
|
+
.command("list")
|
|
187
|
+
.description("list managed wallets")
|
|
188
|
+
.action((_, command) => {
|
|
189
|
+
const wallets = walletRegistry.list().map((entry) => ({
|
|
190
|
+
createdAt: entry.createdAtIso,
|
|
191
|
+
name: entry.name,
|
|
192
|
+
publicKey: entry.publicKey
|
|
193
|
+
}));
|
|
194
|
+
(0, output_1.printResult)(outputOptions(command), wallets, "Managed wallets");
|
|
195
|
+
});
|
|
196
|
+
wallet
|
|
197
|
+
.command("show")
|
|
198
|
+
.requiredOption("--name <name>", "wallet name")
|
|
199
|
+
.description("show wallet details")
|
|
200
|
+
.action((options, command) => {
|
|
201
|
+
const record = walletRegistry.find(options.name);
|
|
202
|
+
if (!record) {
|
|
203
|
+
throw new Error(`Wallet '${options.name}' not found.`);
|
|
204
|
+
}
|
|
205
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
206
|
+
createdAt: record.createdAtIso,
|
|
207
|
+
explorer: (0, output_1.addressExplorer)(record.publicKey),
|
|
208
|
+
name: record.name,
|
|
209
|
+
publicKey: record.publicKey
|
|
210
|
+
}, `Wallet ${options.name}`);
|
|
211
|
+
});
|
|
212
|
+
wallet
|
|
213
|
+
.command("fund")
|
|
214
|
+
.requiredOption("--name <name>", "wallet name")
|
|
215
|
+
.requiredOption("--sol <amount>", "amount in SOL")
|
|
216
|
+
.description("fund wallet from treasury if configured, otherwise request devnet airdrop")
|
|
217
|
+
.action(async (options, command) => {
|
|
218
|
+
const amountSol = parseSol(options.sol);
|
|
219
|
+
const walletName = resolveWalletName(options.name);
|
|
220
|
+
const walletManager = walletRegistry.toWalletManager(walletName);
|
|
221
|
+
const { balanceService, rpcClient, transactionService } = await buildServices();
|
|
222
|
+
const fundingService = new DevnetFundingService_1.DevnetFundingService(rpcClient, transactionService);
|
|
223
|
+
const funding = await fundingService.fundExactSol({
|
|
224
|
+
amountSol,
|
|
225
|
+
recipient: walletManager.publicKey
|
|
226
|
+
});
|
|
227
|
+
const updatedBalance = await fundingService.waitForMinimumBalance({
|
|
228
|
+
attempts: 15,
|
|
229
|
+
balanceService,
|
|
230
|
+
minimumSol: amountSol,
|
|
231
|
+
recipient: walletManager.publicKey
|
|
232
|
+
});
|
|
233
|
+
activity("wallet", {
|
|
234
|
+
action: "fund",
|
|
235
|
+
amountSol,
|
|
236
|
+
method: funding.source,
|
|
237
|
+
name: options.name
|
|
238
|
+
}, { signature: funding.signature });
|
|
239
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
240
|
+
amountSol,
|
|
241
|
+
balanceSol: updatedBalance,
|
|
242
|
+
explorer: (0, output_1.txExplorer)(funding.signature),
|
|
243
|
+
signature: funding.signature,
|
|
244
|
+
source: funding.source,
|
|
245
|
+
wallet: walletName
|
|
246
|
+
}, `Wallet ${walletName} funded`);
|
|
247
|
+
});
|
|
248
|
+
wallet
|
|
249
|
+
.command("balance")
|
|
250
|
+
.requiredOption("--name <name>", "wallet name")
|
|
251
|
+
.description("fetch SOL balance")
|
|
252
|
+
.action(async (options, command) => {
|
|
253
|
+
const walletName = resolveWalletName(options.name);
|
|
254
|
+
const walletManager = walletRegistry.toWalletManager(walletName);
|
|
255
|
+
const { balanceService } = await buildServices();
|
|
256
|
+
const sol = await balanceService.getSolBalance(walletManager.publicKey);
|
|
257
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
258
|
+
balanceSol: sol,
|
|
259
|
+
name: walletName,
|
|
260
|
+
publicKey: walletManager.publicKey.toBase58()
|
|
261
|
+
}, `SOL balance for ${walletName}`);
|
|
262
|
+
});
|
|
263
|
+
wallet
|
|
264
|
+
.command("balance-spl")
|
|
265
|
+
.requiredOption("--name <name>", "wallet name")
|
|
266
|
+
.requiredOption("--mint <mint>", "mint address")
|
|
267
|
+
.description("fetch SPL token balance for wallet")
|
|
268
|
+
.action(async (options, command) => {
|
|
269
|
+
const walletName = resolveWalletName(options.name);
|
|
270
|
+
const walletManager = walletRegistry.toWalletManager(walletName);
|
|
271
|
+
const { balanceService } = await buildServices();
|
|
272
|
+
const mint = new web3_js_1.PublicKey(options.mint);
|
|
273
|
+
const balance = await balanceService.getSplTokenBalance({
|
|
274
|
+
owner: walletManager.publicKey,
|
|
275
|
+
mint
|
|
276
|
+
});
|
|
277
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
278
|
+
balance,
|
|
279
|
+
mint: mint.toBase58(),
|
|
280
|
+
name: walletName
|
|
281
|
+
}, `SPL balance for ${walletName}`);
|
|
282
|
+
});
|
|
283
|
+
wallet
|
|
284
|
+
.command("export-secret")
|
|
285
|
+
.requiredOption("--name <name>", "wallet name or agent id")
|
|
286
|
+
.requiredOption("--recovery-key <key>", "wallet recovery key")
|
|
287
|
+
.description("decrypt and export the managed wallet secret key")
|
|
288
|
+
.action((options, command) => {
|
|
289
|
+
const walletName = resolveWalletName(options.name);
|
|
290
|
+
const secretKey = Array.from(walletRegistry.exportSecretKeyWithRecovery({
|
|
291
|
+
name: walletName,
|
|
292
|
+
recoveryKey: String(options.recoveryKey)
|
|
293
|
+
}));
|
|
294
|
+
const wallet = walletRegistry.find(walletName);
|
|
295
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
296
|
+
publicKey: wallet?.publicKey ?? "<missing>",
|
|
297
|
+
secretKey,
|
|
298
|
+
wallet: walletName
|
|
299
|
+
}, `Wallet ${walletName} exported`);
|
|
300
|
+
});
|
|
301
|
+
wallet
|
|
302
|
+
.command("transfer-sol")
|
|
303
|
+
.requiredOption("--from <wallet>", "source wallet name")
|
|
304
|
+
.requiredOption("--to <pubkey>", "destination public key")
|
|
305
|
+
.requiredOption("--amount <amount>", "amount in SOL")
|
|
306
|
+
.description("transfer SOL")
|
|
307
|
+
.action(async (options, command) => {
|
|
308
|
+
const walletManager = walletRegistry.toWalletManager(resolveWalletName(options.from));
|
|
309
|
+
const to = new web3_js_1.PublicKey(options.to);
|
|
310
|
+
const amountSol = parseSol(options.amount);
|
|
311
|
+
const { transactionService } = await buildServices();
|
|
312
|
+
const built = await transactionService.buildTransaction({
|
|
313
|
+
feePayer: walletManager.publicKey,
|
|
314
|
+
instructions: [
|
|
315
|
+
transactionService.buildSolTransferInstructionInSol({
|
|
316
|
+
from: walletManager.publicKey,
|
|
317
|
+
to,
|
|
318
|
+
amountSol
|
|
319
|
+
})
|
|
320
|
+
],
|
|
321
|
+
signer: walletManager
|
|
322
|
+
});
|
|
323
|
+
const send = await transactionService.sendAndConfirm(built);
|
|
324
|
+
activity("transfer", {
|
|
325
|
+
amountSol,
|
|
326
|
+
from: options.from,
|
|
327
|
+
to: options.to,
|
|
328
|
+
type: "sol"
|
|
329
|
+
}, { signature: send.signature });
|
|
330
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
331
|
+
amountSol,
|
|
332
|
+
explorer: (0, output_1.txExplorer)(send.signature),
|
|
333
|
+
signature: send.signature
|
|
334
|
+
}, "SOL transfer sent");
|
|
335
|
+
});
|
|
336
|
+
wallet
|
|
337
|
+
.command("transfer-spl")
|
|
338
|
+
.requiredOption("--from <wallet>", "source wallet name")
|
|
339
|
+
.requiredOption("--to <pubkey>", "destination owner public key")
|
|
340
|
+
.requiredOption("--mint <mint>", "mint address")
|
|
341
|
+
.requiredOption("--amount <amount>", "amount in UI units")
|
|
342
|
+
.description("transfer SPL tokens")
|
|
343
|
+
.action(async (options, command) => {
|
|
344
|
+
const walletManager = walletRegistry.toWalletManager(resolveWalletName(options.from));
|
|
345
|
+
const destinationOwner = new web3_js_1.PublicKey(options.to);
|
|
346
|
+
const mint = new web3_js_1.PublicKey(options.mint);
|
|
347
|
+
const amountUi = parseSol(options.amount);
|
|
348
|
+
const { rpcClient, tokenService, transactionService } = await buildServices();
|
|
349
|
+
const mintInfo = await (0, spl_token_1.getMint)(rpcClient.connection, mint, "confirmed");
|
|
350
|
+
const amountRaw = BigInt(Math.round(amountUi * 10 ** mintInfo.decimals));
|
|
351
|
+
const sourceAta = tokenService.findAssociatedTokenAddress(walletManager.publicKey, mint);
|
|
352
|
+
const ensureDestination = await tokenService.ensureAtaInstruction({
|
|
353
|
+
mint,
|
|
354
|
+
owner: destinationOwner,
|
|
355
|
+
payer: walletManager.publicKey
|
|
356
|
+
});
|
|
357
|
+
const instructions = [
|
|
358
|
+
...(ensureDestination.createInstruction ? [ensureDestination.createInstruction] : []),
|
|
359
|
+
transactionService.buildSplTransferCheckedInstruction({
|
|
360
|
+
sourceAta,
|
|
361
|
+
mint,
|
|
362
|
+
destinationAta: ensureDestination.address,
|
|
363
|
+
owner: walletManager.publicKey,
|
|
364
|
+
amount: amountRaw,
|
|
365
|
+
decimals: mintInfo.decimals
|
|
366
|
+
})
|
|
367
|
+
];
|
|
368
|
+
const built = await transactionService.buildTransaction({
|
|
369
|
+
feePayer: walletManager.publicKey,
|
|
370
|
+
instructions,
|
|
371
|
+
signer: walletManager
|
|
372
|
+
});
|
|
373
|
+
const send = await transactionService.sendAndConfirm(built);
|
|
374
|
+
activity("transfer", {
|
|
375
|
+
amountRaw: amountRaw.toString(),
|
|
376
|
+
amountUi,
|
|
377
|
+
from: options.from,
|
|
378
|
+
mint: mint.toBase58(),
|
|
379
|
+
to: options.to,
|
|
380
|
+
type: "spl"
|
|
381
|
+
}, { signature: send.signature });
|
|
382
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
383
|
+
explorer: (0, output_1.txExplorer)(send.signature),
|
|
384
|
+
signature: send.signature
|
|
385
|
+
}, "SPL transfer sent");
|
|
386
|
+
});
|
|
387
|
+
const token = program.command("token").description("SPL token operations");
|
|
388
|
+
token
|
|
389
|
+
.command("mint-demo")
|
|
390
|
+
.requiredOption("--authority <wallet>", "authority wallet name")
|
|
391
|
+
.requiredOption("--decimals <n>", "mint decimals")
|
|
392
|
+
.requiredOption("--amount <amount>", "amount in UI units")
|
|
393
|
+
.description("create demo mint and mint tokens to authority ATA")
|
|
394
|
+
.action(async (options, command) => {
|
|
395
|
+
const authority = walletRegistry.toWalletManager(options.authority);
|
|
396
|
+
const decimals = Number(options.decimals);
|
|
397
|
+
if (!Number.isInteger(decimals) || decimals < 0 || decimals > 9) {
|
|
398
|
+
throw new Error("decimals must be an integer between 0 and 9");
|
|
399
|
+
}
|
|
400
|
+
const amountUi = parseSol(options.amount);
|
|
401
|
+
const { tokenService, transactionService } = await buildServices();
|
|
402
|
+
const mintSetup = await tokenService.buildCreateMintInstructions({
|
|
403
|
+
payer: authority.publicKey,
|
|
404
|
+
mintAuthority: authority.publicKey,
|
|
405
|
+
decimals
|
|
406
|
+
});
|
|
407
|
+
const mintTx = await transactionService.buildTransaction({
|
|
408
|
+
feePayer: authority.publicKey,
|
|
409
|
+
instructions: mintSetup.instructions,
|
|
410
|
+
signer: authority
|
|
411
|
+
});
|
|
412
|
+
mintTx.transaction.sign([mintSetup.mintKeypair]);
|
|
413
|
+
await transactionService.sendAndConfirm(mintTx);
|
|
414
|
+
const authorityAta = await tokenService.ensureAtaInstruction({
|
|
415
|
+
mint: mintSetup.mintKeypair.publicKey,
|
|
416
|
+
owner: authority.publicKey,
|
|
417
|
+
payer: authority.publicKey
|
|
418
|
+
});
|
|
419
|
+
const raw = BigInt(Math.round(amountUi * 10 ** decimals));
|
|
420
|
+
const mintToTx = await transactionService.buildTransaction({
|
|
421
|
+
feePayer: authority.publicKey,
|
|
422
|
+
instructions: [
|
|
423
|
+
...(authorityAta.createInstruction ? [authorityAta.createInstruction] : []),
|
|
424
|
+
tokenService.buildMintToInstruction({
|
|
425
|
+
mint: mintSetup.mintKeypair.publicKey,
|
|
426
|
+
destinationAta: authorityAta.address,
|
|
427
|
+
authority: authority.publicKey,
|
|
428
|
+
amount: raw
|
|
429
|
+
})
|
|
430
|
+
],
|
|
431
|
+
signer: authority
|
|
432
|
+
});
|
|
433
|
+
const send = await transactionService.sendAndConfirm(mintToTx);
|
|
434
|
+
activity("token", {
|
|
435
|
+
action: "mint-demo",
|
|
436
|
+
amountRaw: raw.toString(),
|
|
437
|
+
amountUi,
|
|
438
|
+
authority: options.authority,
|
|
439
|
+
decimals,
|
|
440
|
+
mint: mintSetup.mintKeypair.publicKey.toBase58()
|
|
441
|
+
}, { signature: send.signature });
|
|
442
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
443
|
+
explorer: (0, output_1.txExplorer)(send.signature),
|
|
444
|
+
mint: mintSetup.mintKeypair.publicKey.toBase58(),
|
|
445
|
+
signature: send.signature
|
|
446
|
+
}, "Demo mint created");
|
|
447
|
+
});
|
|
448
|
+
token
|
|
449
|
+
.command("create-ata")
|
|
450
|
+
.requiredOption("--owner <wallet>", "owner wallet name")
|
|
451
|
+
.requiredOption("--mint <mint>", "mint address")
|
|
452
|
+
.description("create ATA if missing")
|
|
453
|
+
.action(async (options, command) => {
|
|
454
|
+
const owner = walletRegistry.toWalletManager(options.owner);
|
|
455
|
+
const mint = new web3_js_1.PublicKey(options.mint);
|
|
456
|
+
const { tokenService, transactionService } = await buildServices();
|
|
457
|
+
const ata = await tokenService.ensureAtaInstruction({
|
|
458
|
+
mint,
|
|
459
|
+
owner: owner.publicKey,
|
|
460
|
+
payer: owner.publicKey
|
|
461
|
+
});
|
|
462
|
+
if (!ata.createInstruction) {
|
|
463
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
464
|
+
ata: ata.address.toBase58(),
|
|
465
|
+
existed: true
|
|
466
|
+
}, "ATA already exists");
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const tx = await transactionService.buildTransaction({
|
|
470
|
+
feePayer: owner.publicKey,
|
|
471
|
+
instructions: [ata.createInstruction],
|
|
472
|
+
signer: owner
|
|
473
|
+
});
|
|
474
|
+
const send = await transactionService.sendAndConfirm(tx);
|
|
475
|
+
activity("token", {
|
|
476
|
+
action: "create-ata",
|
|
477
|
+
mint: mint.toBase58(),
|
|
478
|
+
owner: options.owner
|
|
479
|
+
}, { signature: send.signature });
|
|
480
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
481
|
+
ata: ata.address.toBase58(),
|
|
482
|
+
explorer: (0, output_1.txExplorer)(send.signature),
|
|
483
|
+
signature: send.signature
|
|
484
|
+
}, "ATA created");
|
|
485
|
+
});
|
|
486
|
+
const policy = program.command("policy").description("policy inspection");
|
|
487
|
+
policy
|
|
488
|
+
.command("show")
|
|
489
|
+
.requiredOption("--agent <agent>", "agent name")
|
|
490
|
+
.description("show policy for agent")
|
|
491
|
+
.action((options, command) => {
|
|
492
|
+
const agent = resolveAgentRecord(options.agent);
|
|
493
|
+
const resolved = (0, policyPresets_1.resolvePolicyConfig)({
|
|
494
|
+
agentId: agent.name,
|
|
495
|
+
overrides: agent.policyOverrides,
|
|
496
|
+
presetName: agent.policyPreset ?? policyPresets_1.DEFAULT_POLICY_PRESET
|
|
497
|
+
});
|
|
498
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
499
|
+
overrides: agent.policyOverrides ?? null,
|
|
500
|
+
policyMode: agent.policyMode,
|
|
501
|
+
preset: agent.policyPreset ?? policyPresets_1.DEFAULT_POLICY_PRESET,
|
|
502
|
+
resolvedConfig: resolved
|
|
503
|
+
}, `Policy for ${agent.name}`);
|
|
504
|
+
});
|
|
505
|
+
policy
|
|
506
|
+
.command("presets")
|
|
507
|
+
.description("list available provider policy presets")
|
|
508
|
+
.action((_, command) => {
|
|
509
|
+
(0, output_1.printResult)(outputOptions(command), (0, policyPresets_1.listPolicyPresetSummaries)(), "Policy presets");
|
|
510
|
+
});
|
|
511
|
+
policy
|
|
512
|
+
.command("set-preset")
|
|
513
|
+
.requiredOption("--agent <agent>", "agent name")
|
|
514
|
+
.requiredOption("--preset <preset>", "preset name")
|
|
515
|
+
.description("assign a provider policy preset to an agent")
|
|
516
|
+
.action((options, command) => {
|
|
517
|
+
const record = resolveAgentRecord(options.agent);
|
|
518
|
+
const preset = options.preset;
|
|
519
|
+
if (!(0, policyPresets_1.listPolicyPresetSummaries)().some((entry) => entry.name === preset)) {
|
|
520
|
+
throw new Error(`Unknown policy preset '${options.preset}'.`);
|
|
521
|
+
}
|
|
522
|
+
const policyMode = preset === "guarded-live" ? "live" : "sandbox";
|
|
523
|
+
const updated = agentRegistry.patch(record.name, {
|
|
524
|
+
policyMode,
|
|
525
|
+
policyPreset: preset
|
|
526
|
+
});
|
|
527
|
+
(0, output_1.printResult)(outputOptions(command), updated, `Policy preset updated for ${record.name}`);
|
|
528
|
+
});
|
|
529
|
+
policy
|
|
530
|
+
.command("set-limits")
|
|
531
|
+
.requiredOption("--agent <agent>", "agent name")
|
|
532
|
+
.option("--approval-mode <mode>", "sandbox or live")
|
|
533
|
+
.option("--max-sol-per-tx-lamports <n>", "max lamports per transaction")
|
|
534
|
+
.option("--max-spl-per-tx-raw <n>", "max raw SPL units per transaction")
|
|
535
|
+
.option("--max-transactions-per-session <n>", "max transactions per session")
|
|
536
|
+
.option("--max-transactions-per-day <n>", "max transactions per day")
|
|
537
|
+
.option("--session-ttl-minutes <n>", "session ttl in minutes")
|
|
538
|
+
.option("--allowed-mints <csv>", "comma-separated allowed mint addresses")
|
|
539
|
+
.option("--allowed-close-destinations <csv>", "comma-separated destinations allowed for token-account close refunds")
|
|
540
|
+
.option("--allowed-destinations <csv>", "comma-separated allowed destination addresses")
|
|
541
|
+
.option("--extra-program-ids <csv>", "comma-separated extra allowed program ids")
|
|
542
|
+
.option("--allow-opaque-program-ids <csv>", "comma-separated opaque programs to allow")
|
|
543
|
+
.option("--deny-unknown-instructions <true|false>", "override unknown-instruction deny behavior")
|
|
544
|
+
.option("--require-simulation-success <true|false>", "override simulation requirement")
|
|
545
|
+
.option("--reject-suspicious-balance-deltas <true|false>", "override suspicious delta rejection")
|
|
546
|
+
.description("set or replace persisted policy overrides for an agent")
|
|
547
|
+
.action((options, command) => {
|
|
548
|
+
const record = resolveAgentRecord(options.agent);
|
|
549
|
+
const approvalMode = options.approvalMode === undefined ? undefined : String(options.approvalMode);
|
|
550
|
+
if (approvalMode !== undefined && approvalMode !== "sandbox" && approvalMode !== "live") {
|
|
551
|
+
throw new Error("--approval-mode must be 'sandbox' or 'live'");
|
|
552
|
+
}
|
|
553
|
+
const updated = agentRegistry.patch(record.name, {
|
|
554
|
+
policyMode: approvalMode ?? record.policyMode,
|
|
555
|
+
policyOverrides: {
|
|
556
|
+
allowOpaqueProgramIds: parseOptionalCsv(options.allowOpaqueProgramIds),
|
|
557
|
+
allowedCloseAccountDestinations: parseOptionalCsv(options.allowedCloseDestinations),
|
|
558
|
+
allowedMints: parseOptionalCsv(options.allowedMints),
|
|
559
|
+
allowedTransferDestinations: parseOptionalCsv(options.allowedDestinations),
|
|
560
|
+
approvalMode: approvalMode,
|
|
561
|
+
denyUnknownInstructionsByDefault: options.denyUnknownInstructions === undefined
|
|
562
|
+
? undefined
|
|
563
|
+
: String(options.denyUnknownInstructions).toLowerCase() === "true",
|
|
564
|
+
extraAllowedProgramIds: parseOptionalCsv(options.extraProgramIds),
|
|
565
|
+
maxSolPerTxLamports: parseOptionalPositiveInteger(options.maxSolPerTxLamports, "max-sol-per-tx-lamports"),
|
|
566
|
+
maxSplPerTxRawAmount: options.maxSplPerTxRaw
|
|
567
|
+
? String(BigInt(options.maxSplPerTxRaw))
|
|
568
|
+
: undefined,
|
|
569
|
+
maxTransactionsPerDay: parseOptionalPositiveInteger(options.maxTransactionsPerDay, "max-transactions-per-day"),
|
|
570
|
+
maxTransactionsPerSession: parseOptionalPositiveInteger(options.maxTransactionsPerSession, "max-transactions-per-session"),
|
|
571
|
+
rejectSuspiciousBalanceDeltas: options.rejectSuspiciousBalanceDeltas === undefined
|
|
572
|
+
? undefined
|
|
573
|
+
: String(options.rejectSuspiciousBalanceDeltas).toLowerCase() === "true",
|
|
574
|
+
requireSimulationSuccess: options.requireSimulationSuccess === undefined
|
|
575
|
+
? undefined
|
|
576
|
+
: String(options.requireSimulationSuccess).toLowerCase() === "true",
|
|
577
|
+
sessionTtlMinutes: parseOptionalPositiveInteger(options.sessionTtlMinutes, "session-ttl-minutes")
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
(0, output_1.printResult)(outputOptions(command), updated, `Policy overrides updated for ${record.name}`);
|
|
581
|
+
});
|
|
582
|
+
policy
|
|
583
|
+
.command("clear-overrides")
|
|
584
|
+
.requiredOption("--agent <agent>", "agent name")
|
|
585
|
+
.description("clear persisted policy overrides for an agent")
|
|
586
|
+
.action((options, command) => {
|
|
587
|
+
const record = resolveAgentRecord(options.agent);
|
|
588
|
+
const updated = agentRegistry.patch(record.name, {
|
|
589
|
+
policyOverrides: undefined
|
|
590
|
+
});
|
|
591
|
+
(0, output_1.printResult)(outputOptions(command), updated, `Policy overrides cleared for ${record.name}`);
|
|
592
|
+
});
|
|
593
|
+
policy
|
|
594
|
+
.command("validate-intent")
|
|
595
|
+
.requiredOption("--agent <agent>", "agent name")
|
|
596
|
+
.requiredOption("--intent-file <file>", "path to intent JSON")
|
|
597
|
+
.description("validate intent-like transaction against policy")
|
|
598
|
+
.action(async (options, command) => {
|
|
599
|
+
const agent = resolveAgentRecord(options.agent);
|
|
600
|
+
const intentRaw = JSON.parse((0, fs_1.readFileSync)(options.intentFile, "utf8"));
|
|
601
|
+
const walletManager = walletRegistry.toWalletManager(agent.walletName);
|
|
602
|
+
const config = (0, policyPresets_1.resolvePolicyConfig)({
|
|
603
|
+
agentId: agent.name,
|
|
604
|
+
overrides: agent.policyOverrides,
|
|
605
|
+
presetName: agent.policyPreset ?? policyPresets_1.DEFAULT_POLICY_PRESET
|
|
606
|
+
});
|
|
607
|
+
const engine = new policy_1.PolicyEngine(config);
|
|
608
|
+
const { tokenService, transactionService } = await buildServices();
|
|
609
|
+
let inspection;
|
|
610
|
+
if (intentRaw.type === "write-memo") {
|
|
611
|
+
const tx = await transactionService.buildTransaction({
|
|
612
|
+
feePayer: walletManager.publicKey,
|
|
613
|
+
instructions: [transactionService.buildMemoInstruction(String(intentRaw.memo ?? ""))],
|
|
614
|
+
signer: walletManager
|
|
615
|
+
});
|
|
616
|
+
inspection = engine.inspect(tx.transaction);
|
|
617
|
+
}
|
|
618
|
+
else if (intentRaw.type === "transfer-sol") {
|
|
619
|
+
const tx = await transactionService.buildTransaction({
|
|
620
|
+
feePayer: walletManager.publicKey,
|
|
621
|
+
instructions: [
|
|
622
|
+
transactionService.buildSolTransferInstruction({
|
|
623
|
+
from: walletManager.publicKey,
|
|
624
|
+
to: new web3_js_1.PublicKey(String(intentRaw.to)),
|
|
625
|
+
lamports: Number(intentRaw.lamports)
|
|
626
|
+
})
|
|
627
|
+
],
|
|
628
|
+
signer: walletManager
|
|
629
|
+
});
|
|
630
|
+
inspection = engine.inspect(tx.transaction);
|
|
631
|
+
}
|
|
632
|
+
else if (intentRaw.type === "transfer-spl") {
|
|
633
|
+
const mint = new web3_js_1.PublicKey(String(intentRaw.mint));
|
|
634
|
+
const mintDecimals = await tokenService.getMintDecimals(mint);
|
|
635
|
+
const sourceAta = tokenService.findAssociatedTokenAddress(walletManager.publicKey, mint);
|
|
636
|
+
const destOwner = new web3_js_1.PublicKey(String(intentRaw.toOwner));
|
|
637
|
+
const destinationAta = tokenService.findAssociatedTokenAddress(destOwner, mint);
|
|
638
|
+
const tx = await transactionService.buildTransaction({
|
|
639
|
+
feePayer: walletManager.publicKey,
|
|
640
|
+
instructions: [
|
|
641
|
+
transactionService.buildSplTransferCheckedInstruction({
|
|
642
|
+
sourceAta,
|
|
643
|
+
mint,
|
|
644
|
+
destinationAta,
|
|
645
|
+
owner: walletManager.publicKey,
|
|
646
|
+
amount: BigInt(String(intentRaw.amountRaw)),
|
|
647
|
+
decimals: mintDecimals
|
|
648
|
+
})
|
|
649
|
+
],
|
|
650
|
+
signer: walletManager
|
|
651
|
+
});
|
|
652
|
+
inspection = engine.inspect(tx.transaction);
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
throw new Error("Unsupported intent type for validate-intent. Supported: write-memo, transfer-sol, transfer-spl");
|
|
656
|
+
}
|
|
657
|
+
activity("policy", {
|
|
658
|
+
action: "validate-intent",
|
|
659
|
+
agent: options.agent,
|
|
660
|
+
intentType: intentRaw.type
|
|
661
|
+
});
|
|
662
|
+
(0, output_1.printResult)(outputOptions(command), inspection, "Policy inspection result");
|
|
663
|
+
});
|
|
664
|
+
const agent = program.command("agent").description("agent management");
|
|
665
|
+
agent
|
|
666
|
+
.command("create")
|
|
667
|
+
.requiredOption("--agent <name>", "agent id")
|
|
668
|
+
.option("--owner <owner>", "owner id")
|
|
669
|
+
.description("create an agent with an encrypted managed wallet")
|
|
670
|
+
.action((options, command) => {
|
|
671
|
+
const createdWallet = walletRegistry.create(options.agent);
|
|
672
|
+
const createdAgent = agentRegistry.createAgent({
|
|
673
|
+
agentId: options.agent,
|
|
674
|
+
ownerId: options.owner,
|
|
675
|
+
walletName: createdWallet.record.name
|
|
676
|
+
});
|
|
677
|
+
activity("agent", {
|
|
678
|
+
action: "create",
|
|
679
|
+
ownerId: options.owner ?? null,
|
|
680
|
+
wallet: createdWallet.record.name
|
|
681
|
+
}, { agent: createdAgent.name });
|
|
682
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
683
|
+
agent: createdAgent.name,
|
|
684
|
+
custodyModel: CUSTODY_MODEL,
|
|
685
|
+
dataDir: (0, storagePaths_1.getCliDataDir)(),
|
|
686
|
+
defaultPolicyPreset: createdAgent.policyPreset,
|
|
687
|
+
masterKeySource: (0, walletCrypto_1.getPlatformMasterKeySource)(),
|
|
688
|
+
ownerId: createdAgent.ownerId ?? null,
|
|
689
|
+
publicKey: createdWallet.record.publicKey,
|
|
690
|
+
recoveryKey: createdWallet.recoveryKey,
|
|
691
|
+
wallet: createdAgent.walletName
|
|
692
|
+
}, `Agent ${createdAgent.name} created`);
|
|
693
|
+
});
|
|
694
|
+
agent
|
|
695
|
+
.command("fund")
|
|
696
|
+
.requiredOption("--agent <name>", "agent id")
|
|
697
|
+
.requiredOption("--sol <amount>", "amount in SOL")
|
|
698
|
+
.description("fund an agent wallet from treasury if configured, otherwise request devnet airdrop")
|
|
699
|
+
.action(async (options, command) => {
|
|
700
|
+
const record = resolveAgentRecord(options.agent);
|
|
701
|
+
const amountSol = parseSol(options.sol);
|
|
702
|
+
const walletManager = walletRegistry.toWalletManager(record.walletName);
|
|
703
|
+
const { balanceService, rpcClient, transactionService } = await buildServices();
|
|
704
|
+
const fundingService = new DevnetFundingService_1.DevnetFundingService(rpcClient, transactionService);
|
|
705
|
+
const funding = await fundingService.fundExactSol({
|
|
706
|
+
amountSol,
|
|
707
|
+
recipient: walletManager.publicKey
|
|
708
|
+
});
|
|
709
|
+
const updatedBalance = await fundingService.waitForMinimumBalance({
|
|
710
|
+
attempts: 15,
|
|
711
|
+
balanceService,
|
|
712
|
+
minimumSol: amountSol,
|
|
713
|
+
recipient: walletManager.publicKey
|
|
714
|
+
});
|
|
715
|
+
activity("agent", {
|
|
716
|
+
action: "fund",
|
|
717
|
+
amountSol,
|
|
718
|
+
ownerId: record.ownerId ?? null
|
|
719
|
+
}, { agent: record.name, signature: funding.signature });
|
|
720
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
721
|
+
agent: record.name,
|
|
722
|
+
balanceSol: updatedBalance,
|
|
723
|
+
explorer: (0, output_1.txExplorer)(funding.signature),
|
|
724
|
+
publicKey: walletManager.publicKey.toBase58(),
|
|
725
|
+
signature: funding.signature,
|
|
726
|
+
source: funding.source
|
|
727
|
+
}, `Agent ${record.name} funded`);
|
|
728
|
+
});
|
|
729
|
+
agent
|
|
730
|
+
.command("balance")
|
|
731
|
+
.requiredOption("--agent <name>", "agent id")
|
|
732
|
+
.description("fetch SOL balance for the agent wallet")
|
|
733
|
+
.action(async (options, command) => {
|
|
734
|
+
const record = resolveAgentRecord(options.agent);
|
|
735
|
+
const walletManager = walletRegistry.toWalletManager(record.walletName);
|
|
736
|
+
const { balanceService } = await buildServices();
|
|
737
|
+
const sol = await balanceService.getSolBalance(walletManager.publicKey);
|
|
738
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
739
|
+
agent: record.name,
|
|
740
|
+
balanceSol: sol,
|
|
741
|
+
publicKey: walletManager.publicKey.toBase58(),
|
|
742
|
+
wallet: record.walletName
|
|
743
|
+
}, `SOL balance for ${record.name}`);
|
|
744
|
+
});
|
|
745
|
+
agent
|
|
746
|
+
.command("export-wallet")
|
|
747
|
+
.requiredOption("--agent <name>", "agent id")
|
|
748
|
+
.requiredOption("--recovery-key <key>", "wallet recovery key")
|
|
749
|
+
.description("decrypt and export the agent wallet secret key")
|
|
750
|
+
.action((options, command) => {
|
|
751
|
+
const record = resolveAgentRecord(options.agent);
|
|
752
|
+
const secretKey = Array.from(walletRegistry.exportSecretKeyWithRecovery({
|
|
753
|
+
name: record.walletName,
|
|
754
|
+
recoveryKey: String(options.recoveryKey)
|
|
755
|
+
}));
|
|
756
|
+
const wallet = walletRegistry.find(record.walletName);
|
|
757
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
758
|
+
agent: record.name,
|
|
759
|
+
ownerId: record.ownerId ?? null,
|
|
760
|
+
publicKey: wallet?.publicKey ?? "<missing>",
|
|
761
|
+
secretKey,
|
|
762
|
+
wallet: record.walletName
|
|
763
|
+
}, `Agent ${record.name} wallet exported`);
|
|
764
|
+
});
|
|
765
|
+
agent
|
|
766
|
+
.command("list")
|
|
767
|
+
.description("list registered agents")
|
|
768
|
+
.action((_, command) => {
|
|
769
|
+
const agents = agentRegistry.synchronizeWithWallets().map((record) => ({
|
|
770
|
+
lastRunAt: record.lastRunAtIso ?? "-",
|
|
771
|
+
name: record.name,
|
|
772
|
+
ownerId: record.ownerId ?? "-",
|
|
773
|
+
policyMode: record.policyMode,
|
|
774
|
+
policyPreset: record.policyPreset,
|
|
775
|
+
status: record.status,
|
|
776
|
+
strategy: record.strategy,
|
|
777
|
+
wallet: record.walletName
|
|
778
|
+
}));
|
|
779
|
+
(0, output_1.printResult)(outputOptions(command), agents, "Agents");
|
|
780
|
+
});
|
|
781
|
+
agent
|
|
782
|
+
.command("show")
|
|
783
|
+
.requiredOption("--agent <name>", "agent name")
|
|
784
|
+
.description("show agent details")
|
|
785
|
+
.action((options, command) => {
|
|
786
|
+
const record = resolveAgentRecord(options.agent);
|
|
787
|
+
const wallet = walletRegistry.find(record.walletName);
|
|
788
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
789
|
+
...record,
|
|
790
|
+
resolvedPolicy: (0, policyPresets_1.resolvePolicyConfig)({
|
|
791
|
+
agentId: record.name,
|
|
792
|
+
overrides: record.policyOverrides,
|
|
793
|
+
presetName: record.policyPreset ?? policyPresets_1.DEFAULT_POLICY_PRESET
|
|
794
|
+
}),
|
|
795
|
+
walletPublicKey: wallet?.publicKey ?? "<missing>"
|
|
796
|
+
}, `Agent ${record.name}`);
|
|
797
|
+
});
|
|
798
|
+
agent
|
|
799
|
+
.command("run")
|
|
800
|
+
.requiredOption("--agent <name>", "agent name")
|
|
801
|
+
.requiredOption("--strategy <strategy>", "strategy name")
|
|
802
|
+
.description("run a single agent once")
|
|
803
|
+
.action(async (options, command) => {
|
|
804
|
+
const record = resolveAgentRecord(options.agent);
|
|
805
|
+
const updated = agentRegistry.patch(record.name, {
|
|
806
|
+
status: "active",
|
|
807
|
+
strategy: options.strategy
|
|
808
|
+
});
|
|
809
|
+
const result = await (0, agentRuntime_1.runAgentOnce)({
|
|
810
|
+
agent: updated,
|
|
811
|
+
overrideStrategy: options.strategy
|
|
812
|
+
});
|
|
813
|
+
const lastSignature = result.outcomes.find((entry) => entry.signature)?.signature;
|
|
814
|
+
agentRegistry.patch(updated.name, {
|
|
815
|
+
lastAction: `${options.strategy}:run-once`,
|
|
816
|
+
lastRunAtIso: new Date().toISOString(),
|
|
817
|
+
lastSignature: lastSignature ?? undefined,
|
|
818
|
+
status: "active"
|
|
819
|
+
});
|
|
820
|
+
activity("agent", {
|
|
821
|
+
action: "run",
|
|
822
|
+
outcomes: result.outcomes.length,
|
|
823
|
+
strategy: options.strategy
|
|
824
|
+
}, { agent: updated.name, signature: lastSignature ?? undefined });
|
|
825
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
826
|
+
...result,
|
|
827
|
+
explorer: lastSignature ? (0, output_1.txExplorer)(lastSignature) : null
|
|
828
|
+
}, `Agent ${updated.name} run complete`);
|
|
829
|
+
});
|
|
830
|
+
agent
|
|
831
|
+
.command("run-all")
|
|
832
|
+
.description("run all active agents once")
|
|
833
|
+
.action(async (_, command) => {
|
|
834
|
+
const records = agentRegistry.synchronizeWithWallets().filter((entry) => entry.status === "active");
|
|
835
|
+
const results = [];
|
|
836
|
+
for (const record of records) {
|
|
837
|
+
try {
|
|
838
|
+
const result = await (0, agentRuntime_1.runAgentOnce)({ agent: record });
|
|
839
|
+
const lastSignature = result.outcomes.find((entry) => entry.signature)?.signature;
|
|
840
|
+
agentRegistry.patch(record.name, {
|
|
841
|
+
lastAction: `${record.strategy}:run-once`,
|
|
842
|
+
lastRunAtIso: new Date().toISOString(),
|
|
843
|
+
lastSignature: lastSignature ?? undefined
|
|
844
|
+
});
|
|
845
|
+
results.push({
|
|
846
|
+
agent: record.name,
|
|
847
|
+
outcomes: result.outcomes.length,
|
|
848
|
+
signature: lastSignature ?? "-"
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
catch (error) {
|
|
852
|
+
const reason = error instanceof Error ? error.message : "unknown error";
|
|
853
|
+
agentRegistry.patch(record.name, {
|
|
854
|
+
lastError: reason,
|
|
855
|
+
lastRunAtIso: new Date().toISOString()
|
|
856
|
+
});
|
|
857
|
+
results.push({
|
|
858
|
+
agent: record.name,
|
|
859
|
+
error: reason,
|
|
860
|
+
outcomes: 0,
|
|
861
|
+
signature: "-"
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
activity("agent", { action: "run-all", count: results.length });
|
|
866
|
+
(0, output_1.printResult)(outputOptions(command), results, "Run-all summary");
|
|
867
|
+
});
|
|
868
|
+
agent
|
|
869
|
+
.command("stop")
|
|
870
|
+
.requiredOption("--agent <name>", "agent name")
|
|
871
|
+
.description("mark agent as stopped")
|
|
872
|
+
.action((options, command) => {
|
|
873
|
+
const updated = agentRegistry.patch(options.agent, { status: "stopped" });
|
|
874
|
+
activity("agent", { action: "stop" }, { agent: options.agent });
|
|
875
|
+
(0, output_1.printResult)(outputOptions(command), updated, `Agent ${options.agent} stopped`);
|
|
876
|
+
});
|
|
877
|
+
agent
|
|
878
|
+
.command("logs")
|
|
879
|
+
.requiredOption("--agent <name>", "agent name")
|
|
880
|
+
.description("show recent activity logs for agent")
|
|
881
|
+
.action((options, command) => {
|
|
882
|
+
const logs = activityStore.listByAgent(options.agent, 100).map((entry) => ({
|
|
883
|
+
details: JSON.stringify(entry.details),
|
|
884
|
+
kind: entry.kind,
|
|
885
|
+
signature: entry.signature ?? "-",
|
|
886
|
+
timestamp: entry.createdAtIso
|
|
887
|
+
}));
|
|
888
|
+
(0, output_1.printResult)(outputOptions(command), logs, `Recent logs for ${options.agent}`);
|
|
889
|
+
});
|
|
890
|
+
const monitor = program.command("monitor").description("operational monitoring views");
|
|
891
|
+
monitor
|
|
892
|
+
.command("overview")
|
|
893
|
+
.description("summarize agents, wallets and last activity")
|
|
894
|
+
.action(async (_, command) => {
|
|
895
|
+
const rows = await buildOverviewRows();
|
|
896
|
+
activity("monitor", { action: "overview", rows: rows.length });
|
|
897
|
+
(0, output_1.printResult)(outputOptions(command), rows, "Monitor overview");
|
|
898
|
+
});
|
|
899
|
+
monitor
|
|
900
|
+
.command("watch")
|
|
901
|
+
.description("live-refresh monitor overview")
|
|
902
|
+
.option("--interval <seconds>", "refresh interval in seconds", "5")
|
|
903
|
+
.option("--iterations <n>", "stop after n refreshes", "0")
|
|
904
|
+
.action(async (options, command) => {
|
|
905
|
+
const intervalSeconds = Number(options.interval);
|
|
906
|
+
const iterations = Number(options.iterations);
|
|
907
|
+
if (!Number.isFinite(intervalSeconds) || intervalSeconds <= 0) {
|
|
908
|
+
throw new Error("--interval must be a positive number");
|
|
909
|
+
}
|
|
910
|
+
const json = outputOptions(command).json;
|
|
911
|
+
let count = 0;
|
|
912
|
+
// eslint-disable-next-line no-constant-condition
|
|
913
|
+
while (true) {
|
|
914
|
+
count += 1;
|
|
915
|
+
const rows = await buildOverviewRows();
|
|
916
|
+
const snapshot = {
|
|
917
|
+
iteration: count,
|
|
918
|
+
timestamp: new Date().toISOString(),
|
|
919
|
+
rows
|
|
920
|
+
};
|
|
921
|
+
if (json) {
|
|
922
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
console.clear();
|
|
926
|
+
console.log(`PRKT monitor watch | ${snapshot.timestamp} | iteration ${count}`);
|
|
927
|
+
if (rows.length === 0) {
|
|
928
|
+
console.log("No agents found.");
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
console.table(rows);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
activity("monitor", { action: "watch", iteration: count, rows: rows.length });
|
|
935
|
+
if (iterations > 0 && count >= iterations) {
|
|
936
|
+
break;
|
|
937
|
+
}
|
|
938
|
+
await new Promise((resolve) => setTimeout(resolve, Math.round(intervalSeconds * 1000)));
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
monitor
|
|
942
|
+
.command("balances")
|
|
943
|
+
.description("show wallet SOL balances")
|
|
944
|
+
.action(async (_, command) => {
|
|
945
|
+
const { balanceService } = await buildServices();
|
|
946
|
+
const rows = [];
|
|
947
|
+
for (const wallet of walletRegistry.list()) {
|
|
948
|
+
const sol = await balanceService.getSolBalance(new web3_js_1.PublicKey(wallet.publicKey));
|
|
949
|
+
rows.push({
|
|
950
|
+
name: wallet.name,
|
|
951
|
+
publicKey: wallet.publicKey,
|
|
952
|
+
sol: sol.toFixed(4)
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
(0, output_1.printResult)(outputOptions(command), rows, "Wallet balances");
|
|
956
|
+
});
|
|
957
|
+
monitor
|
|
958
|
+
.command("txs")
|
|
959
|
+
.description("show recent transaction activity")
|
|
960
|
+
.action((_, command) => {
|
|
961
|
+
const txs = activityStore
|
|
962
|
+
.list(100)
|
|
963
|
+
.filter((entry) => Boolean(entry.signature))
|
|
964
|
+
.map((entry) => ({
|
|
965
|
+
agent: entry.agent ?? "-",
|
|
966
|
+
kind: entry.kind,
|
|
967
|
+
signature: entry.signature,
|
|
968
|
+
timestamp: entry.createdAtIso
|
|
969
|
+
}));
|
|
970
|
+
(0, output_1.printResult)(outputOptions(command), txs, "Recent transactions");
|
|
971
|
+
});
|
|
972
|
+
monitor
|
|
973
|
+
.command("agents")
|
|
974
|
+
.description("show agent runtime state")
|
|
975
|
+
.action((_, command) => {
|
|
976
|
+
const rows = agentRegistry.synchronizeWithWallets().map((entry) => ({
|
|
977
|
+
agent: entry.name,
|
|
978
|
+
lastError: entry.lastError ?? "-",
|
|
979
|
+
lastRunAt: entry.lastRunAtIso ?? "-",
|
|
980
|
+
policyMode: entry.policyMode,
|
|
981
|
+
status: entry.status,
|
|
982
|
+
strategy: entry.strategy
|
|
983
|
+
}));
|
|
984
|
+
(0, output_1.printResult)(outputOptions(command), rows, "Agent state");
|
|
985
|
+
});
|
|
986
|
+
const demo = program.command("demo").description("demo execution helpers");
|
|
987
|
+
demo
|
|
988
|
+
.command("multi-agent-devnet")
|
|
989
|
+
.description("run existing multi-agent devnet demo")
|
|
990
|
+
.action(async (_, command) => {
|
|
991
|
+
const result = await (0, multiAgentDevnetScenario_1.runMultiAgentDevnetScenario)();
|
|
992
|
+
activity("demo", {
|
|
993
|
+
action: "multi-agent-devnet",
|
|
994
|
+
mintAddress: result.mintAddress,
|
|
995
|
+
signatures: result.signatures.length
|
|
996
|
+
});
|
|
997
|
+
(0, output_1.printResult)(outputOptions(command), {
|
|
998
|
+
...result,
|
|
999
|
+
explorerLinks: result.signatures.map(output_1.txExplorer)
|
|
1000
|
+
}, "Multi-agent devnet demo complete");
|
|
1001
|
+
});
|
|
1002
|
+
program
|
|
1003
|
+
.command("audit")
|
|
1004
|
+
.description("show recent audit log entries")
|
|
1005
|
+
.option("--limit <n>", "max entries", "100")
|
|
1006
|
+
.action((options, command) => {
|
|
1007
|
+
const limit = Number(options.limit);
|
|
1008
|
+
const rows = activityStore.list(Number.isFinite(limit) ? limit : 100).map((entry) => ({
|
|
1009
|
+
agent: entry.agent ?? "-",
|
|
1010
|
+
details: JSON.stringify(entry.details),
|
|
1011
|
+
kind: entry.kind,
|
|
1012
|
+
signature: entry.signature ?? "-",
|
|
1013
|
+
timestamp: entry.createdAtIso
|
|
1014
|
+
}));
|
|
1015
|
+
(0, output_1.printResult)(outputOptions(command), rows, "Audit activity");
|
|
1016
|
+
});
|
|
1017
|
+
const config = program.command("config").description("configuration commands");
|
|
1018
|
+
config
|
|
1019
|
+
.command("show")
|
|
1020
|
+
.description("show runtime config")
|
|
1021
|
+
.action((_, command) => {
|
|
1022
|
+
const rpc = (0, env_1.getRpcUrl)();
|
|
1023
|
+
const dataDirStatus = (0, storagePaths_1.probeCliDataDir)();
|
|
1024
|
+
const payload = {
|
|
1025
|
+
cliDataDir: dataDirStatus.path,
|
|
1026
|
+
cliDataDirHealth: dataDirStatus.details,
|
|
1027
|
+
cliDataDirWritable: dataDirStatus.writable,
|
|
1028
|
+
cluster: (0, env_1.detectClusterFromRpcUrl)(rpc),
|
|
1029
|
+
custodyModel: CUSTODY_MODEL,
|
|
1030
|
+
koraRpc: (0, env_1.getKoraRpcUrl)(),
|
|
1031
|
+
liveRaydiumLp: (0, env_1.isLiveRaydiumLpEnabled)(),
|
|
1032
|
+
liveSwap: (0, env_1.isLiveSwapPathEnabled)(),
|
|
1033
|
+
policyExecutionModel: POLICY_EXECUTION_MODEL,
|
|
1034
|
+
rpc,
|
|
1035
|
+
walletKeySource: (0, walletCrypto_1.getPlatformMasterKeySource)(),
|
|
1036
|
+
universalDefiLiveFirst: (0, env_1.isUniversalDeFiLiveFirstEnabled)(),
|
|
1037
|
+
usdcMint: (0, env_1.getUsdcMintAddress)()
|
|
1038
|
+
};
|
|
1039
|
+
activity("config", { action: "show" });
|
|
1040
|
+
(0, output_1.printResult)(outputOptions(command), payload, "Config");
|
|
1041
|
+
});
|
|
1042
|
+
program
|
|
1043
|
+
.command("doctor")
|
|
1044
|
+
.description("validate env, rpc, and devnet readiness")
|
|
1045
|
+
.action(async (_, command) => {
|
|
1046
|
+
const checks = [];
|
|
1047
|
+
const rpc = (0, env_1.getRpcUrl)();
|
|
1048
|
+
const dataDirStatus = (0, storagePaths_1.probeCliDataDir)();
|
|
1049
|
+
checks.push({
|
|
1050
|
+
check: "cluster",
|
|
1051
|
+
details: (0, env_1.detectClusterFromRpcUrl)(rpc),
|
|
1052
|
+
status: (0, env_1.detectClusterFromRpcUrl)(rpc) === "devnet" ? "ok" : "warn"
|
|
1053
|
+
});
|
|
1054
|
+
try {
|
|
1055
|
+
const connection = new web3_js_1.Connection(rpc, "confirmed");
|
|
1056
|
+
await connection.getLatestBlockhash("confirmed");
|
|
1057
|
+
checks.push({
|
|
1058
|
+
check: "rpc-connectivity",
|
|
1059
|
+
details: rpc,
|
|
1060
|
+
status: "ok"
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
catch (error) {
|
|
1064
|
+
checks.push({
|
|
1065
|
+
check: "rpc-connectivity",
|
|
1066
|
+
details: error instanceof Error ? error.message : "unknown rpc error",
|
|
1067
|
+
status: "fail"
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
const remoteSigner = (0, env_1.getRemoteSignerConfig)();
|
|
1071
|
+
const treasurySecretKey = (0, env_1.getOptionalDevnetTreasurySecretKey)();
|
|
1072
|
+
const treasuryExists = Boolean(remoteSigner ||
|
|
1073
|
+
treasurySecretKey ||
|
|
1074
|
+
(process.env.AGENT_PRIVATE_KEY && process.env.AGENT_PRIVATE_KEY.length > 0));
|
|
1075
|
+
checks.push({
|
|
1076
|
+
check: "treasury-key",
|
|
1077
|
+
details: remoteSigner
|
|
1078
|
+
? `remote signer ${remoteSigner.publicKey.toBase58()}`
|
|
1079
|
+
: treasurySecretKey
|
|
1080
|
+
? "devnet treasury key present"
|
|
1081
|
+
: treasuryExists
|
|
1082
|
+
? "local demo key present"
|
|
1083
|
+
: "missing signer configuration",
|
|
1084
|
+
status: treasuryExists ? "ok" : "warn"
|
|
1085
|
+
});
|
|
1086
|
+
checks.push({
|
|
1087
|
+
check: "custody-model",
|
|
1088
|
+
details: CUSTODY_MODEL,
|
|
1089
|
+
status: "ok"
|
|
1090
|
+
});
|
|
1091
|
+
checks.push({
|
|
1092
|
+
check: "cli-data-dir",
|
|
1093
|
+
details: dataDirStatus.path,
|
|
1094
|
+
status: "ok"
|
|
1095
|
+
});
|
|
1096
|
+
checks.push({
|
|
1097
|
+
check: "cli-data-dir-writable",
|
|
1098
|
+
details: dataDirStatus.details,
|
|
1099
|
+
status: dataDirStatus.writable ? "ok" : "fail"
|
|
1100
|
+
});
|
|
1101
|
+
checks.push({
|
|
1102
|
+
check: "wallet-key-source",
|
|
1103
|
+
details: (0, walletCrypto_1.getPlatformMasterKeySource)(),
|
|
1104
|
+
status: "ok"
|
|
1105
|
+
});
|
|
1106
|
+
checks.push({
|
|
1107
|
+
check: "policy-execution-model",
|
|
1108
|
+
details: POLICY_EXECUTION_MODEL,
|
|
1109
|
+
status: "ok"
|
|
1110
|
+
});
|
|
1111
|
+
checks.push({
|
|
1112
|
+
check: "live-swap-flag",
|
|
1113
|
+
details: String((0, env_1.isLiveSwapPathEnabled)()),
|
|
1114
|
+
status: "ok"
|
|
1115
|
+
});
|
|
1116
|
+
checks.push({
|
|
1117
|
+
check: "live-raydium-flag",
|
|
1118
|
+
details: String((0, env_1.isLiveRaydiumLpEnabled)()),
|
|
1119
|
+
status: "ok"
|
|
1120
|
+
});
|
|
1121
|
+
checks.push({
|
|
1122
|
+
check: "universal-live-first",
|
|
1123
|
+
details: String((0, env_1.isUniversalDeFiLiveFirstEnabled)()),
|
|
1124
|
+
status: "ok"
|
|
1125
|
+
});
|
|
1126
|
+
activity("doctor", { checks: checks.length });
|
|
1127
|
+
(0, output_1.printResult)(outputOptions(command), checks, "Doctor checks");
|
|
1128
|
+
});
|
|
1129
|
+
program
|
|
1130
|
+
.command("completion")
|
|
1131
|
+
.description("print shell completion script")
|
|
1132
|
+
.argument("[shell]", "shell type: bash | zsh | powershell", "bash")
|
|
1133
|
+
.action((shell) => {
|
|
1134
|
+
const normalized = shell.trim().toLowerCase();
|
|
1135
|
+
if (normalized === "bash") {
|
|
1136
|
+
console.log((0, completion_1.buildBashCompletion)());
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
if (normalized === "zsh") {
|
|
1140
|
+
console.log((0, completion_1.buildZshCompletion)());
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
if (normalized === "powershell" || normalized === "pwsh") {
|
|
1144
|
+
console.log((0, completion_1.buildPowerShellCompletion)());
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
throw new Error("Unsupported shell. Use: bash, zsh, powershell");
|
|
1148
|
+
});
|
|
1149
|
+
async function main() {
|
|
1150
|
+
try {
|
|
1151
|
+
await program.parseAsync(process.argv);
|
|
1152
|
+
}
|
|
1153
|
+
catch (error) {
|
|
1154
|
+
const message = error instanceof Error ? error.message : "Unknown CLI error";
|
|
1155
|
+
console.error(`CLI error: ${message}`);
|
|
1156
|
+
process.exitCode = 1;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
main();
|