agentlaunch-templates 0.1.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 (37) hide show
  1. package/dist/generator.d.ts +43 -0
  2. package/dist/generator.d.ts.map +1 -0
  3. package/dist/generator.js +213 -0
  4. package/dist/generator.js.map +1 -0
  5. package/dist/index.d.ts +41 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +39 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/registry.d.ts +49 -0
  10. package/dist/registry.d.ts.map +1 -0
  11. package/dist/registry.js +47 -0
  12. package/dist/registry.js.map +1 -0
  13. package/dist/templates/custom.d.ts +11 -0
  14. package/dist/templates/custom.d.ts.map +1 -0
  15. package/dist/templates/custom.js +458 -0
  16. package/dist/templates/custom.js.map +1 -0
  17. package/dist/templates/data-analyzer.d.ts +11 -0
  18. package/dist/templates/data-analyzer.d.ts.map +1 -0
  19. package/dist/templates/data-analyzer.js +565 -0
  20. package/dist/templates/data-analyzer.js.map +1 -0
  21. package/dist/templates/gifter.d.ts +15 -0
  22. package/dist/templates/gifter.d.ts.map +1 -0
  23. package/dist/templates/gifter.js +717 -0
  24. package/dist/templates/gifter.js.map +1 -0
  25. package/dist/templates/price-monitor.d.ts +11 -0
  26. package/dist/templates/price-monitor.d.ts.map +1 -0
  27. package/dist/templates/price-monitor.js +577 -0
  28. package/dist/templates/price-monitor.js.map +1 -0
  29. package/dist/templates/research.d.ts +11 -0
  30. package/dist/templates/research.d.ts.map +1 -0
  31. package/dist/templates/research.js +593 -0
  32. package/dist/templates/research.js.map +1 -0
  33. package/dist/templates/trading-bot.d.ts +11 -0
  34. package/dist/templates/trading-bot.d.ts.map +1 -0
  35. package/dist/templates/trading-bot.js +559 -0
  36. package/dist/templates/trading-bot.js.map +1 -0
  37. package/package.json +24 -0
@@ -0,0 +1,593 @@
1
+ /**
2
+ * research.ts — Delivers on-demand research reports for AgentLaunch tokens
3
+ *
4
+ * Platform constants (source of truth: deployed smart contracts):
5
+ * - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
6
+ * - Graduation target: 30,000 FET -> auto DEX listing
7
+ * - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
8
+ */
9
+ export const template = {
10
+ name: "research",
11
+ description: "Delivers on-demand research reports and analysis for AgentLaunch tokens",
12
+ category: "AI/ML",
13
+ variables: [
14
+ { name: "agent_name", required: true, description: "Name of the agent" },
15
+ {
16
+ name: "description",
17
+ default: "Delivers on-demand research reports and analysis for AgentLaunch tokens",
18
+ description: "Short description of what this agent does",
19
+ },
20
+ {
21
+ name: "ai_model",
22
+ default: "mistralai/Mistral-7B-Instruct-v0.2",
23
+ description: "Hugging Face model ID for report generation",
24
+ },
25
+ {
26
+ name: "report_max_tokens",
27
+ default: "512",
28
+ description: "Maximum tokens in generated report",
29
+ },
30
+ {
31
+ name: "rate_limit_per_minute",
32
+ default: "10",
33
+ description: "Max requests per user per minute (lower due to AI calls)",
34
+ },
35
+ {
36
+ name: "free_requests_per_day",
37
+ default: "5",
38
+ description: "Free tier daily request quota",
39
+ },
40
+ {
41
+ name: "premium_token_threshold",
42
+ default: "1000",
43
+ description: "Token balance required for premium tier",
44
+ },
45
+ ],
46
+ dependencies: ["requests"],
47
+ secrets: [
48
+ "AGENTVERSE_API_KEY",
49
+ "AGENTLAUNCH_API_KEY",
50
+ "AGENT_ADDRESS",
51
+ "AGENT_OWNER_ADDRESS",
52
+ "HUGGINGFACE_API_KEY",
53
+ ],
54
+ code: `#!/usr/bin/env python3
55
+ """
56
+ {{agent_name}} — AgentLaunch Research Agent
57
+ Generated by: agentlaunch scaffold {{agent_name}} --type research
58
+
59
+ Fetches token data from agent-launch.ai and generates a structured research
60
+ report using an AI model via the Hugging Face Inference API.
61
+
62
+ Platform constants (source of truth: deployed smart contracts):
63
+ - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
64
+ - Graduation target: 30,000 FET -> auto DEX listing
65
+ - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
66
+ """
67
+
68
+ from uagents import Agent, Context, Protocol
69
+ from uagents_core.contrib.protocols.chat import (
70
+ ChatAcknowledgement,
71
+ ChatMessage,
72
+ EndSessionContent,
73
+ TextContent,
74
+ chat_protocol_spec,
75
+ )
76
+
77
+ import json
78
+ import os
79
+ import time
80
+ from collections import defaultdict
81
+ from datetime import datetime
82
+ from typing import Any, Dict, List, Optional
83
+ from uuid import uuid4
84
+
85
+ import requests
86
+
87
+ # ==============================================================================
88
+ # API CONFIG — Override via environment variables, never hardcode
89
+ # ==============================================================================
90
+
91
+ AGENTLAUNCH_API = os.environ.get("AGENTLAUNCH_API", "https://agent-launch.ai/api")
92
+ HF_API_URL = "https://api-inference.huggingface.co/models/{{ai_model}}"
93
+
94
+ # ==============================================================================
95
+ # BUSINESS CONFIG
96
+ # ==============================================================================
97
+
98
+ OWNER_ADDRESS = os.environ.get("AGENT_OWNER_ADDRESS", "")
99
+
100
+ BUSINESS = {
101
+ "name": "{{agent_name}}",
102
+ "description": "{{description}}",
103
+ "version": "1.0.0",
104
+ "ai_model": "{{ai_model}}",
105
+ "report_max_tokens": int("{{report_max_tokens}}"),
106
+ "free_requests_per_day": {{free_requests_per_day}},
107
+ "premium_token_threshold": {{premium_token_threshold}},
108
+ "rate_limit_per_minute": {{rate_limit_per_minute}},
109
+ "max_input_length": 5000,
110
+ }
111
+
112
+
113
+ # ==============================================================================
114
+ # LAYER 1: FOUNDATION
115
+ # ==============================================================================
116
+
117
+
118
+ class Logger:
119
+ """Structured logging with audit trail."""
120
+
121
+ @staticmethod
122
+ def info(ctx: Context, event: str, data: Optional[Dict] = None) -> None:
123
+ ctx.logger.info(f"[{event}] {json.dumps(data or {})}")
124
+
125
+ @staticmethod
126
+ def audit(ctx: Context, user: str, action: str) -> None:
127
+ ctx.logger.info(
128
+ f"[AUDIT] user={user[:20]} action={action} "
129
+ f"ts={datetime.utcnow().isoformat()}"
130
+ )
131
+
132
+ @staticmethod
133
+ def error(ctx: Context, event: str, error: str) -> None:
134
+ ctx.logger.error(f"[{event}] {error}")
135
+
136
+
137
+ # ==============================================================================
138
+ # LAYER 2: SECURITY
139
+ # ==============================================================================
140
+
141
+
142
+ class Security:
143
+ """Rate limiting and input validation."""
144
+
145
+ def __init__(self) -> None:
146
+ self._requests: Dict[str, List[float]] = defaultdict(list)
147
+ self._check_count: int = 0
148
+
149
+ def check(self, ctx: Context, user_id: str, message: str) -> tuple:
150
+ now = time.time()
151
+
152
+ self._requests[user_id] = [
153
+ t for t in self._requests[user_id] if now - t < 60
154
+ ]
155
+ if len(self._requests[user_id]) >= BUSINESS["rate_limit_per_minute"]:
156
+ return None, "Rate limit exceeded. Please wait a moment."
157
+ self._requests[user_id].append(now)
158
+
159
+ self._check_count += 1
160
+ if self._check_count % 100 == 0:
161
+ stale = [
162
+ k
163
+ for k, v in self._requests.items()
164
+ if not v or (now - max(v)) > 300
165
+ ]
166
+ for k in stale:
167
+ del self._requests[k]
168
+
169
+ if not message or not message.strip():
170
+ return None, "Empty message."
171
+ if len(message) > BUSINESS["max_input_length"]:
172
+ return None, f"Message too long (max {BUSINESS['max_input_length']} chars)."
173
+
174
+ return message.strip(), None
175
+
176
+
177
+ # ==============================================================================
178
+ # LAYER 3: STABILITY
179
+ # ==============================================================================
180
+
181
+
182
+ class Health:
183
+ """Track uptime and error rate."""
184
+
185
+ def __init__(self) -> None:
186
+ self._start: datetime = datetime.utcnow()
187
+ self._requests: int = 0
188
+ self._errors: int = 0
189
+
190
+ def record(self, success: bool) -> None:
191
+ self._requests += 1
192
+ if not success:
193
+ self._errors += 1
194
+
195
+ def status(self) -> Dict[str, Any]:
196
+ uptime = (datetime.utcnow() - self._start).total_seconds()
197
+ error_rate = (self._errors / self._requests * 100) if self._requests else 0
198
+ return {
199
+ "status": "healthy" if error_rate < 10 else "degraded",
200
+ "uptime_seconds": int(uptime),
201
+ "requests": self._requests,
202
+ "error_rate": f"{error_rate:.1f}%",
203
+ }
204
+
205
+
206
+ # ==============================================================================
207
+ # LAYER 4: SPEED
208
+ # ==============================================================================
209
+
210
+
211
+ class Cache:
212
+ """In-memory TTL cache."""
213
+
214
+ def __init__(self, max_size: int = 1000) -> None:
215
+ self._data: Dict[str, tuple] = {}
216
+ self._max_size: int = max_size
217
+
218
+ def get(self, key: str) -> Any:
219
+ if key in self._data:
220
+ value, expires = self._data[key]
221
+ if expires > time.time():
222
+ return value
223
+ del self._data[key]
224
+ return None
225
+
226
+ def set(self, key: str, value: Any, ttl: int = 300) -> None:
227
+ if len(self._data) >= self._max_size:
228
+ now = time.time()
229
+ expired = [k for k, (_, exp) in self._data.items() if exp <= now]
230
+ for k in expired:
231
+ del self._data[k]
232
+ if len(self._data) >= self._max_size:
233
+ to_drop = sorted(self._data.items(), key=lambda x: x[1][1])[
234
+ : self._max_size // 10
235
+ ]
236
+ for k, _ in to_drop:
237
+ del self._data[k]
238
+ self._data[key] = (value, time.time() + ttl)
239
+
240
+
241
+ # ==============================================================================
242
+ # LAYER 5: REVENUE
243
+ # ==============================================================================
244
+
245
+
246
+ class Revenue:
247
+ """Token-gated access and daily usage quotas."""
248
+
249
+ def __init__(self, cache: Cache) -> None:
250
+ self._cache = cache
251
+ self._usage: Dict[str, List[str]] = defaultdict(list)
252
+
253
+ def get_tier(self, user_address: str) -> str:
254
+ cached = self._cache.get(f"tier:{user_address}")
255
+ if cached is not None:
256
+ return cached
257
+ try:
258
+ r = requests.get(
259
+ f"{AGENTLAUNCH_API}/agents/token/{user_address}", timeout=5
260
+ )
261
+ if r.status_code == 200:
262
+ data = r.json()
263
+ balance = data.get("balance", 0)
264
+ tier = (
265
+ "premium"
266
+ if balance >= BUSINESS["premium_token_threshold"]
267
+ else "free"
268
+ )
269
+ self._cache.set(f"tier:{user_address}", tier, ttl=300)
270
+ return tier
271
+ except Exception:
272
+ pass
273
+ return "free"
274
+
275
+ def check_quota(self, user_id: str, tier: str) -> tuple:
276
+ today = datetime.utcnow().date().isoformat()
277
+ self._usage[user_id] = [
278
+ t for t in self._usage[user_id] if t.startswith(today)
279
+ ]
280
+ today_usage = len(self._usage[user_id])
281
+ limit = 1000 if tier == "premium" else BUSINESS["free_requests_per_day"]
282
+ if today_usage >= limit:
283
+ if tier == "free":
284
+ return False, (
285
+ f"Free limit reached ({limit}/day). "
286
+ f"Hold {BUSINESS['premium_token_threshold']} tokens for premium!"
287
+ )
288
+ return False, f"Daily limit reached ({limit}/day)."
289
+ self._usage[user_id].append(datetime.utcnow().isoformat())
290
+ return True, None
291
+
292
+
293
+ # ==============================================================================
294
+ # AGENTLAUNCH INTEGRATION
295
+ # ==============================================================================
296
+
297
+
298
+ class AgentLaunch:
299
+ """Create and manage tokens on AgentLaunch."""
300
+
301
+ @staticmethod
302
+ def tokenize() -> Dict:
303
+ agent_address = os.environ.get("AGENT_ADDRESS")
304
+ if not agent_address:
305
+ return {"error": "AGENT_ADDRESS env var not set."}
306
+ try:
307
+ r = requests.post(
308
+ f"{AGENTLAUNCH_API}/agents/tokenize",
309
+ headers={
310
+ "X-API-Key": os.environ.get("AGENTLAUNCH_API_KEY", ""),
311
+ "Content-Type": "application/json",
312
+ },
313
+ json={
314
+ "agentAddress": agent_address,
315
+ "name": BUSINESS["name"],
316
+ "description": BUSINESS["description"],
317
+ },
318
+ timeout=30,
319
+ )
320
+ return r.json() if r.status_code in [200, 201] else {"error": r.text}
321
+ except Exception as e:
322
+ return {"error": str(e)}
323
+
324
+
325
+ # ==============================================================================
326
+ # RESEARCH BUSINESS LOGIC
327
+ # ==============================================================================
328
+
329
+
330
+ class ResearchBusiness:
331
+ """
332
+ Generates structured research reports for AgentLaunch tokens.
333
+
334
+ Steps:
335
+ 1. Fetch token metadata from agent-launch.ai/api
336
+ 2. Build a research prompt with the on-chain data
337
+ 3. Call Hugging Face Inference API for AI-generated analysis
338
+ 4. Return the formatted report
339
+
340
+ Note: Trading fee is 2% -> 100% to protocol treasury (no creator fee).
341
+ """
342
+
343
+ def __init__(self, cache: Cache) -> None:
344
+ self._cache = cache
345
+
346
+ def fetch_token(self, address: str) -> Optional[Dict]:
347
+ cache_key = f"token:{address}"
348
+ cached = self._cache.get(cache_key)
349
+ if cached is not None:
350
+ return cached
351
+ try:
352
+ r = requests.get(
353
+ f"{AGENTLAUNCH_API}/agents/token/{address}", timeout=10
354
+ )
355
+ if r.status_code == 200:
356
+ data = r.json()
357
+ token = data.get("data") or data
358
+ if isinstance(token, dict):
359
+ self._cache.set(cache_key, token, ttl=300)
360
+ return token
361
+ except Exception:
362
+ pass
363
+ return None
364
+
365
+ def generate_report(self, token: Dict, topic: str) -> str:
366
+ """Call Hugging Face Inference API to generate an AI research report."""
367
+ hf_key = os.environ.get("HUGGINGFACE_API_KEY", "")
368
+ if not hf_key:
369
+ return "(AI report unavailable — set HUGGINGFACE_API_KEY to enable)"
370
+
371
+ name = token.get("name", "Unknown")
372
+ symbol = token.get("symbol", "???")
373
+ price = token.get("price") or token.get("currentPrice") or 0
374
+ market_cap = token.get("marketCap") or token.get("market_cap") or 0
375
+ description = token.get("description", "No description provided.")[:300]
376
+ listed = token.get("listed") or token.get("isListed") or False
377
+
378
+ prompt = (
379
+ f"Write a concise research report for the following AI agent token on the "
380
+ f"AgentLaunch platform.\\n\\n"
381
+ f"Token: {name} ({symbol})\\n"
382
+ f"Description: {description}\\n"
383
+ f"Current price: {float(price):.6f} FET\\n"
384
+ f"Market cap: {float(market_cap):,.0f} FET\\n"
385
+ f"DEX listed: {'Yes' if listed else 'No (graduation target: 30,000 FET)'}\\n"
386
+ f"Platform fee: 2% trading fee (100% to protocol treasury)\\n\\n"
387
+ f"Topic: {topic}\\n\\n"
388
+ f"Report:"
389
+ )
390
+
391
+ cache_key = f"report:{name}:{topic[:50]}"
392
+ cached = self._cache.get(cache_key)
393
+ if cached:
394
+ return cached
395
+
396
+ try:
397
+ r = requests.post(
398
+ HF_API_URL,
399
+ headers={"Authorization": f"Bearer {hf_key}"},
400
+ json={
401
+ "inputs": prompt,
402
+ "parameters": {
403
+ "max_new_tokens": BUSINESS["report_max_tokens"],
404
+ "temperature": 0.7,
405
+ },
406
+ },
407
+ timeout=30,
408
+ )
409
+ if r.status_code == 200:
410
+ result = r.json()
411
+ if isinstance(result, list) and result:
412
+ text = result[0].get("generated_text", "")
413
+ # Strip the prompt from the response
414
+ report = text[len(prompt):].strip() if text.startswith(prompt) else text.strip()
415
+ self._cache.set(cache_key, report, ttl=1800)
416
+ return report
417
+ except Exception:
418
+ pass
419
+ return "Could not generate AI report. Please try again later."
420
+
421
+ async def handle(self, ctx: Context, user_id: str, message: str, tier: str) -> str:
422
+ lower = message.lower()
423
+
424
+ # "report <address> [topic]"
425
+ if lower.startswith("report "):
426
+ parts = message.split(None, 2)
427
+ if len(parts) < 2:
428
+ return "Usage: report <token_address> [topic]"
429
+ address = parts[1].strip()
430
+ topic = parts[2].strip() if len(parts) >= 3 else "overview"
431
+
432
+ token = self.fetch_token(address)
433
+ if token is None:
434
+ return f"Could not find token at address {address}."
435
+
436
+ name = token.get("name", "Unknown")
437
+ symbol = token.get("symbol", "???")
438
+ price = token.get("price") or token.get("currentPrice") or 0
439
+ market_cap = token.get("marketCap") or token.get("market_cap") or 0
440
+ description = token.get("description", "N/A")[:200]
441
+ listed = token.get("listed") or token.get("isListed") or False
442
+
443
+ report = self.generate_report(token, topic)
444
+ return (
445
+ f"**Research Report: {name} ({symbol})**\\n"
446
+ f"Address: {address}\\n"
447
+ f"Price: {float(price):.6f} FET | MC: {float(market_cap):,.0f} FET\\n"
448
+ f"DEX listed: {'Yes' if listed else 'No'}\\n"
449
+ f"Description: {description}\\n\\n"
450
+ f"--- AI Analysis ({topic}) ---\\n"
451
+ f"{report}"
452
+ )
453
+
454
+ return (
455
+ f"Welcome to {BUSINESS['name']}!\\n\\n"
456
+ f"Commands:\\n"
457
+ f" report <token_address> — full research report\\n"
458
+ f" report <token_address> <topic> — focused analysis\\n\\n"
459
+ f"Example topics: overview, risks, tokenomics, competition\\n\\n"
460
+ f"Powered by {BUSINESS['ai_model']}"
461
+ )
462
+
463
+
464
+ # ==============================================================================
465
+ # REPLY HELPER
466
+ # ==============================================================================
467
+
468
+
469
+ async def reply(ctx: Context, sender: str, text: str, end: bool = False) -> None:
470
+ content = [TextContent(type="text", text=text)]
471
+ if end:
472
+ content.append(EndSessionContent(type="end-session"))
473
+ try:
474
+ await ctx.send(
475
+ sender,
476
+ ChatMessage(timestamp=datetime.utcnow(), msg_id=uuid4(), content=content),
477
+ )
478
+ except Exception as e:
479
+ ctx.logger.error(f"Failed to send reply to {sender[:20]}: {e}")
480
+
481
+
482
+ # ==============================================================================
483
+ # MAIN AGENT
484
+ # ==============================================================================
485
+
486
+ cache = Cache(max_size=1000)
487
+ security = Security()
488
+ health = Health()
489
+ revenue = Revenue(cache)
490
+ business = ResearchBusiness(cache)
491
+
492
+ agent = Agent()
493
+ chat_proto = Protocol(spec=chat_protocol_spec)
494
+
495
+
496
+ @chat_proto.on_message(ChatMessage)
497
+ async def handle_chat(ctx: Context, sender: str, msg: ChatMessage) -> None:
498
+ try:
499
+ await ctx.send(
500
+ sender,
501
+ ChatAcknowledgement(
502
+ timestamp=datetime.utcnow(), acknowledged_msg_id=msg.msg_id
503
+ ),
504
+ )
505
+ except Exception as e:
506
+ ctx.logger.error(f"Failed to send ack to {sender[:20]}: {e}")
507
+
508
+ text = " ".join(
509
+ item.text for item in msg.content if isinstance(item, TextContent)
510
+ ).strip()
511
+ text = text[: BUSINESS["max_input_length"]]
512
+
513
+ clean, error = security.check(ctx, sender, text)
514
+ if error:
515
+ health.record(False)
516
+ await reply(ctx, sender, error, end=True)
517
+ return
518
+
519
+ Logger.audit(ctx, sender, "request")
520
+
521
+ lower = clean.lower()
522
+
523
+ if lower in ("help", "?"):
524
+ tier = revenue.get_tier(sender)
525
+ await reply(
526
+ ctx,
527
+ sender,
528
+ f"**{BUSINESS['name']}** v{BUSINESS['version']}\\n\\n"
529
+ f"{BUSINESS['description']}\\n\\n"
530
+ f"Your tier: {tier.upper()}\\n\\n"
531
+ f"Commands: help, status, tokenize, report <addr> [topic]",
532
+ )
533
+ return
534
+
535
+ if lower == "status":
536
+ s = health.status()
537
+ await reply(
538
+ ctx,
539
+ sender,
540
+ f"Status: {s['status']} | Uptime: {s['uptime_seconds']}s | "
541
+ f"Requests: {s['requests']} | Error rate: {s['error_rate']}",
542
+ )
543
+ return
544
+
545
+ if "tokenize" in lower:
546
+ if OWNER_ADDRESS and sender != OWNER_ADDRESS:
547
+ await reply(ctx, sender, "Only the agent owner can trigger tokenization.", end=True)
548
+ return
549
+ result = AgentLaunch.tokenize()
550
+ link = result.get("data", {}).get("handoff_link") or result.get("handoff_link")
551
+ await reply(
552
+ ctx,
553
+ sender,
554
+ f"Token created! Deploy here: {link}" if link else f"Result: {json.dumps(result)}",
555
+ end=True,
556
+ )
557
+ return
558
+
559
+ tier = revenue.get_tier(sender)
560
+ allowed, quota_error = revenue.check_quota(sender, tier)
561
+ if not allowed:
562
+ health.record(False)
563
+ await reply(ctx, sender, quota_error, end=True)
564
+ return
565
+
566
+ try:
567
+ response = await business.handle(ctx, sender, clean, tier)
568
+ health.record(True)
569
+ except Exception as e:
570
+ health.record(False)
571
+ Logger.error(ctx, "business_handle", str(e))
572
+ response = "Something went wrong. Please try again."
573
+
574
+ await reply(ctx, sender, response, end=True)
575
+
576
+
577
+ @chat_proto.on_message(ChatAcknowledgement)
578
+ async def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement) -> None:
579
+ ctx.logger.debug(f"Ack from {sender[:20]} for msg {msg.acknowledged_msg_id}")
580
+
581
+
582
+ @agent.on_interval(period=3600)
583
+ async def periodic_health(ctx: Context) -> None:
584
+ ctx.logger.info(f"[HEALTH] {json.dumps(health.status())}")
585
+
586
+
587
+ agent.include(chat_proto, publish_manifest=True)
588
+
589
+ if __name__ == "__main__":
590
+ agent.run()
591
+ `,
592
+ };
593
+ //# sourceMappingURL=research.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/templates/research.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,IAAI,EAAE,UAAU;IAChB,WAAW,EACT,yEAAyE;IAC3E,QAAQ,EAAE,OAAO;IACjB,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE;QACxE;YACE,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,yEAAyE;YAClF,WAAW,EAAE,2CAA2C;SACzD;QACD;YACE,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,oCAAoC;YAC7C,WAAW,EAAE,6CAA6C;SAC3D;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,oCAAoC;SAClD;QACD;YACE,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,0DAA0D;SACxE;QACD;YACE,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,GAAG;YACZ,WAAW,EAAE,+BAA+B;SAC7C;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,yCAAyC;SACvD;KACF;IACD,YAAY,EAAE,CAAC,UAAU,CAAC;IAC1B,OAAO,EAAE;QACP,oBAAoB;QACpB,qBAAqB;QACrB,eAAe;QACf,qBAAqB;QACrB,qBAAqB;KACtB;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyhBP;CACA,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * trading-bot.ts — Generates buy/sell signals based on price momentum
3
+ *
4
+ * Platform constants (source of truth: deployed smart contracts):
5
+ * - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
6
+ * - Graduation target: 30,000 FET -> auto DEX listing
7
+ * - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
8
+ */
9
+ import type { AgentTemplate } from "../registry.js";
10
+ export declare const template: AgentTemplate;
11
+ //# sourceMappingURL=trading-bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trading-bot.d.ts","sourceRoot":"","sources":["../../src/templates/trading-bot.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,eAAO,MAAM,QAAQ,EAAE,aAsiBtB,CAAC"}