agentlaunch 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.
Files changed (70) hide show
  1. package/README.md +475 -0
  2. package/dist/__tests__/config.test.d.ts +20 -0
  3. package/dist/__tests__/config.test.d.ts.map +1 -0
  4. package/dist/__tests__/config.test.js +155 -0
  5. package/dist/__tests__/config.test.js.map +1 -0
  6. package/dist/commands/buy.d.ts +10 -0
  7. package/dist/commands/buy.d.ts.map +1 -0
  8. package/dist/commands/buy.js +126 -0
  9. package/dist/commands/buy.js.map +1 -0
  10. package/dist/commands/comments.d.ts +15 -0
  11. package/dist/commands/comments.d.ts.map +1 -0
  12. package/dist/commands/comments.js +137 -0
  13. package/dist/commands/comments.js.map +1 -0
  14. package/dist/commands/config.d.ts +10 -0
  15. package/dist/commands/config.d.ts.map +1 -0
  16. package/dist/commands/config.js +63 -0
  17. package/dist/commands/config.js.map +1 -0
  18. package/dist/commands/create.d.ts +33 -0
  19. package/dist/commands/create.d.ts.map +1 -0
  20. package/dist/commands/create.js +1177 -0
  21. package/dist/commands/create.js.map +1 -0
  22. package/dist/commands/deploy.d.ts +18 -0
  23. package/dist/commands/deploy.d.ts.map +1 -0
  24. package/dist/commands/deploy.js +178 -0
  25. package/dist/commands/deploy.js.map +1 -0
  26. package/dist/commands/holders.d.ts +13 -0
  27. package/dist/commands/holders.d.ts.map +1 -0
  28. package/dist/commands/holders.js +114 -0
  29. package/dist/commands/holders.js.map +1 -0
  30. package/dist/commands/init.d.ts +3 -0
  31. package/dist/commands/init.d.ts.map +1 -0
  32. package/dist/commands/init.js +506 -0
  33. package/dist/commands/init.js.map +1 -0
  34. package/dist/commands/list.d.ts +10 -0
  35. package/dist/commands/list.d.ts.map +1 -0
  36. package/dist/commands/list.js +135 -0
  37. package/dist/commands/list.js.map +1 -0
  38. package/dist/commands/optimize.d.ts +12 -0
  39. package/dist/commands/optimize.d.ts.map +1 -0
  40. package/dist/commands/optimize.js +134 -0
  41. package/dist/commands/optimize.js.map +1 -0
  42. package/dist/commands/scaffold.d.ts +25 -0
  43. package/dist/commands/scaffold.d.ts.map +1 -0
  44. package/dist/commands/scaffold.js +123 -0
  45. package/dist/commands/scaffold.js.map +1 -0
  46. package/dist/commands/sell.d.ts +10 -0
  47. package/dist/commands/sell.d.ts.map +1 -0
  48. package/dist/commands/sell.js +109 -0
  49. package/dist/commands/sell.js.map +1 -0
  50. package/dist/commands/status.d.ts +10 -0
  51. package/dist/commands/status.d.ts.map +1 -0
  52. package/dist/commands/status.js +124 -0
  53. package/dist/commands/status.js.map +1 -0
  54. package/dist/commands/tokenize.d.ts +16 -0
  55. package/dist/commands/tokenize.d.ts.map +1 -0
  56. package/dist/commands/tokenize.js +207 -0
  57. package/dist/commands/tokenize.js.map +1 -0
  58. package/dist/config.d.ts +44 -0
  59. package/dist/config.d.ts.map +1 -0
  60. package/dist/config.js +137 -0
  61. package/dist/config.js.map +1 -0
  62. package/dist/http.d.ts +24 -0
  63. package/dist/http.d.ts.map +1 -0
  64. package/dist/http.js +53 -0
  65. package/dist/http.js.map +1 -0
  66. package/dist/index.d.ts +19 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +86 -0
  69. package/dist/index.js.map +1 -0
  70. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,475 @@
1
+ # agentlaunch-cli
2
+
3
+ Command-line interface for [AgentLaunch](https://agent-launch.ai) — scaffold, deploy, and tokenize AI agents from your terminal or CI pipeline.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ # Global install (recommended for interactive use)
9
+ npm install -g agentlaunch-cli
10
+
11
+ # Or run without installing
12
+ npx agentlaunch-cli <command>
13
+ ```
14
+
15
+ Requires Node.js >= 18.
16
+
17
+ ## Configure
18
+
19
+ Get your API key from [agentverse.ai/profile/api-keys](https://agentverse.ai/profile/api-keys), then:
20
+
21
+ ```bash
22
+ agentlaunch config set-key YOUR_AGENTVERSE_API_KEY
23
+ ```
24
+
25
+ Check your configuration:
26
+
27
+ ```bash
28
+ agentlaunch config show
29
+ ```
30
+
31
+ Override the API base URL (self-hosted or staging):
32
+
33
+ ```bash
34
+ agentlaunch config set-url https://your-instance.example.com/api
35
+ ```
36
+
37
+ ## Commands
38
+
39
+ ### `agentlaunch create` — flagship one-command flow
40
+
41
+ Scaffold an agent, deploy it to Agentverse, and create a token record in one step.
42
+
43
+ ```bash
44
+ # Interactive — prompts for name, ticker, template, and workflow steps
45
+ agentlaunch create
46
+
47
+ # Fully specified — no prompts
48
+ agentlaunch create \
49
+ --name "My Research Agent" \
50
+ --ticker RSRCH \
51
+ --template research \
52
+ --description "Delivers on-demand research reports" \
53
+ --chain 97 \
54
+ --deploy \
55
+ --tokenize
56
+
57
+ # Machine-readable output for AI agents (no prompts, JSON only)
58
+ agentlaunch create \
59
+ --name "My Agent" --ticker MYAG --template custom \
60
+ --deploy --tokenize --json
61
+ ```
62
+
63
+ **Options:**
64
+
65
+ | Flag | Description | Default |
66
+ |------|-------------|---------|
67
+ | `--name <name>` | Agent name (max 32 chars) | prompted |
68
+ | `--ticker <ticker>` | Token ticker e.g. MYAG | prompted |
69
+ | `--template <t>` | custom, faucet, research, trading, data | prompted |
70
+ | `--description <desc>` | Token description (max 500 chars) | template default |
71
+ | `--chain <chainId>` | 97 = BSC Testnet, 56 = BSC Mainnet | 97 |
72
+ | `--deploy` | Deploy agent to Agentverse after scaffolding | false |
73
+ | `--tokenize` | Create token record after deploy | false |
74
+ | `--json` | Output only JSON (disables interactive prompts) | false |
75
+
76
+ **Flow:**
77
+
78
+ 1. Scaffold — generates `agent.py`, `README.md`, `.env.example` in a new directory
79
+ 2. Deploy (if `--deploy`) — uploads code to Agentverse, sets secrets, starts agent, polls until compiled
80
+ 3. Tokenize (if `--tokenize`) — calls `POST /tokenize`, prints handoff link
81
+
82
+ ---
83
+
84
+ ### `agentlaunch scaffold <name>`
85
+
86
+ Generate an agent project directory from a template.
87
+
88
+ ```bash
89
+ agentlaunch scaffold my-agent --type research
90
+
91
+ # JSON output
92
+ agentlaunch scaffold my-agent --type faucet --json
93
+ ```
94
+
95
+ **Options:**
96
+
97
+ | Flag | Description | Default |
98
+ |------|-------------|---------|
99
+ | `--type <type>` | faucet, research, trading, data | research |
100
+ | `--json` | Output only JSON | false |
101
+
102
+ Generated files:
103
+ - `agent.py` — ready-to-edit uAgents code with security, rate limiting, and AgentLaunch integration
104
+ - `README.md` — quickstart instructions
105
+ - `.env.example` — required environment variables
106
+
107
+ ---
108
+
109
+ ### `agentlaunch deploy`
110
+
111
+ Deploy `agent.py` to Agentverse. Auto-detects `README.md` and description from `agentlaunch.config.json` next to the agent file and uploads them as metadata to improve the agent's Agentverse ranking.
112
+
113
+ ```bash
114
+ agentlaunch deploy
115
+
116
+ # Custom file and name
117
+ agentlaunch deploy --file ./my-agent.py --name "My Research Agent"
118
+
119
+ # JSON output
120
+ agentlaunch deploy --json
121
+ ```
122
+
123
+ **Options:**
124
+
125
+ | Flag | Description | Default |
126
+ |------|-------------|---------|
127
+ | `--file <path>` | Path to agent Python file | `./agent.py` |
128
+ | `--name <name>` | Display name on Agentverse | AgentLaunch Agent |
129
+ | `--json` | Output only JSON | false |
130
+
131
+ Steps performed:
132
+ 1. Create agent on Agentverse (with README + description if detected)
133
+ 2. Upload code
134
+ 3. Set `AGENTVERSE_API_KEY` and `AGENTLAUNCH_API_KEY` secrets
135
+ 4. Start agent
136
+ 5. Poll until compiled (up to 60 seconds)
137
+ 6. Print optimization checklist (7 Agentverse ranking factors)
138
+
139
+ ---
140
+
141
+ ### `agentlaunch optimize <address>`
142
+
143
+ Update metadata on an already-deployed agent to improve its Agentverse ranking. Auto-detects `README.md` in the current directory.
144
+
145
+ ```bash
146
+ # Auto-detect README.md
147
+ agentlaunch optimize agent1q...
148
+
149
+ # Specify all fields
150
+ agentlaunch optimize agent1q... \
151
+ --readme ./README.md \
152
+ --description "AI research reports on demand" \
153
+ --avatar https://example.com/avatar.png
154
+
155
+ # JSON output
156
+ agentlaunch optimize agent1q... --json
157
+ ```
158
+
159
+ **Options:**
160
+
161
+ | Flag | Description | Default |
162
+ |------|-------------|---------|
163
+ | `--readme <path>` | Path to README.md file | auto-detects `./README.md` |
164
+ | `--description <text>` | Short description (max 200 chars) | - |
165
+ | `--avatar <url>` | Public URL for avatar image | - |
166
+ | `--json` | Output only JSON | false |
167
+
168
+ ---
169
+
170
+ ### `agentlaunch tokenize`
171
+
172
+ Create a token record on AgentLaunch and receive a handoff link for on-chain deployment.
173
+
174
+ ```bash
175
+ agentlaunch tokenize \
176
+ --agent agent1qXXXXXXXX \
177
+ --name "My Research Agent" \
178
+ --symbol RSRCH
179
+
180
+ # With optional fields
181
+ agentlaunch tokenize \
182
+ --agent agent1qXXXXXXXX \
183
+ --name "My Research Agent" \
184
+ --symbol RSRCH \
185
+ --description "Delivers on-demand research" \
186
+ --chain 97 \
187
+ --json
188
+ ```
189
+
190
+ **Options:**
191
+
192
+ | Flag | Description | Default |
193
+ |------|-------------|---------|
194
+ | `--agent <address>` | Agentverse address (agent1q...) | required |
195
+ | `--name <name>` | Token name (max 32 chars) | required |
196
+ | `--symbol <symbol>` | Ticker (2-11 chars) | required |
197
+ | `--description <desc>` | Token description | - |
198
+ | `--image <url>` | Token logo URL | - |
199
+ | `--chain <chainId>` | 97 = BSC Testnet, 56 = BSC Mainnet | 97 |
200
+ | `--max-wallet <0\|1\|2>` | Max wallet size: 0=unlimited, 1=0.5% (5M tokens), 2=1% (10M tokens) | 0 |
201
+ | `--initial-buy <amount>` | FET to spend buying tokens immediately after deploy (0–1000 FET) | 0 |
202
+ | `--category <id>` | Category ID for the token | 1 |
203
+ | `--json` | Output only JSON | false |
204
+
205
+ The command returns a **handoff link** (e.g. `https://agent-launch.ai/deploy/123`). Share this with a human who connects their wallet and pays the deployment fee. The URL is set via `AGENT_LAUNCH_FRONTEND_URL` in `.env` (production by default).
206
+
207
+ **Max wallet options:**
208
+
209
+ | Value | Limit | Token cap |
210
+ |-------|-------|-----------|
211
+ | `0` | Unlimited | No cap |
212
+ | `1` | 0.5% of supply | 5,000,000 tokens |
213
+ | `2` | 1% of supply | 10,000,000 tokens |
214
+
215
+ **Initial buy:** Specify a FET amount (e.g. `--initial-buy 100`) to have the deploying wallet purchase tokens immediately when the contract is deployed. This seeds early liquidity and sets an initial price. Maximum 1,000 FET.
216
+
217
+ ---
218
+
219
+ ### `agentlaunch comments <address>`
220
+
221
+ List or post comments on a token.
222
+
223
+ ```bash
224
+ # List comments for a token
225
+ agentlaunch comments 0xAbCdEf...
226
+
227
+ # Post a comment (requires API key configured)
228
+ agentlaunch comments 0xAbCdEf... --post "Great agent, just bought some!"
229
+
230
+ # JSON output for machine parsing
231
+ agentlaunch comments 0xAbCdEf... --json
232
+ ```
233
+
234
+ **Options:**
235
+
236
+ | Flag | Description | Default |
237
+ |------|-------------|---------|
238
+ | `--post <message>` | Post a new comment (max 500 chars). Requires API key. | - |
239
+ | `--json` | Output only JSON | false |
240
+
241
+ **Example table output (listing):**
242
+
243
+ ```
244
+ Comments for 0xAbCdEf... (3 comments)
245
+
246
+ ──────────────────────────────────────────────────────────────────
247
+ Author Message Posted
248
+ ──────────────────────────────────────────────────────────────────
249
+ 0x1234...abcd Great project! Just bought 10k tokens. 2 hours ago
250
+ 0x5678...ef01 When DEX listing? 5 hours ago
251
+ 0x9abc...2345 Solid agent, bullish. 1 day ago
252
+ ──────────────────────────────────────────────────────────────────
253
+ ```
254
+
255
+ ---
256
+
257
+ ### `agentlaunch holders <address>`
258
+
259
+ Show the token holder distribution table.
260
+
261
+ ```bash
262
+ # Show holders for a token
263
+ agentlaunch holders 0xAbCdEf...
264
+
265
+ # JSON output for machine parsing
266
+ agentlaunch holders 0xAbCdEf... --json
267
+ ```
268
+
269
+ **Options:**
270
+
271
+ | Flag | Description |
272
+ |------|-------------|
273
+ | `--json` | Output only JSON |
274
+
275
+ **Example table output:**
276
+
277
+ ```
278
+ Holders for 0xAbCdEf... (47 holders)
279
+
280
+ ──────────────────────────────────────────────────────────
281
+ Address Balance Percentage
282
+ ──────────────────────────────────────────────────────────
283
+ 0x1234...abcd 12,500,000 1.56%
284
+ 0x5678...ef01 8,300,000 1.04%
285
+ 0x9abc...2345 4,100,000 0.51%
286
+ ...
287
+ ──────────────────────────────────────────────────────────
288
+ ```
289
+
290
+ ---
291
+
292
+ ### `agentlaunch list`
293
+
294
+ List tokens on AgentLaunch.
295
+
296
+ ```bash
297
+ agentlaunch list
298
+
299
+ # Custom options
300
+ agentlaunch list --limit 20 --sort market_cap
301
+
302
+ # JSON output for AI agents
303
+ agentlaunch list --limit 5 --json
304
+ ```
305
+
306
+ **Options:**
307
+
308
+ | Flag | Description | Default |
309
+ |------|-------------|---------|
310
+ | `--limit <n>` | Number of tokens to show (1-100) | 10 |
311
+ | `--sort <by>` | trending, latest, market_cap | latest |
312
+ | `--json` | Output only JSON | false |
313
+
314
+ **Example table output:**
315
+
316
+ ```
317
+ AgentLaunch Tokens (sort: trending, limit: 10)
318
+
319
+ ──────────────────────────────────────────────────────────
320
+ Name Symbol Price (FET) Progress Status
321
+ ──────────────────────────────────────────────────────────
322
+ FET Gifter GIFT 0.00004200 14.3% Active
323
+ Research Bot RSRCH 0.00001100 6.8% Active
324
+ ...
325
+ ──────────────────────────────────────────────────────────
326
+ ```
327
+
328
+ ---
329
+
330
+ ### `agentlaunch status <address>`
331
+
332
+ Show detailed status of a token by its contract address.
333
+
334
+ ```bash
335
+ agentlaunch status 0xAbCdEf...
336
+
337
+ # JSON output
338
+ agentlaunch status 0xAbCdEf... --json
339
+ ```
340
+
341
+ **Options:**
342
+
343
+ | Flag | Description |
344
+ |------|-------------|
345
+ | `--json` | Output only JSON |
346
+
347
+ **Example output:**
348
+
349
+ ```
350
+ ==================================================
351
+ TOKEN STATUS
352
+ ==================================================
353
+ Name: FET Gifter
354
+ Symbol: GIFT
355
+ Address: 0xAbCdEf...
356
+ Chain: BSC Testnet
357
+ Price: 0.00004200 FET
358
+ Market Cap: 12.60K FET
359
+ Holders: 47
360
+ Progress: 14.20%
361
+ Status: Bonding curve (14.20% to 30,000 FET target)
362
+ ==================================================
363
+ ```
364
+
365
+ ---
366
+
367
+ ### `agentlaunch config`
368
+
369
+ Manage CLI configuration.
370
+
371
+ ```bash
372
+ agentlaunch config set-key <apiKey> # Store your API key
373
+ agentlaunch config show # Show current config
374
+ agentlaunch config set-url <url> # Set custom API base URL
375
+ ```
376
+
377
+ ---
378
+
379
+ ## JSON Mode (Machine-Readable for AI Agents)
380
+
381
+ Every command supports `--json`. In JSON mode:
382
+ - All output is valid JSON to stdout
383
+ - No decorative text, tables, or prompts
384
+ - Interactive prompts are disabled (missing required flags cause an error JSON)
385
+ - Exit code 0 on success, 1 on error
386
+
387
+ **Example — AI agent creates a token programmatically:**
388
+
389
+ ```bash
390
+ RESULT=$(agentlaunch create \
391
+ --name "Autonomous Analyst" \
392
+ --ticker ANLT \
393
+ --template research \
394
+ --deploy --tokenize --json)
395
+
396
+ HANDOFF=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['handoffLink'])")
397
+ echo "Share with human: $HANDOFF"
398
+ ```
399
+
400
+ ---
401
+
402
+ ## Platform Constants
403
+
404
+ These values are enforced by the deployed smart contracts and cannot be changed by the CLI or platform:
405
+
406
+ | Constant | Value | Notes |
407
+ |----------|-------|-------|
408
+ | Token deployment fee | **120 FET** | Read dynamically from contract; may change via multi-sig governance |
409
+ | Graduation target | **30,000 FET** | Auto DEX listing when reached |
410
+ | Total buy supply | 800,000,000 tokens | Fixed bonding curve supply |
411
+ | Trading fee | **2%** | 100% to protocol treasury. **There is NO creator fee.** |
412
+
413
+ The 2% trading fee goes **entirely to the protocol treasury (REVENUE_ACCOUNT)**. There is no fee split to token creators.
414
+
415
+ ---
416
+
417
+ ## Templates
418
+
419
+ | Template | Use Case |
420
+ |----------|----------|
421
+ | `custom` | Blank slate — add your own business logic |
422
+ | `faucet` | Distributes testnet FET/BNB to developers |
423
+ | `research` | On-demand research reports and analysis |
424
+ | `trading` | Token price monitoring and trade alerts |
425
+ | `data` | Structured data feeds and query results |
426
+
427
+ ---
428
+
429
+ ## Workflow Examples
430
+
431
+ ### One-command launch (interactive)
432
+
433
+ ```bash
434
+ agentlaunch config set-key $MY_API_KEY
435
+ agentlaunch create
436
+ ```
437
+
438
+ ### Step-by-step
439
+
440
+ ```bash
441
+ agentlaunch config set-key $MY_API_KEY
442
+ agentlaunch scaffold my-agent --type research
443
+ cd my-agent
444
+ cp .env.example .env # fill in values
445
+ # Edit agent.py to add your business logic
446
+ agentlaunch deploy
447
+ # Copy the agent address printed above
448
+ agentlaunch tokenize --agent agent1qXXX --name "My Agent" --symbol MYAG
449
+ # Share the handoff link with a human to complete on-chain deployment
450
+ ```
451
+
452
+ ### Headless CI pipeline
453
+
454
+ ```bash
455
+ # All flags provided, JSON output — no interactive prompts
456
+ agentlaunch create \
457
+ --name "Price Oracle" \
458
+ --ticker PORC \
459
+ --template trading \
460
+ --chain 97 \
461
+ --deploy \
462
+ --tokenize \
463
+ --json | jq .handoffLink
464
+ ```
465
+
466
+ ---
467
+
468
+ ## Resources
469
+
470
+ - [AgentLaunch Platform](https://agent-launch.ai) (production, default) | [Dev](https://launchpad-frontend-dev-1056182620041.us-central1.run.app)
471
+ - [API Documentation](https://agent-launch.ai/docs/openapi)
472
+ - [Agent Integration Guide](https://agent-launch.ai/docs/for-agents)
473
+ - [skill.md](https://agent-launch.ai/skill.md) — Machine-readable capability discovery
474
+ - [Agentverse](https://agentverse.ai)
475
+ - [Agentverse API Keys](https://agentverse.ai/profile/api-keys)
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Tests for CLI config module — CLI-001
3
+ *
4
+ * Verifies:
5
+ * - readConfig() returns empty object when config file does not exist
6
+ * - readConfig() returns empty object when config file contains invalid JSON
7
+ * - writeConfig() merges partial updates with existing config
8
+ * - writeConfig() creates the directory when it does not exist
9
+ * - getBaseUrl() returns DEFAULT_BASE_URL when no baseUrl is in config
10
+ * - getBaseUrl() returns the stored baseUrl when one is configured
11
+ * - maskKey() masks keys longer than 8 chars
12
+ * - maskKey() returns '****' for short keys
13
+ * - requireApiKey() throws a descriptive error when no apiKey is set
14
+ *
15
+ * Uses real filesystem operations against a temporary directory to avoid
16
+ * patching the module internals. The config path is redirected by overriding
17
+ * the HOME environment variable before the module is loaded.
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Tests for CLI config module — CLI-001
3
+ *
4
+ * Verifies:
5
+ * - readConfig() returns empty object when config file does not exist
6
+ * - readConfig() returns empty object when config file contains invalid JSON
7
+ * - writeConfig() merges partial updates with existing config
8
+ * - writeConfig() creates the directory when it does not exist
9
+ * - getBaseUrl() returns DEFAULT_BASE_URL when no baseUrl is in config
10
+ * - getBaseUrl() returns the stored baseUrl when one is configured
11
+ * - maskKey() masks keys longer than 8 chars
12
+ * - maskKey() returns '****' for short keys
13
+ * - requireApiKey() throws a descriptive error when no apiKey is set
14
+ *
15
+ * Uses real filesystem operations against a temporary directory to avoid
16
+ * patching the module internals. The config path is redirected by overriding
17
+ * the HOME environment variable before the module is loaded.
18
+ */
19
+ import { describe, it, before, after } from 'node:test';
20
+ import assert from 'node:assert/strict';
21
+ import fs from 'node:fs';
22
+ import os from 'node:os';
23
+ import path from 'node:path';
24
+ import { maskKey, DEFAULT_BASE_URL } from '../config.js';
25
+ // ---------------------------------------------------------------------------
26
+ // maskKey — pure function, no filesystem needed
27
+ // ---------------------------------------------------------------------------
28
+ describe('maskKey()', () => {
29
+ it('returns **** for keys of 8 chars or fewer', () => {
30
+ assert.equal(maskKey('short'), '****');
31
+ assert.equal(maskKey('12345678'), '****');
32
+ });
33
+ it('shows the first 8 characters followed by masked suffix for longer keys', () => {
34
+ const key = 'av-abcdefghijklmnop';
35
+ const masked = maskKey(key);
36
+ assert.ok(masked.startsWith('av-abcde'), `masked: ${masked}`);
37
+ assert.ok(masked.includes('...'), 'should include ellipsis');
38
+ assert.ok(masked.includes('masked'), 'should indicate masking');
39
+ });
40
+ it('does not expose more than the first 8 characters', () => {
41
+ const key = 'SECRETKEY_SHOULDNOTAPPEAR';
42
+ const masked = maskKey(key);
43
+ // Only first 8 chars are shown
44
+ assert.ok(!masked.includes('SHOULDNOTAPPEAR'), `masked: ${masked}`);
45
+ });
46
+ });
47
+ // ---------------------------------------------------------------------------
48
+ // DEFAULT_BASE_URL constant
49
+ // ---------------------------------------------------------------------------
50
+ describe('DEFAULT_BASE_URL', () => {
51
+ it('points to the production API endpoint by default', () => {
52
+ assert.equal(DEFAULT_BASE_URL, 'https://agent-launch.ai/api');
53
+ });
54
+ });
55
+ // ---------------------------------------------------------------------------
56
+ // readConfig / writeConfig / getBaseUrl — filesystem-based tests
57
+ // ---------------------------------------------------------------------------
58
+ describe('readConfig / writeConfig / getBaseUrl', () => {
59
+ let tmpDir;
60
+ let originalHome;
61
+ // We cannot easily redirect the CONFIG_DIR/CONFIG_FILE constants at runtime
62
+ // without re-importing the module, because they are computed at module load
63
+ // time. Instead, we test the behaviour through the real filesystem using
64
+ // the actual ~/.agentlaunch path — but we isolate by restoring the file
65
+ // after each test.
66
+ //
67
+ // Strategy: back up any existing config, run tests, restore.
68
+ const configDir = path.join(os.homedir(), '.agentlaunch');
69
+ const configFile = path.join(configDir, 'config.json');
70
+ let backupContent = null;
71
+ before(() => {
72
+ // Save existing config (if any) so tests are non-destructive
73
+ if (fs.existsSync(configFile)) {
74
+ backupContent = fs.readFileSync(configFile, 'utf8');
75
+ }
76
+ });
77
+ after(() => {
78
+ // Restore original config (or remove the file if it didn't exist before)
79
+ if (backupContent !== null) {
80
+ fs.mkdirSync(configDir, { recursive: true });
81
+ fs.writeFileSync(configFile, backupContent, { mode: 0o600 });
82
+ }
83
+ else if (fs.existsSync(configFile)) {
84
+ fs.unlinkSync(configFile);
85
+ }
86
+ });
87
+ it('readConfig() returns {} when config file does not exist', async () => {
88
+ // Remove config file if present
89
+ if (fs.existsSync(configFile))
90
+ fs.unlinkSync(configFile);
91
+ // Re-import to get a fresh module call
92
+ const { readConfig } = await import('../config.js');
93
+ const cfg = readConfig();
94
+ assert.deepEqual(cfg, {});
95
+ });
96
+ it('readConfig() returns {} when config file contains invalid JSON', async () => {
97
+ fs.mkdirSync(configDir, { recursive: true });
98
+ fs.writeFileSync(configFile, 'NOT_VALID_JSON', { mode: 0o600 });
99
+ const { readConfig } = await import('../config.js');
100
+ const cfg = readConfig();
101
+ assert.deepEqual(cfg, {});
102
+ });
103
+ it('writeConfig() persists apiKey to disk', async () => {
104
+ if (fs.existsSync(configFile))
105
+ fs.unlinkSync(configFile);
106
+ const { writeConfig, readConfig } = await import('../config.js');
107
+ writeConfig({ apiKey: 'av-testkey-123456' });
108
+ const cfg = readConfig();
109
+ assert.equal(cfg.apiKey, 'av-testkey-123456');
110
+ });
111
+ it('writeConfig() merges partial updates with existing values', async () => {
112
+ if (fs.existsSync(configFile))
113
+ fs.unlinkSync(configFile);
114
+ const { writeConfig, readConfig } = await import('../config.js');
115
+ // Write initial config with apiKey
116
+ writeConfig({ apiKey: 'av-initial-key' });
117
+ // Add baseUrl without overwriting apiKey
118
+ writeConfig({ baseUrl: 'https://custom.server.com/api' });
119
+ const cfg = readConfig();
120
+ assert.equal(cfg.apiKey, 'av-initial-key', 'apiKey should be preserved');
121
+ assert.equal(cfg.baseUrl, 'https://custom.server.com/api', 'baseUrl should be set');
122
+ });
123
+ it('getBaseUrl() returns DEFAULT_BASE_URL when no baseUrl is configured', async () => {
124
+ if (fs.existsSync(configFile))
125
+ fs.unlinkSync(configFile);
126
+ const { getBaseUrl } = await import('../config.js');
127
+ assert.equal(getBaseUrl(), DEFAULT_BASE_URL);
128
+ });
129
+ it('getBaseUrl() returns the configured baseUrl', async () => {
130
+ if (fs.existsSync(configFile))
131
+ fs.unlinkSync(configFile);
132
+ const { writeConfig, getBaseUrl } = await import('../config.js');
133
+ writeConfig({ baseUrl: 'https://staging.agent-launch.ai/api' });
134
+ assert.equal(getBaseUrl(), 'https://staging.agent-launch.ai/api');
135
+ });
136
+ it('requireApiKey() throws when no apiKey is configured', async () => {
137
+ if (fs.existsSync(configFile))
138
+ fs.unlinkSync(configFile);
139
+ const { requireApiKey } = await import('../config.js');
140
+ assert.throws(() => requireApiKey(), (err) => {
141
+ assert.ok(err instanceof Error);
142
+ assert.ok(err.message.includes('API key not configured'), `Error message: ${err.message}`);
143
+ return true;
144
+ });
145
+ });
146
+ it('requireApiKey() returns the stored apiKey', async () => {
147
+ if (fs.existsSync(configFile))
148
+ fs.unlinkSync(configFile);
149
+ const { writeConfig, requireApiKey } = await import('../config.js');
150
+ writeConfig({ apiKey: 'av-valid-key-abc' });
151
+ const key = requireApiKey();
152
+ assert.equal(key, 'av-valid-key-abc');
153
+ });
154
+ });
155
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * CLI: buy command
3
+ *
4
+ * agentlaunch buy <address> --amount <FET> [--slippage 5] [--chain 97] [--dry-run] [--json]
5
+ *
6
+ * Executes a buy on a bonding curve token contract, or previews the trade with --dry-run.
7
+ */
8
+ import { Command } from "commander";
9
+ export declare function registerBuyCommand(program: Command): void;
10
+ //# sourceMappingURL=buy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buy.d.ts","sourceRoot":"","sources":["../../src/commands/buy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4HzD"}