@palmyr/cli 1.3.1 → 1.5.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.
@@ -0,0 +1,162 @@
1
+ /** Liquid test tokens with tight spreads — minimises slippage on tiny trades. */
2
+ const TEST_MINT_SOLANA = 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN';
3
+ const TEST_MINT_BASE = '0x4200000000000000000000000000000000000006'; // WETH
4
+ async function timed(fn) {
5
+ const t0 = Date.now();
6
+ try {
7
+ const value = await fn();
8
+ return { ok: true, value, durationMs: Date.now() - t0 };
9
+ }
10
+ catch (e) {
11
+ return { ok: false, message: e?.message ?? String(e), durationMs: Date.now() - t0 };
12
+ }
13
+ }
14
+ export async function runWalletLiveTest(opts) {
15
+ const startedAt = new Date().toISOString();
16
+ if (!(opts.budgetUsdc > 0)) {
17
+ throw new Error('--budget required, e.g. --budget 1usdc');
18
+ }
19
+ if (opts.budgetUsdc > 10) {
20
+ throw new Error(`--budget ${opts.budgetUsdc}usdc exceeds the live-test ceiling ($10). Trade manually for larger sizes.`);
21
+ }
22
+ const perLegUsdc = opts.budgetUsdc / 2;
23
+ const perLegAmountStr = `${perLegUsdc.toFixed(6)}usdc`;
24
+ const wantSolana = !opts.chain || opts.chain === 'solana' || opts.chain === 'all';
25
+ const wantBase = !opts.chain || opts.chain === 'base' || opts.chain === 'all';
26
+ const legs = [];
27
+ let totalRealizedUsdc = 0;
28
+ const { resolveWalletAddresses, buy, sell, buyBase, sellBase, listPositions } = await import('./wallet-trading.js');
29
+ const addrs = await resolveWalletAddresses(opts.walletRef, opts.passphrase);
30
+ // Solana round trip
31
+ if (wantSolana && addrs.solanaAddress) {
32
+ const solBuy = await timed(() => buy({
33
+ ca: TEST_MINT_SOLANA,
34
+ amount: perLegAmountStr,
35
+ thesis: 'live-test round trip',
36
+ walletRef: opts.walletRef,
37
+ passphrase: opts.passphrase,
38
+ }));
39
+ if (!solBuy.ok) {
40
+ legs.push({ name: 'solana-buy', chain: 'solana', step: 'buy', status: 'fail', message: solBuy.message, durationMs: solBuy.durationMs });
41
+ }
42
+ else {
43
+ legs.push({
44
+ name: 'solana-buy',
45
+ chain: 'solana',
46
+ step: 'buy',
47
+ status: 'pass',
48
+ txHash: solBuy.value.txSignature,
49
+ amountIn: solBuy.value.amountIn,
50
+ durationMs: solBuy.durationMs,
51
+ });
52
+ const solSell = await timed(() => sell({
53
+ ca: TEST_MINT_SOLANA,
54
+ percent: 100,
55
+ reason: 'live-test close',
56
+ walletRef: opts.walletRef,
57
+ passphrase: opts.passphrase,
58
+ }));
59
+ if (!solSell.ok) {
60
+ legs.push({ name: 'solana-sell', chain: 'solana', step: 'sell', status: 'fail', message: solSell.message, durationMs: solSell.durationMs });
61
+ }
62
+ else {
63
+ legs.push({
64
+ name: 'solana-sell',
65
+ chain: 'solana',
66
+ step: 'sell',
67
+ status: 'pass',
68
+ txHash: solSell.value.txSignature,
69
+ output: solSell.value.output,
70
+ realized: solSell.value.realized,
71
+ durationMs: solSell.durationMs,
72
+ });
73
+ if (solSell.value.realized.asset === 'USDC') {
74
+ totalRealizedUsdc += solSell.value.realized.amount;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ else if (wantSolana) {
80
+ legs.push({ name: 'solana-buy', chain: 'solana', step: 'buy', status: 'skip', message: 'no Solana address' });
81
+ }
82
+ // Base round trip
83
+ if (wantBase && addrs.evmAddress) {
84
+ const baseBuy = await timed(() => buyBase({
85
+ ca: TEST_MINT_BASE,
86
+ amount: perLegAmountStr,
87
+ thesis: 'live-test round trip',
88
+ walletRef: opts.walletRef,
89
+ passphrase: opts.passphrase,
90
+ }));
91
+ if (!baseBuy.ok) {
92
+ legs.push({ name: 'base-buy', chain: 'base', step: 'buy', status: 'fail', message: baseBuy.message, durationMs: baseBuy.durationMs });
93
+ }
94
+ else {
95
+ legs.push({
96
+ name: 'base-buy',
97
+ chain: 'base',
98
+ step: 'buy',
99
+ status: 'pass',
100
+ txHash: baseBuy.value.txHash,
101
+ amountIn: baseBuy.value.amountIn,
102
+ durationMs: baseBuy.durationMs,
103
+ });
104
+ const baseSell = await timed(() => sellBase({
105
+ ca: TEST_MINT_BASE,
106
+ percent: 100,
107
+ reason: 'live-test close',
108
+ walletRef: opts.walletRef,
109
+ passphrase: opts.passphrase,
110
+ }));
111
+ if (!baseSell.ok) {
112
+ legs.push({ name: 'base-sell', chain: 'base', step: 'sell', status: 'fail', message: baseSell.message, durationMs: baseSell.durationMs });
113
+ }
114
+ else {
115
+ legs.push({
116
+ name: 'base-sell',
117
+ chain: 'base',
118
+ step: 'sell',
119
+ status: 'pass',
120
+ txHash: baseSell.value.txHash,
121
+ output: baseSell.value.output,
122
+ realized: baseSell.value.realized,
123
+ durationMs: baseSell.durationMs,
124
+ });
125
+ if (baseSell.value.realized.asset === 'USDC') {
126
+ totalRealizedUsdc += baseSell.value.realized.amount;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ else if (wantBase) {
132
+ legs.push({ name: 'base-buy', chain: 'base', step: 'buy', status: 'skip', message: 'no EVM address' });
133
+ }
134
+ // Verify no positions left open for this wallet.
135
+ const walletAddrs = [addrs.solanaAddress, addrs.evmAddress].filter((x) => !!x);
136
+ const remaining = walletAddrs.length > 0
137
+ ? listPositions({ walletAddress: walletAddrs, includeClosed: false })
138
+ : [];
139
+ legs.push({
140
+ name: 'verify-no-open-positions',
141
+ chain: remaining[0]?.chain ?? 'solana',
142
+ step: 'verify',
143
+ status: remaining.length === 0 ? 'pass' : 'fail',
144
+ message: remaining.length === 0
145
+ ? undefined
146
+ : `${remaining.length} position(s) still open after live-test: ${remaining.map((p) => `${p.chain}:${p.mint}`).join(', ')}`,
147
+ });
148
+ const anyFail = legs.some((l) => l.status === 'fail');
149
+ const safeForAutonomousTrading = !anyFail && Math.abs(totalRealizedUsdc) <= opts.budgetUsdc;
150
+ return {
151
+ wallet: opts.walletRef,
152
+ startedAt,
153
+ finishedAt: new Date().toISOString(),
154
+ budgetUsdc: opts.budgetUsdc,
155
+ perLegUsdc,
156
+ legs,
157
+ totalRealizedUsdc,
158
+ safeForAutonomousTrading,
159
+ openPositionsAfter: remaining.length,
160
+ };
161
+ }
162
+ //# sourceMappingURL=wallet-live-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-live-test.js","sourceRoot":"","sources":["../wallet-live-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export interface ReadinessCheck {
2
+ name: string;
3
+ status: 'pass' | 'warn' | 'fail' | 'skip';
4
+ value?: string | number | boolean;
5
+ message?: string;
6
+ }
7
+ export interface ReadinessReport {
8
+ wallet: string;
9
+ solanaAddress: string | null;
10
+ evmAddress: string | null;
11
+ /** Aggregate verdict — true only when every required check is `pass`. */
12
+ safeForAutonomousTrading: boolean;
13
+ checks: ReadinessCheck[];
14
+ /** Open position count by chain, plus total. */
15
+ openPositions: {
16
+ solana: number;
17
+ base: number;
18
+ total: number;
19
+ };
20
+ /** Native-asset balances on each chain (display + raw). */
21
+ balances: {
22
+ solana: {
23
+ lamports: number;
24
+ sol: number;
25
+ } | null;
26
+ base: {
27
+ wei: string;
28
+ eth: number;
29
+ } | null;
30
+ };
31
+ /** Daemon process state — running flag + pid if any. */
32
+ daemon: {
33
+ running: boolean;
34
+ pid: number | null;
35
+ lastTick: string | null;
36
+ autoExecute: boolean | null;
37
+ walletRef: string | null;
38
+ };
39
+ }
40
+ export interface ReadinessOpts {
41
+ walletRef: string;
42
+ passphrase?: string;
43
+ /**
44
+ * Minimum native balance (lamports / wei) required to count as "has gas".
45
+ * Defaults are intentionally low — the goal is "can sign + send", not "well
46
+ * funded". Callers tuning for big trades should pass explicit thresholds.
47
+ */
48
+ minSolLamports?: number;
49
+ minEthWei?: bigint;
50
+ }
51
+ export declare function runWalletReadiness(opts: ReadinessOpts): Promise<ReadinessReport>;
@@ -0,0 +1,183 @@
1
+ const DEFAULT_MIN_SOL_LAMPORTS = 1_000_000; // 0.001 SOL — covers fees + a few tx
2
+ const DEFAULT_MIN_ETH_WEI = 100000000000000n; // 0.0001 ETH
3
+ export async function runWalletReadiness(opts) {
4
+ const checks = [];
5
+ const minSol = opts.minSolLamports ?? DEFAULT_MIN_SOL_LAMPORTS;
6
+ const minEth = opts.minEthWei ?? DEFAULT_MIN_ETH_WEI;
7
+ // Resolve addresses for both chains.
8
+ let solanaAddress = null;
9
+ let evmAddress = null;
10
+ try {
11
+ const { resolveWalletAddresses } = await import('./wallet-trading.js');
12
+ const addrs = await resolveWalletAddresses(opts.walletRef, opts.passphrase);
13
+ solanaAddress = addrs.solanaAddress;
14
+ evmAddress = addrs.evmAddress;
15
+ }
16
+ catch (e) {
17
+ checks.push({ name: 'walletResolution', status: 'fail', message: e?.message ?? 'failed' });
18
+ }
19
+ checks.push({ name: 'canSignSolana', status: solanaAddress ? 'pass' : 'fail', value: solanaAddress ?? false });
20
+ checks.push({ name: 'canSignBase', status: evmAddress ? 'pass' : 'fail', value: evmAddress ?? false });
21
+ // Native balance checks — done in parallel with quote checks below.
22
+ const balanceTasks = [];
23
+ let solBalance = null;
24
+ let baseBalance = null;
25
+ if (solanaAddress) {
26
+ balanceTasks.push((async () => {
27
+ try {
28
+ const { PublicKey } = await import('@solana/web3.js');
29
+ const { makeConnection } = await import('./solana/index.js');
30
+ const conn = makeConnection();
31
+ const lamports = await conn.getBalance(new PublicKey(solanaAddress));
32
+ solBalance = { lamports, sol: lamports / 1e9 };
33
+ const hasGas = lamports >= minSol;
34
+ checks.push({
35
+ name: 'solanaHasGas',
36
+ status: hasGas ? 'pass' : 'fail',
37
+ value: `${(lamports / 1e9).toFixed(6)} SOL`,
38
+ message: hasGas ? undefined : `< ${(minSol / 1e9).toFixed(6)} SOL min for tx fees`,
39
+ });
40
+ }
41
+ catch (e) {
42
+ checks.push({ name: 'solanaHasGas', status: 'fail', message: e?.message ?? 'balance check failed' });
43
+ }
44
+ })());
45
+ }
46
+ else {
47
+ checks.push({ name: 'solanaHasGas', status: 'skip', message: 'no Solana address' });
48
+ }
49
+ if (evmAddress) {
50
+ balanceTasks.push((async () => {
51
+ try {
52
+ const { getErc20Balance, makeEvmProvider, NATIVE_ETH } = await import('./evm-trading.js');
53
+ const wei = await getErc20Balance(makeEvmProvider(), NATIVE_ETH, evmAddress);
54
+ const ethValue = Number(wei) / 1e18;
55
+ baseBalance = { wei: wei.toString(), eth: ethValue };
56
+ const hasGas = wei >= minEth;
57
+ checks.push({
58
+ name: 'baseHasGas',
59
+ status: hasGas ? 'pass' : 'fail',
60
+ value: `${ethValue.toFixed(8)} ETH`,
61
+ message: hasGas ? undefined : `< ${(Number(minEth) / 1e18).toFixed(8)} ETH min for gas`,
62
+ });
63
+ }
64
+ catch (e) {
65
+ checks.push({ name: 'baseHasGas', status: 'fail', message: e?.message ?? 'balance check failed' });
66
+ }
67
+ })());
68
+ }
69
+ else {
70
+ checks.push({ name: 'baseHasGas', status: 'skip', message: 'no EVM address' });
71
+ }
72
+ // Quote checks in parallel — trivial amounts, no signing.
73
+ const quoteTasks = [];
74
+ quoteTasks.push((async () => {
75
+ if (!solanaAddress) {
76
+ checks.push({ name: 'canQuoteSolana', status: 'skip', message: 'no Solana address' });
77
+ return;
78
+ }
79
+ try {
80
+ const { fetchQuote, SOL_MINT } = await import('./solana/index.js');
81
+ const { USDC_MINT_SOLANA } = await import('./wallet-trading.js');
82
+ await fetchQuote({
83
+ inputMint: SOL_MINT.toBase58(),
84
+ outputMint: USDC_MINT_SOLANA,
85
+ amount: 1_000_000,
86
+ slippageBps: 50,
87
+ });
88
+ checks.push({ name: 'canQuoteSolana', status: 'pass' });
89
+ }
90
+ catch (e) {
91
+ checks.push({ name: 'canQuoteSolana', status: 'fail', message: e?.message ?? 'quote failed' });
92
+ }
93
+ })());
94
+ quoteTasks.push((async () => {
95
+ if (!evmAddress) {
96
+ checks.push({ name: 'canQuoteBase', status: 'skip', message: 'no EVM address' });
97
+ return;
98
+ }
99
+ try {
100
+ const { fetchParaswapPrice, NATIVE_ETH, BASE_USDC, BASE_CHAIN_ID } = await import('./evm-trading.js');
101
+ await fetchParaswapPrice({
102
+ srcToken: NATIVE_ETH,
103
+ destToken: BASE_USDC,
104
+ amount: '100000000000000',
105
+ srcDecimals: 18,
106
+ destDecimals: 6,
107
+ network: BASE_CHAIN_ID,
108
+ });
109
+ checks.push({ name: 'canQuoteBase', status: 'pass' });
110
+ }
111
+ catch (e) {
112
+ checks.push({ name: 'canQuoteBase', status: 'fail', message: e?.message ?? 'quote failed' });
113
+ }
114
+ })());
115
+ await Promise.all([...balanceTasks, ...quoteTasks]);
116
+ // Daemon status.
117
+ let daemonRunning = false;
118
+ let daemonPid = null;
119
+ let daemonLastTick = null;
120
+ let daemonAuto = null;
121
+ let daemonWalletRef = null;
122
+ try {
123
+ const { getDaemonStatus } = await import('./wallet-daemon.js');
124
+ const status = getDaemonStatus();
125
+ daemonRunning = status.running;
126
+ daemonPid = status.pid;
127
+ daemonLastTick = status.lastTick;
128
+ daemonAuto = status.opts?.autoExecute ?? null;
129
+ daemonWalletRef = status.opts?.walletRef ?? null;
130
+ }
131
+ catch { }
132
+ checks.push({
133
+ name: 'daemonRunning',
134
+ status: daemonRunning ? 'pass' : 'warn',
135
+ value: daemonRunning,
136
+ message: daemonRunning ? undefined : 'daemon not running — run `palmyr wallet daemon start --auto --wallet <ref>` for autonomous monitoring',
137
+ });
138
+ // Open position counts. Cross-chain by default.
139
+ let openSolana = 0;
140
+ let openBase = 0;
141
+ try {
142
+ const { listPositions } = await import('./wallet-trading.js');
143
+ const addrs = [solanaAddress, evmAddress].filter((x) => !!x);
144
+ if (addrs.length > 0) {
145
+ const positions = listPositions({ walletAddress: addrs, includeClosed: false });
146
+ openSolana = positions.filter((p) => p.chain === 'solana').length;
147
+ openBase = positions.filter((p) => p.chain === 'base').length;
148
+ }
149
+ }
150
+ catch { }
151
+ checks.push({
152
+ name: 'openPositions',
153
+ status: 'pass',
154
+ value: openSolana + openBase,
155
+ message: `solana=${openSolana} base=${openBase}`,
156
+ });
157
+ const requiredChecks = ['canSignSolana', 'canSignBase', 'solanaHasGas', 'baseHasGas', 'canQuoteSolana', 'canQuoteBase'];
158
+ const safeForAutonomousTrading = !checks.some((c) => requiredChecks.includes(c.name) && c.status === 'fail');
159
+ return {
160
+ wallet: opts.walletRef,
161
+ solanaAddress,
162
+ evmAddress,
163
+ safeForAutonomousTrading,
164
+ checks,
165
+ openPositions: {
166
+ solana: openSolana,
167
+ base: openBase,
168
+ total: openSolana + openBase,
169
+ },
170
+ balances: {
171
+ solana: solBalance,
172
+ base: baseBalance,
173
+ },
174
+ daemon: {
175
+ running: daemonRunning,
176
+ pid: daemonPid,
177
+ lastTick: daemonLastTick,
178
+ autoExecute: daemonAuto,
179
+ walletRef: daemonWalletRef,
180
+ },
181
+ };
182
+ }
183
+ //# sourceMappingURL=wallet-readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-readiness.js","sourceRoot":"","sources":["../wallet-readiness.ts"],"names":[],"mappings":"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"}
@@ -275,6 +275,7 @@ export type TradeLogLine = {
275
275
  currentPct: number;
276
276
  thresholdPct?: number;
277
277
  peakPct?: number;
278
+ drawdownPct?: number;
278
279
  thresholdDurationMs?: number;
279
280
  elapsedMs?: number;
280
281
  llmVerdict?: 'yes' | 'no' | 'unclear';
@@ -488,6 +489,8 @@ export interface BuyBaseResult {
488
489
  protectedExec: boolean;
489
490
  rpcUrl: string;
490
491
  inputAsset: BaseInputAsset;
492
+ /** One-line human-readable summary; safe to print directly. */
493
+ summary: string;
491
494
  }
492
495
  export declare function buyBase(opts: BuyBaseOpts): Promise<BuyBaseResult>;
493
496
  export interface SellBaseOpts {
@@ -530,6 +533,8 @@ export interface SellBaseResult {
530
533
  output: AssetAmount;
531
534
  /** Canonical, asset-tagged realized PnL for this sell. */
532
535
  realized: AssetPnl;
536
+ /** One-line human-readable summary; safe to print directly. */
537
+ summary: string;
533
538
  }
534
539
  export declare function sellBase(opts: SellBaseOpts): Promise<SellBaseResult>;
535
540
  export interface SyncBaseOpts {
@@ -594,6 +599,8 @@ export interface BuyResult {
594
599
  protectedExec: boolean;
595
600
  forensics?: FillForensics;
596
601
  inputAsset: SolanaInputAsset;
602
+ /** One-line human-readable summary; safe to print directly. */
603
+ summary: string;
597
604
  }
598
605
  export declare function buy(opts: BuyOpts): Promise<BuyResult>;
599
606
  export interface SellOpts {
@@ -630,6 +637,8 @@ export interface SellResult {
630
637
  output: AssetAmount;
631
638
  /** Canonical, asset-tagged realized PnL for this sell. */
632
639
  realized: AssetPnl;
640
+ /** One-line human-readable summary; safe to print directly. */
641
+ summary: string;
633
642
  }
634
643
  export declare function sell(opts: SellOpts): Promise<SellResult>;
635
644
  export interface SyncOpts {
@@ -884,6 +884,7 @@ export async function buyBase(opts) {
884
884
  // Dry-run must be strictly read-only: simulated trades never touch live state.
885
885
  if (!opts.dryRun)
886
886
  writePosition(position);
887
+ const summary = `${opts.dryRun ? '[dry-run] ' : ''}Bought ${tokensOut} ${opts.ca} for ${position.entry.amountIn} on Base.`;
887
888
  return {
888
889
  positionPath: opts.dryRun
889
890
  ? `simulated:${opts.ca}`
@@ -903,6 +904,7 @@ export async function buyBase(opts) {
903
904
  protectedExec: !!opts.protectedExec,
904
905
  rpcUrl,
905
906
  inputAsset,
907
+ summary,
906
908
  };
907
909
  }
908
910
  export async function sellBase(opts) {
@@ -1065,6 +1067,9 @@ export async function sellBase(opts) {
1065
1067
  // position file (otherwise a simulation can "close" a real position).
1066
1068
  if (!opts.dryRun)
1067
1069
  writePosition(position);
1070
+ const realizedSign = realizedAmount >= 0 ? '+' : '';
1071
+ const realizedDigits = outputAsset === 'USDC' ? 6 : 8;
1072
+ const summary = `${opts.dryRun ? '[dry-run] ' : ''}Sold ${tokensInDisplay} ${opts.ca} for ${outDisplay}; realized ${realizedSign}${realizedAmount.toFixed(realizedDigits)} ${outputAsset}; position ${position.status}.`;
1068
1073
  return {
1069
1074
  positionPath: opts.dryRun
1070
1075
  ? `simulated:${opts.ca}`
@@ -1085,6 +1090,7 @@ export async function sellBase(opts) {
1085
1090
  reconcileDriftRaw: reconcileDriftRaw === 0n ? undefined : reconcileDriftRaw.toString(),
1086
1091
  output: { asset: outputAsset, raw: outRaw, display: outDisplay },
1087
1092
  realized: { asset: outputAsset, amount: realizedAmount },
1093
+ summary,
1088
1094
  };
1089
1095
  }
1090
1096
  export async function syncBase(opts = {}) {
@@ -1358,6 +1364,7 @@ export async function buy(opts) {
1358
1364
  protectedExec: !!opts.protectedExec,
1359
1365
  forensics,
1360
1366
  inputAsset,
1367
+ summary: `${opts.dryRun ? '[dry-run] ' : ''}Bought ${tokensOut} ${opts.ca} for ${position.entry.amountIn} on Solana.`,
1361
1368
  };
1362
1369
  }
1363
1370
  export async function sell(opts) {
@@ -1511,6 +1518,9 @@ export async function sell(opts) {
1511
1518
  forensics,
1512
1519
  });
1513
1520
  }
1521
+ const sign = realizedSol >= 0 ? '+' : '';
1522
+ const digits = outputAsset === 'USDC' ? 6 : 8;
1523
+ const summary = `${opts.dryRun ? '[dry-run] ' : ''}Sold ${tokensInDisplay} ${opts.ca} for ${solOutDisplay}; realized ${sign}${realizedSol.toFixed(digits)} ${outputAsset}; position ${position.status}.`;
1514
1524
  return {
1515
1525
  positionPath: opts.dryRun
1516
1526
  ? `simulated:${opts.ca}`
@@ -1531,6 +1541,7 @@ export async function sell(opts) {
1531
1541
  outputAsset,
1532
1542
  output: { asset: outputAsset, raw: String(solOutRaw), display: solOutDisplay },
1533
1543
  realized: { asset: outputAsset, amount: realizedSol },
1544
+ summary,
1534
1545
  };
1535
1546
  }
1536
1547
  export async function sync(opts = {}) {