@agentdata/plugin-elizaos 1.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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/index.js +328 -0
  4. package/package.json +36 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentData API
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # @agentdata/plugin-elizaos
2
+
3
+ **ElizaOS plugin** exposing the [AgentData API](https://agentdata-api.com) as agent actions. Real-time crypto market data for your ElizaOS agent via [x402](https://www.x402.org) micropayments on Base Mainnet.
4
+
5
+ [![ElizaOS](https://img.shields.io/badge/elizaOS-compatible-orange)](https://elizaos.github.io)
6
+ [![x402 v2](https://img.shields.io/badge/x402-v2-00D395)](https://www.x402.org)
7
+ [![Base Mainnet](https://img.shields.io/badge/network-Base%20Mainnet-0052FF)](https://basescan.org)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
9
+
10
+ ## What this plugin does
11
+
12
+ Adds 8 crypto market data **actions** and 1 passive **provider** to any ElizaOS agent. The agent can query live prices, funding rates, DeFi yields, arbitrage opportunities, technical indicators, and sentiment data — paying per request in USDC on Base Mainnet.
13
+
14
+ No API keys. No subscriptions. Just fund a wallet with USDC and your agent can access premium crypto data on demand.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @agentdata/plugin-elizaos
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ In your agent character file:
25
+
26
+ ```typescript
27
+ import { agentdataPlugin } from '@agentdata/plugin-elizaos';
28
+
29
+ export const character = {
30
+ name: 'CryptoTrader',
31
+ // ... other config
32
+ plugins: [agentdataPlugin],
33
+ settings: {
34
+ AGENTDATA_BUYER_PRIVATE_KEY: process.env.BUYER_WALLET_KEY, // 0x...
35
+ AGENTDATA_BASE_URL: 'https://agentdata-api.com', // optional
36
+ },
37
+ };
38
+ ```
39
+
40
+ ## Actions
41
+
42
+ These trigger when the user mentions relevant keywords:
43
+
44
+ | Action | Price | Trigger phrases |
45
+ |--------|-------|----------------|
46
+ | `GET_CHANGES_SINCE_LAST_CALL` | $0.001 | "what changed", "since last time" |
47
+ | `WATCH_CONDITION` | $0.010 | "alert me when", "watch for" |
48
+ | `GET_SIGNAL_CALIBRATION` | free | "how accurate", "track record" |
49
+ | `GET_CRYPTO_PRICES` | $0.002 | "crypto prices", "bitcoin price", "eth price" |
50
+ | `GET_FUNDING_RATES` | $0.002 | "funding rate", "perpetuals" |
51
+ | `GET_MARKET_OVERVIEW` | $0.003 | "market overview", "market sentiment" |
52
+ | `GET_DEFI_YIELDS` | $0.003 | "defi yields", "best yield" |
53
+ | `GET_ARBITRAGE_OPPORTUNITIES` | $0.005 | "arbitrage", "price difference" |
54
+ | `GET_TECHNICAL_INDICATORS` | $0.003 | "rsi", "macd", "ta" |
55
+ | `GET_SENTIMENT` | $0.002 | "fear and greed", "sentiment" |
56
+ | `GET_STABLECOIN_HEALTH` | $0.002 | "usdc peg", "depeg" |
57
+
58
+ ## Provider
59
+
60
+ `agentdata_market_context` — passively injects current BTC/ETH prices and market sentiment into every agent turn. Gives your agent constant awareness of market state without explicit queries.
61
+
62
+ ## Payment modes
63
+
64
+ **Without `AGENTDATA_BUYER_PRIVATE_KEY`** — actions throw "Payment required" with the 402 details. The agent will tell the user how much each query costs.
65
+
66
+ **With `AGENTDATA_BUYER_PRIVATE_KEY`** — plugin auto-signs ERC-3009 `TransferWithAuthorization` using viem. Each query costs $0.001–$0.003 USDC. Fund the buyer wallet with $5 → good for ~1500–5000 queries.
67
+
68
+ No ETH required on the buyer wallet — the AgentData facilitator pays settlement gas.
69
+
70
+ ## Example agent conversation
71
+
72
+ ```
73
+ User: What are BTC and ETH doing right now?
74
+ Agent: [executes GET_CRYPTO_PRICES — $0.002 USDC]
75
+ Bitcoin is at $68,718, Ethereum at $2,079.
76
+
77
+ User: Is there arbitrage anywhere?
78
+ Agent: [executes GET_ARBITRAGE_OPPORTUNITIES — $0.005 USDC]
79
+ Yes: SOL has a 0.12% spread between MEXC and Binance...
80
+ ```
81
+
82
+ ## Related
83
+
84
+ - **[agentdata-api](https://github.com/speteai/agentdata-api)** — the underlying x402 service
85
+ - **[agentdata-mcp](https://github.com/speteai/agentdata-mcp)** — MCP version for Claude Desktop
86
+ - **Live service:** https://agentdata-api.com
87
+
88
+ ## Keywords
89
+
90
+ ElizaOS plugin, ai16z plugin, crypto data plugin, DeFi plugin, x402 plugin, AI agent crypto, agentic crypto trading, DeFAI agent, autonomous trading agent, ElizaOS actions, crypto market data plugin, agent economy
91
+
92
+ ## License
93
+
94
+ MIT — see [LICENSE](LICENSE).
package/index.js ADDED
@@ -0,0 +1,328 @@
1
+ /**
2
+ * @agentdata/plugin-elizaos
3
+ *
4
+ * ElizaOS plugin exposing the AgentData API (https://agentdata-api.com) as
5
+ * Actions and Providers. Supports both proxy mode (agent handles payment
6
+ * externally) and auto-pay mode (plugin signs ERC-3009 authorizations using
7
+ * the configured wallet).
8
+ *
9
+ * Configuration (in agent character file):
10
+ * settings:
11
+ * AGENTDATA_BASE_URL: https://agentdata-api.com
12
+ * AGENTDATA_BUYER_PRIVATE_KEY: 0x... (optional, enables auto-pay)
13
+ */
14
+
15
+ const BASE_URL_DEFAULT = 'https://agentdata-api.com';
16
+ // The PAYMENT-REQUIRED header speaks x402 v2, where the field is `amount` and
17
+ // the network is CAIP-2. Only the 402 *body* still uses v1's
18
+ // `maxAmountRequired`. Reading the header and then asking for the v1 name
19
+ // yields undefined, and BigInt(undefined) throws — which meant this plugin
20
+ // could not complete a single payment in auto-pay mode. Resolve once.
21
+ const amountOf = (accept) => accept.amount ?? accept.maxAmountRequired;
22
+
23
+ const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
24
+
25
+ // ============ AUTO-PAY CLIENT ============
26
+
27
+ async function buildFetcher(runtime) {
28
+ const privateKey = runtime?.getSetting?.('AGENTDATA_BUYER_PRIVATE_KEY') || process.env.AGENTDATA_BUYER_PRIVATE_KEY;
29
+ if (!privateKey) return fetch;
30
+
31
+ try {
32
+ const { createWalletClient, createPublicClient, http } = await import('viem');
33
+ const { privateKeyToAccount } = await import('viem/accounts');
34
+ const { base } = await import('viem/chains');
35
+
36
+ const account = privateKeyToAccount(privateKey);
37
+ const walletClient = createWalletClient({ account, chain: base, transport: http() });
38
+
39
+ return async (url, options = {}) => {
40
+ const r1 = await fetch(url, options);
41
+ if (r1.status !== 402) return r1;
42
+
43
+ const header = r1.headers.get('payment-required');
44
+ if (!header) return r1;
45
+ const payload = JSON.parse(Buffer.from(header, 'base64').toString('utf8'));
46
+ const accept = payload.accepts[0];
47
+
48
+ const validAfter = 0;
49
+ const validBefore = Math.floor(Date.now() / 1000) + (accept.maxTimeoutSeconds || 300);
50
+ const nonce = '0x' + Array.from({length: 64}, () => Math.floor(Math.random() * 16).toString(16)).join('');
51
+
52
+ const signature = await walletClient.signTypedData({
53
+ account,
54
+ domain: { name: 'USD Coin', version: '2', chainId: 8453, verifyingContract: USDC },
55
+ types: {
56
+ TransferWithAuthorization: [
57
+ { name: 'from', type: 'address' }, { name: 'to', type: 'address' },
58
+ { name: 'value', type: 'uint256' }, { name: 'validAfter', type: 'uint256' },
59
+ { name: 'validBefore', type: 'uint256' }, { name: 'nonce', type: 'bytes32' },
60
+ ],
61
+ },
62
+ primaryType: 'TransferWithAuthorization',
63
+ message: {
64
+ from: account.address,
65
+ to: accept.payTo,
66
+ value: BigInt(amountOf(accept)),
67
+ validAfter: BigInt(validAfter),
68
+ validBefore: BigInt(validBefore),
69
+ nonce,
70
+ },
71
+ });
72
+
73
+ const paymentPayload = {
74
+ x402Version: 2, scheme: 'exact', network: accept.network,
75
+ payload: { signature, authorization: {
76
+ from: account.address, to: accept.payTo, value: amountOf(accept),
77
+ validAfter: String(validAfter), validBefore: String(validBefore), nonce,
78
+ }},
79
+ };
80
+ const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
81
+ return fetch(url, {
82
+ ...options,
83
+ headers: { ...options.headers, 'PAYMENT-SIGNATURE': paymentHeader, 'X-PAYMENT': paymentHeader },
84
+ });
85
+ };
86
+ } catch (e) {
87
+ console.error('[agentdata] Auto-pay disabled:', e.message);
88
+ return fetch;
89
+ }
90
+ }
91
+
92
+ async function callEndpoint(runtime, path, params = {}) {
93
+ const baseUrl = runtime?.getSetting?.('AGENTDATA_BASE_URL') || process.env.AGENTDATA_BASE_URL || BASE_URL_DEFAULT;
94
+ const url = new URL(baseUrl + path);
95
+ for (const [k, v] of Object.entries(params)) {
96
+ if (v !== undefined && v !== null) url.searchParams.set(k, String(v));
97
+ }
98
+ const fetcher = await buildFetcher(runtime);
99
+ const res = await fetcher(url.toString());
100
+ if (res.status === 402) {
101
+ const header = res.headers.get('payment-required');
102
+ let info = {};
103
+ if (header) { try { info = JSON.parse(Buffer.from(header, 'base64').toString('utf8')); } catch {} }
104
+ throw new Error(`Payment required. Set AGENTDATA_BUYER_PRIVATE_KEY to enable auto-pay. Accept: ${JSON.stringify(info.accepts?.[0] || {})}`);
105
+ }
106
+ if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
107
+ return res.json();
108
+ }
109
+
110
+ // ============ ACTIONS ============
111
+
112
+ const actions = [
113
+ // Listed first deliberately: these are the capabilities an agent cannot build
114
+ // for itself. It exists only while it runs, so it cannot wait, remember, or
115
+ // compare against its own last look. And a wired-up agent never re-reads the
116
+ // catalogue — whatever it will buy, it learns here, at integration time.
117
+ {
118
+ name: 'GET_CHANGES_SINCE_LAST_CALL',
119
+ similes: ['what changed', 'since last time', 'new data', 'delta', 'diff', 'updates'],
120
+ description: 'Fetch only what changed for a signal since this wallet last paid for it. Costs $0.001 USDC — cheaper than any full payload, and the server keeps the cursor so nothing is re-downloaded.',
121
+ validate: async () => true,
122
+ handler: async (runtime, message, state, options, callback) => {
123
+ const signal = options?.signal || 'sentiment';
124
+ const data = await callEndpoint(runtime, `/api/diff?signal=${encodeURIComponent(signal)}`);
125
+ const d = data.data || data;
126
+ const text = d.firstCall
127
+ ? `First look at ${signal}: ${d.newPoints} points from the last 24h.`
128
+ : `${d.newPoints} new ${signal} point(s) since your last paid call (${d.since}).`;
129
+ if (callback) callback({ text });
130
+ return text;
131
+ },
132
+ examples: [[
133
+ { user: 'user', content: { text: 'What changed in sentiment since I last checked?' }},
134
+ { user: 'agent', content: { text: 'Fetching only the new points.', action: 'GET_CHANGES_SINCE_LAST_CALL' }},
135
+ ]],
136
+ },
137
+
138
+ {
139
+ name: 'WATCH_CONDITION',
140
+ similes: ['alert me', 'notify when', 'watch for', 'tell me when', 'standing order'],
141
+ description: 'Register a standing condition on a signal and let the always-on server watch it. Costs $0.010 USDC for up to 168h. Poll the status free instead of paying for repeated data calls.',
142
+ validate: async () => true,
143
+ handler: async (runtime, message, state, options, callback) => {
144
+ const { signal = 'sentiment', op = 'above', threshold, subject, hours = 24 } = options || {};
145
+ if (threshold === undefined) throw new Error('threshold is required');
146
+ const q = new URLSearchParams({ signal, op, threshold: String(threshold), hours: String(hours) });
147
+ if (subject) q.set('subject', subject);
148
+ const data = await callEndpoint(runtime, `/api/watch?${q}`);
149
+ const d = data.data || data;
150
+ const text = `Watching ${signal} ${op} ${threshold} until ${d.expiresAt}. Note: it reports a CHANGE, so a condition already true fires on the next observation, not instantly.`;
151
+ if (callback) callback({ text });
152
+ return text;
153
+ },
154
+ examples: [[
155
+ { user: 'user', content: { text: 'Tell me when sentiment goes above 70.' }},
156
+ { user: 'agent', content: { text: 'Registering a watch on the server.', action: 'WATCH_CONDITION' }},
157
+ ]],
158
+ },
159
+
160
+ {
161
+ name: 'GET_SIGNAL_CALIBRATION',
162
+ similes: ['how accurate', 'track record', 'hit rate', 'is this reliable', 'calibration'],
163
+ description: 'FREE. How often these signals actually turned out right, scored against a naive baseline. Claims are recorded before the outcome exists. Worth reading before trusting any signal — including to see which ones do not yet justify their price.',
164
+ validate: async () => true,
165
+ handler: async (runtime, message, state, options, callback) => {
166
+ const days = options?.days || 30;
167
+ const data = await callEndpoint(runtime, `/calibration?days=${days}`);
168
+ const rows = (data.signals || []).map(x =>
169
+ `• ${x.signal}/${x.claim}: ${x.hitRate === null ? 'n/a' : (x.hitRate * 100).toFixed(1) + '%'} over ${x.resolved} resolved${x.beatsNaive === null ? '' : (x.beatsNaive ? ' (beats naive)' : ' (does NOT beat naive)')}`);
170
+ const text = rows.length ? `Signal track record:\n${rows.join('\n')}` : 'No resolved claims in this window yet.';
171
+ if (callback) callback({ text });
172
+ return text;
173
+ },
174
+ examples: [[
175
+ { user: 'user', content: { text: 'How reliable are these signals?' }},
176
+ { user: 'agent', content: { text: 'Reading the published track record.', action: 'GET_SIGNAL_CALIBRATION' }},
177
+ ]],
178
+ },
179
+
180
+ {
181
+ name: 'GET_CRYPTO_PRICES',
182
+ similes: ['crypto prices', 'bitcoin price', 'ethereum price', 'btc', 'eth price', 'current prices', 'market prices'],
183
+ description: 'Get real-time prices for BTC, ETH, SOL, BNB, XRP. Costs $0.002 USDC via x402.',
184
+ validate: async () => true,
185
+ handler: async (runtime, message, state, options, callback) => {
186
+ const data = await callEndpoint(runtime, '/api/prices');
187
+ const text = `Current crypto prices:\n${Object.entries(data.data).map(([sym, v]) => `• ${sym}: $${v.price}`).join('\n')}`;
188
+ if (callback) callback({ text });
189
+ return text;
190
+ },
191
+ examples: [[
192
+ { user: 'user', content: { text: 'What are the current crypto prices?' }},
193
+ { user: 'agent', content: { text: 'Let me check the current prices.', action: 'GET_CRYPTO_PRICES' }},
194
+ ]],
195
+ },
196
+
197
+ {
198
+ name: 'GET_FUNDING_RATES',
199
+ similes: ['funding rate', 'perpetuals', 'perp funding', 'longs vs shorts'],
200
+ description: 'Get perpetual futures funding rates with long/short bias signals. Costs $0.002 USDC.',
201
+ validate: async () => true,
202
+ handler: async (runtime, message, state, options, callback) => {
203
+ const data = await callEndpoint(runtime, '/api/funding-rates');
204
+ const lines = Object.entries(data.data).map(([s, v]) =>
205
+ `• ${s}: ${(v.rate * 100).toFixed(4)}% (${v.annualized} annualized, ${v.signal})`
206
+ );
207
+ const text = `Funding rates:\n${lines.join('\n')}`;
208
+ if (callback) callback({ text });
209
+ return text;
210
+ },
211
+ },
212
+
213
+ {
214
+ name: 'GET_MARKET_OVERVIEW',
215
+ similes: ['market overview', 'market sentiment', 'market state', 'how is the market'],
216
+ description: 'Full market overview with sentiment bias and arbitrage signals. Costs $0.003 USDC.',
217
+ validate: async () => true,
218
+ handler: async (runtime, message, state, options, callback) => {
219
+ const data = await callEndpoint(runtime, '/api/market-overview');
220
+ const s = data.data.signals;
221
+ const text = `Market Overview:\n• Bias: ${s.bias}\n• BTC: $${data.data.prices.BTCUSDT?.price}\n• ETH: $${data.data.prices.ETHUSDT?.price}\n• Arb opportunity: ${s.arbOpportunity ? 'YES' : 'no'}\n• Funding yield (annualized): ${s.fundingYieldAnnual}`;
222
+ if (callback) callback({ text });
223
+ return text;
224
+ },
225
+ },
226
+
227
+ {
228
+ name: 'GET_DEFI_YIELDS',
229
+ similes: ['defi yields', 'yield farming', 'best yields', 'usdc yield', 'stablecoin yield'],
230
+ description: 'Top DeFi yield opportunities from Aave, Compound, Morpho, Pendle. Costs $0.003 USDC.',
231
+ validate: async () => true,
232
+ handler: async (runtime, message, state, options, callback) => {
233
+ const data = await callEndpoint(runtime, '/api/defi-yields');
234
+ const top5 = (data.data.topStablecoinYields || []).slice(0, 5);
235
+ const lines = top5.map(p => `• ${p.project} (${p.chain}): ${p.apy}% APY on ${p.symbol} (TVL: $${(p.tvlUsd/1e6).toFixed(1)}M)`);
236
+ const text = `Top 5 Stablecoin Yields:\n${lines.join('\n')}`;
237
+ if (callback) callback({ text });
238
+ return text;
239
+ },
240
+ },
241
+
242
+ {
243
+ name: 'GET_ARBITRAGE_OPPORTUNITIES',
244
+ similes: ['arbitrage', 'arb', 'cross exchange spread', 'price difference'],
245
+ description: 'Cross-exchange arbitrage opportunities (MEXC/Binance/Bybit/OKX). Costs $0.005 USDC.',
246
+ validate: async () => true,
247
+ handler: async (runtime, message, state, options, callback) => {
248
+ const data = await callEndpoint(runtime, '/api/arbitrage-opportunities');
249
+ const opps = (data.data.opportunities || []).slice(0, 5);
250
+ if (!opps.length) return 'No significant arbitrage opportunities right now.';
251
+ const lines = opps.map(o => `• ${o.symbol}: buy on ${o.buyOn} @ $${o.buyPrice}, sell on ${o.sellOn} @ $${o.sellPrice} (${o.spreadPct}% spread${o.profitableAfterFees ? ' ✅ profitable' : ''})`);
252
+ const text = `Arbitrage Opportunities:\n${lines.join('\n')}`;
253
+ if (callback) callback({ text });
254
+ return text;
255
+ },
256
+ },
257
+
258
+ {
259
+ name: 'GET_TECHNICAL_INDICATORS',
260
+ similes: ['rsi', 'macd', 'bollinger', 'technical indicators', 'ta'],
261
+ description: 'Get RSI, MACD, Bollinger Bands, ATR for a symbol. Costs $0.003 USDC.',
262
+ validate: async () => true,
263
+ handler: async (runtime, message, state, options, callback) => {
264
+ const symbol = options?.symbol || state?.symbol || 'BTCUSDT';
265
+ const interval = options?.interval || '1h';
266
+ const data = await callEndpoint(runtime, '/api/indicators', { symbol, interval });
267
+ const i = data.data.indicators;
268
+ const text = `${symbol} ${interval} indicators:\n• RSI: ${i.rsi.value} (${i.rsi.signal})\n• MACD: ${i.macd.trend}\n• Bollinger: ${i.bollinger.signal} (${i.bollinger.positionPct}% of range)\n• ATR: ${i.atr.volatilityPct}`;
269
+ if (callback) callback({ text });
270
+ return text;
271
+ },
272
+ },
273
+
274
+ {
275
+ name: 'GET_SENTIMENT',
276
+ similes: ['fear and greed', 'sentiment', 'market mood'],
277
+ description: 'Composite market sentiment: Fear & Greed Index + Funding-based. Costs $0.002 USDC.',
278
+ validate: async () => true,
279
+ handler: async (runtime, message, state, options, callback) => {
280
+ const data = await callEndpoint(runtime, '/api/sentiment');
281
+ const text = `Market Sentiment:\n• Fear & Greed: ${data.data.fearGreedIndex.value} (${data.data.fearGreedIndex.classification})\n• Funding-based: ${data.data.fundingBasedSentiment}\n• Composite: ${data.data.compositeSentiment.value} (${data.data.compositeSentiment.classification})`;
282
+ if (callback) callback({ text });
283
+ return text;
284
+ },
285
+ },
286
+
287
+ {
288
+ name: 'GET_STABLECOIN_HEALTH',
289
+ similes: ['usdc peg', 'dai peg', 'depeg', 'stablecoin status'],
290
+ description: 'USDC/DAI peg monitoring + top 10 stablecoins. Costs $0.002 USDC.',
291
+ validate: async () => true,
292
+ handler: async (runtime, message, state, options, callback) => {
293
+ const data = await callEndpoint(runtime, '/api/stablecoin-health');
294
+ const peg = data.data.liveDepegCheck;
295
+ const text = `Stablecoin Health:\n• USDC: $${peg.USDC.price} (${peg.USDC.pegDeviation} off peg, ${peg.USDC.status})\n• DAI: $${peg.DAI.price} (${peg.DAI.pegDeviation} off peg, ${peg.DAI.status})\n• Total stablecoin market cap: $${(data.data.totalStablecoinMarketCap/1e9).toFixed(1)}B`;
296
+ if (callback) callback({ text });
297
+ return text;
298
+ },
299
+ },
300
+ ];
301
+
302
+ // ============ PROVIDERS (passive context injection) ============
303
+
304
+ const providers = [
305
+ {
306
+ name: 'agentdata_market_context',
307
+ description: 'Provides current crypto market context for every agent turn',
308
+ get: async (runtime, message) => {
309
+ try {
310
+ const data = await callEndpoint(runtime, '/api/market-overview');
311
+ return `[Market context] BTC: $${data.data.prices.BTCUSDT?.price}, ETH: $${data.data.prices.ETHUSDT?.price}, Sentiment: ${data.data.signals.bias}`;
312
+ } catch { return ''; }
313
+ },
314
+ },
315
+ ];
316
+
317
+ // ============ PLUGIN EXPORT ============
318
+
319
+ export const agentdataPlugin = {
320
+ name: '@agentdata/plugin-elizaos',
321
+ description: 'Real-time crypto market data for AI agents via x402 micropayments on Base',
322
+ actions,
323
+ providers,
324
+ services: [],
325
+ evaluators: [],
326
+ };
327
+
328
+ export default agentdataPlugin;
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@agentdata/plugin-elizaos",
3
+ "version": "1.1.0",
4
+ "description": "ElizaOS plugin for AgentData API — crypto market data via x402",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "keywords": [
8
+ "elizaos",
9
+ "x402",
10
+ "crypto",
11
+ "market-data",
12
+ "ai-agent"
13
+ ],
14
+ "author": "AgentData",
15
+ "license": "MIT",
16
+ "peerDependencies": {
17
+ "@elizaos/core": ">=1.0.0"
18
+ },
19
+ "files": [
20
+ "index.js",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/speteai/elizaos-plugin-agentdata.git"
30
+ },
31
+ "homepage": "https://agentdata-api.com",
32
+ "scripts": {
33
+ "check-catalogue": "node check-catalogue.mjs",
34
+ "prepublishOnly": "npm run check-catalogue"
35
+ }
36
+ }