@wzrd_sol/solana-agent-plugin 0.1.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 +70 -0
- package/dist/actions/claim.d.ts +38 -0
- package/dist/actions/claim.js +84 -0
- package/dist/actions/deposit.d.ts +57 -0
- package/dist/actions/deposit.js +134 -0
- package/dist/actions/index.d.ts +5 -0
- package/dist/actions/index.js +5 -0
- package/dist/actions/leaderboard.d.ts +27 -0
- package/dist/actions/leaderboard.js +63 -0
- package/dist/actions/portfolio.d.ts +24 -0
- package/dist/actions/portfolio.js +48 -0
- package/dist/actions/velocity.d.ts +55 -0
- package/dist/actions/velocity.js +118 -0
- package/dist/client.d.ts +82 -0
- package/dist/client.js +131 -0
- package/dist/index.d.ts +297 -0
- package/dist/index.js +44 -0
- package/examples/hello-wzrd.mjs +79 -0
- package/package.json +46 -0
- package/src/actions/claim.ts +98 -0
- package/src/actions/deposit.ts +197 -0
- package/src/actions/index.ts +5 -0
- package/src/actions/leaderboard.ts +81 -0
- package/src/actions/portfolio.ts +62 -0
- package/src/actions/velocity.ts +143 -0
- package/src/client.ts +207 -0
- package/src/index.ts +64 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* WZRD "Hello World" — prove an agent can interact in 30 seconds.
|
|
4
|
+
*
|
|
5
|
+
* What this does:
|
|
6
|
+
* 1. Read the leaderboard (no auth, 2 seconds)
|
|
7
|
+
* 2. Authenticate with Ed25519 (no browser, 1 second)
|
|
8
|
+
* 3. Check portfolio (what do I hold?)
|
|
9
|
+
* 4. Check claimable CCM (any rewards ready?)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* SOLANA_RPC_URL=https://... WZRD_KEYPAIR_PATH=~/.config/solana/id.json node hello-wzrd.mjs
|
|
13
|
+
*
|
|
14
|
+
* Or generate a fresh keypair:
|
|
15
|
+
* solana-keygen new -o /tmp/agent.json --no-bip39-passphrase
|
|
16
|
+
* SOLANA_RPC_URL=https://... WZRD_KEYPAIR_PATH=/tmp/agent.json node hello-wzrd.mjs
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
import { Keypair } from '@solana/web3.js';
|
|
21
|
+
import { WzrdClient } from '../dist/index.js';
|
|
22
|
+
|
|
23
|
+
const KEYPAIR_PATH = process.env.WZRD_KEYPAIR_PATH;
|
|
24
|
+
if (!KEYPAIR_PATH) {
|
|
25
|
+
console.log('Usage: WZRD_KEYPAIR_PATH=/path/to/keypair.json node hello-wzrd.mjs');
|
|
26
|
+
console.log('Generate one: solana-keygen new -o /tmp/agent.json --no-bip39-passphrase');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const raw = readFileSync(KEYPAIR_PATH, 'utf8');
|
|
31
|
+
const wallet = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(raw)));
|
|
32
|
+
const client = new WzrdClient(wallet);
|
|
33
|
+
|
|
34
|
+
console.log(`\n=== WZRD Hello World ===`);
|
|
35
|
+
console.log(`Agent: ${wallet.publicKey.toBase58()}\n`);
|
|
36
|
+
|
|
37
|
+
// 1. Leaderboard (public, no auth)
|
|
38
|
+
console.log('→ Fetching leaderboard...');
|
|
39
|
+
const board = await client.getLeaderboard(5);
|
|
40
|
+
console.log(` ${board.markets.length} markets, root_seq=${board.root.root_seq}`);
|
|
41
|
+
for (const m of board.markets) {
|
|
42
|
+
const vel = m.velocity_ema >= 1000 ? `${(m.velocity_ema/1000).toFixed(0)}K` : m.velocity_ema.toFixed(0);
|
|
43
|
+
console.log(` #${m.market_id} ${m.metric} — ${vel} velocity (${m.platform})`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Portfolio (auth required — triggers challenge/verify automatically)
|
|
47
|
+
console.log('\n→ Authenticating + fetching portfolio...');
|
|
48
|
+
try {
|
|
49
|
+
const portfolio = await client.getPortfolio();
|
|
50
|
+
const open = portfolio.positions.filter(p => !p.is_settled);
|
|
51
|
+
console.log(` ${open.length} open positions, ${(portfolio.total_deposited_usdc / 1e6).toFixed(4)} USDC total`);
|
|
52
|
+
for (const p of open) {
|
|
53
|
+
console.log(` • Market #${p.market_id}: ${(p.usdc_deposited / 1e6).toFixed(4)} USDC, ${(p.multiplier_bps / 10000).toFixed(1)}x`);
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.log(` No portfolio yet (${e instanceof Error ? e.message : e})`);
|
|
57
|
+
console.log(' → First-time agent? You got auto-funded 0.003 SOL + 1000 CCM signup bonus!');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 3. Claims check
|
|
61
|
+
console.log('\n→ Checking claimable CCM...');
|
|
62
|
+
try {
|
|
63
|
+
const claims = await client.getClaims();
|
|
64
|
+
const claimable = claims.cumulative_total - claims.claimed_total;
|
|
65
|
+
console.log(` Cumulative: ${claims.cumulative_total}, Claimed: ${claims.claimed_total}`);
|
|
66
|
+
console.log(` Claimable now: ${claimable > 0 ? claimable : 'none'}`);
|
|
67
|
+
if (claimable > 0) {
|
|
68
|
+
console.log(' → Run with --claim to harvest via gasless relay');
|
|
69
|
+
}
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.log(` No claims data yet (${e instanceof Error ? e.message : e})`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log('\n=== Done ===');
|
|
75
|
+
console.log('Next steps:');
|
|
76
|
+
console.log(' 1. Fund your wallet with USDC (even 0.01 is enough)');
|
|
77
|
+
console.log(' 2. Use wzrd_deposit to enter a market');
|
|
78
|
+
console.log(' 3. Wait ~10 min for scoring cycle');
|
|
79
|
+
console.log(' 4. Use wzrd_claim to harvest CCM (gasless — no SOL needed)');
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wzrd_sol/solana-agent-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "WZRD Liquid Attention Protocol plugin for Solana Agent Kit — deposit, claim, leaderboard, portfolio, velocity signal",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@solana/web3.js": "^1.95.0",
|
|
20
|
+
"@wzrd_sol/sdk": "^0.1.0",
|
|
21
|
+
"tweetnacl": "^1.0.3"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"solana-agent-kit": "^2.0.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"solana-agent-kit": {
|
|
28
|
+
"optional": true
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"solana",
|
|
33
|
+
"agent",
|
|
34
|
+
"wzrd",
|
|
35
|
+
"attention",
|
|
36
|
+
"defi",
|
|
37
|
+
"mcp",
|
|
38
|
+
"ai-agent",
|
|
39
|
+
"solana-agent-kit"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/twzrd-sol/wzrd-final"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action: wzrd_claim
|
|
3
|
+
*
|
|
4
|
+
* Claim accrued CCM tokens via the gasless relay.
|
|
5
|
+
* Server pays tx fees — agent doesn't need SOL to claim.
|
|
6
|
+
*
|
|
7
|
+
* Flow: check claimable amount → relay claim → receive CCM.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { WzrdClient } from '../client.js';
|
|
11
|
+
|
|
12
|
+
export const CLAIM_ACTION = {
|
|
13
|
+
name: 'wzrd_claim',
|
|
14
|
+
similes: ['wzrd_harvest', 'claim_ccm', 'redeem_rewards', 'collect_yield'],
|
|
15
|
+
description:
|
|
16
|
+
'Claim accrued CCM tokens from your WZRD positions. Uses the gasless relay — ' +
|
|
17
|
+
'the server pays transaction fees, so you don\'t need SOL to claim. ' +
|
|
18
|
+
'CCM accrues based on your velocity multiplier and is distributed via ' +
|
|
19
|
+
'merkle proofs published on-chain every ~10 minutes. ' +
|
|
20
|
+
'Call this periodically to harvest your earned CCM.',
|
|
21
|
+
|
|
22
|
+
examples: [
|
|
23
|
+
[
|
|
24
|
+
{
|
|
25
|
+
user: 'user',
|
|
26
|
+
content: { text: 'Claim my CCM rewards' },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
user: 'assistant',
|
|
30
|
+
content: {
|
|
31
|
+
text: 'Claimed 100,000 CCM via gasless relay. ' +
|
|
32
|
+
'Cumulative total: 250,000 CCM. Tx: 2VKz...J39c',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
{
|
|
38
|
+
user: 'user',
|
|
39
|
+
content: { text: 'How much CCM can I claim?' },
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
user: 'assistant',
|
|
43
|
+
content: {
|
|
44
|
+
text: 'You have 100,000 CCM claimable (250,000 cumulative, 150,000 already claimed). ' +
|
|
45
|
+
'Shall I claim it now?',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
],
|
|
50
|
+
|
|
51
|
+
validate: async () => true,
|
|
52
|
+
|
|
53
|
+
handler: async (client: WzrdClient, params: { execute?: boolean }) => {
|
|
54
|
+
// 1. Check claimable amount
|
|
55
|
+
const claims = await client.getClaims();
|
|
56
|
+
const claimable = claims.cumulative_total - claims.claimed_total;
|
|
57
|
+
|
|
58
|
+
if (claimable <= 0) {
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
text:
|
|
62
|
+
`No CCM to claim. Cumulative: ${claims.cumulative_total}, ` +
|
|
63
|
+
`already claimed: ${claims.claimed_total}. ` +
|
|
64
|
+
`Deposit into markets and wait for the next scoring cycle.`,
|
|
65
|
+
data: claims,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 2. If just checking (not executing), report the amount
|
|
70
|
+
if (params.execute === false) {
|
|
71
|
+
return {
|
|
72
|
+
success: true,
|
|
73
|
+
text:
|
|
74
|
+
`${claimable} CCM claimable ` +
|
|
75
|
+
`(${claims.cumulative_total} cumulative, ${claims.claimed_total} claimed). ` +
|
|
76
|
+
`Root seq: ${claims.root_seq}. Call with execute=true to claim.`,
|
|
77
|
+
data: claims,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3. Execute gasless relay claim
|
|
82
|
+
const result = await client.claimRelay();
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
text:
|
|
87
|
+
`Claimed CCM via gasless relay. ` +
|
|
88
|
+
`Cumulative total: ${result.cumulative_total}. ` +
|
|
89
|
+
`Root seq: ${result.root_seq}. ` +
|
|
90
|
+
`Tx: ${result.tx_sig.slice(0, 16)}...`,
|
|
91
|
+
data: {
|
|
92
|
+
...result,
|
|
93
|
+
claimable_before: claimable,
|
|
94
|
+
explorer: `https://solscan.io/tx/${result.tx_sig}`,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
};
|
|
@@ -0,0 +1,197 @@
|
|
|
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
|
+
Connection,
|
|
13
|
+
Keypair,
|
|
14
|
+
ComputeBudgetProgram,
|
|
15
|
+
TransactionMessage,
|
|
16
|
+
VersionedTransaction,
|
|
17
|
+
} from '@solana/web3.js';
|
|
18
|
+
import {
|
|
19
|
+
createDepositMarketIx,
|
|
20
|
+
fetchOnChainPosition,
|
|
21
|
+
fetchTokenBalance,
|
|
22
|
+
getAta,
|
|
23
|
+
TOKEN_PROGRAM_ID,
|
|
24
|
+
} from '@wzrd_sol/sdk';
|
|
25
|
+
|
|
26
|
+
import type { WzrdClient } from '../client.js';
|
|
27
|
+
|
|
28
|
+
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
29
|
+
const CONFIRM_TIMEOUT_MS = 60_000;
|
|
30
|
+
|
|
31
|
+
export interface DepositParams {
|
|
32
|
+
market_id: number;
|
|
33
|
+
amount_usdc: number;
|
|
34
|
+
priority_fee?: number; // microLamports per CU, default 50_000
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const DEPOSIT_ACTION = {
|
|
38
|
+
name: 'wzrd_deposit',
|
|
39
|
+
similes: ['wzrd_invest', 'deposit_usdc', 'buy_attention', 'enter_market'],
|
|
40
|
+
description:
|
|
41
|
+
'Deposit USDC into a WZRD attention market to mint vLOFI tokens. ' +
|
|
42
|
+
'vLOFI represents your position in the market. As the underlying AI model ' +
|
|
43
|
+
'gains attention (downloads, stars), your multiplier increases and you earn ' +
|
|
44
|
+
'more CCM on each merkle root publication. ' +
|
|
45
|
+
'Requires: market_id (from leaderboard) and amount_usdc (e.g., 0.01). ' +
|
|
46
|
+
'The deposit is atomic — USDC is transferred and vLOFI is minted in one transaction.',
|
|
47
|
+
|
|
48
|
+
examples: [
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
user: 'user',
|
|
52
|
+
content: { text: 'Deposit 0.01 USDC into market 10' },
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
user: 'assistant',
|
|
56
|
+
content: {
|
|
57
|
+
text: 'Deposited 0.01 USDC into Market #10 (Qwen 2.5 72B). ' +
|
|
58
|
+
'Received 10,000 vLOFI. Tx: X7FG...Cziv (772ms, 50687 CU)',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
[
|
|
63
|
+
{
|
|
64
|
+
user: 'user',
|
|
65
|
+
content: { text: 'Invest in the highest velocity market' },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
user: 'assistant',
|
|
69
|
+
content: {
|
|
70
|
+
text: 'Looking up leaderboard... Top market is #16 (Qwen 3.5 35B) ' +
|
|
71
|
+
'with 804K velocity. Depositing 0.01 USDC...',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
],
|
|
76
|
+
|
|
77
|
+
validate: async (_client: WzrdClient, params: DepositParams) => {
|
|
78
|
+
if (!params.market_id || params.market_id < 1) return false;
|
|
79
|
+
if (!params.amount_usdc || params.amount_usdc <= 0) return false;
|
|
80
|
+
if (params.amount_usdc > 100) return false; // safety cap
|
|
81
|
+
return true;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
handler: async (
|
|
85
|
+
_client: WzrdClient,
|
|
86
|
+
params: DepositParams,
|
|
87
|
+
connection: Connection,
|
|
88
|
+
wallet: Keypair,
|
|
89
|
+
) => {
|
|
90
|
+
const { market_id, amount_usdc, priority_fee = 50_000 } = params;
|
|
91
|
+
const amountNative = BigInt(Math.round(amount_usdc * 1_000_000));
|
|
92
|
+
const t0 = Date.now();
|
|
93
|
+
|
|
94
|
+
// 1. Idempotency — check existing position
|
|
95
|
+
const existing = await fetchOnChainPosition(
|
|
96
|
+
connection,
|
|
97
|
+
wallet.publicKey,
|
|
98
|
+
market_id,
|
|
99
|
+
);
|
|
100
|
+
if (existing && existing.depositedAmount > 0n && !existing.settled) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
text: `Position already exists in market ${market_id} ` +
|
|
104
|
+
`(${existing.depositedAmount} deposited). Cannot double-deposit.`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 2. Balance checks
|
|
109
|
+
const { PublicKey } = await import('@solana/web3.js');
|
|
110
|
+
const usdcMint = new PublicKey(USDC_MINT);
|
|
111
|
+
const usdcAta = getAta(wallet.publicKey, usdcMint, TOKEN_PROGRAM_ID);
|
|
112
|
+
const usdcBalance = await fetchTokenBalance(connection, usdcAta);
|
|
113
|
+
if (usdcBalance < amountNative) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
text: `Insufficient USDC: have ${Number(usdcBalance) / 1e6}, need ${amount_usdc}`,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const solBalance = await connection.getBalance(wallet.publicKey);
|
|
121
|
+
if (solBalance < 10_000) {
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
text: `Insufficient SOL for tx fees: ${solBalance} lamports`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 3. Build deposit instructions
|
|
129
|
+
const ixs = await createDepositMarketIx(
|
|
130
|
+
connection,
|
|
131
|
+
wallet.publicKey,
|
|
132
|
+
market_id,
|
|
133
|
+
amountNative,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
ixs.unshift(
|
|
137
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }),
|
|
138
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priority_fee }),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// 4. Simulate
|
|
142
|
+
const { blockhash, lastValidBlockHeight } =
|
|
143
|
+
await connection.getLatestBlockhash('confirmed');
|
|
144
|
+
const message = new TransactionMessage({
|
|
145
|
+
payerKey: wallet.publicKey,
|
|
146
|
+
recentBlockhash: blockhash,
|
|
147
|
+
instructions: ixs,
|
|
148
|
+
}).compileToV0Message();
|
|
149
|
+
|
|
150
|
+
const tx = new VersionedTransaction(message);
|
|
151
|
+
tx.sign([wallet]);
|
|
152
|
+
|
|
153
|
+
const sim = await connection.simulateTransaction(tx);
|
|
154
|
+
if (sim.value.err) {
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
text: `Simulation failed: ${JSON.stringify(sim.value.err)}`,
|
|
158
|
+
data: { logs: sim.value.logs?.slice(-5) },
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 5. Send + confirm
|
|
163
|
+
const signature = await connection.sendTransaction(tx, {
|
|
164
|
+
skipPreflight: true,
|
|
165
|
+
maxRetries: 3,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const confirmed = connection.confirmTransaction(
|
|
169
|
+
{ signature, blockhash, lastValidBlockHeight },
|
|
170
|
+
'confirmed',
|
|
171
|
+
);
|
|
172
|
+
const timeout = new Promise<never>((_, reject) =>
|
|
173
|
+
setTimeout(
|
|
174
|
+
() => reject(new Error(`Timeout after ${CONFIRM_TIMEOUT_MS}ms`)),
|
|
175
|
+
CONFIRM_TIMEOUT_MS,
|
|
176
|
+
),
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
await Promise.race([confirmed, timeout]);
|
|
180
|
+
const elapsed = Date.now() - t0;
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
success: true,
|
|
184
|
+
text:
|
|
185
|
+
`Deposited ${amount_usdc} USDC into Market #${market_id}. ` +
|
|
186
|
+
`Tx: ${signature.slice(0, 16)}... (${elapsed}ms, ${sim.value.unitsConsumed} CU)`,
|
|
187
|
+
data: {
|
|
188
|
+
signature,
|
|
189
|
+
market_id,
|
|
190
|
+
amount_usdc,
|
|
191
|
+
cu_used: sim.value.unitsConsumed,
|
|
192
|
+
elapsed_ms: elapsed,
|
|
193
|
+
explorer: `https://solscan.io/tx/${signature}`,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
},
|
|
197
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
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 type { WzrdClient, WzrdMarket } from '../client.js';
|
|
9
|
+
|
|
10
|
+
export const LEADERBOARD_ACTION = {
|
|
11
|
+
name: 'wzrd_leaderboard',
|
|
12
|
+
similes: ['wzrd_markets', 'wzrd_trending', 'attention_markets', 'top_models'],
|
|
13
|
+
description:
|
|
14
|
+
'Fetch the WZRD attention market leaderboard. Shows AI models and open-source ' +
|
|
15
|
+
'projects ranked by real-time velocity (download/star momentum). Returns market IDs, ' +
|
|
16
|
+
'velocity EMA, multiplier, TVL, and platform (huggingface/github). ' +
|
|
17
|
+
'Use this to find the highest-attention markets before depositing.',
|
|
18
|
+
|
|
19
|
+
examples: [
|
|
20
|
+
[
|
|
21
|
+
{
|
|
22
|
+
user: 'user',
|
|
23
|
+
content: { text: 'Show me the top attention markets' },
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
user: 'assistant',
|
|
27
|
+
content: {
|
|
28
|
+
text: 'Here are the top WZRD markets by velocity:\n' +
|
|
29
|
+
'1. Qwen 3.5 35B — 804K velocity (HuggingFace)\n' +
|
|
30
|
+
'2. Qwen 3.5 9B — 769K velocity (HuggingFace)\n' +
|
|
31
|
+
'3. Ollama — 104K velocity (GitHub)',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
{
|
|
37
|
+
user: 'user',
|
|
38
|
+
content: { text: 'What HuggingFace models are trending?' },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
user: 'assistant',
|
|
42
|
+
content: {
|
|
43
|
+
text: 'Top HuggingFace models by attention velocity: ...',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
validate: async () => true,
|
|
50
|
+
|
|
51
|
+
handler: async (
|
|
52
|
+
client: WzrdClient,
|
|
53
|
+
params: { limit?: number; platform?: string },
|
|
54
|
+
) => {
|
|
55
|
+
const data = await client.getLeaderboard(
|
|
56
|
+
params.limit ?? 10,
|
|
57
|
+
params.platform,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const lines = data.markets.map(
|
|
61
|
+
(m: WzrdMarket, i: number) =>
|
|
62
|
+
`${i + 1}. ${m.metric} — ${formatVelocity(m.velocity_ema)} velocity ` +
|
|
63
|
+
`(${m.platform}) | ${m.multiplier_bps / 10000}x multiplier | ` +
|
|
64
|
+
`${m.position_count} positions | market_id=${m.market_id}`,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
text:
|
|
70
|
+
`WZRD Leaderboard (${data.markets.length} markets, ` +
|
|
71
|
+
`root_seq=${data.root.root_seq}):\n${lines.join('\n')}`,
|
|
72
|
+
data,
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
function formatVelocity(v: number): string {
|
|
78
|
+
if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;
|
|
79
|
+
if (v >= 1_000) return `${(v / 1_000).toFixed(0)}K`;
|
|
80
|
+
return v.toFixed(0);
|
|
81
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
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 type { WzrdClient, WzrdPosition } from '../client.js';
|
|
9
|
+
|
|
10
|
+
export const PORTFOLIO_ACTION = {
|
|
11
|
+
name: 'wzrd_portfolio',
|
|
12
|
+
similes: ['wzrd_positions', 'wzrd_balance', 'wzrd_holdings', 'my_positions'],
|
|
13
|
+
description:
|
|
14
|
+
'Fetch your WZRD portfolio — all open positions across attention markets. ' +
|
|
15
|
+
'Shows USDC deposited, vLOFI minted, multiplier, and settlement status per market. ' +
|
|
16
|
+
'Use this to check your exposure before depositing more or claiming CCM.',
|
|
17
|
+
|
|
18
|
+
examples: [
|
|
19
|
+
[
|
|
20
|
+
{
|
|
21
|
+
user: 'user',
|
|
22
|
+
content: { text: 'Show my WZRD positions' },
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
user: 'assistant',
|
|
26
|
+
content: {
|
|
27
|
+
text: 'Your WZRD portfolio:\n' +
|
|
28
|
+
'• Market #10 (Qwen 2.5 72B): 0.01 USDC, 5.0x multiplier\n' +
|
|
29
|
+
'• Market #8 (Ollama): 0.01 USDC, 5.0x multiplier\n' +
|
|
30
|
+
'Total: 0.02 USDC deposited, 0 CCM earned',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
],
|
|
35
|
+
|
|
36
|
+
validate: async () => true,
|
|
37
|
+
|
|
38
|
+
handler: async (client: WzrdClient) => {
|
|
39
|
+
const portfolio = await client.getPortfolio();
|
|
40
|
+
|
|
41
|
+
const open = portfolio.positions.filter((p: WzrdPosition) => !p.is_settled);
|
|
42
|
+
const lines = open.map(
|
|
43
|
+
(p: WzrdPosition) =>
|
|
44
|
+
`• Market #${p.market_id} (${p.metric}): ` +
|
|
45
|
+
`${(p.usdc_deposited / 1_000_000).toFixed(4)} USDC, ` +
|
|
46
|
+
`${(p.multiplier_bps / 10_000).toFixed(1)}x multiplier` +
|
|
47
|
+
(p.is_settled ? ' [settled]' : ''),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const totalUsdc = portfolio.total_deposited_usdc / 1_000_000;
|
|
51
|
+
const totalCcm = portfolio.total_ccm_earned / 1_000_000;
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
success: true,
|
|
55
|
+
text:
|
|
56
|
+
`Your WZRD portfolio (${open.length} open positions):\n` +
|
|
57
|
+
`${lines.length ? lines.join('\n') : '(no positions)'}\n` +
|
|
58
|
+
`Total: ${totalUsdc.toFixed(4)} USDC deposited, ${totalCcm.toFixed(4)} CCM earned`,
|
|
59
|
+
data: portfolio,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|