@beeperbot/sdk 0.2.2 → 0.2.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.
package/README.md CHANGED
@@ -208,6 +208,11 @@ Use filters with `estimate`, `preview`, and `createBulkIntent`.
208
208
  | `minFollowers` | `number` | Minimum follower count |
209
209
  | `maxFollowers` | `number` | Maximum follower count |
210
210
 
211
+ ### Cast Engagement
212
+ | Filter | Type | Description |
213
+ |--------|------|-------------|
214
+ | `castEngagement` | `{ castUrl?: string; castHash?: string; require?: ('like' \| 'recast')[] }` | Users who liked and/or recasted a specific cast. If `require` is omitted, any engagement counts. |
215
+
211
216
  ### Token Filters
212
217
  | Filter | Type | Description |
213
218
  |--------|------|-------------|
@@ -0,0 +1,553 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ // src/core/agent/engine.ts
6
+
7
+ // src/core/agent/errors.ts
8
+ var AgentCoreError = class _AgentCoreError extends Error {
9
+ code;
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.name = "AgentCoreError";
13
+ this.code = code;
14
+ }
15
+ static validation(message) {
16
+ return new _AgentCoreError("VALIDATION_ERROR", message);
17
+ }
18
+ static notFound(message) {
19
+ return new _AgentCoreError("NOT_FOUND", message);
20
+ }
21
+ static unsupportedChain(chainId) {
22
+ return new _AgentCoreError("UNSUPPORTED_CHAIN", `Unsupported chain: ${chainId}`);
23
+ }
24
+ static noRecipients(message) {
25
+ return new _AgentCoreError("NO_RECIPIENTS", message);
26
+ }
27
+ };
28
+
29
+ // src/core/agent/filters.ts
30
+ var CHAIN_ID_MAP = {
31
+ base: 8453,
32
+ ethereum: 1,
33
+ mainnet: 1,
34
+ arbitrum: 42161,
35
+ polygon: 137,
36
+ optimism: 10
37
+ };
38
+ function hasSubstantiveFilters(filters) {
39
+ return !!(filters.platform || filters.minFollowers || filters.maxFollowers || filters.fids?.length || filters.userIds?.length || filters.castEngagement?.castHash || filters.castEngagement?.castUrl || filters.activeInLastDays || filters.countries?.length || filters.neynarScoreMin || filters.tokenHolders?.length || filters.maxAttentionPriceUsd || filters.hasBaseWallet || filters.spamLabel);
40
+ }
41
+ function normalizeAgentFilters(filters) {
42
+ const normalized = { ...filters };
43
+ const defaultsApplied = [];
44
+ const stripEmptyArray = (key) => {
45
+ const value = normalized[key];
46
+ if (Array.isArray(value) && value.length === 0) {
47
+ delete normalized[key];
48
+ }
49
+ };
50
+ const stripZero = (key) => {
51
+ const value = normalized[key];
52
+ if (typeof value === "number" && value === 0) {
53
+ delete normalized[key];
54
+ }
55
+ };
56
+ if (normalized.platform === "all") delete normalized.platform;
57
+ if (normalized.spamLabel === "all") delete normalized.spamLabel;
58
+ stripZero("minFollowers");
59
+ stripZero("maxFollowers");
60
+ stripZero("activeInLastDays");
61
+ stripZero("minBatteryPercentage");
62
+ stripZero("hasRechargedInLastDays");
63
+ stripZero("maxAttentionPriceUsd");
64
+ stripEmptyArray("signalTokens");
65
+ if (Array.isArray(normalized.tokenHolders)) {
66
+ normalized.tokenHolders = normalized.tokenHolders.map((holder) => {
67
+ if (!holder) return null;
68
+ if ("tokenAddress" in holder && "chainId" in holder) return holder;
69
+ const loose = holder;
70
+ if (!loose.contractAddress || loose.chain == null) return null;
71
+ const chainId = typeof loose.chain === "number" ? loose.chain : CHAIN_ID_MAP[String(loose.chain).toLowerCase()] ?? Number(loose.chain);
72
+ if (!Number.isFinite(chainId)) return null;
73
+ return {
74
+ tokenAddress: loose.contractAddress,
75
+ chainId,
76
+ ...loose.minBalance ? { minBalance: loose.minBalance } : {}
77
+ };
78
+ }).filter((holder) => !!holder);
79
+ }
80
+ stripEmptyArray("tokenHolders");
81
+ if (Array.isArray(normalized.countries)) {
82
+ normalized.countries = normalized.countries.map((country) => {
83
+ if (typeof country === "string") return country;
84
+ return country?.code;
85
+ }).filter((country) => typeof country === "string" && country.length > 0).map((country) => country.toUpperCase());
86
+ }
87
+ stripEmptyArray("countries");
88
+ stripEmptyArray("fids");
89
+ stripEmptyArray("userIds");
90
+ if (normalized.castEngagement) {
91
+ const { castHash, castUrl, require: require2 } = normalized.castEngagement;
92
+ if (!castHash && !castUrl) {
93
+ delete normalized.castEngagement;
94
+ } else if (Array.isArray(require2) && require2.length === 0) {
95
+ normalized.castEngagement = {
96
+ ...castHash != null && { castHash },
97
+ ...castUrl != null && { castUrl }
98
+ };
99
+ }
100
+ }
101
+ if (normalized.neynarScoreMin === 0) delete normalized.neynarScoreMin;
102
+ if (normalized.neynarScoreMax === 1) delete normalized.neynarScoreMax;
103
+ if (normalized.quotientScoreMin === 0) delete normalized.quotientScoreMin;
104
+ if (normalized.quotientScoreMax === 1) delete normalized.quotientScoreMax;
105
+ if (!hasSubstantiveFilters(normalized)) {
106
+ normalized.activeInLastDays = 30;
107
+ normalized.spamLabel = "not_spam_only";
108
+ defaultsApplied.push("activeInLastDays=30", "spamLabel=not_spam_only");
109
+ }
110
+ return { filters: normalized, defaultsApplied };
111
+ }
112
+ function getOrderByOrDefault(filters) {
113
+ return filters.orderBy ?? "attention_price_asc";
114
+ }
115
+ function buildAgentQueryPlan(filters) {
116
+ const normalized = normalizeAgentFilters(filters);
117
+ return {
118
+ inputFilters: { ...filters },
119
+ filters: normalized.filters,
120
+ orderBy: getOrderByOrDefault(normalized.filters),
121
+ defaultsApplied: normalized.defaultsApplied
122
+ };
123
+ }
124
+
125
+ // src/core/agent/costing.ts
126
+ var DEFAULT_MICRO_USD_PER_USD = 1e6;
127
+ var DEFAULT_PLATFORM_FEE_RATE = 0.1;
128
+ var GOAL_BASELINES = {
129
+ max_reach: { payout: 100, bonus: 0 },
130
+ lil_mission: { payout: 80, bonus: 20 },
131
+ hard_mission: { payout: 50, bonus: 50 }
132
+ };
133
+ var SPLIT_ADJUSTMENTS = {
134
+ balanced: 0,
135
+ more_reach: 10,
136
+ more_action: -10
137
+ };
138
+ function computeBudgetSplit(totalUsd, goalType = "max_reach", splitPreset = "balanced", platformFeeRate = DEFAULT_PLATFORM_FEE_RATE) {
139
+ const baseline = GOAL_BASELINES[goalType];
140
+ const adjustment = SPLIT_ADJUSTMENTS[splitPreset];
141
+ let payoutPercent = Math.max(0, Math.min(100, baseline.payout + adjustment));
142
+ let bonusPercent = Math.max(0, Math.min(100, baseline.bonus - adjustment));
143
+ const sum = payoutPercent + bonusPercent;
144
+ if (sum !== 100) {
145
+ payoutPercent = payoutPercent / sum * 100;
146
+ bonusPercent = bonusPercent / sum * 100;
147
+ }
148
+ const payoutUsd = roundToCents(totalUsd * payoutPercent / 100);
149
+ const bonusUsd = roundToCents(totalUsd * bonusPercent / 100);
150
+ const platformFeeUsd = roundToCents(totalUsd * platformFeeRate);
151
+ const userPaysUsd = roundToCents(totalUsd + platformFeeUsd);
152
+ return {
153
+ totalUsd,
154
+ payoutUsd,
155
+ bonusUsd,
156
+ platformFeeUsd,
157
+ userPaysUsd,
158
+ goalType,
159
+ splitPreset,
160
+ payoutPercent: Math.round(payoutPercent),
161
+ bonusPercent: Math.round(bonusPercent)
162
+ };
163
+ }
164
+ function roundToCents(value) {
165
+ return Math.round(value * 100) / 100;
166
+ }
167
+ function parseUsd(value) {
168
+ return parseFloat(value.replace(/^\$/, "").trim());
169
+ }
170
+ function usdToMicroUsd(usd, microUsdPerUsd = DEFAULT_MICRO_USD_PER_USD) {
171
+ return Math.round(usd * microUsdPerUsd);
172
+ }
173
+
174
+ // src/core/agent/engine.ts
175
+ var DEFAULT_CHAIN_INFO = {
176
+ 8453: { name: "Base", usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
177
+ };
178
+ var AgentCore = class {
179
+ adapter;
180
+ defaultChainId;
181
+ platformFeeRate;
182
+ estimateMaxUsers;
183
+ bulkMaxUsers;
184
+ microUsdPerUsd;
185
+ chainInfo;
186
+ constructor(adapter, config = {}) {
187
+ this.adapter = adapter;
188
+ this.defaultChainId = config.defaultChainId ?? 8453;
189
+ this.platformFeeRate = config.platformFeeRate ?? DEFAULT_PLATFORM_FEE_RATE;
190
+ this.estimateMaxUsers = config.estimateMaxUsers ?? 1e4;
191
+ this.bulkMaxUsers = config.bulkMaxUsers ?? 1e4;
192
+ this.microUsdPerUsd = config.microUsdPerUsd ?? DEFAULT_MICRO_USD_PER_USD;
193
+ this.chainInfo = config.chainInfo ?? DEFAULT_CHAIN_INFO;
194
+ }
195
+ buildQueryPlan(filters) {
196
+ return buildAgentQueryPlan(filters);
197
+ }
198
+ normalizeFilters(filters) {
199
+ return normalizeAgentFilters(filters);
200
+ }
201
+ computeBudgetSplit(totalUsd, goalType = "max_reach", splitPreset = "balanced") {
202
+ return computeBudgetSplit(totalUsd, goalType, splitPreset, this.platformFeeRate);
203
+ }
204
+ async lookup(query) {
205
+ const user = await this.adapter.resolveUser(query);
206
+ if (!user) return null;
207
+ const fid = user.fid ?? await this.adapter.getFidForUser(user.id) ?? void 0;
208
+ const walletAddress = user.walletAddress ?? await this.adapter.getPrimaryWalletAddress(user.id) ?? void 0;
209
+ return {
210
+ id: user.id,
211
+ username: user.username,
212
+ platform: user.platform,
213
+ attentionPriceUsd: (Number(user.attentionPriceMicroUsd) / this.microUsdPerUsd).toFixed(2),
214
+ ...fid !== void 0 ? { fid } : {},
215
+ ...user.displayName ? { displayName: user.displayName } : {},
216
+ ...user.pfpUrl ? { pfpUrl: user.pfpUrl } : {},
217
+ ...walletAddress ? { walletAddress } : {},
218
+ ...user.followerCount !== void 0 ? { followerCount: user.followerCount } : {}
219
+ };
220
+ }
221
+ async getPrice(query) {
222
+ const user = await this.lookup(query);
223
+ if (!user) return null;
224
+ const priceUsdNum = parseFloat(user.attentionPriceUsd);
225
+ return {
226
+ userId: user.id,
227
+ username: user.username,
228
+ priceUsd: user.attentionPriceUsd,
229
+ priceUsdc: usdToMicroUsd(priceUsdNum, this.microUsdPerUsd).toString()
230
+ };
231
+ }
232
+ async prepareBeep(params) {
233
+ const user = await this.lookup(params.to);
234
+ if (!user) {
235
+ return { error: "user_not_found", message: `User not found: ${params.to}` };
236
+ }
237
+ if (!user.walletAddress) {
238
+ return { error: "no_wallet", message: `@${user.username} has no connected wallet` };
239
+ }
240
+ const baseAmount = parseUsd(params.amountUsd);
241
+ if (Number.isNaN(baseAmount) || baseAmount <= 0) {
242
+ return { error: "invalid_amount", message: "Amount must be a positive number" };
243
+ }
244
+ const attentionPrice = parseFloat(user.attentionPriceUsd);
245
+ if (baseAmount < attentionPrice) {
246
+ return {
247
+ error: "below_minimum",
248
+ message: `Amount $${baseAmount.toFixed(2)} is below @${user.username}'s minimum beep price of $${attentionPrice.toFixed(2)}.`,
249
+ minimumUsd: user.attentionPriceUsd,
250
+ requestedUsd: params.amountUsd
251
+ };
252
+ }
253
+ const chainId = params.chainId ?? this.defaultChainId;
254
+ const chain = this.chainInfo[chainId];
255
+ if (!chain) {
256
+ return { error: "unsupported_chain", message: `Chain ${chainId} is not supported` };
257
+ }
258
+ const goalType = params.goalType ?? (params.bonusConfig ? "lil_mission" : "max_reach");
259
+ const hasMissions = goalType !== "max_reach";
260
+ const splitPreset = params.splitPreset ?? "balanced";
261
+ const split = hasMissions ? this.computeBudgetSplit(baseAmount, goalType, splitPreset) : void 0;
262
+ const platformFeeUsd = Math.round(baseAmount * this.platformFeeRate * 100) / 100;
263
+ const totalAmountUsd = baseAmount + platformFeeUsd;
264
+ const result = {
265
+ type: "confirmation",
266
+ recipient: {
267
+ username: user.username,
268
+ walletAddress: user.walletAddress,
269
+ ...user.displayName ? { displayName: user.displayName } : {},
270
+ ...user.pfpUrl ? { pfpUrl: user.pfpUrl } : {},
271
+ ...user.fid !== void 0 ? { fid: user.fid } : {}
272
+ },
273
+ message: params.message,
274
+ baseAmountUsd: baseAmount.toFixed(2),
275
+ platformFeeUsd: platformFeeUsd.toFixed(2),
276
+ totalAmountUsd: totalAmountUsd.toFixed(2),
277
+ feePercentage: this.platformFeeRate * 100,
278
+ chainId,
279
+ chainName: chain.name,
280
+ attentionPriceUsd: user.attentionPriceUsd
281
+ };
282
+ if (hasMissions && split) {
283
+ result.hasMissions = true;
284
+ result.budgetSplit = split;
285
+ if (params.bonusConfig) {
286
+ result.bonusConfig = params.bonusConfig;
287
+ }
288
+ }
289
+ return result;
290
+ }
291
+ async createIntent(params) {
292
+ const user = await this.lookup(params.to);
293
+ if (!user || !user.walletAddress) return null;
294
+ const baseAmountUsd = parseUsd(params.amountUsd);
295
+ if (Number.isNaN(baseAmountUsd) || baseAmountUsd <= 0) {
296
+ throw AgentCoreError.validation("Invalid amount");
297
+ }
298
+ const chainId = params.chainId ?? this.defaultChainId;
299
+ const chain = this.chainInfo[chainId];
300
+ if (!chain) throw AgentCoreError.unsupportedChain(chainId);
301
+ const platformFeeUsd = Math.round(baseAmountUsd * this.platformFeeRate * 100) / 100;
302
+ const totalAmountUsd = baseAmountUsd + platformFeeUsd;
303
+ const amountUsdc = usdToMicroUsd(totalAmountUsd, this.microUsdPerUsd).toString();
304
+ const intentId = `intent_${crypto.randomUUID()}`;
305
+ const shortAddress = `${user.walletAddress.slice(0, 6)}...${user.walletAddress.slice(-4)}`;
306
+ const message = params.message ?? "";
307
+ return {
308
+ intentId,
309
+ recipient: user.walletAddress,
310
+ amount: amountUsdc,
311
+ amountFormatted: `${totalAmountUsd.toFixed(2)} USDC`,
312
+ tokenAddress: chain.usdcAddress,
313
+ tokenSymbol: "USDC",
314
+ chainId,
315
+ chainName: chain.name,
316
+ message,
317
+ recipientInfo: {
318
+ username: user.username,
319
+ ...user.displayName ? { displayName: user.displayName } : {},
320
+ ...user.fid !== void 0 ? { fid: user.fid } : {}
321
+ },
322
+ instruction: `Send ${totalAmountUsd.toFixed(2)} USDC to ${shortAddress} on ${chain.name} (${baseAmountUsd.toFixed(2)} to @${user.username} + ${platformFeeUsd.toFixed(2)} platform fee)`,
323
+ expiresAt: new Date(Date.now() + 60 * 60 * 1e3).toISOString(),
324
+ baseAmountUsd: baseAmountUsd.toFixed(2),
325
+ platformFeeUsd: platformFeeUsd.toFixed(2),
326
+ totalAmountUsd: totalAmountUsd.toFixed(2),
327
+ feePercentage: this.platformFeeRate * 100
328
+ };
329
+ }
330
+ async estimate(params) {
331
+ const budgetUsd = parseUsd(params.budgetUsd);
332
+ if (Number.isNaN(budgetUsd) || budgetUsd <= 0) {
333
+ throw AgentCoreError.validation("Budget must be a positive number");
334
+ }
335
+ const plan = this.buildQueryPlan(params.filters);
336
+ const candidates = await this.adapter.findUsers({
337
+ filters: plan.filters,
338
+ orderBy: plan.orderBy,
339
+ limit: this.estimateMaxUsers
340
+ });
341
+ const budgetMicro = usdToMicroUsd(budgetUsd, this.microUsdPerUsd);
342
+ let totalCost = 0;
343
+ let recipientCount = 0;
344
+ let minPrice = Number.POSITIVE_INFINITY;
345
+ let maxPrice = 0;
346
+ for (const candidate of candidates) {
347
+ const priceMicro = Number(candidate.attentionPriceMicroUsd);
348
+ if (totalCost + priceMicro > budgetMicro) break;
349
+ totalCost += priceMicro;
350
+ recipientCount += 1;
351
+ if (priceMicro < minPrice) minPrice = priceMicro;
352
+ if (priceMicro > maxPrice) maxPrice = priceMicro;
353
+ }
354
+ const avgPrice = recipientCount > 0 ? totalCost / recipientCount : 0;
355
+ return {
356
+ recipientCount,
357
+ totalCostUsd: (totalCost / this.microUsdPerUsd).toFixed(2),
358
+ avgPriceUsd: (avgPrice / this.microUsdPerUsd).toFixed(2),
359
+ minPriceUsd: recipientCount > 0 ? (minPrice / this.microUsdPerUsd).toFixed(2) : "0.00",
360
+ maxPriceUsd: recipientCount > 0 ? (maxPrice / this.microUsdPerUsd).toFixed(2) : "0.00",
361
+ remainingBudgetUsd: ((budgetMicro - totalCost) / this.microUsdPerUsd).toFixed(2),
362
+ budgetSufficient: recipientCount > 0,
363
+ diagnostics: {
364
+ candidateCount: candidates.length,
365
+ budgetMicro,
366
+ appliedDefaults: plan.defaultsApplied
367
+ }
368
+ };
369
+ }
370
+ async preview(params) {
371
+ const limit = Math.min(Math.max(params.limit, 1), 20);
372
+ const plan = this.buildQueryPlan(params.filters);
373
+ const [users, totalCount] = await Promise.all([
374
+ this.adapter.findUsers({
375
+ filters: plan.filters,
376
+ orderBy: plan.orderBy,
377
+ limit,
378
+ includeProfile: true,
379
+ includeReputation: true
380
+ }),
381
+ this.adapter.countUsers(plan.filters)
382
+ ]);
383
+ const userIds = users.map((user) => user.id);
384
+ const fidMap = await this.adapter.getBulkFidsForUsers(userIds);
385
+ return {
386
+ users: users.map((user) => {
387
+ const previewUser = {
388
+ username: user.username,
389
+ priceUsd: (Number(user.attentionPriceMicroUsd) / this.microUsdPerUsd).toFixed(2),
390
+ ...user.displayName ? { displayName: user.displayName } : {},
391
+ ...user.followerCount !== void 0 ? { followerCount: user.followerCount } : {},
392
+ ...user.neynarScore !== void 0 ? { neynarScore: user.neynarScore } : {},
393
+ ...user.pfpUrl ? { pfpUrl: user.pfpUrl } : {}
394
+ };
395
+ const fid = fidMap.get(user.id);
396
+ if (fid !== void 0) {
397
+ return { ...previewUser, fid };
398
+ }
399
+ return previewUser;
400
+ }),
401
+ totalCount,
402
+ hasMore: totalCount > limit
403
+ };
404
+ }
405
+ async createBulkIntent(params) {
406
+ const budgetUsd = parseUsd(params.budgetUsd);
407
+ if (Number.isNaN(budgetUsd) || budgetUsd <= 0) {
408
+ throw AgentCoreError.validation("Budget must be a positive number");
409
+ }
410
+ const chainId = params.chainId ?? this.defaultChainId;
411
+ const chain = this.chainInfo[chainId];
412
+ if (!chain) throw AgentCoreError.unsupportedChain(chainId);
413
+ const plan = this.buildQueryPlan(params.filters);
414
+ const users = await this.adapter.findUsers({
415
+ filters: plan.filters,
416
+ orderBy: "attention_price_asc",
417
+ limit: this.bulkMaxUsers
418
+ });
419
+ const budgetMicro = usdToMicroUsd(budgetUsd, this.microUsdPerUsd);
420
+ let totalAmountMicro = 0;
421
+ const selectedUsers = [];
422
+ for (const user of users) {
423
+ const priceMicro = Number(user.attentionPriceMicroUsd);
424
+ if (totalAmountMicro + priceMicro > budgetMicro) break;
425
+ totalAmountMicro += priceMicro;
426
+ selectedUsers.push({
427
+ id: user.id,
428
+ username: user.username,
429
+ amountMicro: priceMicro
430
+ });
431
+ }
432
+ if (selectedUsers.length === 0) {
433
+ throw AgentCoreError.noRecipients("No eligible recipients within budget");
434
+ }
435
+ const walletMap = await this.adapter.getBulkPrimaryWalletAddresses(selectedUsers.map((u) => u.id));
436
+ const payments = selectedUsers.filter((user) => walletMap.has(user.id)).map((user) => ({
437
+ recipient: walletMap.get(user.id),
438
+ amount: user.amountMicro.toString(),
439
+ username: user.username
440
+ }));
441
+ if (payments.length === 0) {
442
+ throw AgentCoreError.noRecipients("No recipients with valid wallets found");
443
+ }
444
+ const totalAmount = payments.reduce((sum, payment) => sum + BigInt(payment.amount), 0n);
445
+ const totalFormatted = (Number(totalAmount) / this.microUsdPerUsd).toFixed(2);
446
+ return {
447
+ bulkIntentId: `bulk_${crypto.randomUUID()}`,
448
+ recipientCount: payments.length,
449
+ totalAmount: totalAmount.toString(),
450
+ totalAmountFormatted: `${totalFormatted} USDC`,
451
+ payments,
452
+ summary: `Send to ${payments.length} recipients for total ${totalFormatted} USDC on ${chain.name}`,
453
+ chainId,
454
+ chainName: chain.name,
455
+ tokenAddress: chain.usdcAddress,
456
+ tokenSymbol: "USDC",
457
+ expiresAt: new Date(Date.now() + 60 * 60 * 1e3).toISOString()
458
+ };
459
+ }
460
+ async prepareCampaign(params) {
461
+ const totalBudget = parseUsd(params.budgetUsd);
462
+ if (Number.isNaN(totalBudget) || totalBudget <= 0) {
463
+ throw AgentCoreError.validation("Budget must be a positive number");
464
+ }
465
+ const chainId = params.chainId ?? this.defaultChainId;
466
+ const chain = this.chainInfo[chainId];
467
+ if (!chain) throw AgentCoreError.unsupportedChain(chainId);
468
+ const goalType = params.goalType ?? (params.bonusConfig ? "lil_mission" : "max_reach");
469
+ const splitPreset = params.splitPreset ?? "balanced";
470
+ const split = this.computeBudgetSplit(totalBudget, goalType, splitPreset);
471
+ const payoutEstimate = await this.estimate({
472
+ filters: params.filters,
473
+ budgetUsd: split.payoutUsd.toFixed(2),
474
+ ...params.message ? { message: params.message } : {}
475
+ });
476
+ let missionSummary;
477
+ if (params.bonusConfig) {
478
+ const ctaLabels = params.bonusConfig.ctas.map((cta) => {
479
+ switch (cta.type) {
480
+ case "follow_profile":
481
+ return `Follow @${cta.profileUsername || cta.profileFid}`;
482
+ case "like_cast":
483
+ return "Like a cast";
484
+ case "recast":
485
+ return "Recast";
486
+ case "share_cast":
487
+ return "Quote cast";
488
+ case "visit_link":
489
+ return `Visit ${cta.label || cta.url || "link"}`;
490
+ case "quiz":
491
+ return `Quiz (${cta.questions?.length || 0} questions)`;
492
+ case "external_verify":
493
+ return cta.description || "Custom quest";
494
+ case "x_follow":
495
+ return `Follow @${cta.handle} on X`;
496
+ case "x_like":
497
+ return "Like tweet on X";
498
+ case "x_recast":
499
+ return "Repost on X";
500
+ default:
501
+ return cta.type;
502
+ }
503
+ });
504
+ const distributionLabel = params.bonusConfig.type === "lottery" ? "BEEPERY (lottery)" : "FCFS (first come)";
505
+ missionSummary = `${distributionLabel} \u2022 $${split.bonusUsd.toFixed(2)} pool \u2022 ${ctaLabels.join(", ")}`;
506
+ }
507
+ return {
508
+ type: "campaign_confirmation",
509
+ recipientCount: payoutEstimate.recipientCount,
510
+ budgetSplit: split,
511
+ payoutEstimate: {
512
+ recipientCount: payoutEstimate.recipientCount,
513
+ totalPayoutCostUsd: payoutEstimate.totalCostUsd,
514
+ avgPriceUsd: payoutEstimate.avgPriceUsd
515
+ },
516
+ platformFeeUsd: split.platformFeeUsd.toFixed(2),
517
+ userPaysUsd: split.userPaysUsd.toFixed(2),
518
+ chainId,
519
+ chainName: chain.name,
520
+ ...params.bonusConfig ? { bonusConfig: params.bonusConfig } : {},
521
+ ...missionSummary ? { missionSummary } : {},
522
+ ...params.message ? { message: params.message } : {}
523
+ };
524
+ }
525
+ async getBeepHistory(params) {
526
+ return this.adapter.getBeepHistory(params);
527
+ }
528
+ };
529
+ function createAgentCore(adapter, config) {
530
+ return new AgentCore(adapter, config);
531
+ }
532
+ function normalizeFilters(filters) {
533
+ return normalizeAgentFilters(filters);
534
+ }
535
+ function buildQueryPlan(filters) {
536
+ return buildAgentQueryPlan(filters);
537
+ }
538
+ function getDefaultOrderBy(filters) {
539
+ return buildAgentQueryPlan(filters).orderBy;
540
+ }
541
+
542
+ exports.AgentCore = AgentCore;
543
+ exports.AgentCoreError = AgentCoreError;
544
+ exports.buildAgentQueryPlan = buildAgentQueryPlan;
545
+ exports.buildQueryPlan = buildQueryPlan;
546
+ exports.computeBudgetSplit = computeBudgetSplit;
547
+ exports.createAgentCore = createAgentCore;
548
+ exports.getDefaultOrderBy = getDefaultOrderBy;
549
+ exports.getOrderByOrDefault = getOrderByOrDefault;
550
+ exports.normalizeAgentFilters = normalizeAgentFilters;
551
+ exports.normalizeFilters = normalizeFilters;
552
+ //# sourceMappingURL=index.cjs.map
553
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/agent/errors.ts","../../src/core/agent/filters.ts","../../src/core/agent/costing.ts","../../src/core/agent/engine.ts"],"names":["require","randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["export type AgentCoreErrorCode =\n | 'VALIDATION_ERROR'\n | 'NOT_FOUND'\n | 'UNSUPPORTED_CHAIN'\n | 'NO_RECIPIENTS'\n | 'INTERNAL_ERROR';\n\nexport class AgentCoreError extends Error {\n readonly code: AgentCoreErrorCode;\n\n constructor(code: AgentCoreErrorCode, message: string) {\n super(message);\n this.name = 'AgentCoreError';\n this.code = code;\n }\n\n static validation(message: string): AgentCoreError {\n return new AgentCoreError('VALIDATION_ERROR', message);\n }\n\n static notFound(message: string): AgentCoreError {\n return new AgentCoreError('NOT_FOUND', message);\n }\n\n static unsupportedChain(chainId: number): AgentCoreError {\n return new AgentCoreError('UNSUPPORTED_CHAIN', `Unsupported chain: ${chainId}`);\n }\n\n static noRecipients(message: string): AgentCoreError {\n return new AgentCoreError('NO_RECIPIENTS', message);\n }\n}\n","import type { AgentQueryPlan, OrderByOption, SimpleFilters } from './types.js';\n\nconst CHAIN_ID_MAP: Record<string, number> = {\n base: 8453,\n ethereum: 1,\n mainnet: 1,\n arbitrum: 42161,\n polygon: 137,\n optimism: 10,\n};\n\nexport interface NormalizedFiltersResult {\n filters: SimpleFilters;\n defaultsApplied: string[];\n}\n\nfunction hasSubstantiveFilters(filters: SimpleFilters): boolean {\n return !!(\n filters.platform ||\n filters.minFollowers ||\n filters.maxFollowers ||\n filters.fids?.length ||\n filters.userIds?.length ||\n filters.castEngagement?.castHash ||\n filters.castEngagement?.castUrl ||\n filters.activeInLastDays ||\n filters.countries?.length ||\n filters.neynarScoreMin ||\n filters.tokenHolders?.length ||\n filters.maxAttentionPriceUsd ||\n filters.hasBaseWallet ||\n filters.spamLabel\n );\n}\n\nexport function normalizeAgentFilters(filters: SimpleFilters): NormalizedFiltersResult {\n const normalized: SimpleFilters = { ...filters };\n const defaultsApplied: string[] = [];\n\n const stripEmptyArray = (key: keyof SimpleFilters) => {\n const value = normalized[key];\n if (Array.isArray(value) && value.length === 0) {\n delete (normalized as Record<string, unknown>)[key];\n }\n };\n\n const stripZero = (key: keyof SimpleFilters) => {\n const value = normalized[key];\n if (typeof value === 'number' && value === 0) {\n delete (normalized as Record<string, unknown>)[key];\n }\n };\n\n if (normalized.platform === 'all') delete (normalized as Record<string, unknown>).platform;\n if (normalized.spamLabel === 'all') delete (normalized as Record<string, unknown>).spamLabel;\n\n stripZero('minFollowers');\n stripZero('maxFollowers');\n stripZero('activeInLastDays');\n stripZero('minBatteryPercentage');\n stripZero('hasRechargedInLastDays');\n stripZero('maxAttentionPriceUsd');\n\n stripEmptyArray('signalTokens');\n\n if (Array.isArray(normalized.tokenHolders)) {\n normalized.tokenHolders = normalized.tokenHolders\n .map((holder) => {\n if (!holder) return null;\n if ('tokenAddress' in holder && 'chainId' in holder) return holder;\n\n const loose = holder as unknown as {\n contractAddress?: string;\n chain?: string | number;\n minBalance?: string;\n };\n\n if (!loose.contractAddress || loose.chain == null) return null;\n\n const chainId =\n typeof loose.chain === 'number'\n ? loose.chain\n : CHAIN_ID_MAP[String(loose.chain).toLowerCase()] ?? Number(loose.chain);\n\n if (!Number.isFinite(chainId)) return null;\n\n return {\n tokenAddress: loose.contractAddress,\n chainId,\n ...(loose.minBalance ? { minBalance: loose.minBalance } : {}),\n };\n })\n .filter((holder): holder is NonNullable<typeof holder> => !!holder);\n }\n\n stripEmptyArray('tokenHolders');\n\n if (Array.isArray(normalized.countries)) {\n normalized.countries = normalized.countries\n .map((country) => {\n if (typeof country === 'string') return country;\n return (country as unknown as { code?: string })?.code;\n })\n .filter((country): country is string => typeof country === 'string' && country.length > 0)\n .map((country) => country.toUpperCase());\n }\n\n stripEmptyArray('countries');\n stripEmptyArray('fids');\n stripEmptyArray('userIds');\n\n if (normalized.castEngagement) {\n const { castHash, castUrl, require } = normalized.castEngagement;\n if (!castHash && !castUrl) {\n delete (normalized as Record<string, unknown>).castEngagement;\n } else if (Array.isArray(require) && require.length === 0) {\n normalized.castEngagement = {\n ...(castHash != null && { castHash }),\n ...(castUrl != null && { castUrl }),\n };\n }\n }\n\n if (normalized.neynarScoreMin === 0) delete (normalized as Record<string, unknown>).neynarScoreMin;\n if (normalized.neynarScoreMax === 1) delete (normalized as Record<string, unknown>).neynarScoreMax;\n if (normalized.quotientScoreMin === 0) delete (normalized as Record<string, unknown>).quotientScoreMin;\n if (normalized.quotientScoreMax === 1) delete (normalized as Record<string, unknown>).quotientScoreMax;\n\n if (!hasSubstantiveFilters(normalized)) {\n normalized.activeInLastDays = 30;\n normalized.spamLabel = 'not_spam_only';\n defaultsApplied.push('activeInLastDays=30', 'spamLabel=not_spam_only');\n }\n\n return { filters: normalized, defaultsApplied };\n}\n\nexport function getOrderByOrDefault(filters: SimpleFilters): OrderByOption {\n return filters.orderBy ?? 'attention_price_asc';\n}\n\nexport function buildAgentQueryPlan(filters: SimpleFilters): AgentQueryPlan {\n const normalized = normalizeAgentFilters(filters);\n return {\n inputFilters: { ...filters },\n filters: normalized.filters,\n orderBy: getOrderByOrDefault(normalized.filters),\n defaultsApplied: normalized.defaultsApplied,\n };\n}\n","import type { BudgetSplit, GoalType, SplitPreset } from './types.js';\n\nexport const DEFAULT_MICRO_USD_PER_USD = 1_000_000;\nexport const DEFAULT_PLATFORM_FEE_RATE = 0.10;\n\nconst GOAL_BASELINES: Record<GoalType, { payout: number; bonus: number }> = {\n max_reach: { payout: 100, bonus: 0 },\n lil_mission: { payout: 80, bonus: 20 },\n hard_mission: { payout: 50, bonus: 50 },\n};\n\nconst SPLIT_ADJUSTMENTS: Record<SplitPreset, number> = {\n balanced: 0,\n more_reach: 10,\n more_action: -10,\n};\n\nexport function computeBudgetSplit(\n totalUsd: number,\n goalType: GoalType = 'max_reach',\n splitPreset: SplitPreset = 'balanced',\n platformFeeRate = DEFAULT_PLATFORM_FEE_RATE,\n): BudgetSplit {\n const baseline = GOAL_BASELINES[goalType];\n const adjustment = SPLIT_ADJUSTMENTS[splitPreset];\n\n let payoutPercent = Math.max(0, Math.min(100, baseline.payout + adjustment));\n let bonusPercent = Math.max(0, Math.min(100, baseline.bonus - adjustment));\n\n const sum = payoutPercent + bonusPercent;\n if (sum !== 100) {\n payoutPercent = (payoutPercent / sum) * 100;\n bonusPercent = (bonusPercent / sum) * 100;\n }\n\n const payoutUsd = roundToCents((totalUsd * payoutPercent) / 100);\n const bonusUsd = roundToCents((totalUsd * bonusPercent) / 100);\n const platformFeeUsd = roundToCents(totalUsd * platformFeeRate);\n const userPaysUsd = roundToCents(totalUsd + platformFeeUsd);\n\n return {\n totalUsd,\n payoutUsd,\n bonusUsd,\n platformFeeUsd,\n userPaysUsd,\n goalType,\n splitPreset,\n payoutPercent: Math.round(payoutPercent),\n bonusPercent: Math.round(bonusPercent),\n };\n}\n\nexport function roundToCents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\nexport function parseUsd(value: string): number {\n return parseFloat(value.replace(/^\\$/, '').trim());\n}\n\nexport function microUsdToUsd(microValue: bigint | number | string, microUsdPerUsd = DEFAULT_MICRO_USD_PER_USD): number {\n return Number(microValue) / microUsdPerUsd;\n}\n\nexport function usdToMicroUsd(usd: number, microUsdPerUsd = DEFAULT_MICRO_USD_PER_USD): number {\n return Math.round(usd * microUsdPerUsd);\n}\n","import { randomUUID } from 'node:crypto';\nimport { AgentCoreError } from './errors.js';\nimport { buildAgentQueryPlan, normalizeAgentFilters } from './filters.js';\nimport {\n computeBudgetSplit,\n DEFAULT_MICRO_USD_PER_USD,\n DEFAULT_PLATFORM_FEE_RATE,\n parseUsd,\n usdToMicroUsd,\n} from './costing.js';\nimport type {\n AgentCoreAdapter,\n AgentCoreConfig,\n AgentUser,\n AttentionPrice,\n BeepHistoryRecord,\n BonusConfig,\n BudgetSplit,\n BulkIntentResult,\n EstimateResult,\n GoalType,\n OrderByOption,\n PaymentIntent,\n PrepareBeepError,\n PrepareBeepResult,\n PrepareCampaignResult,\n PreviewResult,\n SimpleFilters,\n SplitPreset,\n} from './types.js';\n\nconst DEFAULT_CHAIN_INFO: Record<number, { name: string; usdcAddress: string }> = {\n 8453: { name: 'Base', usdcAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' },\n};\n\nexport class AgentCore {\n private readonly adapter: AgentCoreAdapter;\n private readonly defaultChainId: number;\n private readonly platformFeeRate: number;\n private readonly estimateMaxUsers: number;\n private readonly bulkMaxUsers: number;\n private readonly microUsdPerUsd: number;\n private readonly chainInfo: Record<number, { name: string; usdcAddress: string }>;\n\n constructor(adapter: AgentCoreAdapter, config: AgentCoreConfig = {}) {\n this.adapter = adapter;\n this.defaultChainId = config.defaultChainId ?? 8453;\n this.platformFeeRate = config.platformFeeRate ?? DEFAULT_PLATFORM_FEE_RATE;\n this.estimateMaxUsers = config.estimateMaxUsers ?? 10_000;\n this.bulkMaxUsers = config.bulkMaxUsers ?? 10_000;\n this.microUsdPerUsd = config.microUsdPerUsd ?? DEFAULT_MICRO_USD_PER_USD;\n this.chainInfo = config.chainInfo ?? DEFAULT_CHAIN_INFO;\n }\n\n buildQueryPlan(filters: SimpleFilters) {\n return buildAgentQueryPlan(filters);\n }\n\n normalizeFilters(filters: SimpleFilters) {\n return normalizeAgentFilters(filters);\n }\n\n computeBudgetSplit(\n totalUsd: number,\n goalType: GoalType = 'max_reach',\n splitPreset: SplitPreset = 'balanced',\n ): BudgetSplit {\n return computeBudgetSplit(totalUsd, goalType, splitPreset, this.platformFeeRate);\n }\n\n async lookup(query: string | number): Promise<AgentUser | null> {\n const user = await this.adapter.resolveUser(query);\n if (!user) return null;\n\n const fid = user.fid ?? (await this.adapter.getFidForUser(user.id)) ?? undefined;\n const walletAddress = user.walletAddress ?? (await this.adapter.getPrimaryWalletAddress(user.id)) ?? undefined;\n\n return {\n id: user.id,\n username: user.username,\n platform: user.platform,\n attentionPriceUsd: (Number(user.attentionPriceMicroUsd) / this.microUsdPerUsd).toFixed(2),\n ...(fid !== undefined ? { fid } : {}),\n ...(user.displayName ? { displayName: user.displayName } : {}),\n ...(user.pfpUrl ? { pfpUrl: user.pfpUrl } : {}),\n ...(walletAddress ? { walletAddress } : {}),\n ...(user.followerCount !== undefined ? { followerCount: user.followerCount } : {}),\n };\n }\n\n async getPrice(query: string | number): Promise<AttentionPrice | null> {\n const user = await this.lookup(query);\n if (!user) return null;\n\n const priceUsdNum = parseFloat(user.attentionPriceUsd);\n return {\n userId: user.id,\n username: user.username,\n priceUsd: user.attentionPriceUsd,\n priceUsdc: usdToMicroUsd(priceUsdNum, this.microUsdPerUsd).toString(),\n };\n }\n\n async prepareBeep(params: {\n to: string | number;\n amountUsd: string;\n message: string;\n chainId?: number;\n goalType?: GoalType;\n splitPreset?: SplitPreset;\n bonusConfig?: BonusConfig;\n }): Promise<PrepareBeepResult | PrepareBeepError> {\n const user = await this.lookup(params.to);\n if (!user) {\n return { error: 'user_not_found', message: `User not found: ${params.to}` };\n }\n\n if (!user.walletAddress) {\n return { error: 'no_wallet', message: `@${user.username} has no connected wallet` };\n }\n\n const baseAmount = parseUsd(params.amountUsd);\n if (Number.isNaN(baseAmount) || baseAmount <= 0) {\n return { error: 'invalid_amount', message: 'Amount must be a positive number' };\n }\n\n const attentionPrice = parseFloat(user.attentionPriceUsd);\n if (baseAmount < attentionPrice) {\n return {\n error: 'below_minimum',\n message: `Amount $${baseAmount.toFixed(2)} is below @${user.username}'s minimum beep price of $${attentionPrice.toFixed(2)}.`,\n minimumUsd: user.attentionPriceUsd,\n requestedUsd: params.amountUsd,\n };\n }\n\n const chainId = params.chainId ?? this.defaultChainId;\n const chain = this.chainInfo[chainId];\n if (!chain) {\n return { error: 'unsupported_chain', message: `Chain ${chainId} is not supported` };\n }\n\n const goalType = params.goalType ?? (params.bonusConfig ? 'lil_mission' : 'max_reach');\n const hasMissions = goalType !== 'max_reach';\n const splitPreset = params.splitPreset ?? 'balanced';\n\n const split = hasMissions\n ? this.computeBudgetSplit(baseAmount, goalType, splitPreset)\n : undefined;\n\n const platformFeeUsd = Math.round(baseAmount * this.platformFeeRate * 100) / 100;\n const totalAmountUsd = baseAmount + platformFeeUsd;\n\n const result: PrepareBeepResult = {\n type: 'confirmation',\n recipient: {\n username: user.username,\n walletAddress: user.walletAddress,\n ...(user.displayName ? { displayName: user.displayName } : {}),\n ...(user.pfpUrl ? { pfpUrl: user.pfpUrl } : {}),\n ...(user.fid !== undefined ? { fid: user.fid } : {}),\n },\n message: params.message,\n baseAmountUsd: baseAmount.toFixed(2),\n platformFeeUsd: platformFeeUsd.toFixed(2),\n totalAmountUsd: totalAmountUsd.toFixed(2),\n feePercentage: this.platformFeeRate * 100,\n chainId,\n chainName: chain.name,\n attentionPriceUsd: user.attentionPriceUsd,\n };\n\n if (hasMissions && split) {\n result.hasMissions = true;\n result.budgetSplit = split;\n if (params.bonusConfig) {\n result.bonusConfig = params.bonusConfig;\n }\n }\n\n return result;\n }\n\n async createIntent(params: {\n to: string | number;\n amountUsd: string;\n message?: string;\n chainId?: number;\n }): Promise<PaymentIntent | null> {\n const user = await this.lookup(params.to);\n if (!user || !user.walletAddress) return null;\n\n const baseAmountUsd = parseUsd(params.amountUsd);\n if (Number.isNaN(baseAmountUsd) || baseAmountUsd <= 0) {\n throw AgentCoreError.validation('Invalid amount');\n }\n\n const chainId = params.chainId ?? this.defaultChainId;\n const chain = this.chainInfo[chainId];\n if (!chain) throw AgentCoreError.unsupportedChain(chainId);\n\n const platformFeeUsd = Math.round(baseAmountUsd * this.platformFeeRate * 100) / 100;\n const totalAmountUsd = baseAmountUsd + platformFeeUsd;\n const amountUsdc = usdToMicroUsd(totalAmountUsd, this.microUsdPerUsd).toString();\n const intentId = `intent_${randomUUID()}`;\n const shortAddress = `${user.walletAddress.slice(0, 6)}...${user.walletAddress.slice(-4)}`;\n const message = params.message ?? '';\n\n return {\n intentId,\n recipient: user.walletAddress,\n amount: amountUsdc,\n amountFormatted: `${totalAmountUsd.toFixed(2)} USDC`,\n tokenAddress: chain.usdcAddress,\n tokenSymbol: 'USDC',\n chainId,\n chainName: chain.name,\n message,\n recipientInfo: {\n username: user.username,\n ...(user.displayName ? { displayName: user.displayName } : {}),\n ...(user.fid !== undefined ? { fid: user.fid } : {}),\n },\n instruction: `Send ${totalAmountUsd.toFixed(2)} USDC to ${shortAddress} on ${chain.name} (${baseAmountUsd.toFixed(2)} to @${user.username} + ${platformFeeUsd.toFixed(2)} platform fee)`,\n expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),\n baseAmountUsd: baseAmountUsd.toFixed(2),\n platformFeeUsd: platformFeeUsd.toFixed(2),\n totalAmountUsd: totalAmountUsd.toFixed(2),\n feePercentage: this.platformFeeRate * 100,\n };\n }\n\n async estimate(params: {\n filters: SimpleFilters;\n budgetUsd: string;\n message?: string;\n }): Promise<EstimateResult> {\n const budgetUsd = parseUsd(params.budgetUsd);\n if (Number.isNaN(budgetUsd) || budgetUsd <= 0) {\n throw AgentCoreError.validation('Budget must be a positive number');\n }\n\n const plan = this.buildQueryPlan(params.filters);\n const candidates = await this.adapter.findUsers({\n filters: plan.filters,\n orderBy: plan.orderBy,\n limit: this.estimateMaxUsers,\n });\n\n const budgetMicro = usdToMicroUsd(budgetUsd, this.microUsdPerUsd);\n let totalCost = 0;\n let recipientCount = 0;\n let minPrice = Number.POSITIVE_INFINITY;\n let maxPrice = 0;\n\n for (const candidate of candidates) {\n const priceMicro = Number(candidate.attentionPriceMicroUsd);\n if (totalCost + priceMicro > budgetMicro) break;\n\n totalCost += priceMicro;\n recipientCount += 1;\n if (priceMicro < minPrice) minPrice = priceMicro;\n if (priceMicro > maxPrice) maxPrice = priceMicro;\n }\n\n const avgPrice = recipientCount > 0 ? totalCost / recipientCount : 0;\n\n return {\n recipientCount,\n totalCostUsd: (totalCost / this.microUsdPerUsd).toFixed(2),\n avgPriceUsd: (avgPrice / this.microUsdPerUsd).toFixed(2),\n minPriceUsd: recipientCount > 0 ? (minPrice / this.microUsdPerUsd).toFixed(2) : '0.00',\n maxPriceUsd: recipientCount > 0 ? (maxPrice / this.microUsdPerUsd).toFixed(2) : '0.00',\n remainingBudgetUsd: ((budgetMicro - totalCost) / this.microUsdPerUsd).toFixed(2),\n budgetSufficient: recipientCount > 0,\n diagnostics: {\n candidateCount: candidates.length,\n budgetMicro,\n appliedDefaults: plan.defaultsApplied,\n },\n };\n }\n\n async preview(params: {\n filters: SimpleFilters;\n limit: number;\n }): Promise<PreviewResult> {\n const limit = Math.min(Math.max(params.limit, 1), 20);\n const plan = this.buildQueryPlan(params.filters);\n\n const [users, totalCount] = await Promise.all([\n this.adapter.findUsers({\n filters: plan.filters,\n orderBy: plan.orderBy,\n limit,\n includeProfile: true,\n includeReputation: true,\n }),\n this.adapter.countUsers(plan.filters),\n ]);\n\n const userIds = users.map((user) => user.id);\n const fidMap = await this.adapter.getBulkFidsForUsers(userIds);\n\n return {\n users: users.map((user) => {\n const previewUser = {\n username: user.username,\n priceUsd: (Number(user.attentionPriceMicroUsd) / this.microUsdPerUsd).toFixed(2),\n ...(user.displayName ? { displayName: user.displayName } : {}),\n ...(user.followerCount !== undefined ? { followerCount: user.followerCount } : {}),\n ...(user.neynarScore !== undefined ? { neynarScore: user.neynarScore } : {}),\n ...(user.pfpUrl ? { pfpUrl: user.pfpUrl } : {}),\n };\n\n const fid = fidMap.get(user.id);\n if (fid !== undefined) {\n return { ...previewUser, fid };\n }\n\n return previewUser;\n }),\n totalCount,\n hasMore: totalCount > limit,\n };\n }\n\n async createBulkIntent(params: {\n filters: SimpleFilters;\n budgetUsd: string;\n message?: string;\n chainId?: number;\n }): Promise<BulkIntentResult> {\n const budgetUsd = parseUsd(params.budgetUsd);\n if (Number.isNaN(budgetUsd) || budgetUsd <= 0) {\n throw AgentCoreError.validation('Budget must be a positive number');\n }\n\n const chainId = params.chainId ?? this.defaultChainId;\n const chain = this.chainInfo[chainId];\n if (!chain) throw AgentCoreError.unsupportedChain(chainId);\n\n const plan = this.buildQueryPlan(params.filters);\n const users = await this.adapter.findUsers({\n filters: plan.filters,\n orderBy: 'attention_price_asc',\n limit: this.bulkMaxUsers,\n });\n\n const budgetMicro = usdToMicroUsd(budgetUsd, this.microUsdPerUsd);\n let totalAmountMicro = 0;\n const selectedUsers: Array<{ id: string; username: string; amountMicro: number }> = [];\n\n for (const user of users) {\n const priceMicro = Number(user.attentionPriceMicroUsd);\n if (totalAmountMicro + priceMicro > budgetMicro) break;\n totalAmountMicro += priceMicro;\n selectedUsers.push({\n id: user.id,\n username: user.username,\n amountMicro: priceMicro,\n });\n }\n\n if (selectedUsers.length === 0) {\n throw AgentCoreError.noRecipients('No eligible recipients within budget');\n }\n\n const walletMap = await this.adapter.getBulkPrimaryWalletAddresses(selectedUsers.map((u) => u.id));\n\n const payments = selectedUsers\n .filter((user) => walletMap.has(user.id))\n .map((user) => ({\n recipient: walletMap.get(user.id)!,\n amount: user.amountMicro.toString(),\n username: user.username,\n }));\n\n if (payments.length === 0) {\n throw AgentCoreError.noRecipients('No recipients with valid wallets found');\n }\n\n const totalAmount = payments.reduce((sum, payment) => sum + BigInt(payment.amount), 0n);\n const totalFormatted = (Number(totalAmount) / this.microUsdPerUsd).toFixed(2);\n\n return {\n bulkIntentId: `bulk_${randomUUID()}`,\n recipientCount: payments.length,\n totalAmount: totalAmount.toString(),\n totalAmountFormatted: `${totalFormatted} USDC`,\n payments,\n summary: `Send to ${payments.length} recipients for total ${totalFormatted} USDC on ${chain.name}`,\n chainId,\n chainName: chain.name,\n tokenAddress: chain.usdcAddress,\n tokenSymbol: 'USDC',\n expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),\n };\n }\n\n async prepareCampaign(params: {\n filters: SimpleFilters;\n budgetUsd: string;\n message?: string;\n goalType?: GoalType;\n splitPreset?: SplitPreset;\n bonusConfig?: BonusConfig;\n chainId?: number;\n }): Promise<PrepareCampaignResult> {\n const totalBudget = parseUsd(params.budgetUsd);\n if (Number.isNaN(totalBudget) || totalBudget <= 0) {\n throw AgentCoreError.validation('Budget must be a positive number');\n }\n\n const chainId = params.chainId ?? this.defaultChainId;\n const chain = this.chainInfo[chainId];\n if (!chain) throw AgentCoreError.unsupportedChain(chainId);\n\n const goalType = params.goalType ?? (params.bonusConfig ? 'lil_mission' : 'max_reach');\n const splitPreset = params.splitPreset ?? 'balanced';\n const split = this.computeBudgetSplit(totalBudget, goalType, splitPreset);\n\n const payoutEstimate = await this.estimate({\n filters: params.filters,\n budgetUsd: split.payoutUsd.toFixed(2),\n ...(params.message ? { message: params.message } : {}),\n });\n\n let missionSummary: string | undefined;\n if (params.bonusConfig) {\n const ctaLabels = params.bonusConfig.ctas.map((cta) => {\n switch (cta.type) {\n case 'follow_profile':\n return `Follow @${cta.profileUsername || cta.profileFid}`;\n case 'like_cast':\n return 'Like a cast';\n case 'recast':\n return 'Recast';\n case 'share_cast':\n return 'Quote cast';\n case 'visit_link':\n return `Visit ${cta.label || cta.url || 'link'}`;\n case 'quiz':\n return `Quiz (${cta.questions?.length || 0} questions)`;\n case 'external_verify':\n return cta.description || 'Custom quest';\n case 'x_follow':\n return `Follow @${cta.handle} on X`;\n case 'x_like':\n return 'Like tweet on X';\n case 'x_recast':\n return 'Repost on X';\n default:\n return cta.type;\n }\n });\n\n const distributionLabel = params.bonusConfig.type === 'lottery' ? 'BEEPERY (lottery)' : 'FCFS (first come)';\n missionSummary = `${distributionLabel} • $${split.bonusUsd.toFixed(2)} pool • ${ctaLabels.join(', ')}`;\n }\n\n return {\n type: 'campaign_confirmation',\n recipientCount: payoutEstimate.recipientCount,\n budgetSplit: split,\n payoutEstimate: {\n recipientCount: payoutEstimate.recipientCount,\n totalPayoutCostUsd: payoutEstimate.totalCostUsd,\n avgPriceUsd: payoutEstimate.avgPriceUsd,\n },\n platformFeeUsd: split.platformFeeUsd.toFixed(2),\n userPaysUsd: split.userPaysUsd.toFixed(2),\n chainId,\n chainName: chain.name,\n ...(params.bonusConfig ? { bonusConfig: params.bonusConfig } : {}),\n ...(missionSummary ? { missionSummary } : {}),\n ...(params.message ? { message: params.message } : {}),\n };\n }\n\n async getBeepHistory(params: {\n fromFid?: number;\n fromUserId?: string;\n limit?: number;\n offset?: number;\n }): Promise<{ beeps: BeepHistoryRecord[]; total: number }> {\n return this.adapter.getBeepHistory(params);\n }\n}\n\nexport function createAgentCore(adapter: AgentCoreAdapter, config?: AgentCoreConfig): AgentCore {\n return new AgentCore(adapter, config);\n}\n\nexport function normalizeFilters(filters: SimpleFilters) {\n return normalizeAgentFilters(filters);\n}\n\nexport function buildQueryPlan(filters: SimpleFilters) {\n return buildAgentQueryPlan(filters);\n}\n\nexport function getDefaultOrderBy(filters: SimpleFilters): OrderByOption {\n return buildAgentQueryPlan(filters).orderBy;\n}\n"]}