agentlaunch-templates 0.4.2 → 0.4.4

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 (51) hide show
  1. package/dist/__tests__/build.test.d.ts +1 -1
  2. package/dist/__tests__/build.test.js +5 -5
  3. package/dist/__tests__/build.test.js.map +1 -1
  4. package/dist/__tests__/consumer-commerce.test.d.ts +11 -0
  5. package/dist/__tests__/consumer-commerce.test.d.ts.map +1 -0
  6. package/dist/__tests__/consumer-commerce.test.js +118 -0
  7. package/dist/__tests__/consumer-commerce.test.js.map +1 -0
  8. package/dist/__tests__/swarm-starter-integration.test.d.ts +12 -0
  9. package/dist/__tests__/swarm-starter-integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/swarm-starter-integration.test.js +143 -0
  11. package/dist/__tests__/swarm-starter-integration.test.js.map +1 -0
  12. package/dist/__tests__/swarm-starter.test.d.ts +16 -0
  13. package/dist/__tests__/swarm-starter.test.d.ts.map +1 -0
  14. package/dist/__tests__/swarm-starter.test.js +310 -0
  15. package/dist/__tests__/swarm-starter.test.js.map +1 -0
  16. package/dist/claude-context.d.ts +1 -1
  17. package/dist/claude-context.d.ts.map +1 -1
  18. package/dist/claude-context.js +55 -49
  19. package/dist/claude-context.js.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/people.d.ts +108 -0
  25. package/dist/people.d.ts.map +1 -0
  26. package/dist/people.js +563 -0
  27. package/dist/people.js.map +1 -0
  28. package/dist/presets.d.ts +13 -13
  29. package/dist/presets.d.ts.map +1 -1
  30. package/dist/presets.js +331 -96
  31. package/dist/presets.js.map +1 -1
  32. package/dist/registry.d.ts +3 -8
  33. package/dist/registry.d.ts.map +1 -1
  34. package/dist/registry.js +8 -28
  35. package/dist/registry.js.map +1 -1
  36. package/dist/templates/chat-memory.d.ts +5 -14
  37. package/dist/templates/chat-memory.d.ts.map +1 -1
  38. package/dist/templates/chat-memory.js +142 -220
  39. package/dist/templates/chat-memory.js.map +1 -1
  40. package/dist/templates/consumer-commerce.d.ts +14 -0
  41. package/dist/templates/consumer-commerce.d.ts.map +1 -0
  42. package/dist/templates/consumer-commerce.js +439 -0
  43. package/dist/templates/consumer-commerce.js.map +1 -0
  44. package/dist/templates/genesis.d.ts.map +1 -1
  45. package/dist/templates/genesis.js +10 -0
  46. package/dist/templates/genesis.js.map +1 -1
  47. package/dist/templates/swarm-starter.d.ts +26 -0
  48. package/dist/templates/swarm-starter.d.ts.map +1 -0
  49. package/dist/templates/swarm-starter.js +1421 -0
  50. package/dist/templates/swarm-starter.js.map +1 -0
  51. package/package.json +3 -2
@@ -0,0 +1,439 @@
1
+ /**
2
+ * consumer-commerce.ts — Consumer-facing agent template with multi-token payments
3
+ *
4
+ * Extends the swarm-starter commerce stack with:
5
+ * - MultiTokenPricingTable (FET + USDC pricing)
6
+ * - InvoiceManager (create/verify/list invoices in ctx.storage)
7
+ * - FiatOnrampHelper (detect "no crypto" → generate card purchase link)
8
+ * - DelegationChecker (verify allowance → auto-pay or fall back to RequestPayment)
9
+ *
10
+ * No custom smart contracts — uses standard ERC-20 approve/transferFrom.
11
+ */
12
+ const PROD_API_URL = 'https://agent-launch.ai/api';
13
+ const DEV_API_URL = 'https://launchpad-backend-dev-1056182620041.us-central1.run.app';
14
+ const RESOLVED_API_URL = process.env.AGENT_LAUNCH_API_URL ??
15
+ (process.env.AGENT_LAUNCH_ENV === 'dev' ? DEV_API_URL : PROD_API_URL);
16
+ export const template = {
17
+ name: "consumer-commerce",
18
+ description: "Consumer-facing agent with multi-token payments, invoices, fiat onramp, and spending delegation",
19
+ category: "Commerce",
20
+ variables: [
21
+ { name: "agent_name", required: true, description: "Name of the agent" },
22
+ { name: "description", required: true, description: "Short description of what this agent does" },
23
+ { name: "service_price_fet", default: "0.01", description: "Service price in FET" },
24
+ { name: "service_price_usdc", default: "0.05", description: "Service price in USDC" },
25
+ { name: "accepted_tokens", default: "FET,USDC", description: "Comma-separated accepted token symbols" },
26
+ { name: "enable_fiat_onramp", default: "true", description: "Enable fiat onramp link generation" },
27
+ { name: "enable_invoices", default: "true", description: "Enable invoice management" },
28
+ { name: "enable_delegation", default: "true", description: "Enable spending delegation (auto-pay)" },
29
+ ],
30
+ dependencies: ["requests", "web3"],
31
+ secrets: [
32
+ "AGENTVERSE_API_KEY",
33
+ "AGENTLAUNCH_API_KEY",
34
+ "WALLET_PRIVATE_KEY",
35
+ "MOONPAY_API_KEY",
36
+ ],
37
+ code: `#!/usr/bin/env python3
38
+ """
39
+ {{agent_name}} — AgentLaunch Consumer Commerce Agent
40
+ Generated by: agentlaunch scaffold {{agent_name}} --type consumer-commerce
41
+
42
+ Multi-token payments (FET + USDC), invoices, fiat onramp, spending delegation.
43
+ Uses standard ERC-20 patterns — no custom smart contracts.
44
+
45
+ Platform constants (source of truth: deployed smart contracts):
46
+ - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
47
+ - Graduation target: 30,000 FET -> auto DEX listing
48
+ - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
49
+ """
50
+
51
+ from uagents import Agent, Context, Protocol
52
+ from uagents_core.contrib.protocols.chat import (
53
+ ChatAcknowledgement,
54
+ ChatMessage,
55
+ EndSessionContent,
56
+ TextContent,
57
+ chat_protocol_spec,
58
+ )
59
+
60
+ import json
61
+ import os
62
+ from datetime import datetime
63
+ from uuid import uuid4
64
+
65
+ # ==============================================================================
66
+ # CONFIG
67
+ # ==============================================================================
68
+
69
+ AGENTLAUNCH_API = os.environ.get("AGENTLAUNCH_API", "${RESOLVED_API_URL}")
70
+
71
+ BUSINESS = {
72
+ "name": "{{agent_name}}",
73
+ "description": "{{description}}",
74
+ "version": "1.0.0",
75
+ }
76
+
77
+ ACCEPTED_TOKENS = [t.strip() for t in "{{accepted_tokens}}".split(",")]
78
+
79
+ # ==============================================================================
80
+ # MULTI-TOKEN PRICING TABLE
81
+ # ==============================================================================
82
+
83
+ class MultiTokenPricingTable:
84
+ """Service pricing in multiple tokens (FET + USDC)."""
85
+
86
+ def __init__(self, ctx: Context):
87
+ self.ctx = ctx
88
+
89
+ async def get_prices(self) -> dict:
90
+ """Get current pricing table from storage."""
91
+ raw = self.ctx.storage.get("pricing_table")
92
+ if raw:
93
+ return json.loads(raw)
94
+ # Default pricing
95
+ return {
96
+ "default": {
97
+ "FET": "{{service_price_fet}}",
98
+ "USDC": "{{service_price_usdc}}",
99
+ }
100
+ }
101
+
102
+ async def set_price(self, service: str, token: str, price: str):
103
+ """Set price for a service in a specific token."""
104
+ prices = await self.get_prices()
105
+ if service not in prices:
106
+ prices[service] = {}
107
+ prices[service][token] = price
108
+ self.ctx.storage.set("pricing_table", json.dumps(prices))
109
+
110
+ async def format_prices(self, service: str = "default") -> str:
111
+ """Format prices for display."""
112
+ prices = await self.get_prices()
113
+ svc_prices = prices.get(service, prices.get("default", {}))
114
+ lines = []
115
+ for token, price in svc_prices.items():
116
+ if token in ACCEPTED_TOKENS:
117
+ lines.append(f" {price} {token}")
118
+ return "\\n".join(lines) if lines else " Free"
119
+
120
+ # ==============================================================================
121
+ # INVOICE MANAGER
122
+ # ==============================================================================
123
+
124
+ class InvoiceManager:
125
+ """Create, verify, and list invoices in ctx.storage."""
126
+
127
+ def __init__(self, ctx: Context):
128
+ self.ctx = ctx
129
+
130
+ async def create(self, payer: str, service: str, amount: str, token: str = "FET") -> dict:
131
+ """Create a new invoice."""
132
+ invoice_id = f"inv_{uuid4().hex[:8]}"
133
+ invoice = {
134
+ "id": invoice_id,
135
+ "issuer": str(self.ctx.address),
136
+ "payer": payer,
137
+ "service": service,
138
+ "amount": amount,
139
+ "token": token,
140
+ "status": "pending",
141
+ "created_at": datetime.now().isoformat(),
142
+ "updated_at": datetime.now().isoformat(),
143
+ }
144
+ self.ctx.storage.set(f"invoice_{invoice_id}", json.dumps(invoice))
145
+
146
+ # Update index
147
+ index_raw = self.ctx.storage.get("invoice_index")
148
+ index = json.loads(index_raw) if index_raw else []
149
+ index.append(invoice_id)
150
+ self.ctx.storage.set("invoice_index", json.dumps(index))
151
+
152
+ return invoice
153
+
154
+ async def get(self, invoice_id: str) -> dict | None:
155
+ """Get an invoice by ID."""
156
+ raw = self.ctx.storage.get(f"invoice_{invoice_id}")
157
+ return json.loads(raw) if raw else None
158
+
159
+ async def list_invoices(self, status: str = None) -> list:
160
+ """List all invoices, optionally filtered by status."""
161
+ index_raw = self.ctx.storage.get("invoice_index")
162
+ if not index_raw:
163
+ return []
164
+ index = json.loads(index_raw)
165
+ invoices = []
166
+ for inv_id in index:
167
+ inv = await self.get(inv_id)
168
+ if inv and (status is None or inv.get("status") == status):
169
+ invoices.append(inv)
170
+ return invoices
171
+
172
+ async def mark_paid(self, invoice_id: str, tx_hash: str) -> dict | None:
173
+ """Mark an invoice as paid."""
174
+ inv = await self.get(invoice_id)
175
+ if not inv:
176
+ return None
177
+ inv["status"] = "paid"
178
+ inv["tx_hash"] = tx_hash
179
+ inv["updated_at"] = datetime.now().isoformat()
180
+ self.ctx.storage.set(f"invoice_{invoice_id}", json.dumps(inv))
181
+ return inv
182
+
183
+ # ==============================================================================
184
+ # FIAT ONRAMP HELPER
185
+ # ==============================================================================
186
+
187
+ class FiatOnrampHelper:
188
+ """Generate fiat-to-crypto purchase links for users without crypto."""
189
+
190
+ PROVIDERS = {
191
+ "moonpay": "https://buy.moonpay.com",
192
+ "transak": "https://global.transak.com",
193
+ }
194
+
195
+ CRYPTO_CODES = {
196
+ "FET": {"moonpay": "fet_bsc", "transak": "FET"},
197
+ "USDC": {"moonpay": "usdc_bsc", "transak": "USDC"},
198
+ }
199
+
200
+ def __init__(self, ctx: Context):
201
+ self.ctx = ctx
202
+ self.enabled = "{{enable_fiat_onramp}}" == "true"
203
+
204
+ def generate_link(
205
+ self,
206
+ wallet_address: str,
207
+ fiat_amount: str = "50",
208
+ fiat_currency: str = "USD",
209
+ crypto_token: str = "FET",
210
+ provider: str = "moonpay",
211
+ ) -> str | None:
212
+ """Generate a fiat onramp URL."""
213
+ if not self.enabled:
214
+ return None
215
+
216
+ codes = self.CRYPTO_CODES.get(crypto_token.upper())
217
+ if not codes:
218
+ return None
219
+
220
+ base_url = self.PROVIDERS.get(provider)
221
+ if not base_url:
222
+ return None
223
+
224
+ api_key = os.environ.get("MOONPAY_API_KEY", "")
225
+
226
+ if provider == "moonpay":
227
+ return (
228
+ f"{base_url}?"
229
+ f"apiKey={api_key}&"
230
+ f"currencyCode={codes['moonpay']}&"
231
+ f"baseCurrencyCode={fiat_currency.lower()}&"
232
+ f"baseCurrencyAmount={fiat_amount}&"
233
+ f"walletAddress={wallet_address}"
234
+ )
235
+ else:
236
+ return (
237
+ f"{base_url}?"
238
+ f"apiKey={api_key}&"
239
+ f"cryptoCurrencyCode={codes['transak']}&"
240
+ f"fiatCurrency={fiat_currency.upper()}&"
241
+ f"fiatAmount={fiat_amount}&"
242
+ f"walletAddress={wallet_address}&"
243
+ f"network=bsc"
244
+ )
245
+
246
+ # ==============================================================================
247
+ # DELEGATION CHECKER
248
+ # ==============================================================================
249
+
250
+ class DelegationChecker:
251
+ """Check ERC-20 allowances for auto-pay from delegated spending limits."""
252
+
253
+ def __init__(self, ctx: Context):
254
+ self.ctx = ctx
255
+ self.enabled = "{{enable_delegation}}" == "true"
256
+
257
+ async def check_delegation(self, owner: str, token_address: str) -> str:
258
+ """Check allowance on-chain. Returns remaining allowance as string."""
259
+ if not self.enabled:
260
+ return "0"
261
+
262
+ # Store delegation status in ctx.storage for tracking
263
+ key = f"delegation_{owner}_{token_address[:8]}"
264
+ raw = self.ctx.storage.get(key)
265
+ if raw:
266
+ return json.loads(raw).get("remaining", "0")
267
+ return "0"
268
+
269
+ async def record_delegation(self, owner: str, token_address: str, amount: str):
270
+ """Record a delegation grant in storage."""
271
+ key = f"delegation_{owner}_{token_address[:8]}"
272
+ self.ctx.storage.set(key, json.dumps({
273
+ "owner": owner,
274
+ "token_address": token_address,
275
+ "remaining": amount,
276
+ "updated_at": datetime.now().isoformat(),
277
+ }))
278
+
279
+ # ==============================================================================
280
+ # REVENUE TRACKER
281
+ # ==============================================================================
282
+
283
+ class RevenueTracker:
284
+ """Track income and expenses by token."""
285
+
286
+ def __init__(self, ctx: Context):
287
+ self.ctx = ctx
288
+
289
+ async def record_income(self, amount: str, token: str, service: str, payer: str):
290
+ """Record an income event."""
291
+ raw = self.ctx.storage.get("revenue_summary") or "{}"
292
+ summary = json.loads(raw)
293
+
294
+ by_token = summary.get("by_token", {})
295
+ if token not in by_token:
296
+ by_token[token] = {"income": 0.0, "expenses": 0.0}
297
+ by_token[token]["income"] += float(amount)
298
+ summary["by_token"] = by_token
299
+ summary["total_income"] = summary.get("total_income", 0.0) + float(amount)
300
+ summary["transaction_count"] = summary.get("transaction_count", 0) + 1
301
+ summary["last_updated"] = datetime.now().isoformat()
302
+
303
+ self.ctx.storage.set("revenue_summary", json.dumps(summary))
304
+
305
+ async def get_summary(self) -> dict:
306
+ """Get revenue summary."""
307
+ raw = self.ctx.storage.get("revenue_summary") or "{}"
308
+ return json.loads(raw)
309
+
310
+ # ==============================================================================
311
+ # AGENT SETUP
312
+ # ==============================================================================
313
+
314
+ agent = Agent()
315
+ chat_proto = Protocol(spec=chat_protocol_spec)
316
+
317
+ # ==============================================================================
318
+ # CHAT HANDLER — COMMERCE FLOW
319
+ # ==============================================================================
320
+
321
+ @chat_proto.on_message(ChatMessage)
322
+ async def handle_message(ctx: Context, sender: str, msg: ChatMessage):
323
+ ctx.logger.info(f"Message from {sender}")
324
+ text = msg.content[0].text.strip() if msg.content else ""
325
+ lower = text.lower()
326
+
327
+ pricing = MultiTokenPricingTable(ctx)
328
+ invoices = InvoiceManager(ctx)
329
+ fiat = FiatOnrampHelper(ctx)
330
+ revenue = RevenueTracker(ctx)
331
+
332
+ # --- Commands ---
333
+
334
+ if lower in ("help", "/help"):
335
+ prices = await pricing.format_prices()
336
+ response = (
337
+ f"**{BUSINESS['name']}** — {BUSINESS['description']}\\n\\n"
338
+ f"**Pricing:**\\n{prices}\\n\\n"
339
+ f"**Commands:**\\n"
340
+ f" \`help\` — Show this message\\n"
341
+ f" \`prices\` — View pricing in all tokens\\n"
342
+ f" \`invoice <service>\` — Create an invoice\\n"
343
+ f" \`buy-crypto\` — Get a link to buy crypto with a card\\n"
344
+ f" \`revenue\` — View earnings\\n"
345
+ f" \`status\` — Service status\\n\\n"
346
+ f"**Accepted tokens:** {', '.join(ACCEPTED_TOKENS)}"
347
+ )
348
+
349
+ elif lower == "prices":
350
+ prices = await pricing.format_prices()
351
+ response = f"**Current Pricing:**\\n{prices}\\n\\n**Accepted:** {', '.join(ACCEPTED_TOKENS)}"
352
+
353
+ elif lower.startswith("invoice"):
354
+ parts = text.split(maxsplit=1)
355
+ service = parts[1] if len(parts) > 1 else "default"
356
+ inv = await invoices.create(sender, service, "{{service_price_fet}}", "FET")
357
+ response = (
358
+ f"**Invoice Created**\\n"
359
+ f" ID: {inv['id']}\\n"
360
+ f" Service: {inv['service']}\\n"
361
+ f" Amount: {inv['amount']} {inv['token']}\\n"
362
+ f" Status: {inv['status']}"
363
+ )
364
+
365
+ elif lower in ("buy-crypto", "buy crypto", "no crypto", "get crypto"):
366
+ link = fiat.generate_link(sender, "50", "USD", "FET")
367
+ if link:
368
+ response = (
369
+ f"**Buy crypto with your card:**\\n"
370
+ f"[Purchase FET]({link})\\n\\n"
371
+ f"You\\'ll receive FET in your wallet within minutes."
372
+ )
373
+ else:
374
+ response = "Fiat onramp is not enabled for this agent."
375
+
376
+ elif lower == "revenue":
377
+ summary = await revenue.get_summary()
378
+ total = summary.get("total_income", 0)
379
+ txns = summary.get("transaction_count", 0)
380
+ by_token = summary.get("by_token", {})
381
+ token_lines = "\\n".join(
382
+ f" {t}: {d.get('income', 0):.4f} income, {d.get('expenses', 0):.4f} expenses"
383
+ for t, d in by_token.items()
384
+ ) if by_token else " No revenue yet"
385
+ response = (
386
+ f"**Revenue Summary**\\n"
387
+ f" Total income: {total:.4f}\\n"
388
+ f" Transactions: {txns}\\n\\n"
389
+ f"**By Token:**\\n{token_lines}"
390
+ )
391
+
392
+ elif lower == "status":
393
+ inv_list = await invoices.list_invoices("pending")
394
+ response = (
395
+ f"**{BUSINESS['name']}** v{BUSINESS['version']}\\n"
396
+ f" Accepted tokens: {', '.join(ACCEPTED_TOKENS)}\\n"
397
+ f" Pending invoices: {len(inv_list)}\\n"
398
+ f" Delegation: {'enabled' if '{{enable_delegation}}' == 'true' else 'disabled'}\\n"
399
+ f" Fiat onramp: {'enabled' if '{{enable_fiat_onramp}}' == 'true' else 'disabled'}"
400
+ )
401
+
402
+ else:
403
+ # === YOUR COMMERCE LOGIC ===
404
+ # This is where you add your custom service logic.
405
+ # After fulfilling a service, record revenue:
406
+ # await revenue.record_income("0.01", "FET", "my_service", sender)
407
+ prices = await pricing.format_prices()
408
+ response = (
409
+ f"Welcome to **{BUSINESS['name']}**!\\n\\n"
410
+ f"{BUSINESS['description']}\\n\\n"
411
+ f"**Pricing:**\\n{prices}\\n\\n"
412
+ f"Type \`help\` for commands, or \`invoice <service>\` to get started."
413
+ )
414
+
415
+ await ctx.send(sender, ChatMessage(
416
+ timestamp=datetime.now(),
417
+ msg_id=str(uuid4()),
418
+ content=[TextContent(text=response)],
419
+ ))
420
+
421
+ await ctx.send(sender, ChatMessage(
422
+ timestamp=datetime.now(),
423
+ msg_id=str(uuid4()),
424
+ content=[EndSessionContent()],
425
+ ))
426
+
427
+
428
+ @chat_proto.on_message(ChatAcknowledgement)
429
+ async def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement):
430
+ ctx.logger.info(f"Ack from {sender}: {msg.acknowledged_msg_id}")
431
+
432
+
433
+ agent.include(chat_proto, publish_manifest=True)
434
+
435
+ if __name__ == "__main__":
436
+ agent.run()
437
+ `,
438
+ };
439
+ //# sourceMappingURL=consumer-commerce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer-commerce.js","sourceRoot":"","sources":["../../src/templates/consumer-commerce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,WAAW,GAAG,iEAAiE,CAAC;AACtF,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB;IACvD,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EAAE,iGAAiG;IAC9G,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE;QACxE,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2CAA2C,EAAE;QACjG,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE;QACnF,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,uBAAuB,EAAE;QACrF,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,wCAAwC,EAAE;QACvG,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,oCAAoC,EAAE;QAClG,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,2BAA2B,EAAE;QACtF,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,uCAAuC,EAAE;KACrG;IACD,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;IAClC,OAAO,EAAE;QACP,oBAAoB;QACpB,qBAAqB;QACrB,oBAAoB;QACpB,iBAAiB;KAClB;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDAgC+C,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgXtE;CACA,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"genesis.d.ts","sourceRoot":"","sources":["../../src/templates/genesis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,eAAO,MAAM,QAAQ,EAAE,aAiwCtB,CAAC"}
1
+ {"version":3,"file":"genesis.d.ts","sourceRoot":"","sources":["../../src/templates/genesis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,eAAO,MAAM,QAAQ,EAAE,aA2wCtB,CAAC"}
@@ -939,8 +939,16 @@ class HoldingsManager:
939
939
  results.append({"address": addr, "name": "Error", "price": 0, "holders": 0})
940
940
  return results
941
941
 
942
+ @staticmethod
943
+ def _validate_eth_address(address: str) -> bool:
944
+ """Validate Ethereum address format to prevent URL injection."""
945
+ import re
946
+ return bool(re.match(r'^0x[a-fA-F0-9]{40}$', address))
947
+
942
948
  @staticmethod
943
949
  def generate_buy_link(token_address: str, amount: int = 0) -> str:
950
+ if not HoldingsManager._validate_eth_address(token_address):
951
+ return f"Error: Invalid token address format: {token_address}"
944
952
  base = os.environ.get("AGENTLAUNCH_FRONTEND", "https://agent-launch.ai")
945
953
  url = f"{base}/trade/{token_address}?action=buy"
946
954
  if amount:
@@ -949,6 +957,8 @@ class HoldingsManager:
949
957
 
950
958
  @staticmethod
951
959
  def generate_sell_link(token_address: str, amount: int = 0) -> str:
960
+ if not HoldingsManager._validate_eth_address(token_address):
961
+ return f"Error: Invalid token address format: {token_address}"
952
962
  base = os.environ.get("AGENTLAUNCH_FRONTEND", "https://agent-launch.ai")
953
963
  url = f"{base}/trade/{token_address}?action=sell"
954
964
  if amount:
@@ -1 +1 @@
1
- {"version":3,"file":"genesis.js","sourceRoot":"","sources":["../../src/templates/genesis.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"genesis.js","sourceRoot":"","sources":["../../src/templates/genesis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * swarm-starter template: full commerce stack for agent swarms
3
+ *
4
+ * This is the flagship template for the AgentLaunch platform. It generates a
5
+ * production-ready agent with an inline commerce engine: payments, pricing,
6
+ * tiers, revenue tracking, self-awareness (own token metrics), and cross-holdings.
7
+ *
8
+ * Layers (bottom to top):
9
+ * 1. Logger — structured logging with audit trail
10
+ * 2. Security — rate limiting, input validation
11
+ * 3. Health — uptime, error rate tracking
12
+ * 4. Cache — in-memory TTL cache
13
+ * 5. Revenue/Tier — PricingTable, TierManager
14
+ * 6. Commerce — PaymentService, WalletManager, RevenueTracker
15
+ * 7. SelfAware — token price/holder awareness
16
+ * 8. Holdings — HoldingsManager for cross-token operations
17
+ * 9. SwarmBusiness — YOUR LOGIC HERE
18
+ *
19
+ * Platform constants (source of truth: deployed smart contracts):
20
+ * - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
21
+ * - Graduation target: 30,000 FET -> auto DEX listing
22
+ * - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
23
+ */
24
+ import type { AgentTemplate } from "../registry.js";
25
+ export declare const template: AgentTemplate;
26
+ //# sourceMappingURL=swarm-starter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm-starter.d.ts","sourceRoot":"","sources":["../../src/templates/swarm-starter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,eAAO,MAAM,QAAQ,EAAE,aAi3CtB,CAAC"}