@wzrd_sol/eliza-plugin 0.1.2 → 0.3.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 (38) hide show
  1. package/README.md +98 -26
  2. package/dist/actions/claim.d.ts +2 -5
  3. package/dist/actions/claim.js +33 -30
  4. package/dist/actions/earn.d.ts +8 -0
  5. package/dist/actions/earn.js +83 -0
  6. package/dist/actions/infer.d.ts +8 -0
  7. package/dist/actions/infer.js +41 -0
  8. package/dist/actions/intel-preflight.d.ts +5 -0
  9. package/dist/actions/intel-preflight.js +97 -0
  10. package/dist/actions/intel-trust.d.ts +7 -0
  11. package/dist/actions/intel-trust.js +82 -0
  12. package/dist/actions/report.d.ts +8 -0
  13. package/dist/actions/report.js +45 -0
  14. package/dist/actions/rewards.d.ts +5 -0
  15. package/dist/actions/rewards.js +31 -0
  16. package/dist/actions/verify-receipt.d.ts +7 -0
  17. package/dist/actions/verify-receipt.js +44 -0
  18. package/dist/client-factory.d.ts +14 -0
  19. package/dist/client-factory.js +40 -0
  20. package/dist/client.d.ts +91 -3
  21. package/dist/client.js +136 -16
  22. package/dist/index.d.ts +26 -9
  23. package/dist/index.js +25 -9
  24. package/dist/intel-helpers.d.ts +22 -0
  25. package/dist/intel-helpers.js +181 -0
  26. package/dist/paying-fetch.d.ts +9 -0
  27. package/dist/paying-fetch.js +27 -0
  28. package/dist/test/plugin-registration.intel.d.ts +1 -0
  29. package/dist/test/plugin-registration.intel.js +253 -0
  30. package/package.json +21 -10
  31. package/dist/actions/deposit.d.ts +0 -2
  32. package/dist/actions/deposit.js +0 -79
  33. package/dist/actions/leaderboard.d.ts +0 -3
  34. package/dist/actions/leaderboard.js +0 -25
  35. package/dist/actions/portfolio.d.ts +0 -3
  36. package/dist/actions/portfolio.js +0 -20
  37. package/dist/actions/velocity.d.ts +0 -3
  38. package/dist/actions/velocity.js +0 -57
@@ -0,0 +1,181 @@
1
+ import { intelTrustUrl, } from '@wzrd_sol/sdk';
2
+ const DEFAULT_INTEL = 'https://intel.twzrd.xyz';
3
+ export function getIntelBase(runtime) {
4
+ const url = runtime.getSetting('WZRD_INTEL_URL');
5
+ return typeof url === 'string' && url.length > 0 ? url : DEFAULT_INTEL;
6
+ }
7
+ /** Pull structured fields from Eliza message content (flat or JSON-in-text). */
8
+ export function parsePreflightInput(content) {
9
+ const direct = {
10
+ resource_name: str(content.resource_name),
11
+ seller_wallet: str(content.seller_wallet ?? content.pubkey ?? content.wallet),
12
+ resource_url: str(content.resource_url ?? content.url),
13
+ price_usdc: num(content.price_usdc ?? content.price),
14
+ buyer_wallet: str(content.buyer_wallet),
15
+ agent_intent: str(content.agent_intent ?? content.intent),
16
+ marketplace_score: num(content.marketplace_score),
17
+ };
18
+ const text = str(content.text);
19
+ if (text) {
20
+ const fromJson = tryParseJson(text);
21
+ if (fromJson)
22
+ return { ...direct, ...pickPreflight(fromJson) };
23
+ const wallet = extractWallet(text);
24
+ if (wallet && !direct.seller_wallet)
25
+ direct.seller_wallet = wallet;
26
+ if (!direct.agent_intent)
27
+ direct.agent_intent = text;
28
+ }
29
+ return compactPreflight(direct);
30
+ }
31
+ export function parseReceipt(content) {
32
+ if (content.receipt && typeof content.receipt === 'object') {
33
+ return content.receipt;
34
+ }
35
+ const text = str(content.text);
36
+ if (!text)
37
+ return null;
38
+ const parsed = tryParseJson(text);
39
+ if (parsed && typeof parsed === 'object' && 'leaf' in parsed && 'preimage' in parsed) {
40
+ return parsed;
41
+ }
42
+ return null;
43
+ }
44
+ export function extractPubkey(content) {
45
+ const direct = str(content.pubkey ?? content.seller_wallet ?? content.wallet);
46
+ if (direct)
47
+ return direct;
48
+ const text = str(content.text);
49
+ if (!text)
50
+ return null;
51
+ const fromJson = tryParseJson(text);
52
+ if (fromJson) {
53
+ const w = str(fromJson.pubkey ?? fromJson.seller_wallet ?? fromJson.wallet);
54
+ if (w)
55
+ return w;
56
+ }
57
+ return extractWallet(text);
58
+ }
59
+ export function formatPaymentRequired(err, apiBase, pubkey) {
60
+ const url = intelTrustUrl(pubkey, apiBase);
61
+ const reqs = err.paymentRequirements;
62
+ const accepts = reqs && typeof reqs === 'object' && 'accepts' in reqs && Array.isArray(reqs.accepts)
63
+ ? reqs.accepts[0]
64
+ : null;
65
+ const amount = accepts?.amount ?? '50000';
66
+ const payTo = accepts?.payTo ?? '(see accepts)';
67
+ const network = accepts?.network ?? 'solana';
68
+ return (`Intel trust requires x402 payment (~0.05 USDC).\n` +
69
+ `Endpoint: ${url}\n` +
70
+ `Network: ${network}, amount (atomic): ${amount}, payTo: ${payTo}\n\n` +
71
+ `No paying fetch configured. Wire one before runtime creation:\n` +
72
+ ` import { setPayingFetch } from '@wzrd_sol/eliza-plugin';\n` +
73
+ ` setPayingFetch(myAgentcashFetch);\n\n` +
74
+ `Or pay out of band:\n` +
75
+ ` npx agentcash@latest fetch ${url}`);
76
+ }
77
+ function str(v) {
78
+ if (typeof v === 'string' && v.trim())
79
+ return v.trim();
80
+ return undefined;
81
+ }
82
+ function num(v) {
83
+ if (typeof v === 'number' && Number.isFinite(v))
84
+ return v;
85
+ if (typeof v === 'string' && v.trim()) {
86
+ const n = Number(v);
87
+ if (Number.isFinite(n))
88
+ return n;
89
+ }
90
+ return undefined;
91
+ }
92
+ function tryParseJson(text) {
93
+ const trimmed = text.trim();
94
+ if (!trimmed.startsWith('{'))
95
+ return null;
96
+ try {
97
+ const v = JSON.parse(trimmed);
98
+ return v && typeof v === 'object' ? v : null;
99
+ }
100
+ catch {
101
+ return null;
102
+ }
103
+ }
104
+ function extractWallet(text) {
105
+ const m = text.match(/[1-9A-HJ-NP-Za-km-z]{32,44}/);
106
+ return m ? m[0] : null;
107
+ }
108
+ function pickPreflight(obj) {
109
+ return compactPreflight({
110
+ resource_name: str(obj.resource_name),
111
+ seller_wallet: str(obj.seller_wallet ?? obj.pubkey ?? obj.wallet),
112
+ resource_url: str(obj.resource_url ?? obj.url),
113
+ price_usdc: num(obj.price_usdc ?? obj.price),
114
+ buyer_wallet: str(obj.buyer_wallet),
115
+ agent_intent: str(obj.agent_intent ?? obj.intent),
116
+ marketplace_score: num(obj.marketplace_score),
117
+ });
118
+ }
119
+ function compactPreflight(input) {
120
+ const out = {};
121
+ if (input.resource_name)
122
+ out.resource_name = input.resource_name;
123
+ if (input.seller_wallet)
124
+ out.seller_wallet = input.seller_wallet;
125
+ if (input.resource_url)
126
+ out.resource_url = input.resource_url;
127
+ if (input.price_usdc !== undefined)
128
+ out.price_usdc = input.price_usdc;
129
+ if (input.buyer_wallet)
130
+ out.buyer_wallet = input.buyer_wallet;
131
+ if (input.agent_intent)
132
+ out.agent_intent = input.agent_intent;
133
+ if (input.marketplace_score !== undefined)
134
+ out.marketplace_score = input.marketplace_score;
135
+ return out;
136
+ }
137
+ /**
138
+ * Timeout wrapper for SDK network calls (preflight/trust/verify).
139
+ * Supports two call forms for minimal change:
140
+ * - withTimeout(promise) for preflight (SDK does not expose fetchImpl/signal)
141
+ * - withTimeout((signal) => sdkCallWithFetchImpl(abortingFetch)) for trust/verify
142
+ * Uses AbortController + signal: abort() is called on timeout so that when caller
143
+ * wires the returned signal into fetchImpl, the underlying network request is aborted.
144
+ * Always clears timer in finally (no leak). Attaches rejection observer to the
145
+ * call promise (without altering settlement) to avoid unhandled rejections on the
146
+ * loser of the race.
147
+ * Applied to actions + getIntelClient delegates.
148
+ */
149
+ export function withTimeout(pOrMake, ms = 8000) {
150
+ if (typeof pOrMake === 'function') {
151
+ const makeCall = pOrMake;
152
+ const controller = new AbortController();
153
+ let timer;
154
+ const timeoutP = new Promise((_, reject) => {
155
+ timer = setTimeout(() => {
156
+ controller.abort();
157
+ reject(new Error('timeout'));
158
+ }, ms);
159
+ });
160
+ const callP = makeCall(controller.signal);
161
+ // Observe rejections on callP so a late rejection after timeout does not emit unhandledrejection.
162
+ callP.then(undefined, () => { });
163
+ return Promise.race([callP, timeoutP]).finally(() => {
164
+ if (timer !== undefined)
165
+ clearTimeout(timer);
166
+ });
167
+ }
168
+ // legacy path (promise passed directly): still safe timeout + no unhandled + clear
169
+ const p = pOrMake;
170
+ let timer;
171
+ const timeoutP = new Promise((_, reject) => {
172
+ timer = setTimeout(() => {
173
+ reject(new Error('timeout'));
174
+ }, ms);
175
+ });
176
+ p.then(undefined, () => { });
177
+ return Promise.race([p, timeoutP]).finally(() => {
178
+ if (timer !== undefined)
179
+ clearTimeout(timer);
180
+ });
181
+ }
@@ -0,0 +1,9 @@
1
+ /** x402-capable fetch injection for paid intel actions. No embedded wallet. */
2
+ import type { IAgentRuntime } from '@elizaos/core';
3
+ /** Host supplies an x402-capable fetch (agentcash, twzrd-x402-gate, etc.) before runtime creation. */
4
+ export declare function setPayingFetch(f: typeof fetch): void;
5
+ export declare function clearPayingFetch(): void;
6
+ type FetchLike = typeof fetch;
7
+ /** Resolve paying fetch: module setter > runtime service > runtime.fetch > global fetch. */
8
+ export declare function resolvePayingFetch(runtime: IAgentRuntime): FetchLike;
9
+ export {};
@@ -0,0 +1,27 @@
1
+ let modulePayingFetch = null;
2
+ /** Host supplies an x402-capable fetch (agentcash, twzrd-x402-gate, etc.) before runtime creation. */
3
+ export function setPayingFetch(f) {
4
+ modulePayingFetch = f;
5
+ }
6
+ export function clearPayingFetch() {
7
+ modulePayingFetch = null;
8
+ }
9
+ function serviceFetch(runtime) {
10
+ for (const name of ['x402', 'payingFetch', 'agentcash']) {
11
+ const svc = runtime.getService(name);
12
+ if (svc?.fetch && typeof svc.fetch === 'function')
13
+ return svc.fetch;
14
+ }
15
+ return null;
16
+ }
17
+ /** Resolve paying fetch: module setter > runtime service > runtime.fetch > global fetch. */
18
+ export function resolvePayingFetch(runtime) {
19
+ if (modulePayingFetch)
20
+ return modulePayingFetch;
21
+ const fromSvc = serviceFetch(runtime);
22
+ if (fromSvc)
23
+ return fromSvc;
24
+ if (runtime.fetch && typeof runtime.fetch === 'function')
25
+ return runtime.fetch;
26
+ return globalThis.fetch;
27
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Real E2E: load wzrdPlugin via @elizaos/core AgentRuntime (critical missing piece per plan).
3
+ * Constructs minimal runtime with plugins:[wzrdPlugin]; asserts intel action names present;
4
+ * invokes handlers w/ mock Memory (preflight uses seller_wallet/price/resource_name);
5
+ * paid path: injected mock paying fetch that returns fake IntelTrustResponse w/ receipt;
6
+ * verifies callback contains decision/score/ALLOW etc + success result.
7
+ * (Uses package import to match existing tsconfig.test paths + `npm run build && npm test` runtime;
8
+ * plan referenced '../src/index.js' for source-load semantics in test source.)
9
+ */
10
+ import assert from 'node:assert/strict';
11
+ import { describe, it, before, after } from 'node:test';
12
+ import { AgentRuntime } from '@elizaos/core';
13
+ import wzrdPlugin, { intelPreflightAction, intelTrustAction, verifyReceiptAction, setPayingFetch, clearPayingFetch, getIntelClient, resolvePayingFetch, } from '@wzrd_sol/eliza-plugin';
14
+ function mockMemory(content) {
15
+ return {
16
+ id: '00000000-0000-0000-0000-000000000001',
17
+ entityId: '00000000-0000-0000-0000-000000000002',
18
+ roomId: '00000000-0000-0000-0000-000000000003',
19
+ content: content,
20
+ createdAt: Date.now(),
21
+ };
22
+ }
23
+ function mockRuntime(settings = {}) {
24
+ const store = new Map(Object.entries(settings));
25
+ return {
26
+ getSetting: (key) => store.get(key) ?? null,
27
+ getService: () => null,
28
+ fetch: globalThis.fetch,
29
+ };
30
+ }
31
+ describe('wzrdPlugin intel registration + E2E (real runtime load)', () => {
32
+ let runtime;
33
+ before(async () => {
34
+ runtime = new AgentRuntime({
35
+ character: { name: 'wzrd-intel-test', bio: 'test', plugins: [] },
36
+ settings: { WZRD_INTEL_URL: 'https://intel.twzrd.xyz' },
37
+ });
38
+ await runtime.registerPlugin(wzrdPlugin);
39
+ });
40
+ after(() => {
41
+ clearPayingFetch();
42
+ });
43
+ it('constructs runtime with plugins and registers intel actions', () => {
44
+ const names = runtime.actions.map((a) => a.name);
45
+ assert.ok(names.includes('WZRD_INTEL_PREFLIGHT'), 'preflight must be registered');
46
+ assert.ok(names.includes('WZRD_INTEL_TRUST'), 'trust must be registered');
47
+ assert.ok(names.includes('WZRD_VERIFY_RECEIPT'), 'verify must be registered');
48
+ });
49
+ it('preflight handler accepts seller_wallet + price + resource_name, returns success + decision/score text (live)', { timeout: 10000 }, async () => {
50
+ const rt = mockRuntime({ WZRD_INTEL_URL: 'https://intel.twzrd.xyz' });
51
+ const callbacks = [];
52
+ const result = await intelPreflightAction.handler(rt, mockMemory({
53
+ seller_wallet: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE',
54
+ price_usdc: 0.05,
55
+ resource_name: 'test-resource',
56
+ }), undefined, undefined, async (r) => {
57
+ callbacks.push(r.text ?? '');
58
+ return [];
59
+ });
60
+ assert.equal(result?.success, true, `preflight failed: ${result?.error}`);
61
+ assert.equal(typeof result.success, 'boolean');
62
+ assert.ok(callbacks.length > 0);
63
+ const text = callbacks.join('\n');
64
+ assert.match(text, /Decision: (ALLOW|WARN|BLOCK)/i);
65
+ assert.match(text, /score|trust_score/i);
66
+ if (result.data)
67
+ assert.ok(result.data);
68
+ });
69
+ it('preflight validation rejects bad seller_wallet (non-base58)', async () => {
70
+ const rt = mockRuntime({ WZRD_INTEL_URL: 'https://intel.twzrd.xyz' });
71
+ const callbacks = [];
72
+ const result = await intelPreflightAction.handler(rt, mockMemory({ seller_wallet: 'not-base58!!!', price_usdc: 0.05 }), undefined, undefined, async (r) => {
73
+ callbacks.push(r.text ?? '');
74
+ return [];
75
+ });
76
+ assert.equal(result?.success, false);
77
+ assert.equal(typeof result.success, 'boolean');
78
+ const text = callbacks.join('\n');
79
+ assert.match(text, /Invalid preflight input/);
80
+ assert.match(text, /seller_wallet must be 32-44 char base58/);
81
+ });
82
+ it('preflight validation rejects negative price_usdc', async () => {
83
+ const rt = mockRuntime({ WZRD_INTEL_URL: 'https://intel.twzrd.xyz' });
84
+ const callbacks = [];
85
+ const result = await intelPreflightAction.handler(rt, mockMemory({ seller_wallet: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE', price_usdc: -1 }), undefined, undefined, async (r) => {
86
+ callbacks.push(r.text ?? '');
87
+ return [];
88
+ });
89
+ assert.equal(result?.success, false);
90
+ assert.equal(typeof result.success, 'boolean');
91
+ const text = callbacks.join('\n');
92
+ assert.match(text, /Invalid preflight input/);
93
+ assert.match(text, /price_usdc must be non-negative finite number/);
94
+ });
95
+ it('trust handler with injected paying fetch (fake IntelTrustResponse containing receipt) succeeds + surfaces score + leaf in callback', async () => {
96
+ const fakeReceipt = {
97
+ version: 'v5',
98
+ leaf: '0xdeadbeef',
99
+ preimage: { domain: 'TWZRD:AO_REPUTATION_RECEIPT_V5', agent_id: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE', score: 99, version: 'v5' },
100
+ signature: 'sig',
101
+ signing_pubkey: '11111111111111111111111111111111',
102
+ };
103
+ setPayingFetch(async () => ({
104
+ ok: true,
105
+ status: 200,
106
+ json: async () => ({ pubkey: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE', trust: { score: 88 }, paid: true, twzrd_receipt: fakeReceipt }),
107
+ }));
108
+ const rt = mockRuntime();
109
+ const callbacks = [];
110
+ const result = await intelTrustAction.handler(rt, mockMemory({ pubkey: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE' }), undefined, undefined, async (r) => {
111
+ callbacks.push(r.text ?? '');
112
+ return [];
113
+ });
114
+ assert.equal(result?.success, true, String(result?.error));
115
+ assert.equal(typeof result.success, 'boolean');
116
+ assert.ok(callbacks.length > 0);
117
+ const text = callbacks.join('\n');
118
+ assert.match(text, /Score: 88/);
119
+ assert.match(text, /leaf:/i);
120
+ if (result.data)
121
+ assert.ok(result.data);
122
+ });
123
+ it('PREFLIGHT-BEFORE-PAY: decision=block aborts the trust purchase before any payment', async () => {
124
+ // preSpendGate runs the FREE preflight via the SDK's intelPreflight, which uses
125
+ // the global fetch (not the injected paying fetch — that is reserved for the
126
+ // paid leg). So we stub global fetch to return a block ReadinessCard, and put a
127
+ // tripwire on the injected paying fetch: if the pay leg runs after a block, the
128
+ // tripwire fires and the test fails.
129
+ const realFetch = globalThis.fetch;
130
+ let payAttempted = false;
131
+ setPayingFetch(async () => {
132
+ payAttempted = true;
133
+ return { ok: true, status: 200, json: async () => ({}) };
134
+ });
135
+ globalThis.fetch = (async () => ({
136
+ ok: true,
137
+ status: 200,
138
+ json: async () => ({
139
+ readiness_card: { decision: 'block', trust_score: 5, can_spend: false },
140
+ reason: 'seller flagged by corpus',
141
+ }),
142
+ }));
143
+ try {
144
+ const callbacks = [];
145
+ const result = await intelTrustAction.handler(mockRuntime(), mockMemory({ pubkey: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE' }), undefined, undefined, async (r) => {
146
+ callbacks.push(r.text ?? '');
147
+ return [];
148
+ });
149
+ assert.equal(result?.success, false);
150
+ assert.equal(result?.error, 'preflight_block');
151
+ assert.equal(payAttempted, false, 'payment must NOT be attempted after a block decision');
152
+ assert.match(callbacks.join('\n'), /blocked|No payment was sent/i);
153
+ }
154
+ finally {
155
+ globalThis.fetch = realFetch;
156
+ }
157
+ });
158
+ it('VERIFY: a V6 receipt (reputation_* bound into the leaf) is accepted by the verify action path', async () => {
159
+ // Live receipts are V6; the SDK selects the leaf binding from the domain, so a
160
+ // V6 receipt must round-trip through WZRD_VERIFY_RECEIPT without a V5/V6 mixup.
161
+ // We assert the action runs and reports the V6 domain rather than erroring.
162
+ const v6Receipt = {
163
+ version: 'v6',
164
+ leaf: '0x4c82649d2be393b1fca2da7c5d4c7afebb189ad3f0b93b620ce2e552fe5ce558',
165
+ preimage: {
166
+ domain: 'TWZRD:AO_REPUTATION_RECEIPT_V6',
167
+ agent_id: '11111111111111111111111111111111',
168
+ score: 72,
169
+ confidence_bps: 8000,
170
+ timestamp_unix: 1748736000,
171
+ payer: '11111111111111111111111111111111',
172
+ settlement_tx: 'EXAMPLE-sample-receipt-no-real-settlement-tx-0001',
173
+ reputation_score: 4242,
174
+ reputation_confidence_bps: 7500,
175
+ reputation_score_version: 'intel_renorm_v1',
176
+ reputation_feature_window_start_unix: 1748000000,
177
+ reputation_data_quality: 'high',
178
+ version: 'v6',
179
+ },
180
+ signature: 'sig',
181
+ signing_pubkey: '11111111111111111111111111111111',
182
+ };
183
+ const callbacks = [];
184
+ const result = await verifyReceiptAction.handler(mockRuntime(), mockMemory({ receipt: v6Receipt }), undefined, undefined, async (r) => {
185
+ callbacks.push(r.text ?? '');
186
+ return [];
187
+ });
188
+ // The action ran (no exception) and exercised the SDK V6 leaf path. The
189
+ // signature is a stub so it won't pass authenticity, but the leaf must
190
+ // recompute against the V6 binding (not the V5 one) — proven by the SDK's
191
+ // own canonical-vector tests; here we assert the action did not crash and
192
+ // surfaced a verdict for the V6 domain.
193
+ assert.ok(result, 'verify action returned a result for a V6 receipt');
194
+ assert.ok(callbacks.length > 0, 'verify action produced output for a V6 receipt');
195
+ });
196
+ it('trust surfaces payment_required + x402/agentcash text on 402 from (failing) fetch (explicit IntelPaymentRequiredError branch)', async () => {
197
+ setPayingFetch(async () => ({
198
+ ok: false,
199
+ status: 402,
200
+ headers: { get: () => null },
201
+ json: async () => ({ error: 'payment required' }),
202
+ text: async () => '',
203
+ }));
204
+ const rt = mockRuntime();
205
+ const callbacks = [];
206
+ const result = await intelTrustAction.handler(rt, mockMemory({ pubkey: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE' }), undefined, undefined, async (r) => {
207
+ callbacks.push(r.text ?? '');
208
+ return [];
209
+ });
210
+ assert.equal(result?.success, false);
211
+ assert.equal(result?.error, 'payment_required');
212
+ assert.equal(typeof result.success, 'boolean');
213
+ const text = callbacks.join('\n');
214
+ assert.match(text, /x402|Intel trust requires|agentcash/i);
215
+ });
216
+ it('verify handler runs with receipt content (exercises SDK verify path)', async () => {
217
+ const rt = mockRuntime();
218
+ const callbacks = [];
219
+ const minimalReceipt = {
220
+ version: 'v5',
221
+ leaf: '0x0000000000000000000000000000000000000000000000000000000000000000',
222
+ preimage: { domain: 'TWZRD:AO_REPUTATION_RECEIPT_V5', agent_id: '4LkEFjJdXARkKx8FBx4LBFa2SvJNmjQpgGDLoJcypZUE', score: 0, version: 'v5' },
223
+ signature: 'AA',
224
+ signing_pubkey: '11111111111111111111111111111111',
225
+ };
226
+ const result = await verifyReceiptAction.handler(rt, mockMemory({ receipt: minimalReceipt }), undefined, undefined, async (r) => {
227
+ callbacks.push(r.text ?? '');
228
+ return [];
229
+ });
230
+ assert.ok(result, 'verify handler must return');
231
+ assert.equal(typeof result.success, 'boolean');
232
+ assert.equal(result.success, false);
233
+ assert.ok(callbacks.length > 0);
234
+ const text = callbacks.join('\n');
235
+ assert.match(text, /INVALID/);
236
+ });
237
+ it('getIntelClient factory + resolvePayingFetch service fallback exercised (covers factory delegates and resolve branches)', () => {
238
+ clearPayingFetch(); // ensure module-level does not shadow the service fallback we want to test
239
+ const mockPaying = async () => ({ ok: true, status: 200, json: async () => ({}) });
240
+ const rt = {
241
+ getSetting: () => null,
242
+ getService: (n) => (n === 'payingFetch' ? { fetch: mockPaying } : null),
243
+ fetch: globalThis.fetch,
244
+ };
245
+ const intel = getIntelClient(rt);
246
+ assert.equal(typeof intel.preflight, 'function');
247
+ assert.equal(typeof intel.trust, 'function');
248
+ assert.equal(typeof intel.verify, 'function');
249
+ // exercise at least one resolve fallback path (service)
250
+ const resolved = resolvePayingFetch(rt);
251
+ assert.equal(resolved, mockPaying);
252
+ });
253
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wzrd_sol/eliza-plugin",
3
- "version": "0.1.2",
4
- "description": "WZRD Liquid Attention Protocol plugin for ElizaOS — leaderboard, portfolio, deposit, claim, velocity",
3
+ "version": "0.3.0",
4
+ "description": "WZRD Agent Intel for ElizaOS — preflight ReadinessCards, x402-paid V5 trust receipts, offline verification on intel.twzrd.xyz. Also ships the legacy earn loop.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -13,13 +13,15 @@
13
13
  }
14
14
  },
15
15
  "scripts": {
16
- "build": "tsc",
16
+ "build": "tsc && tsc -p tsconfig.test.json",
17
+ "test": "node --test dist/test/plugin-registration.intel.js",
17
18
  "prepublishOnly": "npm run build"
18
19
  },
19
20
  "dependencies": {
20
- "@wzrd_sol/solana-agent-plugin": "^0.1.0",
21
- "@wzrd_sol/sdk": "^0.1.1",
22
- "@solana/web3.js": "^1.95.0"
21
+ "@solana/web3.js": "^1.95.0",
22
+ "@wzrd_sol/sdk": "^0.4.3",
23
+ "bs58": "^5.0.0",
24
+ "tweetnacl": "^1.0.3"
23
25
  },
24
26
  "peerDependencies": {
25
27
  "@elizaos/core": "^1.0.0"
@@ -31,6 +33,7 @@
31
33
  },
32
34
  "devDependencies": {
33
35
  "@elizaos/core": "^1.0.0",
36
+ "@types/node": "^22.13.10",
34
37
  "typescript": "^5.6.3"
35
38
  },
36
39
  "keywords": [
@@ -38,9 +41,17 @@
38
41
  "eliza",
39
42
  "elizaos",
40
43
  "wzrd",
41
- "attention",
42
- "defi",
43
- "ai-agent"
44
+ "intel",
45
+ "x402",
46
+ "trust",
47
+ "receipt",
48
+ "reputation",
49
+ "preflight",
50
+ "ccm",
51
+ "inference",
52
+ "earn",
53
+ "ai-agent",
54
+ "mcp"
44
55
  ],
45
56
  "license": "MIT",
46
57
  "publishConfig": {
@@ -48,7 +59,7 @@
48
59
  },
49
60
  "repository": {
50
61
  "type": "git",
51
- "url": "git+https://github.com/twzrd-sol/wzrd-final.git",
62
+ "url": "git+https://github.com/twzrd-sol/wzrd-velocity.git",
52
63
  "directory": "agents/eliza-plugin"
53
64
  },
54
65
  "files": [
@@ -1,2 +0,0 @@
1
- import type { Action } from '@elizaos/core';
2
- export declare const depositAction: Action;
@@ -1,79 +0,0 @@
1
- /**
2
- * ELIZA Action: WZRD_DEPOSIT — deposit USDC into attention market, mint vLOFI (auth + keypair).
3
- *
4
- * Before depositing, agents can check expected returns via the APR endpoint:
5
- * GET /v1/markets/:id/apr — returns base_apr_bps, attention_multiplier_bps,
6
- * projected_total_apr_bps, tvl_usdc, and the yield formula.
7
- * GET /v1/markets/:id/preview — returns projected_multiplier_bps and freshness_secs
8
- * for a live multiplier snapshot before committing capital.
9
- * Use WzrdClient.getMarketApr(marketId) or WzrdClient.getMarketPreview(marketId).
10
- */
11
- import { Keypair, ComputeBudgetProgram, TransactionMessage, VersionedTransaction, Connection } from '@solana/web3.js';
12
- export const depositAction = {
13
- name: 'WZRD_DEPOSIT',
14
- similes: ['DEPOSIT_USDC', 'BUY_ATTENTION', 'ENTER_MARKET'],
15
- description: 'Deposit USDC into a WZRD attention market to mint vLOFI. Requires market_id and amount_usdc in message content.',
16
- examples: [[
17
- { name: '{{user1}}', content: { text: 'Deposit 0.01 USDC into WZRD market 10' } },
18
- { name: '{{agentName}}', content: { text: 'Deposited 0.0100 USDC into Market #10. Tx: X7FG...' } },
19
- ]],
20
- validate: async () => true,
21
- handler: async (runtime, message, _state, _opt, callback) => {
22
- const { market_id: marketId, amount_usdc: amountUsdc, priority_fee = 50_000 } = message.content;
23
- if (!marketId || !amountUsdc || amountUsdc > 100) {
24
- const text = !marketId || !amountUsdc
25
- ? 'Missing required: market_id and amount_usdc.' : 'Max 100 USDC per deposit.';
26
- await callback?.({ text });
27
- return { success: false, text };
28
- }
29
- const sk = runtime.getSetting('SOLANA_PRIVATE_KEY');
30
- if (!sk)
31
- throw new Error('SOLANA_PRIVATE_KEY not configured');
32
- const kp = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(String(sk))));
33
- const payer = kp.publicKey;
34
- const amt = BigInt(Math.round(amountUsdc * 1e6));
35
- const rpcSetting = runtime.getSetting('SOLANA_RPC_URL');
36
- const rpc = (typeof rpcSetting === 'string' ? rpcSetting : undefined) || 'https://api.mainnet-beta.solana.com';
37
- const conn = new Connection(rpc, 'confirmed');
38
- const sdk = await import('@wzrd_sol/sdk');
39
- const vault = await sdk.fetchMarketVault(conn, marketId);
40
- if (!vault) {
41
- await callback?.({ text: `Market ${marketId} has no vault.` });
42
- return { success: false };
43
- }
44
- const pos = await sdk.fetchOnChainPosition(conn, payer, marketId);
45
- if (pos && pos.depositedAmount > 0n && !pos.settled) {
46
- await callback?.({ text: `Position exists in market ${marketId}.` });
47
- return { success: false };
48
- }
49
- const bal = await sdk.fetchTokenBalance(conn, sdk.getAta(payer, vault.depositMint, sdk.TOKEN_PROGRAM_ID));
50
- if (bal < amt) {
51
- await callback?.({ text: `Insufficient USDC.` });
52
- return { success: false };
53
- }
54
- const ixs = await sdk.createDepositMarketIx(conn, payer, marketId, amt);
55
- ixs.unshift(ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priority_fee }));
56
- const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash('confirmed');
57
- const tx = new VersionedTransaction(new TransactionMessage({ payerKey: payer, recentBlockhash: blockhash, instructions: ixs }).compileToV0Message());
58
- tx.sign([kp]);
59
- const sim = await conn.simulateTransaction(tx);
60
- if (sim.value.err) {
61
- await callback?.({ text: `Sim failed: ${JSON.stringify(sim.value.err)}` });
62
- return { success: false };
63
- }
64
- const sig = await conn.sendTransaction(tx, { skipPreflight: true, maxRetries: 3 });
65
- try {
66
- await Promise.race([
67
- conn.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed'),
68
- new Promise((_, rej) => setTimeout(() => rej(new Error('Timeout')), 60_000)),
69
- ]);
70
- }
71
- catch {
72
- await callback?.({ text: `Deposit sent, confirmation timed out. Tx: ${sig}` });
73
- return { success: true, data: { signature: sig, timed_out: true } };
74
- }
75
- const text = `Deposited ${amountUsdc.toFixed(4)} USDC into Market #${marketId}. Tx: ${sig.slice(0, 16)}...`;
76
- await callback?.({ text });
77
- return { success: true, text, data: { signature: sig, market_id: marketId, amount_usdc: amountUsdc } };
78
- },
79
- };
@@ -1,3 +0,0 @@
1
- /** ELIZA Action: WZRD_LEADERBOARD — fetch attention market leaderboard (no auth). */
2
- import type { Action } from '@elizaos/core';
3
- export declare const leaderboardAction: Action;
@@ -1,25 +0,0 @@
1
- import { getWzrdClient } from '../client.js';
2
- export const leaderboardAction = {
3
- name: 'WZRD_LEADERBOARD',
4
- similes: ['WZRD_MARKETS', 'WZRD_TRENDING', 'TOP_MODELS'],
5
- description: 'Fetch the WZRD attention market leaderboard ranked by velocity EMA.',
6
- examples: [[
7
- { name: '{{user1}}', content: { text: 'Show me the top WZRD markets' } },
8
- { name: '{{agentName}}', content: { text: 'Here are the top WZRD attention markets...' } },
9
- ]],
10
- validate: async () => true,
11
- handler: async (runtime, _msg, _state, _opt, callback) => {
12
- const result = await getWzrdClient(runtime).getLeaderboard(10);
13
- const lines = result.markets.map((m, i) => `${i + 1}. ${m.metric} — ${fmtV(m.velocity_ema)} velocity (${m.platform}) | ${m.multiplier_bps / 10_000}x | id=${m.market_id}`);
14
- const text = `WZRD Leaderboard (${result.markets.length} markets, root_seq=${result.root.root_seq}):\n${lines.join('\n')}`;
15
- await callback?.({ text });
16
- return { success: true, data: result };
17
- },
18
- };
19
- function fmtV(v) {
20
- if (v >= 1e6)
21
- return `${(v / 1e6).toFixed(1)}M`;
22
- if (v >= 1e3)
23
- return `${(v / 1e3).toFixed(0)}K`;
24
- return v.toFixed(0);
25
- }
@@ -1,3 +0,0 @@
1
- /** ELIZA Action: WZRD_PORTFOLIO — fetch agent's positions + CCM earned (auth). */
2
- import type { Action } from '@elizaos/core';
3
- export declare const portfolioAction: Action;