@blockrun/llm 1.0.0 → 1.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/dist/index.d.cts CHANGED
@@ -301,7 +301,7 @@ declare class LLMClient {
301
301
  * ```ts
302
302
  * const result = await client.smartChat('What is 2+2?');
303
303
  * console.log(result.response); // '4'
304
- * console.log(result.model); // 'google/gemini-2.5-flash'
304
+ * console.log(result.model); // 'google/gemini-2.5-flash-lite'
305
305
  * console.log(result.routing.savings); // 0.78 (78% savings)
306
306
  * ```
307
307
  *
@@ -502,6 +502,33 @@ declare class ImageClient {
502
502
 
503
503
  declare const BASE_CHAIN_ID = 8453;
504
504
  declare const USDC_BASE: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
505
+ declare const SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
506
+ declare const USDC_SOLANA = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
507
+ interface CreateSolanaPaymentOptions {
508
+ resourceUrl?: string;
509
+ resourceDescription?: string;
510
+ maxTimeoutSeconds?: number;
511
+ extra?: Record<string, unknown>;
512
+ extensions?: Record<string, unknown>;
513
+ rpcUrl?: string;
514
+ }
515
+ /**
516
+ * Create a signed Solana x402 v2 payment payload.
517
+ *
518
+ * This creates an SPL TransferChecked transaction for USDC payment
519
+ * that the CDP facilitator can verify and settle.
520
+ *
521
+ * Requires @solana/web3.js and @solana/spl-token dependencies.
522
+ *
523
+ * @param secretKey - Solana secret key (Uint8Array, 64 bytes)
524
+ * @param fromAddress - Sender wallet address (base58)
525
+ * @param recipient - Payment recipient address (base58)
526
+ * @param amount - Amount in micro USDC (6 decimals)
527
+ * @param feePayer - CDP facilitator fee payer address (base58)
528
+ * @param options - Additional options
529
+ * @returns Base64-encoded signed payment payload
530
+ */
531
+ declare function createSolanaPaymentPayload(secretKey: Uint8Array, fromAddress: string, recipient: string, amount: string, feePayer: string, options?: CreateSolanaPaymentOptions): Promise<string>;
505
532
 
506
533
  /**
507
534
  * BlockRun Wallet Management - Auto-create and manage wallets.
@@ -602,6 +629,89 @@ declare function formatFundingMessageCompact(address: string): string;
602
629
  declare const WALLET_FILE_PATH: string;
603
630
  declare const WALLET_DIR_PATH: string;
604
631
 
632
+ /**
633
+ * BlockRun Solana LLM Client.
634
+ *
635
+ * Usage:
636
+ * import { SolanaLLMClient } from '@blockrun/llm';
637
+ *
638
+ * // SOLANA_WALLET_KEY env var (bs58-encoded Solana secret key)
639
+ * const client = new SolanaLLMClient();
640
+ *
641
+ * // Or pass key directly
642
+ * const client = new SolanaLLMClient({ privateKey: 'your-bs58-key' });
643
+ *
644
+ * const response = await client.chat('openai/gpt-4o', 'gm Solana');
645
+ */
646
+
647
+ interface SolanaLLMClientOptions {
648
+ /** bs58-encoded Solana secret key (64 bytes). Optional if SOLANA_WALLET_KEY env var is set. */
649
+ privateKey?: string;
650
+ /** API endpoint URL (default: https://sol.blockrun.ai/api) */
651
+ apiUrl?: string;
652
+ /** Solana RPC URL (default: https://api.mainnet-beta.solana.com) */
653
+ rpcUrl?: string;
654
+ /** Request timeout in milliseconds (default: 60000) */
655
+ timeout?: number;
656
+ }
657
+ declare class SolanaLLMClient {
658
+ static readonly SOLANA_API_URL = "https://sol.blockrun.ai/api";
659
+ private privateKey;
660
+ private apiUrl;
661
+ private rpcUrl;
662
+ private timeout;
663
+ private sessionTotalUsd;
664
+ private sessionCalls;
665
+ private addressCache;
666
+ constructor(options?: SolanaLLMClientOptions);
667
+ /** Get Solana wallet address (public key in base58). */
668
+ getWalletAddress(): Promise<string>;
669
+ /** Simple 1-line chat. */
670
+ chat(model: string, prompt: string, options?: ChatOptions): Promise<string>;
671
+ /** Full chat completion (OpenAI-compatible). */
672
+ chatCompletion(model: string, messages: ChatMessage[], options?: ChatCompletionOptions): Promise<ChatResponse>;
673
+ /** List available models. */
674
+ listModels(): Promise<Model[]>;
675
+ /** Get session spending. */
676
+ getSpending(): Spending;
677
+ /** True if using sol.blockrun.ai. */
678
+ isSolana(): boolean;
679
+ private requestWithPayment;
680
+ private handlePaymentAndRetry;
681
+ private fetchWithTimeout;
682
+ }
683
+ /**
684
+ * Convenience function: create SolanaLLMClient for sol.blockrun.ai.
685
+ */
686
+ declare function solanaClient(options?: SolanaLLMClientOptions): SolanaLLMClient;
687
+
688
+ declare const SOLANA_WALLET_FILE: string;
689
+ interface SolanaWalletInfo {
690
+ privateKey: string;
691
+ address: string;
692
+ isNew: boolean;
693
+ }
694
+ /**
695
+ * Create a new Solana wallet.
696
+ * Requires @solana/web3.js (optional dep).
697
+ */
698
+ declare function createSolanaWallet(): {
699
+ address: string;
700
+ privateKey: string;
701
+ };
702
+ /**
703
+ * Convert a bs58 private key string to Uint8Array (64 bytes).
704
+ * Accepts: bs58-encoded 64-byte key (standard Solana format).
705
+ */
706
+ declare function solanaKeyToBytes(privateKey: string): Promise<Uint8Array>;
707
+ /**
708
+ * Get Solana public key (address) from bs58 private key.
709
+ */
710
+ declare function solanaPublicKey(privateKey: string): Promise<string>;
711
+ declare function saveSolanaWallet(privateKey: string): string;
712
+ declare function loadSolanaWallet(): string | null;
713
+ declare function getOrCreateSolanaWallet(): Promise<SolanaWalletInfo>;
714
+
605
715
  /**
606
716
  * OpenAI-compatible API wrapper for BlockRun LLM SDK.
607
717
  *
@@ -741,4 +851,4 @@ declare class OpenAI {
741
851
  getWalletAddress(): string;
742
852
  }
743
853
 
744
- export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet, testnetClient };
854
+ export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, saveSolanaWallet, saveWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, testnetClient };
package/dist/index.d.ts CHANGED
@@ -301,7 +301,7 @@ declare class LLMClient {
301
301
  * ```ts
302
302
  * const result = await client.smartChat('What is 2+2?');
303
303
  * console.log(result.response); // '4'
304
- * console.log(result.model); // 'google/gemini-2.5-flash'
304
+ * console.log(result.model); // 'google/gemini-2.5-flash-lite'
305
305
  * console.log(result.routing.savings); // 0.78 (78% savings)
306
306
  * ```
307
307
  *
@@ -502,6 +502,33 @@ declare class ImageClient {
502
502
 
503
503
  declare const BASE_CHAIN_ID = 8453;
504
504
  declare const USDC_BASE: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
505
+ declare const SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
506
+ declare const USDC_SOLANA = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
507
+ interface CreateSolanaPaymentOptions {
508
+ resourceUrl?: string;
509
+ resourceDescription?: string;
510
+ maxTimeoutSeconds?: number;
511
+ extra?: Record<string, unknown>;
512
+ extensions?: Record<string, unknown>;
513
+ rpcUrl?: string;
514
+ }
515
+ /**
516
+ * Create a signed Solana x402 v2 payment payload.
517
+ *
518
+ * This creates an SPL TransferChecked transaction for USDC payment
519
+ * that the CDP facilitator can verify and settle.
520
+ *
521
+ * Requires @solana/web3.js and @solana/spl-token dependencies.
522
+ *
523
+ * @param secretKey - Solana secret key (Uint8Array, 64 bytes)
524
+ * @param fromAddress - Sender wallet address (base58)
525
+ * @param recipient - Payment recipient address (base58)
526
+ * @param amount - Amount in micro USDC (6 decimals)
527
+ * @param feePayer - CDP facilitator fee payer address (base58)
528
+ * @param options - Additional options
529
+ * @returns Base64-encoded signed payment payload
530
+ */
531
+ declare function createSolanaPaymentPayload(secretKey: Uint8Array, fromAddress: string, recipient: string, amount: string, feePayer: string, options?: CreateSolanaPaymentOptions): Promise<string>;
505
532
 
506
533
  /**
507
534
  * BlockRun Wallet Management - Auto-create and manage wallets.
@@ -602,6 +629,89 @@ declare function formatFundingMessageCompact(address: string): string;
602
629
  declare const WALLET_FILE_PATH: string;
603
630
  declare const WALLET_DIR_PATH: string;
604
631
 
632
+ /**
633
+ * BlockRun Solana LLM Client.
634
+ *
635
+ * Usage:
636
+ * import { SolanaLLMClient } from '@blockrun/llm';
637
+ *
638
+ * // SOLANA_WALLET_KEY env var (bs58-encoded Solana secret key)
639
+ * const client = new SolanaLLMClient();
640
+ *
641
+ * // Or pass key directly
642
+ * const client = new SolanaLLMClient({ privateKey: 'your-bs58-key' });
643
+ *
644
+ * const response = await client.chat('openai/gpt-4o', 'gm Solana');
645
+ */
646
+
647
+ interface SolanaLLMClientOptions {
648
+ /** bs58-encoded Solana secret key (64 bytes). Optional if SOLANA_WALLET_KEY env var is set. */
649
+ privateKey?: string;
650
+ /** API endpoint URL (default: https://sol.blockrun.ai/api) */
651
+ apiUrl?: string;
652
+ /** Solana RPC URL (default: https://api.mainnet-beta.solana.com) */
653
+ rpcUrl?: string;
654
+ /** Request timeout in milliseconds (default: 60000) */
655
+ timeout?: number;
656
+ }
657
+ declare class SolanaLLMClient {
658
+ static readonly SOLANA_API_URL = "https://sol.blockrun.ai/api";
659
+ private privateKey;
660
+ private apiUrl;
661
+ private rpcUrl;
662
+ private timeout;
663
+ private sessionTotalUsd;
664
+ private sessionCalls;
665
+ private addressCache;
666
+ constructor(options?: SolanaLLMClientOptions);
667
+ /** Get Solana wallet address (public key in base58). */
668
+ getWalletAddress(): Promise<string>;
669
+ /** Simple 1-line chat. */
670
+ chat(model: string, prompt: string, options?: ChatOptions): Promise<string>;
671
+ /** Full chat completion (OpenAI-compatible). */
672
+ chatCompletion(model: string, messages: ChatMessage[], options?: ChatCompletionOptions): Promise<ChatResponse>;
673
+ /** List available models. */
674
+ listModels(): Promise<Model[]>;
675
+ /** Get session spending. */
676
+ getSpending(): Spending;
677
+ /** True if using sol.blockrun.ai. */
678
+ isSolana(): boolean;
679
+ private requestWithPayment;
680
+ private handlePaymentAndRetry;
681
+ private fetchWithTimeout;
682
+ }
683
+ /**
684
+ * Convenience function: create SolanaLLMClient for sol.blockrun.ai.
685
+ */
686
+ declare function solanaClient(options?: SolanaLLMClientOptions): SolanaLLMClient;
687
+
688
+ declare const SOLANA_WALLET_FILE: string;
689
+ interface SolanaWalletInfo {
690
+ privateKey: string;
691
+ address: string;
692
+ isNew: boolean;
693
+ }
694
+ /**
695
+ * Create a new Solana wallet.
696
+ * Requires @solana/web3.js (optional dep).
697
+ */
698
+ declare function createSolanaWallet(): {
699
+ address: string;
700
+ privateKey: string;
701
+ };
702
+ /**
703
+ * Convert a bs58 private key string to Uint8Array (64 bytes).
704
+ * Accepts: bs58-encoded 64-byte key (standard Solana format).
705
+ */
706
+ declare function solanaKeyToBytes(privateKey: string): Promise<Uint8Array>;
707
+ /**
708
+ * Get Solana public key (address) from bs58 private key.
709
+ */
710
+ declare function solanaPublicKey(privateKey: string): Promise<string>;
711
+ declare function saveSolanaWallet(privateKey: string): string;
712
+ declare function loadSolanaWallet(): string | null;
713
+ declare function getOrCreateSolanaWallet(): Promise<SolanaWalletInfo>;
714
+
605
715
  /**
606
716
  * OpenAI-compatible API wrapper for BlockRun LLM SDK.
607
717
  *
@@ -741,4 +851,4 @@ declare class OpenAI {
741
851
  getWalletAddress(): string;
742
852
  }
743
853
 
744
- export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadWallet, saveWallet, testnetClient };
854
+ export { APIError, BASE_CHAIN_ID, BlockrunError, type ChatChoice, type ChatCompletionOptions, type ChatMessage, type ChatOptions, type ChatResponse, type ChatUsage, type FunctionCall, type FunctionDefinition, ImageClient, type ImageClientOptions, type ImageData, type ImageGenerateOptions, type ImageModel, type ImageResponse, LLMClient, type LLMClientOptions, type Model, type NewsSearchSource, OpenAI, type OpenAIChatCompletionChoice, type OpenAIChatCompletionChunk, type OpenAIChatCompletionParams, type OpenAIChatCompletionResponse, type OpenAIClientOptions, PaymentError, type PaymentLinks, type RoutingDecision, type RoutingProfile, type RoutingTier, type RssSearchSource, SOLANA_NETWORK, SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH, type SearchParameters, type SearchSource, type SmartChatOptions, type SmartChatResponse, SolanaLLMClient, type SolanaLLMClientOptions, type SolanaWalletInfo, type Spending, type Tool, type ToolCall, type ToolChoice, USDC_BASE, USDC_BASE_CONTRACT, USDC_SOLANA, WALLET_DIR_PATH, WALLET_FILE_PATH, type WalletInfo, type WebSearchSource, type XSearchSource, createSolanaPaymentPayload, createSolanaWallet, createWallet, LLMClient as default, formatFundingMessageCompact, formatNeedsFundingMessage, formatWalletCreatedMessage, getEip681Uri, getOrCreateSolanaWallet, getOrCreateWallet, getPaymentLinks, getWalletAddress, loadSolanaWallet, loadWallet, saveSolanaWallet, saveWallet, solanaClient, solanaKeyToBytes, solanaPublicKey, testnetClient };
@@ -73,10 +73,11 @@ import {
73
73
  VoteInstruction,
74
74
  VoteProgram,
75
75
  clusterApiUrl,
76
+ init_index_esm,
76
77
  sendAndConfirmRawTransaction,
77
78
  sendAndConfirmTransaction
78
- } from "./chunk-S7BEMV6T.js";
79
- import "./chunk-2ESYSVXG.js";
79
+ } from "./chunk-KRDGCX7W.js";
80
+ init_index_esm();
80
81
  export {
81
82
  Account,
82
83
  AddressLookupTableAccount,
package/dist/index.js CHANGED
@@ -1,4 +1,9 @@
1
- import "./chunk-2ESYSVXG.js";
1
+ import {
2
+ __require,
3
+ __toCommonJS,
4
+ index_esm_exports,
5
+ init_index_esm
6
+ } from "./chunk-KRDGCX7W.js";
2
7
 
3
8
  // src/client.ts
4
9
  import { privateKeyToAccount } from "viem/accounts";
@@ -34,6 +39,10 @@ import { route, DEFAULT_ROUTING_CONFIG } from "@blockrun/clawrouter";
34
39
  import { signTypedData } from "viem/accounts";
35
40
  var BASE_CHAIN_ID = 8453;
36
41
  var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
42
+ var SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
43
+ var USDC_SOLANA = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
44
+ var DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
45
+ var DEFAULT_COMPUTE_UNIT_LIMIT = 8e3;
37
46
  var USDC_DOMAIN = {
38
47
  name: "USD Coin",
39
48
  version: "2",
@@ -106,6 +115,66 @@ async function createPaymentPayload(privateKey, fromAddress, recipient, amount,
106
115
  };
107
116
  return btoa(JSON.stringify(paymentData));
108
117
  }
118
+ async function createSolanaPaymentPayload(secretKey, fromAddress, recipient, amount, feePayer, options = {}) {
119
+ const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import("./index.esm-SXKIFLA7.js");
120
+ const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint } = await import("./esm-PTFDM6PE.js");
121
+ const { Keypair } = await import("./index.esm-SXKIFLA7.js");
122
+ const rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
123
+ const connection = new Connection(rpcUrl);
124
+ const keypair = Keypair.fromSecretKey(secretKey);
125
+ const feePayerPubkey = new PublicKey(feePayer);
126
+ const ownerPubkey = keypair.publicKey;
127
+ const tokenMint = new PublicKey(USDC_SOLANA);
128
+ const payToPubkey = new PublicKey(recipient);
129
+ const mintInfo = await getMint(connection, tokenMint);
130
+ const sourceATA = await getAssociatedTokenAddress(tokenMint, ownerPubkey, false);
131
+ const destinationATA = await getAssociatedTokenAddress(tokenMint, payToPubkey, false);
132
+ const { blockhash } = await connection.getLatestBlockhash();
133
+ const setComputeUnitPriceIx = ComputeBudgetProgram.setComputeUnitPrice({
134
+ microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS
135
+ });
136
+ const setComputeUnitLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
137
+ units: DEFAULT_COMPUTE_UNIT_LIMIT
138
+ });
139
+ const transferIx = createTransferCheckedInstruction(
140
+ sourceATA,
141
+ tokenMint,
142
+ destinationATA,
143
+ ownerPubkey,
144
+ BigInt(amount),
145
+ mintInfo.decimals
146
+ );
147
+ const messageV0 = new TransactionMessage({
148
+ payerKey: feePayerPubkey,
149
+ recentBlockhash: blockhash,
150
+ instructions: [setComputeUnitLimitIx, setComputeUnitPriceIx, transferIx]
151
+ }).compileToV0Message();
152
+ const transaction = new VersionedTransaction(messageV0);
153
+ transaction.sign([keypair]);
154
+ const serializedTx = Buffer.from(transaction.serialize()).toString("base64");
155
+ const paymentData = {
156
+ x402Version: 2,
157
+ resource: {
158
+ url: options.resourceUrl || "https://blockrun.ai/api/v1/chat/completions",
159
+ description: options.resourceDescription || "BlockRun AI API call",
160
+ mimeType: "application/json"
161
+ },
162
+ accepted: {
163
+ scheme: "exact",
164
+ network: SOLANA_NETWORK,
165
+ amount,
166
+ asset: USDC_SOLANA,
167
+ payTo: recipient,
168
+ maxTimeoutSeconds: options.maxTimeoutSeconds || 300,
169
+ extra: options.extra || { feePayer }
170
+ },
171
+ payload: {
172
+ transaction: serializedTx
173
+ },
174
+ extensions: options.extensions || {}
175
+ };
176
+ return btoa(JSON.stringify(paymentData));
177
+ }
109
178
  function parsePaymentRequired(headerValue) {
110
179
  try {
111
180
  const decoded = atob(headerValue);
@@ -304,7 +373,7 @@ var LLMClient = class {
304
373
  * ```ts
305
374
  * const result = await client.smartChat('What is 2+2?');
306
375
  * console.log(result.response); // '4'
307
- * console.log(result.model); // 'google/gemini-2.5-flash'
376
+ * console.log(result.model); // 'google/gemini-2.5-flash-lite'
308
377
  * console.log(result.routing.savings); // 0.78 (78% savings)
309
378
  * ```
310
379
  *
@@ -947,6 +1016,255 @@ Check my balance: ${links.basescan}`;
947
1016
  var WALLET_FILE_PATH = WALLET_FILE;
948
1017
  var WALLET_DIR_PATH = WALLET_DIR;
949
1018
 
1019
+ // src/solana-wallet.ts
1020
+ import * as fs2 from "fs";
1021
+ import * as path2 from "path";
1022
+ import * as os2 from "os";
1023
+ var WALLET_DIR2 = path2.join(os2.homedir(), ".blockrun");
1024
+ var SOLANA_WALLET_FILE = path2.join(WALLET_DIR2, ".solana-session");
1025
+ function createSolanaWallet() {
1026
+ const { Keypair } = (init_index_esm(), __toCommonJS(index_esm_exports));
1027
+ const bs58 = __require("bs58");
1028
+ const keypair = Keypair.generate();
1029
+ return {
1030
+ address: keypair.publicKey.toBase58(),
1031
+ privateKey: bs58.default?.encode(keypair.secretKey) ?? bs58.encode(keypair.secretKey)
1032
+ };
1033
+ }
1034
+ async function solanaKeyToBytes(privateKey) {
1035
+ try {
1036
+ const bs58 = await import("bs58");
1037
+ const bytes = (bs58.default ?? bs58).decode(privateKey);
1038
+ if (bytes.length !== 64) {
1039
+ throw new Error(`Invalid Solana key length: expected 64 bytes, got ${bytes.length}`);
1040
+ }
1041
+ return bytes;
1042
+ } catch (err) {
1043
+ const msg = err instanceof Error ? err.message : String(err);
1044
+ throw new Error(`Invalid Solana private key: ${msg}`);
1045
+ }
1046
+ }
1047
+ async function solanaPublicKey(privateKey) {
1048
+ const { Keypair } = await import("./index.esm-SXKIFLA7.js");
1049
+ const bytes = await solanaKeyToBytes(privateKey);
1050
+ return Keypair.fromSecretKey(bytes).publicKey.toBase58();
1051
+ }
1052
+ function saveSolanaWallet(privateKey) {
1053
+ if (!fs2.existsSync(WALLET_DIR2)) fs2.mkdirSync(WALLET_DIR2, { recursive: true });
1054
+ fs2.writeFileSync(SOLANA_WALLET_FILE, privateKey, { mode: 384 });
1055
+ return SOLANA_WALLET_FILE;
1056
+ }
1057
+ function loadSolanaWallet() {
1058
+ if (fs2.existsSync(SOLANA_WALLET_FILE)) {
1059
+ const key = fs2.readFileSync(SOLANA_WALLET_FILE, "utf-8").trim();
1060
+ if (key) return key;
1061
+ }
1062
+ return null;
1063
+ }
1064
+ async function getOrCreateSolanaWallet() {
1065
+ const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
1066
+ if (envKey) {
1067
+ const address2 = await solanaPublicKey(envKey);
1068
+ return { privateKey: envKey, address: address2, isNew: false };
1069
+ }
1070
+ const fileKey = loadSolanaWallet();
1071
+ if (fileKey) {
1072
+ const address2 = await solanaPublicKey(fileKey);
1073
+ return { privateKey: fileKey, address: address2, isNew: false };
1074
+ }
1075
+ const { address, privateKey } = createSolanaWallet();
1076
+ saveSolanaWallet(privateKey);
1077
+ return { address, privateKey, isNew: true };
1078
+ }
1079
+
1080
+ // src/solana-client.ts
1081
+ var SOLANA_API_URL = "https://sol.blockrun.ai/api";
1082
+ var DEFAULT_MAX_TOKENS2 = 1024;
1083
+ var DEFAULT_TIMEOUT3 = 6e4;
1084
+ var SDK_VERSION2 = "0.3.0";
1085
+ var USER_AGENT2 = `blockrun-ts/${SDK_VERSION2}`;
1086
+ var SolanaLLMClient = class {
1087
+ static SOLANA_API_URL = SOLANA_API_URL;
1088
+ privateKey;
1089
+ apiUrl;
1090
+ rpcUrl;
1091
+ timeout;
1092
+ sessionTotalUsd = 0;
1093
+ sessionCalls = 0;
1094
+ addressCache = null;
1095
+ constructor(options = {}) {
1096
+ const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
1097
+ const privateKey = options.privateKey || envKey;
1098
+ if (!privateKey) {
1099
+ throw new Error(
1100
+ "Private key required. Pass privateKey in options or set SOLANA_WALLET_KEY environment variable."
1101
+ );
1102
+ }
1103
+ this.privateKey = privateKey;
1104
+ const apiUrl = options.apiUrl || SOLANA_API_URL;
1105
+ validateApiUrl(apiUrl);
1106
+ this.apiUrl = apiUrl.replace(/\/$/, "");
1107
+ this.rpcUrl = options.rpcUrl || "https://api.mainnet-beta.solana.com";
1108
+ this.timeout = options.timeout || DEFAULT_TIMEOUT3;
1109
+ }
1110
+ /** Get Solana wallet address (public key in base58). */
1111
+ async getWalletAddress() {
1112
+ if (!this.addressCache) {
1113
+ this.addressCache = await solanaPublicKey(this.privateKey);
1114
+ }
1115
+ return this.addressCache;
1116
+ }
1117
+ /** Simple 1-line chat. */
1118
+ async chat(model, prompt, options) {
1119
+ const messages = [];
1120
+ if (options?.system) messages.push({ role: "system", content: options.system });
1121
+ messages.push({ role: "user", content: prompt });
1122
+ const result = await this.chatCompletion(model, messages, {
1123
+ maxTokens: options?.maxTokens,
1124
+ temperature: options?.temperature,
1125
+ topP: options?.topP,
1126
+ search: options?.search,
1127
+ searchParameters: options?.searchParameters
1128
+ });
1129
+ return result.choices[0].message.content || "";
1130
+ }
1131
+ /** Full chat completion (OpenAI-compatible). */
1132
+ async chatCompletion(model, messages, options) {
1133
+ const body = {
1134
+ model,
1135
+ messages,
1136
+ max_tokens: options?.maxTokens || DEFAULT_MAX_TOKENS2
1137
+ };
1138
+ if (options?.temperature !== void 0) body.temperature = options.temperature;
1139
+ if (options?.topP !== void 0) body.top_p = options.topP;
1140
+ if (options?.searchParameters !== void 0) body.search_parameters = options.searchParameters;
1141
+ else if (options?.search === true) body.search_parameters = { mode: "on" };
1142
+ if (options?.tools !== void 0) body.tools = options.tools;
1143
+ if (options?.toolChoice !== void 0) body.tool_choice = options.toolChoice;
1144
+ return this.requestWithPayment("/v1/chat/completions", body);
1145
+ }
1146
+ /** List available models. */
1147
+ async listModels() {
1148
+ const response = await this.fetchWithTimeout(`${this.apiUrl}/v1/models`, { method: "GET" });
1149
+ if (!response.ok) {
1150
+ throw new APIError(`Failed to list models: ${response.status}`, response.status);
1151
+ }
1152
+ const data = await response.json();
1153
+ return data.data || [];
1154
+ }
1155
+ /** Get session spending. */
1156
+ getSpending() {
1157
+ return { totalUsd: this.sessionTotalUsd, calls: this.sessionCalls };
1158
+ }
1159
+ /** True if using sol.blockrun.ai. */
1160
+ isSolana() {
1161
+ return this.apiUrl.includes("sol.blockrun.ai");
1162
+ }
1163
+ async requestWithPayment(endpoint, body) {
1164
+ const url = `${this.apiUrl}${endpoint}`;
1165
+ const response = await this.fetchWithTimeout(url, {
1166
+ method: "POST",
1167
+ headers: { "Content-Type": "application/json", "User-Agent": USER_AGENT2 },
1168
+ body: JSON.stringify(body)
1169
+ });
1170
+ if (response.status === 402) {
1171
+ return this.handlePaymentAndRetry(url, body, response);
1172
+ }
1173
+ if (!response.ok) {
1174
+ let errorBody;
1175
+ try {
1176
+ errorBody = await response.json();
1177
+ } catch {
1178
+ errorBody = { error: "Request failed" };
1179
+ }
1180
+ throw new APIError(`API error: ${response.status}`, response.status, sanitizeErrorResponse(errorBody));
1181
+ }
1182
+ return response.json();
1183
+ }
1184
+ async handlePaymentAndRetry(url, body, response) {
1185
+ let paymentHeader = response.headers.get("payment-required");
1186
+ if (!paymentHeader) {
1187
+ try {
1188
+ const respBody = await response.json();
1189
+ if (respBody.accepts || respBody.x402Version) {
1190
+ paymentHeader = btoa(JSON.stringify(respBody));
1191
+ }
1192
+ } catch {
1193
+ }
1194
+ }
1195
+ if (!paymentHeader) {
1196
+ throw new PaymentError("402 response but no payment requirements found");
1197
+ }
1198
+ const paymentRequired = parsePaymentRequired(paymentHeader);
1199
+ const details = extractPaymentDetails(paymentRequired, SOLANA_NETWORK);
1200
+ if (!details.network?.startsWith("solana:")) {
1201
+ throw new PaymentError(
1202
+ `Expected Solana payment network, got: ${details.network}. Use LLMClient for Base payments.`
1203
+ );
1204
+ }
1205
+ const feePayer = details.extra?.feePayer;
1206
+ if (!feePayer) throw new PaymentError("Missing feePayer in 402 extra field");
1207
+ const fromAddress = await this.getWalletAddress();
1208
+ const secretKey = await solanaKeyToBytes(this.privateKey);
1209
+ const extensions = paymentRequired.extensions;
1210
+ const paymentPayload = await createSolanaPaymentPayload(
1211
+ secretKey,
1212
+ fromAddress,
1213
+ details.recipient,
1214
+ details.amount,
1215
+ feePayer,
1216
+ {
1217
+ resourceUrl: validateResourceUrl(
1218
+ details.resource?.url || `${this.apiUrl}/v1/chat/completions`,
1219
+ this.apiUrl
1220
+ ),
1221
+ resourceDescription: details.resource?.description || "BlockRun Solana AI API call",
1222
+ maxTimeoutSeconds: details.maxTimeoutSeconds || 300,
1223
+ extra: details.extra,
1224
+ extensions,
1225
+ rpcUrl: this.rpcUrl
1226
+ }
1227
+ );
1228
+ const retryResponse = await this.fetchWithTimeout(url, {
1229
+ method: "POST",
1230
+ headers: {
1231
+ "Content-Type": "application/json",
1232
+ "User-Agent": USER_AGENT2,
1233
+ "PAYMENT-SIGNATURE": paymentPayload
1234
+ },
1235
+ body: JSON.stringify(body)
1236
+ });
1237
+ if (retryResponse.status === 402) {
1238
+ throw new PaymentError("Payment was rejected. Check your Solana USDC balance.");
1239
+ }
1240
+ if (!retryResponse.ok) {
1241
+ let errorBody;
1242
+ try {
1243
+ errorBody = await retryResponse.json();
1244
+ } catch {
1245
+ errorBody = { error: "Request failed" };
1246
+ }
1247
+ throw new APIError(`API error after payment: ${retryResponse.status}`, retryResponse.status, sanitizeErrorResponse(errorBody));
1248
+ }
1249
+ const costUsd = parseFloat(details.amount) / 1e6;
1250
+ this.sessionCalls += 1;
1251
+ this.sessionTotalUsd += costUsd;
1252
+ return retryResponse.json();
1253
+ }
1254
+ async fetchWithTimeout(url, options) {
1255
+ const controller = new AbortController();
1256
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1257
+ try {
1258
+ return await fetch(url, { ...options, signal: controller.signal });
1259
+ } finally {
1260
+ clearTimeout(timeoutId);
1261
+ }
1262
+ }
1263
+ };
1264
+ function solanaClient(options = {}) {
1265
+ return new SolanaLLMClient({ ...options, apiUrl: SOLANA_API_URL });
1266
+ }
1267
+
950
1268
  // src/openai-compat.ts
951
1269
  var StreamingResponse = class {
952
1270
  reader;
@@ -1124,20 +1442,32 @@ export {
1124
1442
  LLMClient,
1125
1443
  OpenAI,
1126
1444
  PaymentError,
1445
+ SOLANA_NETWORK,
1446
+ SOLANA_WALLET_FILE as SOLANA_WALLET_FILE_PATH,
1447
+ SolanaLLMClient,
1127
1448
  USDC_BASE,
1128
1449
  USDC_BASE_CONTRACT,
1450
+ USDC_SOLANA,
1129
1451
  WALLET_DIR_PATH,
1130
1452
  WALLET_FILE_PATH,
1453
+ createSolanaPaymentPayload,
1454
+ createSolanaWallet,
1131
1455
  createWallet,
1132
1456
  client_default as default,
1133
1457
  formatFundingMessageCompact,
1134
1458
  formatNeedsFundingMessage,
1135
1459
  formatWalletCreatedMessage,
1136
1460
  getEip681Uri,
1461
+ getOrCreateSolanaWallet,
1137
1462
  getOrCreateWallet,
1138
1463
  getPaymentLinks,
1139
1464
  getWalletAddress,
1465
+ loadSolanaWallet,
1140
1466
  loadWallet,
1467
+ saveSolanaWallet,
1141
1468
  saveWallet,
1469
+ solanaClient,
1470
+ solanaKeyToBytes,
1471
+ solanaPublicKey,
1142
1472
  testnetClient
1143
1473
  };