@wzrd_sol/solana-agent-plugin 0.1.2 → 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/src/client.ts DELETED
@@ -1,238 +0,0 @@
1
- /**
2
- * WZRD API client — handles agent auth (Ed25519 challenge/verify),
3
- * token caching, and all REST calls.
4
- *
5
- * Standalone: no framework dependency. Works with a Keypair or any wallet
6
- * implementation that supports `publicKey` + `signMessage()`.
7
- */
8
-
9
- import { Keypair, type PublicKey } from '@solana/web3.js';
10
-
11
- export const DEFAULT_API_URL = 'https://api.twzrd.xyz';
12
- const TOKEN_REFRESH_MARGIN_MS = 5 * 60 * 1000;
13
-
14
- export interface WzrdSigner {
15
- publicKey: PublicKey;
16
- signMessage?: (message: Uint8Array) => Promise<Uint8Array>;
17
- secretKey?: Uint8Array;
18
- }
19
-
20
- // ── Base58 encoder (zero-dependency) ────────────────────
21
-
22
- const B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
23
- function toBase58(bytes: Uint8Array): string {
24
- const digits = [0];
25
- for (const byte of bytes) {
26
- let carry = byte;
27
- for (let j = 0; j < digits.length; j++) {
28
- carry += digits[j] << 8;
29
- digits[j] = carry % 58;
30
- carry = (carry / 58) | 0;
31
- }
32
- while (carry > 0) {
33
- digits.push(carry % 58);
34
- carry = (carry / 58) | 0;
35
- }
36
- }
37
- let out = '';
38
- for (const b of bytes) {
39
- if (b !== 0) break;
40
- out += '1';
41
- }
42
- for (let i = digits.length - 1; i >= 0; i--) out += B58[digits[i]];
43
- return out;
44
- }
45
-
46
- // ── Types ───────────────────────────────────────────────
47
-
48
- export interface WzrdMarket {
49
- market_id: number;
50
- channel_id: string;
51
- platform: string;
52
- metric: string;
53
- velocity_ema: number;
54
- multiplier_bps: number;
55
- position_count: number;
56
- tvl_usdc: number;
57
- rank: number;
58
- status: string;
59
- snapshot_count: number;
60
- last_scored_at: string;
61
- depositable: boolean;
62
- }
63
-
64
- export interface WzrdLeaderboard {
65
- markets: WzrdMarket[];
66
- root: { root_seq: number; root_hash: string; published_slot: number };
67
- total_positions: number;
68
- total_tvl_usdc: number;
69
- total_snapshots: number;
70
- updated_at: string;
71
- }
72
-
73
- export interface WzrdPosition {
74
- market_id: number;
75
- metric: string;
76
- usdc_deposited: number;
77
- vlofi_minted: number;
78
- multiplier_bps: number;
79
- status: string;
80
- is_settled: boolean;
81
- }
82
-
83
- export interface WzrdPortfolio {
84
- positions: WzrdPosition[];
85
- total_deposited_usdc: number;
86
- total_vlofi: number;
87
- total_ccm_earned: number;
88
- }
89
-
90
- export interface WzrdClaim {
91
- root_seq: number;
92
- cumulative_total: number;
93
- claimed_total: number;
94
- leaf_index: number;
95
- proof: string[];
96
- accounts: Record<string, string>;
97
- }
98
-
99
- export interface WzrdRelayResult {
100
- root_seq: number;
101
- cumulative_total: number;
102
- claimed_total?: number;
103
- tx_sig?: string;
104
- status?: 'already_claimed';
105
- }
106
-
107
- // ── Client ──────────────────────────────────────────────
108
-
109
- export class WzrdClient {
110
- private token: string | null = null;
111
- private tokenExpiresAt = 0;
112
-
113
- constructor(
114
- private readonly signer: WzrdSigner | Keypair,
115
- private readonly apiUrl: string = DEFAULT_API_URL,
116
- ) {}
117
-
118
- get pubkey(): string {
119
- return this.signer.publicKey.toBase58();
120
- }
121
-
122
- private isWalletSigner(
123
- signer: WzrdSigner | Keypair,
124
- ): signer is WzrdSigner & { signMessage: NonNullable<WzrdSigner['signMessage']> } {
125
- return typeof (signer as WzrdSigner).signMessage === 'function';
126
- }
127
-
128
- private hasSecretKey(signer: WzrdSigner | Keypair): signer is WzrdSigner & { secretKey: Uint8Array } {
129
- return signer instanceof Keypair || signer.secretKey instanceof Uint8Array;
130
- }
131
-
132
- private async signAuthMessage(message: Uint8Array): Promise<Uint8Array> {
133
- if (this.isWalletSigner(this.signer)) {
134
- return this.signer.signMessage(message);
135
- }
136
-
137
- if (this.hasSecretKey(this.signer)) {
138
- const { default: nacl } = await import('tweetnacl');
139
- return nacl.sign.detached(message, this.signer.secretKey);
140
- }
141
-
142
- throw new Error(
143
- 'WzrdClient requires a signer with signMessage() or an Ed25519 secretKey',
144
- );
145
- }
146
-
147
- // ── Auth ────────────────────────────────────────────
148
-
149
- private async authenticate(): Promise<void> {
150
- // 1. Challenge
151
- const cr = await fetch(`${this.apiUrl}/v1/agent/challenge`);
152
- if (!cr.ok) throw new Error(`Challenge failed: ${cr.status}`);
153
- const { nonce } = (await cr.json()) as { nonce: string };
154
-
155
- // 2. Sign with Ed25519
156
- const message = `wzrd-agent-auth v1 | wallet:${this.pubkey} | nonce:${nonce}`;
157
- const sig = await this.signAuthMessage(new TextEncoder().encode(message));
158
-
159
- // 3. Verify
160
- const vr = await fetch(`${this.apiUrl}/v1/agent/verify`, {
161
- method: 'POST',
162
- headers: { 'Content-Type': 'application/json' },
163
- body: JSON.stringify({
164
- pubkey: this.pubkey,
165
- nonce,
166
- signature: toBase58(sig),
167
- }),
168
- });
169
- if (!vr.ok) throw new Error(`Verify failed: ${vr.status} ${await vr.text()}`);
170
-
171
- const { token, expires_at } = (await vr.json()) as {
172
- token: string;
173
- expires_at: string;
174
- };
175
- this.token = token;
176
- this.tokenExpiresAt = new Date(expires_at).getTime();
177
- }
178
-
179
- private async getToken(): Promise<string> {
180
- if (
181
- !this.token ||
182
- Date.now() > this.tokenExpiresAt - TOKEN_REFRESH_MARGIN_MS
183
- ) {
184
- await this.authenticate();
185
- }
186
- return this.token!;
187
- }
188
-
189
- private async authedFetch(path: string, init?: RequestInit): Promise<Response> {
190
- const token = await this.getToken();
191
- return fetch(`${this.apiUrl}${path}`, {
192
- ...init,
193
- headers: { ...init?.headers, Authorization: `Bearer ${token}` },
194
- });
195
- }
196
-
197
- // ── Public API ──────────────────────────────────────
198
-
199
- /** Fetch leaderboard — no auth required. */
200
- async getLeaderboard(limit = 20, platform?: string): Promise<WzrdLeaderboard> {
201
- const params = new URLSearchParams({ limit: String(limit) });
202
- if (platform) params.set('platform', platform);
203
- const res = await fetch(`${this.apiUrl}/v1/leaderboard?${params}`);
204
- if (!res.ok) throw new Error(`Leaderboard failed: ${res.status}`);
205
- return (await res.json()) as WzrdLeaderboard;
206
- }
207
-
208
- /** Fetch authenticated portfolio. */
209
- async getPortfolio(): Promise<WzrdPortfolio> {
210
- const res = await this.authedFetch('/v1/portfolio');
211
- if (!res.ok) throw new Error(`Portfolio failed: ${res.status}`);
212
- return (await res.json()) as WzrdPortfolio;
213
- }
214
-
215
- /** Fetch claim data (proof + amounts). */
216
- async getClaims(): Promise<WzrdClaim> {
217
- const res = await this.authedFetch(`/v1/claims/${this.pubkey}`);
218
- if (!res.ok) throw new Error(`Claims failed: ${res.status}`);
219
- return (await res.json()) as WzrdClaim;
220
- }
221
-
222
- /** Execute gasless relay claim — server pays tx fees. */
223
- async claimRelay(): Promise<WzrdRelayResult> {
224
- const res = await this.authedFetch(`/v1/claims/${this.pubkey}/relay`, {
225
- method: 'POST',
226
- headers: { 'Content-Type': 'application/json' },
227
- });
228
- if (!res.ok) throw new Error(`Relay claim failed: ${res.status} ${await res.text()}`);
229
- return (await res.json()) as WzrdRelayResult;
230
- }
231
-
232
- /** Fetch system health — no auth required. */
233
- async getHealth(): Promise<Record<string, unknown>> {
234
- const res = await fetch(`${this.apiUrl}/health`);
235
- if (!res.ok) throw new Error(`Health failed: ${res.status}`);
236
- return (await res.json()) as Record<string, unknown>;
237
- }
238
- }
package/src/index.ts DELETED
@@ -1,122 +0,0 @@
1
- /**
2
- * @wzrd_sol/solana-agent-plugin
3
- *
4
- * WZRD Liquid Attention Protocol plugin for autonomous Solana agents.
5
- *
6
- * 5 actions:
7
- * wzrd_leaderboard — browse attention markets (no auth)
8
- * wzrd_velocity — classify signal strength (no auth)
9
- * wzrd_portfolio — view positions + CCM earned (auth)
10
- * wzrd_deposit — deposit USDC → mint vLOFI (auth + keypair)
11
- * wzrd_claim — claim CCM via gasless relay (auth)
12
- *
13
- * Works with:
14
- * - Solana Agent Kit (SendAI) — register as plugin
15
- * - ElizaOS — wrap actions as ELIZA-style actions
16
- * - Standalone — use WzrdClient directly
17
- *
18
- * Quick start:
19
- * import { WzrdClient } from '@wzrd_sol/solana-agent-plugin';
20
- * const client = new WzrdClient(keypair);
21
- * const leaderboard = await client.getLeaderboard();
22
- */
23
-
24
- export { WzrdClient } from './client.js';
25
- export type {
26
- WzrdMarket,
27
- WzrdLeaderboard,
28
- WzrdPosition,
29
- WzrdPortfolio,
30
- WzrdClaim,
31
- WzrdRelayResult,
32
- } from './client.js';
33
-
34
- export {
35
- LEADERBOARD_ACTION,
36
- PORTFOLIO_ACTION,
37
- DEPOSIT_ACTION,
38
- CLAIM_ACTION,
39
- VELOCITY_ACTION,
40
- } from './actions/index.js';
41
- export type { MarketSignal } from './actions/index.js';
42
-
43
- // ── Convenience: all actions as array ────────────────────
44
-
45
- import type { Plugin, SolanaAgentKit } from 'solana-agent-kit';
46
-
47
- import { getClaimsData, getClientForAgent, getLeaderboardData } from './runtime.js';
48
- import { LEADERBOARD_ACTION } from './actions/leaderboard.js';
49
- import { PORTFOLIO_ACTION } from './actions/portfolio.js';
50
- import { DEPOSIT_ACTION, depositHandler } from './actions/deposit.js';
51
- import { CLAIM_ACTION, claimHandler } from './actions/claim.js';
52
- import { VELOCITY_ACTION, velocityHandler, type MarketSignal } from './actions/velocity.js';
53
-
54
- export const WZRD_ACTIONS = [
55
- LEADERBOARD_ACTION,
56
- PORTFOLIO_ACTION,
57
- DEPOSIT_ACTION,
58
- CLAIM_ACTION,
59
- VELOCITY_ACTION,
60
- ] as Plugin['actions'];
61
-
62
- export interface WzrdPluginMethods {
63
- wzrdLeaderboard(limit?: number, platform?: string): Promise<ReturnType<typeof getLeaderboardData>>;
64
- wzrdPortfolio(): Promise<ReturnType<typeof getClientForAgent>['getPortfolio']>;
65
- wzrdClaims(): Promise<ReturnType<typeof getClaimsData>>;
66
- wzrdDeposit(marketId: number, amountUsdc: number, priorityFee?: number): Promise<Record<string, unknown>>;
67
- wzrdClaim(execute?: boolean): Promise<Record<string, unknown>>;
68
- wzrdVelocity(platform?: string, minSignal?: MarketSignal['signal']): Promise<Record<string, unknown>>;
69
- wzrdClient(): ReturnType<typeof getClientForAgent>;
70
- }
71
-
72
- export function createWzrdPlugin(): Plugin {
73
- let agentRef: SolanaAgentKit | null = null;
74
-
75
- const requireAgent = (): SolanaAgentKit => {
76
- if (!agentRef) {
77
- throw new Error('WZRD plugin has not been initialized with a SolanaAgentKit instance');
78
- }
79
- return agentRef;
80
- };
81
-
82
- return {
83
- name: 'wzrd',
84
- initialize(agent) {
85
- agentRef = agent;
86
- },
87
- methods: {
88
- wzrdClient() {
89
- return getClientForAgent(requireAgent());
90
- },
91
- async wzrdLeaderboard(limit = 20, platform?: string) {
92
- return getLeaderboardData(requireAgent(), { limit, platform });
93
- },
94
- async wzrdPortfolio() {
95
- return getClientForAgent(requireAgent()).getPortfolio();
96
- },
97
- async wzrdClaims() {
98
- return getClaimsData(requireAgent());
99
- },
100
- async wzrdDeposit(marketId: number, amountUsdc: number, priorityFee?: number) {
101
- return depositHandler(requireAgent(), {
102
- market_id: marketId,
103
- amount_usdc: amountUsdc,
104
- priority_fee: priorityFee,
105
- });
106
- },
107
- async wzrdClaim(execute = true) {
108
- return claimHandler(requireAgent(), { execute });
109
- },
110
- async wzrdVelocity(platform?: string, minSignal?: MarketSignal['signal']) {
111
- return velocityHandler(requireAgent(), {
112
- platform,
113
- min_signal: minSignal,
114
- });
115
- },
116
- },
117
- actions: WZRD_ACTIONS,
118
- };
119
- }
120
-
121
- /** Default plugin instance for direct registration via `agent.use(...)`. */
122
- export const WZRD_PLUGIN: Plugin = createWzrdPlugin();
package/src/runtime.ts DELETED
@@ -1,60 +0,0 @@
1
- import { PublicKey } from '@solana/web3.js';
2
- import type { SolanaAgentKit } from 'solana-agent-kit';
3
-
4
- import {
5
- DEFAULT_API_URL,
6
- WzrdClient,
7
- type WzrdClaim,
8
- type WzrdLeaderboard,
9
- type WzrdPortfolio,
10
- } from './client.js';
11
-
12
- export type SignalTier =
13
- | 'BREAKOUT'
14
- | 'MOMENTUM'
15
- | 'EMERGING'
16
- | 'STABLE'
17
- | 'COOLING'
18
- | 'WEAK';
19
-
20
- export function resolveApiUrl(explicit?: string): string {
21
- const envUrl = process.env.WZRD_API_URL?.trim();
22
- return explicit?.trim() || envUrl || DEFAULT_API_URL;
23
- }
24
-
25
- export function getClientForAgent(agent: SolanaAgentKit, apiUrl?: string): WzrdClient {
26
- return new WzrdClient(agent.wallet, resolveApiUrl(apiUrl));
27
- }
28
-
29
- export function getWalletPublicKey(agent: SolanaAgentKit): PublicKey {
30
- return agent.wallet.publicKey;
31
- }
32
-
33
- export function formatVelocity(v: number): string {
34
- if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;
35
- if (v >= 1_000) return `${(v / 1_000).toFixed(0)}K`;
36
- return v.toFixed(0);
37
- }
38
-
39
- export function formatUsdc(nativeAmount: number | bigint): string {
40
- return (Number(nativeAmount) / 1_000_000).toFixed(4);
41
- }
42
-
43
- export function formatCcm(nativeAmount: number | bigint): string {
44
- return (Number(nativeAmount) / 1_000_000).toFixed(4);
45
- }
46
-
47
- export async function getLeaderboardData(
48
- agent: SolanaAgentKit,
49
- input: { limit?: number; platform?: string },
50
- ): Promise<WzrdLeaderboard> {
51
- return getClientForAgent(agent).getLeaderboard(input.limit ?? 10, input.platform);
52
- }
53
-
54
- export async function getPortfolioData(agent: SolanaAgentKit): Promise<WzrdPortfolio> {
55
- return getClientForAgent(agent).getPortfolio();
56
- }
57
-
58
- export async function getClaimsData(agent: SolanaAgentKit): Promise<WzrdClaim> {
59
- return getClientForAgent(agent).getClaims();
60
- }
package/tsconfig.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "nodenext",
5
- "moduleResolution": "nodenext",
6
- "declaration": true,
7
- "outDir": "dist",
8
- "rootDir": "src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true
12
- },
13
- "include": ["src"]
14
- }
@@ -1,8 +0,0 @@
1
- import type { Action, Plugin } from 'solana-agent-kit';
2
- import { WZRD_PLUGIN, LEADERBOARD_ACTION } from './dist/index.js';
3
-
4
- const plugin: Plugin = WZRD_PLUGIN;
5
- const action: Action = LEADERBOARD_ACTION;
6
-
7
- void plugin;
8
- void action;