@wzrd_sol/solana-agent-plugin 0.1.0 → 0.1.1
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/actions/claim.d.ts +11 -30
- package/dist/actions/claim.js +57 -60
- package/dist/actions/deposit.d.ts +15 -46
- package/dist/actions/deposit.js +148 -105
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/leaderboard.d.ts +14 -21
- package/dist/actions/leaderboard.js +26 -42
- package/dist/actions/portfolio.d.ts +5 -18
- package/dist/actions/portfolio.js +28 -28
- package/dist/actions/velocity.d.ts +15 -33
- package/dist/actions/velocity.js +67 -75
- package/dist/client.d.ts +18 -5
- package/dist/client.js +25 -8
- package/dist/index.d.ts +18 -273
- package/dist/index.js +53 -12
- package/dist/runtime.d.ts +16 -0
- package/dist/runtime.js +33 -0
- package/examples/hello-wzrd.mjs +1 -1
- package/package.json +10 -4
- package/src/actions/claim.ts +74 -71
- package/src/actions/deposit.ts +189 -157
- package/src/actions/index.ts +1 -0
- package/src/actions/leaderboard.ts +40 -57
- package/src/actions/portfolio.ts +41 -39
- package/src/actions/velocity.ts +84 -91
- package/src/client.ts +42 -11
- package/src/index.ts +70 -12
- package/src/runtime.ts +60 -0
- package/type-smoke-Cvxu.ts +8 -0
package/src/actions/velocity.ts
CHANGED
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
* WEAK — below p20
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import type { Action, SolanaAgentKit } from 'solana-agent-kit';
|
|
18
|
+
import type { WzrdMarket } from '../client.js';
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
import { formatVelocity, getLeaderboardData, type SignalTier } from '../runtime.js';
|
|
19
21
|
|
|
20
22
|
export interface MarketSignal {
|
|
21
23
|
market_id: number;
|
|
@@ -26,7 +28,79 @@ export interface MarketSignal {
|
|
|
26
28
|
percentile: number;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
export const
|
|
31
|
+
export const velocitySchema = z.object({
|
|
32
|
+
platform: z.string().min(1).optional(),
|
|
33
|
+
min_signal: z
|
|
34
|
+
.enum(['BREAKOUT', 'MOMENTUM', 'EMERGING', 'STABLE', 'COOLING', 'WEAK'])
|
|
35
|
+
.optional(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export async function velocityHandler(
|
|
39
|
+
agent: SolanaAgentKit,
|
|
40
|
+
input: z.infer<typeof velocitySchema>,
|
|
41
|
+
): Promise<Record<string, unknown>> {
|
|
42
|
+
const data = await getLeaderboardData(agent, { limit: 50, platform: input.platform });
|
|
43
|
+
const markets = data.markets;
|
|
44
|
+
|
|
45
|
+
if (markets.length === 0) {
|
|
46
|
+
return { success: true, text: 'No markets found.', data: { signals: [] } };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sorted = [...markets].sort((a, b) => a.velocity_ema - b.velocity_ema);
|
|
50
|
+
const signals: MarketSignal[] = markets.map((m: WzrdMarket) => {
|
|
51
|
+
const rank = sorted.findIndex((s) => s.market_id === m.market_id);
|
|
52
|
+
const percentile = ((rank + 1) / sorted.length) * 100;
|
|
53
|
+
const signal = classify(m, percentile);
|
|
54
|
+
return {
|
|
55
|
+
market_id: m.market_id,
|
|
56
|
+
metric: m.metric,
|
|
57
|
+
platform: m.platform,
|
|
58
|
+
velocity_ema: m.velocity_ema,
|
|
59
|
+
signal,
|
|
60
|
+
percentile: Math.round(percentile),
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const tierOrder: SignalTier[] = ['BREAKOUT', 'MOMENTUM', 'EMERGING', 'STABLE', 'COOLING', 'WEAK'];
|
|
65
|
+
const minIdx = input.min_signal
|
|
66
|
+
? tierOrder.indexOf(input.min_signal)
|
|
67
|
+
: tierOrder.length;
|
|
68
|
+
const filtered = minIdx < tierOrder.length
|
|
69
|
+
? signals.filter((s) => tierOrder.indexOf(s.signal) <= minIdx)
|
|
70
|
+
: signals;
|
|
71
|
+
|
|
72
|
+
const grouped = new Map<SignalTier, MarketSignal[]>();
|
|
73
|
+
for (const s of filtered) {
|
|
74
|
+
const arr = grouped.get(s.signal) ?? [];
|
|
75
|
+
arr.push(s);
|
|
76
|
+
grouped.set(s.signal, arr);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const lines: string[] = [];
|
|
80
|
+
for (const tier of tierOrder) {
|
|
81
|
+
const group = grouped.get(tier);
|
|
82
|
+
if (!group?.length) continue;
|
|
83
|
+
lines.push(`${tier}:`);
|
|
84
|
+
for (const s of group) {
|
|
85
|
+
lines.push(
|
|
86
|
+
` • ${s.metric} (${formatVelocity(s.velocity_ema)} velocity, p${s.percentile}) [${s.platform}]`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const medianIdx = Math.floor(sorted.length / 2);
|
|
92
|
+
const medianVelocity = sorted[medianIdx]?.velocity_ema ?? 0;
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
text:
|
|
97
|
+
`Velocity analysis (${markets.length} markets, ` +
|
|
98
|
+
`median ${formatVelocity(medianVelocity)}):\n${lines.join('\n')}`,
|
|
99
|
+
data: { signals: filtered, median_velocity: medianVelocity },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const VELOCITY_ACTION: Action = {
|
|
30
104
|
name: 'wzrd_velocity',
|
|
31
105
|
similes: ['wzrd_signal', 'attention_signal', 'market_analysis', 'velocity_check'],
|
|
32
106
|
description:
|
|
@@ -39,92 +113,17 @@ export const VELOCITY_ACTION = {
|
|
|
39
113
|
examples: [
|
|
40
114
|
[
|
|
41
115
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
user: 'assistant',
|
|
47
|
-
content: {
|
|
48
|
-
text: 'BREAKOUT signals:\n' +
|
|
49
|
-
'• Qwen 3.5 35B (804K velocity, p95)\n' +
|
|
50
|
-
'MOMENTUM signals:\n' +
|
|
51
|
-
'• Qwen 3.5 9B (769K velocity, p85)\n' +
|
|
52
|
-
'• Qwen 2.5 72B (378K velocity, p72)',
|
|
116
|
+
input: { min_signal: 'MOMENTUM' },
|
|
117
|
+
output: {
|
|
118
|
+
success: true,
|
|
119
|
+
signals: ['BREAKOUT: Qwen 3.5 35B', 'MOMENTUM: Qwen 2.5 72B'],
|
|
53
120
|
},
|
|
121
|
+
explanation: 'Classify the current leaderboard into signal tiers for deposit decisions.',
|
|
54
122
|
},
|
|
55
123
|
],
|
|
56
124
|
],
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
handler: async (
|
|
61
|
-
client: WzrdClient,
|
|
62
|
-
params: { platform?: string; min_signal?: SignalTier },
|
|
63
|
-
) => {
|
|
64
|
-
const data = await client.getLeaderboard(50, params.platform);
|
|
65
|
-
const markets = data.markets;
|
|
66
|
-
|
|
67
|
-
if (markets.length === 0) {
|
|
68
|
-
return { success: true, text: 'No markets found.', data: { signals: [] } };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Sort by velocity for percentile calculation
|
|
72
|
-
const sorted = [...markets].sort((a, b) => a.velocity_ema - b.velocity_ema);
|
|
73
|
-
const signals: MarketSignal[] = markets.map((m: WzrdMarket) => {
|
|
74
|
-
const rank = sorted.findIndex((s) => s.market_id === m.market_id);
|
|
75
|
-
const percentile = ((rank + 1) / sorted.length) * 100;
|
|
76
|
-
const signal = classify(m, percentile);
|
|
77
|
-
return {
|
|
78
|
-
market_id: m.market_id,
|
|
79
|
-
metric: m.metric,
|
|
80
|
-
platform: m.platform,
|
|
81
|
-
velocity_ema: m.velocity_ema,
|
|
82
|
-
signal,
|
|
83
|
-
percentile: Math.round(percentile),
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Filter by minimum signal if requested
|
|
88
|
-
const tierOrder: SignalTier[] = ['BREAKOUT', 'MOMENTUM', 'EMERGING', 'STABLE', 'COOLING', 'WEAK'];
|
|
89
|
-
const minIdx = params.min_signal
|
|
90
|
-
? tierOrder.indexOf(params.min_signal)
|
|
91
|
-
: tierOrder.length;
|
|
92
|
-
const filtered = minIdx < tierOrder.length
|
|
93
|
-
? signals.filter((s) => tierOrder.indexOf(s.signal) <= minIdx)
|
|
94
|
-
: signals;
|
|
95
|
-
|
|
96
|
-
// Group by signal tier
|
|
97
|
-
const grouped = new Map<SignalTier, MarketSignal[]>();
|
|
98
|
-
for (const s of filtered) {
|
|
99
|
-
const arr = grouped.get(s.signal) ?? [];
|
|
100
|
-
arr.push(s);
|
|
101
|
-
grouped.set(s.signal, arr);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const lines: string[] = [];
|
|
105
|
-
for (const tier of tierOrder) {
|
|
106
|
-
const group = grouped.get(tier);
|
|
107
|
-
if (!group?.length) continue;
|
|
108
|
-
lines.push(`${tier}:`);
|
|
109
|
-
for (const s of group) {
|
|
110
|
-
lines.push(
|
|
111
|
-
` • ${s.metric} (${formatVelocity(s.velocity_ema)} velocity, p${s.percentile}) [${s.platform}]`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Median velocity
|
|
117
|
-
const medianIdx = Math.floor(sorted.length / 2);
|
|
118
|
-
const medianVelocity = sorted[medianIdx]?.velocity_ema ?? 0;
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
success: true,
|
|
122
|
-
text:
|
|
123
|
-
`Velocity analysis (${markets.length} markets, ` +
|
|
124
|
-
`median ${formatVelocity(medianVelocity)}):\n${lines.join('\n')}`,
|
|
125
|
-
data: { signals: filtered, median_velocity: medianVelocity },
|
|
126
|
-
};
|
|
127
|
-
},
|
|
125
|
+
schema: velocitySchema,
|
|
126
|
+
handler: async (agent, input) => velocityHandler(agent, velocitySchema.parse(input)),
|
|
128
127
|
};
|
|
129
128
|
|
|
130
129
|
function classify(m: WzrdMarket, percentile: number): SignalTier {
|
|
@@ -135,9 +134,3 @@ function classify(m: WzrdMarket, percentile: number): SignalTier {
|
|
|
135
134
|
if (percentile >= 20) return 'COOLING';
|
|
136
135
|
return 'WEAK';
|
|
137
136
|
}
|
|
138
|
-
|
|
139
|
-
function formatVelocity(v: number): string {
|
|
140
|
-
if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;
|
|
141
|
-
if (v >= 1_000) return `${(v / 1_000).toFixed(0)}K`;
|
|
142
|
-
return v.toFixed(0);
|
|
143
|
-
}
|
package/src/client.ts
CHANGED
|
@@ -2,14 +2,21 @@
|
|
|
2
2
|
* WZRD API client — handles agent auth (Ed25519 challenge/verify),
|
|
3
3
|
* token caching, and all REST calls.
|
|
4
4
|
*
|
|
5
|
-
* Standalone: no framework dependency. Works with
|
|
5
|
+
* Standalone: no framework dependency. Works with a Keypair or any wallet
|
|
6
|
+
* implementation that supports `publicKey` + `signMessage()`.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
|
-
import { Keypair } from '@solana/web3.js';
|
|
9
|
+
import { Keypair, type PublicKey } from '@solana/web3.js';
|
|
9
10
|
|
|
10
|
-
const DEFAULT_API_URL = 'https://api.twzrd.xyz';
|
|
11
|
+
export const DEFAULT_API_URL = 'https://api.twzrd.xyz';
|
|
11
12
|
const TOKEN_REFRESH_MARGIN_MS = 5 * 60 * 1000;
|
|
12
13
|
|
|
14
|
+
export interface WzrdSigner {
|
|
15
|
+
publicKey: PublicKey;
|
|
16
|
+
signMessage?: (message: Uint8Array) => Promise<Uint8Array>;
|
|
17
|
+
secretKey?: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
// ── Base58 encoder (zero-dependency) ────────────────────
|
|
14
21
|
|
|
15
22
|
const B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
@@ -51,6 +58,7 @@ export interface WzrdMarket {
|
|
|
51
58
|
status: string;
|
|
52
59
|
snapshot_count: number;
|
|
53
60
|
last_scored_at: string;
|
|
61
|
+
depositable: boolean;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
export interface WzrdLeaderboard {
|
|
@@ -91,7 +99,9 @@ export interface WzrdClaim {
|
|
|
91
99
|
export interface WzrdRelayResult {
|
|
92
100
|
root_seq: number;
|
|
93
101
|
cumulative_total: number;
|
|
94
|
-
|
|
102
|
+
claimed_total?: number;
|
|
103
|
+
tx_sig?: string;
|
|
104
|
+
status?: 'already_claimed';
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
// ── Client ──────────────────────────────────────────────
|
|
@@ -101,12 +111,37 @@ export class WzrdClient {
|
|
|
101
111
|
private tokenExpiresAt = 0;
|
|
102
112
|
|
|
103
113
|
constructor(
|
|
104
|
-
private readonly
|
|
114
|
+
private readonly signer: WzrdSigner | Keypair,
|
|
105
115
|
private readonly apiUrl: string = DEFAULT_API_URL,
|
|
106
116
|
) {}
|
|
107
117
|
|
|
108
118
|
get pubkey(): string {
|
|
109
|
-
return this.
|
|
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
|
+
);
|
|
110
145
|
}
|
|
111
146
|
|
|
112
147
|
// ── Auth ────────────────────────────────────────────
|
|
@@ -119,11 +154,7 @@ export class WzrdClient {
|
|
|
119
154
|
|
|
120
155
|
// 2. Sign with Ed25519
|
|
121
156
|
const message = `wzrd-agent-auth v1 | wallet:${this.pubkey} | nonce:${nonce}`;
|
|
122
|
-
const
|
|
123
|
-
const sig = nacl.sign.detached(
|
|
124
|
-
new TextEncoder().encode(message),
|
|
125
|
-
this.keypair.secretKey,
|
|
126
|
-
);
|
|
157
|
+
const sig = await this.signAuthMessage(new TextEncoder().encode(message));
|
|
127
158
|
|
|
128
159
|
// 3. Verify
|
|
129
160
|
const vr = await fetch(`${this.apiUrl}/v1/agent/verify`, {
|
package/src/index.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Works with:
|
|
14
14
|
* - Solana Agent Kit (SendAI) — register as plugin
|
|
15
|
-
* - ElizaOS — wrap actions as
|
|
15
|
+
* - ElizaOS — wrap actions as ELIZA-style actions
|
|
16
16
|
* - Standalone — use WzrdClient directly
|
|
17
17
|
*
|
|
18
18
|
* Quick start:
|
|
@@ -38,14 +38,18 @@ export {
|
|
|
38
38
|
CLAIM_ACTION,
|
|
39
39
|
VELOCITY_ACTION,
|
|
40
40
|
} from './actions/index.js';
|
|
41
|
+
export type { MarketSignal } from './actions/index.js';
|
|
41
42
|
|
|
42
43
|
// ── Convenience: all actions as array ────────────────────
|
|
43
44
|
|
|
45
|
+
import type { Plugin, SolanaAgentKit } from 'solana-agent-kit';
|
|
46
|
+
|
|
47
|
+
import { getClaimsData, getClientForAgent, getLeaderboardData } from './runtime.js';
|
|
44
48
|
import { LEADERBOARD_ACTION } from './actions/leaderboard.js';
|
|
45
49
|
import { PORTFOLIO_ACTION } from './actions/portfolio.js';
|
|
46
|
-
import { DEPOSIT_ACTION } from './actions/deposit.js';
|
|
47
|
-
import { CLAIM_ACTION } from './actions/claim.js';
|
|
48
|
-
import { VELOCITY_ACTION } from './actions/velocity.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';
|
|
49
53
|
|
|
50
54
|
export const WZRD_ACTIONS = [
|
|
51
55
|
LEADERBOARD_ACTION,
|
|
@@ -53,12 +57,66 @@ export const WZRD_ACTIONS = [
|
|
|
53
57
|
DEPOSIT_ACTION,
|
|
54
58
|
CLAIM_ACTION,
|
|
55
59
|
VELOCITY_ACTION,
|
|
56
|
-
] as
|
|
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
|
+
}
|
|
57
120
|
|
|
58
|
-
/**
|
|
59
|
-
export const WZRD_PLUGIN =
|
|
60
|
-
name: 'wzrd',
|
|
61
|
-
description: 'WZRD Liquid Attention Protocol — deposit USDC into AI attention markets, earn CCM yield',
|
|
62
|
-
actions: WZRD_ACTIONS,
|
|
63
|
-
version: '0.1.0',
|
|
64
|
-
};
|
|
121
|
+
/** Default plugin instance for direct registration via `agent.use(...)`. */
|
|
122
|
+
export const WZRD_PLUGIN: Plugin = createWzrdPlugin();
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
}
|