@blockrun/llm 3.18.0 → 3.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -1
- package/dist/index.cjs +478 -90
- package/dist/index.d.cts +61 -1
- package/dist/index.d.ts +61 -1
- package/dist/index.js +480 -93
- package/package.json +19 -4
package/README.md
CHANGED
|
@@ -443,6 +443,65 @@ const tweet = await client.chat('xai/grok-4.5', 'What is trending on X?', { sear
|
|
|
443
443
|
**Supported endpoint:** `https://sol.blockrun.ai/api`
|
|
444
444
|
**Payment:** Solana USDC (SPL, mainnet)
|
|
445
445
|
|
|
446
|
+
### Metered billing with x402 batch-settlement (opt-in)
|
|
447
|
+
|
|
448
|
+
By default every Solana call is an `exact` payment: one SPL transfer per call, priced at the call's **ceiling** (the quote for your `maxTokens`), settled on-chain before the model answers. With `batch-settlement` you lock a small deposit in a payment channel once. After that, each call carries only a signed authorization for its ceiling. The gateway serves the call, meters what it **actually** cost, and charges that, never more than the ceiling. It then redeems the charges on-chain in batches.
|
|
449
|
+
|
|
450
|
+
Batch mode runs on three optional peer dependencies:
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
npm install @x402/core@~2.28.0 @x402/svm@~2.28.0 @solana/kit
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import { SolanaLLMClient, BLOCKRUN_SOL_OPERATOR } from '@blockrun/llm';
|
|
458
|
+
|
|
459
|
+
const client = new SolanaLLMClient({
|
|
460
|
+
privateKey: process.env.SOLANA_WALLET_KEY,
|
|
461
|
+
batch: {
|
|
462
|
+
// BlockRun's operator public key, 5YKPQUFjw5WQqhSUkEGKNNfYYVqnRRNbpYyL71qQ1vm3.
|
|
463
|
+
// Batch stays off until you list it: you decide which operator may sign
|
|
464
|
+
// vouchers against your deposit.
|
|
465
|
+
operators: [BLOCKRUN_SOL_OPERATOR],
|
|
466
|
+
// Most USDC this client will ever lock in the channel (deposit + top-ups),
|
|
467
|
+
// and so the most an operator could claim. Default "$1".
|
|
468
|
+
maxDeposit: '$5',
|
|
469
|
+
},
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// The first call opens the channel. By default the SDK deposits 5x this
|
|
473
|
+
// call's ceiling (never more than maxDeposit), and the call that opens or tops
|
|
474
|
+
// up the channel is charged its quoted price, as it would be with exact.
|
|
475
|
+
await client.chat('openai/gpt-4o-mini', 'gm');
|
|
476
|
+
|
|
477
|
+
// Every later call is metered: you pay for the tokens the call actually used.
|
|
478
|
+
const reply = await client.chat('anthropic/claude-sonnet-4.6', 'Summarize x402 in one line', {
|
|
479
|
+
maxTokens: 2048, // a ceiling, not a price: a short answer is not billed for 2,048 tokens
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
console.log(client.getSpending()); // { totalUsd: <actual charges>, calls: 2 }
|
|
483
|
+
|
|
484
|
+
// Done for good? Close the channel to get the unused escrow back.
|
|
485
|
+
// BlockRun closes it cooperatively when it can; otherwise this starts a
|
|
486
|
+
// payer-forced close and the escrow returns after the channel's grace period.
|
|
487
|
+
await client.closeBatchChannel();
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
How it behaves:
|
|
491
|
+
|
|
492
|
+
- **Opt-in and trust-pinned.** In server-signed mode BlockRun's operator key signs the vouchers, so it could claim up to the whole unspent deposit. The SDK only enters a channel for an operator you list in `operators`, and only up to `maxDeposit`. A 402 that asks for any other operator is paid with `exact`. BlockRun's key is exported as `BLOCKRUN_SOL_OPERATOR` (`5YKPQUFjw5WQqhSUkEGKNNfYYVqnRRNbpYyL71qQ1vm3`). The SDK pins it and never takes it from a 402. If BlockRun ever rotates the key, the old and new keys overlap, and `operators` takes a list for that case.
|
|
493
|
+
- **Never worse than `exact`.** These cases all pay with `exact` instead:
|
|
494
|
+
- the 402 has no batch accept;
|
|
495
|
+
- the deposit would exceed `maxDeposit`;
|
|
496
|
+
- the gateway refuses batch (payer not admitted, admission paused, verifier unavailable);
|
|
497
|
+
- another batch call for the same wallet is in flight.
|
|
498
|
+
|
|
499
|
+
Parallel calls never queue behind the channel. A gateway refusal charges nothing, so the `exact` retry is the only charge.
|
|
500
|
+
- **Scope.** Batch covers non-streaming chat: `chat`, `chatCompletion`, `smartChat`, and `smartChatCompletion`. `stream()` and the image and media jobs still pay with `exact`.
|
|
501
|
+
- **One channel per wallet.** Every `SolanaLLMClient` for a wallet in one process shares a single channel. A second client with different `batch` options pays `exact`. On disk, one live process owns a wallet's channel file through a pid lock; other processes pay `exact` until that process exits.
|
|
502
|
+
- **State.** The open channel is saved to `~/.blockrun/solana-batch/<wallet>.json` (mode `0600`), so a restart reuses it. A custom `channelStore` path must also be per wallet. With `channelStore: false` the channel is kept in memory only and found again on-chain, and nothing coordinates processes, so use it for a single process per wallet. If a channel open or top-up gets no clean answer, or after `closeBatchChannel()`, the SDK forgets the saved channel and reads the real one from the chain. The channel uses your `rpcUrl` / `SOLANA_RPC_URL`.
|
|
503
|
+
- **Rollout.** sol.blockrun.ai lists `exact` first, and offers `batch-settlement` only once BlockRun enables it. Until then, and for any payer not yet admitted, a client with `batch` set simply keeps paying `exact`.
|
|
504
|
+
|
|
446
505
|
## Arc Support
|
|
447
506
|
|
|
448
507
|
The same `LLMClient` pays on [Circle's Arc](https://www.arc.network) via [arc.blockrun.ai](https://arc.blockrun.ai) — point `apiUrl` at it and hold USDC on Arc in the same EVM wallet:
|
|
@@ -530,7 +589,7 @@ const summary = getCostSummary(); // across sessions (~/.blockr
|
|
|
530
589
|
console.log(`Lifetime: $${summary.totalUsd.toFixed(2)} over ${summary.calls} calls`);
|
|
531
590
|
```
|
|
532
591
|
|
|
533
|
-
In wallet mode, every paid request is a real on-chain USDC transfer — look up your wallet address on [Basescan](https://basescan.org) (or a Solana explorer) to verify each settlement independently.
|
|
592
|
+
In wallet mode, every paid request is a real on-chain USDC transfer — look up your wallet address on [Basescan](https://basescan.org) (or a Solana explorer) to verify each settlement independently. The exception is Solana [batch-settlement](#metered-billing-with-x402-batch-settlement-opt-in): there the on-chain records are the channel deposit and BlockRun's batched redemptions, and each call is a signed voucher.
|
|
534
593
|
|
|
535
594
|
**Non-custodial by design: your private key never leaves your machine** — it is only used for local signing, and no funds are ever held by BlockRun.
|
|
536
595
|
|