@alleyboss/micropay-solana-x402-paywall 3.3.15 → 3.5.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.
@@ -0,0 +1,403 @@
1
+ import { WalletAdapter } from '@solana/wallet-adapter-base';
2
+ import { Keypair, Connection } from '@solana/web3.js';
3
+
4
+ /**
5
+ * @fileoverview Type definitions for x402Fetch
6
+ * @module @alleyboss/micropay-solana-x402-paywall/fetch
7
+ */
8
+
9
+ /**
10
+ * Solana network identifier
11
+ */
12
+ type SolanaNetwork = 'devnet' | 'mainnet-beta' | 'testnet';
13
+ /**
14
+ * Wallet type - supports both browser wallet adapters and server-side keypairs
15
+ */
16
+ type WalletLike = WalletAdapter | Keypair;
17
+ /**
18
+ * Payment requirements extracted from 402 response
19
+ */
20
+ interface PaymentRequirements {
21
+ /** Recipient wallet address */
22
+ readonly payTo: string;
23
+ /** Amount in smallest unit (lamports for SOL) */
24
+ readonly amount: string;
25
+ /** Asset identifier (e.g., 'SOL', 'USDC') */
26
+ readonly asset: string;
27
+ /** Network identifier */
28
+ readonly network: string;
29
+ /** Optional: Human-readable description */
30
+ readonly description?: string;
31
+ /** Optional: Resource identifier */
32
+ readonly resource?: string;
33
+ /** Optional: Maximum age of payment proof in seconds */
34
+ readonly maxAge?: number;
35
+ }
36
+ /**
37
+ * Configuration for createX402Fetch factory
38
+ */
39
+ interface X402FetchConfig {
40
+ /**
41
+ * Solana wallet - WalletAdapter for browser, Keypair for server/agents
42
+ * @example
43
+ * // Browser
44
+ * { wallet: useWallet() }
45
+ * // Server/Agent
46
+ * { wallet: Keypair.fromSecretKey(...) }
47
+ */
48
+ readonly wallet: WalletLike;
49
+ /**
50
+ * Solana network to use
51
+ * @default 'mainnet-beta'
52
+ */
53
+ readonly network?: SolanaNetwork;
54
+ /**
55
+ * Solana RPC connection (optional - will create one if not provided)
56
+ */
57
+ readonly connection?: Connection;
58
+ /**
59
+ * Custom facilitator URL for verification
60
+ * If not provided, uses built-in verification
61
+ */
62
+ readonly facilitatorUrl?: string;
63
+ /**
64
+ * Callback when payment is required
65
+ * Return `true` to proceed with payment, `false` to abort
66
+ * If not provided, payment proceeds automatically
67
+ *
68
+ * @example
69
+ * onPaymentRequired: async (req) => {
70
+ * return confirm(`Pay ${req.amount} ${req.asset}?`);
71
+ * }
72
+ */
73
+ readonly onPaymentRequired?: PaymentRequiredHook;
74
+ /**
75
+ * Callback after successful payment
76
+ */
77
+ readonly onPaymentSuccess?: PaymentSuccessHook;
78
+ /**
79
+ * Callback on payment failure
80
+ */
81
+ readonly onPaymentError?: PaymentErrorHook;
82
+ /**
83
+ * Priority fee configuration for Solana transactions
84
+ */
85
+ readonly priorityFee?: PriorityFeeConfig;
86
+ /**
87
+ * Maximum retries for transaction confirmation
88
+ * @default 3
89
+ */
90
+ readonly maxRetries?: number;
91
+ /**
92
+ * Timeout for payment flow in milliseconds
93
+ * @default 30000 (30 seconds)
94
+ */
95
+ readonly timeout?: number;
96
+ /**
97
+ * Maximum payment amount per request in lamports
98
+ * Prevents wallet drain from malicious 402 responses
99
+ * @default undefined (no limit - USE WITH CAUTION)
100
+ * @example 10_000_000n // Max 0.01 SOL per request
101
+ */
102
+ readonly maxPaymentPerRequest?: bigint;
103
+ /**
104
+ * Whitelist of allowed recipient addresses
105
+ * Payments to addresses not in this list will be rejected
106
+ * @default undefined (allow all - USE WITH CAUTION)
107
+ * @example ['7fPjN...', 'ABC123...']
108
+ */
109
+ readonly allowedRecipients?: readonly string[];
110
+ /**
111
+ * Solana commitment level for transaction confirmation
112
+ * - 'processed': Fastest (~100ms), optimistic, may revert
113
+ * - 'confirmed': Balanced (~400ms), supermajority confirmed
114
+ * - 'finalized': Slowest (~30s), irreversible
115
+ * @default 'confirmed'
116
+ */
117
+ readonly commitment?: 'processed' | 'confirmed' | 'finalized';
118
+ /**
119
+ * Rate limiting configuration to prevent infinite payment loops
120
+ */
121
+ readonly rateLimit?: RateLimitConfig;
122
+ }
123
+ /**
124
+ * Rate limiting configuration
125
+ */
126
+ interface RateLimitConfig {
127
+ /**
128
+ * Maximum number of payments allowed within the time window
129
+ * @default 10
130
+ */
131
+ readonly maxPayments: number;
132
+ /**
133
+ * Time window in milliseconds
134
+ * @default 60000 (1 minute)
135
+ */
136
+ readonly windowMs: number;
137
+ }
138
+ /**
139
+ * Priority fee configuration
140
+ */
141
+ interface PriorityFeeConfig {
142
+ /** Enable priority fees */
143
+ readonly enabled: boolean;
144
+ /** Micro-lamports per compute unit */
145
+ readonly microLamports?: number;
146
+ }
147
+ /**
148
+ * Hook called when payment is required
149
+ * @returns Promise<boolean> - true to proceed, false to abort
150
+ */
151
+ type PaymentRequiredHook = (requirements: PaymentRequirements, url: string) => Promise<boolean> | boolean;
152
+ /**
153
+ * Hook called after successful payment
154
+ */
155
+ type PaymentSuccessHook = (signature: string, requirements: PaymentRequirements) => void | Promise<void>;
156
+ /**
157
+ * Hook called on payment error
158
+ */
159
+ type PaymentErrorHook = (error: Error, requirements?: PaymentRequirements) => void | Promise<void>;
160
+ /**
161
+ * Extended RequestInit with x402-specific options
162
+ */
163
+ interface X402RequestInit extends RequestInit {
164
+ /**
165
+ * Skip payment flow - useful for checking if resource requires payment
166
+ */
167
+ readonly skipPayment?: boolean;
168
+ /**
169
+ * Custom payment requirements override
170
+ */
171
+ readonly paymentOverride?: Partial<PaymentRequirements>;
172
+ }
173
+ /**
174
+ * x402Fetch function signature
175
+ */
176
+ interface X402FetchFunction {
177
+ /**
178
+ * Fetch with automatic 402 handling
179
+ *
180
+ * @param input - URL or Request object
181
+ * @param init - Extended fetch options
182
+ * @returns Promise<Response>
183
+ * @throws {X402PaymentError} on payment failure
184
+ *
185
+ * @example
186
+ * const response = await x402Fetch('/api/premium');
187
+ * const data = await response.json();
188
+ */
189
+ (input: RequestInfo | URL, init?: X402RequestInit): Promise<Response>;
190
+ }
191
+ /**
192
+ * Error codes for X402PaymentError
193
+ */
194
+ declare const X402ErrorCode: {
195
+ /** User rejected the payment */
196
+ readonly USER_REJECTED: "USER_REJECTED";
197
+ /** Insufficient wallet balance */
198
+ readonly INSUFFICIENT_BALANCE: "INSUFFICIENT_BALANCE";
199
+ /** Transaction failed on-chain */
200
+ readonly TRANSACTION_FAILED: "TRANSACTION_FAILED";
201
+ /** Payment verification failed */
202
+ readonly VERIFICATION_FAILED: "VERIFICATION_FAILED";
203
+ /** Network/RPC error */
204
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
205
+ /** Invalid 402 response format */
206
+ readonly INVALID_402_RESPONSE: "INVALID_402_RESPONSE";
207
+ /** Payment timeout */
208
+ readonly TIMEOUT: "TIMEOUT";
209
+ /** Wallet not connected */
210
+ readonly WALLET_NOT_CONNECTED: "WALLET_NOT_CONNECTED";
211
+ /** Payment amount exceeds maxPaymentPerRequest */
212
+ readonly AMOUNT_EXCEEDS_LIMIT: "AMOUNT_EXCEEDS_LIMIT";
213
+ /** Recipient address not in allowedRecipients whitelist */
214
+ readonly RECIPIENT_NOT_ALLOWED: "RECIPIENT_NOT_ALLOWED";
215
+ /** Rate limit exceeded */
216
+ readonly RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED";
217
+ };
218
+ type X402ErrorCode = (typeof X402ErrorCode)[keyof typeof X402ErrorCode];
219
+ /**
220
+ * Payment result from successful transaction
221
+ */
222
+ interface PaymentResult {
223
+ /** Transaction signature */
224
+ readonly signature: string;
225
+ /** Amount paid in lamports */
226
+ readonly amountPaid: bigint;
227
+ /** Recipient address */
228
+ readonly recipient: string;
229
+ /** Timestamp of payment */
230
+ readonly timestamp: number;
231
+ }
232
+
233
+ /**
234
+ * @fileoverview x402Fetch - Drop-in fetch() replacement with automatic 402 handling
235
+ * @module @alleyboss/micropay-solana-x402-paywall/fetch
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * import { createX402Fetch } from '@alleyboss/micropay-solana-x402-paywall/fetch';
240
+ *
241
+ * const x402Fetch = createX402Fetch({
242
+ * wallet: useWallet(), // or Keypair for server-side
243
+ * network: 'mainnet-beta',
244
+ * });
245
+ *
246
+ * // Use it like fetch() - automatically handles 402 responses
247
+ * const response = await x402Fetch('/api/premium-data');
248
+ * const data = await response.json();
249
+ * ```
250
+ */
251
+
252
+ /**
253
+ * Parse payment requirements from 402 response headers
254
+ */
255
+ declare function parse402Response(response: Response): PaymentRequirements;
256
+ /**
257
+ * Build x402 payment proof header
258
+ */
259
+ declare function buildPaymentHeader(signature: string): string;
260
+ /**
261
+ * Create a configured x402Fetch instance
262
+ *
263
+ * This factory function returns a fetch-like function that automatically
264
+ * handles HTTP 402 responses by executing Solana payments.
265
+ *
266
+ * @param config - Configuration options
267
+ * @returns A fetch function that handles 402 automatically
268
+ *
269
+ * @example Browser (with Wallet Adapter)
270
+ * ```typescript
271
+ * import { useWallet } from '@solana/wallet-adapter-react';
272
+ *
273
+ * function MyComponent() {
274
+ * const wallet = useWallet();
275
+ * const x402Fetch = useMemo(() => createX402Fetch({
276
+ * wallet,
277
+ * network: 'mainnet-beta',
278
+ * onPaymentRequired: async (req) => {
279
+ * return confirm(`Pay ${req.amount} lamports?`);
280
+ * },
281
+ * }), [wallet]);
282
+ *
283
+ * // Use it like fetch
284
+ * const loadData = () => x402Fetch('/api/premium').then(r => r.json());
285
+ * }
286
+ * ```
287
+ *
288
+ * @example Server/Agent (with Keypair)
289
+ * ```typescript
290
+ * import { Keypair } from '@solana/web3.js';
291
+ * import bs58 from 'bs58';
292
+ *
293
+ * const agentKeypair = Keypair.fromSecretKey(
294
+ * bs58.decode(process.env.AGENT_PRIVATE_KEY!)
295
+ * );
296
+ *
297
+ * const x402Fetch = createX402Fetch({
298
+ * wallet: agentKeypair,
299
+ * network: 'mainnet-beta',
300
+ * });
301
+ *
302
+ * // Autonomous payment
303
+ * const response = await x402Fetch('https://api.example.com/data');
304
+ * ```
305
+ */
306
+ declare function createX402Fetch(config: X402FetchConfig): X402FetchFunction;
307
+
308
+ /**
309
+ * @fileoverview Custom error classes for x402Fetch
310
+ * @module @alleyboss/micropay-solana-x402-paywall/fetch
311
+ */
312
+
313
+ /**
314
+ * Base error for all x402 payment-related errors
315
+ *
316
+ * @example
317
+ * try {
318
+ * await x402Fetch('/api/premium');
319
+ * } catch (error) {
320
+ * if (error instanceof X402PaymentError) {
321
+ * console.log(error.code); // 'USER_REJECTED'
322
+ * console.log(error.requirements); // { payTo: '...', amount: '...' }
323
+ * }
324
+ * }
325
+ */
326
+ declare class X402PaymentError extends Error {
327
+ /** Error code for programmatic handling */
328
+ readonly code: X402ErrorCode;
329
+ /** Payment requirements that triggered the error */
330
+ readonly requirements?: PaymentRequirements | undefined;
331
+ /** Original error if this wraps another error */
332
+ readonly cause?: Error | undefined;
333
+ readonly name: "X402PaymentError";
334
+ constructor(message: string,
335
+ /** Error code for programmatic handling */
336
+ code: X402ErrorCode,
337
+ /** Payment requirements that triggered the error */
338
+ requirements?: PaymentRequirements | undefined,
339
+ /** Original error if this wraps another error */
340
+ cause?: Error | undefined);
341
+ /**
342
+ * Check if error is retryable
343
+ */
344
+ get isRetryable(): boolean;
345
+ /**
346
+ * Convert to JSON-serializable object
347
+ */
348
+ toJSON(): Record<string, unknown>;
349
+ }
350
+ /**
351
+ * Create error for user rejection
352
+ */
353
+ declare function userRejectedError(requirements: PaymentRequirements): X402PaymentError;
354
+ /**
355
+ * Create error for insufficient balance
356
+ */
357
+ declare function insufficientBalanceError(requirements: PaymentRequirements, balance: bigint): X402PaymentError;
358
+ /**
359
+ * Create error for transaction failure
360
+ */
361
+ declare function transactionFailedError(requirements: PaymentRequirements, cause?: Error): X402PaymentError;
362
+ /**
363
+ * Create error for verification failure
364
+ */
365
+ declare function verificationFailedError(requirements: PaymentRequirements, reason?: string): X402PaymentError;
366
+ /**
367
+ * Create error for network issues
368
+ */
369
+ declare function networkError(cause?: Error): X402PaymentError;
370
+ /**
371
+ * Create error for invalid 402 response
372
+ */
373
+ declare function invalid402ResponseError(details?: string): X402PaymentError;
374
+ /**
375
+ * Create error for timeout
376
+ */
377
+ declare function timeoutError(requirements?: PaymentRequirements): X402PaymentError;
378
+ /**
379
+ * Create error for wallet not connected
380
+ */
381
+ declare function walletNotConnectedError(): X402PaymentError;
382
+ /**
383
+ * Create error when payment amount exceeds configured limit
384
+ */
385
+ declare function amountExceedsLimitError(requirements: PaymentRequirements, limit: bigint): X402PaymentError;
386
+ /**
387
+ * Create error when recipient is not in whitelist
388
+ */
389
+ declare function recipientNotAllowedError(requirements: PaymentRequirements, recipient: string): X402PaymentError;
390
+ /**
391
+ * Create error when rate limit is exceeded
392
+ */
393
+ declare function rateLimitExceededError(limit: number, windowMs: number): X402PaymentError;
394
+ /**
395
+ * Check if an error is an X402PaymentError
396
+ */
397
+ declare function isX402PaymentError(error: unknown): error is X402PaymentError;
398
+ /**
399
+ * Check if error indicates user explicitly rejected
400
+ */
401
+ declare function isUserRejection(error: unknown): boolean;
402
+
403
+ export { type PaymentErrorHook, type PaymentRequiredHook, type PaymentRequirements, type PaymentResult, type PaymentSuccessHook, type PriorityFeeConfig, type RateLimitConfig, type SolanaNetwork, type WalletLike, X402ErrorCode, type X402FetchConfig, type X402FetchFunction, X402PaymentError, type X402RequestInit, amountExceedsLimitError, buildPaymentHeader, createX402Fetch, insufficientBalanceError, invalid402ResponseError, isUserRejection, isX402PaymentError, networkError, parse402Response as parsePaymentRequirements, rateLimitExceededError, recipientNotAllowedError, timeoutError, transactionFailedError, userRejectedError, verificationFailedError, walletNotConnectedError };