@wzrd_sol/sdk 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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Unit tests for SDK instruction builders and helpers.
3
+ *
4
+ * Tests the sync / pure parts of instructions.ts, pda.ts, accounts.ts, and constants.ts
5
+ * without requiring an RPC Connection.
6
+ */
7
+ export {};
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Unit tests for SDK instruction builders and helpers.
3
+ *
4
+ * Tests the sync / pure parts of instructions.ts, pda.ts, accounts.ts, and constants.ts
5
+ * without requiring an RPC Connection.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ import { PublicKey, SystemProgram } from '@solana/web3.js';
9
+ import { anchorDisc, createAtaIdempotentIx, createAddLiquidityIx, createRemoveLiquidityIx, DLMM_PROGRAM_ID, } from './instructions.js';
10
+ import { PROGRAM_ID, MAINNET_PROGRAM_ID, DEVNET_PROGRAM_ID, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, PROTOCOL_STATE_SEED, MARKET_VAULT_SEED, MARKET_POSITION_SEED, GLOBAL_ROOT_SEED, CLAIM_STATE_GLOBAL_SEED, CHANNEL_CONFIG_V2_SEED, } from './constants.js';
11
+ import { getProtocolStatePDA, getMarketVaultPDA, getUserPositionPDA, getGlobalRootConfigPDA, getClaimStatePDA, getChannelConfigV2PDA, getAta, } from './pda.js';
12
+ import { parseMarketVault, parseProtocolState, parseUserMarketPosition, } from './accounts.js';
13
+ // ── Test fixtures ────────────────────────────────────────
14
+ const DUMMY_KEY_A = new PublicKey('11111111111111111111111111111111');
15
+ const DUMMY_KEY_B = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
16
+ const CCM_MINT = new PublicKey('Dxk8mAb3C7AM8JN6tAJfVuSja5yidhZM5sEKW3SRX2BM');
17
+ const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
18
+ // ── anchorDisc ──────────────────────────────────────────
19
+ describe('anchorDisc', () => {
20
+ it('produces an 8-byte Buffer', async () => {
21
+ const disc = await anchorDisc('deposit_market');
22
+ expect(disc).toBeInstanceOf(Buffer);
23
+ expect(disc.length).toBe(8);
24
+ });
25
+ it('is deterministic — same name gives same bytes', async () => {
26
+ const a = await anchorDisc('deposit_market');
27
+ const b = await anchorDisc('deposit_market');
28
+ expect(a.equals(b)).toBe(true);
29
+ });
30
+ it('different names produce different discriminators', async () => {
31
+ const deposit = await anchorDisc('deposit_market');
32
+ const settle = await anchorDisc('settle_market');
33
+ expect(deposit.equals(settle)).toBe(false);
34
+ });
35
+ it('matches SHA-256("global:<name>")[0..8]', async () => {
36
+ // We manually verify deposit_market against the Node.js crypto module
37
+ const { createHash } = await import('crypto');
38
+ const hash = createHash('sha256').update('global:deposit_market').digest();
39
+ const expected = hash.subarray(0, 8);
40
+ const disc = await anchorDisc('deposit_market');
41
+ expect(disc.equals(expected)).toBe(true);
42
+ });
43
+ it('produces correct disc for claim_global', async () => {
44
+ const { createHash } = await import('crypto');
45
+ const hash = createHash('sha256').update('global:claim_global').digest();
46
+ const expected = hash.subarray(0, 8);
47
+ const disc = await anchorDisc('claim_global');
48
+ expect(disc.equals(expected)).toBe(true);
49
+ });
50
+ it('handles empty name gracefully', async () => {
51
+ const disc = await anchorDisc('');
52
+ expect(disc.length).toBe(8);
53
+ });
54
+ it('handles snake_case names', async () => {
55
+ const disc = await anchorDisc('initialize_market_vault');
56
+ expect(disc.length).toBe(8);
57
+ });
58
+ });
59
+ // ── createAtaIdempotentIx ───────────────────────────────
60
+ describe('createAtaIdempotentIx', () => {
61
+ it('uses ASSOCIATED_TOKEN_PROGRAM_ID as programId', () => {
62
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
63
+ expect(ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)).toBe(true);
64
+ });
65
+ it('has exactly 6 account keys', () => {
66
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
67
+ expect(ix.keys.length).toBe(6);
68
+ });
69
+ it('sets payer as signer + writable', () => {
70
+ const payer = CCM_MINT;
71
+ const ix = createAtaIdempotentIx(payer, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
72
+ expect(ix.keys[0].pubkey.equals(payer)).toBe(true);
73
+ expect(ix.keys[0].isSigner).toBe(true);
74
+ expect(ix.keys[0].isWritable).toBe(true);
75
+ });
76
+ it('sets ata as writable, not signer', () => {
77
+ const ata = DUMMY_KEY_B;
78
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, ata, DUMMY_KEY_A, USDC_MINT);
79
+ expect(ix.keys[1].pubkey.equals(ata)).toBe(true);
80
+ expect(ix.keys[1].isSigner).toBe(false);
81
+ expect(ix.keys[1].isWritable).toBe(true);
82
+ });
83
+ it('data is single byte [1] (CreateIdempotent)', () => {
84
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
85
+ expect(ix.data.length).toBe(1);
86
+ expect(ix.data[0]).toBe(1);
87
+ });
88
+ it('defaults to TOKEN_PROGRAM_ID when no tokenProgramId provided', () => {
89
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
90
+ // 5th account is tokenProgramId
91
+ expect(ix.keys[5].pubkey.equals(TOKEN_PROGRAM_ID)).toBe(true);
92
+ });
93
+ it('uses Token-2022 when specified', () => {
94
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, CCM_MINT, TOKEN_2022_PROGRAM_ID);
95
+ expect(ix.keys[5].pubkey.equals(TOKEN_2022_PROGRAM_ID)).toBe(true);
96
+ });
97
+ it('includes SystemProgram in account keys', () => {
98
+ const ix = createAtaIdempotentIx(DUMMY_KEY_A, DUMMY_KEY_B, DUMMY_KEY_A, USDC_MINT);
99
+ expect(ix.keys[4].pubkey.equals(SystemProgram.programId)).toBe(true);
100
+ });
101
+ });
102
+ // ── createAddLiquidityIx ────────────────────────────────
103
+ describe('createAddLiquidityIx', () => {
104
+ const pool = PublicKey.unique();
105
+ const position = PublicKey.unique();
106
+ const owner = PublicKey.unique();
107
+ const tokenXMint = PublicKey.unique();
108
+ const tokenYMint = PublicKey.unique();
109
+ const userTokenX = PublicKey.unique();
110
+ const userTokenY = PublicKey.unique();
111
+ const reserveX = PublicKey.unique();
112
+ const reserveY = PublicKey.unique();
113
+ const binArrayLower = PublicKey.unique();
114
+ const binArrayUpper = PublicKey.unique();
115
+ const ix = createAddLiquidityIx(pool, position, owner, tokenXMint, tokenYMint, userTokenX, userTokenY, reserveX, reserveY, binArrayLower, binArrayUpper, 1000n, 2000n, 100, 5);
116
+ it('uses DLMM_PROGRAM_ID', () => {
117
+ expect(ix.programId.equals(DLMM_PROGRAM_ID)).toBe(true);
118
+ });
119
+ it('has 14 account keys', () => {
120
+ expect(ix.keys.length).toBe(14);
121
+ });
122
+ it('data is 33 bytes (8 disc + 8 amountX + 8 amountY + 4 activeBinId + 4 binCount + 1 strategyType)', () => {
123
+ expect(ix.data.length).toBe(33);
124
+ });
125
+ it('encodes amountX correctly as LE u64', () => {
126
+ const amountX = ix.data.readBigUInt64LE(8);
127
+ expect(amountX).toBe(1000n);
128
+ });
129
+ it('encodes amountY correctly as LE u64', () => {
130
+ const amountY = ix.data.readBigUInt64LE(16);
131
+ expect(amountY).toBe(2000n);
132
+ });
133
+ it('encodes activeBinId as LE i32', () => {
134
+ const activeBinId = ix.data.readInt32LE(24);
135
+ expect(activeBinId).toBe(100);
136
+ });
137
+ it('encodes binCount as LE i32', () => {
138
+ const binCount = ix.data.readInt32LE(28);
139
+ expect(binCount).toBe(5);
140
+ });
141
+ it('sets strategy type to 0 (Spot)', () => {
142
+ expect(ix.data.readUInt8(32)).toBe(0);
143
+ });
144
+ it('marks owner as signer', () => {
145
+ const ownerKey = ix.keys.find(k => k.pubkey.equals(owner));
146
+ expect(ownerKey?.isSigner).toBe(true);
147
+ });
148
+ });
149
+ // ── createRemoveLiquidityIx ─────────────────────────────
150
+ describe('createRemoveLiquidityIx', () => {
151
+ const pool = PublicKey.unique();
152
+ const position = PublicKey.unique();
153
+ const owner = PublicKey.unique();
154
+ const reserveX = PublicKey.unique();
155
+ const reserveY = PublicKey.unique();
156
+ const userTokenX = PublicKey.unique();
157
+ const userTokenY = PublicKey.unique();
158
+ const tokenXMint = PublicKey.unique();
159
+ const tokenYMint = PublicKey.unique();
160
+ const binArrayLower = PublicKey.unique();
161
+ const binArrayUpper = PublicKey.unique();
162
+ const ix = createRemoveLiquidityIx(pool, position, owner, reserveX, reserveY, userTokenX, userTokenY, tokenXMint, tokenYMint, binArrayLower, binArrayUpper, 10000);
163
+ it('uses DLMM_PROGRAM_ID', () => {
164
+ expect(ix.programId.equals(DLMM_PROGRAM_ID)).toBe(true);
165
+ });
166
+ it('has 13 account keys', () => {
167
+ expect(ix.keys.length).toBe(13);
168
+ });
169
+ it('data is 10 bytes (8 disc + 2 bps)', () => {
170
+ expect(ix.data.length).toBe(10);
171
+ });
172
+ it('encodes bpsBasisPointsToRemove as LE u16', () => {
173
+ const bps = ix.data.readUInt16LE(8);
174
+ expect(bps).toBe(10000);
175
+ });
176
+ it('marks owner as signer', () => {
177
+ const ownerKey = ix.keys.find(k => k.pubkey.equals(owner));
178
+ expect(ownerKey?.isSigner).toBe(true);
179
+ });
180
+ it('encodes partial removal correctly', () => {
181
+ const partialIx = createRemoveLiquidityIx(pool, position, owner, reserveX, reserveY, userTokenX, userTokenY, tokenXMint, tokenYMint, binArrayLower, binArrayUpper, 5000);
182
+ expect(partialIx.data.readUInt16LE(8)).toBe(5000);
183
+ });
184
+ });
185
+ // ── PDA derivation ──────────────────────────────────────
186
+ describe('PDA derivation', () => {
187
+ it('getProtocolStatePDA is deterministic', () => {
188
+ const a = getProtocolStatePDA(PROGRAM_ID);
189
+ const b = getProtocolStatePDA(PROGRAM_ID);
190
+ expect(a.equals(b)).toBe(true);
191
+ });
192
+ it('getProtocolStatePDA differs by program', () => {
193
+ const mainnet = getProtocolStatePDA(MAINNET_PROGRAM_ID);
194
+ const devnet = getProtocolStatePDA(DEVNET_PROGRAM_ID);
195
+ expect(mainnet.equals(devnet)).toBe(false);
196
+ });
197
+ it('getMarketVaultPDA differs by market ID', () => {
198
+ const ps = getProtocolStatePDA(PROGRAM_ID);
199
+ const vault1 = getMarketVaultPDA(ps, 1, PROGRAM_ID);
200
+ const vault2 = getMarketVaultPDA(ps, 2, PROGRAM_ID);
201
+ expect(vault1.equals(vault2)).toBe(false);
202
+ });
203
+ it('getUserPositionPDA differs by user', () => {
204
+ const ps = getProtocolStatePDA(PROGRAM_ID);
205
+ const vault = getMarketVaultPDA(ps, 1, PROGRAM_ID);
206
+ const pos1 = getUserPositionPDA(vault, CCM_MINT, PROGRAM_ID);
207
+ const pos2 = getUserPositionPDA(vault, USDC_MINT, PROGRAM_ID);
208
+ expect(pos1.equals(pos2)).toBe(false);
209
+ });
210
+ it('getGlobalRootConfigPDA derives from CCM mint', () => {
211
+ const root = getGlobalRootConfigPDA(CCM_MINT, PROGRAM_ID);
212
+ expect(PublicKey.isOnCurve(root.toBuffer())).toBe(false); // PDAs are off-curve
213
+ });
214
+ it('getClaimStatePDA is unique per claimer', () => {
215
+ const claim1 = getClaimStatePDA(CCM_MINT, USDC_MINT, PROGRAM_ID);
216
+ const claim2 = getClaimStatePDA(CCM_MINT, CCM_MINT, PROGRAM_ID);
217
+ expect(claim1.equals(claim2)).toBe(false);
218
+ });
219
+ it('getChannelConfigV2PDA is unique per subject', () => {
220
+ const ch1 = getChannelConfigV2PDA(CCM_MINT, USDC_MINT, PROGRAM_ID);
221
+ const ch2 = getChannelConfigV2PDA(CCM_MINT, CCM_MINT, PROGRAM_ID);
222
+ expect(ch1.equals(ch2)).toBe(false);
223
+ });
224
+ it('getAta derives a valid off-curve address', () => {
225
+ const ata = getAta(CCM_MINT, USDC_MINT, TOKEN_PROGRAM_ID);
226
+ expect(PublicKey.isOnCurve(ata.toBuffer())).toBe(false);
227
+ });
228
+ });
229
+ // ── Constants ───────────────────────────────────────────
230
+ describe('constants', () => {
231
+ it('PROGRAM_ID equals MAINNET_PROGRAM_ID', () => {
232
+ expect(PROGRAM_ID.equals(MAINNET_PROGRAM_ID)).toBe(true);
233
+ });
234
+ it('DEVNET_PROGRAM_ID is different from mainnet', () => {
235
+ expect(DEVNET_PROGRAM_ID.equals(MAINNET_PROGRAM_ID)).toBe(false);
236
+ });
237
+ it('TOKEN_PROGRAM_ID is the legacy SPL token program', () => {
238
+ expect(TOKEN_PROGRAM_ID.toBase58()).toBe('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
239
+ });
240
+ it('TOKEN_2022_PROGRAM_ID is the Token-2022 program', () => {
241
+ expect(TOKEN_2022_PROGRAM_ID.toBase58()).toBe('TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb');
242
+ });
243
+ it('DLMM_PROGRAM_ID matches Meteora mainnet', () => {
244
+ expect(DLMM_PROGRAM_ID.toBase58()).toBe('LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo');
245
+ });
246
+ it('seed strings match expected values', () => {
247
+ expect(PROTOCOL_STATE_SEED).toBe('protocol_state');
248
+ expect(MARKET_VAULT_SEED).toBe('market_vault');
249
+ expect(MARKET_POSITION_SEED).toBe('market_position');
250
+ expect(GLOBAL_ROOT_SEED).toBe('global_root');
251
+ expect(CLAIM_STATE_GLOBAL_SEED).toBe('claim_global');
252
+ expect(CHANNEL_CONFIG_V2_SEED).toBe('channel_cfg_v2');
253
+ });
254
+ });
255
+ // ── Account parsers ─────────────────────────────────────
256
+ describe('parseMarketVault', () => {
257
+ it('extracts depositMint at correct offset', () => {
258
+ // Build a fake MarketVault buffer: 8 disc + 1 bump + 8 marketId + 32 depositMint + ...
259
+ const buf = Buffer.alloc(8 + 1 + 8 + 32 + 32 + 32 + 16);
260
+ USDC_MINT.toBuffer().copy(buf, 8 + 1 + 8); // depositMint at offset 17
261
+ CCM_MINT.toBuffer().copy(buf, 8 + 1 + 8 + 32); // vlofiMint at offset 49
262
+ const vault = parseMarketVault(buf);
263
+ expect(vault.depositMint.equals(USDC_MINT)).toBe(true);
264
+ });
265
+ it('extracts vlofiMint at correct offset', () => {
266
+ const buf = Buffer.alloc(8 + 1 + 8 + 32 + 32 + 32 + 16);
267
+ USDC_MINT.toBuffer().copy(buf, 8 + 1 + 8);
268
+ CCM_MINT.toBuffer().copy(buf, 8 + 1 + 8 + 32);
269
+ const vault = parseMarketVault(buf);
270
+ expect(vault.vlofiMint.equals(CCM_MINT)).toBe(true);
271
+ });
272
+ it('reads bump from first byte after discriminator', () => {
273
+ const buf = Buffer.alloc(8 + 1 + 8 + 32 + 32 + 32 + 16);
274
+ buf[8] = 254; // bump
275
+ const vault = parseMarketVault(buf);
276
+ expect(vault.bump).toBe(254);
277
+ });
278
+ });
279
+ describe('parseProtocolState', () => {
280
+ it('reads isInitialized correctly', () => {
281
+ const buf = Buffer.alloc(8 + 165);
282
+ buf[8] = 1; // isInitialized
283
+ const state = parseProtocolState(buf);
284
+ expect(state.isInitialized).toBe(true);
285
+ });
286
+ it('reads paused flag correctly', () => {
287
+ const buf = Buffer.alloc(8 + 165);
288
+ buf[8 + 162] = 1; // paused
289
+ const state = parseProtocolState(buf);
290
+ expect(state.paused).toBe(true);
291
+ });
292
+ it('reads version byte', () => {
293
+ const buf = Buffer.alloc(8 + 165);
294
+ buf[8 + 1] = 3; // version
295
+ const state = parseProtocolState(buf);
296
+ expect(state.version).toBe(3);
297
+ });
298
+ });
299
+ describe('parseUserMarketPosition', () => {
300
+ it('returns null for data too short', () => {
301
+ const buf = Buffer.alloc(50);
302
+ expect(parseUserMarketPosition(buf)).toBeNull();
303
+ });
304
+ it('reads settled flag correctly', () => {
305
+ const buf = Buffer.alloc(114);
306
+ buf[8 + 89] = 1; // settled
307
+ const pos = parseUserMarketPosition(buf);
308
+ expect(pos).not.toBeNull();
309
+ expect(pos.settled).toBe(true);
310
+ });
311
+ it('reads depositedAmount as u64 LE', () => {
312
+ const buf = Buffer.alloc(114);
313
+ buf.writeBigUInt64LE(1000000n, 8 + 1 + 32 + 32); // depositedAmount at offset 73 from disc
314
+ const pos = parseUserMarketPosition(buf);
315
+ expect(pos).not.toBeNull();
316
+ expect(pos.depositedAmount).toBe(1000000n);
317
+ });
318
+ });
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Model Selector — pick the best open-source model using live WZRD velocity data.
3
+ *
4
+ * Combines on-chain attention signals from the WZRD protocol with
5
+ * OpenRouter pricing to compute a value score for every tracked model,
6
+ * then returns a ranked list filtered by budget, task, and trend.
7
+ *
8
+ * Usage:
9
+ * import { bestModel } from '@wzrd_sol/sdk';
10
+ * const picks = await bestModel({ task: 'code', budget: 'micro' });
11
+ * console.log(picks[0].model_id);
12
+ *
13
+ * @module model-selector
14
+ */
15
+ /** Budget tiers controlling the maximum blended price per million tokens. */
16
+ export type BudgetTier = 'micro' | 'budget' | 'mid' | 'premium';
17
+ /** Supported task types. The selector applies a task-specific boost. */
18
+ export type TaskType = 'chat' | 'code' | 'reasoning';
19
+ /** Velocity trend labels returned by the WZRD momentum API. */
20
+ export type VelocityTrend = 'surging' | 'accelerating' | 'stable' | 'insufficient_history' | 'decelerating' | 'cooling';
21
+ /** Confidence level from the WZRD momentum API. */
22
+ export type Confidence = 'high' | 'medium' | 'low' | 'insufficient';
23
+ /** A single model recommendation returned by the selector. */
24
+ export interface ModelRecommendation {
25
+ /** Full model identifier (e.g. "google/gemma-3-27b-it"). */
26
+ model_id: string;
27
+ /** Routing provider — currently always "openrouter". */
28
+ provider: string;
29
+ /** Blended price per million tokens in USD (3:1 prompt:completion weighting). */
30
+ price_per_m_tokens: number;
31
+ /** Exponential moving average of the model's velocity from WZRD. */
32
+ velocity_ema: number;
33
+ /** Composite value score: velocity_ema / (blended_price + epsilon). Higher is better. */
34
+ value_score: number;
35
+ /** Current velocity trend from the WZRD momentum signal. */
36
+ trend: VelocityTrend;
37
+ /** Confidence level of the momentum signal. */
38
+ confidence: Confidence;
39
+ }
40
+ /** Options for filtering and ranking models. */
41
+ export interface ModelSelectorOptions {
42
+ /** Maximum price tier. Default: "mid". */
43
+ budget?: BudgetTier;
44
+ /** Task type — applies a relevance boost to known-good models. Default: "chat". */
45
+ task?: TaskType;
46
+ /** Minimum confidence level from the momentum signal. Default: "low". */
47
+ min_confidence?: Confidence;
48
+ /** Maximum number of results to return. Default: 5. */
49
+ limit?: number;
50
+ /** Model ID substrings to exclude (case-insensitive). */
51
+ exclude?: string[];
52
+ }
53
+ /** Configuration for the ModelSelector class. */
54
+ export interface ModelSelectorConfig {
55
+ /** WZRD API base URL. Default: "https://api.twzrd.xyz". */
56
+ wzrd_base_url?: string;
57
+ /** OpenRouter catalog URL. Default: "https://openrouter.ai/api/v1/models". */
58
+ openrouter_url?: string;
59
+ /** Cache TTL in milliseconds. Default: 300_000 (5 minutes). */
60
+ cache_ttl_ms?: number;
61
+ }
62
+ /**
63
+ * Fetches WZRD velocity data and OpenRouter pricing, caches results,
64
+ * and scores models by value (velocity / cost).
65
+ *
66
+ * Create one instance and reuse it — the internal cache avoids redundant
67
+ * HTTP requests within the TTL window.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const selector = new ModelSelector({ wzrd_base_url: 'https://api.twzrd.xyz' });
72
+ * const picks = await selector.select({ task: 'code', budget: 'budget', limit: 3 });
73
+ * console.log(picks[0].model_id);
74
+ * ```
75
+ */
76
+ export declare class ModelSelector {
77
+ private readonly wzrdBaseUrl;
78
+ private readonly openrouterUrl;
79
+ private readonly cacheTtlMs;
80
+ private cache;
81
+ constructor(config?: ModelSelectorConfig);
82
+ /**
83
+ * Select the best models for a given task and budget.
84
+ *
85
+ * Fetches live data from the WZRD leaderboard, momentum signal, and
86
+ * OpenRouter catalog (all cached for 5 minutes by default), then ranks
87
+ * every OpenRouter model tracked by WZRD using:
88
+ *
89
+ * value_score = velocity_ema / (blended_price_per_m_tokens + epsilon)
90
+ *
91
+ * Results are filtered by budget tier, task relevance, minimum confidence,
92
+ * and exclusion list, then sorted by value_score descending.
93
+ *
94
+ * @param options - Filtering and ranking options.
95
+ * @returns Ranked array of model recommendations (may be empty).
96
+ */
97
+ select(options?: ModelSelectorOptions): Promise<ModelRecommendation[]>;
98
+ /**
99
+ * Invalidate the in-memory cache.
100
+ *
101
+ * Useful when you know upstream data has changed and want
102
+ * fresh results on the next `select()` call.
103
+ */
104
+ clearCache(): void;
105
+ private fetchLeaderboard;
106
+ private fetchMomentum;
107
+ private fetchOpenRouterCatalog;
108
+ /**
109
+ * Fetch JSON from a URL with in-memory TTL caching.
110
+ * Returns null on any error (network, HTTP status, parse failure).
111
+ */
112
+ private cachedFetch;
113
+ }
114
+ /**
115
+ * Pick the best open-source model for a task using live WZRD velocity data.
116
+ *
117
+ * This is a convenience wrapper around {@link ModelSelector.select} that
118
+ * uses a module-level singleton with default configuration. For custom
119
+ * base URLs or cache settings, instantiate {@link ModelSelector} directly.
120
+ *
121
+ * @param options - Filtering and ranking options.
122
+ * @returns Ranked array of model recommendations (may be empty if the API is unreachable).
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * import { bestModel } from '@wzrd_sol/sdk';
127
+ *
128
+ * // Cheapest model good for code
129
+ * const picks = await bestModel({ task: 'code', budget: 'micro' });
130
+ * console.log(picks[0].model_id);
131
+ *
132
+ * // Premium reasoning model, exclude specific providers
133
+ * const reasoning = await bestModel({
134
+ * task: 'reasoning',
135
+ * budget: 'premium',
136
+ * exclude: ['gpt'],
137
+ * limit: 3,
138
+ * });
139
+ * ```
140
+ */
141
+ export declare function bestModel(options?: ModelSelectorOptions): Promise<ModelRecommendation[]>;