@jhinresh/elizaos-plugin 0.1.1 → 0.2.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.
- package/dist/index.d.ts +78 -0
- package/dist/index.js +306 -0
- package/package.json +1 -1
- package/src/index.ts +191 -15
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @maiat/elizaos-plugin
|
|
3
|
+
*
|
|
4
|
+
* Maiat Trust Score plugin for ElizaOS (ai16z agent framework).
|
|
5
|
+
*
|
|
6
|
+
* V0.2.0 — Cold-start update:
|
|
7
|
+
* - CHECK_TRUST: Trust score lookup (existing)
|
|
8
|
+
* - SUBMIT_REVIEW: Submit reviews with Scarab staking
|
|
9
|
+
* - GET_INTERACTIONS: Discover wallet contract interactions
|
|
10
|
+
* - GET_PASSPORT: Reputation passport
|
|
11
|
+
* - DEFI_INFO: Query DeFi protocols
|
|
12
|
+
* - AGENT_INFO: Query AI agents
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { maiatPlugin } from "@maiat/elizaos-plugin";
|
|
17
|
+
*
|
|
18
|
+
* const agent = new ElizaAgent({
|
|
19
|
+
* plugins: [maiatPlugin({ minScore: 3.0 })],
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export interface MaiatElizaConfig {
|
|
24
|
+
apiUrl?: string;
|
|
25
|
+
apiKey?: string;
|
|
26
|
+
chain?: string;
|
|
27
|
+
minScore?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* ElizaOS plugin definition following the standard plugin interface.
|
|
31
|
+
*
|
|
32
|
+
* Registers:
|
|
33
|
+
* - Actions: CHECK_TRUST, SUBMIT_REVIEW, GET_INTERACTIONS, GET_PASSPORT, DEFI_INFO, AGENT_INFO
|
|
34
|
+
* - Evaluator: TRUST_GATE
|
|
35
|
+
* - Provider: TRUST_DATA
|
|
36
|
+
*/
|
|
37
|
+
export declare function maiatPlugin(config?: MaiatElizaConfig): {
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
actions: {
|
|
41
|
+
name: string;
|
|
42
|
+
description: string;
|
|
43
|
+
examples: string[];
|
|
44
|
+
validate: (message: string) => Promise<boolean>;
|
|
45
|
+
handler: (message: string) => Promise<{
|
|
46
|
+
text: string;
|
|
47
|
+
data?: undefined;
|
|
48
|
+
} | {
|
|
49
|
+
text: string;
|
|
50
|
+
data: any;
|
|
51
|
+
}>;
|
|
52
|
+
}[];
|
|
53
|
+
evaluators: {
|
|
54
|
+
name: string;
|
|
55
|
+
description: string;
|
|
56
|
+
handler: (context: {
|
|
57
|
+
address?: string;
|
|
58
|
+
}) => Promise<{
|
|
59
|
+
pass: boolean;
|
|
60
|
+
reason: string;
|
|
61
|
+
score?: undefined;
|
|
62
|
+
risk?: undefined;
|
|
63
|
+
} | {
|
|
64
|
+
pass: boolean;
|
|
65
|
+
score: number;
|
|
66
|
+
risk: string;
|
|
67
|
+
reason: string;
|
|
68
|
+
}>;
|
|
69
|
+
}[];
|
|
70
|
+
providers: {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
handler: () => Promise<{
|
|
74
|
+
text: string;
|
|
75
|
+
}>;
|
|
76
|
+
}[];
|
|
77
|
+
};
|
|
78
|
+
export default maiatPlugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @maiat/elizaos-plugin
|
|
3
|
+
*
|
|
4
|
+
* Maiat Trust Score plugin for ElizaOS (ai16z agent framework).
|
|
5
|
+
*
|
|
6
|
+
* V0.2.0 — Cold-start update:
|
|
7
|
+
* - CHECK_TRUST: Trust score lookup (existing)
|
|
8
|
+
* - SUBMIT_REVIEW: Submit reviews with Scarab staking
|
|
9
|
+
* - GET_INTERACTIONS: Discover wallet contract interactions
|
|
10
|
+
* - GET_PASSPORT: Reputation passport
|
|
11
|
+
* - DEFI_INFO: Query DeFi protocols
|
|
12
|
+
* - AGENT_INFO: Query AI agents
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { maiatPlugin } from "@maiat/elizaos-plugin";
|
|
17
|
+
*
|
|
18
|
+
* const agent = new ElizaAgent({
|
|
19
|
+
* plugins: [maiatPlugin({ minScore: 3.0 })],
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
// ═══════════════════════════════════════════
|
|
24
|
+
// API Client (lightweight)
|
|
25
|
+
// ═══════════════════════════════════════════
|
|
26
|
+
function getHeaders(config) {
|
|
27
|
+
const h = {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
"User-Agent": "maiat-elizaos-plugin/0.2.0",
|
|
30
|
+
};
|
|
31
|
+
if (config.apiKey)
|
|
32
|
+
h["Authorization"] = `Bearer ${config.apiKey}`;
|
|
33
|
+
return h;
|
|
34
|
+
}
|
|
35
|
+
function getApiUrl(config) {
|
|
36
|
+
return config.apiUrl || "https://maiat-protocol.vercel.app";
|
|
37
|
+
}
|
|
38
|
+
async function queryMaiat(address, config) {
|
|
39
|
+
const apiUrl = getApiUrl(config);
|
|
40
|
+
const chain = config.chain || "base";
|
|
41
|
+
const minScore = config.minScore ?? 3.0;
|
|
42
|
+
const res = await fetch(`${apiUrl}/api/v1/score/${address}?chain=${chain}`, {
|
|
43
|
+
headers: getHeaders(config),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
throw new Error(`Maiat API error: ${res.status}`);
|
|
47
|
+
}
|
|
48
|
+
const data = await res.json();
|
|
49
|
+
return {
|
|
50
|
+
address: data.address,
|
|
51
|
+
score: data.score,
|
|
52
|
+
risk: data.risk,
|
|
53
|
+
type: data.type,
|
|
54
|
+
flags: data.flags || [],
|
|
55
|
+
safe: data.score >= minScore,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// ═══════════════════════════════════════════
|
|
59
|
+
// ElizaOS Plugin
|
|
60
|
+
// ═══════════════════════════════════════════
|
|
61
|
+
/**
|
|
62
|
+
* ElizaOS plugin definition following the standard plugin interface.
|
|
63
|
+
*
|
|
64
|
+
* Registers:
|
|
65
|
+
* - Actions: CHECK_TRUST, SUBMIT_REVIEW, GET_INTERACTIONS, GET_PASSPORT, DEFI_INFO, AGENT_INFO
|
|
66
|
+
* - Evaluator: TRUST_GATE
|
|
67
|
+
* - Provider: TRUST_DATA
|
|
68
|
+
*/
|
|
69
|
+
export function maiatPlugin(config = {}) {
|
|
70
|
+
const apiUrl = getApiUrl(config);
|
|
71
|
+
const headers = getHeaders(config);
|
|
72
|
+
return {
|
|
73
|
+
name: "maiat-trust",
|
|
74
|
+
description: "Trust scoring for on-chain addresses via Maiat Protocol",
|
|
75
|
+
actions: [
|
|
76
|
+
// --- Existing: CHECK_TRUST ---
|
|
77
|
+
{
|
|
78
|
+
name: "CHECK_TRUST",
|
|
79
|
+
description: "Check the trust score of an on-chain address",
|
|
80
|
+
examples: [
|
|
81
|
+
"Is 0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24 safe?",
|
|
82
|
+
"Check trust score for 0x1234...",
|
|
83
|
+
"Should I interact with this address: 0xabcd...?",
|
|
84
|
+
],
|
|
85
|
+
validate: async (message) => {
|
|
86
|
+
return /0x[a-fA-F0-9]{40}/.test(message);
|
|
87
|
+
},
|
|
88
|
+
handler: async (message) => {
|
|
89
|
+
const match = message.match(/0x[a-fA-F0-9]{40}/);
|
|
90
|
+
if (!match)
|
|
91
|
+
return { text: "Please provide a valid Ethereum address (0x...)" };
|
|
92
|
+
try {
|
|
93
|
+
const result = await queryMaiat(match[0], config);
|
|
94
|
+
const emoji = result.safe ? "🟢" : result.risk === "CRITICAL" ? "🔴" : "🟡";
|
|
95
|
+
return {
|
|
96
|
+
text: `${emoji} **Trust Score: ${result.score}/10** (${result.risk} risk)\n\nAddress: \`${result.address}\`\nType: ${result.type}\nFlags: ${result.flags.join(", ") || "None"}\n\n${result.safe ? "✅ Safe to interact." : "⚠️ Exercise caution — low trust score."}`,
|
|
97
|
+
data: result,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
text: `❌ Could not check trust score: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
// --- NEW: SUBMIT_REVIEW ---
|
|
108
|
+
{
|
|
109
|
+
name: "SUBMIT_REVIEW",
|
|
110
|
+
description: "Submit a trust review for a contract. Costs 2 Scarab, earn 3-10 for quality.",
|
|
111
|
+
examples: [
|
|
112
|
+
"Review 0x833589... — rating 8, great stablecoin",
|
|
113
|
+
"Submit review: address 0xabc, rating 3, seems risky",
|
|
114
|
+
],
|
|
115
|
+
validate: async (message) => /0x[a-fA-F0-9]{40}/.test(message) && /\d/.test(message),
|
|
116
|
+
handler: async (message) => {
|
|
117
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
118
|
+
const ratingMatch = message.match(/rating\s*:?\s*(\d+)/i) || message.match(/(\d+)\s*\/\s*10/);
|
|
119
|
+
if (!addrMatch)
|
|
120
|
+
return { text: "Please provide a contract address (0x...)" };
|
|
121
|
+
const rating = ratingMatch ? Math.min(10, Math.max(1, parseInt(ratingMatch[1]))) : 5;
|
|
122
|
+
try {
|
|
123
|
+
const res = await fetch(`${apiUrl}/api/v1/review`, {
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers,
|
|
126
|
+
body: JSON.stringify({
|
|
127
|
+
address: addrMatch[0],
|
|
128
|
+
rating,
|
|
129
|
+
comment: message,
|
|
130
|
+
reviewer: "eliza-agent",
|
|
131
|
+
}),
|
|
132
|
+
});
|
|
133
|
+
const data = await res.json();
|
|
134
|
+
if (!res.ok)
|
|
135
|
+
throw new Error(data.error || `HTTP ${res.status}`);
|
|
136
|
+
return {
|
|
137
|
+
text: `✅ Review submitted!\n\n- Address: \`${addrMatch[0]}\`\n- Rating: ${rating}/10\n- Scarab earned: ${data.meta?.scarabReward || 0} 🪲`,
|
|
138
|
+
data,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return { text: `❌ Review failed: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
// --- NEW: GET_INTERACTIONS ---
|
|
147
|
+
{
|
|
148
|
+
name: "GET_INTERACTIONS",
|
|
149
|
+
description: "Discover which contracts a wallet has interacted with",
|
|
150
|
+
examples: [
|
|
151
|
+
"What contracts has 0x1234... interacted with?",
|
|
152
|
+
"Show interactions for 0xabcd...",
|
|
153
|
+
],
|
|
154
|
+
validate: async (message) => /0x[a-fA-F0-9]{40}/.test(message),
|
|
155
|
+
handler: async (message) => {
|
|
156
|
+
const match = message.match(/0x[a-fA-F0-9]{40}/);
|
|
157
|
+
if (!match)
|
|
158
|
+
return { text: "Please provide a wallet address." };
|
|
159
|
+
try {
|
|
160
|
+
const res = await fetch(`${apiUrl}/api/v1/wallet/${match[0]}/interactions`, { headers });
|
|
161
|
+
if (!res.ok)
|
|
162
|
+
throw new Error(`HTTP ${res.status}`);
|
|
163
|
+
const data = await res.json();
|
|
164
|
+
const list = data.interacted?.map((c) => ` • ${c.name} (${c.category}) — ${c.txCount} txs`).join("\n") || "None found";
|
|
165
|
+
return {
|
|
166
|
+
text: `📋 Wallet Interactions (${data.interactedCount} contracts):\n\n${list}`,
|
|
167
|
+
data,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
// --- NEW: GET_PASSPORT ---
|
|
176
|
+
{
|
|
177
|
+
name: "GET_PASSPORT",
|
|
178
|
+
description: "Get a wallet's reputation passport",
|
|
179
|
+
examples: [
|
|
180
|
+
"Show passport for 0x1234...",
|
|
181
|
+
"What's my reputation level?",
|
|
182
|
+
],
|
|
183
|
+
validate: async (message) => /0x[a-fA-F0-9]{40}/.test(message),
|
|
184
|
+
handler: async (message) => {
|
|
185
|
+
const match = message.match(/0x[a-fA-F0-9]{40}/);
|
|
186
|
+
if (!match)
|
|
187
|
+
return { text: "Please provide a wallet address." };
|
|
188
|
+
try {
|
|
189
|
+
const res = await fetch(`${apiUrl}/api/v1/wallet/${match[0]}/passport`, { headers });
|
|
190
|
+
if (!res.ok)
|
|
191
|
+
throw new Error(`HTTP ${res.status}`);
|
|
192
|
+
const data = await res.json();
|
|
193
|
+
const p = data.passport;
|
|
194
|
+
return {
|
|
195
|
+
text: `🛡️ Reputation Passport\n\n- Trust Level: ${p.trustLevel.toUpperCase()}\n- Reputation: ${p.reputationScore}\n- Reviews: ${p.totalReviews}\n- Scarab: ${data.scarab?.balance || 0} 🪲\n- Fee Tier: ${p.feeTier.discount}`,
|
|
196
|
+
data,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
// --- NEW: DEFI_INFO ---
|
|
205
|
+
{
|
|
206
|
+
name: "DEFI_INFO",
|
|
207
|
+
description: "Look up a DeFi protocol by name or address",
|
|
208
|
+
examples: [
|
|
209
|
+
"Tell me about USDC",
|
|
210
|
+
"What's the trust score for Aerodrome?",
|
|
211
|
+
"Look up 0x833589...",
|
|
212
|
+
],
|
|
213
|
+
validate: async (message) => true,
|
|
214
|
+
handler: async (message) => {
|
|
215
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
216
|
+
const slugMatch = message.match(/\b(usdc|weth|dai|aerodrome|aave|compound|morpho|uniswap|chainlink|stargate)\b/i);
|
|
217
|
+
const query = addrMatch?.[0] || slugMatch?.[0]?.toLowerCase();
|
|
218
|
+
if (!query)
|
|
219
|
+
return { text: "Please specify a DeFi protocol name (e.g. USDC, Aave) or address." };
|
|
220
|
+
try {
|
|
221
|
+
const res = await fetch(`${apiUrl}/api/v1/defi/${query}`, { headers });
|
|
222
|
+
if (!res.ok)
|
|
223
|
+
throw new Error(res.status === 404 ? `"${query}" not found` : `HTTP ${res.status}`);
|
|
224
|
+
const data = await res.json();
|
|
225
|
+
const e = data.entity;
|
|
226
|
+
return {
|
|
227
|
+
text: `📊 ${e.name}\n\n- Address: \`${e.address}\`\n- Category: ${e.category}\n- Trust: ${data.trust?.score ?? "N/A"}/10\n- Reviews: ${data.reviews?.total || 0}`,
|
|
228
|
+
data,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
// --- NEW: AGENT_INFO ---
|
|
237
|
+
{
|
|
238
|
+
name: "AGENT_INFO",
|
|
239
|
+
description: "Look up an AI agent by name or address",
|
|
240
|
+
examples: [
|
|
241
|
+
"Tell me about AIXBT",
|
|
242
|
+
"What's Virtuals trust score?",
|
|
243
|
+
"Look up agent 0x4f9fd6...",
|
|
244
|
+
],
|
|
245
|
+
validate: async (message) => true,
|
|
246
|
+
handler: async (message) => {
|
|
247
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
248
|
+
const slugMatch = message.match(/\b(aixbt|virtuals|luna|vaderai|freysa|sekoia)\b/i);
|
|
249
|
+
const query = addrMatch?.[0] || slugMatch?.[0]?.toLowerCase();
|
|
250
|
+
if (!query)
|
|
251
|
+
return { text: "Please specify an agent name (e.g. AIXBT, Virtuals) or address." };
|
|
252
|
+
try {
|
|
253
|
+
const res = await fetch(`${apiUrl}/api/v1/agent/${query}`, { headers });
|
|
254
|
+
if (!res.ok)
|
|
255
|
+
throw new Error(res.status === 404 ? `"${query}" not found` : `HTTP ${res.status}`);
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
const e = data.entity;
|
|
258
|
+
return {
|
|
259
|
+
text: `🤖 ${e.name}\n\n- Address: \`${e.address}\`\n- Category: ${e.category}\n- Trust: ${data.trust?.score ?? "N/A"}/10\n- Reviews: ${data.reviews?.total || 0}`,
|
|
260
|
+
data,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
evaluators: [
|
|
270
|
+
{
|
|
271
|
+
name: "TRUST_GATE",
|
|
272
|
+
description: "Evaluates if a target address meets minimum trust requirements",
|
|
273
|
+
handler: async (context) => {
|
|
274
|
+
if (!context.address)
|
|
275
|
+
return { pass: true, reason: "No address to check" };
|
|
276
|
+
try {
|
|
277
|
+
const result = await queryMaiat(context.address, config);
|
|
278
|
+
return {
|
|
279
|
+
pass: result.safe,
|
|
280
|
+
score: result.score,
|
|
281
|
+
risk: result.risk,
|
|
282
|
+
reason: result.safe
|
|
283
|
+
? `Address trusted (${result.score}/10)`
|
|
284
|
+
: `Address untrusted (${result.score}/10, ${result.risk} risk)`,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return { pass: false, reason: "Trust check failed — blocking by default" };
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
providers: [
|
|
294
|
+
{
|
|
295
|
+
name: "TRUST_DATA",
|
|
296
|
+
description: "Provides trust scoring context for agent reasoning",
|
|
297
|
+
handler: async () => {
|
|
298
|
+
return {
|
|
299
|
+
text: "You have Maiat trust scoring. Use CHECK_TRUST for address safety, SUBMIT_REVIEW to review contracts, GET_INTERACTIONS to discover wallet activity, GET_PASSPORT for reputation, DEFI_INFO/AGENT_INFO to look up protocols and agents.",
|
|
300
|
+
};
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
export default maiatPlugin;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Maiat Trust Score plugin for ElizaOS (ai16z agent framework).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
6
|
+
* V0.2.0 — Cold-start update:
|
|
7
|
+
* - CHECK_TRUST: Trust score lookup (existing)
|
|
8
|
+
* - SUBMIT_REVIEW: Submit reviews with Scarab staking
|
|
9
|
+
* - GET_INTERACTIONS: Discover wallet contract interactions
|
|
10
|
+
* - GET_PASSPORT: Reputation passport
|
|
11
|
+
* - DEFI_INFO: Query DeFi protocols
|
|
12
|
+
* - AGENT_INFO: Query AI agents
|
|
10
13
|
*
|
|
11
14
|
* @example
|
|
12
15
|
* ```typescript
|
|
@@ -42,20 +45,30 @@ interface TrustResult {
|
|
|
42
45
|
// API Client (lightweight)
|
|
43
46
|
// ═══════════════════════════════════════════
|
|
44
47
|
|
|
48
|
+
function getHeaders(config: MaiatElizaConfig): Record<string, string> {
|
|
49
|
+
const h: Record<string, string> = {
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
"User-Agent": "maiat-elizaos-plugin/0.2.0",
|
|
52
|
+
};
|
|
53
|
+
if (config.apiKey) h["Authorization"] = `Bearer ${config.apiKey}`;
|
|
54
|
+
return h;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getApiUrl(config: MaiatElizaConfig): string {
|
|
58
|
+
return config.apiUrl || "https://maiat-protocol.vercel.app";
|
|
59
|
+
}
|
|
60
|
+
|
|
45
61
|
async function queryMaiat(
|
|
46
62
|
address: string,
|
|
47
63
|
config: MaiatElizaConfig
|
|
48
64
|
): Promise<TrustResult> {
|
|
49
|
-
const apiUrl = config
|
|
65
|
+
const apiUrl = getApiUrl(config);
|
|
50
66
|
const chain = config.chain || "base";
|
|
51
67
|
const minScore = config.minScore ?? 3.0;
|
|
52
68
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
if (config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
57
|
-
|
|
58
|
-
const res = await fetch(`${apiUrl}/api/v1/score/${address}?chain=${chain}`, { headers });
|
|
69
|
+
const res = await fetch(`${apiUrl}/api/v1/score/${address}?chain=${chain}`, {
|
|
70
|
+
headers: getHeaders(config),
|
|
71
|
+
});
|
|
59
72
|
|
|
60
73
|
if (!res.ok) {
|
|
61
74
|
throw new Error(`Maiat API error: ${res.status}`);
|
|
@@ -80,16 +93,20 @@ async function queryMaiat(
|
|
|
80
93
|
* ElizaOS plugin definition following the standard plugin interface.
|
|
81
94
|
*
|
|
82
95
|
* Registers:
|
|
83
|
-
* -
|
|
84
|
-
* - Evaluator: TRUST_GATE
|
|
85
|
-
* - Provider: TRUST_DATA
|
|
96
|
+
* - Actions: CHECK_TRUST, SUBMIT_REVIEW, GET_INTERACTIONS, GET_PASSPORT, DEFI_INFO, AGENT_INFO
|
|
97
|
+
* - Evaluator: TRUST_GATE
|
|
98
|
+
* - Provider: TRUST_DATA
|
|
86
99
|
*/
|
|
87
100
|
export function maiatPlugin(config: MaiatElizaConfig = {}) {
|
|
101
|
+
const apiUrl = getApiUrl(config);
|
|
102
|
+
const headers = getHeaders(config);
|
|
103
|
+
|
|
88
104
|
return {
|
|
89
105
|
name: "maiat-trust",
|
|
90
106
|
description: "Trust scoring for on-chain addresses via Maiat Protocol",
|
|
91
107
|
|
|
92
108
|
actions: [
|
|
109
|
+
// --- Existing: CHECK_TRUST ---
|
|
93
110
|
{
|
|
94
111
|
name: "CHECK_TRUST",
|
|
95
112
|
description: "Check the trust score of an on-chain address",
|
|
@@ -120,6 +137,165 @@ export function maiatPlugin(config: MaiatElizaConfig = {}) {
|
|
|
120
137
|
}
|
|
121
138
|
},
|
|
122
139
|
},
|
|
140
|
+
// --- NEW: SUBMIT_REVIEW ---
|
|
141
|
+
{
|
|
142
|
+
name: "SUBMIT_REVIEW",
|
|
143
|
+
description: "Submit a trust review for a contract. Costs 2 Scarab, earn 3-10 for quality.",
|
|
144
|
+
examples: [
|
|
145
|
+
"Review 0x833589... — rating 8, great stablecoin",
|
|
146
|
+
"Submit review: address 0xabc, rating 3, seems risky",
|
|
147
|
+
],
|
|
148
|
+
validate: async (message: string) => /0x[a-fA-F0-9]{40}/.test(message) && /\d/.test(message),
|
|
149
|
+
handler: async (message: string) => {
|
|
150
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
151
|
+
const ratingMatch = message.match(/rating\s*:?\s*(\d+)/i) || message.match(/(\d+)\s*\/\s*10/);
|
|
152
|
+
if (!addrMatch) return { text: "Please provide a contract address (0x...)" };
|
|
153
|
+
const rating = ratingMatch ? Math.min(10, Math.max(1, parseInt(ratingMatch[1]))) : 5;
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const res = await fetch(`${apiUrl}/api/v1/review`, {
|
|
157
|
+
method: "POST",
|
|
158
|
+
headers,
|
|
159
|
+
body: JSON.stringify({
|
|
160
|
+
address: addrMatch[0],
|
|
161
|
+
rating,
|
|
162
|
+
comment: message,
|
|
163
|
+
reviewer: "eliza-agent",
|
|
164
|
+
}),
|
|
165
|
+
});
|
|
166
|
+
const data = await res.json();
|
|
167
|
+
if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
text: `✅ Review submitted!\n\n- Address: \`${addrMatch[0]}\`\n- Rating: ${rating}/10\n- Scarab earned: ${data.meta?.scarabReward || 0} 🪲`,
|
|
171
|
+
data,
|
|
172
|
+
};
|
|
173
|
+
} catch (error) {
|
|
174
|
+
return { text: `❌ Review failed: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
// --- NEW: GET_INTERACTIONS ---
|
|
179
|
+
{
|
|
180
|
+
name: "GET_INTERACTIONS",
|
|
181
|
+
description: "Discover which contracts a wallet has interacted with",
|
|
182
|
+
examples: [
|
|
183
|
+
"What contracts has 0x1234... interacted with?",
|
|
184
|
+
"Show interactions for 0xabcd...",
|
|
185
|
+
],
|
|
186
|
+
validate: async (message: string) => /0x[a-fA-F0-9]{40}/.test(message),
|
|
187
|
+
handler: async (message: string) => {
|
|
188
|
+
const match = message.match(/0x[a-fA-F0-9]{40}/);
|
|
189
|
+
if (!match) return { text: "Please provide a wallet address." };
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const res = await fetch(`${apiUrl}/api/v1/wallet/${match[0]}/interactions`, { headers });
|
|
193
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
194
|
+
const data = await res.json();
|
|
195
|
+
|
|
196
|
+
const list = data.interacted?.map((c: { name: string; category: string; txCount: number }) =>
|
|
197
|
+
` • ${c.name} (${c.category}) — ${c.txCount} txs`
|
|
198
|
+
).join("\n") || "None found";
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
text: `📋 Wallet Interactions (${data.interactedCount} contracts):\n\n${list}`,
|
|
202
|
+
data,
|
|
203
|
+
};
|
|
204
|
+
} catch (error) {
|
|
205
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
// --- NEW: GET_PASSPORT ---
|
|
210
|
+
{
|
|
211
|
+
name: "GET_PASSPORT",
|
|
212
|
+
description: "Get a wallet's reputation passport",
|
|
213
|
+
examples: [
|
|
214
|
+
"Show passport for 0x1234...",
|
|
215
|
+
"What's my reputation level?",
|
|
216
|
+
],
|
|
217
|
+
validate: async (message: string) => /0x[a-fA-F0-9]{40}/.test(message),
|
|
218
|
+
handler: async (message: string) => {
|
|
219
|
+
const match = message.match(/0x[a-fA-F0-9]{40}/);
|
|
220
|
+
if (!match) return { text: "Please provide a wallet address." };
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const res = await fetch(`${apiUrl}/api/v1/wallet/${match[0]}/passport`, { headers });
|
|
224
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
225
|
+
const data = await res.json();
|
|
226
|
+
|
|
227
|
+
const p = data.passport;
|
|
228
|
+
return {
|
|
229
|
+
text: `🛡️ Reputation Passport\n\n- Trust Level: ${p.trustLevel.toUpperCase()}\n- Reputation: ${p.reputationScore}\n- Reviews: ${p.totalReviews}\n- Scarab: ${data.scarab?.balance || 0} 🪲\n- Fee Tier: ${p.feeTier.discount}`,
|
|
230
|
+
data,
|
|
231
|
+
};
|
|
232
|
+
} catch (error) {
|
|
233
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
// --- NEW: DEFI_INFO ---
|
|
238
|
+
{
|
|
239
|
+
name: "DEFI_INFO",
|
|
240
|
+
description: "Look up a DeFi protocol by name or address",
|
|
241
|
+
examples: [
|
|
242
|
+
"Tell me about USDC",
|
|
243
|
+
"What's the trust score for Aerodrome?",
|
|
244
|
+
"Look up 0x833589...",
|
|
245
|
+
],
|
|
246
|
+
validate: async (message: string) => true,
|
|
247
|
+
handler: async (message: string) => {
|
|
248
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
249
|
+
const slugMatch = message.match(/\b(usdc|weth|dai|aerodrome|aave|compound|morpho|uniswap|chainlink|stargate)\b/i);
|
|
250
|
+
const query = addrMatch?.[0] || slugMatch?.[0]?.toLowerCase();
|
|
251
|
+
if (!query) return { text: "Please specify a DeFi protocol name (e.g. USDC, Aave) or address." };
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
const res = await fetch(`${apiUrl}/api/v1/defi/${query}`, { headers });
|
|
255
|
+
if (!res.ok) throw new Error(res.status === 404 ? `"${query}" not found` : `HTTP ${res.status}`);
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
const e = data.entity;
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
text: `📊 ${e.name}\n\n- Address: \`${e.address}\`\n- Category: ${e.category}\n- Trust: ${data.trust?.score ?? "N/A"}/10\n- Reviews: ${data.reviews?.total || 0}`,
|
|
261
|
+
data,
|
|
262
|
+
};
|
|
263
|
+
} catch (error) {
|
|
264
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
// --- NEW: AGENT_INFO ---
|
|
269
|
+
{
|
|
270
|
+
name: "AGENT_INFO",
|
|
271
|
+
description: "Look up an AI agent by name or address",
|
|
272
|
+
examples: [
|
|
273
|
+
"Tell me about AIXBT",
|
|
274
|
+
"What's Virtuals trust score?",
|
|
275
|
+
"Look up agent 0x4f9fd6...",
|
|
276
|
+
],
|
|
277
|
+
validate: async (message: string) => true,
|
|
278
|
+
handler: async (message: string) => {
|
|
279
|
+
const addrMatch = message.match(/0x[a-fA-F0-9]{40}/);
|
|
280
|
+
const slugMatch = message.match(/\b(aixbt|virtuals|luna|vaderai|freysa|sekoia)\b/i);
|
|
281
|
+
const query = addrMatch?.[0] || slugMatch?.[0]?.toLowerCase();
|
|
282
|
+
if (!query) return { text: "Please specify an agent name (e.g. AIXBT, Virtuals) or address." };
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const res = await fetch(`${apiUrl}/api/v1/agent/${query}`, { headers });
|
|
286
|
+
if (!res.ok) throw new Error(res.status === 404 ? `"${query}" not found` : `HTTP ${res.status}`);
|
|
287
|
+
const data = await res.json();
|
|
288
|
+
const e = data.entity;
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
text: `🤖 ${e.name}\n\n- Address: \`${e.address}\`\n- Category: ${e.category}\n- Trust: ${data.trust?.score ?? "N/A"}/10\n- Reviews: ${data.reviews?.total || 0}`,
|
|
292
|
+
data,
|
|
293
|
+
};
|
|
294
|
+
} catch (error) {
|
|
295
|
+
return { text: `❌ Error: ${error instanceof Error ? error.message : "Unknown error"}` };
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
},
|
|
123
299
|
],
|
|
124
300
|
|
|
125
301
|
evaluators: [
|
|
@@ -152,7 +328,7 @@ export function maiatPlugin(config: MaiatElizaConfig = {}) {
|
|
|
152
328
|
description: "Provides trust scoring context for agent reasoning",
|
|
153
329
|
handler: async () => {
|
|
154
330
|
return {
|
|
155
|
-
text: "You have
|
|
331
|
+
text: "You have Maiat trust scoring. Use CHECK_TRUST for address safety, SUBMIT_REVIEW to review contracts, GET_INTERACTIONS to discover wallet activity, GET_PASSPORT for reputation, DEFI_INFO/AGENT_INFO to look up protocols and agents.",
|
|
156
332
|
};
|
|
157
333
|
},
|
|
158
334
|
},
|