MCPcopy Index your code
hub / github.com/BlockRunAI/ClawRouter / createPayFetchWithPreAuth

Function createPayFetchWithPreAuth

src/payment-preauth.ts:47–171  ·  view source on GitHub ↗
(
  baseFetch: FetchFn,
  client: x402Client,
  ttlMs = DEFAULT_TTL_MS,
  options?: { skipPreAuth?: boolean; estimateAmount?: EstimateFn },
)

Source from the content-addressed store, hash-verified

45type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
46
47export function createPayFetchWithPreAuth(
48 baseFetch: FetchFn,
49 client: x402Client,
50 ttlMs = DEFAULT_TTL_MS,
51 options?: { skipPreAuth?: boolean; estimateAmount?: EstimateFn },
52): FetchFn {
53 const httpClient = new x402HTTPClient(client);
54 const cache = new Map<string, CachedEntry>();
55
56 return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
57 const request = new Request(input, init);
58 const urlPath = new URL(request.url).pathname;
59
60 // Extract model + size from the request body. Model gives a per-model cache
61 // key (a cached sonnet payment must not be applied to a free model); body
62 // length + max_tokens drive the up-front cost estimate used to decide
63 // whether a cached pre-auth still covers this (possibly larger) request.
64 let requestModel = "";
65 let bodyLength = 0;
66 let maxTokens = 0;
67 if (init?.body) {
68 try {
69 const bodyStr =
70 init.body instanceof Uint8Array
71 ? new TextDecoder().decode(init.body)
72 : typeof init.body === "string"
73 ? init.body
74 : "";
75 if (bodyStr) {
76 bodyLength = bodyStr.length;
77 const parsed = JSON.parse(bodyStr) as { model?: string; max_tokens?: number };
78 requestModel = parsed.model ?? "";
79 maxTokens = Number(parsed.max_tokens) || 0;
80 }
81 } catch {
82 /* not JSON, use empty model */
83 }
84 }
85 const cacheKey = `${urlPath}:${requestModel}`;
86
87 // Up-front estimate of what THIS request will cost (USDC micro-units), used
88 // both to gate pre-auth reuse and to record what a new cache entry covers.
89 const estimateMicros = (): number | undefined => {
90 if (!options?.estimateAmount || !requestModel) return undefined;
91 const est = options.estimateAmount(requestModel, bodyLength, maxTokens);
92 return est === undefined ? undefined : Number(est);
93 };
94 const needMicros = estimateMicros();
95
96 // Try pre-auth only when we can PROVE the cached payment still covers this
97 // request (needMicros <= what the cached entry covered). Skip for Solana:
98 // payments use per-tx blockhashes that expire ~60-90s, making cached
99 // requirements useless and causing double charges.
100 const cached = !options?.skipPreAuth ? cache.get(cacheKey) : undefined;
101 const preAuthCovers =
102 cached !== undefined &&
103 Date.now() - cached.cachedAt < ttlMs &&
104 cached.coverMicros !== undefined &&

Callers 2

startProxyFunction · 0.85

Calls 3

estimateMicrosFunction · 0.85
getMethod · 0.80
setMethod · 0.80

Tested by

no test coverage detected