@wzrd_sol/solana-agent-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/README.md +81 -23
- package/dist/actions/claim.d.ts +2 -10
- package/dist/actions/claim.js +25 -40
- package/dist/actions/earn.d.ts +20 -0
- package/dist/actions/earn.js +107 -0
- package/dist/actions/index.d.ts +4 -5
- package/dist/actions/index.js +4 -4
- package/dist/actions/infer.d.ts +23 -0
- package/dist/actions/infer.js +56 -0
- package/dist/actions/report.d.ts +29 -0
- package/dist/actions/report.js +59 -0
- package/dist/actions/rewards.d.ts +10 -0
- package/dist/actions/rewards.js +48 -0
- package/dist/client.d.ts +72 -55
- package/dist/client.js +83 -37
- package/dist/index.d.ts +16 -19
- package/dist/index.js +33 -37
- package/dist/runtime.d.ts +1 -12
- package/dist/runtime.js +2 -24
- package/package.json +17 -8
- package/dist/actions/deposit.d.ts +0 -26
- package/dist/actions/deposit.js +0 -177
- package/dist/actions/leaderboard.d.ts +0 -20
- package/dist/actions/leaderboard.js +0 -47
- package/dist/actions/portfolio.d.ts +0 -11
- package/dist/actions/portfolio.js +0 -48
- package/dist/actions/velocity.d.ts +0 -37
- package/dist/actions/velocity.js +0 -110
- package/examples/hello-wzrd.mjs +0 -79
- package/src/actions/claim.ts +0 -101
- package/src/actions/deposit.ts +0 -229
- package/src/actions/index.ts +0 -6
- package/src/actions/leaderboard.ts +0 -64
- package/src/actions/portfolio.ts +0 -64
- package/src/actions/velocity.ts +0 -136
- package/src/client.ts +0 -238
- package/src/index.ts +0 -122
- package/src/runtime.ts +0 -60
- package/tsconfig.json +0 -14
- package/type-smoke-Cvxu.ts +0 -8
package/src/actions/deposit.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action: wzrd_deposit
|
|
3
|
-
*
|
|
4
|
-
* Deposit USDC into a WZRD attention market → mint vLOFI tokens.
|
|
5
|
-
* Requires: Keypair with USDC balance + SOL for tx fees.
|
|
6
|
-
*
|
|
7
|
-
* The agent picks a market_id (from leaderboard), specifies USDC amount,
|
|
8
|
-
* and the handler builds + signs + sends the deposit transaction.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
ComputeBudgetProgram,
|
|
13
|
-
TransactionMessage,
|
|
14
|
-
VersionedTransaction,
|
|
15
|
-
} from '@solana/web3.js';
|
|
16
|
-
import { z } from 'zod';
|
|
17
|
-
import type { Action, SolanaAgentKit } from 'solana-agent-kit';
|
|
18
|
-
|
|
19
|
-
import { formatUsdc, getWalletPublicKey } from '../runtime.js';
|
|
20
|
-
|
|
21
|
-
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
22
|
-
const CONFIRM_TIMEOUT_MS = 60_000;
|
|
23
|
-
|
|
24
|
-
type WzrdSdk = typeof import('@wzrd_sol/sdk');
|
|
25
|
-
|
|
26
|
-
export const depositSchema = z.object({
|
|
27
|
-
market_id: z.number().int().min(1),
|
|
28
|
-
amount_usdc: z.number().positive().max(100),
|
|
29
|
-
priority_fee: z.number().int().positive().optional(),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export async function depositHandler(
|
|
33
|
-
agent: SolanaAgentKit,
|
|
34
|
-
input: z.infer<typeof depositSchema>,
|
|
35
|
-
): Promise<Record<string, unknown>> {
|
|
36
|
-
const { market_id, amount_usdc, priority_fee = 50_000 } = input;
|
|
37
|
-
const connection = agent.connection;
|
|
38
|
-
const payer = getWalletPublicKey(agent);
|
|
39
|
-
const amountNative = BigInt(Math.round(amount_usdc * 1_000_000));
|
|
40
|
-
const t0 = Date.now();
|
|
41
|
-
const sdk = await loadSdk();
|
|
42
|
-
const {
|
|
43
|
-
createDepositMarketIx,
|
|
44
|
-
fetchMarketVault,
|
|
45
|
-
fetchOnChainPosition,
|
|
46
|
-
fetchTokenBalance,
|
|
47
|
-
getAta,
|
|
48
|
-
TOKEN_PROGRAM_ID,
|
|
49
|
-
} = sdk;
|
|
50
|
-
|
|
51
|
-
const vault = await fetchMarketVault(connection, market_id);
|
|
52
|
-
if (!vault) {
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
text:
|
|
56
|
-
`Market ${market_id} is listed but does not have an on-chain vault yet. ` +
|
|
57
|
-
'Pick a market with an initialized vault before depositing.',
|
|
58
|
-
data: { market_id, reason: 'missing_vault' },
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const existing = await fetchOnChainPosition(connection, payer, market_id);
|
|
63
|
-
if (existing && existing.depositedAmount > 0n && !existing.settled) {
|
|
64
|
-
return {
|
|
65
|
-
success: false,
|
|
66
|
-
text:
|
|
67
|
-
`Position already exists in market ${market_id} ` +
|
|
68
|
-
`(${formatUsdc(existing.depositedAmount)} USDC deposited). Cannot double-deposit.`,
|
|
69
|
-
data: { market_id, deposited_amount: existing.depositedAmount.toString() },
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const usdcAta = getAta(payer, vault.depositMint, TOKEN_PROGRAM_ID);
|
|
74
|
-
const usdcBalance = await fetchTokenBalance(connection, usdcAta);
|
|
75
|
-
if (usdcBalance < amountNative) {
|
|
76
|
-
return {
|
|
77
|
-
success: false,
|
|
78
|
-
text: `Insufficient USDC: have ${formatUsdc(usdcBalance)}, need ${amount_usdc.toFixed(4)}`,
|
|
79
|
-
data: {
|
|
80
|
-
market_id,
|
|
81
|
-
required_native: amountNative.toString(),
|
|
82
|
-
balance_native: usdcBalance.toString(),
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const solBalance = await connection.getBalance(payer);
|
|
88
|
-
if (solBalance < 10_000) {
|
|
89
|
-
return {
|
|
90
|
-
success: false,
|
|
91
|
-
text: `Insufficient SOL for tx fees: ${solBalance} lamports`,
|
|
92
|
-
data: { market_id, sol_balance_lamports: solBalance },
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
let ixs;
|
|
97
|
-
try {
|
|
98
|
-
ixs = await createDepositMarketIx(connection, payer, market_id, amountNative);
|
|
99
|
-
} catch (error) {
|
|
100
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
-
if (message.includes('MarketVault not found')) {
|
|
102
|
-
return {
|
|
103
|
-
success: false,
|
|
104
|
-
text:
|
|
105
|
-
`Market ${market_id} does not have a live vault yet. ` +
|
|
106
|
-
'Choose a depositable market and retry.',
|
|
107
|
-
data: { market_id, reason: 'missing_vault' },
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
ixs.unshift(
|
|
114
|
-
ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }),
|
|
115
|
-
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priority_fee }),
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
const { blockhash, lastValidBlockHeight } =
|
|
119
|
-
await connection.getLatestBlockhash('confirmed');
|
|
120
|
-
const message = new TransactionMessage({
|
|
121
|
-
payerKey: payer,
|
|
122
|
-
recentBlockhash: blockhash,
|
|
123
|
-
instructions: ixs,
|
|
124
|
-
}).compileToV0Message();
|
|
125
|
-
|
|
126
|
-
const tx = new VersionedTransaction(message);
|
|
127
|
-
const signedTx = await agent.wallet.signTransaction(tx);
|
|
128
|
-
|
|
129
|
-
const sim = await connection.simulateTransaction(signedTx);
|
|
130
|
-
if (sim.value.err) {
|
|
131
|
-
return {
|
|
132
|
-
success: false,
|
|
133
|
-
text: `Simulation failed: ${JSON.stringify(sim.value.err)}`,
|
|
134
|
-
data: { market_id, logs: sim.value.logs?.slice(-5) ?? [] },
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const { signature } = await agent.wallet.signAndSendTransaction(tx, {
|
|
139
|
-
skipPreflight: true,
|
|
140
|
-
maxRetries: 3,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
const confirmed = connection.confirmTransaction(
|
|
144
|
-
{ signature, blockhash, lastValidBlockHeight },
|
|
145
|
-
'confirmed',
|
|
146
|
-
);
|
|
147
|
-
const timeout = new Promise<never>((_, reject) =>
|
|
148
|
-
setTimeout(
|
|
149
|
-
() => reject(new Error(`Timeout after ${CONFIRM_TIMEOUT_MS}ms`)),
|
|
150
|
-
CONFIRM_TIMEOUT_MS,
|
|
151
|
-
),
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
await Promise.race([confirmed, timeout]);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
return {
|
|
158
|
-
success: true,
|
|
159
|
-
text:
|
|
160
|
-
`Deposit transaction sent for Market #${market_id}, but confirmation timed out. ` +
|
|
161
|
-
`Tx: ${signature}`,
|
|
162
|
-
data: {
|
|
163
|
-
signature,
|
|
164
|
-
market_id,
|
|
165
|
-
amount_usdc,
|
|
166
|
-
timed_out: true,
|
|
167
|
-
explorer: `https://solscan.io/tx/${signature}`,
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const elapsed = Date.now() - t0;
|
|
173
|
-
return {
|
|
174
|
-
success: true,
|
|
175
|
-
text:
|
|
176
|
-
`Deposited ${amount_usdc.toFixed(4)} USDC into Market #${market_id}. ` +
|
|
177
|
-
`Tx: ${signature.slice(0, 16)}... (${elapsed}ms, ${sim.value.unitsConsumed} CU)`,
|
|
178
|
-
data: {
|
|
179
|
-
signature,
|
|
180
|
-
market_id,
|
|
181
|
-
amount_usdc,
|
|
182
|
-
cu_used: sim.value.unitsConsumed,
|
|
183
|
-
elapsed_ms: elapsed,
|
|
184
|
-
explorer: `https://solscan.io/tx/${signature}`,
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async function loadSdk(): Promise<WzrdSdk> {
|
|
190
|
-
try {
|
|
191
|
-
return await import('@wzrd_sol/sdk');
|
|
192
|
-
} catch (error) {
|
|
193
|
-
const fallbackUrl = new URL('../../../../sdk/dist/index.js', import.meta.url);
|
|
194
|
-
try {
|
|
195
|
-
return (await import(fallbackUrl.href)) as WzrdSdk;
|
|
196
|
-
} catch {
|
|
197
|
-
throw error;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export const DEPOSIT_ACTION: Action = {
|
|
203
|
-
name: 'wzrd_deposit',
|
|
204
|
-
similes: ['wzrd_invest', 'deposit_usdc', 'buy_attention', 'enter_market'],
|
|
205
|
-
description:
|
|
206
|
-
'Deposit USDC into a WZRD attention market to mint vLOFI tokens. ' +
|
|
207
|
-
'vLOFI represents your position in the market. As the underlying AI model ' +
|
|
208
|
-
'gains attention (downloads, stars), your multiplier increases and you earn ' +
|
|
209
|
-
'more CCM on each merkle root publication. ' +
|
|
210
|
-
'Requires: market_id (from leaderboard) and amount_usdc (e.g., 0.01). ' +
|
|
211
|
-
'The deposit is atomic — USDC is transferred and vLOFI is minted in one transaction.',
|
|
212
|
-
|
|
213
|
-
examples: [
|
|
214
|
-
[
|
|
215
|
-
{
|
|
216
|
-
input: { market_id: 10, amount_usdc: 0.01 },
|
|
217
|
-
output: {
|
|
218
|
-
success: true,
|
|
219
|
-
market_id: 10,
|
|
220
|
-
amount_usdc: 0.01,
|
|
221
|
-
signature: 'X7FG...',
|
|
222
|
-
},
|
|
223
|
-
explanation: 'Deposit 0.01 USDC into a known vaulted market and mint vLOFI.',
|
|
224
|
-
},
|
|
225
|
-
],
|
|
226
|
-
],
|
|
227
|
-
schema: depositSchema,
|
|
228
|
-
handler: async (agent, input) => depositHandler(agent, depositSchema.parse(input)),
|
|
229
|
-
};
|
package/src/actions/index.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export type { MarketSignal } from './velocity.js';
|
|
2
|
-
export { LEADERBOARD_ACTION } from './leaderboard.js';
|
|
3
|
-
export { PORTFOLIO_ACTION } from './portfolio.js';
|
|
4
|
-
export { DEPOSIT_ACTION } from './deposit.js';
|
|
5
|
-
export { CLAIM_ACTION } from './claim.js';
|
|
6
|
-
export { VELOCITY_ACTION } from './velocity.js';
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action: wzrd_leaderboard
|
|
3
|
-
*
|
|
4
|
-
* Fetch the WZRD attention market leaderboard — ranked by velocity EMA.
|
|
5
|
-
* No auth required. Permissionless read.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
import type { Action, SolanaAgentKit } from 'solana-agent-kit';
|
|
10
|
-
|
|
11
|
-
import { formatVelocity, getLeaderboardData } from '../runtime.js';
|
|
12
|
-
|
|
13
|
-
export const leaderboardSchema = z.object({
|
|
14
|
-
limit: z.number().int().min(1).max(50).optional(),
|
|
15
|
-
platform: z.string().min(1).optional(),
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export async function leaderboardHandler(
|
|
19
|
-
agent: SolanaAgentKit,
|
|
20
|
-
input: z.infer<typeof leaderboardSchema>,
|
|
21
|
-
): Promise<Record<string, unknown>> {
|
|
22
|
-
const data = await getLeaderboardData(agent, input);
|
|
23
|
-
|
|
24
|
-
const lines = data.markets.map(
|
|
25
|
-
(m, i) =>
|
|
26
|
-
`${i + 1}. ${m.metric} — ${formatVelocity(m.velocity_ema)} velocity ` +
|
|
27
|
-
`(${m.platform}) | ${m.multiplier_bps / 10000}x multiplier | ` +
|
|
28
|
-
`${m.position_count} positions | market_id=${m.market_id}`,
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
success: true,
|
|
33
|
-
text:
|
|
34
|
-
`WZRD Leaderboard (${data.markets.length} markets, ` +
|
|
35
|
-
`root_seq=${data.root.root_seq}):\n${lines.join('\n')}`,
|
|
36
|
-
data,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const LEADERBOARD_ACTION: Action = {
|
|
41
|
-
name: 'wzrd_leaderboard',
|
|
42
|
-
similes: ['wzrd_markets', 'wzrd_trending', 'attention_markets', 'top_models'],
|
|
43
|
-
description:
|
|
44
|
-
'Fetch the WZRD attention market leaderboard. Shows AI models and open-source ' +
|
|
45
|
-
'projects ranked by real-time velocity (download/star momentum). Returns market IDs, ' +
|
|
46
|
-
'velocity EMA, multiplier, TVL, and platform (huggingface/github). ' +
|
|
47
|
-
'Use this to find the highest-attention markets before depositing.',
|
|
48
|
-
|
|
49
|
-
examples: [
|
|
50
|
-
[
|
|
51
|
-
{
|
|
52
|
-
input: { limit: 3 },
|
|
53
|
-
output: {
|
|
54
|
-
success: true,
|
|
55
|
-
root_seq: 1549,
|
|
56
|
-
markets: ['#16 Qwen 3.5 35B', '#14 Qwen 3.5 9B', '#10 Qwen 2.5 72B'],
|
|
57
|
-
},
|
|
58
|
-
explanation: 'Fetch the top three WZRD markets without requiring auth.',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
],
|
|
62
|
-
schema: leaderboardSchema,
|
|
63
|
-
handler: async (agent, input) => leaderboardHandler(agent, leaderboardSchema.parse(input)),
|
|
64
|
-
};
|
package/src/actions/portfolio.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action: wzrd_portfolio
|
|
3
|
-
*
|
|
4
|
-
* Fetch the agent's WZRD portfolio — positions, USDC deposited, vLOFI held, CCM earned.
|
|
5
|
-
* Requires auth (Ed25519 agent session).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
import type { Action, SolanaAgentKit } from 'solana-agent-kit';
|
|
10
|
-
|
|
11
|
-
import { formatCcm, formatUsdc, getPortfolioData } from '../runtime.js';
|
|
12
|
-
|
|
13
|
-
export const portfolioSchema = z.object({});
|
|
14
|
-
|
|
15
|
-
export async function portfolioHandler(
|
|
16
|
-
agent: SolanaAgentKit,
|
|
17
|
-
_input: z.infer<typeof portfolioSchema>,
|
|
18
|
-
): Promise<Record<string, unknown>> {
|
|
19
|
-
const portfolio = await getPortfolioData(agent);
|
|
20
|
-
const open = portfolio.positions.filter((p) => !p.is_settled);
|
|
21
|
-
const lines = open.map(
|
|
22
|
-
(p) =>
|
|
23
|
-
`• Market #${p.market_id} (${p.metric}): ` +
|
|
24
|
-
`${formatUsdc(p.usdc_deposited)} USDC, ` +
|
|
25
|
-
`${(p.multiplier_bps / 10_000).toFixed(1)}x multiplier` +
|
|
26
|
-
(p.is_settled ? ' [settled]' : ''),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
success: true,
|
|
31
|
-
text:
|
|
32
|
-
`Your WZRD portfolio (${open.length} open positions):\n` +
|
|
33
|
-
`${lines.length ? lines.join('\n') : '(no positions)'}\n` +
|
|
34
|
-
`Total: ${formatUsdc(portfolio.total_deposited_usdc)} USDC deposited, ` +
|
|
35
|
-
`${formatCcm(portfolio.total_ccm_earned)} CCM earned`,
|
|
36
|
-
data: portfolio,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const PORTFOLIO_ACTION: Action = {
|
|
41
|
-
name: 'wzrd_portfolio',
|
|
42
|
-
similes: ['wzrd_positions', 'wzrd_balance', 'wzrd_holdings', 'my_positions'],
|
|
43
|
-
description:
|
|
44
|
-
'Fetch your WZRD portfolio — all open positions across attention markets. ' +
|
|
45
|
-
'Shows USDC deposited, vLOFI minted, multiplier, and settlement status per market. ' +
|
|
46
|
-
'Use this to check your exposure before depositing more or claiming CCM.',
|
|
47
|
-
|
|
48
|
-
examples: [
|
|
49
|
-
[
|
|
50
|
-
{
|
|
51
|
-
input: {},
|
|
52
|
-
output: {
|
|
53
|
-
success: true,
|
|
54
|
-
open_positions: 2,
|
|
55
|
-
total_deposited_usdc: 20000,
|
|
56
|
-
total_ccm_earned: 0,
|
|
57
|
-
},
|
|
58
|
-
explanation: 'Fetch the authenticated agent portfolio and summarize open exposure.',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
],
|
|
62
|
-
schema: portfolioSchema,
|
|
63
|
-
handler: async (agent, input) => portfolioHandler(agent, portfolioSchema.parse(input)),
|
|
64
|
-
};
|
package/src/actions/velocity.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action: wzrd_velocity
|
|
3
|
-
*
|
|
4
|
-
* Analyze attention velocity across markets — classify signal strength.
|
|
5
|
-
* No auth required. Pure analytics over leaderboard data.
|
|
6
|
-
*
|
|
7
|
-
* Signal tiers:
|
|
8
|
-
* BREAKOUT — top 10% velocity (p90+)
|
|
9
|
-
* MOMENTUM — p70-90
|
|
10
|
-
* EMERGING — new market (<300 snapshots) with above-median velocity
|
|
11
|
-
* STABLE — p40-70
|
|
12
|
-
* COOLING — p20-40
|
|
13
|
-
* WEAK — below p20
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { z } from 'zod';
|
|
17
|
-
import type { Action, SolanaAgentKit } from 'solana-agent-kit';
|
|
18
|
-
import type { WzrdMarket } from '../client.js';
|
|
19
|
-
|
|
20
|
-
import { formatVelocity, getLeaderboardData, type SignalTier } from '../runtime.js';
|
|
21
|
-
|
|
22
|
-
export interface MarketSignal {
|
|
23
|
-
market_id: number;
|
|
24
|
-
metric: string;
|
|
25
|
-
platform: string;
|
|
26
|
-
velocity_ema: number;
|
|
27
|
-
signal: SignalTier;
|
|
28
|
-
percentile: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
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 = {
|
|
104
|
-
name: 'wzrd_velocity',
|
|
105
|
-
similes: ['wzrd_signal', 'attention_signal', 'market_analysis', 'velocity_check'],
|
|
106
|
-
description:
|
|
107
|
-
'Analyze attention velocity across WZRD markets. Classifies each market into ' +
|
|
108
|
-
'signal tiers: BREAKOUT (top 10%), MOMENTUM (70-90th percentile), EMERGING ' +
|
|
109
|
-
'(new + above median), STABLE, COOLING, WEAK. ' +
|
|
110
|
-
'Use this to find the best deposit opportunities — BREAKOUT and MOMENTUM ' +
|
|
111
|
-
'markets have the strongest attention momentum.',
|
|
112
|
-
|
|
113
|
-
examples: [
|
|
114
|
-
[
|
|
115
|
-
{
|
|
116
|
-
input: { min_signal: 'MOMENTUM' },
|
|
117
|
-
output: {
|
|
118
|
-
success: true,
|
|
119
|
-
signals: ['BREAKOUT: Qwen 3.5 35B', 'MOMENTUM: Qwen 2.5 72B'],
|
|
120
|
-
},
|
|
121
|
-
explanation: 'Classify the current leaderboard into signal tiers for deposit decisions.',
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
],
|
|
125
|
-
schema: velocitySchema,
|
|
126
|
-
handler: async (agent, input) => velocityHandler(agent, velocitySchema.parse(input)),
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
function classify(m: WzrdMarket, percentile: number): SignalTier {
|
|
130
|
-
if (percentile >= 90) return 'BREAKOUT';
|
|
131
|
-
if (percentile >= 70) return 'MOMENTUM';
|
|
132
|
-
if (m.snapshot_count < 300 && percentile >= 50) return 'EMERGING';
|
|
133
|
-
if (percentile >= 40) return 'STABLE';
|
|
134
|
-
if (percentile >= 20) return 'COOLING';
|
|
135
|
-
return 'WEAK';
|
|
136
|
-
}
|