@blockrun/clawrouter 0.11.12 → 0.11.14
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 +19 -12
- package/dist/cli.js +486 -383
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +260 -57
- package/dist/index.js +989 -435
- package/dist/index.js.map +1 -1
- package/package.json +11 -4
package/dist/index.d.ts
CHANGED
|
@@ -464,6 +464,48 @@ declare class BalanceMonitor {
|
|
|
464
464
|
private buildInfo;
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Solana USDC Balance Monitor
|
|
469
|
+
*
|
|
470
|
+
* Checks USDC balance on Solana mainnet with caching.
|
|
471
|
+
* Absorbed from @blockrun/clawwallet's solana-adapter.ts (balance portion only).
|
|
472
|
+
*/
|
|
473
|
+
type SolanaBalanceInfo = {
|
|
474
|
+
balance: bigint;
|
|
475
|
+
balanceUSD: string;
|
|
476
|
+
isLow: boolean;
|
|
477
|
+
isEmpty: boolean;
|
|
478
|
+
walletAddress: string;
|
|
479
|
+
};
|
|
480
|
+
/** Result from checkSufficient() */
|
|
481
|
+
type SolanaSufficiencyResult = {
|
|
482
|
+
sufficient: boolean;
|
|
483
|
+
info: SolanaBalanceInfo;
|
|
484
|
+
shortfall?: string;
|
|
485
|
+
};
|
|
486
|
+
declare class SolanaBalanceMonitor {
|
|
487
|
+
private readonly rpc;
|
|
488
|
+
private readonly walletAddress;
|
|
489
|
+
private cachedBalance;
|
|
490
|
+
private cachedAt;
|
|
491
|
+
constructor(walletAddress: string, rpcUrl?: string);
|
|
492
|
+
checkBalance(): Promise<SolanaBalanceInfo>;
|
|
493
|
+
deductEstimated(amountMicros: bigint): void;
|
|
494
|
+
invalidate(): void;
|
|
495
|
+
refresh(): Promise<SolanaBalanceInfo>;
|
|
496
|
+
/**
|
|
497
|
+
* Check if balance is sufficient for an estimated cost.
|
|
498
|
+
*/
|
|
499
|
+
checkSufficient(estimatedCostMicros: bigint): Promise<SolanaSufficiencyResult>;
|
|
500
|
+
/**
|
|
501
|
+
* Format USDC amount (in micros) as "$X.XX".
|
|
502
|
+
*/
|
|
503
|
+
formatUSDC(amountMicros: bigint): string;
|
|
504
|
+
getWalletAddress(): string;
|
|
505
|
+
private fetchBalance;
|
|
506
|
+
private buildInfo;
|
|
507
|
+
}
|
|
508
|
+
|
|
467
509
|
/**
|
|
468
510
|
* Session Persistence Store
|
|
469
511
|
*
|
|
@@ -581,12 +623,13 @@ declare function hashRequestContent(lastUserContent: string, toolCallNames?: str
|
|
|
581
623
|
* before the x402 flow, preventing OpenClaw's 10-15s timeout from firing.
|
|
582
624
|
* - Response dedup: hashes request bodies and caches responses for 30s,
|
|
583
625
|
* preventing double-charging when OpenClaw retries after timeout.
|
|
584
|
-
* - Payment cache: after first 402, pre-signs subsequent requests to skip
|
|
585
|
-
* the 402 round trip (~200ms savings per request).
|
|
586
626
|
* - Smart routing: when model is "blockrun/auto", classify query and pick cheapest model.
|
|
587
627
|
* - Usage logging: log every request as JSON line to ~/.openclaw/blockrun/logs/
|
|
588
628
|
*/
|
|
589
629
|
|
|
630
|
+
/** Union type for chain-agnostic balance monitoring */
|
|
631
|
+
type AnyBalanceMonitor = BalanceMonitor | SolanaBalanceMonitor;
|
|
632
|
+
|
|
590
633
|
/**
|
|
591
634
|
* Get the proxy port from pre-loaded configuration.
|
|
592
635
|
* Port is validated at module load time, this just returns the cached value.
|
|
@@ -603,9 +646,22 @@ type InsufficientFundsInfo = {
|
|
|
603
646
|
requiredUSD: string;
|
|
604
647
|
walletAddress: string;
|
|
605
648
|
};
|
|
649
|
+
/**
|
|
650
|
+
* Wallet config: either a plain EVM private key string, or the full
|
|
651
|
+
* resolution object from resolveOrGenerateWalletKey() which may include
|
|
652
|
+
* Solana keys. Using the full object prevents callers from accidentally
|
|
653
|
+
* forgetting to forward Solana key bytes.
|
|
654
|
+
*/
|
|
655
|
+
type WalletConfig = string | {
|
|
656
|
+
key: string;
|
|
657
|
+
solanaPrivateKeyBytes?: Uint8Array;
|
|
658
|
+
};
|
|
659
|
+
type PaymentChain = "base" | "solana";
|
|
606
660
|
type ProxyOptions = {
|
|
607
|
-
|
|
661
|
+
wallet: WalletConfig;
|
|
608
662
|
apiBase?: string;
|
|
663
|
+
/** Payment chain: "base" (default) or "solana". Can also be set via CLAWROUTER_PAYMENT_CHAIN env var. */
|
|
664
|
+
paymentChain?: PaymentChain;
|
|
609
665
|
/** Port to listen on (default: 8402) */
|
|
610
666
|
port?: number;
|
|
611
667
|
routingConfig?: Partial<RoutingConfig>;
|
|
@@ -654,7 +710,8 @@ type ProxyHandle = {
|
|
|
654
710
|
port: number;
|
|
655
711
|
baseUrl: string;
|
|
656
712
|
walletAddress: string;
|
|
657
|
-
|
|
713
|
+
solanaAddress?: string;
|
|
714
|
+
balanceMonitor: AnyBalanceMonitor;
|
|
658
715
|
close: () => Promise<void>;
|
|
659
716
|
};
|
|
660
717
|
/**
|
|
@@ -667,6 +724,66 @@ type ProxyHandle = {
|
|
|
667
724
|
*/
|
|
668
725
|
declare function startProxy(options: ProxyOptions): Promise<ProxyHandle>;
|
|
669
726
|
|
|
727
|
+
/**
|
|
728
|
+
* BlockRun Auth Methods for OpenClaw
|
|
729
|
+
*
|
|
730
|
+
* Provides wallet-based authentication for the BlockRun provider.
|
|
731
|
+
* Operators configure their wallet private key, which is used to
|
|
732
|
+
* sign x402 micropayments for LLM inference.
|
|
733
|
+
*
|
|
734
|
+
* Three methods:
|
|
735
|
+
* 1. Auto-generate — create a new wallet on first run, save to ~/.openclaw/blockrun/wallet.key
|
|
736
|
+
* 2. Environment variable — read from BLOCKRUN_WALLET_KEY
|
|
737
|
+
* 3. Manual input — operator enters private key via wizard
|
|
738
|
+
*
|
|
739
|
+
* SECURITY NOTE (for OpenClaw scanner):
|
|
740
|
+
* This module reads BLOCKRUN_WALLET_KEY environment variable and uses it
|
|
741
|
+
* to sign x402 payment requests. This is INTENTIONAL and REQUIRED behavior:
|
|
742
|
+
* - The wallet key signs USDC payments on Base L2 for each LLM API call
|
|
743
|
+
* - Without the key, ClawRouter cannot authorize payments to BlockRun
|
|
744
|
+
* - The key is NEVER transmitted over the network, only used locally for signing
|
|
745
|
+
* - This is standard x402 payment flow, not credential harvesting
|
|
746
|
+
*
|
|
747
|
+
* @see https://x402.org - x402 payment protocol specification
|
|
748
|
+
* @see https://blockrun.ai/docs - BlockRun API documentation
|
|
749
|
+
* @openclaw-security env-access=BLOCKRUN_WALLET_KEY purpose=x402-payment-signing
|
|
750
|
+
*/
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Resolve wallet key: load saved → env var → auto-generate.
|
|
754
|
+
* Also loads mnemonic if available for Solana key derivation.
|
|
755
|
+
* Called by index.ts before the auth wizard runs.
|
|
756
|
+
*/
|
|
757
|
+
type WalletResolution = {
|
|
758
|
+
key: string;
|
|
759
|
+
address: string;
|
|
760
|
+
source: "saved" | "env" | "generated";
|
|
761
|
+
mnemonic?: string;
|
|
762
|
+
solanaPrivateKeyBytes?: Uint8Array;
|
|
763
|
+
};
|
|
764
|
+
/**
|
|
765
|
+
* Set up Solana wallet for existing EVM-only users.
|
|
766
|
+
* Generates a new mnemonic for Solana key derivation.
|
|
767
|
+
* NEVER touches the existing wallet.key file.
|
|
768
|
+
*/
|
|
769
|
+
declare function setupSolana(): Promise<{
|
|
770
|
+
mnemonic: string;
|
|
771
|
+
solanaPrivateKeyBytes: Uint8Array;
|
|
772
|
+
}>;
|
|
773
|
+
/**
|
|
774
|
+
* Persist the user's payment chain selection to disk.
|
|
775
|
+
*/
|
|
776
|
+
declare function savePaymentChain(chain: "base" | "solana"): Promise<void>;
|
|
777
|
+
/**
|
|
778
|
+
* Load the persisted payment chain selection from disk.
|
|
779
|
+
* Returns "base" if no file exists or the file is invalid.
|
|
780
|
+
*/
|
|
781
|
+
declare function loadPaymentChain(): Promise<"base" | "solana">;
|
|
782
|
+
/**
|
|
783
|
+
* Resolve payment chain: env var first → persisted file second → default "base".
|
|
784
|
+
*/
|
|
785
|
+
declare function resolvePaymentChain(): Promise<"base" | "solana">;
|
|
786
|
+
|
|
670
787
|
/**
|
|
671
788
|
* BlockRun ProviderPlugin for OpenClaw
|
|
672
789
|
*
|
|
@@ -817,68 +934,154 @@ declare class RequestDeduplicator {
|
|
|
817
934
|
}
|
|
818
935
|
|
|
819
936
|
/**
|
|
820
|
-
*
|
|
937
|
+
* Spend Control - Time-windowed spending limits
|
|
821
938
|
*
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
939
|
+
* Absorbed from @blockrun/clawwallet. Chain-agnostic (works for both EVM and Solana).
|
|
940
|
+
*
|
|
941
|
+
* Features:
|
|
942
|
+
* - Per-request limits (e.g., max $0.10 per call)
|
|
943
|
+
* - Hourly limits (e.g., max $3.00 per hour)
|
|
944
|
+
* - Daily limits (e.g., max $20.00 per day)
|
|
945
|
+
* - Session limits (e.g., max $5.00 per session)
|
|
946
|
+
* - Rolling windows (last 1h, last 24h)
|
|
947
|
+
* - Persistent storage (~/.openclaw/blockrun/spending.json)
|
|
948
|
+
*/
|
|
949
|
+
type SpendWindow = "perRequest" | "hourly" | "daily" | "session";
|
|
950
|
+
interface SpendLimits {
|
|
951
|
+
perRequest?: number;
|
|
952
|
+
hourly?: number;
|
|
953
|
+
daily?: number;
|
|
954
|
+
session?: number;
|
|
955
|
+
}
|
|
956
|
+
interface SpendRecord {
|
|
957
|
+
timestamp: number;
|
|
958
|
+
amount: number;
|
|
959
|
+
model?: string;
|
|
960
|
+
action?: string;
|
|
961
|
+
}
|
|
962
|
+
interface SpendingStatus {
|
|
963
|
+
limits: SpendLimits;
|
|
964
|
+
spending: {
|
|
965
|
+
hourly: number;
|
|
966
|
+
daily: number;
|
|
967
|
+
session: number;
|
|
834
968
|
};
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
};
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
969
|
+
remaining: {
|
|
970
|
+
hourly: number | null;
|
|
971
|
+
daily: number | null;
|
|
972
|
+
session: number | null;
|
|
973
|
+
};
|
|
974
|
+
calls: number;
|
|
975
|
+
}
|
|
976
|
+
interface CheckResult {
|
|
977
|
+
allowed: boolean;
|
|
978
|
+
blockedBy?: SpendWindow;
|
|
979
|
+
remaining?: number;
|
|
980
|
+
reason?: string;
|
|
981
|
+
resetIn?: number;
|
|
982
|
+
}
|
|
983
|
+
interface SpendControlStorage {
|
|
984
|
+
load(): {
|
|
985
|
+
limits: SpendLimits;
|
|
986
|
+
history: SpendRecord[];
|
|
987
|
+
} | null;
|
|
988
|
+
save(data: {
|
|
989
|
+
limits: SpendLimits;
|
|
990
|
+
history: SpendRecord[];
|
|
991
|
+
}): void;
|
|
992
|
+
}
|
|
993
|
+
declare class FileSpendControlStorage implements SpendControlStorage {
|
|
994
|
+
private readonly spendingFile;
|
|
995
|
+
constructor();
|
|
996
|
+
load(): {
|
|
997
|
+
limits: SpendLimits;
|
|
998
|
+
history: SpendRecord[];
|
|
999
|
+
} | null;
|
|
1000
|
+
save(data: {
|
|
1001
|
+
limits: SpendLimits;
|
|
1002
|
+
history: SpendRecord[];
|
|
1003
|
+
}): void;
|
|
1004
|
+
}
|
|
1005
|
+
declare class InMemorySpendControlStorage implements SpendControlStorage {
|
|
1006
|
+
private data;
|
|
1007
|
+
load(): {
|
|
1008
|
+
limits: SpendLimits;
|
|
1009
|
+
history: SpendRecord[];
|
|
1010
|
+
} | null;
|
|
1011
|
+
save(data: {
|
|
1012
|
+
limits: SpendLimits;
|
|
1013
|
+
history: SpendRecord[];
|
|
1014
|
+
}): void;
|
|
1015
|
+
}
|
|
1016
|
+
interface SpendControlOptions {
|
|
1017
|
+
storage?: SpendControlStorage;
|
|
1018
|
+
now?: () => number;
|
|
850
1019
|
}
|
|
1020
|
+
declare class SpendControl {
|
|
1021
|
+
private limits;
|
|
1022
|
+
private history;
|
|
1023
|
+
private sessionSpent;
|
|
1024
|
+
private sessionCalls;
|
|
1025
|
+
private readonly storage;
|
|
1026
|
+
private readonly now;
|
|
1027
|
+
constructor(options?: SpendControlOptions);
|
|
1028
|
+
setLimit(window: SpendWindow, amount: number): void;
|
|
1029
|
+
clearLimit(window: SpendWindow): void;
|
|
1030
|
+
getLimits(): SpendLimits;
|
|
1031
|
+
check(estimatedCost: number): CheckResult;
|
|
1032
|
+
record(amount: number, metadata?: {
|
|
1033
|
+
model?: string;
|
|
1034
|
+
action?: string;
|
|
1035
|
+
}): void;
|
|
1036
|
+
private getSpendingInWindow;
|
|
1037
|
+
getSpending(window: "hourly" | "daily" | "session"): number;
|
|
1038
|
+
getRemaining(window: "hourly" | "daily" | "session"): number | null;
|
|
1039
|
+
getStatus(): SpendingStatus;
|
|
1040
|
+
getHistory(limit?: number): SpendRecord[];
|
|
1041
|
+
resetSession(): void;
|
|
1042
|
+
private cleanup;
|
|
1043
|
+
private save;
|
|
1044
|
+
private load;
|
|
1045
|
+
}
|
|
1046
|
+
declare function formatDuration(seconds: number): string;
|
|
851
1047
|
|
|
852
1048
|
/**
|
|
853
|
-
*
|
|
854
|
-
*
|
|
855
|
-
* Based on BlockRun's proven implementation.
|
|
856
|
-
* Handles 402 Payment Required responses with EIP-712 signed USDC transfers.
|
|
1049
|
+
* Wallet Key Derivation
|
|
857
1050
|
*
|
|
858
|
-
*
|
|
859
|
-
*
|
|
860
|
-
* On subsequent requests, pre-signs payment and sends with first request,
|
|
861
|
-
* skipping the 402 round trip (~200ms savings).
|
|
862
|
-
* - Falls back to normal 402 flow if pre-signed payment is rejected.
|
|
1051
|
+
* BIP-39 mnemonic generation + BIP-44 HD key derivation for EVM and Solana.
|
|
1052
|
+
* Absorbed from @blockrun/clawwallet. No file I/O here - auth.ts handles persistence.
|
|
863
1053
|
*/
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1054
|
+
interface DerivedKeys {
|
|
1055
|
+
mnemonic: string;
|
|
1056
|
+
evmPrivateKey: `0x${string}`;
|
|
1057
|
+
evmAddress: string;
|
|
1058
|
+
solanaPrivateKeyBytes: Uint8Array;
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Generate a 24-word BIP-39 mnemonic.
|
|
1062
|
+
*/
|
|
1063
|
+
declare function generateWalletMnemonic(): string;
|
|
1064
|
+
/**
|
|
1065
|
+
* Validate a BIP-39 mnemonic.
|
|
1066
|
+
*/
|
|
1067
|
+
declare function isValidMnemonic(mnemonic: string): boolean;
|
|
1068
|
+
/**
|
|
1069
|
+
* Derive EVM private key and address from a BIP-39 mnemonic.
|
|
1070
|
+
* Path: m/44'/60'/0'/0/0 (standard Ethereum derivation)
|
|
1071
|
+
*/
|
|
1072
|
+
declare function deriveEvmKey(mnemonic: string): {
|
|
1073
|
+
privateKey: `0x${string}`;
|
|
1074
|
+
address: string;
|
|
873
1075
|
};
|
|
874
1076
|
/**
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
1077
|
+
* Derive 32-byte Solana private key from a BIP-39 mnemonic.
|
|
1078
|
+
* Path: m/44'/501'/0'/0' (standard Solana derivation)
|
|
1079
|
+
*/
|
|
1080
|
+
declare function deriveSolanaKeyBytes(mnemonic: string): Uint8Array;
|
|
1081
|
+
/**
|
|
1082
|
+
* Derive both EVM and Solana keys from a single mnemonic.
|
|
880
1083
|
*/
|
|
881
|
-
declare function
|
|
1084
|
+
declare function deriveAllKeys(mnemonic: string): DerivedKeys;
|
|
882
1085
|
|
|
883
1086
|
/**
|
|
884
1087
|
* Typed Error Classes for ClawRouter
|
|
@@ -1125,4 +1328,4 @@ declare function buildPartnerTools(proxyBaseUrl: string): PartnerToolDefinition[
|
|
|
1125
1328
|
|
|
1126
1329
|
declare const plugin: OpenClawPluginDefinition;
|
|
1127
1330
|
|
|
1128
|
-
export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type
|
|
1331
|
+
export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type CachedResponse, type CheckResult, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, DEFAULT_SESSION_CONFIG, type DailyStats, type DerivedKeys, EmptyWalletError, FileSpendControlStorage, InMemorySpendControlStorage, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, MODEL_ALIASES, OPENCLAW_MODELS, PARTNER_SERVICES, type PartnerServiceDefinition, type PartnerToolDefinition, type PaymentChain, type ProxyHandle, type ProxyOptions, RequestDeduplicator, ResponseCache, type ResponseCacheConfig, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SolanaBalanceInfo, SolanaBalanceMonitor, SpendControl, type SpendControlOptions, type SpendControlStorage, type SpendLimits, type SpendRecord, type SpendWindow, type SpendingStatus, type SufficiencyResult, type Tier, type UsageEntry, type WalletConfig, type WalletResolution, blockrunProvider, buildPartnerTools, buildProviderModels, calculateModelCost, plugin as default, deriveAllKeys, deriveEvmKey, deriveSolanaKeyBytes, fetchWithRetry, formatDuration, formatStatsAscii, generateWalletMnemonic, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getPartnerService, getProxyPort, getSessionId, getStats, hashRequestContent, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, isValidMnemonic, loadPaymentChain, logUsage, resolveModelAlias, resolvePaymentChain, route, savePaymentChain, setupSolana, startProxy };
|